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.
- package/.claude-plugin/plugin.json +10 -0
- package/LICENSE +21 -0
- package/README.md +419 -0
- package/agents/ttm-producer.md +53 -0
- package/bin/lib/campaign.cjs +553 -0
- package/bin/lib/commit.cjs +105 -0
- package/bin/lib/core.cjs +172 -0
- package/bin/lib/deviation.cjs +149 -0
- package/bin/lib/drift-log.cjs +219 -0
- package/bin/lib/health.cjs +438 -0
- package/bin/lib/slug.cjs +59 -0
- package/bin/lib/state.cjs +96 -0
- package/bin/ttm-tools.cjs +157 -0
- package/gates/base-gates.md +266 -0
- package/gates/discipline/.gitkeep +0 -0
- package/gates/gate-evaluation.md +341 -0
- package/gates/meta-gates.md +19 -0
- package/install.js +307 -0
- package/package.json +53 -0
- package/playbooks/.gitkeep +0 -0
- package/playbooks/aeo.md +223 -0
- package/playbooks/affiliate.md +272 -0
- package/playbooks/base.md +110 -0
- package/playbooks/email.md +306 -0
- package/playbooks/events.md +320 -0
- package/playbooks/linkedin.md +263 -0
- package/playbooks/paid-ads.md +318 -0
- package/playbooks/pr-media.md +296 -0
- package/playbooks/seo.md +284 -0
- package/playbooks/social.md +305 -0
- package/playbooks/youtube.md +325 -0
- package/references/context-loading.md +107 -0
- package/references/learnings-extraction.md +94 -0
- package/references/measurement-template.md +48 -0
- package/references/meta-gate-evaluation.md +169 -0
- package/references/positioning-check-report.md +197 -0
- package/references/review-checklist.md +78 -0
- package/references/ship-checklist-items.md +94 -0
- package/settings.json +4 -0
- package/skills/ttm-aeo-check/SKILL.md +20 -0
- package/skills/ttm-affiliate-kit/SKILL.md +19 -0
- package/skills/ttm-archive/SKILL.md +13 -0
- package/skills/ttm-brand-refresh/SKILL.md +19 -0
- package/skills/ttm-brief/SKILL.md +14 -0
- package/skills/ttm-competitor-scan/SKILL.md +19 -0
- package/skills/ttm-email-preflight/SKILL.md +19 -0
- package/skills/ttm-fix/SKILL.md +13 -0
- package/skills/ttm-health/SKILL.md +12 -0
- package/skills/ttm-icp-refresh/SKILL.md +19 -0
- package/skills/ttm-init/SKILL.md +12 -0
- package/skills/ttm-keyword-map/SKILL.md +19 -0
- package/skills/ttm-learn/SKILL.md +14 -0
- package/skills/ttm-measure/SKILL.md +14 -0
- package/skills/ttm-new-campaign/SKILL.md +13 -0
- package/skills/ttm-next/SKILL.md +12 -0
- package/skills/ttm-positioning-check/SKILL.md +19 -0
- package/skills/ttm-positioning-shift/SKILL.md +19 -0
- package/skills/ttm-produce/SKILL.md +14 -0
- package/skills/ttm-repurpose/SKILL.md +20 -0
- package/skills/ttm-research/SKILL.md +13 -0
- package/skills/ttm-resume/SKILL.md +13 -0
- package/skills/ttm-review/SKILL.md +13 -0
- package/skills/ttm-seo-audit/SKILL.md +20 -0
- package/skills/ttm-ship/SKILL.md +13 -0
- package/skills/ttm-state/SKILL.md +13 -0
- package/skills/ttm-verify/SKILL.md +14 -0
- package/templates/agents-md.md +65 -0
- package/templates/campaign-brief.md +74 -0
- package/templates/campaign-research.md +39 -0
- package/templates/campaign-state.md +40 -0
- package/templates/claude-md.md +65 -0
- package/templates/deviation-log.md +12 -0
- package/templates/drift-log.md +17 -0
- package/templates/fix-brief.md +59 -0
- package/templates/fix-log.md +22 -0
- package/templates/measurement-report.md +75 -0
- package/templates/migration-plan.md +24 -0
- package/templates/production-manifest.json +20 -0
- package/templates/reference-files/brand.md +45 -0
- package/templates/reference-files/calendar.md +30 -0
- package/templates/reference-files/channels.md +40 -0
- package/templates/reference-files/competitors.md +40 -0
- package/templates/reference-files/icp.md +50 -0
- package/templates/reference-files/learnings.md +40 -0
- package/templates/reference-files/metrics.md +42 -0
- package/templates/reference-files/positioning.md +38 -0
- package/templates/reference-files/state.md +27 -0
- package/templates/verification-report.md +59 -0
- package/workflows/discipline/.gitkeep +0 -0
- package/workflows/discipline/aeo-check.md +180 -0
- package/workflows/discipline/affiliate-kit.md +147 -0
- package/workflows/discipline/email-preflight.md +150 -0
- package/workflows/discipline/keyword-map.md +125 -0
- package/workflows/discipline/repurpose.md +329 -0
- package/workflows/discipline/seo-audit.md +169 -0
- package/workflows/lifecycle/.gitkeep +0 -0
- package/workflows/lifecycle/brief-positioning-check.md +90 -0
- package/workflows/lifecycle/brief.md +355 -0
- package/workflows/lifecycle/fix.md +495 -0
- package/workflows/lifecycle/learn.md +405 -0
- package/workflows/lifecycle/measure.md +379 -0
- package/workflows/lifecycle/produce.md +383 -0
- package/workflows/lifecycle/research.md +264 -0
- package/workflows/lifecycle/review.md +432 -0
- package/workflows/lifecycle/ship.md +521 -0
- package/workflows/lifecycle/verify.md +507 -0
- package/workflows/reference-mgmt/.gitkeep +0 -0
- package/workflows/reference-mgmt/brand-refresh.md +193 -0
- package/workflows/reference-mgmt/competitor-scan.md +228 -0
- package/workflows/reference-mgmt/icp-refresh.md +200 -0
- package/workflows/reference-mgmt/positioning-check.md +339 -0
- package/workflows/reference-mgmt/positioning-shift.md +368 -0
- package/workflows/setup/.gitkeep +0 -0
- package/workflows/setup/init-questions.md +225 -0
- package/workflows/setup/init-validation.md +155 -0
- package/workflows/setup/init.md +449 -0
- package/workflows/setup/new-campaign.md +134 -0
- package/workflows/utility/.gitkeep +0 -0
- package/workflows/utility/archive.md +334 -0
- package/workflows/utility/health.md +166 -0
- package/workflows/utility/next.md +187 -0
- package/workflows/utility/resume.md +249 -0
- 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
|