@aicopycoders/exodus 2026.9.1100-beta.3 → 2026.9.1400-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/assets/docs/CLAUDE.md +22 -1
  2. package/assets/docs/PIPELINES.md +20 -0
  3. package/assets/skills/anatomy-of-ads/SKILL.md +138 -0
  4. package/assets/skills/anatomy-of-ads/references/beat-map.md +69 -0
  5. package/assets/skills/anatomy-of-ads/references/concept-angle.md +50 -0
  6. package/assets/skills/anatomy-of-ads/references/hook-and-structure.md +69 -0
  7. package/assets/skills/bot-builder/SKILL.md +147 -0
  8. package/assets/skills/bot-builder/references/exodus-prompt-node.md +113 -0
  9. package/assets/skills/bot-builder/references/prompt-blocks.md +169 -0
  10. package/assets/skills/copy-instincts/SKILL.md +154 -0
  11. package/assets/skills/copy-instincts/references/instincts-catalog.md +131 -0
  12. package/assets/skills/copy-instincts/references/locked-examples.md +104 -0
  13. package/assets/skills/copy-instincts/references/worked-runs.md +148 -0
  14. package/assets/skills/exodus/SKILL.md +10 -1
  15. package/assets/skills/find-competitors/SKILL.md +148 -0
  16. package/assets/skills/find-competitors/references/query-grid.md +78 -0
  17. package/assets/skills/find-competitors/scripts/__pycache__/adlib_sweep.cpython-314.pyc +0 -0
  18. package/assets/skills/find-competitors/scripts/__pycache__/competitor_signals.cpython-314.pyc +0 -0
  19. package/assets/skills/find-competitors/scripts/adlib_sweep.py +100 -0
  20. package/assets/skills/find-competitors/scripts/competitor_signals.py +168 -0
  21. package/assets/skills/handoff/SKILL.md +81 -0
  22. package/assets/skills/mechanism/SKILL.md +130 -0
  23. package/assets/skills/mechanism/references/bot-prompts.md +94 -0
  24. package/assets/skills/mechanism/references/competitor-mechanisms.md +39 -0
  25. package/assets/skills/odf/SKILL.md +167 -0
  26. package/assets/skills/patterns-and-gaps/SKILL.md +120 -0
  27. package/assets/skills/positioning-spiral/SKILL.md +166 -0
  28. package/assets/skills/remember-that/SKILL.md +56 -0
  29. package/assets/skills/segment-grid/README.md +45 -0
  30. package/assets/skills/segment-grid/SKILL.md +84 -0
  31. package/assets/skills/thinking-vs-build/SKILL.md +120 -0
  32. package/assets/templates/STANDARDS.md +49 -0
  33. package/dist/commands/init.d.ts +1 -0
  34. package/dist/commands/init.js +10 -5
  35. package/dist/commands/update.js +1 -1
  36. package/dist/commands/video.d.ts +6 -0
  37. package/dist/commands/video.js +30 -1
  38. package/dist/lib/assets.d.ts +1 -0
  39. package/dist/lib/assets.js +3 -0
  40. package/dist/lib/scaffold.d.ts +3 -0
  41. package/dist/lib/scaffold.js +18 -1
  42. package/package.json +1 -1
