Creative Blueprint
BlueprintWorked exampleBefore / AfterSam batch — finalAll adsSkillsLessonsProtocols

← Both skills · wildhorn-static-ads · wildhorn/paths-and-commands.md

wildhorn-static-ads · files
wildhorn-static-ads/wildhorn/paths-and-commands.md · 208 lines
Where everything lives on the VPS: workshop, scripts, pages, exports, copy-paste commands.
Download the whole skill (zip)

Paths, pages and commands — the Wildhorn static-ad workshop

Everything runs on the VPS (ssh vps-claude). Never run Playwright/Chromium or generation on the Mac. Secrets are referenced by path only.


1. Workshop layout — /root/workspace/wh-remix/

Path What it is
LESSONS.md the anti-regression rulebook (A1–A26, B1–B16, C1–C11, D1–D10, E1–E7). Port the audit rules (A27–A31, B17–B19, C12–C18, D11–D13, E8–E13) from wildhorn/lessons-wildhorn.md when you next edit it.
lint.py blocking linter: python3 lint.py SPECFILE → "LINT OK" or the list of violations. Imported by srun.py.
PRODUCT.md product sheet (FR). Note: "Autoship -50%" is site-only; never in ads (B7).
kit/ brand kit saved at step 5A: research.md (Primal Edge study), angle-01.md (locked angle), product.md, product-jar.jpg, creatives.jsonl (ads already made — don't duplicate).
product-jar.jpg Image 1 of every generation (real jar photo).
remix.py OpenAI gpt-image-2 edit: remix.py NAME --prompt FILE [--concept TEMPLATE] [--product JAR] [--n 1] [--quality high] [--size 1024x1024] → out/NAME_vK.png, copy in /srv/wildhorn-lp/remix/, log log.jsonl, gallery rebuilt. Retries 3× on 5xx/429. Key: /etc/secrets/openai_api_key.
kie_gen.py kie.ai fallback: kie_gen.py NAME --prompt FILE [--concept IMG] [--product IMG] --model seedream|flux|nano [--aspect portrait_16_9|square_hd…] → out/NAME_vK.png. Models: seedream = bytedance/seedream-v4-edit, flux = flux-2/pro-image-to-image, nano = nano-banana-pro. Uses /root/workspace/wildhorn-lp/p6/gen/kie6.py (key loaded there).
composite.py composite.py IN OUT spec.json — pastes the REAL jar cutout /srv/wildhorn-lp/p6/jar-30.webp and exact text. Spec keys: jar {x,y,h[,noshadow]} or jars [..], rects [[x0,y0,x1,y1,color]], band {y0,y1,color}, texts [{y,size,font,weight,align,x,maxw,lh,runs:[[text,color(,weight)]],shadow,sunscreen}], strikes [[x0,y0,x1,y1,color]]. Fonts: Anton, Montserrat, Oswald, Fredoka, DejaVu. All coordinates are fractions of the image.
jarswap.py jarswap.py base.png out.png x0 y0 x1 y1 — swaps ONLY the jar inside the box with a masked gpt-image-2 edit (A25). Its prompt is written for the S11 "jar replaces her head" case — edit the prompt sentence before reusing it for another placement.
fonts/ Anton-Regular.ttf, Montserrat.ttf (variable weight), Oswald.ttf, Fredoka.ttf
out/ every generated image: run 1 <cNNNN>_vK.png / bN_NN…, Sam s_NN_vK.png, Seedream raws s_NN_sd_vK.png, kie temp out/_kie/
feedback/ loom-b2…b9.{mp4,txt} (run 1), loom-s1…s4.{mp4,txt} (Sam). Transcribe new Looms with mr-transcribe <file> --lang en (OpenAI API, never local whisper).
batch-01/ … batch-09/ run-1 ateliers: bNspecs.py, bNrun.py/run.sh, build_bN.py (page), meta.json, prompts/, logs/. batch-01/families.json (9 concept families), numbers.json (#N → template id), json/ (B1 JSON blueprints), overrides.py (R9 headlines).
run1-final/ the 79 final run-1 PNGs Wildhorn_01..79.png
stats.py / stats_run1.json run-1 hit-rate stats (⚠ ignores batch-09: no meta.json)
build_lessons.py rebuilds https://blueprint.machineroom.app/lessons from LESSONS.md
build_all.py rebuilds https://blueprint.machineroom.app/all-ads (run 1 + Sam = 162)
templates/ Adrien's TEMPLATE WINNER library by family (BEFORE AND AFTER, BOLD CLAIM, Feature benefit, MEME, NEGATIE HOOK, PROBLEME SOLUTION, US VS THEM, offer:sales, statistic)
concepts/ early remix concepts (t100, t144…)
gallery.py rebuilds https://wildhorn-lp.machineroom.app/remix (raw remix gallery)

2. Sam-batch workshop — /root/workspace/wh-remix/sam-batch/ (the current pipeline)

Path What it is
templates/ the 83 Sam templates (MM-DD_cNNNN_Brand.ext). S-number = position in sorted(os.listdir(templates)).
s1specs.py round 1 specs S1–S10 (+ shared strings ORGANS, CAPS)
s2specs.py round 2: redos S2 S7 S8 S9 + new S11–S40
s3specs.py round 3: redos S8 S11 S14 S15 S17 S18 S24 S29 S33 S35 + new S41–S83
s3fixspecs.py QC round 3: Seedream scene + composite for S55 S58 S74 S79
s4specs.py Loom-3 redos S11 S18 S29 S42 S50 S52 S56 S57 S74 S80 (helper ad(), OLD avatar string, HORN suffix)
srun.py the pipeline: python3 srun.py SPECFILE NUM → lint (blocking) → engine chain → composite → out/s_NN_vK.png; logs calls.jsonl
calls.jsonl one line per generation call {num, engine, ok, ts} (133 lines)
prompts/ the exact prompt sent per ad (s_NN.txt, s_NN_sd.txt, s_NN_comp*.json, s_NN_bg.png)
logs/ r1_N.log, r2_N.log, fix3_s_NN.log… + done flags _r2done, _r3done
jobs2.txt, jobs3.txt, round2_list.txt, round3_list.txt the S-numbers / templates of each round
validated.json Adrien's verdict per S-number: "✅ Validated (first try)", "✅ Validated (redo)", "✅ Loom 4 (after fix)"… (❌ … / ⏳ when pending)
sell_override.json which try is the SELL version when it isn't the last: {"9":1,"58":1,"79":1,"35":2,"42":1} (A20/A26)
sell/ Wildhorn_SNN.png = sell version of every ad
validated/ Wildhorn_01..83.png = validated sell versions in S order
build_sam.py review page https://blueprint.machineroom.app/sam (hides ✅ ads)
build_samfinal.py https://blueprint.machineroom.app/sam-final (every try + SELL VERSION + stats) and refreshes sell/
build_validated.py validated/ + https://blueprint.machineroom.app/wildhorn-ads (images only, no text)
proto_sam2.py inserts a feedback-loop section into /srv/blueprint/protocols.html (pattern to copy for each new Loom)

3. Published pages (all noindex, clean URLs)

URL Content Built by
https://blueprint.machineroom.app/ the generic AI Blueprint (steps 0–5, rules R1–R14) hand-edited /srv/blueprint/index.html
https://blueprint.machineroom.app/example Module 2 — the Wildhorn × Primal Edge worked example, 79 run-1 pairs batch-01/build_pages.py
https://blueprint.machineroom.app/before-after run 1 numbered #1–#79 (anchors #adN) batch-01 builder
https://blueprint.machineroom.app/batch-02 … /batch-09 run-1 review pages per round batch-0N/build_bN.py
https://blueprint.machineroom.app/lessons LESSONS.md as a page build_lessons.py
https://blueprint.machineroom.app/protocols Protocol 0 (Template DNA), golden rules, copy rules, prompt structure, QC checklist, every feedback loop edited per round (proto_*.py)
https://blueprint.machineroom.app/sam Sam batch review page (only ads still to review) sam-batch/build_sam.py
https://blueprint.machineroom.app/sam-final Sam batch: every try + SELL VERSION + hit rate sam-batch/build_samfinal.py
https://blueprint.machineroom.app/wildhorn-ads 83 validated Sam ads, images only sam-batch/build_validated.py
https://blueprint.machineroom.app/all-ads 162 ads: Batch 1 (79) + Batch 2 (83) build_all.py
https://blueprint.machineroom.app/skill.md the generic ad-blueprint skill incl. Section 18 Template Clone Protocol /srv/blueprint/skill.md
https://wildhorn-lp.machineroom.app/remix raw remix gallery (concept + outputs + prompt) gallery.py
https://wildhorn-lp.machineroom.app/ads-demo/ run-1 demo (images only) batch-01 builder
https://intel.machineroom.app/en/primaledge Primal Edge ad-library study (angles, mechanisms, LPs) /root/workspace/competitors/adlib/site/

Static root: /srv/blueprint/ (ex/ = full-size tries, ex/web/ = webp thumbs, all-ads/b1 b2, wildhorn-ads/).

4. Mac exports (~/Downloads/)

Folder Content
~/Downloads/Wildhorn-Final-Ads/ run 1 — 79 finals Wildhorn_01..79.png
~/Downloads/Wildhorn-Sam-Batch/ Sam — 83 sell versions Wildhorn_S01..S83.png
~/Downloads/Wildhorn-Validated/ Sam — 83 validated Wildhorn_01..83.png
~/Downloads/Sam-static-concepts-14-18-Sept/ (+ .zip) the 83 Sam templates as Adrien sent them

Export commands (run on the Mac — the only thing allowed locally):

rsync -a vps-claude:/root/workspace/wh-remix/sam-batch/sell/ ~/Downloads/Wildhorn-Sam-Batch/
rsync -a vps-claude:/root/workspace/wh-remix/sam-batch/validated/ ~/Downloads/Wildhorn-Validated/
rsync -a vps-claude:/root/workspace/wh-remix/run1-final/ ~/Downloads/Wildhorn-Final-Ads/

For a new batch, create a new folder (e.g. ~/Downloads/Wildhorn-Batch-3/), never overwrite the previous exports.

Templates from the Mac to the VPS (Adrien drops them in iCloud BUSINESS/WILDHORN CONCEPTS/, a zip in Downloads, or the TEMPLATE WINNER folder ~/Library/Mobile Documents/com~apple~CloudDocs/BUSINESS/E-COMMERCE/- ADS ECOM/TEMPLATE WINNER/):

scp -r "<local folder>"/* vps-claude:/root/workspace/wh-remix/<new-batch>/templates/

5. Memory & checkpoints

  • Checkpoint (read at the start of any Wildhorn batch work): ~/.claude/bin/checkpoint wildhorn-batch-test (stored on the VPS in /root/workspace/_checkpoints/). Write: ~/.claude/bin/checkpoint wildhorn-batch-test --write (stdin).
  • Mac memory notes: wildhorn-remix-system.md, creas-gpt-image-2.md, clone-winner-system.md, english-deliverables.md, wildhorn-lp-compliance.md (project memory folder of the Mybusiness project).
  • Vault copy of the rulebook: /root/claude-vault/knowledge/copywriting/TEMPLATE-CLONE-LESSONS.md.
  • Research: /root/claude-vault/knowledge/product-research/primal-bison/etude-marche-primal-edge.md, structured /srv/intel/data/primaledge.json.
  • Landing (product claims source): /srv/wildhorn-lp/product-v6-monument.html.

6. Command cookbook

Lint a spec file (always first)

ssh vps-claude 'cd /root/workspace/wh-remix && python3 lint.py sam-batch/s5specs.py'

Template-path sanity check (D13 — not in lint yet)

ssh vps-claude 'cd /root/workspace/wh-remix/sam-batch && python3 - <<EOF
import importlib.util, os
T = sorted(os.listdir("templates"))
sp = importlib.util.spec_from_file_location("m", "s5specs.py"); m = importlib.util.module_from_spec(sp); sp.loader.exec_module(m)
for s in m.S:
    if not s.get("tpl_abs") and s["tpl"] != T[s["num"]-1]: print("MISMATCH", s["num"], s["tpl"], "->", T[s["num"]-1])
print("checked", len(m.S))
EOF'

Generate one ad

ssh vps-claude 'cd /root/workspace/wh-remix/sam-batch && python3 srun.py s5specs.py 84'

Output: #84: openai OK (or REFUSED -> seedream_comp then seedream+comp OK). D10: OK only if a new out/s_84_vK.png exists.

Generate a round in parallel (10 ads, 5 at a time), with logs and a done flag

ssh vps-claude 'cd /root/workspace/wh-remix/sam-batch && echo "84 85 86 87 88 89 90 91 92 93" | tr " " "\n" > jobs5.txt && \
nohup sh -c "cat jobs5.txt | xargs -P 5 -I{} sh -c \"python3 srun.py s5specs.py {} > logs/r5_{}.log 2>&1\"; touch logs/_r5done" >/dev/null 2>&1 &'

Check: ssh vps-claude 'ls /root/workspace/wh-remix/sam-batch/logs/_r5done; tail -n1 /root/workspace/wh-remix/sam-batch/logs/r5_*.log'. ~110 s per gpt-image-2 image.

Manual fallback (sexual / refused) — Seedream scene + composite

# spec has engine="seedream_comp" (or fallback="seedream_comp"), sd_prompt (scene only: no text, no product, empty zones), composite {...}
python3 srun.py s5specs.py 88
# by hand:
python3 ../kie_gen.py s_88_sd --prompt prompts/s_88_sd.txt --product templates/<tpl> --model seedream [--aspect portrait_16_9]
python3 ../composite.py ../out/s_88_sd_v1.png ../out/s_88_v2.png prompts/s_88_comp.json

Painted-in text (sunscreen, chalk…) — Nano Banana Pro

python3 ../kie_gen.py s_88_nano --prompt prompts/s_88_nano.txt --product ../product-jar.jpg --concept templates/<tpl> --model nano

A25 — copy THEIR production method (minimal edit of the template)

# 1) Seedream edits the template itself: age the man, clear the text, nothing else (keep aspect)
python3 ../kie_gen.py s_11_sd --prompt prompts/s_11_sd7.txt --product templates/09-14_c0025_Primal-Viking.png --model seedream --aspect portrait_16_9
# 2) swap only their jar for ours inside a box (pixels of the base image)
python3 ../jarswap.py ../out/s_11_sd_v6.png prompts/s_11_jar.png X0 Y0 X1 Y1
# 3) exact text by script
python3 ../composite.py prompts/s_11_jar.png ../out/s_11_v5.png prompts/s_11_comp5.json

"Change only the wording" on a liked try (A22)

Spec with tpl_abs=O + "s_29_v2.png" (O = /root/workspace/wh-remix/out/) → Image 2 = our own try.

Record verdicts after a Loom

ssh vps-claude 'cd /root/workspace/wh-remix/sam-batch && python3 - <<EOF
import json
v = json.load(open("validated.json"))
v.update({"84": "✅ Validated (first try)", "85": "❌ Loom 6: off-angle (A24)"})
json.dump(v, open("validated.json", "w"), ensure_ascii=False, indent=1)
so = json.load(open("sell_override.json")); so.update({"86": 1}); json.dump(so, open("sell_override.json", "w"))
EOF'

Rebuild every page + exports

ssh vps-claude 'cd /root/workspace/wh-remix && python3 sam-batch/build_sam.py && python3 sam-batch/build_samfinal.py && python3 sam-batch/build_validated.py && python3 build_all.py && python3 build_lessons.py'
rsync -a vps-claude:/root/workspace/wh-remix/sam-batch/sell/ ~/Downloads/Wildhorn-Sam-Batch/

(For a new batch folder, copy the builders and change their paths/titles; keep SKIP_VALIDATED on the review page.)

Transcribe Adrien's Loom

ssh vps-claude 'cd /root/workspace/wh-remix/feedback && mr-transcribe loom-s5.mp4 --lang en'

(download the Loom mp4 to that folder first; API transcription only.)

Hit-rate numbers

ssh vps-claude 'cd /root/workspace/wh-remix/sam-batch && python3 -c "
import json; v=json.load(open(\"validated.json\")); c=[json.loads(l) for l in open(\"calls.jsonl\")]
ft=sum(\"first try\" in x for x in v.values()); ok=sum(x.startswith(\"✅\") for x in v.values())
print(f\"first try {ft}/{len(v)} = {100*ft/len(v):.1f}%  validated {ok}/{len(v)}  calls {len(c)}  per validated {len(c)/max(ok,1):.2f}\")"'

7. Reference numbers

Run 1 (79 templates) Sam batch (83 templates)
Generations 258 + 3 refused = 261 133 calls (125 ok, 8 refused/failed)
Generations per validated ad 3.3 1.6
Validated first try 0 / 79 = 0 % 59 / 83 = 71.1 %
After one fix — ≈ 87 %
Final 79 / 79 after 9 rounds 83 / 83 after 4 Looms (+ S11 in Loom 5)
Hit rate (validated ÷ generations) 30.3 % ≈ 62 %
Total validated 162 ads on https://blueprint.machineroom.app/all-ads