taketomarket 0.1.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 (123) hide show
  1. package/.claude-plugin/plugin.json +10 -0
  2. package/LICENSE +21 -0
  3. package/README.md +419 -0
  4. package/agents/ttm-producer.md +53 -0
  5. package/bin/lib/campaign.cjs +553 -0
  6. package/bin/lib/commit.cjs +105 -0
  7. package/bin/lib/core.cjs +172 -0
  8. package/bin/lib/deviation.cjs +149 -0
  9. package/bin/lib/drift-log.cjs +219 -0
  10. package/bin/lib/health.cjs +438 -0
  11. package/bin/lib/slug.cjs +59 -0
  12. package/bin/lib/state.cjs +96 -0
  13. package/bin/ttm-tools.cjs +157 -0
  14. package/gates/base-gates.md +266 -0
  15. package/gates/discipline/.gitkeep +0 -0
  16. package/gates/gate-evaluation.md +341 -0
  17. package/gates/meta-gates.md +19 -0
  18. package/install.js +307 -0
  19. package/package.json +53 -0
  20. package/playbooks/.gitkeep +0 -0
  21. package/playbooks/aeo.md +223 -0
  22. package/playbooks/affiliate.md +272 -0
  23. package/playbooks/base.md +110 -0
  24. package/playbooks/email.md +306 -0
  25. package/playbooks/events.md +320 -0
  26. package/playbooks/linkedin.md +263 -0
  27. package/playbooks/paid-ads.md +318 -0
  28. package/playbooks/pr-media.md +296 -0
  29. package/playbooks/seo.md +284 -0
  30. package/playbooks/social.md +305 -0
  31. package/playbooks/youtube.md +325 -0
  32. package/references/context-loading.md +107 -0
  33. package/references/learnings-extraction.md +94 -0
  34. package/references/measurement-template.md +48 -0
  35. package/references/meta-gate-evaluation.md +169 -0
  36. package/references/positioning-check-report.md +197 -0
  37. package/references/review-checklist.md +78 -0
  38. package/references/ship-checklist-items.md +94 -0
  39. package/settings.json +4 -0
  40. package/skills/ttm-aeo-check/SKILL.md +20 -0
  41. package/skills/ttm-affiliate-kit/SKILL.md +19 -0
  42. package/skills/ttm-archive/SKILL.md +13 -0
  43. package/skills/ttm-brand-refresh/SKILL.md +19 -0
  44. package/skills/ttm-brief/SKILL.md +14 -0
  45. package/skills/ttm-competitor-scan/SKILL.md +19 -0
  46. package/skills/ttm-email-preflight/SKILL.md +19 -0
  47. package/skills/ttm-fix/SKILL.md +13 -0
  48. package/skills/ttm-health/SKILL.md +12 -0
  49. package/skills/ttm-icp-refresh/SKILL.md +19 -0
  50. package/skills/ttm-init/SKILL.md +12 -0
  51. package/skills/ttm-keyword-map/SKILL.md +19 -0
  52. package/skills/ttm-learn/SKILL.md +14 -0
  53. package/skills/ttm-measure/SKILL.md +14 -0
  54. package/skills/ttm-new-campaign/SKILL.md +13 -0
  55. package/skills/ttm-next/SKILL.md +12 -0
  56. package/skills/ttm-positioning-check/SKILL.md +19 -0
  57. package/skills/ttm-positioning-shift/SKILL.md +19 -0
  58. package/skills/ttm-produce/SKILL.md +14 -0
  59. package/skills/ttm-repurpose/SKILL.md +20 -0
  60. package/skills/ttm-research/SKILL.md +13 -0
  61. package/skills/ttm-resume/SKILL.md +13 -0
  62. package/skills/ttm-review/SKILL.md +13 -0
  63. package/skills/ttm-seo-audit/SKILL.md +20 -0
  64. package/skills/ttm-ship/SKILL.md +13 -0
  65. package/skills/ttm-state/SKILL.md +13 -0
  66. package/skills/ttm-verify/SKILL.md +14 -0
  67. package/templates/agents-md.md +65 -0
  68. package/templates/campaign-brief.md +74 -0
  69. package/templates/campaign-research.md +39 -0
  70. package/templates/campaign-state.md +40 -0
  71. package/templates/claude-md.md +65 -0
  72. package/templates/deviation-log.md +12 -0
  73. package/templates/drift-log.md +17 -0
  74. package/templates/fix-brief.md +59 -0
  75. package/templates/fix-log.md +22 -0
  76. package/templates/measurement-report.md +75 -0
  77. package/templates/migration-plan.md +24 -0
  78. package/templates/production-manifest.json +20 -0
  79. package/templates/reference-files/brand.md +45 -0
  80. package/templates/reference-files/calendar.md +30 -0
  81. package/templates/reference-files/channels.md +40 -0
  82. package/templates/reference-files/competitors.md +40 -0
  83. package/templates/reference-files/icp.md +50 -0
  84. package/templates/reference-files/learnings.md +40 -0
  85. package/templates/reference-files/metrics.md +42 -0
  86. package/templates/reference-files/positioning.md +38 -0
  87. package/templates/reference-files/state.md +27 -0
  88. package/templates/verification-report.md +59 -0
  89. package/workflows/discipline/.gitkeep +0 -0
  90. package/workflows/discipline/aeo-check.md +180 -0
  91. package/workflows/discipline/affiliate-kit.md +147 -0
  92. package/workflows/discipline/email-preflight.md +150 -0
  93. package/workflows/discipline/keyword-map.md +125 -0
  94. package/workflows/discipline/repurpose.md +329 -0
  95. package/workflows/discipline/seo-audit.md +169 -0
  96. package/workflows/lifecycle/.gitkeep +0 -0
  97. package/workflows/lifecycle/brief-positioning-check.md +90 -0
  98. package/workflows/lifecycle/brief.md +355 -0
  99. package/workflows/lifecycle/fix.md +495 -0
  100. package/workflows/lifecycle/learn.md +405 -0
  101. package/workflows/lifecycle/measure.md +379 -0
  102. package/workflows/lifecycle/produce.md +383 -0
  103. package/workflows/lifecycle/research.md +264 -0
  104. package/workflows/lifecycle/review.md +432 -0
  105. package/workflows/lifecycle/ship.md +521 -0
  106. package/workflows/lifecycle/verify.md +507 -0
  107. package/workflows/reference-mgmt/.gitkeep +0 -0
  108. package/workflows/reference-mgmt/brand-refresh.md +193 -0
  109. package/workflows/reference-mgmt/competitor-scan.md +228 -0
  110. package/workflows/reference-mgmt/icp-refresh.md +200 -0
  111. package/workflows/reference-mgmt/positioning-check.md +339 -0
  112. package/workflows/reference-mgmt/positioning-shift.md +368 -0
  113. package/workflows/setup/.gitkeep +0 -0
  114. package/workflows/setup/init-questions.md +225 -0
  115. package/workflows/setup/init-validation.md +155 -0
  116. package/workflows/setup/init.md +449 -0
  117. package/workflows/setup/new-campaign.md +134 -0
  118. package/workflows/utility/.gitkeep +0 -0
  119. package/workflows/utility/archive.md +334 -0
  120. package/workflows/utility/health.md +166 -0
  121. package/workflows/utility/next.md +187 -0
  122. package/workflows/utility/resume.md +249 -0
  123. package/workflows/utility/state.md +207 -0
