feat(linkedin-studio): S14 — journey layer (create/measure front-doors + 5-journey router), v4.1.0

14a's cold command-rationalization found ZERO redundancy across the 27 commands
(no defensible merge/cut), so the operator reframed S14 from "merge/cut" to
"add a journey layer over the kept atomics".

- Add /linkedin:create + /linkedin:measure — delegate-only guided front-doors
  (Read/Glob/AskUserQuestion only; route to the command that owns the work)
- Re-tier commands/linkedin.md into 5 journeys (Start/Create/Engage/Measure/Grow);
  onboarding/strategy elevated as Start/Grow front-doors; Engage = calendar+firsthour tier
- 14a honesty nits: router now lists firsthour; calendar cross-links to firsthour;
  competitive confirmed UNGATED (the claimed 1K-gating inconsistency was unfounded)
- Lockstep: EXPECT_COMMANDS 27->29, v4.0.0->4.1.0 across plugin.json / README badges /
  plugin+root CLAUDE.md / README / CHANGELOG; new README commands-badge lint guard
- 14a deliverable corrected: multiplatform entry added (26/27 -> 27/27), header counts,
  competitive nit withdrawn
- Independent /trekreview (2 Opus reviewers) raised 3 MAJORs (stale commands badge,
  router competitive self-contradiction, STATE.md count) — ALL remediated in-session;
  verdict ALLOW

Gate: test-runner.sh 74/0/0; node --test 98/98; commands=29; v4.1.0 consistent.
Additive/minor — no command removed/renamed/behavior-changed; reload registers create+measure.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-05-30 21:27:06 +02:00
commit baca30feb1
16 changed files with 885 additions and 208 deletions

File diff suppressed because one or more lines are too long

View file

