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,521 @@
1
+ <purpose>
2
+ Ship workflow for /ttm-ship. Generates a dynamic launch checklist per campaign
3
+ based on channel mix and asset types (D-09). AI auto-checks verifiable items,
4
+ presents results with checkboxes for human confirmation (D-10). Per-asset ship
5
+ status allows staggered launches (D-11). Only ship-ready assets can ship.
6
+ </purpose>
7
+
8
+ <required_reading>
9
+ @${CLAUDE_PLUGIN_ROOT}/references/context-loading.md
10
+ @${CLAUDE_PLUGIN_ROOT}/references/ship-checklist-items.md
11
+ </required_reading>
12
+
13
+ <constraints>
14
+ ## POSITIONING.md is READ-ONLY
15
+
16
+ **Do NOT modify `.marketing/POSITIONING.md` during this workflow.**
17
+
18
+ POSITIONING.md is an architectural invariant. If you detect positioning drift:
19
+ - In verify: use the Escalate option to launch /ttm-positioning-shift
20
+ - In other workflows: flag the issue and recommend running /ttm-positioning-check
21
+
22
+ Only /ttm-positioning-shift and /ttm-init may modify POSITIONING.md.
23
+ </constraints>
24
+
25
+ <process>
26
+
27
+ ## Text-Mode Detection
28
+
29
+ **Text mode (`--text` flag):** Set `TEXT_MODE=true` if `--text` is present in `$ARGUMENTS`
30
+ or if the runtime is not Claude Code. When TEXT_MODE is active, replace every
31
+ `AskUserQuestion` call with a plain-text numbered list.
32
+
33
+ Detection:
34
+ ```bash
35
+ if echo "$ARGUMENTS" | grep -q -- '--text'; then TEXT_MODE=true; fi
36
+ ```
37
+
38
+ If `AskUserQuestion` tool is not available in the current runtime, set `TEXT_MODE=true`.
39
+
40
+ When TEXT_MODE is active, replace each AskUserQuestion with a plain-text numbered list:
41
+ ```
42
+ [HEADER]
43
+ [QUESTION]
44
+ 1. [OPTION_1_LABEL] -- [OPTION_1_DESCRIPTION]
45
+ 2. [OPTION_2_LABEL] -- [OPTION_2_DESCRIPTION]
46
+ ...
47
+ Type the number of your choice:
48
+ ```
49
+
50
+ ---
51
+
52
+ ## Step 1: Load Context
53
+
54
+ ```
55
+ takeToMarket > LOADING CONTEXT
56
+ ```
57
+
58
+ Extract SLUG from $ARGUMENTS (strip `--text` flag if present):
59
+ ```bash
60
+ SLUG=$(echo "$ARGUMENTS" | sed 's/--text//g' | xargs)
61
+ ```
62
+
63
+ If SLUG is empty, error: "Usage: /ttm-ship [campaign-slug]. Provide a campaign slug." Exit.
64
+
65
+ **Load Tier 1 summaries** from all 9 reference files (lines 1 to `<!-- END_SUMMARY -->`):
66
+ - `.marketing/POSITIONING.md`
67
+ - `.marketing/BRAND.md`
68
+ - `.marketing/ICP.md`
69
+ - `.marketing/CHANNELS.md`
70
+ - `.marketing/STATE.md` (frontmatter only)
71
+ - `.marketing/CALENDAR.md`
72
+ - `.marketing/COMPETITORS.md`
73
+ - `.marketing/METRICS.md`
74
+ - `.marketing/LEARNINGS.md`
75
+
76
+ **Load Tier 2 (full content)** for ship checklist generation:
77
+ - `.marketing/CHANNELS.md` (needed for UTM schema and channel-specific details)
78
+
79
+ **Load campaign-specific files** (always full-load per context-loading.md rule 4):
80
+ - `.marketing/CAMPAIGNS/${SLUG}/STATE.md`
81
+ - `.marketing/CAMPAIGNS/${SLUG}/BRIEF.md`
82
+
83
+ **Load MANIFEST.json:**
84
+ ```bash
85
+ MANIFEST_PATH=".marketing/CAMPAIGNS/${SLUG}/MANIFEST.json"
86
+ ```
87
+
88
+ Read `.marketing/CAMPAIGNS/${SLUG}/MANIFEST.json`. If the file does not exist, error:
89
+ "No production manifest found for campaign '${SLUG}'. Run /ttm-produce first."
90
+ Exit.
91
+
92
+ **Load VERIFICATION.md:**
93
+ Read `.marketing/CAMPAIGNS/${SLUG}/VERIFICATION.md`. If the file does not exist, error:
94
+ "No verification report found for campaign '${SLUG}'. Run /ttm-verify first."
95
+ Exit.
96
+
97
+ ---
98
+
99
+ ## Step 2: Validate Campaign State
100
+
101
+ ```
102
+ takeToMarket > VALIDATING CAMPAIGN
103
+ ```
104
+
105
+ Check campaign exists:
106
+ ```bash
107
+ node "${CLAUDE_PLUGIN_ROOT}/bin/ttm-tools.cjs" campaign state "${SLUG}" --raw
108
+ ```
109
+
110
+ If result shows `exists: false`: Tell the user the campaign does not exist and suggest
111
+ running `/ttm-new-campaign` first. Exit.
112
+
113
+ **Check review completion:**
114
+ Read `review.overall_result` from campaign state.
115
+
116
+ - If `review.overall_result` is null: "Campaign has not been reviewed. Run /ttm-review first." Exit.
117
+ - If `review.overall_result` is `needs-fix` or `mixed`:
118
+ Read `fix.overall_result` from campaign state.
119
+ If `fix.overall_result` is null:
120
+ Warn: "Some assets need fixing. Run /ttm-fix first, or proceed to ship only approved assets?"
121
+ Using AskUserQuestion (or text-mode numbered list):
122
+ ```
123
+ Some assets have not been fixed yet.
124
+ 1. Proceed -- ship only approved/ship-ready assets
125
+ 2. Fix first -- exit and run /ttm-fix
126
+ ```
127
+ If "Fix first": exit workflow.
128
+
129
+ ---
130
+
131
+ ## Step 3: Identify Ship-Ready Assets
132
+
133
+ ```
134
+ takeToMarket > CHECKING SHIP READINESS
135
+ ```
136
+
137
+ Parse MANIFEST.json. Collect hero and all derivative assets. For each asset,
138
+ read its `review_status` and `ship_status` fields. Categorize:
139
+
140
+ - **Ship-ready:** `review_status` is `"approved"` or `"ship-ready"` AND `ship_status` is NOT `"shipped"`
141
+ - **Not ready:** `review_status` is `"needs-fix"` or `"needs-human-fix"` -- display warning
142
+ - **Already shipped:** `ship_status` is `"shipped"` -- skip
143
+ - **Rejected:** `review_status` is `"rejected"` -- excluded, already final
144
+
145
+ If no assets are eligible for shipping:
146
+ "No ship-ready assets found. All assets are either awaiting fix, rejected, or already shipped."
147
+ Exit.
148
+
149
+ Display ship readiness summary:
150
+ ```
151
+ takeToMarket > SHIP READINESS
152
+
153
+ Ship-ready assets: ${COUNT}
154
+ ${FOR EACH SHIP-READY ASSET:}
155
+ - ${ASSET_NAME} (${ASSET_TYPE}, ${CHANNEL})
156
+ ${END FOR}
157
+
158
+ ${IF ANY NOT READY:}
159
+ Not ready (excluded from this ship run):
160
+ ${FOR EACH NOT-READY ASSET:}
161
+ - ${ASSET_NAME}: ${STATUS} -- ${REASON}
162
+ ${END FOR}
163
+
164
+ ${IF ANY ALREADY SHIPPED:}
165
+ Already shipped:
166
+ ${FOR EACH SHIPPED ASSET:}
167
+ - ${ASSET_NAME} (shipped at ${SHIPPED_AT})
168
+ ${END FOR}
169
+ ```
170
+
171
+ ---
172
+
173
+ ## Step 4: Generate Dynamic Checklist (D-09)
174
+
175
+ Read `${CLAUDE_PLUGIN_ROOT}/references/ship-checklist-items.md` for the checklist
176
+ item definitions.
177
+
178
+ From BRIEF.md, identify the campaign's channel mix. From the ship-ready asset list,
179
+ identify the unique asset types present (e.g., `blog-post`, `email`, `linkedin-post`,
180
+ `social-post`, `twitter-post`, `landing-page`, `video`, `youtube-video`, `paid-ad`).
181
+
182
+ Build the checklist by combining:
183
+
184
+ 1. **Universal section** -- always included for all campaigns. Load items from the
185
+ "Universal (all campaigns)" section of ship-checklist-items.md.
186
+
187
+ 2. **Channel-specific sections** -- for each unique asset type in the ship-ready list:
188
+ - `blog-post` -> load "Blog / SEO" section
189
+ - `email` -> load "Email" section
190
+ - `linkedin-post` -> load "LinkedIn" section
191
+ - `social-post` or `twitter-post` -> load "Social / Twitter/X" section
192
+ - `landing-page` -> load "Landing Page" section
193
+ - `video` or `youtube-video` -> load "Video / YouTube" section
194
+ - `paid-ad` -> load "Paid Ads" section
195
+ - Any unmatched type -> load "Default" section
196
+
197
+ Only include sections that match asset types in the ship-ready list. Do NOT include
198
+ sections for asset types that are not present -- the checklist must be relevant, not
199
+ exhaustive (D-09).
200
+
201
+ Store the assembled checklist as a structured list:
202
+ ```
203
+ CHECKLIST = [
204
+ { section: "Universal", items: [
205
+ { name: "UTM parameters valid...", tag: "AI", result: null },
206
+ { name: "Tracking/analytics configured...", tag: "HUMAN", result: null },
207
+ ...
208
+ ]},
209
+ { section: "Blog / SEO", items: [...] },
210
+ ...
211
+ ]
212
+ ```
213
+
214
+ ---
215
+
216
+ ## Step 5: Run AI Auto-Checks (D-10)
217
+
218
+ For each `[AI]`-tagged checklist item, attempt automated verification by reading
219
+ the ship-ready asset files and campaign data.
220
+
221
+ ### Universal AI Checks
222
+
223
+ **UTM parameter validity:**
224
+ Scan each ship-ready asset file for URLs containing `utm_` parameters.
225
+ - Check format: `utm_source`, `utm_medium`, `utm_campaign` must all be present in each
226
+ tracked URL.
227
+ - Cross-reference against `.marketing/CHANNELS.md` UTM schema if available.
228
+ - Result: PASS (valid UTMs found on all trackable links), WARN (no trackable links found
229
+ in assets -- may be expected for some asset types), FAIL (malformed UTMs -- missing
230
+ required parameters or inconsistent naming).
231
+
232
+ **Draft marker detection:**
233
+ Scan each ship-ready asset file for strings: `TODO`, `PLACEHOLDER`, `TBD`, `DRAFT`,
234
+ `[INSERT`, `XXX`.
235
+ - Result: PASS (none found across all assets), FAIL (markers found -- list file and
236
+ location for each).
237
+
238
+ **Verification status:**
239
+ Read VERIFICATION.md frontmatter `overall_result`.
240
+ - Result: PASS if `pass` or `accepted`, FAIL if `fail` or `warn` without acceptance.
241
+
242
+ **Review status:**
243
+ Check MANIFEST.json -- verify all ship-ready assets have `review_status` of `approved`
244
+ or `ship-ready`.
245
+ - Result: PASS (all ship-ready assets confirmed), FAIL (any asset has unexpected status).
246
+
247
+ ### Channel-Specific AI Checks
248
+
249
+ For each channel-specific section in the assembled checklist, run the applicable AI
250
+ checks against the corresponding asset files:
251
+
252
+ **Blog / SEO:**
253
+ - Meta title: Check for first H1 or frontmatter `title` field. PASS if found.
254
+ - Meta description: Check for frontmatter `description` field or first paragraph under
255
+ 160 chars. PASS if present, WARN if over 160 chars.
256
+ - H1 with keyword: Check that first H1 contains primary keyword from BRIEF.md or
257
+ positioning anchor from POSITIONING.md summary. PASS/WARN.
258
+ - Orphaned links: Scan for markdown links `[text](url)` -- flag any with empty or
259
+ clearly broken targets. PASS/WARN.
260
+
261
+ **Email:**
262
+ - Subject line length: Read frontmatter `subject` field, check length < 60 chars.
263
+ PASS/FAIL.
264
+ - Preview text length: Read frontmatter `preview` or `preview_text` field, check < 90
265
+ chars. PASS/WARN.
266
+ - Unsubscribe: Scan for string "unsubscribe" (case-insensitive). PASS/FAIL.
267
+ - Physical address: Scan for a postal/mailing address pattern. PASS/WARN.
268
+ - Spam trigger words: Check subject for common spam triggers (FREE, URGENT, ACT NOW,
269
+ LIMITED TIME, GUARANTEED). PASS/WARN.
270
+
271
+ **LinkedIn:**
272
+ - Post length: Count characters. PASS if under 3000, FAIL if over.
273
+ - Opening line: Check if first non-empty line starts with "I". WARN if yes.
274
+ - External URL in first line: Check if first line contains http(s) URL. WARN if yes.
275
+
276
+ **Social / Twitter/X:**
277
+ - Character count: Count total post characters. PASS if under 280 (Twitter/X) or
278
+ platform-appropriate limit, FAIL if over.
279
+ - Rhetorical questions: Scan for question marks in sentences that start with "Why",
280
+ "How", "What if", "Have you". WARN if found.
281
+ - Hashtag count: Count `#` tags. PASS if 0-3, WARN if more.
282
+
283
+ **Landing Page:**
284
+ - CTA presence: Scan for `[CTA]`, button-like markup (`<button`, `[Button]`), or
285
+ strong action verbs (Get, Start, Join, Try, Download, Request, Schedule). PASS/FAIL.
286
+ - Form fields: Check for form-like content matching brief's conversion goal. PASS/WARN.
287
+ - UTM capture: Check for form fields or hidden inputs referencing UTM parameters.
288
+ PASS/WARN.
289
+
290
+ **Video / YouTube:**
291
+ - Title length: Check frontmatter `title` field < 60 chars. PASS/FAIL.
292
+ - Description keyword: Check that description's first 2 lines contain primary keyword.
293
+ PASS/WARN.
294
+ - Timestamps: If content references a video longer than 5 minutes, check for
295
+ timestamp markers. PASS/WARN/N/A.
296
+
297
+ **Paid Ads:**
298
+ - Character limits: Check headline and description against platform limits. PASS/FAIL.
299
+ - Headline and description: Verify both are present. PASS/FAIL.
300
+ - Display URL: Check for a formatted display URL. PASS/WARN.
301
+
302
+ For each AI check, record:
303
+ ```
304
+ { item_name, result: "PASS"|"WARN"|"FAIL", detail: "what was found or why it failed" }
305
+ ```
306
+
307
+ ---
308
+
309
+ ## Step 6: Present Checklist with Results (D-10)
310
+
311
+ Display the complete checklist organized by section. For each item:
312
+ - `[AI]` items: Show result (PASS/WARN/FAIL) with detail
313
+ - `[HUMAN]` items: Show as unchecked checkbox for user to confirm
314
+
315
+ ```
316
+ takeToMarket > LAUNCH CHECKLIST: ${SLUG}
317
+
318
+ ## Universal Checks
319
+ - [PASS] UTM parameters valid on all trackable links
320
+ - [PASS] All asset files finalized (no draft markers)
321
+ - [PASS] VERIFICATION.md shows pass/accepted
322
+ - [PASS] All ship-ready assets have approved review status
323
+ - [ ] Tracking/analytics configured for outcome metric -- CONFIRM? (yes/no)
324
+ - [ ] Monitoring and alerts set up -- CONFIRM? (yes/no)
325
+ - [ ] Team notified of launch timeline -- CONFIRM? (yes/no)
326
+
327
+ ${IF BLOG/SEO SECTION:}
328
+ ## Blog / SEO Checks
329
+ - [PASS] Meta title present
330
+ - [WARN] Meta description: 180 chars (recommend under 160)
331
+ - [ ] Schema markup deployed -- CONFIRM? (yes/no)
332
+ - [ ] Internal links added -- CONFIRM? (yes/no)
333
+ ...
334
+ ${END IF}
335
+
336
+ ${OTHER CHANNEL SECTIONS AS APPLICABLE}
337
+ ```
338
+
339
+ ### Collect Human Confirmations
340
+
341
+ For each `[HUMAN]` item, use AskUserQuestion (or text-mode) to collect confirmation:
342
+
343
+ ```
344
+ Confirm: [CHECKLIST_ITEM]
345
+ 1. Yes -- confirmed
346
+ 2. No -- not ready yet
347
+ 3. N/A -- not applicable to this campaign
348
+ ```
349
+
350
+ Track which items are confirmed (yes), not ready (no), or not applicable (N/A).
351
+
352
+ **IMPORTANT:** Group human confirmations by section to reduce interaction fatigue.
353
+ Present all [HUMAN] items in a section together:
354
+
355
+ ```
356
+ Universal human checks:
357
+ 1. Tracking/analytics configured for outcome metric?
358
+ 2. Monitoring and alerts set up?
359
+ 3. Team notified of launch timeline?
360
+
361
+ For each item above, type: yes / no / n/a
362
+ (Example: yes, yes, n/a)
363
+ ```
364
+
365
+ ---
366
+
367
+ ## Step 7: Determine Ship Decision
368
+
369
+ After all items processed:
370
+
371
+ **All clear:** If all [AI] checks PASS (or WARN) and all [HUMAN] items confirmed
372
+ (yes or N/A):
373
+ ```
374
+ takeToMarket > ALL CLEAR TO SHIP
375
+
376
+ All checklist items passed or confirmed. Ready to proceed with shipping.
377
+ ```
378
+
379
+ **Blockers found:** If any [AI] checks FAIL or any [HUMAN] items answered "no":
380
+ ```
381
+ Blockers preventing ship:
382
+ ${FOR EACH BLOCKER:}
383
+ - ${ITEM_NAME}: ${REASON}
384
+ ${END FOR}
385
+
386
+ Resolve these items and re-run /ttm-ship ${SLUG}
387
+ ```
388
+
389
+ Ask user using AskUserQuestion (or text-mode numbered list):
390
+ ```
391
+ Ship decision:
392
+ 1. Ship anyway -- proceed with documented exceptions
393
+ 2. Resolve first -- exit and fix blockers
394
+ ```
395
+
396
+ If "Ship anyway": proceed to Step 8. Record all blockers as exceptions.
397
+ If "Resolve first": exit workflow.
398
+
399
+ ---
400
+
401
+ ## Step 8: Update Per-Asset Ship Status (D-11)
402
+
403
+ For each ship-ready asset being shipped:
404
+
405
+ Read MANIFEST.json. Update each shipped asset entry:
406
+ - Set `ship_status: "shipped"`
407
+ - Set `shipped_at: "[ISO_TIMESTAMP]"` (current timestamp)
408
+
409
+ ```bash
410
+ TIMESTAMP=$(node "${CLAUDE_PLUGIN_ROOT}/bin/ttm-tools.cjs" timestamp --raw)
411
+ ```
412
+
413
+ Assets NOT being shipped (not ready, user deferred) retain their current status.
414
+
415
+ Write updated MANIFEST.json back to disk.
416
+
417
+ ---
418
+
419
+ ## Step 9: Update Campaign State
420
+
421
+ Determine ship status:
422
+ - `shipped` -- all ship-ready assets shipped (none deferred or blocked)
423
+ - `partial` -- some assets shipped, others still pending
424
+
425
+ ```bash
426
+ TIMESTAMP=$(node "${CLAUDE_PLUGIN_ROOT}/bin/ttm-tools.cjs" timestamp --raw)
427
+ node "${CLAUDE_PLUGIN_ROOT}/bin/ttm-tools.cjs" campaign update "${SLUG}" ship.status "[shipped|partial]"
428
+ node "${CLAUDE_PLUGIN_ROOT}/bin/ttm-tools.cjs" campaign update "${SLUG}" ship.shipped_at "$TIMESTAMP"
429
+ node "${CLAUDE_PLUGIN_ROOT}/bin/ttm-tools.cjs" campaign update "${SLUG}" ship.checklist_result "[all-clear|exceptions]"
430
+ ```
431
+
432
+ **ship.status logic:**
433
+ - `shipped` -- all ship-ready assets shipped
434
+ - `partial` -- some assets shipped, others deferred or blocked
435
+
436
+ **ship.checklist_result logic:**
437
+ - `all-clear` -- all AI checks passed and all human items confirmed
438
+ - `exceptions` -- shipped with documented blockers/warnings
439
+
440
+ Only update campaign phase to "shipped" if at least one asset was shipped:
441
+ ```bash
442
+ node "${CLAUDE_PLUGIN_ROOT}/bin/ttm-tools.cjs" campaign update "${SLUG}" phase shipped
443
+ node "${CLAUDE_PLUGIN_ROOT}/bin/ttm-tools.cjs" campaign update "${SLUG}" phase.shipped "$TIMESTAMP"
444
+ ```
445
+
446
+ ---
447
+
448
+ ## Step 10: Display Completion
449
+
450
+ ```
451
+ takeToMarket > SHIP COMPLETE
452
+
453
+ Date: ${ISO_DATE}
454
+ Assets shipped: ${SHIPPED_COUNT}/${TOTAL_SHIP_READY}
455
+
456
+ Shipped:
457
+ ${FOR EACH SHIPPED ASSET:}
458
+ - ${ASSET_NAME} (shipped at ${TIMESTAMP})
459
+ ${END FOR}
460
+
461
+ ${IF PARTIAL:}
462
+ Deferred (not shipped yet):
463
+ ${FOR EACH DEFERRED ASSET:}
464
+ - ${ASSET_NAME}: ${REASON}
465
+ ${END FOR}
466
+
467
+ ${IF EXCEPTIONS:}
468
+ Shipped with exceptions:
469
+ ${FOR EACH EXCEPTION:}
470
+ - ${EXCEPTION_ITEM}: ${JUSTIFICATION}
471
+ ${END FOR}
472
+
473
+ Checklist result: ${CHECKLIST_RESULT}
474
+
475
+ Next: Run /ttm-measure ${SLUG} when measurement window begins
476
+ (or /ttm-ship ${SLUG} again to ship deferred assets)
477
+ ```
478
+
479
+ ---
480
+
481
+ ## Step 11: Positioning Check Auto-Suggest (D-02)
482
+
483
+ Check if a positioning audit is recommended:
484
+ ```bash
485
+ SHIPPED_JSON=$(node "${CLAUDE_PLUGIN_ROOT}/bin/ttm-tools.cjs" campaign list --shipped-since-last-audit --raw)
486
+ SHIPPED_COUNT=$(echo "$SHIPPED_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))")
487
+ ```
488
+
489
+ If SHIPPED_COUNT >= 3, display:
490
+
491
+ ```
492
+ takeToMarket > POSITIONING CHECK SUGGESTED
493
+
494
+ ${SHIPPED_COUNT} campaigns have shipped since your last positioning audit.
495
+ Consider running /ttm-positioning-check to verify positioning consistency
496
+ across recent assets.
497
+
498
+ This is a suggestion, not a requirement. Run it when convenient.
499
+ ```
500
+
501
+ If SHIPPED_COUNT < 3, do not display anything.
502
+
503
+ </process>
504
+
505
+ <success_criteria>
506
+ - [ ] Campaign state validated (exists, has been reviewed)
507
+ - [ ] Ship-ready assets identified from MANIFEST.json review_status
508
+ - [ ] Dynamic checklist generated from campaign channel mix (D-09)
509
+ - [ ] AI auto-checks run for all [AI]-tagged items (UTM, draft markers, verification, review status)
510
+ - [ ] Channel-specific AI checks run for applicable asset types
511
+ - [ ] Human confirmation collected for all [HUMAN]-tagged items (D-10)
512
+ - [ ] Ship decision made (all clear or ship with exceptions)
513
+ - [ ] Per-asset ship_status and shipped_at updated in MANIFEST.json (D-11)
514
+ - [ ] Campaign state updated: ship.status, ship.shipped_at, ship.checklist_result
515
+ - [ ] Campaign phase advanced to "shipped" (if at least one asset shipped)
516
+ - [ ] User directed to /ttm-measure as next step
517
+ </success_criteria>
518
+
519
+ <output>
520
+ - `.marketing/CAMPAIGNS/${SLUG}/MANIFEST.json` (updated with ship_status and shipped_at per asset)
521
+ </output>