@@ -0,0 +1,168 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ competitor_signals.py — score a list of brands on the six strength signals using the Atria API.
4
+
5
+ Usage:
6
+ python3 competitor_signals.py --names "Brand A" "Brand B" --out sheet.md
7
+ python3 competitor_signals.py --file brands.txt --out sheet.md --json signals.json
8
+
9
+ brands.txt: one brand name per line (blank lines and # comments ignored).
10
+
11
+ Needs ATRIA_API_KEY in the workspace .env (or the environment). Rate limit is tight:
12
+ ~10 calls in quick succession returns 429, so the script pauses and retries.
13
+
14
+ Signals per brand (all from Atria's brand feed, no spend estimates). Three feed orders are used:
15
+ most_impressions (top ads, offer words, reuse), newest (launches in 30 days), oldest (longest-running).
16
+ active_total active ads right now
17
+ longest_days days_running of the longest active ad
18
+ launches_30d active ads with start_date in the last 30 days
19
+ reuse active ads Atria marks as creative duplicates (re-launched winners), in the top-impression sample
20
+ offer intro-offer words seen in active ad bodies (%, off, free, trial, quiz)
21
+ verdict FOLLOW (3+ strong) · WATCH (2) · SKIP (0–1)
22
+
23
+ Thresholds (edit STRONG below to fit the category):
24
+ active_total >= 50 · longest_days >= 90 · launches_30d >= 10 · reuse >= 5 · offer >= 3
25
+ Cost: about 6 to 8 Atria calls per brand. 30 brands is a few minutes with the rate-limit pauses.
26
+ """
27
+ import argparse, json, os, re, sys, time, datetime as dt
28
+ from collections import Counter
29
+
30
+ try:
31
+ import requests
32
+ except ImportError:
33
+ sys.exit("pip3 install requests python-dotenv (use --break-system-packages on Homebrew python)")
34
+
35
+ try:
36
+ from dotenv import load_dotenv
37
+ here = os.path.abspath(os.getcwd())
38
+ for _ in range(7):
39
+ env = os.path.join(here, ".env")
40
+ if os.path.exists(env):
41
+ load_dotenv(env); break
42
+ here = os.path.dirname(here)
43
+ except ImportError:
44
+ pass
45
+
46
+ KEY = os.environ.get("ATRIA_API_KEY")
47
+ if not KEY:
48
+ sys.exit("ATRIA_API_KEY not found in .env or environment")
49
+ H = {"X-API-Key": KEY}
50
+ B = "https://api.tryatria.com/open/v1"
51
+ STRONG = dict(active_total=50, longest_days=90, launches_30d=10, reuse=5, offer=3)
52
+ OFFER_RX = re.compile(r"(\d{2}% ?off|% off|free (shipping|trial|gift)|buy \d get|bogo|quiz|first[- ]time|intro(ductory)? (offer|price)|money[- ]back|save \$?\d)", re.I)
53
+
54
+
55
+ def get(path, params, tries=5):
56
+ for i in range(tries):
57
+ r = requests.get(B + path, headers=H, params=params, timeout=60)
58
+ if r.status_code == 429:
59
+ time.sleep(20); continue
60
+ r.raise_for_status()
61
+ return r.json().get("data") or {}
62
+ raise RuntimeError(f"429 persisted on {path}")
63
+
64
+
65
+ def search_brand(name):
66
+ items = get("/brand-library/search", {"keyword": name, "page_size": 8}).get("items", [])
67
+ first = name.lower().split()[0]
68
+ exact = [i for i in items if i.get("name", "").lower() == name.lower()]
69
+ close = [i for i in items if first in i.get("name", "").lower()]
70
+ if exact or close:
71
+ return (exact or close)[:1]
72
+ # no name match: do not guess. Report what Atria returned so the user can pick.
73
+ return [dict(_candidates=[i.get("name") for i in items[:6]])]
74
+
75
+
76
+ def brand_ads(bid, status="active", pages=2, order="most_impressions", stop=None):
77
+ out, cur, total = [], None, None
78
+ for _ in range(pages):
79
+ p = {"status": status, "page_size": 50, "order": order}
80
+ if cur: p["cursor"] = cur
81
+ d = get(f"/brand-library/{bid}/ads", p)
82
+ items = d.get("items", []); out += items; cur = d.get("cursor"); total = d.get("total", total)
83
+ time.sleep(0.8)
84
+ if not cur or len(items) < 50: break
85
+ if stop and items and stop(items[-1]): break
86
+ return out, total
87
+
88
+
89
+ def parse_date(s):
90
+ if not s: return None
91
+ try: return dt.datetime.fromisoformat(str(s).replace("Z", "+00:00")).replace(tzinfo=None)
92
+ except Exception: pass
93
+ try: return dt.datetime.utcfromtimestamp(int(s))
94
+ except Exception: return None
95
+
96
+
97
+ def age_days(a, now):
98
+ d = parse_date(a.get("start_date"))
99
+ return (now - d).days if d else 10**6
100
+
101
+
102
+ def score(name):
103
+ hits = search_brand(name)
104
+ if not hits or "_candidates" in hits[0]:
105
+ cands = hits[0]["_candidates"] if hits else []
106
+ return dict(name=name, found=False, error=("no name match; Atria offered: " + ", ".join(cands)) if cands else "no results")
107
+ b = hits[0]; bid = b["id"]
108
+ now = dt.datetime.now(dt.timezone.utc).replace(tzinfo=None)
109
+ act, total = brand_ads(bid, "active", 1, "most_impressions")
110
+ newest, _ = brand_ads(bid, "active", 4, "newest", stop=lambda a: age_days(a, now) > 30)
111
+ oldest, _ = brand_ads(bid, "active", 1, "oldest")
112
+ longest = max([a.get("days_running") or 0 for a in (oldest[:5] + act)] or [0])
113
+ launches = sum(1 for a in newest if age_days(a, now) <= 30)
114
+ if len(newest) >= 200 and launches >= 200: launches = f"{launches}+"
115
+ reuse = sum(1 for a in act if (a.get("creative_duplicates") or 0) > 0)
116
+ offer = sum(1 for a in act if OFFER_RX.search((a.get("body") or "") + " " + (a.get("title") or "")))
117
+ fmts = Counter(a.get("media_format") for a in act)
118
+ top = sorted(oldest[:5] + act, key=lambda a: -(a.get("days_running") or 0))[:3]
119
+ sig = dict(active_total=total if total is not None else len(act), longest_days=longest,
120
+ launches_30d=launches, reuse=reuse, offer=offer)
121
+ def num(x):
122
+ try: return int(str(x).rstrip("+"))
123
+ except Exception: return 0
124
+ strong = [k for k, v in STRONG.items() if num(sig[k]) >= v]
125
+ verdict = "FOLLOW" if len(strong) >= 3 else "WATCH" if len(strong) == 2 else "SKIP"
126
+ return dict(name=b.get("name", name), atria_id=bid, found=True, lifetime_ads=b.get("ad_num"),
127
+ website=b.get("website"), industries=b.get("industries"), **sig,
128
+ strong=strong, verdict=verdict, formats=dict(fmts),
129
+ longest_ads=[dict(days=a.get("days_running"), title=(a.get("title") or "")[:90],
130
+ hook=(a.get("body") or "")[:160].replace("\n", " "), link=a.get("link_url")) for a in top])
131
+
132
+
133
+ def main():
134
+ ap = argparse.ArgumentParser()
135
+ ap.add_argument("--names", nargs="*", default=[])
136
+ ap.add_argument("--file")
137
+ ap.add_argument("--out", default="competitor-sheet.md")
138
+ ap.add_argument("--json")
139
+ a = ap.parse_args()
140
+ names = list(a.names)
141
+ if a.file:
142
+ names += [l.strip() for l in open(a.file) if l.strip() and not l.startswith("#")]
143
+ if not names: sys.exit("no brand names given")
144
+ rows = []
145
+ for n in names:
146
+ try:
147
+ r = score(n); rows.append(r)
148
+ print(f"{r.get('name', n):<34} {r.get('verdict', 'NOT FOUND'):<9} active={r.get('active_total')} longest={r.get('longest_days')}d launches30={r.get('launches_30d')} reuse={r.get('reuse')} offer={r.get('offer')}", flush=True)
149
+ except Exception as e:
150
+ rows.append(dict(name=n, found=False, error=str(e))); print(n, "ERR", e, flush=True)
151
+ time.sleep(1.0)
152
+ order = {"FOLLOW": 0, "WATCH": 1, "SKIP": 2}
153
+ rows.sort(key=lambda r: (order.get(r.get("verdict"), 3), -(r.get("active_total") or 0)))
154
+ with open(a.out, "w") as f:
155
+ f.write(f"# Competitor sheet ({dt.date.today()})\n\nVerdict: FOLLOW = 3+ strong signals · WATCH = 2 · SKIP = 0–1. Thresholds: {STRONG}\n\n")
156
+ f.write("| Brand | Verdict | Active | Longest (d) | Launches 30d | Reuse | Offer | Strong on | Longest-running ad |\n|---|---|---|---|---|---|---|---|---|\n")
157
+ for r in rows:
158
+ if not r.get("found"):
159
+ f.write(f"| {r['name']} | NOT FOUND | | | | | | | {r.get('error', '')} |\n"); continue
160
+ la = r["longest_ads"][0] if r["longest_ads"] else {}
161
+ f.write(f"| {r['name']} | {r['verdict']} | {r['active_total']} | {r['longest_days']} | {r['launches_30d']} | {r['reuse']} | {r['offer']} | {', '.join(r['strong'])} | {la.get('days', '')}d: {la.get('hook', '')[:100]} |\n")
162
+ f.write("\n## Fill in by hand\n\nFor every FOLLOW: UMP (the mechanism they sell) · offer · persona pages · why it matters · what to steal · Amazon review count.\n")
163
+ if a.json: json.dump(rows, open(a.json, "w"), indent=1)
164
+ print("wrote", a.out)
165
+
166
+
167
+ if __name__ == "__main__":
168
+ main()
@@ -0,0 +1,81 @@
1
+ ---
2
+ name: handoff
3
+ description: End a working session properly, and periodically read the sessions back. Fires on "handoff", "wrap up", "scrape this chat", "save this session", "add this to my workflow", "note your place and close", "what did we do today", or at the natural end of a session. It (1) scrapes the chat into a dated session file with verbatim asks, outputs and where they live, corrections, and the steering behind each ask; (2) proposes STANDARDS.md entries from what it saw the user say, edit, and pick, and waits for a yes; (3) writes a resume prompt so the next session starts warm; (4) updates the one-page distilled workflow. In review mode ("handoff review", "read my last ten sessions", "how do I actually work") it reads the session files and standards and writes an end-to-end read of the user's workflow with patterns, disagreements between their own versions, and suggestions. The session files are the most valuable asset in the folder: the before-and-after record of how the user thinks. Never edit one after it is written.
4
+ ---
5
+
6
+ # Handoff
7
+
8
+ The chat is where feedback actually lives: what was said, what was edited, what was picked. Most of it evaporates when the window closes. This skill catches it, once, at the end.
9
+
10
+ Read `STANDARDS.md` first ("How I give feedback" decides how much this skill proposes). Sessions live in `workflow/` at the workspace root: `workflow/sessions/` for the dated session files, `workflow/workflow.md` for the one-page distilled workflow, `workflow/reviews/` for review reads. Create the folder on first use.
11
+
12
+ ## Mode 1: session (default)
13
+
14
+ Start with one question and nothing else: "Pull this session into your workflow?" No means write nothing. Yes means all four steps, then a short reply.
15
+
16
+ ### Step 1. Scrape the chat
17
+
18
+ Write `workflow/sessions/YYYY-MM-DD_<brand>-<topic>.md` (date is the session start). Split the chat into phases by intent (setup, research, planning, build, review, meta). Per phase:
19
+
20
+ 1. **Ask (verbatim).** The user's exact words in a blockquote, typos included. Several quotes if the ask evolved. Never paraphrase here.
21
+ 2. **What happened.** Two to four sentences.
22
+ 3. **Outputs.** Paths, artifact links, Drive links, Exodus surfaces. Exact.
23
+ 4. **Steering.** Why they asked it, what it reveals about how they work, the rule or preference it implies. One paragraph.
24
+ 5. **Corrections.** Anything redirected, quoted verbatim, with the lesson.
25
+ 6. **Tool feedback.** Gaps hit in Exodus or any tool.
26
+
27
+ At the end of the file: **Where everything lives** (a table), **Principles extracted** (numbered, from this session's quotes only), **What to make better next time** (concrete, from the corrections).
28
+
29
+ Rules: quotes exact; include the meta-asks (honesty checks, "can you see the context"); include reversals; note when another person or session edited files; never save secrets (write "keys pasted in chat" and nothing else); if context was summarised, say so and mark unquotable phases "reconstructed". Once written, the file is read-only to the system.
30
+
31
+ ### Step 2. Propose standards
32
+
33
+ Read the session back for three kinds of signal and turn each into a proposed entry in the shape STANDARDS.md uses (one dated line, the quote underneath, the section):
34
+
35
+ - **Said.** Anything with always, never, from now on, I hate, I love, do it like this. Also any note given twice across this and earlier sessions (check the Log).
36
+ - **Edited.** Any place the user changed a draft: what was there, what they made it, the principle in one line. These are before-and-after pairs; record them as pairs.
37
+ - **Picked.** Any place the user chose from a set (three hooks out of twenty, one option of four): what they kept, what they rejected, the pattern in one line.
38
+
39
+ Present them as a numbered list, at most ten, strongest first. The user answers by number. Write only the approved ones, exactly as `remember-that` would (section, log line, bank promote for approved winning lines, offer for anything that touches a workflow or primer). If "How I give feedback" says no proposals, skip this step and say so.
40
+
41
+ ### Step 3. Write the resume prompt
42
+
43
+ Append to the session file a section **Resume** with: what is done, what is missing, what is next (in that order, the way "note your place" works), the files to read first, and one paragraph the user can paste into a new session to start warm. Say the paragraph back in the reply so it is one copy away.
44
+
45
+ ### Step 4. Update the distilled workflow
46
+
47
+ Open `workflow/workflow.md` (create it if it does not exist). Add or adjust only what this session changed. Keep it one page. Do not rewrite it.
48
+
49
+ ### The reply
50
+
51
+ Short: the session file path, the two or three strongest steering signals in one line each, the proposals awaiting a yes (or that they were written), the resume paragraph, and any change to `workflow.md`. No essay.
52
+
53
+ ## Mode 2: review
54
+
55
+ Fires on "handoff review", "read my sessions", "how do I actually work", or when the session count since the last review passes the number in "How I give feedback" (default ten). Reads every session file, `workflow.md`, and `STANDARDS.md`, and writes `workflow/reviews/YYYY-MM-DD_review.md`:
56
+
57
+ 1. **The shape of it.** The user's workflow as a numbered sequence of stages, drawn from what they actually did across sessions, not what any skill says they should do.
58
+ 2. **The rules underneath it.** What drives the work: the modes they switch between, what they read raw before trusting, how they brief (by example, by list), the taxonomy they use, what they check every time.
59
+ 3. **Where their own versions disagree.** Places the sessions contradict each other or the standards, one line each, with the decision it implies.
60
+ 4. **Where it stands.** What is done, unfinished, blocked, and what has moved on disk since the last scrape.
61
+ 5. **Suggestions.** Three to five, each with the evidence rung it rests on (own sessions, standards, logic marked HYPOTHESIS). Things to make into rules, tools, or skills; things to retire; things the user keeps doing by hand that should be a bot (hand to `bot-builder`).
62
+ 6. **Standards proposals** from the review, same numbered shape as Mode 1, waiting for a yes.
63
+
64
+ Then say the three biggest findings in the reply and stop. The user decides what to act on.
65
+
66
+ ## Mode 3: resume
67
+
68
+ At the start of a session, check the newest file in `workflow/sessions/`. If it has a Resume section, offer it: "Last session ended at: <done / missing / next>. Continue from there?" Yes means read the files it names and pick up at "next". Do not re-derive what was already decided.
69
+
70
+ ## Rules
71
+
72
+ - Session files are never edited after writing. A correction to a scrape is a new note in the next session.
73
+ - Quotes are the asset. Steering is your read of them, labelled as such.
74
+ - Plain language throughout. Collaborators will read these. No jargon that needs explaining. Do not call anyone a junior.
75
+ - Keep the where-it-lives table current; the scrape is mechanical when the index was kept during the session.
76
+ - Never propose the same standard twice. Check the Log.
77
+ - The user is the only source of rules. Proposals wait.
78
+
79
+ ## Changelog
80
+
81
+ - 2026-09-14 · v1. Absorbs the earlier workflow-scrape skill; adds proposals from said, edited, picked; adds review and resume modes.
@@ -0,0 +1,130 @@
1
+ ---
2
+ name: mechanism
3
+ description: Luke's way of finding a product's mechanism (the unique mechanism of the problem and of the solution) for each segment and persona: one problem, one solution, simple, intuitive, visual, concrete, never multi-headed. Use it whenever someone asks "what's the mechanism", "what's our UMP / UMS", "why does this work", "name the problem", "what's the ingredient story", "find the lock", "which ingredient leads", "what mechanism for this persona", or wants mechanism ideas from the Genesis bots (Universal Mechanism Bot, Health Mechanism Matrix Bot, and the supporting characterizations, metaphors, and surprising-culprit bots). It reads the competitor mechanism file first, uses the bots for breadth, then filters everything through the simplicity criteria and matches the survivors to the product's unique features (star ingredient, booster, delivery, founder, story) until the story locks. Runs inside the positioning-spiral as the features station and hands the chosen mechanisms to copy-instincts and the writing pipeline. Needs GENESIS_API_KEY plus a provider key in .env for the bot calls; works without them as a conversation.
4
+ ---
5
+
6
+ # Mechanism
7
+
8
+ A mechanism is the story of why the problem happens and why this product fixes it. The best ones are two links long. A student's mechanism has six moving parts and nothing rhymes; a great one is "your hormones deplete, so your cells can't absorb" and the star ingredient is the thing that opens the door. This skill exists to keep mechanisms that simple, to find them per segment rather than once for the brand, and to match each one to the feature that makes it ownable.
9
+
10
+ Think mode until a bot run or a competitor scrape. Those are build bursts: say the plan and cost back in two lines, get the go, run, then come back with a short list. Read `thinking-vs-build` if installed.
11
+
12
+ ## The rules
13
+
14
+ 1. **One problem, one solution.** Two links maximum: A happens → B is the symptom. The fix inverts A. If it needs a third link it is not a mechanism yet, it is a paragraph.
15
+ 2. **Simple, intuitive, visual, concrete.** A ten-year-old gets it in three seconds. It can be drawn on a whiteboard. It matches how the problem feels in the body (stuck → flowing, heavy → light, wired → settled). "It's like a [familiar thing] for [this]" completes without effort.
16
+ 3. **Not multi-headed.** One cause. Not "hormones and cortisol and gut". If the market believes three causes, pick the one this segment believes and leave the others for other segments.
17
+ 4. **The name implies the fix.** A pulse can be quieted, a leak plugged, a switch flipped, gunk cleaned. Cannibal brain cannot be un-eaten. Name it in two or three words: body thing plus what it is doing wrong.
18
+ 5. **Per segment, per persona.** A mechanism that explains the 3AM wake does not explain rage at the kids. Build the map cell by cell; some cells share a mechanism, most do not.
19
+ 6. **Ownable.** The mechanism must land on a unique feature so no competitor can say it the same way. Star ingredient alone. Star × booster. Star × delivery. Star × booster × delivery. Feature × founder. Feature × story. Supporting ingredients never lead.
20
+ 7. **Zeitgeist counts, borrowed words are fine, saturated words are not.** If the market already says "cortisol", use it and take the unowned corner of it (night cortisol, not belly). If four strong brands own the exact phrase, move one word over.
21
+ 8. **Psychology first, then make it true.** Decide the mechanism that would be most intuitive, then check the science can carry it and the compliance team can live with it. Facts-first produces the same mechanism everyone has.
22
+
23
+ ## Inputs
24
+
25
+ - The product's features: formula with doses, form factor and timing, founder and story, process, proof. From the `positioning-spiral` features station or the brief.
26
+ - The segment grid and any personas: the outcome, sub-outcome, and the Belief facet for each cell. From `odf`.
27
+ - The competitor mechanism file (below). From `find-competitors` and the rip.
28
+ - Voice-of-customer quote banks: the words they use for the cause ("I think it's my hormones", "wired but exhausted").
29
+
30
+ ## Step 1. The competitor mechanism file
31
+
32
+ Before generating anything, know what the market is already being sold. One file, one row per competitor mechanism, built from the ad bank, the swipe file, and the sheet from `find-competitors`. Template and the operations to run on it are in `references/competitor-mechanisms.md`. The short version:
33
+
34
+ - **UMP census:** count competitors by the mechanism word they sell. Crowded words are proven; empty words are either unowned or unwanted.
35
+ - **Corner map:** for each crowded word, which corner do they own (cortisol → belly, face, morning) and which corners are empty (cortisol → night).
36
+ - **The visual each one uses**, the name each one gives the problem, and the two-link version of their story. If their story cannot be written in two links, that is a weakness you can beat.
37
+ - **What they blame** (the industry, a food, a habit, the body) and **what they absolve**.
38
+
39
+ Output in think mode: the three or four crowded words, the empty corners, one line each.
40
+
41
+ ## Step 2. Breadth from the bots
42
+
43
+ The bots produce more candidates than a person will, and they are meant to be over-generated then cut. They also tend to be over-complicated; that is what Step 3 is for.
44
+
45
+ Which bot:
46
+ - **Supplements and anything with a body mechanism:** `health-mechanism-matrix-bot`. It builds a 12-mechanism research prompt from the 12-box matrix (structure / function / element × too much / too little / out of balance / dysfunctional), then ranks the top four on five criteria (understand, attention, visualise, A→B path, body-feel) out of 50. Told to "run the full process" it ranks from its own knowledge without waiting for external research.
47
+ - **Everything else, and a second pass on supplements:** `universal-mechanism-bot`. 36 candidates from the 9-box matrix, scored on zeitgeist 40, intuitive simplicity 40, novelty 20, top three with hooks.
48
+ - **After a mechanism is chosen:** `characterizations-bot` for 20 names and a top three, `metaphors-bot` for the visual, `surprising-culprit-bot` for the villain angle, `segmentmech-swapper-bot` to swap the mechanism into an existing winner.
49
+
50
+ How to call them: the `genesis-bots` skill's helper, one call at a time (one concurrent stream per key), output to a file in the folder. Prompt templates that produce the shape this skill needs are in `references/bot-prompts.md`. The prompt always carries the constraint: one problem, one solution, two links, star ingredient named, competitor words listed so the bot avoids the crowded corners.
51
+
52
+ Cost: each bot run is one long completion on the provider key (a few cents to a few tens of cents). Say it back before running.
53
+
54
+ Run one bot per segment cell you are working, not one per brand. Save each output inside the active brand's folder, under `<brand>/state/mechanisms/<segment-slug>/<bot>.md` (run `npx @aicopycoders/exodus brand current` first; never write one brand's material into another brand's folder).
55
+
56
+ ## Step 3. Cut to simple
57
+
58
+ Take every candidate (bot output, competitor corners, your own) and put it through this in order. Most die at the first gate.
59
+
60
+ 1. **Two links?** Write it as "A → B". If it needs "and" or a third arrow, cut or collapse it.
61
+ 2. **One cause?** If it names two causes, split it into two candidates or cut one.
62
+ 3. **Draw it.** One picture. If you cannot draw it, simplify until you can.
63
+ 4. **Barista test.** Say it while ordering coffee. If it needs a setup sentence, cut.
64
+ 5. **Body-feel.** Does the solution match how the problem feels? Wired → settled, not wired → "optimised".
65
+ 6. **Belief match.** Does it use the cause this segment already believes, or one they will accept in a sentence? A mechanism the persona has to be taught is a mechanism for a different persona.
66
+ 7. **Name implies fix.** Rename until it does.
67
+ 8. **Corner check.** Against the competitor file: is this word crowded, and if so is this the empty corner?
68
+ 9. **Plausibility.** Can the science carry the two links at the doses in the bottle? Mark the rung compliance will pull.
69
+
70
+ Survivors get the bot's scores if it gave them, otherwise score simplicity, zeitgeist, and novelty 40/40/20 by hand. Keep the top three per cell.
71
+
72
+ ## Step 4. Find the lock
73
+
74
+ For each surviving mechanism, match it to the unique feature that makes it ownable. Try the combinations in this order and stop at the first that rhymes:
75
+
76
+ | Shape | Question |
77
+ |---|---|
78
+ | Star alone | Does the star ingredient's natural story explain the fix by itself? |
79
+ | Star × booster | Does one partner make the two-link story stronger without adding a link? |
80
+ | Star × delivery | Does the form factor or timing carry the mechanism (evening gummy active at 3AM; sublingual in 20 minutes; patch while you sleep)? |
81
+ | Star × booster × delivery | Only if all three say the same thing in different languages. Three dials, one rhyme. |
82
+ | Feature × founder | Does the founder's background make them the natural discoverer? |
83
+ | Feature × story | Does the origin, process, or place carry it (untouched land, forged rock)? |
84
+
85
+ Then the lock test from `copy-instincts`: one breath, no "and also", pain and solution share a root metaphor, the spokesperson is irreplaceable, proof is a chapter of the story. Write the one-breath version. If it does not lock, go back to the competitor file or the bots with the constraint tightened.
86
+
87
+ Sympathetic magic belongs here: what does the star ingredient's source do in nature that maps to the fix? Use it if it rhymes, drop it if it needs explaining.
88
+
89
+ ## Step 5. The mechanism map
90
+
91
+ One row per segment cell that has a chosen mechanism. Lives in the active brand's folder as `<brand>/state/mechanism-map.md` and feeds the ingredient-story column of the segment grid.
92
+
93
+ ```
94
+ # <Brand> — <Product> — Mechanism Map (v<n>, <date>)
95
+
96
+ | Segment (O → sub · D · F) | Problem, named | A → B | Solution, named | Lock (star / booster / delivery / feature) | One picture | Belief it uses | Competitor corner | Proof rung | Compliance rung |
97
+
98
+ ## One-breath versions
99
+ - <segment>: "<one breath>"
100
+
101
+ ## Cut and why
102
+ - <candidate> — died at gate <n>: <reason>
103
+
104
+ ## Bot runs
105
+ - <segment>: health-mechanism-matrix-bot → <brand>/state/mechanisms/<slug>/health.md (top pick: …)
106
+ ```
107
+
108
+ Hand-offs: `copy-instincts` for the story and the hooks (the mechanism is the curiosity block), `characterizations-bot` and `metaphors-bot` for names and visuals, the writing pipeline for ads, and back to `positioning-spiral` for the catalog collision check (a mechanism a sister SKU already claims is a collision).
109
+
110
+ ## Worked example: Evenkeel Reset Gummies (fictional)
111
+
112
+ Evening gummy: saffron 30mg, magnesium glycinate 200mg, rhodiola 100mg. Founder a former ER night-shift nurse. Segment: women 45 to 60 who fall asleep fine and wake at 3AM, many on HRT and still waking, melatonin fails, Belief facet "hormones or cortisol".
113
+
114
+ **Step 1.** Competitor file: cortisol is crowded (four strong brands) but they own belly, face, and morning. Sleep-onset is crowded and fatiguing. Peri hormone-balance is crowded. Empty corner: night cortisol, "stay asleep".
115
+
116
+ **Step 2.** `health-mechanism-matrix-bot` with the template prompt. Top four, scored out of 50: 3AM Cortisol Pulse (45), Serotonin Night Drain (44), HPA Brake Failure (40), Sleep-Guard Signal Collapse (39). Its own read: lead with the pulse because it borrows the word competitors already taught and takes the unowned night corner; the evening gummy timing becomes the delivery story.
117
+
118
+ **Step 3.** Pulse: two links (cortisol fires too early and too hard → brain snaps awake). One cause. Drawable (a flare at 3AM on a line that should slide downhill). Barista: "your cortisol fires at 3AM instead of 6". Body-feel: snapping awake, exactly what they describe. Belief: cortisol, already held. Name implies fix: a pulse can be quieted. Corner: empty. Plausible at the doses with saffron's HPA evidence; "the only thing shown to quiet it" is the rung compliance pulls. HPA Brake Failure died at gate 1 (three links). Sleep-Guard died at gate 4.
119
+
120
+ **Step 4.** Star × delivery locks: saffron quiets the pulse, and an evening gummy is in the blood at 3AM when the pulse fires. Magnesium as booster adds no link, so it stays supporting. Founder rhymes: an ER nurse lived the 3AM surge every shift. One breath: "You don't have a falling-asleep problem, you have a 3AM cortisol pulse. It fires too early and snaps you awake. An evening saffron gummy is active in your blood at 3AM to quiet it, so you sleep through."
121
+
122
+ **Step 5.** Row written. Serotonin Night Drain held for the melatonin-fails persona as its own row. Collision check: Glow Collagen keeps belly and face; night is clear.
123
+
124
+ ## What this skill is not
125
+
126
+ It does not position the brand (positioning-spiral), map segments (odf), or write ads. It finds the two-link story per segment, proves it is ownable, and hands it on.
127
+
128
+ ## Standards
129
+
130
+ Before producing anything, read `STANDARDS.md` at the workspace root (and the section for this output type). Grade the draft against it before showing it; rewrite failures first. When the user reacts with a judgment, a banking phrase, or the same note twice, hand the reaction to `remember-that`. At the end of the session, `handoff` scrapes the chat and proposes entries.
@@ -0,0 +1,94 @@
1
+ # Bot prompts for the mechanism skill
2
+
3
+ All calls go through the `genesis-bots` helper, one at a time:
4
+
5
+ ```
6
+ node .claude/skills/genesis-bots/scripts/genesis-stream.mjs <bot-slug> <prompt.txt> <out.md>
7
+ ```
8
+
9
+ Slugs (confirm against the live list; they can change): `health-mechanism-matrix-bot`, `universal-mechanism-bot`, `characterizations-bot`, `metaphors-bot`, `surprising-culprit-bot`, `segmentmech-swapper-bot`.
10
+
11
+ Limits: one concurrent stream per key, 60 requests a minute. Each run is a long completion on the provider key. Run per segment cell, save under `state/mechanisms/<segment-slug>/`.
12
+
13
+ ## The constraint block (goes in every prompt)
14
+
15
+ ```
16
+ CONSTRAINT: I want ONE problem and ONE solution. Two links maximum (A happens → B is the symptom; the fix inverts A).
17
+ Simple, intuitive, visual, concrete. No multi-headed mechanisms. Name the problem in two or three words and make the name imply the fix.
18
+ Star ingredient: <name>. It must lead. <Booster> may support. <Delivery / timing> may carry the mechanism. Supporting ingredients never lead.
19
+ Avoid the crowded corners: <list the competitor words and the corners they own>. Take an empty corner if one exists.
20
+ Keep the output compact.
21
+ ```
22
+
23
+ ## health-mechanism-matrix-bot (supplements)
24
+
25
+ Tested prompt shape. Output: STEP 1 a research prompt covering 12 matrix mechanisms; STEP 2 a scoring table (Understand, Attention, Visualise, A→B Path, Body-Feel, total /50), the top four with mechanism, ingredient fix, criterion notes, marketing application and weakness, then a final recommendation. Told to "run your full process", it ranks from its own knowledge instead of waiting for external research. If you want the deeper version, take its STEP 1 research prompt, run it yourself (with the model, or a research tool the user has approved), paste the findings back to the bot, and ask it to re-rank.
26
+
27
+ ```
28
+ PRODUCT: <name>. <form factor and timing>. <formula with doses>. <founder and story in one line>.
29
+
30
+ SEGMENT / PERSONA: <outcome → sub-outcome · demographic · facets>. <what they have tried>. <what they believe causes it>. Money symptom: <the one they would pay anything to erase>.
31
+
32
+ COMPETITOR MECHANISMS ALREADY IN MARKET: <from the competitor file: word → who owns it → which corner>. Nobody strong owns <empty corner>.
33
+
34
+ <constraint block>
35
+
36
+ Run your full process on this.
37
+ ```
38
+
39
+ ## universal-mechanism-bot (any market; second pass on supplements)
40
+
41
+ Output: 9-box matrix × 3 examples each with names, a scoring table (zeitgeist 40, intuitive simplicity 40, novelty 20), top three with why-it-works and implementation notes. It will produce 27 to 36 candidates; expect most to be too complex, that is what Step 3 of the skill is for.
42
+
43
+ ```
44
+ BUILD A BUYER: <persona card or the ODF coordinate with self-ID line, tried-and-failed, belief>.
45
+
46
+ MARKET INFORMATION: <sophistication in one line>. <competitor mechanism census: the crowded words and their corners>. <zeitgeist words the market is using this quarter>.
47
+
48
+ OFFER BRIEF: <product, features, star ingredient or feature, delivery, founder, proof, transformation>.
49
+
50
+ <constraint block>
51
+
52
+ Generate the full matrix, score it, and give the top 3. For each of the top 3 also write the A → B in one line and the one picture I would draw on a whiteboard.
53
+ ```
54
+
55
+ ## characterizations-bot (after a mechanism is chosen)
56
+
57
+ ```
58
+ MECHANISM (UMP): <A → B in one line>. Problem name so far: "<name>".
59
+ SOLUTION (UMS): <the fix in one line>. Star: <ingredient or feature>. Delivery: <form/timing>.
60
+ SEGMENT: <coordinate and self-ID line>.
61
+ AVOID: names that imply the problem is permanent (eating, mutated, degenerating). Names must imply the fix.
62
+ Give 20 characterizations, classified UMP / UMS, then a ranked top 3 with one line on why each would stop the scroll.
63
+ ```
64
+
65
+ ## metaphors-bot (the one picture)
66
+
67
+ ```
68
+ UMP: <A → B>. UMS: <the fix>. Body-feel of the problem: <how it feels, in their words>. Body-feel of the fix: <the opposite>.
69
+ Give natural, mechanical, and object metaphors. Prefer ones I can draw in one frame and feel in the body (termites, not bulldozers). Mark the three you would put in a hook.
70
+ ```
71
+
72
+ ## surprising-culprit-bot (the villain, when the thesis needs one)
73
+
74
+ ```
75
+ PROBLEM: <money symptom>. SEGMENT: <coordinate>. MECHANISM: <A → B>.
76
+ What they are doing now to fix it: <the tried-and-failed list>.
77
+ Give 15 surprising culprits where something they trust or do every day is the cause. Rank by which the segment would believe in one sentence. Blame the product or the industry, never the person's body or discipline.
78
+ ```
79
+
80
+ ## segmentmech-swapper-bot (aim a winner at a new cell)
81
+
82
+ ```
83
+ WINNING AD: <full transcript or copy>.
84
+ KEEP: the structure, beat order, proof, offer, CTA, certainty.
85
+ SWAP: the mechanism from "<old A → B>" to "<new A → B>" and the segment from <old coordinate> to <new coordinate>, self-ID line "<line>".
86
+ Change only the lines the swap forces. List every line you changed.
87
+ ```
88
+
89
+ ## Reading bot output
90
+
91
+ - Take the scoring tables as a first sort, not a decision. The skill's Step 3 gates decide.
92
+ - Bots over-complicate. A "mechanism" with three arrows is two mechanisms or a paragraph. Collapse or split.
93
+ - Bots invent numbers and studies. Anything with a percentage or a citation gets marked as the compliance rung until checked.
94
+ - Keep the bot's "potential weakness" lines; they are usually right.
@@ -0,0 +1,39 @@
1
+ # The competitor mechanism file
2
+
3
+ One file per brand, inside that brand's folder: `<brand>/inputs/competitor-mechanisms.md`. One row per mechanism a competitor sells, built from the ad bank, the swipe file, and the FOLLOW rows of the competitor sheet. It is the thing you read before generating anything, because the market has already paid to learn which words work.
4
+
5
+ ## Row template
6
+
7
+ | Competitor | UMP word (the belief they sell) | Corner (which symptom or moment they own) | Problem, named (their words) | A → B (their story in two links, or "3+ links") | Solution, named | Star ingredient or feature | Visual they use | What they blame | What they absolve | Longest run (days) | Source (ad id) |
8
+
9
+ Rules for filling it:
10
+
11
+ - Their words, not yours. If the ad says "cortisol face", write that, not "elevated cortisol".
12
+ - One row per mechanism, not per ad. Ten ads on the same story is one row with the longest run.
13
+ - If their story cannot be written in two links, write "3+ links" and quote the extra link. That is a weakness.
14
+ - The visual is what is on screen when the mechanism is said: the diagram, the diagnosis overlay, the metaphor object.
15
+ - What they blame and what they absolve are the thesis: "the industry sold you falling asleep", "your body is fine".
16
+
17
+ ## Operations to run on the file
18
+
19
+ **UMP census.** Count rows by UMP word. Crowded words are proven demand. Empty words are unowned or unwanted; the reviews decide which.
20
+
21
+ **Corner map.** For each crowded word, list the corners owned and the corners empty. Cortisol: belly, face, morning owned; night empty. Gut: bloating, biofilm owned; mood empty.
22
+
23
+ **Two-link test.** How many competitor stories are two links? The ones that are not can be beaten on simplicity alone.
24
+
25
+ **Visual census.** Which pictures repeat (the diagram, the doctor skit, the before-and-after body)? A repeated picture is a proven picture and also a saturated one.
26
+
27
+ **Blame map.** Who is the villain across the set? An enemy nobody has named is an open lane.
28
+
29
+ **Ingredient map.** Which star ingredients carry which mechanisms? If three brands lead with ashwagandha on cortisol, ashwagandha cannot be your star on cortisol.
30
+
31
+ **Plain-word check.** For each UMP word, count it in reviews and comments (the voice-of-customer files). A word that is in every ad and few human mouths is competitor coinage; the plain word underneath it is the one to map.
32
+
33
+ ## Output in think mode
34
+
35
+ Three lines, then the next axis:
36
+
37
+ - Crowded: <word (n brands)> · <word (n)> · <word (n)>
38
+ - Empty corners: <word → corner> · <word → corner>
39
+ - Beatable on simplicity: <competitor, 3+ links>