From 2a27a7cd6a494d33f90683ffdab90f24a8e7dab6 Mon Sep 17 00:00:00 2001 From: Kjell Tore Guttormsen Date: Thu, 28 May 2026 10:09:47 +0200 Subject: [PATCH] =?UTF-8?q?feat(linkedin):=20v2.1.0=20=E2=80=94=20skeleton?= =?UTF-8?q?=20+=20spine-prose=20gates=20BEFORE=20prose=20in=20/linkedin:ne?= =?UTF-8?q?wsletter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two new pipeline phases gate the spine before any prose is written: - Step 2.5 — Skeleton + section pitch: writes /NN-skjelett.md with the five-line spine (premiss / problem / anbefaling / gevinst / vei videre) + one-line section pitches. Operator-gate (JA / REVIDER / NEI) AND parallel persona-skjelett-sweep must both return JA before the pipeline can advance. - Step 3a — Spine prose: one paragraph per section against the gated skeleton, ~20-30% of final edition length. Operator-gate on whether the axis lands now that there is prose on it. Old Step 3 (Draft) split into 3a (spine) and 3b (full expansion); 3b owns the multi-session draft-cursor logic. Third persona-reviewer mode added: skjelett (alongside resonans + konverter). Five spine axes scored HOLDER / TVILER / MANGLER, max 3 direction-only flags, per-pitch section-pay-in check. Reads the skeleton + pitches only. Pipeline grows from 11 to 13 phases; commands (24) and agents (14) counts unchanged. Encodes the Maskinrommet writing-contract section A discipline (premiss / problem / anbefaling / gevinst / vei videre) into the pipeline. Empirically motivated by the Seres-serien Del 3 + Del 4 production: a spine error caught at the skeleton stage costs 5-15 min, the same error caught at Step 6 (resonance) costs 4-12 h, post-lock it costs a day of cascading rework (delingstekst, hooks, carousel, doc refs). Backward-compatible: existing editions stop at currentPhase: "research" and now resume at Step 2.5 instead of Step 3 — an intended deterministic improvement, never a contract break. Steps 1, 2, 4-10 bit-for-bit unchanged. Renderers (build-html.mjs, build-linkedin.mjs) untouched. New phase strings in edition-state.template.json _doc.phases: - skeleton-pitch (between research and draft) - spine-prose (between skeleton-pitch and draft) Files changed (10): - plugin.json: 2.0.0 -> 2.1.0 - CHANGELOG.md: new [2.1.0] entry - CLAUDE.md (plugin + marketplace): pipeline 11->13 phases noted - README.md (plugin + marketplace): What's New v2.1.0 + version row - agents/persona-reviewer.md: third mode skjelett added; resonans + konverter unchanged - commands/newsletter.md: Step 2.5 + 3a + 3b sections, resumption + pipeline tables - config/edition-state.template.json: 11 -> 13 phases in _doc.phases - references/longform-quality-rules.md: Rule 8 (Skjelett foer prosa) Verification: 9/9 criteria PASS pre-commit. Phase strings consistent across template + command + resumption table. Renderer files git-untouched. All 11 original step headings preserved (Step 0/1/2/4-10). Co-Authored-By: Claude Opus 4.7 --- CLAUDE.md | 2 +- README.md | 9 +- .../.claude-plugin/plugin.json | 4 +- .../linkedin-thought-leadership/CHANGELOG.md | 24 ++ plugins/linkedin-thought-leadership/CLAUDE.md | 8 +- plugins/linkedin-thought-leadership/README.md | 24 +- .../agents/persona-reviewer.md | 259 +++++++++--- .../commands/newsletter.md | 382 +++++++++++++++--- .../config/edition-state.template.json | 4 +- .../references/longform-quality-rules.md | 32 +- 10 files changed, 611 insertions(+), 137 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 8b9a22b..4f7489d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,7 +9,7 @@ plugins/ ai-psychosis/ v1.0.0 — Interaction awareness (sycophancy, reinforcement loops) config-audit/ v3.1.0 — Configuration intelligence (health, opportunities, auto-fix, whats-active) graceful-handoff/ v2.1.0 — Auto-trigger handoff via Stop hook (skill + JSON pipeline + 4-step model-aware context resolution) - linkedin-thought-leadership/ v2.0.0 — Full-spectrum LinkedIn content engine (short-form feed + long-form newsletter). v2.0.0 consolidated surface (27→24 commands, 16→14 agents) + added `/linkedin:newsletter` orchestrator with fact-check + persona-sweep gates BEFORE lock. Render pipeline migrated in-plugin (self-hosted OFL-1.1 fonts). Built across 21 Voyage sessions. + linkedin-thought-leadership/ v2.1.0 — Full-spectrum LinkedIn content engine (short-form feed + long-form newsletter). v2.0.0 consolidated surface (27→24 commands, 16→14 agents) + added `/linkedin:newsletter` orchestrator with fact-check + persona-sweep gates BEFORE lock. v2.1.0 adds skeleton-gate BEFORE prose (Step 2.5 + Step 3a) to `/linkedin:newsletter` + third `persona-reviewer` mode (`skjelett`); pipeline 11→13 phases; commands/agents unchanged in count (24, 14). Render pipeline self-hosted (OFL-1.1 fonts). llm-security/ v7.7.2 — Security scanning, auditing, threat modeling. HTML report output for all 18 skill commands (render-report CLI + canonical ESM module mirrored bit-identical into the playground). v7.7.2 translated the remaining Norwegian surface text in the playground UI, the canonical renderer, the agent prompts, and the README/CLAUDE.md state sections to English. v7.7.1 stripped the playground to the catalog as the only routable surface. ms-ai-architect/ v1.15.0 — Microsoft AI architecture (Cosmo Skyberg persona) + manual KB-refresh slash command + v3 project-view (sidebar med 17 artifacts + main + import-modal overlay, v2-surface fjernet i v1.15.0) okr/ v1.0.0 — OKR guidance for Norwegian public sector diff --git a/README.md b/README.md index 2278dd8..1d39913 100644 --- a/README.md +++ b/README.md @@ -206,14 +206,15 @@ Key commands: `/architect`, `/architect:ros`, `/architect:security`, `/architect --- -### [LinkedIn Thought Leadership](plugins/linkedin-thought-leadership/) `v2.0.0` +### [LinkedIn Thought Leadership](plugins/linkedin-thought-leadership/) `v2.1.0` Build authentic LinkedIn authority through algorithmic understanding, strategic consistency, and AI-assisted content creation. -v2.0.0 is a full-spectrum content engine: short-form feed posts AND long-form newsletter editions in one cohesive surface, with net-fewer commands and net-stronger pipeline. Updated for the January 2026 360Brew algorithm change, which validates your creator profile before distributing content. +v2.1.0 adds a **skeleton gate BEFORE prose** to `/linkedin:newsletter` — two new pipeline phases (Step 2.5 skeleton + section pitch, Step 3a spine prose) each with their own operator-gate, plus a third `persona-reviewer` mode (`skjelett`) that judges the five-line spine before any prose is written. Empirically motivated by the Seres-serien Del 3 + Del 4 production: a spine error caught at the skeleton stage costs 5–15 minutes; the same error caught at the resonance stage (Step 6) costs 4–12 hours; post-lock it costs a day. The pipeline grows from 11 to 13 phases; command and agent counts (24, 14) are unchanged. v2.0.0's full-spectrum surface (short-form feed posts AND long-form newsletter editions) is preserved bit-for-bit. Updated for the January 2026 360Brew algorithm change, which validates your creator profile before distributing content. -- **Long-form `/linkedin:newsletter` orchestrator** — multi-session pipeline (research → draft → fact-check sweep → persona sweep → lock → delivery → hook-gate) with maintained edition-state. Newsletter editions, essays, series articles -- **Two new longform-quality gates** — `fact-checker` (Opus, verifies every claim against primary sources) and `persona-reviewer` (Opus, reader-persona resonance + hook conversion). Both run BEFORE lock +- **Skeleton gate BEFORE prose (v2.1)** — `/linkedin:newsletter` Step 2.5 writes a five-line spine (premiss / problem / anbefaling / gevinst / vei videre) + one-line section pitches to `/NN-skjelett.md`. Operator-gate AND parallel persona-skjelett-sweep must both return JA before the pipeline can advance. Step 3a follows with spine prose (one paragraph per section) and its own operator-gate. Encodes the Maskinrommet writing-contract §A discipline into the pipeline. +- **Long-form `/linkedin:newsletter` orchestrator** — multi-session 13-phase pipeline (research → **skeleton + persona-skjelett-sweep** → **spine prose** → full prose draft → fact-check sweep → persona sweep → lock → delivery → hook-gate) with maintained edition-state. Newsletter editions, essays, series articles +- **Three longform-quality gate agent modes** — `fact-checker` (Opus, verifies every claim against primary sources) and `persona-reviewer` (Opus) with three modes: **`skjelett`** (Step 2.5, before prose), **`resonans`** (Step 6, before lock), **`konverter`** (Step 9, after lock) - **Render pipeline in-plugin** — `build-html.mjs`, `build-pdf.mjs`, `build-linkedin.mjs`, `build-carousel.mjs` with self-hosted Newsreader/Inter/JetBrains Mono under OFL-1.1 - **Guided onboarding** — `/linkedin:onboarding` walks new users through profile → setup → first post in one flow - **360Brew profile optimization** — audit your profile against LinkedIn's creator validation criteria diff --git a/plugins/linkedin-thought-leadership/.claude-plugin/plugin.json b/plugins/linkedin-thought-leadership/.claude-plugin/plugin.json index b10d168..2298d36 100644 --- a/plugins/linkedin-thought-leadership/.claude-plugin/plugin.json +++ b/plugins/linkedin-thought-leadership/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "linkedin-thought-leadership", - "version": "2.0.0", - "description": "Full-spectrum LinkedIn content engine — feed posts, carousels, video scripts, and long-form newsletter editions — with the January 2026 360Brew algorithm baked in. Net-fewer commands, net-stronger pipeline.", + "version": "2.1.0", + "description": "Full-spectrum LinkedIn content engine — feed posts, carousels, video scripts, and long-form newsletter editions — with the January 2026 360Brew algorithm baked in. v2.1 adds skeleton + spine-prose gates BEFORE prose to /linkedin:newsletter.", "author": { "name": "Kjell Tore Guttormsen" }, diff --git a/plugins/linkedin-thought-leadership/CHANGELOG.md b/plugins/linkedin-thought-leadership/CHANGELOG.md index 2f7b951..a8e7471 100644 --- a/plugins/linkedin-thought-leadership/CHANGELOG.md +++ b/plugins/linkedin-thought-leadership/CHANGELOG.md @@ -5,6 +5,30 @@ 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/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.1.0] - 2026-05-28 + +### Summary +Skeleton gate before prose in `/linkedin:newsletter`. Two new pipeline phases (Step 2.5 — Skeleton + section pitch; Step 3a — Spine prose) split the old Step 3 into pre-prose / spine-prose / full-prose stages, each with an operator-gate. Adds a third `persona-reviewer` mode (`skjelett`) that judges the five-line skeleton + section pitches BEFORE prose is written. Empirically motivated by the Seres-serien Del 3 + Del 4 production: spine errors caught post-prose cost ~1 day; the same error caught at the skeleton stage costs 5–15 minutes. Backward-compatible: existing editions stop at `currentPhase: "research"` and now resume at Step 2.5 instead of Step 3 — an intended deterministic improvement, never a contract break. + +### Added +- **Step 2.5 — Skeleton + section pitch** in `commands/newsletter.md`. Writes `/NN-skjelett.md` with the five-line spine (premiss / problem / anbefaling / gevinst / vei videre) + one-line section pitches. Operator-gate (JA / REVIDER / NEI) AND parallel persona-skjelett-sweep must both return JA before the pipeline advances. Encodes the Maskinrommet writing-contract §A discipline into the pipeline itself. +- **Step 3a — Spine prose** in `commands/newsletter.md`. One paragraph per section against the gated skeleton, ~20–30 % of final edition length. Operator-gate on whether the axis lands now that there is prose on it. Cheap second checkpoint before full expansion. +- **Step 3b — Full prose expansion** in `commands/newsletter.md`. Splits the old Step 3 (Draft) into spine prose (3a) and full prose expansion (3b). 3b owns the existing draft-cursor logic for multi-session expansion; 3a is short enough to restart on interruption. +- **`persona-reviewer` skjelett-mode** (third mode alongside `resonans` and `konverter`). Five spine axes (Premiss / Problem / Anbefaling / Gevinst / Vei videre) scored HOLDER / TVILER / MANGLER, ≤3 direction-only flags, per-pitch section-pay-in check, gate ladder PASS / REWORK / BLOCK. Caller passes `mode: skjelett`. +- **`skeleton-pitch` + `spine-prose` phase strings** in `config/edition-state.template.json` `_doc.phases` — 11 → 13 phases. Resumption table in `commands/newsletter.md` extended with deterministic rows for both new phases. +- **Rule 8 — Skjelett før prosa** in `references/longform-quality-rules.md`. Documents the skeleton-before-prose pre-condition that all other rules implicitly rely on, with the same five-slot format the pipeline enforces. + +### Changed +- **`/linkedin:newsletter` pipeline overview** — 11 → 13 phases; pipeline tables in `commands/newsletter.md` and `CLAUDE.md` reflect the new ordering (0, 1, 2, **2.5**, **3a**, **3b**, 4–10). +- **Resumption table** in `commands/newsletter.md` — `currentPhase: "research"` now resumes at Step 2.5 (was Step 3). Two new rows added for `skeleton-pitch` (→ Step 3a) and `spine-prose` (→ Step 3b). Draft-cursor note clarifies that the cursor applies only to Step 3b. +- **`agents/persona-reviewer.md` description, principles, and anti-patterns** — extended to cover the third mode (skjelett). Existing resonans + konverter modes unchanged in contract. +- **`CLAUDE.md` header + persona-reviewer row + newsletter command row** — reflect v2.1.0 surface. + +### Not changed (explicit non-deltas) +- **Step 1, Step 2, Steps 4–10** in `/linkedin:newsletter` — bit-for-bit unchanged in contract. +- **Renderers** — `render/build-html.mjs` and `render/build-linkedin.mjs` untouched; both still consume `NN-utkast.md` (3a writes the spine state, 3b overwrites with the full state, but only `currentPhase: "draft"` triggers rendering). +- **Hooks, scripts, command count (24), agent count (14)** — all unchanged. + ## [2.0.0] - 2026-05-28 ### Summary diff --git a/plugins/linkedin-thought-leadership/CLAUDE.md b/plugins/linkedin-thought-leadership/CLAUDE.md index de0a84d..801bafc 100644 --- a/plugins/linkedin-thought-leadership/CLAUDE.md +++ b/plugins/linkedin-thought-leadership/CLAUDE.md @@ -1,6 +1,6 @@ -# LinkedIn Thought Leadership Plugin (v2.0.0) +# LinkedIn Thought Leadership Plugin (v2.1.0) -Full-spectrum LinkedIn content engine — short-form feed posts, carousels, video scripts, and long-form newsletter editions — with the January 2026 360Brew algorithm baked in. v2.0.0 consolidated the surface (27 commands → 24, 16 agents → 14) while adding the long-form `/linkedin:newsletter` orchestrator + two longform-quality gate agents (`fact-checker`, `persona-reviewer`). +Full-spectrum LinkedIn content engine — short-form feed posts, carousels, video scripts, and long-form newsletter editions — with the January 2026 360Brew algorithm baked in. v2.0.0 consolidated the surface (27 commands → 24, 16 agents → 14) while adding the long-form `/linkedin:newsletter` orchestrator + two longform-quality gate agents (`fact-checker`, `persona-reviewer`). **v2.1.0** adds two new gates BEFORE prose to `/linkedin:newsletter` — Step 2.5 (skeleton + section pitch with operator-gate + persona-skjelett-sweep) and Step 3a (spine prose with operator-gate) — plus a third `persona-reviewer` mode (`skjelett`), encoding the Maskinrommet writing-contract §A discipline (premiss / problem / anbefaling / gevinst / vei videre) into the pipeline itself. Pipeline grows from 11 to 13 phases; commands and agents unchanged in count (24, 14). ## Architecture @@ -46,7 +46,7 @@ All content commands (post, quick, react, pipeline, first-post, video, multiplat | `/linkedin:post` | Full post creation (10-15 min) | | `/linkedin:quick` | 5-minute quick post (3-line formula) + 8 post-type templates | | `/linkedin:pipeline` | Full end-to-end content pipeline | -| `/linkedin:newsletter` | Long-form orchestrator: newsletter edition / essay / series article — multi-session pipeline with fact-check + persona-sweep BEFORE lock | +| `/linkedin:newsletter` | Long-form orchestrator: newsletter edition / essay / series article — multi-session 13-phase pipeline with **skeleton + spine-prose gates BEFORE prose (v2.1)** and fact-check + persona-sweep BEFORE lock | | `/linkedin:batch` | Create a full week of content | | `/linkedin:calendar` | View/manage post scheduling queue + publish action (mark scheduled posts as published) | | `/linkedin:carousel` | Structured multi-slide carousel generator | @@ -80,7 +80,7 @@ All content commands (post, quick, react, pipeline, first-post, video, multiplat | `post-feedback-monitor` | Haiku | Lime | Post-publish 48h monitoring | | `video-scripter` | Sonnet | Violet | Video script creation with pacing | | `fact-checker` | Opus | Brown | Factual-claim verification against primary sources (longform) | -| `persona-reviewer` | Opus | Olive | Reader-persona resonance + hook-conversion gate (longform) | +| `persona-reviewer` | Opus | Olive | Reader-persona skeleton (v2.1, before prose) + resonance (before lock) + hook-conversion (after lock) gate (longform) | **Rule:** Always read `assets/voice-samples/` before generating content. diff --git a/plugins/linkedin-thought-leadership/README.md b/plugins/linkedin-thought-leadership/README.md index d9fdc18..9171875 100644 --- a/plugins/linkedin-thought-leadership/README.md +++ b/plugins/linkedin-thought-leadership/README.md @@ -6,7 +6,7 @@ *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-2.0.0-blue) +![Version](https://img.shields.io/badge/version-2.1.0-blue) ![Platform](https://img.shields.io/badge/platform-Claude_Code_Plugin-purple) ![Commands](https://img.shields.io/badge/commands-24-green) ![Agents](https://img.shields.io/badge/agents-14-orange) @@ -14,12 +14,13 @@ ![Reference Docs](https://img.shields.io/badge/reference_docs-24-teal) ![License](https://img.shields.io/badge/license-MIT-lightgrey) -A comprehensive Claude Code plugin that turns LinkedIn from a chore into a full-spectrum content engine — short-form feed posts, carousels, video scripts, and long-form newsletter editions. v2.0.0 consolidated the surface (27 → 24 commands, 16 → 14 agents) and added `/linkedin:newsletter` as a multi-session long-form orchestrator with fact-check + persona-sweep gates BEFORE lock. 24 slash commands, 14 specialized agents, 9 automated hooks, and a 24-document knowledge base grounded in LinkedIn's actual algorithm signals. Updated for the January 2026 **360Brew** algorithm change, where LinkedIn now validates your profile before distributing content. +A comprehensive Claude Code plugin that turns LinkedIn from a chore into a full-spectrum content engine — short-form feed posts, carousels, video scripts, and long-form newsletter editions. v2.0.0 consolidated the surface (27 → 24 commands, 16 → 14 agents) and added `/linkedin:newsletter` as a multi-session long-form orchestrator with fact-check + persona-sweep gates BEFORE lock. **v2.1.0** adds two more gates BEFORE prose to `/linkedin:newsletter` — a skeleton gate (Step 2.5) and a spine-prose gate (Step 3a) — encoding the Maskinrommet writing-contract §A discipline (premiss / problem / anbefaling / gevinst / vei videre) into the pipeline itself, so spine errors get caught in minutes at the skeleton stage instead of hours at the resonance stage or a full day post-lock. 24 slash commands, 14 specialized agents, 9 automated hooks, and a 24-document knowledge base grounded in LinkedIn's actual algorithm signals. Updated for the January 2026 **360Brew** algorithm change, where LinkedIn now validates your profile before distributing content. --- ## Table of Contents +- [What's New in v2.1.0](#whats-new-in-v210) - [What's New in v2.0.0](#whats-new-in-v200) - [What Is This?](#what-is-this) - [Quick Start](#quick-start) @@ -39,6 +40,20 @@ A comprehensive Claude Code plugin that turns LinkedIn from a chore into a full- --- +## What's New in v2.1.0 + +**Skeleton gate before prose** in `/linkedin:newsletter` — the single most expensive failure mode in long-form (spine errors caught post-prose) is now gated before the first sentence is written. Empirically motivated by the Seres-serien Del 3 + Del 4 production (~1 day lost to spine rework that a 15-minute skeleton gate would have caught). + +- **New Step 2.5 — Skeleton + section pitch** — writes `/NN-skjelett.md` with the five-line spine (premiss / problem / anbefaling / gevinst / vei videre) + one-line section pitches. Operator-gate (JA / REVIDER / NEI) AND parallel persona-skjelett-sweep must both return JA before the pipeline can advance. No prose is written until the spine is right. +- **New Step 3a — Spine prose** — one paragraph per section against the gated skeleton, ~20–30 % of final edition length. Operator-gate on whether the axis lands now that there is prose on it. The old Step 3 (Draft) is split into 3a (spine) and 3b (full expansion); 3b owns the multi-session draft-cursor logic, 3a is short enough to restart on interruption. +- **New `persona-reviewer` mode: `skjelett`** — third mode alongside `resonans` (before lock) and `konverter` (after lock). Five spine axes (Premiss / Problem / Anbefaling / Gevinst / Vei videre) scored HOLDER / TVILER / MANGLER, ≤3 direction-only flags, per-pitch section-pay-in check. Reads the skeleton + pitches only — no prose. +- **Two new phase strings** in `edition-state.template.json` — `skeleton-pitch` + `spine-prose`. The pipeline grows from 11 to 13 phases; resumption is deterministic across every new phase boundary. +- **Rule 8 — Skjelett før prosa** in `references/longform-quality-rules.md` — codifies the skeleton-before-prose pre-condition that all other quality rules implicitly rely on. + +Backward-compatible: existing editions with `currentPhase: "research"` now resume at Step 2.5 (was Step 3) — an intended deterministic improvement; the contract on every other phase is bit-for-bit unchanged. + +--- + ## What's New in v2.0.0 **Full-spectrum content engine** — feed posts AND long-form newsletter editions in one cohesive surface, with net-fewer commands. @@ -202,7 +217,7 @@ The plugin delegates specialized work to 14 purpose-built agents. Each agent has | `post-feedback-monitor` | Haiku | Lime | Post-publish 48h monitoring and real-time interventions | | `video-scripter` | Sonnet | Violet | Video script creation with pacing and visual cues | | `fact-checker` | Opus | Brown | Factual-claim verification against primary/credible sources (longform) | -| `persona-reviewer` | Opus | Olive | Reader-persona resonance + hook-conversion gate (longform) | +| `persona-reviewer` | Opus | Olive | Reader-persona **skeleton** (v2.1, before prose) + **resonance** (before lock) + **hook-conversion** (after lock) gate (longform) | ### Content Pipeline @@ -220,7 +235,7 @@ trend-spotter --> content-planner --> differentiation-checker --> content-optimi Parallel support agents: `strategy-advisor`, `analytics-interpreter`, `network-builder`, `content-repurposer`, `video-scripter`. -Longform quality gates (newsletter): `fact-checker` → `persona-reviewer` run BEFORE lock. +Longform quality gates (newsletter): **`persona-reviewer` (skjelett) run BEFORE prose** (v2.1, Step 2.5) → `fact-checker` (Step 5) → `persona-reviewer` (resonance) run BEFORE lock (Step 6) → `persona-reviewer` (conversion) run AFTER lock on the hook (Step 9). > **Note (agent invocation + reload):** Commands invoke agents by their **namespaced** > type — `subagent_type: linkedin-thought-leadership:`, never the bare name. And a @@ -530,6 +545,7 @@ Scheduled posts are tracked in `assets/drafts/queue.json`: | Version | Date | Highlights | |---------|------|-----------| +| **2.1.0** | 2026-05-28 | Skeleton gate BEFORE prose in `/linkedin:newsletter`. New Step 2.5 (skeleton + section pitch, operator-gate + persona-skjelett-sweep) and Step 3a (spine prose, operator-gate) split the old Step 3 into pre-prose stages with their own gates. New `persona-reviewer` mode (`skjelett`). Pipeline grows 11 → 13 phases; commands and agents unchanged in count (24, 14). Encodes the Maskinrommet writing-contract §A discipline (premiss / problem / anbefaling / gevinst / vei videre) into the pipeline. Empirically motivated by the Seres-serien Del 3 + Del 4 spine-rework cost. | | **2.0.0** | 2026-05-28 | Full-spectrum content engine. `/linkedin:newsletter` long-form orchestrator with multi-session edition-state, fact-check + persona-sweep gates BEFORE lock. New agents: `fact-checker`, `persona-reviewer` (both Opus). Render pipeline migrated in-plugin with self-hosted OFL-1.1 fonts. Net-fewer surface: 27 → 24 commands (5 removed, 2 added), 16 → 14 agents (4 merged, 2 added). Router gating on monetize/outreach (unlocks at ~1K). `/linkedin:import` delegates analysis to `/linkedin:report`. | | **1.2.0** | 2026-04-11 | Friction reduction release. Auto-clipboard on all content commands, reduced interactive steps (max 2 per post), deterministic state management (`state-updater.mjs`), MCP image carousel pipeline, progressive onboarding, iCal calendar integration for batch scheduling, auto-prune content history (90 days). | | **1.1.0** | 2026-04-08 | Q2 feature release. 27 commands (+onboarding, +carousel). Week-rollover automation, voice drift scoring, industry content matrix, multi-URL react, day-of-week heatmap, month-over-month reports. | diff --git a/plugins/linkedin-thought-leadership/agents/persona-reviewer.md b/plugins/linkedin-thought-leadership/agents/persona-reviewer.md index 0a6ab6f..28f2223 100644 --- a/plugins/linkedin-thought-leadership/agents/persona-reviewer.md +++ b/plugins/linkedin-thought-leadership/agents/persona-reviewer.md @@ -1,21 +1,25 @@ --- name: persona-reviewer description: | - Read a draft as ONE named reader persona and judge whether it lands — not - whether it is correct. Returns at most five flags as direction (never - rewritten copy): the jury judges, the editor writes. Two modes: resonance - (before lock, all six axes) and conversion (after lock, binary "would YOU - click?" on the hook only). + Read a draft (or its pre-prose skeleton) as ONE named reader persona and + judge whether it lands — not whether it is correct. Returns direction as + flags, never rewritten copy: the jury judges, the editor writes. Three + modes: skeleton (before prose, five spine axes, ≤3 flags), resonance + (before lock, all six axes, ≤5 flags), and conversion (after lock, binary + "would YOU click?" on the hook only). Use when the user says: + - "does this skeleton argue what it claims to argue?", "skeleton check" - "does this land for [persona]?", "read this as my reader" - "persona check", "resonance check", "will this resonate?" - "would my reader click this?", "conversion check on the hook" - "is the takeaway clear for a leader?", "does the hook hold?" - "run the persona sweep", "judge this draft as the primær reader" + - "does this section pitch pay in?", "is the spine right?" - Triggers on: "persona check", "resonance check", "does this land", - "would they click", "conversion check", "persona sweep", "resonans", + Triggers on: "skeleton check", "skjelett-sjekk", "persona check", + "resonance check", "does this land", "would they click", + "conversion check", "persona sweep", "skjelett", "resonans", "konverter", "read as my reader". model: opus color: olive @@ -24,11 +28,13 @@ tools: ["Read"] # Persona Reviewer Agent -You are a reader's stand-in. You read a finished or near-finished draft **as one -named reader persona** and judge whether it *lands* for that reader — whether the -hook holds, the point resonates, the tone fits, the claim is believed, the -takeaway is actionable, and the piece keeps moving. You do not judge whether the -text is factually correct (that is `fact-checker`) or original (that is +You are a reader's stand-in. You read a finished draft, a near-finished draft, +or a pre-prose **skeleton + section pitches** — **as one named reader persona** +— and judge whether it *lands* for that reader. At the skeleton stage you judge +whether the argument-line *would* land if the prose delivered it faithfully; at +the resonance stage you judge whether the realized prose lands; at the +conversion stage you judge the hook only. You do not judge whether the text is +factually correct (that is `fact-checker`) or original (that is `differentiation-checker`). You judge whether it **works for this reader**. ## Your Mission @@ -47,26 +53,41 @@ clean JA. A *sekundær* NO caused by a role mismatch or an expertise ceiling («this I already know cold») is a SIGNAL that the gate works — report it, do not distort the text to chase it. -## Two Modes +## Three Modes -Both modes run the same persona. The caller passes the mode; you adapt scope and -output accordingly. +All three modes run the same persona. The caller passes the mode; you adapt +scope and output accordingly. The modes are listed in pipeline order — skjelett +runs first (Step 2.5, before prose), resonans next (Step 6, before lock), +konverter last (Step 9, after lock). + +### Skjelett-modus (before prose) + +Runs at the long-form pipeline's pre-prose skeleton gate (Step 2.5), against the +**five-line skeleton** (premiss / problem / anbefaling / gevinst / vei videre) +plus the **section pitches**. There is no prose yet — only the argument-line and +the section-level promise of what each section will do for that argument. Judge +on the **five spine axes** (below) and return **at most three flags** as +direction, each tracked **HOLDER / TVILER / MANGLER**. Produce a per-persona +verdict (JA / NEI). The gate question is: *would this argument-line land for +this reader if the prose delivered it faithfully?* This is the cheapest place to +catch a spine error — fixing one here costs minutes; fixing it after prose costs +hours; fixing it after lock costs a day. ### Resonans-modus (before lock) -Runs at the long-form pipeline's pre-lock resonance sweep. Judge the draft on -**all six axes** (below) and return **at most five flags** as direction, each -tracked **LØST / DELVIS / IKKE**. Produce a per-persona verdict (JA / NEI) and a -gate decision (PASS / REWORK / BLOCK). This is where the draft earns the right to -be locked. +Runs at the long-form pipeline's pre-lock resonance sweep (Step 6). Judge the +realized prose draft on **all six axes** (below) and return **at most five +flags** as direction, each tracked **LØST / DELVIS / IKKE**. Produce a +per-persona verdict (JA / NEI) and a gate decision (PASS / REWORK / BLOCK). This +is where the draft earns the right to be locked. ### Konverter-modus (after lock) -Runs at the post-lock conversion sweep. Judge the **hook only**, binary: -«would YOU click?» — **JA / NEI**. No axis scoring, no flags, no copy. Return the -click verdict and a single concrete reason in the reader's own voice ("I'd scroll -past — the first line is machinery, not me"). The body is already locked; the -only open question is whether this reader stops the scroll. +Runs at the post-lock conversion sweep (Step 9). Judge the **hook only**, +binary: «would YOU click?» — **JA / NEI**. No axis scoring, no flags, no copy. +Return the click verdict and a single concrete reason in the reader's own voice +("I'd scroll past — the first line is machinery, not me"). The body is already +locked; the only open question is whether this reader stops the scroll. ## Review Process @@ -77,31 +98,90 @@ Read the named persona from `config/personas.template.md` (or the project's **overbeviser**, **ekspertise**, **sjargong**. Judge as that reader — not as yourself, not as a generic audience. One run = one persona. -### Step 2: Read the draft as that reader +### Step 2: Read the input as that reader -Read the draft top to bottom, read-only, once, the way this reader actually would -— skimming the hook on mobile, stopping where `avkobler` triggers, leaning in -where `overbeviser` lands. Note where this specific reader would disengage. +Read top to bottom, read-only, once, the way this reader actually would. -### Step 3: Judge on the six axes (resonance mode) +- **Skjelett-modus:** read the five-line skeleton + section pitches as the + reader would skim an outline — does each line earn its keep for THIS reader, + does the argument-line stand on its own, does any section pitch fail to pay + in? There is no prose to disengage from yet — you are judging the *promise*, + not the delivery. +- **Resonans-modus:** read the prose draft as the reader would on mobile — + skimming the hook, stopping where `avkobler` triggers, leaning in where + `overbeviser` lands. Note where this specific reader would disengage. +- **Konverter-modus:** read the first two lines of the distribution hook only — + the body is locked; only the krok is in play. -Score each axis as **LØST** (lands), **DELVIS** (partly), or **IKKE** (fails), -each with a one-line reason grounded in the persona's fields. Do not invent a -seventh axis; do not skip one. +### Step 3: Judge on axes (mode-dependent) -### Step 4: Sort to at most five flags +- **Skjelett-modus** — score each of the **five spine axes** (Premiss / Problem / + Anbefaling / Gevinst / Vei videre) as **HOLDER** (lands as-is), **TVILER** + (lands only partly — this reader hesitates), or **MANGLER** (does not land — + missing or wrong for this reader), each with a one-line reason grounded in the + persona's fields. Vei videre may be N/A if the edition is not part of a series + (record `HOLDER (N/A)` and move on). Do not invent a sixth axis; do not skip + one (Vei-videre N/A excepted). +- **Resonans-modus** — score each of the **six axes** (below) as **LØST** + (lands), **DELVIS** (partly), or **IKKE** (fails), each with a one-line reason + grounded in the persona's fields. Do not invent a seventh axis; do not skip + one. +- **Konverter-modus** — no axis scoring. Skip to Step 5. -Surface the flags that matter most to THIS reader — IKKE before DELVIS, the -primær's blockers before a sekundary's nice-to-haves. **Cap at five.** The axis -that passes cleanest does not need a flag. Each flag is a *direction*, phrased so -the editor knows where to dig — never a line of replacement copy. +### Step 4: Sort to flags (mode-dependent cap) + +Surface the flags that matter most to THIS reader — the worst grade before the +softer grade (MANGLER before TVILER in skjelett; IKKE before DELVIS in +resonans), the primær's blockers before a sekundary's nice-to-haves. + +- **Skjelett-modus:** **cap at three.** The spine should be tight; if more than + three things are wrong, the skeleton itself needs rethinking — surface the + three load-bearing problems and stop. +- **Resonans-modus:** **cap at five.** The axis that passes cleanest does not + need a flag. +- **Konverter-modus:** no flags. Only the binary verdict + one reason. + +Each flag is a *direction*, phrased so the editor knows where to dig — never a +line of replacement copy. ### Step 5: Verdict + convergence -Give the per-persona verdict (JA / NEI) and the gate decision. If NEI, the editor -revises and you **re-judge** the same axes against the revision (LØST / DELVIS / -IKKE again). Loop until the primær returns a clean JA. You re-judge every round; -you never write the fix. +Give the per-persona verdict (JA / NEI) and the gate decision per the mode's +gate ladder (see Verdict Tokens below). + +- **Skjelett-modus convergence:** if NEI, the editor revises the **skeleton + + pitches** (not prose — there is none yet), and you re-judge the same five + spine axes against the revision. Loop until the primær returns a clean JA. + The cycle is fast (minutes per round) and is the point of the gate. +- **Resonans-modus convergence:** if NEI, the editor revises the prose and you + re-judge the same six axes. Loop until the primær returns a clean JA. You + re-judge every round; you never write the fix. +- **Konverter-modus:** no convergence within this agent — the editor revises + the **distribution hook only** between calls; you re-judge JA / NEI on the + revised hook when called again. + +## The Five Spine Axes (skjelett mode) + +These axes mirror the five-line skeleton structure 1:1. There is no prose +yet — you judge the *argument-line* and the *promise* of each section, not +hook quality, tone, formatting, or length (those belong to resonans-modus once +prose exists). + +| # | Axis | The question for THIS reader | +|---|------|------------------------------| +| 1 | **Premiss** | Does the premise hold for this reader — given `avkobler` / `overbeviser` — or is it a premise they cannot accept? | +| 2 | **Problem** | Is the problem concretely named in language this reader recognizes, or is it abstract / mis-aimed for their domain? | +| 3 | **Anbefaling** | Is the recommendation a clear direction this reader can apply, or does it dissolve into platitude? | +| 4 | **Gevinst** | Does this reader see the upside in their own context, or does the payoff land for someone else? | +| 5 | **Vei videre** | If part of a series: does the forward-pointer cohere with where the series is going (and where THIS reader needs it to go)? N/A for standalone editions. | + +### Section-pitch check (skjelett mode addendum) + +In addition to scoring the five spine axes, scan each **section pitch** — does +this section's one-line promise actually pay into the spine? Flag any pitch +that does not earn its keep (it reads as filler, restates a prior section, or +points away from the recommendation). A pitch failure counts toward the +three-flag cap. ## The Six Axes (resonance mode) @@ -116,9 +196,28 @@ you never write the fix. ## Verdict Tokens & Gate Logic -**Per-axis flag:** LØST (lands) · DELVIS (partly lands) · IKKE (fails for this reader). +**Per-axis flag (mode-dependent):** -**Per-persona verdict:** JA (the draft lands for this reader) · NEI (it does not). +- *Skjelett-modus:* HOLDER (lands as-is) · TVILER (lands partly — reader + hesitates) · MANGLER (does not land — missing or wrong for this reader). +- *Resonans-modus:* LØST (lands) · DELVIS (partly lands) · IKKE (fails for this + reader). + +**Per-persona verdict (all modes):** JA (it lands for this reader) · NEI (it +does not). + +**Gate decision (skjelett mode):** + +- **PASS** — primær = JA, no sekundær MANGLER on Premiss or Anbefaling. The + argument-line is sound for this reader; the editor can proceed to spine + prose (Step 3a). +- **REWORK** — primær = NEI, or a fixable TVILER/MANGLER the editor should + address. Provide the (≤3) flags as direction; editor revises skeleton + + pitches and re-runs the sweep. *Never let prose start on a REWORK skeleton — + the entire point of this gate is to catch spine errors before prose.* +- **BLOCK** — primær = MANGLER on Premiss or Anbefaling (the reader cannot + accept the premise, or there is no actionable direction). Must be reworked + before any prose; this is the dangerous failure mode the gate exists for. **Gate decision (resonance mode):** @@ -135,13 +234,51 @@ and one reason. ## Convergence Loop Re-run per persona until the primær returns a clean JA. Each round: the editor -revises, you re-judge the same six axes against the new draft, re-emit ≤5 flags. -A sekundær that stays IKKE on a known ceiling is accepted (signal, not failure); -a primær that stays NEI keeps the loop open. The jury never writes the revision — -it only re-judges whether the revision now lands. +revises, you re-judge the same axes against the new input, re-emit flags within +the mode's cap. A sekundær that stays in the worst grade (MANGLER / IKKE) on a +known ceiling is accepted (signal, not failure); a primær that stays NEI keeps +the loop open. The jury never writes the revision — it only re-judges whether +the revision now lands. + +The loop is cheap in skjelett-modus (skeleton edits take minutes) and the place +where you want the bulk of convergence to happen — every round saved at the +skeleton stage is hours saved at the prose stage. ## Output Format +### Skeleton mode + +``` +## Persona Skeleton Review — [persona name] ([primær | sekundær]) + +**Mode:** skjelett (before prose) +**Read as:** [rolle, one line] +**Input:** five-line skeleton + N section pitches (no prose yet) + +### Spine Axis Judgments +| # | Axis | Flag | Why (for this reader) | +|---|------|------|------------------------| +| 1 | Premiss | HOLDER/TVILER/MANGLER | [one line grounded in avkobler/overbeviser] | +| 2 | Problem | … | … | +| 3 | Anbefaling | … | … | +| 4 | Gevinst | … | … | +| 5 | Vei videre | HOLDER/TVILER/MANGLER (or N/A — standalone edition) | … | + +### Section-Pitch Check +[For each pitch — does it pay into the spine? Flag any that do not. +List only failures; passes are silent.] +- Pitch N "[…]" — [why it fails to pay in, for this reader] + +### Flags (≤3, direction only — NO rewritten copy) +1. [axis or pitch] — [where this reader loses it + which direction to fix] +2. … + +### Verdict: [JA | NEI] +### Gate: [PASS | REWORK | BLOCK] +[If REWORK/BLOCK: which flags are the priority directions. The editor revises +the skeleton + pitches (NOT prose — there is none yet) and re-runs this sweep.] +``` + ### Resonance mode ``` @@ -183,31 +320,45 @@ it only re-judges whether the revision now lands. ## Key Principles 1. **The jury judges; the editor writes.** Return direction, never rewritten - copy. Handing back edited text is the single worst failure of this role. + copy. Handing back edited text is the single worst failure of this role — + in every mode, including skjelett (do not hand back a fixed skeleton). 2. **One persona per run.** Judge as that named reader, with their fields — not as yourself, not as a generic audience. 3. **Primær trumfer.** A primær NO keeps the loop open; a sekundær ceiling-NO is a signal the gate works, not a defect to chase. 4. **Land, don't correct.** You judge whether it *works for this reader* — not whether it is true (fact-checker) or original (differentiation-checker). -5. **At most five flags.** Surface what matters most to this reader; let the - cleanest axis pass unflagged. +5. **Flag cap matches the mode.** Skjelett ≤ 3, resonans ≤ 5, konverter = 0 + (binary verdict + one reason). Tighter caps in earlier modes are deliberate + — the spine should be tight. 6. **Ground every flag in the persona.** "Hits `avkobler`" beats "weak hook." Tie each judgment to rolle / avkobler / overbeviser / ekspertise / sjargong. 7. **Conversion is binary.** In konverter-modus, judge the hook only — JA/NEI and one reason. No axes, no flags, no copy. +8. **Skjelett judges the promise, not the prose.** There is no prose yet. Do + not flag hook quality, formatting, or length — those belong to resonans-modus. + Do flag a premise the reader cannot accept, a recommendation that dissolves + into platitude, or a section pitch that does not pay in. ## Anti-Patterns -- Rewrite the draft or hand back replacement copy (that is the editor's pen) +- Rewrite the draft (or skeleton) or hand back replacement copy (that is the + editor's pen) - Judge as yourself instead of as the named persona - Distort the text to chase a sekundær ceiling-NO - Accept a primær NEI as "good enough" -- Exceed five flags, or invent a seventh axis +- Exceed the mode's flag cap (3 / 5 / 0), or invent an extra axis (sixth in + skjelett, seventh in resonans) - Score factual accuracy or originality (wrong agent) - Give vague flags ("make it punchier") instead of persona-grounded direction - Run axis scoring in konverter-modus, or skip the binary click verdict -- Soften a primær BLOCK (Krok/Leder-takeaway IKKE) to REWORK to be agreeable +- Use resonans axes (Krok, Tone, Lengde/driv) in skjelett-modus — there is no + prose to judge them against +- Soften a primær BLOCK (skjelett: Premiss/Anbefaling MANGLER; resonans: Krok/ + Leder-takeaway IKKE) to REWORK to be agreeable +- Let prose drafting start on a skjelett-REWORK (the gate exists exactly to + catch this; bypassing it reproduces the spine-error failure mode the gate + was built to prevent) - Mix two personas in one run ## References diff --git a/plugins/linkedin-thought-leadership/commands/newsletter.md b/plugins/linkedin-thought-leadership/commands/newsletter.md index 63ee3e7..2ae24d1 100644 --- a/plugins/linkedin-thought-leadership/commands/newsletter.md +++ b/plugins/linkedin-thought-leadership/commands/newsletter.md @@ -59,17 +59,21 @@ delegate the fan-out to a nested background agent. > only layer that can reliably spawn parallel sub-agents. So this command issues > the parallel `Task` calls itself and synthesizes their returns inline. -## Pipeline overview (11 phases) +## Pipeline overview (13 phases) -The phase order is fixed. The persona sweep runs **BEFORE** lock — this is the -single most important correction from the Seres process (plan §0.4, principle 5). +The phase order is fixed. Two gates run **BEFORE prose** (skeleton + spine +prose), and the persona resonance sweep runs **BEFORE lock** — these are the +single most important corrections from the Seres process (plan §0.4, principle +5; v2.1 brief §1 on spine-error cost). | Step | Phase | What | Tools | |------|-------|------|-------| | 0 | **Load context** | edition-state/HANDOVER, voice profile, persona library, series brief | `Read` | | 1 | **Brief + calibration** | angle, voice, audience personas (mark primær), key points, tone, leader-takeaway. ≤3 questions | `AskUserQuestion` | | 2 | **Research** | parallel scoped mandates → verified notes; triangulation | **`Task` fan-out (foreground)** | -| 3 | **Draft** | dramaturgical order, voice-matched; may span sessions | `content-repurposer` + `Task` | +| 2.5 | **Skeleton + section pitch — BEFORE prose** | five-line skeleton (premiss/problem/anbefaling/gevinst/vei videre) + per-section one-line pitch. Operator-gate JA/NEI/REVIDER. Persona-skjelett-sweep before any prose is written. | `AskUserQuestion` + **`persona-reviewer`** (skjelett mode) | +| 3a | **Spine prose — BEFORE full expansion** | one paragraph per section carrying that section's pitch, nothing more. ~20–30 % of final length. Operator-gate on whether the axis is right now that there is prose on it. | inline drafting + `content-repurposer` | +| 3b | **Full prose expansion** | expand each section with argument, examples, anchors from research; may span sessions | `content-repurposer` + `Task` | | 4 | **Consistency + quality** | threads, premise→conclusion arc, leader-takeaway, AI-slop removal, formatting dose | inline + `references/longform-quality-rules.md` | | 5 | **Fact-check sweep** | risk-sorted (🔴/🟡/🟢), guilty-until-disproven, verification log | **`fact-checker` (parallel)** | | 6 | **Persona sweep — BEFORE lock** | reader jury, primær wins, convergence to clean YES | **`persona-reviewer`** (resonance mode) | @@ -78,12 +82,23 @@ single most important correction from the Seres process (plan §0.4, principle 5 | 9 | **Hook / conversion gate** | persona gate on the distribution text post-lock: "would YOU click?" | **`persona-reviewer`** (conversion mode) | | 10 | **Scheduling** | register the edition in the plugin queue/state for native scheduling | `hooks/scripts/queue-manager.mjs` | -> **Build status:** all 11 phases (Steps 0–10) are implemented below. This -> command takes an edition end-to-end: load → calibration → verified research → -> draft → consistency/quality → fact-check sweep → pre-lock persona sweep → -> optional annotation → LOCK/delivery → post-lock hook gate → scheduling, -> persisting each phase to `edition-state.json` and the HANDOVER and stopping -> cleanly between sessions. +> **Build status:** all 13 phases (Steps 0–2.5, 3a, 3b, 4–10) are implemented +> below. This command takes an edition end-to-end: load → calibration → +> verified research → **skeleton + section pitch (operator + persona gate +> BEFORE prose)** → **spine prose (operator gate BEFORE full expansion)** → +> full prose draft → consistency/quality → fact-check sweep → pre-lock persona +> sweep → optional annotation → LOCK/delivery → post-lock hook gate → +> scheduling, persisting each phase to `edition-state.json` and the HANDOVER +> and stopping cleanly between sessions. + +> **Why two gates BEFORE prose (v2.1).** Spine errors are the dearest failure +> mode in long-form: catching one at the skeleton stage costs 5–15 min, at the +> spine-prose stage 30–60 min, at the resonance stage (Step 6) 4–12 h, and +> post-lock a whole day of cascading rework (delingstekst, hooks, carousel, +> doc references). Steps 2.5 and 3a exist to force the spine to be **explicit, +> visible, and confirmed** before a single full-prose sentence is written — +> they encode the discipline that already lives in the Maskinrommet writing +> contract §A. --- @@ -144,7 +159,9 @@ Look up `edition-state.json` → `articles.` (and the top-level | *(no state file)* | **NEW edition** → Step 1 (init state at end of Step 2) | | `load-context` | Step 1 — Brief + calibration | | `brief-calibration` | Step 2 — Research | -| `research` | Step 3 — Draft | +| `research` | Step 2.5 — Skeleton + section pitch *(v2.1 — skeleton gate BEFORE prose)* | +| `skeleton-pitch` | Step 3a — Spine prose *(v2.1 — one paragraph per section, BEFORE full expansion)* | +| `spine-prose` | Step 3b — Full prose expansion | | `draft` | Step 4 — Consistency + quality *(see draft-cursor note)* | | `consistency-quality` | Step 5 — Fact-check sweep | | `factcheck-sweep` | Step 6 — Persona sweep (pre-lock) | @@ -160,12 +177,19 @@ Steps below write exactly these strings. If `currentPhase` is missing or unrecognized, do NOT guess — read the edition-HANDOVER §6 next-session pointer and confirm with the operator before proceeding. -**Draft-cursor note (Step 3 only).** `draft` is the one phase that can be -*partial*: if Step 3 stopped mid-draft it records a section-level cursor in -`edition-state.json` and a "draft resumes at section " pointer in HANDOVER §6. -On resume with `currentPhase: "draft"`, check for that cursor first — if present, -re-enter **Step 3** at the cursor and finish the draft before Step 4; only when the -HANDOVER records "draft complete" do you resume at **Step 4**. +**Draft-cursor note (Step 3b only).** `draft` is the one phase that can be +*partial* — full prose expansion (Step 3b) is the only sub-step long enough to +exceed a single session's context budget. If Step 3b stopped mid-prose, it +records a section-level cursor in `edition-state.json` and a "draft resumes at +section " pointer in HANDOVER §6. On resume with `currentPhase: "draft"`, +check for that cursor first — if present, re-enter **Step 3b** at the cursor and +finish the prose expansion before Step 4; only when the HANDOVER records "draft +complete" (no open cursor) do you resume at **Step 4**. + +Step 3a (spine prose) is short enough that it does NOT need a cursor: if 3a +is interrupted, `currentPhase` stays at `skeleton-pitch` and the resume point +is "Step 3a — restart from section 1" (one short paragraph per section against +the gated skeleton — typically minutes, not session-length work). > **Resumption is the deterministic test (plan §10, archetype E).** Abort after > Step 6 → `currentPhase` is `persona-sweep-prelock` → re-run → the table resumes @@ -272,9 +296,11 @@ Edition brief 5. **Persist + checkpoint state.** Write the resolved brief (Step 1) and the verified research notes into the edition's `edition-state.json` (`currentPhase: "research"`, article status `in-progress`) and append a - "research complete → next: draft" pointer to the edition-HANDOVER §6. If this - is a fresh edition, initialize `edition-state.json` from the template schema - first. Then stop cleanly — drafting (Step 3) begins in the next session. + "research complete → next: skeleton + section pitch (BEFORE prose)" pointer to + the edition-HANDOVER §6. If this is a fresh edition, initialize + `edition-state.json` from the template schema first. Stop cleanly here if + context budget is tight — Step 2.5 begins in the next session; otherwise + Step 2.5 may run inline (it is short and operator-interactive). ``` Research phase complete. @@ -282,64 +308,289 @@ Research phase complete. - Verified notes: by key point - Carried to fact-check (🟡 unverified): State written: /linkedin/edition-state.json (phase: research) -Next session: Step 3 — Draft. +Next: Step 2.5 — Skeleton + section pitch (operator + persona gate BEFORE prose). ``` --- -## Step 3: Draft — dramaturgical order, voice-matched +## Step 2.5: Skeleton + section pitch — BEFORE prose (operator + persona gate) -Turn the verified research notes (Step 2) into a full draft. This is a -*long-form* draft, not a feed post: it has an arc, not a hook-and-three-bullets. +> **This is the cheapest gate in the pipeline (v2.1 brief §6).** A spine error +> caught here costs 5–15 min to fix; the same error caught at Step 6 costs +> 4–12 h; post-lock it costs a day of cascading rework (delingstekst, hooks, +> carousel, doc references). The whole reason this step exists is to force the +> argument-line to be **explicit, visible, and confirmed** before a single +> full-prose sentence is written. -> **This phase may span multiple sessions.** A long edition can exceed a single -> session's context budget. If you approach the budget mid-draft, stop cleanly, -> write the partial draft to the series root as `/NN-utkast.md` (the -> canonical draft path — see step 4), record `currentPhase: "draft"` -> with a section-level cursor in `edition-state.json`, and append a precise -> "draft resumes at section " pointer to the edition-HANDOVER §6. The next -> session re-reads Step 0, picks up the cursor, and continues. Never start the -> consistency pass (Step 4) on a half-written draft. +> **Order assertion (enforced).** Step 2.5 runs AFTER research (Step 2) and +> BEFORE any prose (Step 3a). No section of the draft is written — not even +> spine prose — until the operator says JA on the skeleton and the +> persona-skjelett-sweep returns a clean primær JA. This ordering encodes the +> Maskinrommet writing-contract §A discipline (skeleton before prose) into the +> pipeline. `[GATE]` **Procedure:** -1. **Re-read the voice profile** (`assets/voice-samples/`) before writing a single - sentence — this is the existing LTL rule and it is not optional for long-form. - The draft must read as the author, not as generic LinkedIn prose. +1. **Propose the five-line skeleton.** Synthesize from the resolved brief + (Step 1) + verified research notes (Step 2). The format is fixed — five + lines, one per slot, each one sentence: -2. **Lay out the dramaturgical order** from the brief (Step 1) and notes (Step 2): - - **Ingress + first paragraph** establish ONE clear premise (this is the front - half of the premise→conclusion arc enforced in Step 4). - - **Body** develops the 2–4 key points in the order that builds tension, each - anchored to a verified note. Carry each note's source marker inline as a - comment so the Step 5 fact-check sweep can find it. - - **Conclusion** grips the premise concretely and twists it forward (direction + - one concrete grip) — it does not merely summarize. + - **Premiss** — what must the reader accept for the rest to land? + - **Problem** — what stands in the way, concretely named? + - **Anbefaling** — what should the reader think or do differently? + - **Gevinst** — what do they win? + - **Vei videre** — what does the next article cover, or what does the rest + of the series do with this? (N/A for standalone editions — say so + explicitly.) -3. **Draft with the `content-repurposer` muscle.** Reuse `agents/content-repurposer.md` - (its article→long-form conversion discipline) for the section-to-prose work — - invoke it via `Task` (`subagent_type: linkedin-thought-leadership:content-repurposer`) - for individual sections when useful, *from this command layer* (foreground, - principle 4). The command owns assembly and voice; the - agent assists with conversion. The draft is voice-matched by THIS session, not - self-certified for voice — voice-match remains an `[OPERATØR]` / `[GATE: - voice-trainer]` judgment, never auto-passed (plan §10.0). +2. **Propose section pitches — one line per section.** List the section + headings (provisional) and, for each, a single-line pitch of *what that + section does for the argument*. A pitch that does not pay into the spine + is a section that should not exist; flag those for cut or rework. -4. **Write the draft** to the **series root** as `/NN-utkast.md` (NN = - zero-padded edition number — the SAME filename Steps 7 and 8 render from). - This is the single canonical draft path: `render/build-html.mjs` (Step 7) and - `render/build-linkedin.mjs` (Step 8) both consume `NN-utkast.md` from cwd, and - the renderer **silently skips** any draft without an `NN` prefix. Do NOT write - to `linkedin/
.draft.md` — that path is skipped at render. Set - `currentPhase: "draft"` in `edition-state.json`, and append a "draft complete → - next: consistency/quality" pointer to the HANDOVER §6. +3. **Write the skeleton + pitches to `/NN-skjelett.md`** (NN = the same + zero-padded edition number used by `NN-utkast.md`, new suffix). This is a + first-class artifact — the editor can re-open it, the persona sweep reads + it, and it becomes the contract that Step 3a (spine prose) writes against. + + Suggested file structure: + + ```markdown + # Skjelett — Del NN «» + + ## Spine + - **Premiss:** … + - **Problem:** … + - **Anbefaling:** … + - **Gevinst:** … + - **Vei videre:** … (or: N/A — standalone edition) + + ## Seksjons-pitcher + 1. + 2. … + ``` + +4. **Operator-gate (first round).** Present the skeleton + pitches to the + operator with `AskUserQuestion`. Three options: + + - **JA** — skeleton is right, proceed to the persona-skjelett-sweep (step 5). + - **REVIDER** — operator gives direction; revise the skeleton inline and + re-present. Loop until JA or NEI. + - **NEI** — the skeleton is wrong at a load-bearing level (premise unsound, + argument-line incoherent). Return to brief calibration (Step 1) or + research (Step 2) to surface the missing piece before re-attempting. + + Do not proceed past this gate without an explicit JA. The pipeline may not + advance to Step 3a (spine prose) until both this operator-gate AND the + persona-skjelett-sweep below return JA. `[OPERATØR]` + +5. **Persona-skjelett-sweep — fan out `persona-reviewer` in skjelett-mode.** + Issue one `persona-reviewer` call per active persona in parallel — a SINGLE + message with multiple `Task` tool-uses, `subagent_type: + linkedin-thought-leadership:persona-reviewer`, from THIS command layer in + the foreground (principle 4). Pass each call the persona name, the path to + `/NN-skjelett.md`, and **`mode: skjelett`** (the before-prose mode — + five spine axes, ≤3 flags as direction, HOLDER/TVILER/MANGLER scoring). + This is NOT resonans mode (Step 6 — that runs on full prose) and NOT + konverter mode (Step 9 — that judges the hook only). + +6. **Collect skjelett verdicts and gate.** Each call returns per-axis flags + (HOLDER/TVILER/MANGLER), ≤3 direction-only flags, a section-pitch check + (any pitch that does not pay in), a per-persona verdict (JA/NEI), and a + gate decision. Aggregate per the agent's rule: + - **primær JA** + no sekundær MANGLER on Premiss/Anbefaling → PASS, ready + to write spine prose. + - **primær NEI**, or a fixable TVILER/MANGLER the editor should address → + REWORK. Revise the skeleton + pitches; re-run the sweep on the revision. + - **primær MANGLER on Premiss or Anbefaling** → BLOCK. The reader cannot + accept the premise, or there is no actionable direction. Return to brief + (Step 1) or research (Step 2) — do NOT paper over this with a + skeleton-level rewrite. + + A *sekundær* NEI from a role mismatch or expertise ceiling is a SIGNAL the + gate works (accept it, do not distort the skeleton to chase it — the same + "primær trumfer" rule as Step 6). The jury returns **direction only** — + the editor (this session) holds the pen; never paste a persona's rewritten + skeleton. `[GATE]` + +7. **Convergence loop.** If gate is REWORK/BLOCK, fold flags into the + skeleton + pitches (or, on BLOCK, return upstream) and re-run the same + `persona-reviewer` calls against the revision. Loop until the primær + returns a clean JA. This loop is **cheap and frequent at this stage** — + every round saved here is hours saved at the prose stage. + +8. **Persist + checkpoint state.** Once the skeleton is JA from both operator + AND persona-skjelett-sweep, record: + + - The final skeleton + pitches in `/NN-skjelett.md` (already written + in step 3, with any in-loop revisions applied). + - Per-persona skjelett verdicts in + `edition-state.json` → `articles.NN.personaSweep.skeleton` (or alongside + resonance/conversion under the same `personaSweep` object). + - `currentPhase: "skeleton-pitch"` in `edition-state.json` (the marker that + Step 2.5 is complete and the gate has passed). + - A "skeleton + pitches PASS (primær JA) → next: Step 3a (spine prose)" + pointer in HANDOVER §6. ``` -Draft complete (or: partial — resumes at section ). -- Premise established: -- Key points drafted: / +Skeleton + section pitch (BEFORE prose) — complete. +- Skeleton: 5 lines (premiss / problem / anbefaling / gevinst / vei videre) +- Section pitches: sections, all paying into the spine (else: pitches reworked, see flags) +- Operator gate: JA (after revision rounds) +- Persona-skjelett-sweep: primær JA (else: still NEI — loop open, NOT ready for prose) +- Convergence rounds: +- Accepted sekundær ceiling-NOs (signal, not failure): +Gate: [PASS — primær JA, ready for spine prose] (else REWORK/BLOCK) +Next: Step 3a — Spine prose (one paragraph per section, BEFORE full expansion). +``` + +--- + +## Step 3a: Spine prose — one paragraph per section (BEFORE full expansion) + +Take the gated skeleton (`NN-skjelett.md`) and the section pitches and write +**one paragraph per section** that carries that section's pitch — and nothing +more. The output is "spine prose": the skeleton turned into running text, but +without the argumentation, examples, or research anchors that Step 3b adds. +Typically ~20–30 % of the edition's final length. + +> **Order assertion (enforced).** Step 3a runs AFTER the Step 2.5 skeleton gate +> (operator + persona-skjelett-sweep both JA) and BEFORE Step 3b (full prose +> expansion). The point of running spine prose as its own phase is to give the +> operator one more cheap chance to see the axis on actual prose — sometimes +> an argument-line that looked sound on a one-line skeleton reveals a thin spot +> only when you try to put a paragraph on it. `[GATE]` + +**Procedure:** + +1. **Re-read the voice profile** (`assets/voice-samples/`) before writing a + single sentence — this is the existing LTL rule and it is not optional for + long-form. Voice match starts at the spine, not at expansion. + +2. **For each section in `NN-skjelett.md`, write ONE paragraph that delivers + that section's pitch.** No examples yet, no anecdotes, no research citations + — just the paragraph that carries the pitch and connects to the next + section's pitch. Think of it as the skeleton turned into running prose, + one paragraph per bone: + + - Ingress paragraph carries the **Premiss** + (where the skeleton calls for + it) the **Problem**, establishing the front half of the premise→conclusion + arc that Step 4 will enforce. + - Each body paragraph carries one section pitch (one pitch = one paragraph). + - Closing paragraph carries the **Anbefaling** + **Gevinst** and the close + that grips the premise and twists it forward (the back half of the arc). + - If the skeleton has a **Vei videre**, surface it in or after the close + — never as a tacked-on summary. + +3. **Write the spine draft** to `/NN-utkast.md` (the canonical draft + path — Steps 7 and 8 render this exact file). This is the same `NN-utkast.md` + that Step 3b expands into the full draft; spine-prose is the first state of + that file, full prose is the second state, and `currentPhase` is the + disambiguator (see resumption table). Do NOT render in this state (Step 7's + review HTML and Step 8's POST.html require `currentPhase: "draft"` — i.e. + Step 3b complete). + +4. **Operator-gate.** Present the spine draft to the operator with + `AskUserQuestion`. The gate question is *narrow*: «Is the axis right now + that there is prose on it?» Three options: + + - **JA** — the axis lands as prose; proceed to Step 3b (full expansion). + - **REVIDER** — operator gives direction; tighten the spine paragraphs and + re-present. Stay in 3a; do NOT slip into expansion. (Closing gaps by + tightening — rule 6 of `references/longform-quality-rules.md` — applies + here just as it does in Steps 4–9.) + - **NEI** — the axis still fails as prose. Return to Step 2.5 (revise + skeleton + pitches), re-run the persona-skjelett-sweep, and re-write + spine prose against the corrected skeleton. Do not paper over a NEI by + pressing forward into expansion. + + The pipeline may not advance to Step 3b without an explicit JA. `[OPERATØR]` + +5. **Persist + checkpoint state.** Once the operator says JA: + + - `NN-utkast.md` holds the spine-prose draft (will be overwritten by Step 3b + with the expanded prose). + - `currentPhase: "spine-prose"` in `edition-state.json` (the marker that 3a + is complete and the gate has passed). + - A "spine prose JA → next: Step 3b (full prose expansion)" pointer in + HANDOVER §6. + +``` +Spine prose (BEFORE full expansion) — complete. +- Sections drafted (one paragraph per section): / +- Length: words (target: ~20–30 % of final edition length) +- Operator gate: JA (after revision rounds) (else: still NEI — loop open or returned to Step 2.5) - Voice-match: [OPERATØR]/[GATE: voice-trainer] — NOT self-certified -Draft written: /NN-utkast.md (series root, NN-prefixed — Steps 7/8 render this exact file) +Draft written: /NN-utkast.md (spine-prose state — Step 3b expands the same file) +Next: Step 3b — Full prose expansion. +``` + +--- + +## Step 3b: Full prose expansion — against the gated spine + +Take the gated spine prose (Step 3a → `currentPhase: "spine-prose"`) and expand +each paragraph into the section it promised — with argumentation, examples, +anchors from the verified research notes (Step 2), and the dramaturgical +turning-points the spine already named. + +> **This phase may span multiple sessions.** A long edition can exceed a +> single session's context budget. If you approach the budget mid-expansion, +> stop cleanly, write the partial draft to `/NN-utkast.md` (the +> canonical draft path), record `currentPhase: "draft"` **with a section-level +> cursor** in `edition-state.json`, and append a precise "draft resumes at +> section " pointer to the edition-HANDOVER §6. The next session re-reads +> Step 0, picks up the cursor, and continues. Never start the consistency +> pass (Step 4) on a half-written expansion. (Step 3a is short and does NOT +> need a cursor — see the draft-cursor note above.) + +**Procedure:** + +1. **Re-read the voice profile** (`assets/voice-samples/`) before expanding — + the voice was set at the spine; do not lose it in expansion. + +2. **Expand section by section, against the spine.** Each section's paragraph + from Step 3a is the *contract* for that section: the expansion must + *deliver* what the spine paragraph promised, not drift to a different + point. For each section: + + - Open with the spine paragraph (revised in voice if needed, but the + argument-line stays). + - Add the argument, examples, and anchors that turn the spine paragraph + into the full section. Carry each verified-research-note source marker + inline as a comment so the Step 5 fact-check sweep can find it. + - Close the section in a way that hands the next section's pitch a clean + pickup. + + Expansion is **expansion against the spine**, not expansion to fill space — + if a section grows but does not strengthen its pitch, cut back. (Rule 6 of + `references/longform-quality-rules.md`, applied during writing rather than + only afterward.) + +3. **Expand with the `content-repurposer` muscle.** Reuse + `agents/content-repurposer.md` (its article→long-form conversion discipline) + for individual section expansions — invoke it via `Task` (`subagent_type: + linkedin-thought-leadership:content-repurposer`) when useful, *from this + command layer* (foreground, principle 4). The command owns assembly and + voice; the agent assists with conversion. The draft is voice-matched by + THIS session, not self-certified for voice — voice-match remains an + `[OPERATØR]` / `[GATE: voice-trainer]` judgment, never auto-passed (plan + §10.0). + +4. **Write the expanded draft** to `/NN-utkast.md` (overwriting the + spine-prose state — this is the SAME canonical filename Steps 7 and 8 + render from; `render/build-html.mjs` and `render/build-linkedin.mjs` + silently skip any draft without an `NN` prefix). Set + `currentPhase: "draft"` in `edition-state.json`, and append a "draft + complete → next: consistency/quality" pointer to the HANDOVER §6. + +``` +Full prose expansion — complete (or: partial — resumes at section ). +- Sections expanded: / (or: cursor at section ) +- Premise established: +- Length: words (full-prose target) +- Voice-match: [OPERATØR]/[GATE: voice-trainer] — NOT self-certified +Draft written: /NN-utkast.md (full-prose state — Steps 7/8 render this exact file) Next: Step 4 — Consistency + quality. ``` @@ -749,14 +1000,15 @@ Edition complete. Visible in /linkedin:calendar; mark live via /linkedin:calenda ## Reference Files -- `${CLAUDE_PLUGIN_ROOT}/config/edition-state.template.json` — edition-state schema (11 phases) +- `${CLAUDE_PLUGIN_ROOT}/config/edition-state.template.json` — edition-state schema (13 phases including v2.1 skeleton + spine-prose gates) - `${CLAUDE_PLUGIN_ROOT}/config/edition-config.template.json` — static delivery metadata schema (calendar, freshness, credit, captions) — Step 8 - `${CLAUDE_PLUGIN_ROOT}/config/edition-delingstekst.template.md` — distribution-copy grammar (`## Del N —` / `## Samle`) — Steps 8/9 - `${CLAUDE_PLUGIN_ROOT}/config/edition-HANDOVER.template.md` — narrative production-state structure (§1–§6) — Step 0 - `${CLAUDE_PLUGIN_ROOT}/config/personas.template.md` — reusable reader personas + "primær trumfer" rule - `${CLAUDE_PLUGIN_ROOT}/agents/fact-checker.md` — Step 5 fact-check agent (risk-sorted, guilty-until-disproven) -- `${CLAUDE_PLUGIN_ROOT}/agents/persona-reviewer.md` — Step 6/9 reader jury (resonance + conversion modes) +- `${CLAUDE_PLUGIN_ROOT}/agents/persona-reviewer.md` — Step 2.5/6/9 reader jury (skeleton + resonance + conversion modes) - `${CLAUDE_PLUGIN_ROOT}/commands/react.md` — multi-source synthesis discipline (reused in Step 2) - `${CLAUDE_PLUGIN_ROOT}/assets/voice-samples/authentic-voice-samples.md` — voice matching +- `${CLAUDE_PLUGIN_ROOT}/references/longform-quality-rules.md` — canonical long-form rules (Steps 2.5, 3a, 3b, 4–9 all reference) - `${CLAUDE_PLUGIN_ROOT}/render/build-linkedin.mjs` — POST.html delivery (Step 8) - `${CLAUDE_PLUGIN_ROOT}/render/build-html.mjs` — annotatable review renderer (Step 7) diff --git a/plugins/linkedin-thought-leadership/config/edition-state.template.json b/plugins/linkedin-thought-leadership/config/edition-state.template.json index ef3463c..0285388 100644 --- a/plugins/linkedin-thought-leadership/config/edition-state.template.json +++ b/plugins/linkedin-thought-leadership/config/edition-state.template.json @@ -8,7 +8,9 @@ "load-context — read state/HANDOVER, voice profile, persona library, series brief (Step 0)", "brief-calibration — angle, voice, audience personas, key points, leader-takeaway (Step 1)", "research — parallel scoped mandates → verified notes, triangulation (Step 2)", - "draft — dramaturgical order, voice-matched; may span sessions (Step 3)", + "skeleton-pitch — five-line skeleton (premise/problem/recommendation/payoff/forward) + section pitches, operator gate + persona-skjelett-sweep BEFORE prose (Step 2.5)", + "spine-prose — one paragraph per section against the gated skeleton, operator gate BEFORE full expansion (Step 3a)", + "draft — full prose expansion against the gated spine; may span sessions (Step 3b)", "consistency-quality — threads, premise→conclusion arc, AI-slop removal, formatting dose (Step 4)", "factcheck-sweep — risk-sorted, guilty-until-disproven, verification log (Step 5)", "persona-sweep-prelock — reader jury, primary wins, convergence to clean YES (Step 6)", diff --git a/plugins/linkedin-thought-leadership/references/longform-quality-rules.md b/plugins/linkedin-thought-leadership/references/longform-quality-rules.md index 875c4d3..a8d9566 100644 --- a/plugins/linkedin-thought-leadership/references/longform-quality-rules.md +++ b/plugins/linkedin-thought-leadership/references/longform-quality-rules.md @@ -117,15 +117,43 @@ Ask once if the Step 1 brief did not already settle it. Do not assume an aggressiveness; the same draft can be tightened conservatively or aggressively and the operator owns that dial. +### 8. Skjelett før prosa (skeleton before prose — pre-condition for every other rule) + +The argument-line — premiss, problem, anbefaling, gevinst, vei videre — must +be **explicit, visible, and confirmed** before the first sentence of prose is +written. None of the other rules can bite reliably on a draft whose spine was +never declared: Rule 1 (leder-takeaway) and Rule 2 (premiss→konklusjon-bue) in +particular collapse into post-hoc reconstruction if the spine was never gated. + +- Write the five-line skeleton (premiss / problem / anbefaling / gevinst / vei + videre) and the section pitches **before any prose**. Both the operator and + the persona-skjelett-sweep (`persona-reviewer` mode: skjelett) must say JA on + this skeleton before Step 3a (spine prose) starts. +- A spine error caught at the skeleton stage costs 5–15 min; the same error + caught at Step 6 (resonance) costs 4–12 h; caught post-lock it costs a day + of cascading rework. The cheapest gate is also the earliest. +- The skeleton format is **identical to the Maskinrommet writing-contract §A** + (premiss / problem / anbefaling / gevinst / vei videre). Pipeline editions + produced through `/linkedin:newsletter` therefore satisfy that contract at + the structural level by construction. + +**Pass/flag:** PASS when the skeleton + pitches exist as `/NN-skjelett.md` +and both the operator-gate AND the persona-skjelett-sweep returned JA before +prose started; FLAG retroactively if a draft turns out to have skipped this gate +(treat as a process miss and harvest the lesson — do not retrofit a skeleton +to a finished draft and call it gated). + --- ## How the pipeline uses these rules | Phase | Where the rules bite | |-------|----------------------| -| Step 4 — Consistency + quality | Primary enforcement: apply rules 1–6, calibrate per rule 7, report a pass/flag per rule. | +| Step 2.5 — Skeleton + section pitch | Primary enforcement of rule 8: skeleton + pitches MUST exist and be JA from operator + persona-skjelett-sweep before prose. | +| Step 3a — Spine prose | Rule 6 applies even within spine prose (tighten, don't expand the spine); rule 8 is the gate that lets 3a start. | +| Step 4 — Consistency + quality | Primary enforcement: apply rules 1–6, calibrate per rule 7, report a pass/flag per rule. Rule 8 is verified as historical fact (skeleton existed + was gated). | | Step 5 — Fact-check sweep | Fixes obey rule 6 (tighten, don't expand). | -| Step 6 — Persona sweep (pre-lock) | Rework obeys rule 6; the leader-takeaway (rule 1) and arc (rule 2) are what the reader jury judges for resonance. | +| Step 6 — Persona sweep (pre-lock) | Rework obeys rule 6; the leader-takeaway (rule 1) and arc (rule 2) are what the reader jury judges for resonance. A draft that passed rule 8 typically lands here with far fewer spine-level reworks. | | Step 9 — Hook / conversion gate | Hook revisions obey rule 6 (sharpen the krok by tightening, body stays locked). | ## Self-certification boundary