@@ -0,0 +1,339 @@
1
+ <purpose>
2
+ Positioning drift audit workflow for /ttm-positioning-check. Samples recent assets
3
+ across all campaigns within a configurable time window (default 30 days per D-01),
4
+ evaluates each against GATE-01 positioning drift checks, generates a structured
5
+ audit report, and appends the results to .marketing/DRIFT-LOG.md.
6
+
7
+ This workflow can be invoked manually or auto-suggested by the ship workflow
8
+ after every 3rd campaign ships since the last audit (per D-02).
9
+ </purpose>
10
+
11
+ <required_reading>
12
+ @${CLAUDE_PLUGIN_ROOT}/references/context-loading.md
13
+ @${CLAUDE_PLUGIN_ROOT}/gates/gate-evaluation.md
14
+ @${CLAUDE_PLUGIN_ROOT}/references/positioning-check-report.md
15
+ </required_reading>
16
+
17
+ <constraints>
18
+ ## POSITIONING.md is READ-ONLY
19
+
20
+ **Do NOT modify `.marketing/POSITIONING.md` during this workflow.**
21
+
22
+ POSITIONING.md is an architectural invariant. If you detect positioning drift:
23
+ - In verify: use the Escalate option to launch /ttm-positioning-shift
24
+ - In other workflows: flag the issue and recommend running /ttm-positioning-check
25
+
26
+ Only /ttm-positioning-shift and /ttm-init may modify POSITIONING.md.
27
+ </constraints>
28
+
29
+ <process>
30
+
31
+ ## Text-Mode Detection
32
+
33
+ **Text mode (`--text` flag):** Set `TEXT_MODE=true` if `--text` is present in `$ARGUMENTS`
34
+ or if the runtime is not Claude Code. When TEXT_MODE is active, replace every
35
+ `AskUserQuestion` call with a plain-text numbered list.
36
+
37
+ Detection:
38
+ ```bash
39
+ if echo "$ARGUMENTS" | grep -q -- '--text'; then TEXT_MODE=true; fi
40
+ ```
41
+
42
+ If `AskUserQuestion` tool is not available in the current runtime, set `TEXT_MODE=true`.
43
+
44
+ When TEXT_MODE is active, replace each AskUserQuestion with a plain-text numbered list:
45
+ ```
46
+ [HEADER]
47
+ [QUESTION]
48
+ 1. [OPTION_1_LABEL] -- [OPTION_1_DESCRIPTION]
49
+ 2. [OPTION_2_LABEL] -- [OPTION_2_DESCRIPTION]
50
+ ...
51
+ Type the number of your choice:
52
+ ```
53
+
54
+ ---
55
+
56
+ ## Step 1: Load Context
57
+
58
+ ```
59
+ takeToMarket > LOADING CONTEXT FOR POSITIONING AUDIT
60
+ ```
61
+
62
+ **Load Tier 1 summaries** from all 9 reference files (lines 1 to `<!-- END_SUMMARY -->`):
63
+ - `.marketing/POSITIONING.md`
64
+ - `.marketing/BRAND.md`
65
+ - `.marketing/ICP.md`
66
+ - `.marketing/CHANNELS.md`
67
+ - `.marketing/STATE.md` (frontmatter only)
68
+ - `.marketing/CALENDAR.md`
69
+ - `.marketing/COMPETITORS.md`
70
+ - `.marketing/METRICS.md`
71
+ - `.marketing/LEARNINGS.md`
72
+
73
+ **Load Tier 2 (full content)** for drift evaluation:
74
+ - `.marketing/POSITIONING.md` (needed for all 3 GATE-01 checks)
75
+
76
+ If `.marketing/POSITIONING.md` does not exist: Error:
77
+ "No POSITIONING.md found. Run /ttm-init first to set up your marketing workspace."
78
+ Exit.
79
+
80
+ ---
81
+
82
+ ## Step 2: Parse Time Window
83
+
84
+ Parse optional `--since` argument from $ARGUMENTS. Default: `30d` (per D-01).
85
+
86
+ ```bash
87
+ WINDOW=$(echo "$ARGUMENTS" | grep -oP '(?<=--since\s)\S+' || echo "30d")
88
+ ```
89
+
90
+ Extract number and unit:
91
+ - Format: `Nd` where N is a number and d = days
92
+ - Example: `30d` = last 30 days, `90d` = last 90 days, `7d` = last 7 days
93
+ - Calculate cutoff date from current date minus N days
94
+
95
+ Display:
96
+ ```
97
+ takeToMarket > AUDIT WINDOW: last ${WINDOW}
98
+ ```
99
+
100
+ ---
101
+
102
+ ## Step 3: Enumerate Campaigns and Assets
103
+
104
+ ```
105
+ takeToMarket > ENUMERATING CAMPAIGNS
106
+ ```
107
+
108
+ Run campaign enumeration via CLI:
109
+ ```bash
110
+ CAMPAIGNS_JSON=$(node "${CLAUDE_PLUGIN_ROOT}/bin/ttm-tools.cjs" campaign list --since ${WINDOW} --raw)
111
+ ```
112
+
113
+ Parse the JSON result. Expected format: `{ "campaigns": [...], "count": N }`
114
+
115
+ If count is 0:
116
+ ```
117
+ takeToMarket > NO CAMPAIGNS FOUND
118
+
119
+ No campaigns with assets in the last ${WINDOW}. Nothing to audit.
120
+ ```
121
+ Exit.
122
+
123
+ **Per Pitfall 2:** The CLI already excludes archived campaigns from the results.
124
+
125
+ For each campaign in the result:
126
+ 1. Read the campaign's ASSETS/ directory:
127
+ ```
128
+ Glob: .marketing/CAMPAIGNS/${SLUG}/ASSETS/*
129
+ ```
130
+ 2. Collect all asset files found
131
+ 3. Also read `.marketing/CAMPAIGNS/${SLUG}/DEVIATIONS.md` if it exists
132
+ - Filter for rows where Gate = `positioning_drift` (GATE-01 deviations per D-13)
133
+ - Store these as accepted deviations for the cross-reference section
134
+
135
+ Display:
136
+ ```
137
+ takeToMarket > FOUND ${ASSET_COUNT} assets across ${CAMPAIGN_COUNT} campaigns
138
+ ```
139
+
140
+ ---
141
+
142
+ ## Step 4: Evaluate Each Asset Against GATE-01
143
+
144
+ ```
145
+ takeToMarket > EVALUATING POSITIONING DRIFT
146
+ ```
147
+
148
+ For each collected asset:
149
+
150
+ 1. Read the full asset content from disk
151
+ 2. Evaluate against GATE-01's 3 checks (from @gate-evaluation.md):
152
+
153
+ **Check 1: Differentiator Alignment**
154
+ Does the asset restate or naturally extend the primary differentiator from
155
+ POSITIONING.md? Or does it introduce a different claim?
156
+ - PASS: Asset reinforces the primary differentiator
157
+ - WARN: Asset is neutral -- neither reinforces nor contradicts
158
+ - FAIL: Asset introduces a different/competing claim
159
+
160
+ **Check 2: Proof Point Sourcing**
161
+ Are all factual claims in the asset backed by proof points in the POSITIONING.md
162
+ proof point library?
163
+ - PASS: All claims backed by POSITIONING.md proof points
164
+ - WARN: Some claims present but not all sourced
165
+ - FAIL: Claims contradict or fabricate proof points
166
+
167
+ **Check 3: Must-Not-Say Compliance**
168
+ Does the asset contain any terms from the POSITIONING.md must-not-say list?
169
+ - PASS: No must-not-say terms found
170
+ - WARN: Terms appear in non-customer-facing context
171
+ - FAIL: Must-not-say terms in customer-facing copy
172
+
173
+ 3. Record per-check result: PASS / WARN / FAIL with evidence
174
+ 4. Calculate per-asset drift %: (WARN count + FAIL count) / 3 * 100
175
+
176
+ **IMPORTANT per RESEARCH.md Pitfall 1:** Drift = (WARN + FAIL checks) / total checks.
177
+ Both WARN and FAIL contribute equally to the drift percentage calculation.
178
+
179
+ Display progress for each asset:
180
+ ```
181
+ [${INDEX}/${TOTAL}] ${ASSET_NAME} (${CAMPAIGN_SLUG}): ${DRIFT_PCT}% drift
182
+ ```
183
+
184
+ ---
185
+
186
+ ## Step 5: Calculate Aggregates
187
+
188
+ After evaluating all assets:
189
+
190
+ - **Total assets evaluated:** count of all sampled assets
191
+ - **Aggregate drift %:** total (WARN + FAIL results) / (total assets * 3) * 100
192
+ - **Count by drift category:**
193
+ - Differentiator Alignment: count of WARN + FAIL on Check 1 across all assets
194
+ - Proof Point Sourcing: count of WARN + FAIL on Check 2 across all assets
195
+ - Must-Not-Say Violations: count of WARN + FAIL on Check 3 across all assets
196
+ - **Cross-reference accepted deviations** from DEVIATIONS.md files collected in Step 3 (per D-13)
197
+
198
+ ---
199
+
200
+ ## Step 5b: Bleeding Analysis
201
+
202
+ ```
203
+ takeToMarket > ANALYZING MUST-NOT-SAY BLEEDING
204
+ ```
205
+
206
+ From the per-asset evaluation results collected in Step 4, extract all assets where
207
+ Check 3 (Must-Not-Say Compliance) returned WARN or FAIL.
208
+
209
+ For each must-not-say violation:
210
+
211
+ 1. **Classify the asset as customer-facing or non-customer-facing:**
212
+ - Customer-facing: landing pages, blog posts, ad copy, social posts, email campaigns,
213
+ any asset intended for external audience consumption
214
+ - Non-customer-facing: internal briefs, research docs, planning notes, strategy docs
215
+ - When ambiguous, classify as customer-facing (conservative default per
216
+ @positioning-check-report.md Bleeding Analysis rules)
217
+
218
+ 2. **Determine bleeding status:**
219
+ - Check 3 = FAIL (customer-facing asset): Mark as **BLEEDING** (Critical)
220
+ - Check 3 = WARN (non-customer-facing asset): Mark as **NOT BLEEDING** (Advisory)
221
+
222
+ 3. **Extract the specific must-not-say term and surrounding context** (10 words before
223
+ and after the term occurrence) for inclusion in the Bleeding Analysis report section.
224
+
225
+ Calculate bleeding metrics:
226
+ - **BLEEDING_COUNT:** Number of assets with Check 3 = FAIL (customer-facing violations)
227
+ - **MNS_VIOLATION_COUNT:** Total assets with Check 3 = WARN or FAIL
228
+ - **BLEEDING_RATE:** BLEEDING_COUNT / MNS_VIOLATION_COUNT * 100 (0% if no violations)
229
+
230
+ Display:
231
+ ```
232
+ Bleeding: ${BLEEDING_COUNT} of ${MNS_VIOLATION_COUNT} must-not-say violations in customer-facing materials
233
+ ```
234
+
235
+ These values feed into the Bleeding Analysis section of the report generated in Step 7.
236
+
237
+ ---
238
+
239
+ ## Step 6: Trend Comparison
240
+
241
+ Read `.marketing/DRIFT-LOG.md`. Find the most recent entry with Event = `audit`.
242
+
243
+ **If a prior audit entry exists (per D-03):**
244
+ 1. Parse the Details column to extract the prior aggregate drift percentage
245
+ - Expected format: `"Nd audit: X% drift, Y findings across Z assets"`
246
+ - Extract X as the prior drift percentage
247
+ 2. Calculate delta: current aggregate drift % - prior aggregate drift %
248
+ 3. Determine trend:
249
+ - Delta > +5%: UP (drift increasing -- positioning adherence worsening)
250
+ - Delta < -5%: DOWN (drift decreasing -- positioning adherence improving)
251
+ - Delta between -5% and +5%: STABLE (no significant change)
252
+ 4. Set TREND_ARROW and TREND_DETAIL for the report
253
+
254
+ **If no prior audit entry exists:**
255
+ - Set TREND_ARROW = ""
256
+ - Set TREND_DETAIL = "First audit -- no trend data available."
257
+
258
+ ---
259
+
260
+ ## Step 7: Generate Report
261
+
262
+ Follow the report format from @positioning-check-report.md.
263
+
264
+ Generate the full audit report including:
265
+ - Header with audit window and asset count
266
+ - Aggregate drift percentage with trend arrow
267
+ - Per-asset results table (asset x check matrix with drift %)
268
+ - Drift type breakdown (count per category)
269
+ - Bleeding analysis (must-not-say violations classified by asset type with bleeding count and rate)
270
+ - Findings detail for every WARN and FAIL result
271
+ - Accepted deviations cross-reference
272
+ - Trend comparison (if prior audit exists)
273
+ - Recommendations based on aggregate drift thresholds
274
+
275
+ **Display the report to stdout** (per A1 -- this is a cross-campaign audit,
276
+ not scoped to a single campaign directory).
277
+
278
+ ---
279
+
280
+ ## Step 8: Log to DRIFT-LOG.md
281
+
282
+ Append the audit results to `.marketing/DRIFT-LOG.md` via CLI:
283
+
284
+ ```bash
285
+ node "${CLAUDE_PLUGIN_ROOT}/bin/ttm-tools.cjs" drift-log append \
286
+ --event-type audit \
287
+ --source "/ttm-positioning-check" \
288
+ --details "${WINDOW} audit: ${AGGREGATE_DRIFT}% drift, ${DRIFT_COUNT} findings across ${ASSET_COUNT} assets" \
289
+ --affected ${ASSET_COUNT}
290
+ ```
291
+
292
+ **IMPORTANT:** Always use the CLI for DRIFT-LOG.md writes. Never write to the file
293
+ directly. The CLI handles append-only semantics, marker-based insertion, and
294
+ consistent formatting.
295
+
296
+ Display:
297
+ ```
298
+ takeToMarket > AUDIT LOGGED TO .marketing/DRIFT-LOG.md
299
+ ```
300
+
301
+ ---
302
+
303
+ ## Step 9: Completion Banner
304
+
305
+ ```
306
+ ========================================
307
+ takeToMarket > POSITIONING AUDIT COMPLETE
308
+ ========================================
309
+
310
+ Window: last ${WINDOW} | Assets audited: ${ASSET_COUNT}
311
+ Aggregate drift: ${AGGREGATE_DRIFT}% ${TREND_ARROW}
312
+ Campaigns covered: ${CAMPAIGN_COUNT}
313
+
314
+ Drift logged to: .marketing/DRIFT-LOG.md
315
+
316
+ Next steps:
317
+ - Run /ttm-fix [campaign-slug] to address specific FAIL results
318
+ - Run /ttm-positioning-shift if aggregate drift > 30% warrants a positioning change
319
+ ```
320
+
321
+ </process>
322
+
323
+ <success_criteria>
324
+ - [ ] All assets from campaigns within the time window evaluated against GATE-01's 3 checks
325
+ - [ ] Per-asset drift percentage calculated (WARN+FAIL / 3 * 100)
326
+ - [ ] Aggregate drift percentage calculated across all sampled assets
327
+ - [ ] Drift categorized by type (differentiator, proof point, must-not-say)
328
+ - [ ] Bleeding analysis classifies must-not-say violations by asset type (customer-facing vs non-customer-facing)
329
+ - [ ] Accepted deviations cross-referenced from campaign DEVIATIONS.md files
330
+ - [ ] Trend comparison shown if a prior audit exists in DRIFT-LOG.md
331
+ - [ ] Report displayed to stdout in the standard format
332
+ - [ ] Audit results appended to DRIFT-LOG.md via CLI
333
+ - [ ] Recommendations provided based on aggregate drift thresholds
334
+ </success_criteria>
335
+
336
+ <output>
337
+ - Audit report displayed to stdout (cross-campaign, no file written)
338
+ - `.marketing/DRIFT-LOG.md` updated with audit entry via CLI
339
+ </output>
@@ -0,0 +1,368 @@
1
+ <purpose>
2
+ Controlled positioning shift workflow for /ttm-positioning-shift. Requires explicit
3
+ reasoning for the change, collects new positioning fields, generates a migration plan
4
+ for active campaigns, sets deprecation schedule for shipped assets, presents a
5
+ before/after diff for mandatory human approval, and atomically updates POSITIONING.md
6
+ with History table archival. Logs all changes to .marketing/DRIFT-LOG.md.
7
+ </purpose>
8
+
9
+ <required_reading>
10
+ @${CLAUDE_PLUGIN_ROOT}/references/context-loading.md
11
+ @${CLAUDE_PLUGIN_ROOT}/templates/reference-files/positioning.md
12
+ @${CLAUDE_PLUGIN_ROOT}/templates/migration-plan.md
13
+ </required_reading>
14
+
15
+ <constraints>
16
+ ## This Workflow WRITES to POSITIONING.md
17
+
18
+ This is one of only two workflows authorized to modify `.marketing/POSITIONING.md`
19
+ (the other is `/ttm-init`). All writes are gated behind mandatory human approval
20
+ in Step 4. Never write to POSITIONING.md without explicit "Approve" from the user.
21
+ </constraints>
22
+
23
+ <process>
24
+
25
+ ## Text-Mode Detection
26
+
27
+ **Text mode (`--text` flag):** Set `TEXT_MODE=true` if `--text` is present in `$ARGUMENTS`
28
+ or if the runtime is not Claude Code. When TEXT_MODE is active, replace every
29
+ `AskUserQuestion` call with a plain-text numbered list.
30
+
31
+ Detection:
32
+ ```bash
33
+ if echo "$ARGUMENTS" | grep -q -- '--text'; then TEXT_MODE=true; fi
34
+ ```
35
+
36
+ If `AskUserQuestion` tool is not available in the current runtime, set `TEXT_MODE=true`.
37
+
38
+ When TEXT_MODE is active, replace each AskUserQuestion with a plain-text numbered list:
39
+ ```
40
+ [HEADER]
41
+ [QUESTION]
42
+ 1. [OPTION_1_LABEL] -- [OPTION_1_DESCRIPTION]
43
+ 2. [OPTION_2_LABEL] -- [OPTION_2_DESCRIPTION]
44
+ ...
45
+ Type the number of your choice:
46
+ ```
47
+
48
+ ---
49
+
50
+ ## Step 1: Load Context
51
+
52
+ ```
53
+ takeToMarket > LOADING CONTEXT
54
+ ```
55
+
56
+ **Load Tier 1 summaries** from all 9 reference files (lines 1 to `<!-- END_SUMMARY -->`):
57
+ - `.marketing/POSITIONING.md`
58
+ - `.marketing/BRAND.md`
59
+ - `.marketing/ICP.md`
60
+ - `.marketing/CHANNELS.md`
61
+ - `.marketing/STATE.md` (frontmatter only)
62
+ - `.marketing/CALENDAR.md`
63
+ - `.marketing/COMPETITORS.md`
64
+ - `.marketing/METRICS.md`
65
+ - `.marketing/LEARNINGS.md`
66
+
67
+ **Load Tier 2 (full content)** for before/after diff:
68
+ - `.marketing/POSITIONING.md` (full -- needed for field comparison and History table)
69
+
70
+ If `.marketing/POSITIONING.md` does not exist, error:
71
+ "POSITIONING.md not found. Run /ttm-init first to set up your marketing system."
72
+ Exit.
73
+
74
+ Parse the current POSITIONING.md into structured fields:
75
+ - `CURRENT_CATEGORY` -- from `**Category:**` line
76
+ - `CURRENT_DIFFERENTIATOR` -- from `**Primary differentiator:**` line
77
+ - `CURRENT_AUDIENCE` -- from `**Target audience:**` line
78
+ - `CURRENT_PROOF_POINTS` -- from `## Proof Point Library` table rows
79
+ - `CURRENT_MUST_NOT_SAY` -- from `## Must-Not-Say Terms` table rows
80
+ - `CURRENT_HISTORY` -- from `### Positioning History` table rows
81
+
82
+ ---
83
+
84
+ ## Step 2: Check for Active Campaigns (per D-08, D-09, D-10)
85
+
86
+ ```bash
87
+ ACTIVE_JSON=$(node "${CLAUDE_PLUGIN_ROOT}/bin/ttm-tools.cjs" campaign list --active --raw)
88
+ ACTIVE_COUNT=$(echo "$ACTIVE_JSON" | node -e "process.stdin.resume();let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>console.log(JSON.parse(d).count))")
89
+ ```
90
+
91
+ If ACTIVE_COUNT > 0:
92
+ Display warning:
93
+ ```
94
+ takeToMarket > ACTIVE CAMPAIGNS DETECTED
95
+
96
+ ${ACTIVE_COUNT} campaign(s) have active assets that may conflict with
97
+ a positioning change. A migration plan will be generated.
98
+
99
+ Campaigns: [list campaign slugs and phases from ACTIVE_JSON]
100
+ ```
101
+
102
+ If ACTIVE_COUNT == 0:
103
+ Display:
104
+ ```
105
+ takeToMarket > NO ACTIVE CAMPAIGNS
106
+
107
+ No active campaigns detected. Shift will apply to all future campaigns.
108
+ A migration plan is not required, but a deprecation schedule for
109
+ previously shipped assets may still be needed.
110
+ ```
111
+
112
+ ---
113
+
114
+ ## Step 3: Collect Shift Information (per D-06)
115
+
116
+ ### 3a: Reasoning
117
+
118
+ Using AskUserQuestion (text-mode fallback):
119
+ - header: "Positioning Shift Reasoning"
120
+ - question: "Why is this positioning change needed? Provide specific reasoning (market shift, customer feedback, competitive pressure, etc.)"
121
+ - type: free text
122
+
123
+ Record the reasoning as `SHIFT_REASONING`.
124
+
125
+ ### 3b: New Positioning Fields
126
+
127
+ Collect ALL structured positioning fields (matching POSITIONING.md template).
128
+ For each field, show the CURRENT value and ask for the NEW value.
129
+
130
+ **Field 1: Primary Differentiator**
131
+
132
+ Using AskUserQuestion (text-mode fallback):
133
+ - header: "Primary Differentiator"
134
+ - question: "Current: ${CURRENT_DIFFERENTIATOR}\n\nEnter the NEW primary differentiator phrase (or type 'keep' to keep current):"
135
+ - type: free text
136
+
137
+ Record as `NEW_DIFFERENTIATOR`. If "keep", use `CURRENT_DIFFERENTIATOR`.
138
+
139
+ **Field 2: Category**
140
+
141
+ Using AskUserQuestion (text-mode fallback):
142
+ - header: "Market Category"
143
+ - question: "Current: ${CURRENT_CATEGORY}\n\nEnter the NEW market category (or type 'keep' to keep current):"
144
+ - type: free text
145
+
146
+ Record as `NEW_CATEGORY`. If "keep", use `CURRENT_CATEGORY`.
147
+
148
+ **Field 3: Target Audience**
149
+
150
+ Using AskUserQuestion (text-mode fallback):
151
+ - header: "Target Audience"
152
+ - question: "Current: ${CURRENT_AUDIENCE}\n\nEnter the NEW target audience (or type 'keep' to keep current):"
153
+ - type: free text
154
+
155
+ Record as `NEW_AUDIENCE`. If "keep", use `CURRENT_AUDIENCE`.
156
+
157
+ **Field 4: Proof Points**
158
+
159
+ Display current proof points table. Ask:
160
+ - header: "Proof Points"
161
+ - question: "Current proof points shown above.\n\nProvide the NEW proof points as a numbered list. Each item: claim | source\n(or type 'keep' to keep current):"
162
+ - type: free text
163
+
164
+ Record as `NEW_PROOF_POINTS`. If "keep", use `CURRENT_PROOF_POINTS`.
165
+
166
+ **Field 5: Must-Not-Say Terms**
167
+
168
+ Display current must-not-say terms table. Ask:
169
+ - header: "Must-Not-Say Terms"
170
+ - question: "Current terms shown above.\n\nProvide the NEW must-not-say terms. Each item: term | reason\n(or type 'keep' to keep current):"
171
+ - type: free text
172
+
173
+ Record as `NEW_MUST_NOT_SAY`. If "keep", use `CURRENT_MUST_NOT_SAY`.
174
+
175
+ **Validate at least one field changed.** If ALL fields are "keep", display:
176
+ "No fields changed. Nothing to shift. Exiting."
177
+ Exit.
178
+
179
+ ### 3c: Migration Plan for Active Campaigns (per D-04, only if ACTIVE_COUNT > 0)
180
+
181
+ For each active campaign from `ACTIVE_JSON`:
182
+
183
+ 1. List all assets in `.marketing/CAMPAIGNS/<slug>/ASSETS/` or from MANIFEST.json
184
+ 2. Quick-evaluate each asset against the NEW positioning using GATE-01 3-check logic:
185
+ - Does the asset align with the NEW differentiator?
186
+ - Are claims backed by NEW proof points?
187
+ - Does the asset avoid NEW must-not-say terms?
188
+ 3. For each asset, recommend one of:
189
+ - **re-verify**: Asset may still pass under new positioning (minor drift)
190
+ - **re-produce**: Asset fundamentally conflicts with new positioning
191
+ - **accept-as-is**: Asset is channel/format where positioning is less critical
192
+
193
+ Present the migration plan per campaign using the `templates/migration-plan.md` format.
194
+
195
+ Ask user to confirm or override each recommendation:
196
+ Using AskUserQuestion (text-mode fallback):
197
+ - header: "Migration Plan Review"
198
+ - question: "Review the migration plan above. Do you accept these recommendations?"
199
+ - options:
200
+ - label: "Accept all" -- Keep all recommendations as-is
201
+ - label: "Override" -- Change specific recommendations (will prompt per asset)
202
+ - label: "Cancel" -- Abandon the shift entirely
203
+
204
+ **On "Override":** For each asset, ask user to select action (re-verify / re-produce / accept-as-is).
205
+ **On "Cancel":** Display "Positioning shift cancelled. No changes made." Exit.
206
+ **On "Accept all":** Continue.
207
+
208
+ ### 3d: Deprecation Schedule (per D-05)
209
+
210
+ Ask user to set deprecation timeline for shipped assets:
211
+ Using AskUserQuestion (text-mode fallback):
212
+ - header: "Deprecation Schedule"
213
+ - question: "Set a deadline for updating old-positioning assets (e.g., 90 days from now, or a specific date like 2025-06-01). Type 'skip' if no shipped assets need updating:"
214
+ - type: free text
215
+
216
+ If not "skip":
217
+ Record `DEPRECATION_DEADLINE`.
218
+
219
+ For each campaign with shipped assets (from campaign list):
220
+ - List shipped assets
221
+ - Record deprecation entry: asset, campaign, old positioning element, required update, deadline
222
+
223
+ ---
224
+
225
+ ## Step 4: Present Before/After Diff and Approval Gate (per D-06, D-07)
226
+
227
+ Build a summary of all changed fields. Only show fields that actually changed.
228
+
229
+ Display the complete change for review:
230
+
231
+ ```
232
+ takeToMarket > POSITIONING SHIFT APPROVAL
233
+
234
+ ## Current Positioning
235
+ **Category:** [CURRENT_CATEGORY]
236
+ **Primary Differentiator:** [CURRENT_DIFFERENTIATOR]
237
+ **Target Audience:** [CURRENT_AUDIENCE]
238
+ **Proof Points:** [current count] points
239
+ **Must-Not-Say:** [current count] terms
240
+
241
+ ## Proposed Positioning
242
+ **Category:** [NEW_CATEGORY]
243
+ **Primary Differentiator:** [NEW_DIFFERENTIATOR]
244
+ **Target Audience:** [NEW_AUDIENCE]
245
+ **Proof Points:** [new count] points
246
+ **Must-Not-Say:** [new count] terms
247
+
248
+ ## What Changed
249
+ [field-by-field diff showing only changed fields]
250
+ [For each changed field: "- [FIELD]: [old value] -> [new value]"]
251
+
252
+ ## Reasoning
253
+ [SHIFT_REASONING]
254
+
255
+ ## Impact
256
+ - Active campaigns affected: [ACTIVE_COUNT]
257
+ - Migration actions needed: [count of re-verify + re-produce actions]
258
+ - Deprecation items: [count]
259
+ - Deprecation deadline: [DEPRECATION_DEADLINE or "N/A"]
260
+ ```
261
+
262
+ Using AskUserQuestion (text-mode fallback):
263
+ - header: "Approve Positioning Shift"
264
+ - question: "Review the changes above. This will update POSITIONING.md and affect all future campaigns."
265
+ - options:
266
+ - label: "Approve" -- Apply the new positioning
267
+ - label: "Revise" -- Go back and modify the proposed positioning
268
+ - label: "Cancel" -- Abandon the shift entirely
269
+
270
+ **On "Revise":** Loop back to Step 3b to re-collect fields.
271
+ **On "Cancel":** Display "Positioning shift cancelled. No changes made." Exit.
272
+ **On "Approve":** Proceed to Step 5.
273
+
274
+ ---
275
+
276
+ ## Step 5: Apply Changes (per D-07)
277
+
278
+ ### 5a: Archive Old Positioning in History Table
279
+
280
+ Read current POSITIONING.md. Find the `### Positioning History` table.
281
+ Append a new row:
282
+ ```
283
+ | [ISO date] | [summary of what changed] | [user's reasoning, sanitized to 100 chars] |
284
+ ```
285
+
286
+ **Sanitization (per T-06-09, Pitfall 3):** Strip pipes (`|`), backticks, newlines from the
287
+ reasoning text. Replace with spaces. Limit to 100 characters. This prevents Markdown table
288
+ delimiter breakage.
289
+
290
+ ### 5b: Update POSITIONING.md Fields
291
+
292
+ Update the `<!-- _SUMMARY -->` block with new Category, Primary Differentiator, Target Audience.
293
+ Update the `## Proof Point Library` table with new proof points.
294
+ Update the `## Must-Not-Say Terms` table with new terms.
295
+
296
+ **CRITICAL:** Preserve the `<!-- _SUMMARY -->` and `<!-- END_SUMMARY -->` delimiters exactly
297
+ as they are. All other workflows depend on these markers for Tier 1 context loading.
298
+
299
+ Write the updated POSITIONING.md atomically via the Write tool.
300
+
301
+ ### 5c: Log Shift to DRIFT-LOG.md (per T-06-10)
302
+
303
+ ```bash
304
+ CHANGED_FIELDS="[list of field names that changed, e.g., differentiator, category]"
305
+ SANITIZED_REASONING=$(echo "${SHIFT_REASONING}" | head -c 100 | tr '|`\n' ' ')
306
+
307
+ node "${CLAUDE_PLUGIN_ROOT}/bin/ttm-tools.cjs" drift-log append \
308
+ --event-type shift \
309
+ --source "/ttm-positioning-shift" \
310
+ --details "Changed: ${CHANGED_FIELDS}. Reasoning: ${SANITIZED_REASONING}" \
311
+ --affected ${ACTIVE_COUNT}
312
+ ```
313
+
314
+ ### 5d: Log Deprecation Entries
315
+
316
+ For each deprecation item collected in Step 3d:
317
+ ```bash
318
+ node "${CLAUDE_PLUGIN_ROOT}/bin/ttm-tools.cjs" drift-log deprecation \
319
+ --asset "[asset name]" \
320
+ --campaign "[campaign slug]" \
321
+ --old-element "[changed positioning element]" \
322
+ --required-update "[what needs updating]" \
323
+ --deadline "[ISO date]"
324
+ ```
325
+
326
+ If no deprecation items were collected (user typed "skip" in 3d), skip this step.
327
+
328
+ ---
329
+
330
+ ## Step 6: Completion Banner
331
+
332
+ ```
333
+ takeToMarket > POSITIONING SHIFT COMPLETE
334
+
335
+ Old positioning archived in POSITIONING.md History table.
336
+ New positioning is now active for all future campaigns.
337
+
338
+ Changes logged: .marketing/DRIFT-LOG.md
339
+ Deprecation items: [count] (deadline: [DEPRECATION_DEADLINE or "N/A"])
340
+ Active campaigns: [ACTIVE_COUNT] -- review migration plan above
341
+
342
+ Next steps:
343
+ [If active campaigns]: Re-run /ttm-verify <slug> for campaigns marked "re-verify"
344
+ [If deprecation items]: Update shipped assets before [DEPRECATION_DEADLINE]
345
+ [Always]: Run /ttm-positioning-check periodically to monitor drift
346
+ ```
347
+
348
+ </process>
349
+
350
+ <success_criteria>
351
+ - [ ] User provided explicit reasoning for the positioning change
352
+ - [ ] All 5 structured positioning fields collected (differentiator, category, audience, proof points, must-not-say)
353
+ - [ ] Active campaigns detected and migration plan generated (if any exist)
354
+ - [ ] Deprecation schedule set for shipped assets (if any exist)
355
+ - [ ] Before/after diff presented showing all changed fields
356
+ - [ ] Human approval gate passed (Approve/Revise/Cancel with Approve required)
357
+ - [ ] Old positioning archived in POSITIONING.md History table before update
358
+ - [ ] History table entry sanitized (no pipes, backticks, newlines; max 100 chars)
359
+ - [ ] POSITIONING.md _SUMMARY and END_SUMMARY delimiters preserved
360
+ - [ ] Shift event appended to DRIFT-LOG.md via CLI
361
+ - [ ] Deprecation entries appended to DRIFT-LOG.md via CLI
362
+ - [ ] Completion banner displayed with next steps
363
+ </success_criteria>
364
+
365
+ <output>
366
+ - `.marketing/POSITIONING.md` (updated with new positioning and History table entry)
367
+ - `.marketing/DRIFT-LOG.md` (shift event appended + deprecation entries)
368
+ </output>
File without changes