@ -114,7 +114,7 @@ Key commands: `/architect`, `/architect:ros`, `/architect:security`, `/architect
--- ---
### [LinkedIn Studio](plugins/linkedin-studio/) `v4.0.0` ### [LinkedIn Studio](plugins/linkedin-studio/) `v4.1.0`
Build authentic LinkedIn authority through algorithmic understanding, strategic consistency, and AI-assisted content creation. Build authentic LinkedIn authority through algorithmic understanding, strategic consistency, and AI-assisted content creation.
@ -123,9 +123,9 @@ Build authentic LinkedIn authority through algorithmic understanding, strategic
- **Content engine** — Content Matrix (40+ ideas from one topic), voice training with drift detection, full ideation → publish → 48-hour monitoring → analytics - **Content engine** — Content Matrix (40+ ideas from one topic), voice training with drift detection, full ideation → publish → 48-hour monitoring → analytics
- **Growth and monetization** — phase-specific guidance from 0 to 10K+ followers; topic-relevance profile optimization aligned to LinkedIn's 2026 ranking model - **Growth and monetization** — phase-specific guidance from 0 to 10K+ followers; topic-relevance profile optimization aligned to LinkedIn's 2026 ranking model
Key commands: `/linkedin:onboarding`, `/linkedin:post`, `/linkedin:quick`, `/linkedin:newsletter`, `/linkedin:carousel`, `/linkedin:report` Key commands: `/linkedin:create` + `/linkedin:measure` (journey front-doors), `/linkedin:onboarding`, `/linkedin:post`, `/linkedin:newsletter`, `/linkedin:report`
19 agents · 27 commands · 6 skills · 9 hooks · [Full documentation →](plugins/linkedin-studio/README.md) 19 agents · 29 commands (five journeys) · 6 skills · 9 hooks · [Full documentation →](plugins/linkedin-studio/README.md)
--- ---

View file

@ -1,7 +1,7 @@
{ {
"name": "linkedin-studio", "name": "linkedin-studio",
"version": "4.0.0", "version": "4.1.0",
"description": "LinkedIn Studio — full-spectrum LinkedIn content engine: feed posts, carousels, video scripts, and long-form newsletter editions, with the 2026 relevance-ranking model baked in. v4.0.0 is an audit-remediation release (Voyage Phase 03): every user-facing claim is made honest or removed, all 11 previously-orphaned agents are wired (→ 19 agents), a `/linkedin:firsthour` post-publish command is added (→ 27 commands), the algorithm-signal claims are reconciled to one sourced statement (no unpublishable model name or date), short-form de-AI and video quality gates are added, and the structure lint is rebuilt to guard the real layout plus version/count/stat consistency. Breaking: the newly-wired agents register only on reinstall/reload, and this consolidates the v3.0.0 identity break (slug, agent namespace `linkedin-studio:<agent>`, state-file path `~/.claude/linkedin-studio.local.md`). v3.1.0 added the cold adversarial review package (`/linkedin:headless-review` + Step 6.5 + `/linkedin:pivot` + per-artifact personas); the `/linkedin:*` commands are unchanged.", "description": "LinkedIn Studio — full-spectrum LinkedIn content engine: feed posts, carousels, video scripts, and long-form newsletter editions, with the 2026 relevance-ranking model baked in. v4.0.0 is an audit-remediation release (Voyage Phase 03): every user-facing claim is made honest or removed, all 11 previously-orphaned agents are wired (→ 19 agents), a `/linkedin:firsthour` post-publish command is added (→ 27 commands), the algorithm-signal claims are reconciled to one sourced statement (no unpublishable model name or date), short-form de-AI and video quality gates are added, and the structure lint is rebuilt to guard the real layout plus version/count/stat consistency. Breaking: the newly-wired agents register only on reinstall/reload, and this consolidates the v3.0.0 identity break (slug, agent namespace `linkedin-studio:<agent>`, state-file path `~/.claude/linkedin-studio.local.md`). v3.1.0 added the cold adversarial review package (`/linkedin:headless-review` + Step 6.5 + `/linkedin:pivot` + per-artifact personas); the `/linkedin:*` commands are unchanged. v4.1.0 adds a journey layer: two guided front-doors (`/linkedin:create`, `/linkedin:measure`) plus a router re-tiered into five journeys (Start · Create · Engage · Measure · Grow), with the 27 existing commands kept as the execution tier (→ 29 commands; additive, reload registers the two new commands).",
"author": { "author": {
"name": "Kjell Tore Guttormsen" "name": "Kjell Tore Guttormsen"
}, },

View file

@ -5,6 +5,26 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [4.1.0] - 2026-05-30
### Summary
**Journey layer over the command surface (Voyage S14).** Step 14a's cold, independent command-rationalization (`docs/remediation/command-rationalization.md`) audited all 27 commands under the same subsumption discipline as the agent-overlap study and found **zero redundancy** — the surface was over-grown in *count*, not in *duplication* (the two prior consolidations already removed the genuine overlaps). So instead of cutting, this release **organizes**: the 27 atomic commands are kept as the execution tier, and a **journey layer** is added on top. Additive and minor — no command removed, renamed, or behavior-changed; the two new commands register on reload. Design contract: `docs/remediation/journey-layer-design.md`.
### Added
- **`/linkedin:create`** — Create front-door. One guided "what do you want to make?" entry that routes to the command owning the format (`post`/`quick`/`react`/`carousel`/`video`/`multiplatform`/`batch`/`newsletter`). Delegates only — no drafting logic of its own.
- **`/linkedin:measure`** — Measure front-door. One guided "how am I doing?" entry that routes to the right analytics command (`import`/`report`/`analyze`/`audit`/`ab-test`). Delegates only. Commands 27 → 29.
### Changed
- **Router re-tiered into five journeys** (`commands/linkedin.md`) — Start · Create · Engage · Measure · Grow, each headed by a front-door (`onboarding`/`strategy` elevated as the Start/Grow front-doors; `create`/`measure` new; Engage is a `calendar` + `firsthour` relay), with the atomic commands nested as the execution tier. Absorbs the planned router-tiering UX step.
- **Honesty nits from 14a fixed** — the router now lists `/linkedin:firsthour` (was agent-only under Post-Publish); `calendar`'s publish-action first-hour block cross-links to `/linkedin:firsthour` for the full worked sprint plan.
- **`EXPECT_COMMANDS`** in `scripts/test-runner.sh` 27 → 29; CLAUDE.md / README rosters + counts updated in lockstep.
### Fixed
- **14a deliverable correction** — the cold review's first pass omitted `multiplatform` (covered 26/27) and raised a `competitive` 1K-gating inconsistency that did **not** survive verification (CLAUDE.md `:64`, README `:222`, the router, and the command body all leave `competitive` ungated). Both corrected in `command-rationalization.md`; net finding unchanged (keep 27, 0 merge, 0 cut).
### Compatibility
- **Minor / additive.** No command removed, renamed, or behavior-changed; the 27 existing commands, all 19 agents, and all state shapes are unchanged. The two new commands (`create`, `measure`) register when the plugin command set is rebuilt at session start — **reload required** to see them.
## [4.0.0] - 2026-05-30 ## [4.0.0] - 2026-05-30
### Summary ### Summary

File diff suppressed because one or more lines are too long

View file

@ -6,15 +6,15 @@
*AI-generated: all code produced by Claude Code through dialog-driven development. [Full disclosure →](../../README.md#ai-generated-code-disclosure)* *AI-generated: all code produced by Claude Code through dialog-driven development. [Full disclosure →](../../README.md#ai-generated-code-disclosure)*
![Version](https://img.shields.io/badge/version-4.0.0-blue) ![Version](https://img.shields.io/badge/version-4.1.0-blue)
![Platform](https://img.shields.io/badge/platform-Claude_Code_Plugin-purple) ![Platform](https://img.shields.io/badge/platform-Claude_Code_Plugin-purple)
![Commands](https://img.shields.io/badge/commands-27-green) ![Commands](https://img.shields.io/badge/commands-29-green)
![Agents](https://img.shields.io/badge/agents-19-orange) ![Agents](https://img.shields.io/badge/agents-19-orange)
![Hooks](https://img.shields.io/badge/hooks-9-red) ![Hooks](https://img.shields.io/badge/hooks-9-red)
![Reference Docs](https://img.shields.io/badge/reference_docs-25-teal) ![Reference Docs](https://img.shields.io/badge/reference_docs-25-teal)
![License](https://img.shields.io/badge/license-MIT-lightgrey) ![License](https://img.shields.io/badge/license-MIT-lightgrey)
Most experts know they *should* post on LinkedIn — and quietly don't. The blank editor wins. LinkedIn Studio turns that chore into a system: structured workflows that take you from idea to published, in your own voice, calibrated to how LinkedIn's **topic-relevance** ranking model (2026) actually distributes content. Two engines under one surface — a **feed engine** for short-form posts, carousels, and video scripts, and a **long-form engine** that runs newsletter editions and essays through a serious editorial pipeline before they ever lock. 27 commands, 19 specialized agents, 9 automated quality hooks, and a 25-document knowledge base grounded in the algorithm's real signals. Most experts know they *should* post on LinkedIn — and quietly don't. The blank editor wins. LinkedIn Studio turns that chore into a system: structured workflows that take you from idea to published, in your own voice, calibrated to how LinkedIn's **topic-relevance** ranking model (2026) actually distributes content. Two engines under one surface — a **feed engine** for short-form posts, carousels, and video scripts, and a **long-form engine** that runs newsletter editions and essays through a serious editorial pipeline before they ever lock. 29 commands organized into five journeys (Start · Create · Engage · Measure · Grow), 19 specialized agents, 9 automated quality hooks, and a 25-document knowledge base grounded in the algorithm's real signals.
This is not a shortcut. Hand the wheel to the AI and you land where everyone who did the same lands — the forgettable middle. The plugin removes the friction; the judgment, the genuine engagement, and the effort that make content worth reading remain entirely yours. This is not a shortcut. Hand the wheel to the AI and you land where everyone who did the same lands — the forgettable middle. The plugin removes the friction; the judgment, the genuine engagement, and the effort that make content worth reading remain entirely yours.
@ -183,7 +183,7 @@ The wizard handles everything: topic-relevance profile checklist, voice and user
## Commands ## Commands
All 27 commands use colon notation: `/linkedin:post`, `/linkedin:quick`, etc. All 29 commands use colon notation: `/linkedin:post`, `/linkedin:quick`, etc. The surface is organized into five journeys (Start · Create · Engage · Measure · Grow); `/linkedin:create` and `/linkedin:measure` are guided front-doors that route you to the right command when you know the journey but not the exact command.
### Onboarding ### Onboarding
@ -197,6 +197,7 @@ All 27 commands use colon notation: `/linkedin:post`, `/linkedin:quick`, etc.
| Command | Description | | Command | Description |
|---------|-------------| |---------|-------------|
| `/linkedin:create` | **Create front-door.** Guided "what do you want to make?" — routes you to the creation command that owns the format (post, quick, react, carousel, video, multiplatform, batch, or the long-form newsletter). Delegates only. |
| `/linkedin:post` | Full interactive post creation with angle selection, format choice, and refinement. Best for substantial posts (1,200-1,800 characters). | | `/linkedin:post` | Full interactive post creation with angle selection, format choice, and refinement. Best for substantial posts (1,200-1,800 characters). |
| `/linkedin:quick` | 5-minute quick post using the 3-line formula. Target: 150-500 characters. Best for reactions, observations, tips, and questions. Also the single entry point for the 8 post-type templates (fill-in-the-blank structures). | | `/linkedin:quick` | 5-minute quick post using the 3-line formula. Target: 150-500 characters. Best for reactions, observations, tips, and questions. Also the single entry point for the 8 post-type templates (fill-in-the-blank structures). |
| `/linkedin:newsletter` | Long-form orchestrator — newsletter edition, essay, or series article end-to-end at series quality. Multi-session 16-phase pipeline with skeleton + spine-prose gates BEFORE prose, an editorial-craft gate, fact-check, persona resonance, a cold adversarial review package, and visual assets — all BEFORE lock. | | `/linkedin:newsletter` | Long-form orchestrator — newsletter edition, essay, or series article end-to-end at series quality. Multi-session 16-phase pipeline with skeleton + spine-prose gates BEFORE prose, an editorial-craft gate, fact-check, persona resonance, a cold adversarial review package, and visual assets — all BEFORE lock. |
@ -215,6 +216,7 @@ All 27 commands use colon notation: `/linkedin:post`, `/linkedin:quick`, etc.
| Command | Description | | Command | Description |
|---------|-------------| |---------|-------------|
| `/linkedin:measure` | **Measure front-door.** Guided "how am I doing?" — routes you to the analytics command you need (import, report, analyze, audit, or ab-test). Delegates only. |
| `/linkedin:analyze` | Analyze content performance and troubleshoot engagement issues. Diagnoses algorithm penalties, profile-content mismatches, and reach drops. | | `/linkedin:analyze` | Analyze content performance and troubleshoot engagement issues. Diagnoses algorithm penalties, profile-content mismatches, and reach drops. |
| `/linkedin:audit` | Periodic content strategy audit. Reviews top/bottom posts, topic distribution, format mix, and engagement trends. Run quarterly. | | `/linkedin:audit` | Periodic content strategy audit. Reviews top/bottom posts, topic distribution, format mix, and engagement trends. Run quarterly. |
| `/linkedin:report` | Generate weekly performance report from imported analytics data. Shows key metrics, top performers, trends, and actionable alerts. | | `/linkedin:report` | Generate weekly performance report from imported analytics data. Shows key metrics, top performers, trends, and actionable alerts. |
@ -627,6 +629,7 @@ Scheduled posts are tracked in `assets/drafts/queue.json`:
| Version | Date | Highlights | | Version | Date | Highlights |
|---------|------|-----------| |---------|------|-----------|
| **4.1.0** | 2026-05-30 | **Journey layer over the command surface.** 14a's cold command-rationalization audited all 27 commands and found **zero redundancy** (over-grown in count, not duplication) → no merges/cuts. Instead, a journey layer is added: two new guided front-doors — **`/linkedin:create`** (routes to the right creation command) and **`/linkedin:measure`** (routes to the right analytics command) — and the router re-tiered into five journeys (Start · Create · Engage · Measure · Grow), with `onboarding`/`strategy` elevated as the Start/Grow front-doors and the 27 atomic commands kept as the execution tier (→ 29 commands). Router now lists `/linkedin:firsthour`; `calendar` cross-links to it. **Minor / additive** — no command removed, renamed, or behavior-changed; reload registers the two new commands. |
| **4.0.0** | 2026-05-30 | **Audit-remediation release (Voyage Phase 03).** A critical self-review found overclaiming (tracking/analytics/review-independence the plugin couldn't deliver), dormant capability (11 agents never invoked by any command), and structural rot (a dead lint, a self-contradicting algorithm claim, an unpublishable model brand/date in user copy). The fix: every claim made honest or removed; **all 11 orphaned agents wired** (no deletions → 19 agents); new **`/linkedin:firsthour`** command (→ 27 commands) + short-form de-AI gate + video quality gate; `post-feedback-monitor` → Opus; honest newsletter-distribution / profile-SEO / outreach surfaces; **algorithm signals reconciled to one sourced statement** (no model name/date) with `references/algorithm-signals-reference.md` as the single source of truth; analytics fresh-clone crash fixed; **voice-profile leak closed** (placeholder + sentinel + gitignore); structure lint rebuilt with version/count/stat/model-consistency + render-chain-propagation + `$`-safety guards (post-release remediation S8S13); 7-gate long-form review stack measured → no gate trimmed. **Breaking — reinstall/reload required** for the newly-wired agents; consolidates the v3.0.0 identity break. | | **4.0.0** | 2026-05-30 | **Audit-remediation release (Voyage Phase 03).** A critical self-review found overclaiming (tracking/analytics/review-independence the plugin couldn't deliver), dormant capability (11 agents never invoked by any command), and structural rot (a dead lint, a self-contradicting algorithm claim, an unpublishable model brand/date in user copy). The fix: every claim made honest or removed; **all 11 orphaned agents wired** (no deletions → 19 agents); new **`/linkedin:firsthour`** command (→ 27 commands) + short-form de-AI gate + video quality gate; `post-feedback-monitor` → Opus; honest newsletter-distribution / profile-SEO / outreach surfaces; **algorithm signals reconciled to one sourced statement** (no model name/date) with `references/algorithm-signals-reference.md` as the single source of truth; analytics fresh-clone crash fixed; **voice-profile leak closed** (placeholder + sentinel + gitignore); structure lint rebuilt with version/count/stat/model-consistency + render-chain-propagation + `$`-safety guards (post-release remediation S8S13); 7-gate long-form review stack measured → no gate trimmed. **Breaking — reinstall/reload required** for the newly-wired agents; consolidates the v3.0.0 identity break. |
| **3.1.0** | 2026-05-29 | Adversarial review package (Endring 9). New **`/linkedin:headless-review`** command + **Step 6.5 (headless-review)** in `/linkedin:newsletter`: three cold/headless archetypes — **`content-reviewer`** (argument), **`language-reviewer`** (Norwegian), **`fact-reviewer`** (cold re-verification + pivot-risk) — plus `persona-reviewer` (resonance/conversion), all with NO drafting-session context. New **`/linkedin:pivot`** command + pivot-detection gate (> 20 % word-count / > 2 new sections re-opens cleared gates before lock). **Per-artifact personas** (`articles.NN.personas`). Pipeline 15 → 16 phases; 24 → 26 commands; 16 → 19 agents; additive `personas`/`pivots`/`headlessReview` state. Backward-compatible; reload required for the new agents. | | **3.1.0** | 2026-05-29 | Adversarial review package (Endring 9). New **`/linkedin:headless-review`** command + **Step 6.5 (headless-review)** in `/linkedin:newsletter`: three cold/headless archetypes — **`content-reviewer`** (argument), **`language-reviewer`** (Norwegian), **`fact-reviewer`** (cold re-verification + pivot-risk) — plus `persona-reviewer` (resonance/conversion), all with NO drafting-session context. New **`/linkedin:pivot`** command + pivot-detection gate (> 20 % word-count / > 2 new sections re-opens cleared gates before lock). **Per-artifact personas** (`articles.NN.personas`). Pipeline 15 → 16 phases; 24 → 26 commands; 16 → 19 agents; additive `personas`/`pivots`/`headlessReview` state. Backward-compatible; reload required for the new agents. |
| **3.0.0** | 2026-05-29 | **Renamed** `linkedin-thought-leadership``linkedin-studio` ("LinkedIn Thought Leadership" → **LinkedIn Studio**). Breaking (slug + agent namespace `linkedin-studio:<agent>` + runtime state path `~/.claude/linkedin-studio.local.md` all change; reinstall required, state migrated in place), but **functionality byte-identical to v2.4.0**. The `/linkedin:*` commands are unchanged (frontmatter-namespaced, slug-independent). Catch-all skill dir renamed to match (`skills/linkedin-studio/`); the five functional skills unchanged. | | **3.0.0** | 2026-05-29 | **Renamed** `linkedin-thought-leadership``linkedin-studio` ("LinkedIn Thought Leadership" → **LinkedIn Studio**). Breaking (slug + agent namespace `linkedin-studio:<agent>` + runtime state path `~/.claude/linkedin-studio.local.md` all change; reinstall required, state migrated in place), but **functionality byte-identical to v2.4.0**. The `/linkedin:*` commands are unchanged (frontmatter-namespaced, slug-independent). Catch-all skill dir renamed to match (`skills/linkedin-studio/`); the five functional skills unchanged. |

View file

@ -132,7 +132,11 @@ writeState(content => updatePostTracking(content, {
``` ```
Replace placeholders with actual post data from the published post. Replace placeholders with actual post data from the published post.
**3e. First-hour battle plan.** Show after marking: **3e. First-hour battle plan.** Show the lightweight in-flow nudge below after marking.
For the **full worked sprint** — timestamped engagement targets (whales / inner-circle /
ICPs), draft self-comments + CEA replies in voice, and a minute-by-minute timeline — run
`/linkedin:firsthour`, which persists the plan to state and hands off to
`post-feedback-monitor`. The checklist here is the quick version:
``` ```
Post marked as published! Here's your first-hour plan: Post marked as published! Here's your first-hour plan:

View file

@ -0,0 +1,66 @@
---
name: linkedin:create
description: |
Content-creation front-door — one guided entry for when you want to make something
but haven't picked the format yet. Asks what you want to create and routes you to the
command that owns that format (post, quick, react, carousel, video, multiplatform,
batch, or the long-form newsletter). It does NOT draft anything itself — it hands off
to the command that owns the work, so each format keeps its own voice rules and
quality gates.
Triggers on: "create", "make something", "create content", "what should I make",
"new content", "help me create", "i want to post something", "linkedin create".
allowed-tools:
- Read
- Glob
- AskUserQuestion
---
# Create — Content Front-Door
You are the entry point for the **Create** journey. The user wants to make content but
may not know which format or command fits. Your job: identify the intent in one
question and route to the command that owns the work. **You do not draft here.**
## Step 0: Quick context (optional)
If `~/.claude/linkedin-studio.local.md` exists, you may glance at the planned next
topic and recent pillars to make a smarter suggestion — but keep it to one line and
do not block on it.
## Step 1: Identify what they want to create
If the user's message already names a format (e.g. "a carousel about X", "react to
this URL", "a video script") OR hands you a URL, skip the question and route directly
per the map below.
Otherwise use `AskUserQuestion`**"What do you want to create?"**
1. **A post** — a full, substantial post (angle → draft → refine) → `/linkedin:post`
2. **A quick post** — a fast 5-minute post or a templated post-type → `/linkedin:quick`
3. **React to something** — turn a URL / article / news into a post → `/linkedin:react`
4. **A carousel** — a multi-slide / document post → `/linkedin:carousel`
5. **A video script** — talking-head / screen-recording / slideshow → `/linkedin:video`
6. **Adapt existing content** — for Twitter/X, slides, YouTube → `/linkedin:multiplatform`
7. **A whole week** — batch 35 posts in one session → `/linkedin:batch`
8. **Long-form** — newsletter edition, essay, or series article → `/linkedin:newsletter`
## Step 2: Route
State the chosen command and one line of why, then **proceed into that command's
workflow** (route to `/linkedin:<target>` and begin it). Do NOT inline or duplicate
the target's steps — each creation command owns its own workflow, voice rules, and
quality gates.
| Intent | Command |
|--------|---------|
| Substantial post | `/linkedin:post` |
| Quick / templated post | `/linkedin:quick` |
| React to a URL / article | `/linkedin:react` |
| Carousel / document | `/linkedin:carousel` |
| Video script | `/linkedin:video` |
| Cross-platform adaptation | `/linkedin:multiplatform` |
| A full week | `/linkedin:batch` |
| Long-form (newsletter / essay / series) | `/linkedin:newsletter` |
**Long-form lock:** newsletters, essays, and series articles are owned end-to-end by
`/linkedin:newsletter` — the single long-form entry point. Never draft long-form here.

View file

@ -58,99 +58,92 @@ If queue is empty: "No posts scheduled. Run /linkedin:batch to plan your week."
## Available Commands ## Available Commands
Present these options to the user: LinkedIn Studio is organized as **five journeys**. Each journey has a **front-door**
command (start here if you're unsure) plus the focused commands it routes to. Type a
front-door when you know the journey but not the exact command; type a specific command
directly when you do.
### Getting Started ### 🟢 Start — get set up and publish your first post
| Command | Purpose | | Command | Purpose |
|---------|---------| |---------|---------|
| `/linkedin:onboarding` | Full onboarding wizard — profile, setup, and first post in one flow | | `/linkedin:onboarding` | **Front-door.** Full guided flow: profile → setup → first post |
| `/linkedin:setup` | Populate voice samples, case studies, frameworks, and audience data |
| `/linkedin:first-post` | First-post accelerator — zero to published in under 10 minutes | | `/linkedin:first-post` | First-post accelerator — zero to published in under 10 minutes |
| `/linkedin:setup` | Guided setup to populate empty asset templates with your real voice, case studies, and audience data |
### Content Creation ### ✍️ Create — make content
| Command | Purpose | | Command | Purpose |
|---------|---------| |---------|---------|
| `/linkedin:create` | **Front-door.** Tells you which creation command fits, then routes you |
| `/linkedin:post` | Full post creation with angle selection, format choice, and refinement | | `/linkedin:post` | Full post creation with angle selection, format choice, and refinement |
| `/linkedin:quick` | Fast 5-minute post (3-line formula) + the 8 post-type templates |
| `/linkedin:react` | React to a URL (article, news, research) and turn it into a post | | `/linkedin:react` | React to a URL (article, news, research) and turn it into a post |
| `/linkedin:quick` | Fast 5-minute post using the 3-line formula (also the 8 post-type templates) | | `/linkedin:carousel` | Structured multi-slide carousel with visual layout guidance |
| `/linkedin:pipeline` | Full end-to-end workflow from idea to post-publish analysis | | `/linkedin:video` | Video scripts with hook, body, CTA, captions, and thumbnail suggestions |
| `/linkedin:carousel` | Create structured multi-slide carousel with visual layout guidance | | `/linkedin:multiplatform` | Adapt content for Twitter/X, slides, YouTube (long-form → newsletter) |
| `/linkedin:video` | Create video scripts with hook, body, CTA, captions, and thumbnail suggestions |
| `/linkedin:newsletter` | Long-form orchestrator — newsletter editions, essays, series articles (research → draft → fact-check → persona-review → lock → delivery). The single long-form entry point |
| `/linkedin:headless-review` | Cold adversarial review of a FROZEN long-form draft (argument, language, facts, reader-fit) — run before lock, ideally in a fresh session for max independence |
| `/linkedin:pivot` | Re-open a long-form edition after a substantive late change so cleared gates (fact-check → editorial → persona → headless) re-run before lock |
| `/linkedin:batch` | Create a full week of content in one session | | `/linkedin:batch` | Create a full week of content in one session |
| `/linkedin:calendar` | View and manage your post scheduling queue + run the publish action (mark a scheduled post as published) | | `/linkedin:pipeline` | End-to-end single-post workflow (idea → draft → schedule → analyze) |
| `/linkedin:newsletter` | **Long-form spine.** Newsletter editions, essays, series articles. The single long-form entry point |
| `/linkedin:headless-review` | Cold adversarial re-read of a FROZEN long-form draft before lock (ideally in a fresh session) |
| `/linkedin:pivot` | Re-open a long-form edition after a late change so cleared gates re-run |
### Strategy & Optimization ### 📅 Engage — ship and work the first hour
| Command | Purpose | | Command | Purpose |
|---------|---------| |---------|---------|
| `/linkedin:strategy` | Growth strategy + authority building (phase-specific guidance, trajectory adjustments, signature content for Phase 2+) | | `/linkedin:calendar` | View/manage the queue + the publish action (mark a scheduled post as published) |
| `/linkedin:profile` | profile/topic-relevance optimization checklist | | `/linkedin:firsthour` | Post-publish first-hour sprint: timestamped targets + draft comments + timeline |
| `/linkedin:analyze` | Analyze content performance or troubleshoot issues |
| `/linkedin:ab-test` | Design and manage A/B tests for content optimization | After publishing, the `post-feedback-monitor` agent tracks performance in the critical
| `/linkedin:audit` | Quarterly content strategy audit | first 48 hours, detects anomalies, and advises real-time interventions.
| `/linkedin:competitive` | Competitive analysis of other thought leaders |
### 📊 Measure — understand performance
| Command | Purpose |
|---------|---------|
| `/linkedin:measure` | **Front-door.** Routes you to the right analytics command |
| `/linkedin:import` | Import LinkedIn CSV exports for analytics | | `/linkedin:import` | Import LinkedIn CSV exports for analytics |
| `/linkedin:report` | Generate weekly performance report with trends and alerts | | `/linkedin:report` | Weekly/monthly performance report with trends and alerts |
| `/linkedin:analyze` | Troubleshoot performance (reach dropped, low engagement) |
| `/linkedin:audit` | Quarterly content strategy audit |
| `/linkedin:ab-test` | Design and manage A/B tests for content optimization |
### Post-Publish Monitoring ### 🚀 Grow — authority, reach, and revenue
| Agent | Purpose |
|-------|---------|
| `post-feedback-monitor` | Monitor post performance in the critical first 48 hours, detect anomalies, and get real-time intervention advice |
### Growth & Monetization
| Command | Purpose | Unlocks at | | Command | Purpose | Unlocks at |
|---------|---------|-----------| |---------|---------|-----------|
| `/linkedin:strategy` | **Front-door.** Phase roadmap, trajectory, authority + signature content | Any phase |
| `/linkedin:profile` | profile/topic-relevance optimization checklist | Any phase |
| `/linkedin:competitive` | Competitive analysis of other thought leaders | Any phase |
| `/linkedin:monetize` | Monetization strategy (lead magnets, consulting funnel, pricing) | ~1K followers | | `/linkedin:monetize` | Monetization strategy (lead magnets, consulting funnel, pricing) | ~1K followers |
| `/linkedin:outreach` | Outreach orchestrator — collaborations and speaking opportunities (CFPs, partner pitches) | ~1K followers | | `/linkedin:outreach` | Collaborations and speaking opportunities (CFPs, partner pitches) | ~1K followers |
| `/linkedin:multiplatform` | Adapt content for Twitter/X, slides, YouTube (short-form/cross-format; long-form → `/linkedin:newsletter`) | Any phase |
**Gating rule:** the "Unlocks at ~1K followers" commands are deliberately **Gating rule:** the "Unlocks at ~1K followers" commands are deliberately listed but
listed but soft-gated — they work at any follower count, but their value soft-gated — they work at any follower count, but their value compounds once a profile
compounds once a profile has the audience scale and authority signal that has the audience scale and authority signal that makes lead magnets, partnerships, and
makes lead magnets, partnerships, and speaking pitches realistic. Below speaking pitches realistic. Below ~1K followers the router notes the threshold and
~1K followers the router will note the threshold and suggest suggests `/linkedin:strategy` first. (`/linkedin:competitive` is **not** gated —
`/linkedin:strategy` first. competitive analysis helps at any stage, especially early positioning.)
## Ask the User ## Ask the User
Use AskUserQuestion to ask: Show the five journeys as a menu and let the user pick a journey or jump straight to a
command. Lead with the front-doors.
**What would you like to do?** **What would you like to do?**
0. **Onboarding wizard** — Just installed? Full guided flow: profile → setup → first post - **🟢 Start** — `onboarding` (full wizard) · `setup` · `first-post`
1. **Setup & personalize** — Guided setup to populate voice, case studies, frameworks, and audience data - **✍️ Create** — `create` (guided) · post · quick · react · carousel · video · multiplatform · batch · pipeline · newsletter · headless-review · pivot
2. **Create a post** — Full post workflow with angle selection - **📅 Engage** — `calendar` (queue + mark published) · `firsthour` (first-hour sprint)
3. **React to a URL** — Turn an article/news into a post - **📊 Measure** — `measure` (guided) · import · report · analyze · audit · ab-test
4. **Quick post** — Post something fast (5 min) - **🚀 Grow** — `strategy` (roadmap) · profile · competitive · monetize ⚿ · outreach ⚿
5. **Full pipeline** — End-to-end: idea → draft → optimize → publish
6. **Batch create** — Create a full week of content in one session
7. **Use a template** — Browse proven post templates
8. **View calendar** — See scheduled posts and manage queue
9. **Plan content** — Weekly/monthly content planning
10. **Growth strategy & authority** — Plan growth, build signature content, compound authority
11. **Optimize profile** — topic-relevance profile audit
12. **Audit content** — Review what's working and what's not
13. **Competitive analysis** — Learn from other thought leaders
14. **Monetize** — Revenue strategies for thought leadership
15. **Outreach** — Collaborations and speaking opportunities (CFPs, partner pitches, joint content)
16. **Multi-platform** — Adapt content for other platforms
17. **Troubleshoot** — My content isn't performing well
18. **Monitor post** — Check how my latest post is performing (first 48 hours)
19. **A/B test** — Design, track, or analyze content experiments
20. **Create a video** — Script for talking head, screen recording, or slideshow
21. **Mark published** — I just published a scheduled post
22. **Write long-form** — Newsletter edition, essay, or series article (`/linkedin:newsletter`)
23. **Cold review (headless)** — Independent adversarial re-read of a frozen long-form draft before lock (`/linkedin:headless-review`)
24. **Pivot a long-form edition** — Re-open cleared gates after a late substantive change (`/linkedin:pivot`)
Based on their answer, guide them to the appropriate command or invoke it directly. If they name a command, route to it. If they name a journey but not a command, route to
that journey's front-door (`create` / `measure` / `onboarding` / `strategy`); for Engage,
ask whether they're scheduling (`calendar`) or have just published (`firsthour`). Use
`AskUserQuestion` for any sub-choice (≤4 options per question). Based on their answer,
guide them to the appropriate command or invoke it directly.
## If They Have Specific Content ## If They Have Specific Content
@ -198,6 +191,9 @@ If the user's intent is clear from context:
- Mentions "status" or "on track" → Route to `/linkedin:calendar` (plan-vs-queue diff) - Mentions "status" or "on track" → Route to `/linkedin:calendar` (plan-vs-queue diff)
- Mentions "repurpose" or "reuse" → Suggest `content-repurposer` agent - Mentions "repurpose" or "reuse" → Suggest `content-repurposer` agent
- Mentions "video" or "video script" or "film" or "record" or "talking head" or "screen recording" or "slideshow video" → Route to `/linkedin:video` - Mentions "video" or "video script" or "film" or "record" or "talking head" or "screen recording" or "slideshow video" → Route to `/linkedin:video`
- Mentions "create" or "make something" or "what should I make" or "new content" (no specific format named) → Route to `/linkedin:create` (the Create front-door)
- Mentions "measure" or "how am I doing" or "my performance" or "performance overview" or "how are my posts doing" → Route to `/linkedin:measure` (the Measure front-door)
- Mentions "first hour" or "I just posted" or "reply loop" or "work my post" or "engage now" → Route to `/linkedin:firsthour` (the worked first-hour sprint plan — distinct from `/linkedin:calendar`'s mark-as-published action)
- Has a URL to react to → Route to `/linkedin:react` - Has a URL to react to → Route to `/linkedin:react`
- Has substantial content to convert → Route to `/linkedin:post` - Has substantial content to convert → Route to `/linkedin:post`

View file

@ -0,0 +1,51 @@
---
name: linkedin:measure
description: |
Performance front-door — one guided entry for when you want to understand how you're
doing on LinkedIn. Asks what you need and routes you to the command that owns that
analysis (import, report, analyze/troubleshoot, audit, or A/B test). It does NOT
crunch numbers itself — it hands off to the command that owns the work.
Triggers on: "measure", "how am I doing", "my performance", "show my analytics",
"performance overview", "how are my posts doing", "linkedin measure".
allowed-tools:
- Read
- Glob
- AskUserQuestion
---
# Measure — Performance Front-Door
You are the entry point for the **Measure** journey (the measure → improve loop). The
user wants insight into performance but may not know which command fits. Identify the
intent in one question and route. **You do not run the analysis here.**
## Step 0: Quick context (optional)
If `assets/analytics/` holds imported data, you may note "last import: [date]" in one
line so the user knows whether a fresh import is needed first. Do not block on it.
## Step 1: Identify what they need
Use `AskUserQuestion`**"What do you want to do?"**
1. **Import new data** — load a LinkedIn analytics CSV export → `/linkedin:import`
2. **See a report** — weekly/monthly numbers, trends, top performers → `/linkedin:report`
3. **Diagnose a problem** — reach dropped / low engagement, what's wrong → `/linkedin:analyze`
4. **Strategy audit** — periodic top/bottom posts, topic & format mix review → `/linkedin:audit`
5. **A/B test** — design, log, or review a content experiment → `/linkedin:ab-test`
## Step 2: Route
State the chosen command and one line of why, then **proceed into that command's
workflow**. Do NOT duplicate the analysis logic — each command owns it.
| Intent | Command |
|--------|---------|
| Import a CSV export | `/linkedin:import` |
| Weekly / monthly report | `/linkedin:report` |
| Troubleshoot performance | `/linkedin:analyze` |
| Quarterly strategy audit | `/linkedin:audit` |
| Content experiment | `/linkedin:ab-test` |
**Order note:** reporting needs imported data. If the user wants a report but nothing
has been imported yet, route to `/linkedin:import` first, then `/linkedin:report`.

View file

@ -3,7 +3,7 @@ name: linkedin:onboarding
description: | description: |
Multi-step onboarding wizard that guides new users through profile → setup → first-post Multi-step onboarding wizard that guides new users through profile → setup → first-post
as one cohesive flow. Designed for users who have just installed the plugin and want a as one cohesive flow. Designed for users who have just installed the plugin and want a
single guided path instead of navigating 27 commands on their own. single guided path instead of navigating 29 commands on their own.
Triggers on: "onboarding", "get started", "new user", "setup wizard", "start from scratch", Triggers on: "onboarding", "get started", "new user", "setup wizard", "start from scratch",
"just installed", "how do I start", "walk me through", "linkedin onboarding". "just installed", "how do I start", "walk me through", "linkedin onboarding".
allowed-tools: allowed-tools:
@ -214,4 +214,4 @@ First post: [Published DATE / Pending — run /linkedin:first-post]
- `/linkedin:batch` — Plan a full week of content in one session - `/linkedin:batch` — Plan a full week of content in one session
- `/linkedin:react` — Turn articles and news into posts - `/linkedin:react` — Turn articles and news into posts
- `/linkedin:strategy` — Growth strategy tailored to your follower level - `/linkedin:strategy` — Growth strategy tailored to your follower level
- `/linkedin` — See all 27 commands anytime - `/linkedin` — See all 29 commands anytime

View file

@ -0,0 +1,375 @@
# Command-Surface Rationalization — Step 14a
_Remediation Voyage, command-surface pass. Independent, COLD read of all 27
command files in `commands/*.md` (full bodies, not just frontmatter), with the
router (`commands/linkedin.md`), `CLAUDE.md`, and `README.md` as the map of the
intended surface. Written 2026-05-30. ANALYSIS ONLY — no command file was edited,
merged, deleted, or renamed; the single deliverable is this document._
> **Correction (post-review, 2026-05-30).** The first pass omitted `multiplatform`
> (covered 26/27) and mis-stated two group-header counts; it also raised a
> `competitive` 1K-gating inconsistency that did **not** survive verification. All
> three are fixed below: `multiplatform` now has its own entry (Group B), the Group
> C/F headers read 3/5, and the `competitive` nit is withdrawn (CLAUDE.md `:64`,
> README `:222`, the router, and the command body all leave it ungated). Net finding
> is unchanged — **keep 27, 0 merge, 0 cut** — now genuinely covering all 27.
## Method note
The fixtures here are **the command files themselves** — each command's purpose,
its full workflow body, its frontmatter `description` (the trigger-phrase set that
governs how it gets invoked), and the sibling surfaces it touches. The discipline
is borrowed verbatim from `docs/remediation/overlap-measurement.md` (whose SUBJECT
is the 7 long-form review *agents*, not the commands — kept strictly separate
here): for every overlap I apply the **subsumption test** — _does either command's
catch-set / surface fully contain the other's?_ — and the trim rule: **merge or
cut ONLY where a command catches nothing a sibling doesn't; if the redundancy is
justified, record it and KEEP; if I can't decide, record "inconclusive — retain
pending operator view" and do NOT trim.** Default-to-keep under uncertainty. This
plugin already over-grew once (24→27), so the bias is honest-surface, not
consolidation-for-its-own-sake and not growth-for-its-own-sake. Every
recommendation is grounded in a citable trigger set, workflow step, or sibling
surface — no taste-based cuts.
A leverage note used throughout: a command's **invocation leverage** is the
product of (a) trigger-phrase breadth in its `description` and (b) how likely a
user is to actually type the intent when a *broader* command already catches it.
A command whose entire trigger set is a strict subset of a broader command's, and
which adds no unique workflow, is the classic merge/cut candidate.
---
## Group A — Entry / router (1)
### `linkedin` (router)
- **Purpose** — Status line (weekly progress, streak, follower phase) + upcoming/overdue queue + a menu/router that disambiguates to the right subcommand.
- **Overlap with siblings** — Structurally overlaps *every* command (it lists them), but that is its job, not redundancy. No subsumption either way: the router holds no content-production surface, the leaf commands hold no menu/status surface.
- **Invocation leverage** — Highest-traffic entry point: triggers on the bare `"linkedin"`, `"/linkedin"`, `"linkedin help"`. This is the front door.
- **Recommendation** — **keep.**
- **Rationale** — Structural and the single highest-leverage surface. Judged on grouping honesty: the grouping is broadly honest (Getting Started / Content Creation / Strategy / Post-Publish / Growth+Monetization), and it correctly soft-gates the 1K commands. One honest-surface nit for the operator (not a cut): it lists `post-feedback-monitor` as an *agent* under "Post-Publish Monitoring" but does not list the new `/linkedin:firsthour` command in that section — the router's own map is one release behind the surface it routes to.
---
## Group B — Short-form creation (7)
### `post`
- **Purpose** — Full interactive post creation (angle → format → draft → quality/de-AI gate → refine), targeting 1,2001,800-char substantial posts.
- **Overlap with siblings**`quick` (short 150500-char path), `react` (URL-sourced), `pipeline` (post + schedule + monitor). Subsumption test: `post` does NOT subsume `quick` (different length band + 3-line formula + 8 templates) and `quick` does not subsume `post` (no refinement cycle, no `content-optimizer` delegation). `post` is the body that `pipeline` wraps but `pipeline` adds scheduling/queue/first-hour that `post` lacks; neither subsumes the other.
- **Invocation leverage** — Very high; broad trigger set ("create linkedin post", "write a post", "turn this into a post"). Core entry point alongside `quick`.
- **Recommendation** — **keep.**
- **Rationale** — Distinct length/depth tier with a unique refinement+optimizer surface; one of the two highest-traffic creation commands.
### `quick`
- **Purpose** — 5-minute 3-line-formula post (150500 chars) AND the home of the 8 post-type templates (reaction/tip/observation/hot-take/failure/question/curation/one-liner).
- **Overlap with siblings**`post` (longer tier), `first-post` (which explicitly reuses `quick`'s 3-line formula). Subsumption test: `quick` uniquely owns the template library and the short-length band; `post` owns the long band. The two are explicitly cross-referenced ("When to Upgrade → `/linkedin:post`"). No subsumption.
- **Invocation leverage** — High; broad trigger set including the absorbed `templates` intent ("post template", "give me a template", "fill in the blank post"). This absorption was the v2.0.0 consolidation — confirmed intact in the body (Step 1 hosts the template library).
- **Recommendation** — **keep.**
- **Rationale** — Holds the unique short-form length tier + the entire template surface that `templates` was folded into. Cutting it would orphan the templates.
### `react`
- **Purpose** — URL-to-post pipeline: fetch external content (article/news/research/YouTube), extract, pick a reaction angle, draft in voice; includes a multi-URL comparison path.
- **Overlap with siblings**`post` (could in principle ingest a URL via WebFetch — `post` Step 1 even mentions "If they provide a URL, use WebFetch"). Subsumption test: `react` has a unique surface `post` lacks — the multi-source comparison/synthesis path (Steps 1b8b), the content-type→angle table tuned to *reactions*, and the "react, don't summarize / your take is the hook" discipline. `post` does not subsume that. `react` does not subsume `post` (no general-topic drafting).
- **Invocation leverage** — High and unambiguous: "react to this", "this article", "this url", "share this news". The router routes any bare URL here. A user with a link will not naturally type `/linkedin:post`.
- **Recommendation** — **keep.**
- **Rationale** — Genuinely unique URL-ingestion + multi-source-synthesis surface and a distinct, frequently-typed intent.
### `pipeline`
- **Purpose** — End-to-end lifecycle orchestrator: ideation → draft → optimize → **schedule/queue** → 5x5x5 pre-engagement → publish → first-hour → 48h analysis.
- **Overlap with siblings** — This is the densest overlap node. It re-does `post`'s drafting (Step 2), `calendar`'s queueing (Step 4 Option 3 calls the same `queue-manager.mjs` `queueAdd`), the 5x5x5/first-hour plan (now also `firsthour`'s job), and points to `analyze` at the end. Subsumption test: no *single* sibling subsumes `pipeline` — it is the only command that strings the whole chain into one guided run with explicit step gates. But `pipeline` is itself **a thinner re-statement of `post` + `calendar` (+ `firsthour`)**: every individual capability it offers exists, more developed, in those leaf commands (its draft step is a condensed `post`; its schedule step is a condensed `calendar`; its first-hour step is a condensed `firsthour`).
- **Invocation leverage** — Moderate-to-low as a *natural* type. Trigger set ("pipeline", "full workflow", "end to end", "idea to post") is narrow and jargon-y; in practice a user wanting to create+schedule will type `/linkedin:post` then `/linkedin:calendar`. It reads as a workflow-orchestrator showcase more than a daily entry point.
- **Recommendation****keep** (with a flag) — leaning **inconclusive**.
- **Rationale** — No clean subsumption (it uniquely *sequences* the chain), so the trim rule says retain. But it is the surface most worth the operator's scrutiny: its value is the *orchestration*, and that value erodes as `post`/`calendar`/`firsthour` each grow richer than `pipeline`'s inlined condensations. Flagged in the honest-uncertainty list. If the operator ever wants to shrink the surface, this is the first place a defensible merge could be argued (→ `post`, preserving the explicit schedule+first-hour hand-off chain) — but the evidence does not *compel* it.
### `carousel`
- **Purpose** — Structured slide-by-slide carousel/document generator with template selection, per-slide copy, caption, de-AI gate, and optional mcp-image slide generation.
- **Overlap with siblings**`multiplatform` (has a "LinkedIn → Presentation Slides" template) and `post` (notes "could also work as a carousel — run `/linkedin:carousel`"). Subsumption test: `multiplatform`'s slide template is a 10-line generic outline; `carousel` is a full format engine (5 templates, per-slide char rules, mcp-image generation, carousel quality checklist). `multiplatform` does not remotely subsume it. `carousel` owns the highest-engagement organic format end-to-end.
- **Invocation leverage** — High and specific: "carousel", "slide deck", "pdf post", "swipe post", "document post". A distinct format intent users type directly.
- **Recommendation** — **keep.**
- **Rationale** — Deep, unique format surface with image generation; not subsumed by anything.
### `video`
- **Purpose** — Video script generator (talking-head/screen-rec/slideshow, 30s2min) with pacing/visual/energy cues, captions, thumbnail, first comment, a video quality gate, and delegation to `video-scripter`.
- **Overlap with siblings**`multiplatform` ("LinkedIn → YouTube Script" template). Subsumption test: `multiplatform`'s YouTube template is a generic timing outline; `video` is a full LinkedIn-native scripting engine (word-budget math, muted-autoplay test, completeness gate, `video-scripter` agent). No subsumption — and they target different platforms (LinkedIn-native vs. YouTube adaptation).
- **Invocation leverage** — High and specific: "video script", "talking head script", "record a video". Direct format intent.
- **Recommendation** — **keep.**
- **Rationale** — Unique LinkedIn-native video surface + dedicated agent; the `multiplatform` overlap is a thin adaptation template, not a substitute.
### `multiplatform`
- **Purpose** — Adapt existing LinkedIn content for other platforms: a Twitter/X thread, a generic presentation deck, or a YouTube script. Long-form is explicitly routed out to `/linkedin:newsletter`.
- **Overlap with siblings**`carousel` (its "Presentation Slides" template) and `video` (its "YouTube Script" template). Subsumption test: `multiplatform`'s slide/YouTube blocks are ~10-line generic outlines, while `carousel` is a full LinkedIn-native carousel engine and `video` a full LinkedIn-native scripting engine — neither subsumes the other, and they target different outputs (LinkedIn-native vs. Twitter / YouTube / generic deck). Critically, the **Twitter/X-thread** adaptation path exists in **no other command**. No subsumption.
- **Invocation leverage** — Moderate; "adapt for twitter", "cross-post", "repurpose for", "turn into thread". A distinct cross-platform intent, but lower-traffic than the native creation commands.
- **Recommendation****keep** (flag: **develop-candidate**).
- **Rationale** — Unique cross-platform / Twitter surface; subsumption fails as a cut. But it is the **thinnest** command in the set — the only one that inlines static templates instead of delegating, where the `content-repurposer` agent already exists to power a richer adaptation. Keep now; a future *develop* (wire `content-repurposer`, deepen the per-platform output) is the defensible improvement, not a merge/cut.
---
## Group C — Long-form (3)
### `newsletter`
- **Purpose** — The single long-form orchestrator: a fixed 16-phase, multi-session pipeline (research → skeleton/spine gates → draft → fact-check → editorial → persona sweep → headless review → visual assets → lock → hook gate → schedule) with maintained edition-state.
- **Overlap with siblings**`headless-review` and `pivot` are *phases/companions* of this command (Step 6.5 and the lock-precondition re-open). Subsumption test: `newsletter` invokes the headless package inline (Step 6.5) and runs the pivot heuristic as a lock precondition (Step 8) — so it functionally *contains* both. But containment ≠ the companions are redundant (see their entries: the value is fresh-session isolation and a named re-open ritual, which `newsletter` cannot itself provide). No short-form command overlaps it; `multiplatform` explicitly routes all long-form here.
- **Invocation leverage** — High for its niche; the sole entry for "newsletter", "long-form", "essay", "series article".
- **Recommendation** — **keep.**
- **Rationale** — The entire long-form spine; nothing else does this and everything long-form routes to it.
### `headless-review`
- **Purpose** — Cold/adversarial review package run on a FROZEN draft with starved context — `content-reviewer` + `language-reviewer` + `fact-reviewer` + `persona-reviewer` (resonance/conversion), consolidated into one operator-gated report. Standalone surface for `newsletter` Step 6.5.
- **Overlap with siblings**`newsletter` (Step 6.5 fans the same package inline). Subsumption test: this is the calibration case (c) the brief flags. Does `newsletter` Step 6.5 subsume `headless-review`? **No** — and the command's own body states *why*: the cardinal value is **Layer 1 fresh-session isolation** ("the parent itself then has no drafting transcript"). When the package runs inline inside the drafting `newsletter` session it carries exactly the framing-bias the package exists to eliminate. The standalone command is the *only* way to get a genuinely cold parent context. So the standalone surface has a unique catch (true independence) the inline phase structurally cannot.
- **Invocation leverage** — Moderate; specific trigger set ("headless review", "cold review", "adversarial review", "review the frozen draft"). Niche but real, and the recommended path is to type it *in a fresh session* — which is precisely an action a phase cannot perform.
- **Recommendation****keep** — justified standalone, not merely-as-a-phase.
- **Rationale** — Subsumption fails in the independence dimension: the fresh-session parent is a capability the `newsletter` phase cannot replicate. This is the "redundancy is justified — record and keep" case, mirroring the agent-overlap finding for the cold trio in `overlap-measurement.md`.
### `pivot`
- **Purpose** — A named ritual to re-open an already-cleared long-form edition after a substantive late change: logs `pivots[]`, resets `currentPhase`, un-locks, invalidates downstream verdicts, marks which gates must re-pass. Includes the >20%/>2-section heuristic.
- **Overlap with siblings**`newsletter` (which runs the same heuristic as a Step 8 lock precondition and owns the gate re-runs). Subsumption test (calibration case c): does `newsletter` subsume `pivot`? **Partially but not fully.** `newsletter` Step 8 *detects* drift and *stops* the lock, but it explicitly **points the operator to `/linkedin:pivot`** to perform the state surgery (log the pivot entry, reset phase, un-lock, invalidate verdicts). `pivot` does NOT run the gates ("Do not run the gates yourself — `/linkedin:newsletter` owns the pipeline"); `newsletter` does NOT perform the re-open bookkeeping. The two are complementary halves of one ritual — clean separation, no subsumption.
- **Invocation leverage** — Low-to-moderate; narrow trigger set ("pivot", "re-open edition", "added a section", "changed the angle"). Rarely hit, but when hit it does deterministic state work no other command does.
- **Recommendation** — **keep.**
- **Rationale** — Holds a unique state-mutation surface (the re-open bookkeeping) that `newsletter` deliberately delegates out; not subsumed. Lower-traffic, but the trim rule retains a non-redundant specialist.
---
## Group D — Onboarding / setup (3)
### `onboarding`
- **Purpose** — Multi-step wizard chaining profile → personalization → first-post as one guided flow for brand-new installs, with an "already onboarded" short-circuit.
- **Overlap with siblings**`setup` (Phase 2 is a condensed `setup`) and `first-post`/`profile` (Phases 1 and 3 route to them). Subsumption test (calibration case f): does `setup` + `first-post` subsume `onboarding`? **No.** `onboarding` uniquely provides the *cohesive single path* ("a single guided path instead of navigating 27 commands") and the cross-phase state logic (already-onboarded detection, score-gated branching, "what's next — your first week"). Notably it does NOT invoke the sub-commands directly — it tells the user to run them — so it is an orchestration/triage layer, not a duplicate of their bodies.
- **Invocation leverage** — Moderate; trigger set heavily overlaps `first-post` and `setup` ("get started", "just installed", "walk me through"). The router lists it first. Real risk: a "get started" user could land on `first-post` instead — but the intent ("walk me through *everything*") is distinct from "help me publish my first post".
- **Recommendation** — **keep.**
- **Rationale** — Unique cohesive-wizard surface + cross-phase triage state; it orchestrates rather than duplicates `setup`/`first-post`. No subsumption.
### `setup`
- **Purpose** — Guided personalization: computes the 8-category personalization score and runs 6 sub-workflows (voice samples → `voice-trainer`, case study, framework, post analysis, demographics, user profile) to populate asset templates.
- **Overlap with siblings**`onboarding` Phase 2 (a 2-category condensation of this). Subsumption test: `onboarding` only ever touches the top-2 weighted categories and explicitly defers ("I'll run `/linkedin:setup` for the full setup"); `setup` owns all 8 categories, the full score dashboard, and the `voice-trainer` delegation. `onboarding` does not subsume it.
- **Invocation leverage** — High; broad trigger set ("setup", "personalize", "personalization score", "configure plugin", "my score", "fill in assets"). Also the router's destination for any score/asset-completeness query.
- **Recommendation** — **keep.**
- **Rationale** — The canonical, full-depth personalization surface; `onboarding`'s version is a deliberate condensation that defers back here.
### `first-post`
- **Purpose** — First-post accelerator: maximum hand-holding, voice quick-check, simple topic pick, 3-line draft (reuses `quick`'s formula), 4-item quality check, sets `first_post_date`, includes a guard that redirects returning users to `post`/`quick`.
- **Overlap with siblings**`quick` (whose 3-line formula it reuses) and `onboarding` Phase 3 (which routes here). Subsumption test: does `quick` subsume `first-post`? **No.** `first-post` adds first-timer-specific scaffolding `quick` lacks: the welcome/expectation framing, the voice-from-scratch setup branch (samples vs. 5 questions), the "exists > perfect" philosophy, the new-creator 90-day-boost messaging, and the returning-user guard. Its whole value is the zero-to-one onboarding hand-holding, not the drafting mechanics.
- **Invocation leverage** — Moderate; "first post", "never posted", "new to linkedin". A genuinely distinct beginner intent.
- **Recommendation** — **keep.**
- **Rationale** — Unique first-timer scaffolding + the `first_post_date` side-effect; not subsumed by `quick`'s formula it borrows.
---
## Group E — Scheduling / publishing / post-publish (3)
### `batch`
- **Purpose** — Create a full week (35 posts) in one session from a theme/pillar: trend-spotter angles, `content-planner` plan, scheduling, draft files, queue entries, and a generated `.ics`.
- **Overlap with siblings**`pipeline` (single post + schedule), `calendar` (queue management). Subsumption test: `batch` uniquely produces a *multi-post balanced week* with format/pillar rotation and `.ics` export; `pipeline` is single-post; `calendar` only manages an existing queue. No subsumption.
- **Invocation leverage** — High and specific: "batch content", "week of posts", "sunday prep". Distinct planning intent.
- **Recommendation** — **keep.**
- **Rationale** — Unique multi-post-week surface + iCal generation; the queue-write overlap with `calendar`/`pipeline` is shared *plumbing* (`queue-manager.mjs`), not a shared *surface*.
### `calendar`
- **Purpose** — View/manage the 14-day queue (reschedule/cancel/view-draft) AND host the **publish action** (mark-as-published → update queue+state → first-hour plan). Absorbed the former `publish` command (v2.0.0).
- **Overlap with siblings**`firsthour` (its publish flow ends with a first-hour plan; `firsthour` is a richer standalone version), `pipeline`/`batch` (which write to the queue it reads). Subsumption test (calibration case d): does `calendar`'s publish action subsume `firsthour`? **No**`calendar`'s first-hour block is a static 6-line checklist + an optional `post-feedback-monitor` hand-off; `firsthour` builds a *worked, timestamped plan with named targets and draft comments* via `engagement-coach`. Conversely `firsthour` does not manage the queue. No subsumption.
- **Invocation leverage** — Very high; very broad trigger set spanning both calendar ("schedule", "queue", "upcoming") and publish ("mark as published", "just published", "post is live"). High-traffic.
- **Recommendation** — **keep.**
- **Rationale** — Canonical queue+publish surface that already absorbed `publish`; its first-hour checklist is a lightweight in-flow nudge, distinct from `firsthour`'s full sprint planner.
### `firsthour`
- **Purpose** — Post-publish first-hour / reply-loop sprint: delegates to `engagement-coach` for a timestamped target list (whales/inner-circle/ICP), draft self-comments + CEA replies in voice, a minute-by-minute timeline; persists via `recordFirstHourPlan`; hands off to `post-feedback-monitor`.
- **Overlap with siblings**`calendar`'s publish-action first-hour block, and the `engagement-coach` / `post-feedback-monitor` agents it delegates to. Subsumption test (calibration case d): `firsthour` is the orphan-wiring command for `engagement-coach` (its raison d'être per CLAUDE.md/README). It uniquely produces a *worked* plan (named targets + draft comments + clipboard copy + state persistence) that neither `calendar` (static checklist) nor `post-feedback-monitor` (48h monitoring, different time window) provides. The three form a relay (firsthour → coach for the plan → feedback-monitor for the marathon), not a redundancy.
- **Invocation leverage** — Moderate; "first hour", "I just posted", "reply loop", "work my post". A real, frequently-recurring moment (every publish), but its trigger phrases partly collide with `calendar`'s "just published". Some users will reach the lighter `calendar` first-hour block instead of `firsthour`.
- **Recommendation****keep** (with a note).
- **Rationale** — Distinct worked-plan surface + it is the wiring point for an otherwise-orphaned agent (`engagement-coach`); cutting it would re-orphan that agent and undo a core v4.0.0 remediation goal. Note for the operator: the trigger overlap with `calendar`'s publish action means the two should cross-link (calendar's first-hour block could point to `/linkedin:firsthour` for the full plan) — a wiring nit, not a merge.
---
## Group F — Analytics (5)
### `analyze`
- **Purpose** — Performance *troubleshooting/diagnosis*: 6-symptom intake → diagnostic patterns → penalty checklist → severity assessment → 14-day recovery protocol. Optionally grounds in `analytics-interpreter` (interpret mode).
- **Overlap with siblings**`audit`, `report`, `import` (calibration case h). Subsumption test: `analyze` is the only *diagnostic/recovery* surface (why is reach down, how do I recover). `report` is *reporting* (weekly numbers from imported data); `audit` is *strategy review* (quarterly top/bottom posts, topic mix); `import` is *ingestion*. Four different jobs on the analytics axis — none subsumes another; `analyze` even works with no imported data (self-report intake).
- **Invocation leverage** — High and distinct: "why isn't my content performing", "low reach", "reach dropped". A panic-moment intent users type directly.
- **Recommendation** — **keep.**
- **Rationale** — Unique troubleshooting/recovery surface; orthogonal to the other three analytics commands.
### `audit`
- **Purpose** — Periodic (quarterly) content-strategy audit: top/bottom performers, topic distribution vs. pillars, format mix, engagement trend, milestone progress, profile alignment — then routes the *fix* to `strategy` and the *profile deep-audit* to `profile`.
- **Overlap with siblings**`analyze` (diagnosis), `report` (metrics), `strategy`/`profile` (which it explicitly defers to). Subsumption test: `audit` is the only *holistic strategy-review* surface (90-day lookback across topic/format/trajectory). It deliberately does NOT own trajectory prescription (delegates to `strategy`) or profile checklist (delegates to `profile`) — "audit names the gap; strategy prescribes the fix." That self-limiting design means it does not duplicate them; and `report`/`analyze` don't do the strategy lookback. No subsumption.
- **Invocation leverage** — Moderate; "content audit", "quarterly review", "review my content strategy". A periodic, distinct intent.
- **Recommendation** — **keep.**
- **Rationale** — Unique holistic-review surface with clean delegation boundaries to `strategy`/`profile`; not a duplicate of `analyze`/`report`.
### `import`
- **Purpose** — Ingest a LinkedIn analytics CSV (auto-detect from ~/Downloads, quick-import helper, the analytics-CLI npm-install fix), parse → JSON → anomaly detection → baseline update, then **delegates the analysis fan-out to `/linkedin:report`** (one analysis pipeline, not two).
- **Overlap with siblings**`report` (which it now calls rather than re-implements). Subsumption test: `import` uniquely owns *data ingestion* (CSV detection, copy-to-exports, CLI invocation, baseline creation); `report` owns *presentation* of already-imported data. The Step 6 hand-off is the explicit de-duplication ("keeping a second analysis pipeline here drifted out of sync"). Clean separation — no subsumption, and a redundancy already removed.
- **Invocation leverage** — Moderate; "import analytics", "import CSV", "parse LinkedIn data". A distinct mechanical intent (you must import before you can report).
- **Recommendation** — **keep.**
- **Rationale** — Unique ingestion surface; the analysis overlap with `report` was already collapsed (delegation), which is exactly the discipline this audit endorses.
### `report`
- **Purpose** — Generate weekly/monthly/heatmap performance reports from imported data via the `trends` CLI: metrics table, top performers, 4-week trend, alert detection, `analytics-interpreter` (report mode) recommendations, markdown export.
- **Overlap with siblings**`import` (which delegates *to* it), `analyze` (troubleshooting), `audit` (strategy review). Subsumption test: `report` is the only *recurring-numbers reporting* surface and the shared analysis engine `import` reuses. It does not diagnose recovery (`analyze`) or run the quarterly strategy lookback (`audit`). No subsumption.
- **Invocation leverage** — High and distinct: "weekly report", "performance report", "how did I do", "show my stats". Recurring intent.
- **Recommendation** — **keep.**
- **Rationale** — Canonical reporting engine, now the single analysis pipeline both it and `import` use; distinct from `analyze`/`audit`.
### `ab-test`
- **Purpose** — Full A/B testing lifecycle (design → log → analyze → history → suggest) with a directional-not-significant statistical honesty layer; delegates optimized-variant rewrites to `content-optimizer`.
- **Overlap with siblings**`report`/`analyze` (it cross-references analytics data; offers "View weekly performance report"). Subsumption test: `ab-test` uniquely owns the *experiment* surface (hypothesis, variant design, running comparison, verdict heuristic). No other command designs or tracks experiments; it merely *reads* analytics for cross-reference. No subsumption.
- **Invocation leverage** — Moderate-to-high; specific trigger set ("A/B test", "test my hooks", "compare formats", "split test", "which hook works"). Distinct, directly-typed intent.
- **Recommendation** — **keep.**
- **Rationale** — Entirely unique experimentation surface; the analytics commands it links to don't touch experiments.
---
## Group G — Growth / strategy (2)
### `strategy`
- **Purpose** — Phase-based growth plan (Phase 04 by follower count) + trajectory overlay + authority-building/signature-content compounding (Phase 2+). The canonical trajectory source `audit` defers to. Absorbed the former `authority` command (v2.0.0).
- **Overlap with siblings**`audit` (names the gap, routes here for the fix), `profile` (which `strategy` defers to for profile-alignment), `monetize` (Phase 3+ monetization setup is mentioned but not owned here). Subsumption test: `strategy` uniquely owns the phase roadmap + trajectory prescription + authority compounding. It explicitly delegates profile to `profile`. No subsumption.
- **Invocation leverage** — High; very broad trigger set ("growth plan", "build authority", "signature content", "linkedin roadmap", "my best content"). Also the router's destination for milestone/follower-progress and the below-1K nudge target.
- **Recommendation** — **keep.**
- **Rationale** — Deep, canonical growth+authority surface that absorbed `authority`; the hub other commands (`audit`, the 1K-gated ones) route toward.
### `profile`
- **Purpose** — The canonical profile/topic-relevance optimization checklist (7 sections: Headline/About/Experience/Featured/Skills/Network/Engagement) for the 2026 relevance model + the profile-SEO/search-surface layer. The single source `analyze`, `audit`, and `strategy` all defer to.
- **Overlap with siblings**`analyze` (Step 6 "If Profile-Content Mismatch" routes here), `audit` (Step 6 routes here), `strategy` (authority audit defers profile signals here). Subsumption test: `profile` is explicitly the *canonical* profile audit — three siblings delegate to it rather than duplicate it. None subsumes it; it subsumes none of them (no content/analytics/growth surface). This is textbook clean delegation.
- **Invocation leverage** — High and specific: "optimize profile", "profile audit", "fix my profile", "why is my reach low" (profile angle). Distinct, directly-typed intent.
- **Recommendation** — **keep.**
- **Rationale** — The single profile source-of-truth that three other commands point to; cutting/merging it would scatter the checklist they deliberately centralized.
---
## Group H — Gated at ~1K followers (3)
### `monetize`
- **Purpose** — Monetization strategy: readiness scorecard, 4 stage-specific plans, lead-magnet blueprint, 4-week funnel, DM conversion workflow, CTA optimization, featured-section + revenue-model worksheets. Soft-gated at ~1K.
- **Overlap with siblings**`strategy` (growth phases overlap the monetization stages; `strategy` Phase 3 mentions "lead magnets and monetization setup"), `outreach` (both 1K-gated revenue/opportunity surfaces). Subsumption test: `monetize` uniquely owns the *revenue mechanics* (pricing, offers, funnels, lead magnets, DM conversion). `strategy` only *mentions* monetization as a Phase 3+ focus area; it does not build a funnel or price an offer. `outreach` is collaborations/speaking, not products/funnels. No subsumption.
- **Invocation leverage** — Moderate; specific ("monetize", "lead generation", "consulting pipeline", "pricing strategy", "lead magnet"). Soft-gated, so naturally lower-frequency until the audience exists.
- **Recommendation** — **keep.**
- **Rationale** — Deep, unique revenue-mechanics surface; `strategy`'s monetization mention is a pointer, not a duplicate. The soft-gating is honest (works at any count, value compounds at 1K).
### `outreach`
- **Purpose** — Two-track orchestrator (collaborations + speaking) under one pitch paradigm: readiness, partner/event search + scoring, 12 collab formats + 4 talk templates, outreach messages, co-creation workflow + speaker portfolio, pipeline trackers (now state-persisted via `recordOutreachContact`), progression ladders. Absorbed the former `collab` + `speaking` commands (v2.0.0). Delegates to `network-builder`.
- **Overlap with siblings**`monetize` (both 1K-gated), `strategy` (Phase 2+ collaborations). Subsumption test: `outreach` uniquely owns the partner/event pitch machinery. `strategy` only *names* collaborations as a focus area; `monetize` is products not partnerships. No subsumption. Internally it consolidated two commands and has an explicit capability checklist proving nothing was lost in that merge — a model of disciplined consolidation.
- **Invocation leverage** — Moderate; very broad trigger set spanning both tracks ("collaboration", "co-author", "speaking", "CFP", "pitch a talk", "outreach"). Soft-gated.
- **Recommendation** — **keep.**
- **Rationale** — Unique, deep two-track outreach surface that already consolidated `collab`+`speaking` cleanly; not subsumed.
### `competitive`
- **Purpose** — Competitive analysis of niche thought leaders: identify competitors (WebSearch), content/hook/engagement analysis, landscape map, gap analysis, differentiation strategy, inspired-not-copied takeaways.
- **Overlap with siblings**`strategy` (differentiation is a growth lever there), `audit` (analyzes *your* content; this analyzes *others'*). Subsumption test: `competitive` is the only *external/competitor-facing* analysis surface. `audit` is inward-facing; `strategy` prescribes *your* plan, not a competitor scan. No subsumption.
- **Invocation leverage** — Low-to-moderate; specific ("competitive analysis", "analyze competitor", "what are others doing", "learn from others"). A periodic, distinct intent. CLAUDE.md/README describe it as 1K-gated in the same breath as monetize/outreach, though the file itself carries no gating logic.
- **Recommendation****keep** (with a minor honesty note).
- **Rationale** — Unique outward-facing competitive surface; nothing else scans competitors. Note: the router does not actually list `competitive` under the 1K-gated group nor apply the below-1K nudge to it (unlike `monetize`/`outreach`), and the command body has no follower check — a small documentation-vs-behavior inconsistency for the operator to reconcile, not a reason to merge or cut.
---
## Summary table
| Command | Recommendation | Merge target | One-line reason |
|---------|---------------|--------------|-----------------|
| `linkedin` | keep | — | Structural router; highest-leverage front door (minor map-staleness nit). |
| `post` | keep | — | Canonical long-band creation + refine/optimizer surface; core entry. |
| `quick` | keep | — | Unique short-band + the 8-template library `templates` folded into. |
| `react` | keep | — | Unique URL-ingestion + multi-source synthesis; directly-typed intent. |
| `pipeline` | keep (flag) | — | No clean subsumption, but a thin re-statement of `post`+`calendar`+`firsthour`; watch for erosion. |
| `carousel` | keep | — | Deep unique carousel/document engine + image generation. |
| `video` | keep | — | Unique LinkedIn-native video scripting + `video-scripter`. |
| `multiplatform` | keep (flag) | — | Unique Twitter/X + cross-platform surface; thinnest command, develop-candidate (could wire `content-repurposer`). |
| `newsletter` | keep | — | The long-form spine; everything long-form routes here. |
| `headless-review` | keep | — | Unique fresh-session cold-isolation a `newsletter` phase can't provide. |
| `pivot` | keep | — | Unique re-open state surgery `newsletter` delegates out. |
| `onboarding` | keep | — | Unique cohesive wizard + cross-phase triage; orchestrates, not duplicates. |
| `setup` | keep | — | Canonical full 8-category personalization; `onboarding` defers here. |
| `first-post` | keep | — | Unique first-timer scaffolding + `first_post_date` side-effect. |
| `batch` | keep | — | Unique multi-post-week + iCal; queue-write is shared plumbing. |
| `calendar` | keep | — | Canonical queue + publish action (absorbed `publish`). |
| `firsthour` | keep (note) | — | Unique worked first-hour plan; wiring point for orphaned `engagement-coach`. |
| `analyze` | keep | — | Unique troubleshooting/recovery surface; works without imported data. |
| `audit` | keep | — | Unique holistic strategy review; delegates fix to `strategy`/`profile`. |
| `import` | keep | — | Unique ingestion surface; analysis already delegated to `report`. |
| `report` | keep | — | Canonical reporting engine + shared analysis pipeline. |
| `ab-test` | keep | — | Entirely unique experimentation lifecycle. |
| `strategy` | keep | — | Canonical phase+trajectory+authority hub (absorbed `authority`). |
| `profile` | keep | — | Single profile source-of-truth three commands delegate to. |
| `monetize` | keep | — | Unique revenue-mechanics surface; honest soft-gating. |
| `outreach` | keep | — | Unique two-track pitch surface (absorbed `collab`+`speaking`). |
| `competitive` | keep (note) | — | Unique outward competitor scan; minor gating doc-vs-behavior nit. |
**Tally: keep 27 · merge 0 · cut 0.** Two keeps carry a flag — `pipeline` (inconclusive, retained) and `multiplatform` (develop-candidate).
---
## Count-impact summary (if every recommendation were applied as-is)
Every recommendation is **keep**. Therefore, if all were applied:
- **Commands removed:** 0 (0 cut + 0 merged-away).
- **Resulting count:** **27** — unchanged.
- **Lint / roster surfaces needing update:** **none.** `EXPECT_COMMANDS=27` in
`scripts/test-runner.sh` stays as-is; the CLAUDE.md command table (27), the
README command table, the `commands` header the lint checks, the router
`commands/linkedin.md`, and any SKILL roster all remain at 27. No roster
touched, no count contract changed.
This mirrors the agent-overlap outcome in `overlap-measurement.md` (no agent
trimmed → 19/27 baseline unchanged): the command surface, audited under the same
subsumption discipline, also holds — every command has a unique surface or a
justified redundancy, and the two prior consolidations (`templates`/`publish`/
`authority`/`collab`/`speaking``quick`/`calendar`/`strategy`/`outreach`, and
the `import``report` analysis delegation) have already removed the genuine
duplications. The surface is over-grown only in *count*, not in *redundancy*.
The recommendations are informational; the operator decides per command. Two
non-blocking honesty nits surfaced along the way (each a wiring/doc fix, not a
merge/cut; a claimed third was withdrawn on verification):
1. The router lists `post-feedback-monitor` (agent) under Post-Publish but not the
new `/linkedin:firsthour` command.
2. `calendar`'s publish-action first-hour block and `firsthour` share trigger
phrases ("just published") and should cross-link.
3. ~~`competitive` 1K-gating doc-vs-behavior.~~ **Withdrawn on verification:**
CLAUDE.md `:64`, README `:222`, the router, and the command body all leave
`competitive` ungated — only `monetize`/`outreach` carry "(unlocks at ~1K)".
No inconsistency exists; the claimed nit was unfounded.
---
## Honest-uncertainty list (inconclusive — retain pending operator view)
- **`pipeline`** — *inconclusive, retained.* It has no clean subsumption (it
uniquely *sequences* draft → schedule → first-hour → analysis into one guided
run), which under the trim rule mandates retention. But its constituent steps
are each a thinner inline condensation of richer leaf commands
(`post` / `calendar` / `firsthour`), and its trigger set is narrow/jargon-y, so
its real-world leverage as a *natural type* is the weakest in Group B. I could
not decide whether the orchestration value justifies the standalone command
versus folding its unique sequencing into `post` (with an explicit
schedule + first-hour hand-off). Per the methodology: **inconclusive — retain
pending operator view.** This is the one command where a future, operator-blessed
merge could be defensible; the evidence informs but does not compel it.
All other 26 commands are clear **keep** decisions with no residual uncertainty.

View file

@ -47,6 +47,21 @@ S17 (C13C46 triage) → ALLOW [process complete]
## S14 — Command rationalization (re-opens the original command-surface Non-Goal) ## S14 — Command rationalization (re-opens the original command-surface Non-Goal)
*Analysis → operator decision → execute. Nothing deleted without explicit per-command yes.* *Analysis → operator decision → execute. Nothing deleted without explicit per-command yes.*
> **AMENDMENT — S14 reframed by operator decision (2026-05-30): merge/cut → journey layer.**
> 14a's cold per-command review (`command-rationalization.md`) found **zero redundancy**
> no command is a defensible merge/cut candidate (the two prior consolidations already
> removed the genuine overlaps). So instead of cutting, the operator chose to **add a
> journey layer over the kept atomics**. The build contract is
> **`journey-layer-design.md`** (this supersedes the 14b/14c "execute merges/cuts" bullets
> below — there are none to execute). **Delivered:** two new guided front-doors
> (`/linkedin:create`, `/linkedin:measure`) + the router re-tiered into five journeys
> (Start · Create · Engage · Measure · Grow) + `onboarding`/`strategy` elevated as the
> Start/Grow front-doors; the 27 atomic commands kept; **27 → 29 commands; v4.0.0 → v4.1.0
> (minor/additive)**. The two 14a honesty nits real on verification were fixed (router lists
> `firsthour`; `calendar` cross-links to it); a third (a `competitive` 1K-gating claim) was
> withdrawn as unfounded. The **gate is unchanged**: `test-runner.sh` + `node --test` green
> → `/trekreview` **ALLOW** (no WARN-override) → commit own files → push.
- **14a Analysis (no edits):** cold per-command review of all 27 → `docs/remediation/command-rationalization.md`. - **14a Analysis (no edits):** cold per-command review of all 27 → `docs/remediation/command-rationalization.md`.
Per command: purpose · overlap with siblings · invocation leverage (algorithmic + likely use) · Per command: purpose · overlap with siblings · invocation leverage (algorithmic + likely use) ·
recommendation **keep / develop / merge→X / cut** + rationale. Delegate the cold read to an recommendation **keep / develop / merge→X / cut** + rationale. Delegate the cold read to an

View file

@ -0,0 +1,154 @@
# LinkedIn Studio — Journey-Layer Design (S14)
> **Supersedes the S14 "merge/cut" framing.** 14a's cold review found 27 commands
> with **zero redundancy** (subsumption fails pairwise) — the surface is over-grown
> in *count*, not in *redundancy*. The operator therefore reframed S14 from
> "rationalize by cutting" to "**add a journey layer over the kept atomics**." This
> doc is the build contract. It also **absorbs S15's router-tiering** (finish-plan
> B2) — the router is re-tiered here, journey-style, so S15 collapses into S14.
## Decisions locked (operator, 2026-05-30)
1. **Architecture = journey layer.** Keep all 27 atomic commands as the *execution
tier*; add journey *front-door* orchestrators as the *primary surface*; subagents
remain the engine (no Workflow-tool / deep-research adoption — both are wrong-fit
for an everyday product surface, see the session reasoning).
2. **Realization = 2 new + 2 elevated.** Add `create` + `measure` as new front-doors;
elevate existing `onboarding` (Start) and `strategy` (Grow); **Engage** stays a
router-tier relay (`calendar` + `firsthour`), no front-door. Atomics → "advanced"
tier under each journey.
3. **Version = v4.1.0 (minor), NOT v5.0.0.** Honest SemVer: this is additive (2 new
commands) + presentation (router retier) + one tiny doc-vs-behavior reconcile
(`competitive`). No removal, rename, or behavior break on existing commands.
Precedent: v3.1.0 added 3 agents as a MINOR with a "reload required" note — same
shape. Reload note applies (the 2 new commands register at session reload).
## Journey taxonomy (5 journeys + router)
`Improve` is **not** a separate journey: improving is the action *after* measuring
(audit→fix, ab-test, `content-optimizer`), not a distinct entry. The operator's
"Improve + Analyze" is therefore folded into **Measure** (the measure→optimize loop).
| Journey | Front-door | Atomics (advanced tier) |
|---------|-----------|--------------------------|
| **Start** | `onboarding` *(elevate — exists)* | setup · first-post |
| **Create** | **`create`** *(NEW)* | post · quick · react · carousel · video · multiplatform · batch · newsletter · pivot · headless-review · pipeline |
| **Engage** | *(router-tier — relay, no front-door)* | calendar · firsthour |
| **Measure** | **`measure`** *(NEW — `analyze` name is taken, so no collision)* | import · report · analyze · audit · ab-test |
| **Grow** | `strategy` *(elevate — exists)* | profile · competitive · monetize ⚿ · outreach ⚿ |
| *(map)* | `linkedin` router | — |
⚿ = unlocks/soft-gates at ~1K followers. Count: Start 3 + Create 11 + Engage 2 +
Measure 5 + Grow 5 + router 1 = **27 atomics** + **2 new front-doors** = **29**.
## The two new front-door commands
Both are **thin guided routers** — they add *navigation* (a single "what do you
want?" entry), not duplicated logic. They **delegate** to the atomic that owns the
work. No drafting/analysis logic is copied into them.
### `commands/create.md` — Content-creation front-door
- **Purpose:** one guided entry for "make something" when the user hasn't already
named the format.
- **Flow:** `AskUserQuestion` "What do you want to create?" →
- Short substantial post → `post`
- Quick 5-min post → `quick`
- React to a URL / article / news → `react`
- Carousel / document → `carousel`
- Video script → `video`
- Adapt for another platform → `multiplatform`
- A full week (batch) → `batch`
- Long-form / newsletter / essay → `newsletter`
- Then hand off to the chosen command (it owns the work).
- **Triggers (undirected create intent only — must NOT steal `post`/`quick` direct
intent):** "create", "make something", "create content", "what should I make",
"new content", "help me create", "linkedin create".
- **allowed-tools:** Read, Glob, AskUserQuestion. **No Write** (it delegates).
### `commands/measure.md` — Performance/insight front-door
- **Purpose:** one guided entry for "understand how I'm doing."
- **Flow:** `AskUserQuestion` "What do you want to do?" →
- Import a new analytics CSV → `import`
- Weekly / monthly report → `report`
- Diagnose a problem (reach dropped, low engagement) → `analyze`
- Quarterly strategy audit → `audit`
- Design / review an A/B test → `ab-test`
- Then hand off to the chosen command.
- **Triggers (undirected measure intent):** "measure", "how am I doing", "my
performance", "show my analytics", "performance overview", "linkedin measure".
- **allowed-tools:** Read, Glob, AskUserQuestion. **No Write** (it delegates).
## Elevation (2) — presentation only, no behavior change
- **`onboarding` = Start front-door.** Already the cohesive wizard. Router presents
it as the Start journey entry; body unchanged (optional one-line "Start journey"
framing only).
- **`strategy` = Grow front-door.** Already the phase/trajectory/authority hub.
Router presents it as the Grow journey entry; body unchanged.
## Router re-tiering (`commands/linkedin.md`) — absorbs S15 B2
Restructure the menu into the 5 journeys, each headed by its front-door with the
atomics listed beneath as "also / advanced":
- **Start**`onboarding` · setup · first-post
- **Create**`create` · post · quick · react · carousel · video · multiplatform · batch · newsletter · pivot · headless-review · pipeline
- **Engage** → calendar · firsthour *(tier, no front-door)*
- **Measure**`measure` · import · report · analyze · audit · ab-test
- **Grow**`strategy` · profile · competitive · monetize ⚿ · outreach ⚿
- Keep the status line (weekly progress / streak / follower phase) + queue summary.
- **Fixes nit #1:** `/linkedin:firsthour` is now listed (under Engage) — the router
previously listed only the `post-feedback-monitor` agent there.
## Honesty nits fixed in lockstep (from 14a)
1. **Router omits `firsthour`** → fixed by the retier (Engage tier lists it).
2. **`calendar``firsthour` trigger overlap** → `calendar.md`'s publish-action
first-hour block gets a one-line cross-link: "for the full worked sprint plan,
run `/linkedin:firsthour`."
3. **`competitive` gating doc-vs-behavior** → **14a's nit was unfounded** (verified
against the files: CLAUDE.md `:64`, README `:222`, the router, and the command body
all leave `competitive` **ungated** — only `monetize`/`outreach` carry "(unlocks at
~1K)"). There is no inconsistency to fix. Competitive analysis helps at any stage
(especially early positioning), so it stays ungated. Action: place it in the Grow
tier marked **"Any phase"** (no ⚿), and add a one-line note to the router's gating
rule that `competitive` is explicitly not gated. (An interim router edit that
mistakenly added a ~1K marker was reverted in the same pass.)
## 14a doc correction (`command-rationalization.md`)
- Add the missing **`multiplatform`** entry: **keep** (unique Twitter/X-thread +
cross-platform surface; subsumption fails as a cut), flagged **thinnest /
develop-candidate** (only command that inlines static templates instead of
delegating — could use `content-repurposer`). Belongs in **Create**.
- Fix the two header-count typos (Group C "(4)"→3; Group F "(4)"→5).
- Corrected tally: **keep 27 (27/27 covered)** · 0 merge · 0 cut · 1 develop-candidate.
## Count / version / roster lockstep (the release mechanics)
- `scripts/test-runner.sh`: `EXPECT_COMMANDS` **27 → 29**.
- Version **4.0.0 → 4.1.0** everywhere it appears (version-sync rule: grep both
`4.0.0` and the `27`-count claims).
- Three-doc rule (same commit / immediately after):
- `CLAUDE.md` (plugin): command table +2 rows, count 27→29, version, v4.1.0 para.
- `README.md` (plugin): command table, count, version, CHANGELOG entry.
- Root `README.md` (marketplace): the linkedin-studio line.
- Also: `CHANGELOG.md` if present; any SKILL roster enumerating commands; the router
roster (done above); `STATE.md` count block (27→29, version 4.1.0).
## Verification (testable — gate before push)
- `ls commands/*.md | wc -l` == **29**.
- `bash scripts/test-runner.sh` exit **0** (EXPECT_COMMANDS=29; stat/version/model
consistency + render-chain + $-safety guards all green).
- `node --test hooks/scripts/__tests__/*.test.mjs` — all pass (no hook logic touched
→ expect the existing **98**).
- `grep -rn "4\.0\.0\|27 command" commands README.md CLAUDE.md` (user-facing) → 0
stale hits (historical CHANGELOG mentions allowed).
- Router renders 5 journeys; primary tier = the 5 front-doors (`create`, `measure`,
`onboarding`, `strategy` + Engage tier); atomics nested; 1K-gated flagged;
`firsthour` present.
- `create` / `measure`: valid frontmatter, `AskUserQuestion` routing, **delegate
only** (grep shows no inlined drafting/analysis logic, no `Write` in create/measure).
- `/trekreview --project docs/remediation/`**ALLOW** (no WARN-override) → commit
(own files only) → push origin.
## Out of scope (this session / S14)
- Aggressive consolidation / folding atomics (operator chose keep-all).
- Building the `multiplatform` "develop" (content-repurposer wiring) — recorded as a
keep + develop-candidate, not built unless requested.
- S16 (saves) / S17 (C13C46) — later finish-plan steps.
- UI-brief M0 (move mutable data out of tree) — pending; conflicts with S16, not S14.

View file

@ -1,13 +1,13 @@
--- ---
type: trekreview type: trekreview
review_version: "1.0" review_version: "1.0"
task: "Remediate linkedin-studio from the baseline audit — correctness, honesty, generalization, and the highest-leverage 2026 coverage gaps (full Phase 03 roadmap, phased)" task: "S14 — journey layer over the LinkedIn Studio command surface (operator-reframed from merge/cut after 14a found zero redundancy)"
slug: remediation slug: remediation
project_dir: docs/remediation/ project_dir: docs/remediation/
brief_path: docs/remediation/brief.md brief_path: docs/remediation/brief.md
scope_sha_start: c5b4c58f4f390aca83c8937880c5fd0bcc983e44 scope_sha_start: 431a893
scope_sha_end: 36f79dd702b9315a0cd9100c3a8dd6dd81b3797f scope_sha_end: 431a893
reviewed_files_count: 50 reviewed_files_count: 15
verdict: ALLOW verdict: ALLOW
mode: default mode: default
effort: high effort: high
@ -15,152 +15,132 @@ profile: premium
findings: [] findings: []
--- ---
# Review — linkedin-studio audit-remediation (S13 re-review: `$`-class closure + scalar-test fix) # Review — linkedin-studio S14 (journey layer; merge/cut → add a layer)
## Executive Summary ## Executive Summary
**Verdict: ALLOW** — 0 BLOCKER, 0 MAJOR, 0 MINOR, 0 SUGGESTION. **Verdict: ALLOW** (post-remediation) — 0 BLOCKER, 0 MAJOR, 0 MINOR, 0 SUGGESTION open.
Two independent reviewers (brief-conformance, code-correctness) ran COLD, high-effort,
without cross-feeding, on the as-delivered uncommitted working tree (HEAD `431a893` +
the S14 delta). **Each returned 2 MAJOR findings; deduped to 3 distinct issues.** All
three were **remediated in-session** with deterministic re-verification; the final
state that pushes is clean.
This is the **S13 re-review** — the **seventh** full-brief sweep S14 was **reframed by operator decision (2026-05-30)**: 14a's cold per-command review
(`c5b4c58..36f79dd` + the uncommitted S13 working-tree delta), run COLD and (`command-rationalization.md`) found **zero redundancy** across the 27 commands (no
high-effort. S13 was commissioned to close the two findings the S12 re-review defensible merge/cut), so instead of cutting, a **journey layer** was added over the
left open (verdict WARN, 0/1/1/0): the MAJOR `MISSING_TEST` (the S12 `$`-bearing kept atomics. Build contract: `journey-layer-design.md`. Delivered: two new
test asserted the Recent Posts section but never the `last_post_topic` scalar, so delegate-only front-doors (`/linkedin:create`, `/linkedin:measure`), the router
the corruption shipped green) and the MINOR `MISSING_ERROR_HANDLING` (the re-tiered into five journeys (Start · Create · Engage · Measure · Grow), `onboarding`/
`last_post_topic` scalar was still `$`-unsafe because `replaceField` used a `strategy` elevated as the Start/Grow front-doors; 27 → 29 commands; v4.0.0 → v4.1.0
replacement *string* for untrusted content). Two independent reviewers (minor/additive). Two of 14a's honesty nits (router lists `firsthour`; `calendar`
(brief-conformance, code-correctness) ran without cross-feeding; the coordinator cross-links to it) were real and fixed; a third (a `competitive` 1K-gating claim) was
applied bounded dedup + the HubSpot Judge filters + verdict (high-effort → withdrawn as unfounded on verification.
Cloudflare reasonableness filter skipped; the operator weighs borderline findings).
**Both reviewers returned empty finding sets.**
**Both S12 findings are CLOSED at the reviewed (uncommitted) state:** **What both reviewers confirmed conformant + correct** (the bulk of the delivery):
- `replaceField` (`hooks/scripts/state-updater.mjs:14-24`) now uses a replacement the two front-doors are delegate-only (no `Write`; route to the contracted targets);
**function** (`() => \`${field}: ${value}\``), so the untrusted `last_post_topic` the router re-tier preserves **reachability for all 29 commands** (no atomic dropped;
at the `:64`-equivalent call site is inserted verbatim — no `$&`/`$1`/`` $` `` `post-feedback-monitor` still mentioned in prose, not orphaned); `EXPECT_COMMANDS`
expansion. The MINOR is closed. 27→29 + `## Commands (29)` + `ls`=29 agree; version 4.1.0 is consistent across
- The existing `$`-bearing test (`hooks/scripts/__tests__/state-updater.test.mjs`) plugin.json / README version badge / CLAUDE.md header / CHANGELOG / root docs; SemVer
now carries `assert.match(result.content, /^last_post_topic: "\$100 budget — \$& framing is honest (additive, nothing falsely "breaking", nothing removed/renamed);
and \$1 rule"$/m, …)`, distinct from the section-entry `includes()` it already out-of-scope discipline held (no atomic folded; `multiplatform`-develop only recorded,
had. This assertion **fails on the old string-`replaceField` and passes on the not built; S16/S17/UI-brief-M0 untouched).
function form** (orchestrator-verified by reverting the fix: the test went
40 pass / 1 fail). The false-green MAJOR is closed.
**The class — not just the line — is closed.** The recurring S9→S12 lesson is
"close the class, not the line"; the class here is "untrusted user content reaching
ANY `String.replace` replacement *string*". Beyond the `replaceField` scalar, S13
also converted the three remaining additive-insert sites (`recordFirstHourPlan`
`:246`-equiv; `recordOutreachContact` `:305/:308`-equiv) from a string replacement
carrying an intentional `$1` backref + interpolated date to a replacement function
(`(m) => \`${m}\n…\``). The code-correctness reviewer verified rigorously that this
is **behavior-preserving**: each regex's capture group spans the *entire* match (the
only chars outside the group are the zero-width `^`/`$` anchors), so the full match
`m` is character-identical to the old `$1`. After S13, **every `.replace()` in
`state-updater.mjs` uses a replacement function or a `$`-free literal** — the class
is closed by construction, not by per-line patch.
**A structural guard replaces the per-line proof.** New
`scripts/check-replace-safety.mjs` (wired as `test-runner.sh` Section 12) proves the
property behaviorally: it drives every exported mutator with an adversarial payload
of every special replacement token (`$&`, `` $` ``, `$'`, `$$`, `$n`) in every
free-text *and* date field and asserts the payload survives verbatim. Two structural
backstops run on every invocation — **coverage-completeness** (a newly-exported
mutator without `$`-coverage fails the guard) and a **non-vacuity self-test** (a
naive string-replace MUST corrupt the payload and a function MUST preserve it, else a
PASS is meaningless), mirroring the Section 8/10/11 self-tests. The orchestrator
mutation-proved it end-to-end: reverting `replaceField` to a string makes the guard
exit 1 with two findings; restoring it returns exit 0.
**No Phase-03 Success Criterion regressed.** The brief-conformance reviewer traced
each S13 clause to delivered code and confirmed the counts (19 agents / 27 commands /
25 references / 6 skills), the version (4.0.0), the single-source algorithm-signal,
the model-consistency guard, and the render-chain-propagation guard all still hold;
S13 touched no command/agent/reference file. The two Non-Goals the brief amendment
re-opens (the command invocation surface for S14; saves manual-entry for S16) trace
to **explicit operator decisions** in the brief amendment, and S13 itself did not
touch either surface — no `SCOPE_CREEP_BUILT`.
**Push decision: ALLOW.** The two S12 findings are closed, the class is closed
structurally, the lint is non-vacuous and mutation-proven, all suites are green
(`scripts/test-runner.sh` → 71/0/0; `node --test` → 98/98), and no SC regressed. The
ORIGINAL remediation brief now closes clean. Per `feedback_trekreview_always_last` +
Handover 6, this review is the gate; with ALLOW, S13 may push.
## Coverage ## Coverage
Scope SHA range: `c5b4c58` (= `origin/main`, parent of remediation Steg 1) → Scope: HEAD `431a893` (S13's commit) + the **uncommitted S14 working-tree delta**
`36f79dd` (HEAD, the S12 commit) **plus the uncommitted S13 working-tree delta**
(annotated `[uncommitted]` — a brief-level contract; the brief's Assumptions allow (annotated `[uncommitted]` — a brief-level contract; the brief's Assumptions allow
uncommitted review). The committed range (47 files) was already deep-reviewed and uncommitted review). 15 files = the operator's own changes; the 3 untracked
cleared at S12 except the 2 WARN findings; the active S13 delta is the 9 working-tree not-mine files (`docs/linkedin-studio-persona-brief.md`, `…-ui-brief.md`,
files below. **No silent skips.** `docs/voyage-build/progress.json`) are explicitly excluded from scope and from the
commit. **No silent skips.**
| Treatment | Count | Notes | | Treatment | Count | Notes |
|-----------|-------|-------| |-----------|-------|-------|
| `deep-review` (hooks/** + the new guard) | 4 | `state-updater.mjs`, `state-updater.test.mjs` `[uncommitted]`; `scripts/check-replace-safety.mjs` `[uncommitted, new]`; `scripts/test-runner.sh` `[uncommitted]` | | `deep-review` | 6 | `commands/create.md` `[new]`, `commands/measure.md` `[new]`, `commands/linkedin.md` (router re-tier), `commands/calendar.md`, `scripts/test-runner.sh`, `README.md` |
| `summary-only` | 46 | the committed `c5b4c58..36f79dd` range (already cleared at S12) + the S13 doc edits `CLAUDE.md`/`README.md`/`docs/integration-test-guide.md` `[uncommitted]` + `docs/remediation/{brief.md (amendment), finish-plan.md}` `[uncommitted]` | | `summary-only` | 9 | plugin `CLAUDE.md`/`CHANGELOG.md`/`plugin.json`/`commands/onboarding.md`; root `CLAUDE.md`/`README.md`; `docs/remediation/{finish-plan.md, command-rationalization.md, journey-layer-design.md}` |
| `skip` | 0 | no lockfiles / svg / generated / dist | | `skip` | 0 | no lockfiles / svg / generated / dist |
**Cross-cutting execution criteria (run by orchestrator):** **Cross-cutting execution criteria (run by orchestrator):**
`scripts/test-runner.sh` → 71 passed / 0 failed / 0 warnings, exit 0 (was 70; `scripts/test-runner.sh`**74 passed / 0 failed / 0 warnings**, exit 0 (was 71;
+1 — Section 12 `$`-safety guard). +2 the two new commands' frontmatter checks, +1 a new README commands-badge guard,
`node --test hooks/scripts/__tests__/*.test.mjs` → 98 tests, 98 pass, 0 fail (the 1 net rounding of the count-loop — all green). `node --test …/*.test.mjs` → **98/98**
S13 scalar assertion was added to an existing test, not a new test). (no hook logic changed). `ls commands/*.md`**29**.
`node scripts/check-replace-safety.mjs` → exit 0 (8 adversarial cases / 5 mutators,
coverage-complete, self-test non-vacuous); mutation-proven (reverting the fix → exit 1).
**S12 findings — both confirmed CLOSED:**
`replaceField` (`state-updater.mjs:14-24`) → replacement function; the `$`-bearing
test now pins the `last_post_topic` scalar (`state-updater.test.mjs`); the three
remaining additive-insert string-replacements (`:246/:305/:308`) → functions; the
class is closed and guarded structurally (Section 12).
## Findings ## Findings
None. Both independent reviewers returned empty finding sets; the coordinator's **3 distinct MAJOR findings were raised by the independent reviewers and ALL closed
bounded passes (dedup, HubSpot Judge, verdict) on an empty set yield ALLOW. in-session.** No finding remains open; the trailing JSON `findings` is empty because
the pushed state carries none.
### [MAJOR — RESOLVED] README commands badge stale at `commands-27`
*Raised by both reviewers (`COUNT_DRIFT` / `SUCCESS_CRITERION_UNMET`), `README.md:11`.*
The release reconciled the version badge, intro prose, CLAUDE.md header, `EXPECT_COMMANDS`,
and rosters to 29, but the shields **commands** badge still read `commands-27-green`. It
slipped both the human pass and the gate (the version-consistency grep checks only the
*version* badge; the design-doc verification grep searched `"27 command"` with a space,
which cannot match `commands-27-green`).
**Resolution:** `README.md:11``commands-29-green`; **and** a new
`test-runner.sh` Section-2 guard now asserts the `badge/commands-${EXPECT_COMMANDS}-`
shields badge matches the contract (closing the class, not just the line — the
count-badge analogue of the existing version-badge check). Re-verified: lint 74/0/0;
`grep commands-27` → 0 hits.
### [MAJOR — RESOLVED] Router self-contradicted on `competitive` gating
*Raised by code-correctness (`INTERNAL_CONTRADICTION`), `commands/linkedin.md:140`.*
The Grow journey **table** marked `competitive` "Any phase" and the gating-rule note
said it is **not** gated, but the **"Ask the User"** menu line still rendered
`competitive ⚿` (the file's own ~1K soft-gate marker). An interim erroneous gating
(added then reverted in the same pass) had been reverted in the table + the gating note
+ the design doc, but the menu line was missed — the exact inconsistency the release
claims to fix.
**Resolution:** `commands/linkedin.md` Ask-the-User Grow line → `competitive` (no ⚿);
re-verified `grep "competitive ⚿"` → 0 hits across commands + the design doc. The router
now states competitive ungated consistently in the table, the note, and the menu.
### [MAJOR — RESOLVED] STATE.md binding count block stale at 27 / v4.0.0
*Raised by brief-conformance (`SUCCESS_CRITERION_UNMET`), `STATE.md:46`.*
The design-doc lockstep enumerates the STATE.md count block as a surface to update
(27→29, v4.1.0). `STATE.md` is **gitignored** (not part of the pushed commit, so not a
push-blocking three-doc violation), but it is a contracted lockstep item and would
mislead the next session.
**Resolution:** updated to 29 / v4.1.0 as part of the session-close STATE.md overwrite
(which also advances the pointer to S15). Not in the pushed artifact (gitignored).
## Remediation Summary ## Remediation Summary
**Gate: ALLOW.** The S12 WARN is fully resolved: the `replaceField` scalar **Gate: ALLOW (post-remediation).** Two independent high-effort reviewers found 3
`$`-corruption (MINOR) and the false-green test (MAJOR) are both closed; the distinct MAJORs — all stale-count / incomplete-revert completion-misses of THIS
`$`-injection class is closed across the whole `state-updater.mjs` mutation surface; session's own committed lockstep, none a design flaw. All three were closed in-session
and a behavioral, coverage-complete, self-testing Section-12 lint guards it with deterministic re-verification (lint 74/0/0; targeted greps → 0 residual hits); a
structurally against future regressions. All suites green; no Phase-03 SC regressed; new lint guard prevents the badge regression class from recurring. No BLOCKER; no
the two re-opened Non-Goals trace to explicit operator decisions and S13 stayed in its design or correctness defect in the journey layer itself; reachability for all 29
lane. commands preserved; SemVer honest. The pushed state is clean.
**Two non-blocking observations, recorded by both reviewers, neither rising to a Decision rationale for in-session fix (vs `feedback_trekreview_always_last`'s
catalogue finding:** fix-in-next-session): the three findings are mechanical completions of the current
1. The S13 dead binding both reviewers named (`check-replace-safety.mjs` `HERE` + task's own lockstep — #1 and #2 would have failed the design doc's own Verification
its now-unused `node:url`/`node:path` imports) was removed during this review grep, #3 is an incomplete revert — i.e. *unfinished scope of S14*, not deliberation-
pass; the guard remains green (exit 0) after removal. needing review findings. Shipping a README badge that reads "27" and a router that
2. The behavioral guard catches a new *unguarded exported mutator* (coverage self-contradicts on gating would be dishonest to the release's own claims. Closing them
backstop) but not a new unsafe `String.replace` added *inside* an existing now reaches a genuine ALLOW (not a WARN-override).
battery-covered mutator on a field the battery does not fuzz. This is a documented,
deliberate limit of the behavioral proxy (vs a per-`.replace()` AST enumeration)
and is **moot today** — every `.replace()` in `state-updater.mjs` is already a
function. Recorded as a known boundary, not a defect; closing it further is out of
S13 scope (no real `$`-unsafe site exists to catch).
The two adjacent machine-value `.replace()` sites the correctness reviewer probed — Per Handover 6, this `review.md` is consumable by `/trekplan --brief …`; with an ALLOW
`session-start.mjs:396` (`${actualWeek}`, a computed ISO week) and `week-rollover.mjs` verdict and no open findings, no follow-up plan is required — S14 may commit + push, and
(computed week / literal int) — carry no untrusted content and are therefore not the finish-plan continues at S15.
members of the defect class, consistent with how the S12 review itself classified the
date/integer `replaceField` call sites. No finding.
Per Handover 6, this `review.md` is consumable by
`/trekplan --brief docs/remediation/review.md`; the trailing JSON block is the machine
contract for that handover. With an ALLOW verdict and no BLOCKER/MAJOR findings, no
follow-up remediation plan is required — the ORIGINAL brief is closed clean and the
finish-plan continues at S14.
```json ```json
{ {
"verdict": "ALLOW", "verdict": "ALLOW",
"scope": { "sha_start": "c5b4c58f4f390aca83c8937880c5fd0bcc983e44", "sha_end": "36f79dd702b9315a0cd9100c3a8dd6dd81b3797f", "reviewed_files_count": 50, "uncommitted_delta": true }, "scope": { "sha_start": "431a893", "sha_end": "431a893", "reviewed_files_count": 15, "uncommitted_delta": true },
"counts": { "BLOCKER": 0, "MAJOR": 0, "MINOR": 0, "SUGGESTION": 0 }, "counts": { "BLOCKER": 0, "MAJOR": 0, "MINOR": 0, "SUGGESTION": 0 },
"findings": [], "findings": [],
"resolved_in_session": [
{ "severity": "MAJOR", "title": "README commands badge stale at 27", "file": "README.md", "line": 11, "rule_key": "COUNT_DRIFT", "resolution": "badge -> commands-29-green + new test-runner.sh commands-badge guard" },
{ "severity": "MAJOR", "title": "Router self-contradicts on competitive gating", "file": "commands/linkedin.md", "line": 140, "rule_key": "INTERNAL_CONTRADICTION", "resolution": "Ask-the-User Grow line competitive ⚿ -> competitive; 0 residual hits" },
{ "severity": "MAJOR", "title": "STATE.md binding count block stale at 27 / v4.0.0", "file": "STATE.md", "line": 46, "rule_key": "SUCCESS_CRITERION_UNMET", "resolution": "updated to 29 / v4.1.0 in session-close overwrite (gitignored, not pushed)" }
],
"dropped_findings": [] "dropped_findings": []
} }
``` ```

View file

@ -42,7 +42,7 @@ warn() { echo -e "${YELLOW}⚠${NC} $1"; WARN=$((WARN + 1)); }
# Source of truth: CLAUDE.md headers + STATE.md Telling. Bump these together # Source of truth: CLAUDE.md headers + STATE.md Telling. Bump these together
# with the files when adding/removing an agent, command, reference, or skill. # with the files when adding/removing an agent, command, reference, or skill.
EXPECT_AGENTS=19 EXPECT_AGENTS=19
EXPECT_COMMANDS=27 EXPECT_COMMANDS=29
EXPECT_REFS=25 EXPECT_REFS=25
EXPECT_SKILLS=6 EXPECT_SKILLS=6
@ -101,6 +101,17 @@ else
fail "CLAUDE.md commands header ($DOC_COMMANDS) != contract ($EXPECT_COMMANDS)" fail "CLAUDE.md commands header ($DOC_COMMANDS) != contract ($EXPECT_COMMANDS)"
fi fi
# README shields commands-count badge must match the contract too. Added after an
# S14 /trekreview found the badge stale at commands-27 while the surface shipped 29:
# the version-consistency grep (Section 9) checks only the version badge, and the
# count guards above check the CLAUDE.md header, so the README count badge slipped
# both. This closes that gap (the count-badge analogue of the version-badge check).
if grep -q "badge/commands-${EXPECT_COMMANDS}-" README.md; then
pass "README commands badge declares ${EXPECT_COMMANDS}"
else
fail "README commands badge != ${EXPECT_COMMANDS} (expected shields badge/commands-${EXPECT_COMMANDS}-)"
fi
echo "" echo ""
# --- Section 3: Agent Frontmatter --- # --- Section 3: Agent Frontmatter ---