feat(linkedin): v2.2.0 — harden longform gates from 2nd production run
Implements the 6-change spec from the Seres-serien production (linkedin-plugin-endringsspec.md). All acceptance criteria met. 1. Avoid-patterns (modell-/navne-katalog, completeness-over-reader-action, self-referential overhead openings) → longform-quality-rules.md (rule 1+3) + user-profile.template.md. 2. Persona gate now BLOCKING with explicit hard-fail list (primær mistet meg / doesn't own action / sjargong-mur / modell-navne-katalog → BLOCK; "JA med store forbehold" = NEI) → persona-reviewer.md + personas.template.md. 3. Fact-check declared orthogonal to narrative strength + post-cutoff web-search mandate + high-frequency-error checklist → fact-checker.md. 4. NEW agent voice-scrubber.md (Opus) — de-AI scrub + Norwegian-chronicle voice-drift; gold standard = approved Norwegian editions, NOT the English post corpus. Wired into newsletter.md Step 4. 5. Operator gates = render+annotate rounds (build-html.mjs to file://) as primary flow, AskUserQuestion as receipt/fallback → newsletter.md 2.5+3a. 6. Edition state reconciled with STATE.md (ONE-system). edition-HANDOVER template deleted; narrative to <serie>/STATE.md, machine data (factcheckLog, personaSweep, immutableRules) to edition-state.json. Agents 14 to 15; commands unchanged (24). Backward-compatible (additive state-shape only). Docs updated across all three levels + CHANGELOG. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2a27a7cd6a
commit
4ed9717627
15 changed files with 494 additions and 152 deletions
|
|
@ -9,7 +9,7 @@ plugins/
|
||||||
ai-psychosis/ v1.0.0 — Interaction awareness (sycophancy, reinforcement loops)
|
ai-psychosis/ v1.0.0 — Interaction awareness (sycophancy, reinforcement loops)
|
||||||
config-audit/ v3.1.0 — Configuration intelligence (health, opportunities, auto-fix, whats-active)
|
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)
|
graceful-handoff/ v2.1.0 — Auto-trigger handoff via Stop hook (skill + JSON pipeline + 4-step model-aware context resolution)
|
||||||
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).
|
linkedin-thought-leadership/ v2.2.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 added skeleton-gate BEFORE prose (Step 2.5 + Step 3a) + third `persona-reviewer` mode (`skjelett`); pipeline 11→13 phases. v2.2.0 hardens the longform gates (2nd production run): blocking persona hard-fails (mistet meg / doesn't own action / sjargong-mur / modell-navne-katalog → BLOCK), fact-check post-cutoff web-search mandate + orthogonal-to-narrative rule, new `voice-scrubber` agent (Opus, de-AI + Norwegian-chronicle voice; gold standard = approved Norwegian editions NOT English post corpus), render+annotate operator gates (2.5/3a), and edition-state reconciled with STATE.md (`edition-HANDOVER.md` deleted). Agents 14→15; commands unchanged (24). 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.
|
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)
|
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
|
okr/ v1.0.0 — OKR guidance for Norwegian public sector
|
||||||
|
|
|
||||||
11
README.md
11
README.md
|
|
@ -206,14 +206,19 @@ Key commands: `/architect`, `/architect:ros`, `/architect:security`, `/architect
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### [LinkedIn Thought Leadership](plugins/linkedin-thought-leadership/) `v2.1.0`
|
### [LinkedIn Thought Leadership](plugins/linkedin-thought-leadership/) `v2.2.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.
|
||||||
|
|
||||||
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.
|
v2.2.0 **hardens the longform gates** with the lessons from the second `/linkedin:newsletter` production run (Seres-serien): the persona gate is now **blocking with an explicit hard-fail list** (primær «mistet meg» / doesn't own the action / sjargong-mur / modell-/navne-katalog → BLOCK; «JA med store forbehold» = NEI); fact-check is **orthogonal to narrative strength** with a **post-cutoff web-search mandate** + high-frequency-error checklist; a new **`voice-scrubber`** agent (Opus) does de-AI scrub + Norwegian-chronicle voice-drift correction (gold standard = approved Norwegian editions, NOT the English post corpus); operator gates become **render+annotate** rounds; and per-edition state is **reconciled with the global STATE.md** continuity system (`edition-HANDOVER.md` removed). Agents 14 → 15; commands unchanged (24). v2.1.0's skeleton-gate-before-prose and v2.0.0's full-spectrum surface are preserved. Updated for the January 2026 360Brew algorithm change, which validates your creator profile before distributing content.
|
||||||
|
|
||||||
|
- **Blocking persona hard-fails (v2.2)** — `persona-reviewer` + `personas.template.md` make primær «mistet meg», doesn't-own-the-action, sjargong-mur, and modell-/navne-katalog BLOCK-level rewrites, not annotations. The bar is the primær reader's *clean* JA.
|
||||||
|
- **Fact-check orthogonal to polish (v2.2)** — `fact-checker` web-searches every post-cutoff claim (never confirms from memory) and runs an explicit checklist for person titles, org-varying "standards", over-credited studies, source scope, and founding/release years.
|
||||||
|
- **New `voice-scrubber` agent (v2.2, Opus)** — aggressive de-AI scrub (Pass 1) + Norwegian-chronicle voice-drift correction (Pass 2), calibrated to the **approved Norwegian editions** rather than the English post corpus; wired into Step 4. *New agent — requires a session reload before invokable.*
|
||||||
|
- **Render+annotate operator gates (v2.2)** — Steps 2.5/3a surface an annotatable `file://` review page (`build-html.mjs`) as the primary operator-review flow; `AskUserQuestion` becomes a receipt + fallback.
|
||||||
|
- **STATE.md-reconciled edition state (v2.2)** — narrative state in `<serie>/STATE.md` (auto-injected, overwritten each phase), machine state in `edition-state.json`; no separate `edition-HANDOVER.md`.
|
||||||
- **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 `<serie>/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.
|
- **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 `<serie>/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
|
- **Long-form `/linkedin:newsletter` orchestrator** — multi-session 13-phase pipeline (research → **skeleton + persona-skjelett-sweep** → **spine prose** → full prose draft → **de-AI/voice scrub** → 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)
|
- **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
|
- **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
|
- **Guided onboarding** — `/linkedin:onboarding` walks new users through profile → setup → first post in one flow
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "linkedin-thought-leadership",
|
"name": "linkedin-thought-leadership",
|
||||||
"version": "2.1.0",
|
"version": "2.2.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.",
|
"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.2 hardens the longform gates: blocking persona hard-fails, post-cutoff fact-check mandate, a Norwegian-chronicle de-AI voice-scrubber, render+annotate operator gates, and STATE.md-reconciled edition state.",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Kjell Tore Guttormsen"
|
"name": "Kjell Tore Guttormsen"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,28 @@ 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).
|
||||||
|
|
||||||
|
## [2.2.0] - 2026-05-28
|
||||||
|
|
||||||
|
### Summary
|
||||||
|
Longform gates hardened with the lessons from the second `/linkedin:newsletter` production run (Seres-serien). A chronicle built as a model/name catalog passed persona review (its flags were read as notes, not stop-signs) and nearly shipped; the rewrite was stronger but introduced fresh factual errors. v2.2.0 closes six concrete weaknesses: the persona gate becomes blocking with an explicit hard-fail list, fact-check is made orthogonal to narrative strength (more polish → more verification) with a post-cutoff web-search mandate, a new Norwegian-chronicle de-AI voice-scrubber is added and wired into Step 4, operator gates become render+annotate rounds, and per-edition production state is reconciled with the global STATE.md continuity system (no more `edition-HANDOVER.md`). 14 → 15 agents; commands unchanged (24). Backward-compatible — the only state-shape change is additive.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- **`agents/voice-scrubber.md`** (new, Opus) — aggressive de-AI scrubber + voice-drift corrector for long-form **Norwegian chronicle** drafts. Pass 1 strips objective AI-tells («la meg være ærlig», reflex rule-of-three, em-dash-spam, self-referential overhead, modell-/navne-katalog); Pass 2 corrects drift toward the chronicle voice; Pass 3 appends to a chronicle-voice-drift-log so it sharpens over editions. **Calibration rule (cardinal):** gold standard = the approved Norwegian editions, NEVER `assets/voice-samples/authentic-voice-samples.md` (English short-form, forbids the em-dash). *New agent — requires a session reload before it is invokable.*
|
||||||
|
- **De-AI / voice scrub sub-pass** in `commands/newsletter.md` Step 4 — fans out `voice-scrubber` (foreground, namespaced) with the draft + approved-Norwegian-edition paths as the gold standard.
|
||||||
|
- **Blocking hard-fail list** in `agents/persona-reviewer.md` + `config/personas.template.md` — primær «mistet meg» / doesn't own the action / sjargong-mur / modell-/navne-katalog → BLOCK regardless of other axes. «JA med store forbehold» = NEI.
|
||||||
|
- **Post-cutoff fact-check mandate + high-frequency-error checklist** in `agents/fact-checker.md` — claims dated after the model's knowledge cutoff MUST be web-searched; explicit checks for person titles, org-varying "standards", over-credited studies, source scope, and founding/release years. Fact-check declared orthogonal to narrative strength.
|
||||||
|
- **Render+annotate operator gates** in `commands/newsletter.md` Steps 2.5 + 3a — HTML annotation via `render/build-html.mjs` → `file://` link is the primary operator-review flow; `AskUserQuestion` becomes a receipt + fallback.
|
||||||
|
- **Avoid-patterns** — modell-/navne-katalog, completeness-over-reader-action, self-referential overhead openings added to `references/longform-quality-rules.md` (rules 1 + 3) and `config/user-profile.template.md`.
|
||||||
|
- **`personaSweep.skeleton` + `immutableRules`** fields in `config/edition-state.template.json` (additive).
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- **Edition production state reconciled with STATE.md (ONE-system).** `commands/newsletter.md` Step 0 now reads `<serie>/STATE.md` (auto-injected by the session-start hook); every phase writes narrative status to `<serie>/STATE.md` (overwrite) and machine state (fact-check log, persona verdicts, immutable rules) to `edition-state.json`. All `HANDOVER §4/§5/§6` references replaced.
|
||||||
|
- `agents/fact-checker.md` principle 3 strengthened to make web search mandatory for post-cutoff claims.
|
||||||
|
- README, CLAUDE.md, root README, plugin.json version + descriptions.
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
- **`config/edition-HANDOVER.template.md`** — deleted. The plugin no longer ships or requires a separate handover mechanism; `<serie>/STATE.md` + `edition-state.json` carry its content per the global continuity rule.
|
||||||
|
|
||||||
## [2.1.0] - 2026-05-28
|
## [2.1.0] - 2026-05-28
|
||||||
|
|
||||||
### Summary
|
### Summary
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# LinkedIn Thought Leadership Plugin (v2.1.0)
|
# LinkedIn Thought Leadership Plugin (v2.2.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`). **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).
|
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 added two gates BEFORE prose (Step 2.5 skeleton + Step 3a spine prose) + a third `persona-reviewer` mode (`skjelett`). **v2.2.0** hardens the longform gates with the lessons from the second production run (Seres-serien): the persona gate is now **blocking with an explicit hard-fail list** (primær «mistet meg» / doesn't own the action / sjargong-mur / modell-/navne-katalog → BLOCK; «JA med store forbehold» = NEI); fact-check is declared **orthogonal to narrative strength** with a **post-cutoff web-search mandate** + high-frequency-error checklist; a new **`voice-scrubber`** agent (Opus) does de-AI scrub + Norwegian-chronicle voice-drift correction (gold standard = approved Norwegian editions, NOT the English post corpus) wired into Step 4; operator gates become **render+annotate** rounds (Steps 2.5/3a); and per-edition production state is **reconciled with the global STATE.md** continuity system — `edition-HANDOVER.md` is gone. Agents 14 → 15; commands unchanged (24).
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
|
|
@ -63,7 +63,7 @@ All content commands (post, quick, react, pipeline, first-post, video, multiplat
|
||||||
| `/linkedin:outreach` | Outreach orchestrator — collaborations + speaking opportunities (unlocks at ~1K followers) |
|
| `/linkedin:outreach` | Outreach orchestrator — collaborations + speaking opportunities (unlocks at ~1K followers) |
|
||||||
| `/linkedin:profile` | 360Brew profile optimization |
|
| `/linkedin:profile` | 360Brew profile optimization |
|
||||||
|
|
||||||
## Agents (14)
|
## Agents (15)
|
||||||
|
|
||||||
| Agent | Model | Color | Responsibility |
|
| Agent | Model | Color | Responsibility |
|
||||||
|-------|-------|-------|----------------|
|
|-------|-------|-------|----------------|
|
||||||
|
|
@ -79,8 +79,9 @@ All content commands (post, quick, react, pipeline, first-post, video, multiplat
|
||||||
| `differentiation-checker` | Sonnet | Gray | Originality scoring + commodity detection |
|
| `differentiation-checker` | Sonnet | Gray | Originality scoring + commodity detection |
|
||||||
| `post-feedback-monitor` | Haiku | Lime | Post-publish 48h monitoring |
|
| `post-feedback-monitor` | Haiku | Lime | Post-publish 48h monitoring |
|
||||||
| `video-scripter` | Sonnet | Violet | Video script creation with pacing |
|
| `video-scripter` | Sonnet | Violet | Video script creation with pacing |
|
||||||
| `fact-checker` | Opus | Brown | Factual-claim verification against primary sources (longform) |
|
| `fact-checker` | Opus | Brown | Factual-claim verification against primary sources, post-cutoff web-search mandate (longform) |
|
||||||
| `persona-reviewer` | Opus | Olive | Reader-persona skeleton (v2.1, before prose) + resonance (before lock) + hook-conversion (after lock) gate (longform) |
|
| `persona-reviewer` | Opus | Olive | Reader-persona skeleton (v2.1, before prose) + resonance (before lock) + hook-conversion (after lock) gate, blocking hard-fail list (longform) |
|
||||||
|
| `voice-scrubber` | Opus | Red | De-AI scrub + Norwegian-chronicle voice-drift correction; gold standard = approved Norwegian editions, not the English post corpus (longform, v2.2) |
|
||||||
|
|
||||||
**Rule:** Always read `assets/voice-samples/` before generating content.
|
**Rule:** Always read `assets/voice-samples/` before generating content.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,20 +6,21 @@
|
||||||
|
|
||||||
*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)*
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||

|

|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
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.
|
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. **v2.2.0** hardens the longform gates with the lessons from the next production run: blocking persona hard-fails (primær «mistet meg» / doesn't own the action / jargon wall / model-name catalog → BLOCK), a post-cutoff fact-check mandate, a new Norwegian-chronicle de-AI voice-scrubber agent, render+annotate operator gates, and edition state reconciled with the global STATE.md continuity system. 24 slash commands, 15 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
|
## Table of Contents
|
||||||
|
|
||||||
|
- [What's New in v2.2.0](#whats-new-in-v220)
|
||||||
- [What's New in v2.1.0](#whats-new-in-v210)
|
- [What's New in v2.1.0](#whats-new-in-v210)
|
||||||
- [What's New in v2.0.0](#whats-new-in-v200)
|
- [What's New in v2.0.0](#whats-new-in-v200)
|
||||||
- [What Is This?](#what-is-this)
|
- [What Is This?](#what-is-this)
|
||||||
|
|
@ -40,6 +41,21 @@ A comprehensive Claude Code plugin that turns LinkedIn from a chore into a full-
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## What's New in v2.2.0
|
||||||
|
|
||||||
|
**Longform gates hardened** — the second production run (Seres-serien) surfaced six concrete weaknesses; v2.2.0 closes all of them. A chronicle built as a model/name catalog passed review (flags were read as notes, not stop-signs) and nearly shipped; the rewrite was better but introduced fresh factual errors. The gates now make both failure modes blocking.
|
||||||
|
|
||||||
|
- **Persona gate is blocking, with an explicit hard-fail list** (`agents/persona-reviewer.md`, `config/personas.template.md`). The bar is the primær reader's *clean* JA — «JA med store forbehold» = NEI. Hard fails (= rewrite, not annotate): primær «mistet meg», primær doesn't own the action, **sjargong-mur**, **modell-/navne-katalog**. Any one → BLOCK regardless of the other axes.
|
||||||
|
- **Fact-check is orthogonal to narrative strength** (`agents/fact-checker.md`). The more convincing a draft reads, the *more* verification — not less. Claims dated after the model's knowledge cutoff **MUST** be web-searched (never confirmed from memory), plus an explicit checklist for the high-frequency error types (person titles, org-varying "standards", over-credited studies, source scope, founding/release years).
|
||||||
|
- **New `voice-scrubber` agent** (Opus) — aggressive de-AI scrub (Pass 1, objective: «la meg være ærlig», reflex rule-of-three, em-dash-spam, self-referential overhead, modell-/navne-katalog) + voice-drift correction (Pass 2, calibrated). **Gold standard = the approved Norwegian editions, NOT the English `authentic-voice-samples.md`** (which forbids the em-dash and would degrade chronicle voice). Wired into Step 4 of `/linkedin:newsletter`. *(New agent — requires a session reload before it is invokable.)*
|
||||||
|
- **Render+annotate operator gates** (`commands/newsletter.md` Steps 2.5, 3a). The operator review is HTML annotation in the browser (`render/build-html.mjs` → `file://` link), not a multiple-choice prompt — for every write deliverable, skeleton included. `AskUserQuestion` becomes a receipt + fallback.
|
||||||
|
- **Edition state reconciled with STATE.md** (ONE-system). `edition-HANDOVER.md` is gone; narrative state lives in `<serie>/STATE.md` (overwritten each phase, auto-injected by the session-start hook), machine state (fact-check log, persona verdicts, immutable rules) in `edition-state.json`. `config/edition-HANDOVER.template.md` deleted.
|
||||||
|
- **Voice-profile + longform-rules avoid-patterns** — modell-/navne-katalog, completeness-over-reader-action, and self-referential overhead openings added to `references/longform-quality-rules.md` (rules 1 + 3) and `config/user-profile.template.md`.
|
||||||
|
|
||||||
|
15 agents (was 14). No command-count change (24). Backward-compatible: existing editions resume by `currentPhase`; the only state-shape change is additive (`personaSweep.skeleton`, `immutableRules`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## What's New in v2.1.0
|
## 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).
|
**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).
|
||||||
|
|
@ -200,7 +216,7 @@ All 24 commands use colon notation: `/linkedin:post`, `/linkedin:quick`, etc.
|
||||||
|
|
||||||
## Agent Architecture
|
## Agent Architecture
|
||||||
|
|
||||||
The plugin delegates specialized work to 14 purpose-built agents. Each agent has its own model assignment, color identity, and focused responsibility.
|
The plugin delegates specialized work to 15 purpose-built agents. Each agent has its own model assignment, color identity, and focused responsibility.
|
||||||
|
|
||||||
| Agent | Model | Color | Primary Responsibility |
|
| Agent | Model | Color | Primary Responsibility |
|
||||||
|-------|-------|-------|----------------------|
|
|-------|-------|-------|----------------------|
|
||||||
|
|
@ -216,8 +232,9 @@ The plugin delegates specialized work to 14 purpose-built agents. Each agent has
|
||||||
| `differentiation-checker` | Sonnet | Gray | Originality scoring and commodity content detection |
|
| `differentiation-checker` | Sonnet | Gray | Originality scoring and commodity content detection |
|
||||||
| `post-feedback-monitor` | Haiku | Lime | Post-publish 48h monitoring and real-time interventions |
|
| `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 |
|
| `video-scripter` | Sonnet | Violet | Video script creation with pacing and visual cues |
|
||||||
| `fact-checker` | Opus | Brown | Factual-claim verification against primary/credible sources (longform) |
|
| `fact-checker` | Opus | Brown | Factual-claim verification against primary/credible sources, post-cutoff web-search mandate (longform) |
|
||||||
| `persona-reviewer` | Opus | Olive | Reader-persona **skeleton** (v2.1, before prose) + **resonance** (before lock) + **hook-conversion** (after lock) gate (longform) |
|
| `persona-reviewer` | Opus | Olive | Reader-persona **skeleton** (v2.1, before prose) + **resonance** (before lock) + **hook-conversion** (after lock) gate, blocking hard-fail list (longform) |
|
||||||
|
| `voice-scrubber` | Opus | Red | De-AI scrub + Norwegian-chronicle voice-drift correction; gold standard = approved Norwegian editions, not the English post corpus (longform, v2.2) |
|
||||||
|
|
||||||
### Content Pipeline
|
### Content Pipeline
|
||||||
|
|
||||||
|
|
@ -235,7 +252,7 @@ trend-spotter --> content-planner --> differentiation-checker --> content-optimi
|
||||||
|
|
||||||
Parallel support agents: `strategy-advisor`, `analytics-interpreter`, `network-builder`, `content-repurposer`, `video-scripter`.
|
Parallel support agents: `strategy-advisor`, `analytics-interpreter`, `network-builder`, `content-repurposer`, `video-scripter`.
|
||||||
|
|
||||||
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).
|
Longform quality gates (newsletter): **`persona-reviewer` (skjelett) run BEFORE prose** (v2.1, Step 2.5) → `voice-scrubber` de-AI / chronicle-voice scrub (v2.2, Step 4) → `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**
|
> **Note (agent invocation + reload):** Commands invoke agents by their **namespaced**
|
||||||
> type — `subagent_type: linkedin-thought-leadership:<name>`, never the bare name. And a
|
> type — `subagent_type: linkedin-thought-leadership:<name>`, never the bare name. And a
|
||||||
|
|
@ -545,6 +562,7 @@ Scheduled posts are tracked in `assets/drafts/queue.json`:
|
||||||
|
|
||||||
| Version | Date | Highlights |
|
| Version | Date | Highlights |
|
||||||
|---------|------|-----------|
|
|---------|------|-----------|
|
||||||
|
| **2.2.0** | 2026-05-28 | Longform gates hardened (2nd production run). Persona gate blocking with explicit hard-fail list (primær mistet meg / doesn't own action / sjargong-mur / modell-navne-katalog → BLOCK; «JA med forbehold» = NEI). Fact-check post-cutoff web-search mandate + high-frequency-error checklist. New `voice-scrubber` agent (Opus): de-AI scrub + Norwegian-chronicle voice-drift, gold standard = approved Norwegian editions (NOT the English post corpus). Render+annotate operator gates (Steps 2.5/3a). Edition state reconciled with STATE.md (ONE-system); `edition-HANDOVER.template.md` deleted. 14 → 15 agents; commands unchanged (24). |
|
||||||
| **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.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`. |
|
| **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.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). |
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,30 @@ Before searching, identify:
|
||||||
- **Out of scope:** Opinions, predictions, and value judgments are NOT claims to
|
- **Out of scope:** Opinions, predictions, and value judgments are NOT claims to
|
||||||
verify. Mark them as opinion and move on — do not score them.
|
verify. Mark them as opinion and move on — do not score them.
|
||||||
|
|
||||||
|
**Fact-check is orthogonal to narrative strength.** The more convincing a draft
|
||||||
|
reads, the MORE source-verification it needs — not less. A fluent, confident
|
||||||
|
passage is exactly where a wrong fact hides best; never let polish lower the bar.
|
||||||
|
|
||||||
|
**Post-cutoff mandate (non-negotiable).** Any claim dated *after the model's
|
||||||
|
knowledge cutoff* — a recent appointment, a 2025/2026 figure, a just-announced
|
||||||
|
product, a current title — **MUST be web-searched.** Never confirm such a claim
|
||||||
|
from memory; memory cannot contain it. An unsearched post-cutoff claim defaults
|
||||||
|
to 🟡 at best, 🔴 if precise.
|
||||||
|
|
||||||
|
**High-frequency error types — check these explicitly:**
|
||||||
|
- **Person titles / roles** — someone may have left, changed role, or never held
|
||||||
|
the title claimed. Verify the title *as of now*, not as of training.
|
||||||
|
- **«Standards» that actually vary** — practices presented as universal often
|
||||||
|
differ per organization/jurisdiction. Flag a claimed standard that is really a
|
||||||
|
local convention.
|
||||||
|
- **Studies credited with too-strong findings** — a study cited as proving X
|
||||||
|
often only suggested X, or measured something narrower. Check what it actually
|
||||||
|
concluded.
|
||||||
|
- **Source scope** — distinguish what a source *concluded* from what was *outside
|
||||||
|
its scope*. A source silent on X does not support a claim about X.
|
||||||
|
- **Start / founding / release years** — dates of founding, launch, or release are
|
||||||
|
frequently misremembered by a year or more. Verify the exact year.
|
||||||
|
|
||||||
### Step 2: Search for Primary / Credible Sources (3-5 searches per claim)
|
### Step 2: Search for Primary / Credible Sources (3-5 searches per claim)
|
||||||
|
|
||||||
Prefer primary sources (the originating document, dataset, or official record)
|
Prefer primary sources (the originating document, dataset, or official record)
|
||||||
|
|
@ -207,7 +231,9 @@ Aggregate the per-claim verdicts into a publish decision:
|
||||||
2. **Never fill gaps with guesses.** No invented sources, no plausible numbers.
|
2. **Never fill gaps with guesses.** No invented sources, no plausible numbers.
|
||||||
"Cannot verify" is a complete, acceptable answer.
|
"Cannot verify" is a complete, acceptable answer.
|
||||||
3. **Search before judging.** Never assign a verdict without running searches.
|
3. **Search before judging.** Never assign a verdict without running searches.
|
||||||
Web search is non-negotiable.
|
Web search is non-negotiable — and **mandatory** for any claim dated after the
|
||||||
|
model's knowledge cutoff (titles, recent figures, new releases). Memory cannot
|
||||||
|
verify what postdates it.
|
||||||
4. **Primary over secondary.** Trace claims to the originating document, not the
|
4. **Primary over secondary.** Trace claims to the originating document, not the
|
||||||
blog post that summarized it.
|
blog post that summarized it.
|
||||||
5. **Precision matters.** "Exactly 37%" needs an exact source; a directional
|
5. **Precision matters.** "Exactly 37%" needs an exact source; a directional
|
||||||
|
|
|
||||||
|
|
@ -216,8 +216,11 @@ does not).
|
||||||
pitches and re-runs the sweep. *Never let prose start on a REWORK 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.*
|
the entire point of this gate is to catch spine errors before prose.*
|
||||||
- **BLOCK** — primær = MANGLER on Premiss or Anbefaling (the reader cannot
|
- **BLOCK** — primær = MANGLER on Premiss or Anbefaling (the reader cannot
|
||||||
accept the premise, or there is no actionable direction). Must be reworked
|
accept the premise, or there is no actionable direction), **OR a section pitch
|
||||||
before any prose; this is the dangerous failure mode the gate exists for.
|
promises a modell-/navne-katalog or a sjargong-mur** (see the hard-fail
|
||||||
|
conditions under the resonance gate — catching them at the pitch stage is
|
||||||
|
cheapest). Must be reworked before any prose; this is the dangerous failure
|
||||||
|
mode the gate exists for.
|
||||||
|
|
||||||
**Gate decision (resonance mode):**
|
**Gate decision (resonance mode):**
|
||||||
|
|
||||||
|
|
@ -226,11 +229,34 @@ does not).
|
||||||
- **REWORK** — primær = NEI, or a fixable DELVIS/IKKE that the editor should
|
- **REWORK** — primær = NEI, or a fixable DELVIS/IKKE that the editor should
|
||||||
address. Provide the flags as direction; editor decides.
|
address. Provide the flags as direction; editor decides.
|
||||||
- **BLOCK** — primær = NEI on Krok or Leder-takeaway (the reader never starts, or
|
- **BLOCK** — primær = NEI on Krok or Leder-takeaway (the reader never starts, or
|
||||||
leaves with nothing to do). Must be reworked before lock.
|
leaves with nothing to do), **OR any hard-fail condition below is present for
|
||||||
|
the primær.** Must be reworked before lock.
|
||||||
|
|
||||||
**Conversion mode** has no gate ladder — only the binary click verdict (JA / NEI)
|
**Conversion mode** has no gate ladder — only the binary click verdict (JA / NEI)
|
||||||
and one reason.
|
and one reason.
|
||||||
|
|
||||||
|
### Hard-fail conditions (blocking — rewrite, do NOT annotate)
|
||||||
|
|
||||||
|
The bar is **the primær persona's genuine JA.** The following are *hard fails*:
|
||||||
|
the verdict is **NEI** and the gate is **BLOCK** regardless of how the other axes
|
||||||
|
score. These are rewrite triggers, not notes the editor can wave through:
|
||||||
|
|
||||||
|
1. **The primær «mistet meg».** The primær reader disengaged anywhere before the
|
||||||
|
takeaway — they stopped reading, skimmed past the point, or could not follow.
|
||||||
|
2. **The primær does not own the action.** The leader-takeaway's action belongs to
|
||||||
|
someone else (a technician, a different role) — the primær cannot act on it
|
||||||
|
from their own chair.
|
||||||
|
3. **Sjargong-mur (jargon wall).** A wall of technical vocabulary the primær's
|
||||||
|
`sjargong` field rejects — the reader hits language that assumes they can read
|
||||||
|
the code.
|
||||||
|
4. **Modell-/navne-katalog.** A run of product names, model names, or benchmarks
|
||||||
|
listed for completeness. To the primær this reads as a jargon wall; it is the
|
||||||
|
exact failure mode the Seres process nearly shipped.
|
||||||
|
|
||||||
|
**«JA med store forbehold» = NEI.** A hedged, qualified, or reluctant yes is not
|
||||||
|
a JA. Only a clean, unqualified primær JA passes the gate. Do not soften a
|
||||||
|
hard-fail BLOCK to REWORK to be agreeable.
|
||||||
|
|
||||||
## Convergence Loop
|
## Convergence Loop
|
||||||
|
|
||||||
Re-run per persona until the primær returns a clean JA. Each round: the editor
|
Re-run per persona until the primær returns a clean JA. Each round: the editor
|
||||||
|
|
@ -324,8 +350,11 @@ the skeleton + pitches (NOT prose — there is none yet) and re-runs this sweep.
|
||||||
in every mode, including skjelett (do not hand back a fixed skeleton).
|
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
|
2. **One persona per run.** Judge as that named reader, with their fields — not as
|
||||||
yourself, not as a generic audience.
|
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
|
3. **Primær trumfer — and a hedged JA is a NEI.** A primær NO keeps the loop open;
|
||||||
signal the gate works, not a defect to chase.
|
a sekundær ceiling-NO is a signal the gate works, not a defect to chase. The
|
||||||
|
bar is the primær's *clean, unqualified* JA — «JA med store forbehold» = NEI.
|
||||||
|
The hard-fail conditions (primær mistet meg / does not own the action /
|
||||||
|
sjargong-mur / modell-/navne-katalog) are BLOCK-level rewrites, never notes.
|
||||||
4. **Land, don't correct.** You judge whether it *works for this reader* — not
|
4. **Land, don't correct.** You judge whether it *works for this reader* — not
|
||||||
whether it is true (fact-checker) or original (differentiation-checker).
|
whether it is true (fact-checker) or original (differentiation-checker).
|
||||||
5. **Flag cap matches the mode.** Skjelett ≤ 3, resonans ≤ 5, konverter = 0
|
5. **Flag cap matches the mode.** Skjelett ≤ 3, resonans ≤ 5, konverter = 0
|
||||||
|
|
|
||||||
184
plugins/linkedin-thought-leadership/agents/voice-scrubber.md
Normal file
184
plugins/linkedin-thought-leadership/agents/voice-scrubber.md
Normal file
|
|
@ -0,0 +1,184 @@
|
||||||
|
---
|
||||||
|
name: voice-scrubber
|
||||||
|
description: |
|
||||||
|
Aggressive de-AI / voice scrubber for long-form Norwegian chronicle drafts.
|
||||||
|
Strips everything that reads as LLM-generated (tics, hedging, reflex
|
||||||
|
rule-of-three, «la meg være ærlig», em-dash-spam, generic summaries,
|
||||||
|
self-referential overhead) AND corrects drift toward the author's Norwegian
|
||||||
|
chronicle voice — learning that voice better over time from the APPROVED
|
||||||
|
Norwegian editions (the gold standard), never from the English post corpus.
|
||||||
|
|
||||||
|
Use when the user says:
|
||||||
|
- "scrub this draft", "de-AI this", "remove the AI tells"
|
||||||
|
- "does this sound like an AI essay?", "fix the AI voice"
|
||||||
|
- "make this sound like my chronicle voice", "voice scrub"
|
||||||
|
- "strip the slop", "kill the em-dash spam"
|
||||||
|
|
||||||
|
Triggers on: "scrub draft", "de-AI", "remove AI tells", "AI essay", "voice
|
||||||
|
scrub", "strip slop", "sound like my chronicle".
|
||||||
|
model: opus
|
||||||
|
color: red
|
||||||
|
tools: ["Read", "Glob", "Write"]
|
||||||
|
---
|
||||||
|
|
||||||
|
# Voice Scrubber Agent
|
||||||
|
|
||||||
|
You are an aggressive de-AI editor for **long-form Norwegian chronicle** drafts.
|
||||||
|
You do two things, in this order, every run:
|
||||||
|
|
||||||
|
1. **De-AI scrub** — strip *everything* that smells of LLM-generated prose.
|
||||||
|
2. **Voice-drift correction** — pull the draft toward the author's authentic
|
||||||
|
Norwegian chronicle voice, and learn that voice better over time from the
|
||||||
|
approved editions.
|
||||||
|
|
||||||
|
You are sharper and narrower than `voice-trainer` (which builds a general,
|
||||||
|
multi-format, often English-leaning profile) and narrower than `content-optimizer`
|
||||||
|
(short-form algorithm/hook tuning). This agent is calibrated to ONE thing: the
|
||||||
|
author's Norwegian chronicle register, judged against the approved Norwegian
|
||||||
|
editions.
|
||||||
|
|
||||||
|
## ⚠️ Calibration: the gold standard is the APPROVED NORWEGIAN editions
|
||||||
|
|
||||||
|
This is the single most important rule of this agent.
|
||||||
|
|
||||||
|
- The gold standard for Norwegian chronicle voice is the **approved Norwegian
|
||||||
|
editions** (e.g. the series' approved Del 1 + Del 2). The caller passes the
|
||||||
|
path(s); read them as the corpus before scrubbing.
|
||||||
|
- **Do NOT calibrate against `assets/voice-samples/authentic-voice-samples.md`.**
|
||||||
|
That corpus is for **English short-form posts** and encodes rules that are
|
||||||
|
WRONG for Norwegian chronicle — e.g. it forbids the em-dash, which the author
|
||||||
|
*does* use in long-form Norwegian. Using it as the gold standard would actively
|
||||||
|
degrade chronicle voice.
|
||||||
|
- If no approved Norwegian edition is available, say so plainly and scrub only the
|
||||||
|
objective AI-tells (Pass 1); do NOT invent voice corrections from the English
|
||||||
|
corpus or from your own assumptions.
|
||||||
|
|
||||||
|
## Pass 1 — Aggressive de-AI scrub (objective; apply)
|
||||||
|
|
||||||
|
Remove on sight. These are mechanical AI-tells, not matters of taste — strip each
|
||||||
|
and log it. The Norwegian ban-list is canonical in
|
||||||
|
`${CLAUDE_PLUGIN_ROOT}/references/longform-quality-rules.md` (rule 3); this agent
|
||||||
|
enforces it and adds the finer-grained tells below.
|
||||||
|
|
||||||
|
| Tell | What to do |
|
||||||
|
|------|------------|
|
||||||
|
| «la meg være ærlig» / «for å være ærlig» / «her må jeg innrømme» | Cut entirely — forbidden. The honesty is in the argument, not the announcement. |
|
||||||
|
| «ikke bare X, men Y» as a reflex construction | Rewrite to a direct statement. |
|
||||||
|
| Reflex rule-of-three (lists of three used as rhythm, not real enumeration) | Collapse to the one item that carries weight. |
|
||||||
|
| Tacked-on summary sentences that restate the paragraph | Cut. |
|
||||||
|
| Self-referential overhead openings («Det er bra. Det er ikke det denne teksten handler om», meta-commentary, warm-ups) | Cut; start on the reader's problem. |
|
||||||
|
| Throat-clearing openers («i en stadig mer kompleks verden») | Cut. |
|
||||||
|
| Hedging stacks («kanskje», «på mange måter», «i noen grad» piled up) | Cut to the claim; keep at most one genuine qualifier. |
|
||||||
|
| **Em-dash-spam** | Keep em-dashes the author actually uses in the gold standard; cut the *excess* the draft over-produces. This is dose, not prohibition — calibrate the dose against the approved Norwegian editions, never against the English corpus. |
|
||||||
|
| Generic AI summary closers («Alt i alt», «Oppsummert», «Til syvende og sist») | Cut; let the conclusion grip the premise and twist forward (rule 2). |
|
||||||
|
| Modell-/navne-katalog (product/model/benchmark name-dumps) | Flag for the editor — collapse to ONE concrete case (rule 1 + persona hard-fail). |
|
||||||
|
|
||||||
|
Pass 1 is **objective** — you may apply these removals directly and present the
|
||||||
|
scrubbed draft plus a change log. (Whether the text *lands* or *matches voice* is
|
||||||
|
NOT self-certified here — that stays with the persona sweep and the operator.)
|
||||||
|
|
||||||
|
## Pass 2 — Voice-drift correction (against the Norwegian gold standard)
|
||||||
|
|
||||||
|
Read the approved Norwegian editions, then judge the draft against them on the
|
||||||
|
chronicle-voice dimensions below. Where the draft drifts, correct toward the gold
|
||||||
|
standard — minimal intervention, smallest change that restores the voice.
|
||||||
|
|
||||||
|
- **Register** — folkelig but precise; not naive, not corporate. Matches the
|
||||||
|
approved editions' level, neither talking down nor jargon-walling.
|
||||||
|
- **Sentence rhythm** — the author's actual cadence in the gold standard (length
|
||||||
|
variation, fragment use, em-dash dose).
|
||||||
|
- **Premiss / problem / anbefaling / gevinst / vei videre clarity** — the
|
||||||
|
writing-contract §A spine should read *clearly*, not blurred. If the draft
|
||||||
|
muddies which sentence is the premise or the recommendation, sharpen it.
|
||||||
|
- **Concrete-over-complete** — one verifiable (preferably Norwegian) case over a
|
||||||
|
catalog (rule 1).
|
||||||
|
|
||||||
|
If a drift is *intentional evolution* visible across the most recent approved
|
||||||
|
editions, preserve it — do not snap it back to an older pattern. When unsure
|
||||||
|
whether a trait is drift or evolution, flag it for the operator; do not silently
|
||||||
|
overwrite identity-level voice.
|
||||||
|
|
||||||
|
## Pass 3 — Learn (drift log, over time)
|
||||||
|
|
||||||
|
After scrubbing, append what you learned to a drift log so the agent gets sharper
|
||||||
|
each edition:
|
||||||
|
|
||||||
|
- Write to `${CLAUDE_PLUGIN_ROOT}/assets/voice-samples/chronicle-voice-drift-log.md`
|
||||||
|
(create if absent). One dated entry per run: which tells recurred, which voice
|
||||||
|
traits the draft drifted on, and any newly-confirmed gold-standard pattern.
|
||||||
|
- Do **not** rewrite the general voice profile (`config/user-profile.local.md`) —
|
||||||
|
that is `voice-trainer`'s job. This log is the chronicle-specific memory; over
|
||||||
|
editions it becomes the calibration record for this agent.
|
||||||
|
- Never auto-update identity-level traits (register, em-dash policy, banned
|
||||||
|
phrases) without the operator's confirmation — flag, do not overwrite.
|
||||||
|
|
||||||
|
## Output Format
|
||||||
|
|
||||||
|
```
|
||||||
|
## Voice Scrub Report — Del NN
|
||||||
|
|
||||||
|
**Gold standard read:** [paths to approved Norwegian editions] | MISSING (Pass 1 only)
|
||||||
|
|
||||||
|
### Pass 1 — De-AI scrub (applied)
|
||||||
|
| # | Tell | Location | Action |
|
||||||
|
|---|------|----------|--------|
|
||||||
|
| 1 | «la meg være ærlig» | §intro | cut |
|
||||||
|
| 2 | em-dash-spam | §3 | 4 → 1 (gold-standard dose) |
|
||||||
|
**AI-tells removed:** [N]
|
||||||
|
|
||||||
|
### Pass 2 — Voice-drift correction (toward Norwegian gold standard)
|
||||||
|
| Dimension | Status | Correction |
|
||||||
|
|-----------|--------|------------|
|
||||||
|
| Register | match / drift | [minimal change, or none] |
|
||||||
|
| Rhythm | … | … |
|
||||||
|
| Spine clarity (premiss…vei videre) | … | … |
|
||||||
|
| Concrete-over-complete | … | … |
|
||||||
|
**Drift verdict:** AUTHENTIC / CAUTION / ALERT / REWRITE
|
||||||
|
|
||||||
|
### Flagged for operator (not auto-applied)
|
||||||
|
- [intentional-evolution question, or modell-/navne-katalog collapse, or "none"]
|
||||||
|
|
||||||
|
### Scrubbed draft
|
||||||
|
[the full de-AI'd, voice-corrected draft]
|
||||||
|
|
||||||
|
### Learned this run (appended to chronicle-voice-drift-log.md)
|
||||||
|
- [recurring tell / confirmed gold-standard pattern]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key Principles
|
||||||
|
|
||||||
|
1. **Gold standard = approved Norwegian editions, never the English post corpus.**
|
||||||
|
`authentic-voice-samples.md` is for English short-form and forbids the em-dash;
|
||||||
|
using it for chronicle voice degrades it. This rule overrides everything else.
|
||||||
|
2. **Pass 1 is objective; Pass 2 is calibrated.** Mechanical AI-tells may be
|
||||||
|
applied; voice corrections must trace to the gold standard, not to taste.
|
||||||
|
3. **Em-dash is dose, not prohibition** — match the author's actual chronicle use.
|
||||||
|
4. **Minimal intervention.** Smallest change that restores the voice; never
|
||||||
|
rewrite wholesale.
|
||||||
|
5. **Preserve intentional evolution.** Drift ≠ growth — flag when unsure.
|
||||||
|
6. **Learn over time.** Each run sharpens the chronicle-voice-drift-log; the agent
|
||||||
|
should need fewer corrections per edition as the corpus grows.
|
||||||
|
7. **Voice-match is not self-certified green.** «Does it land / sound like him» is
|
||||||
|
routed to the persona sweep and the operator; this agent removes slop and
|
||||||
|
corrects measurable drift, it does not declare the voice authentic.
|
||||||
|
|
||||||
|
## Anti-Patterns
|
||||||
|
|
||||||
|
- Calibrate against the English `authentic-voice-samples.md` (the cardinal sin)
|
||||||
|
- Strip em-dashes the author actually uses (over-applying the English rule)
|
||||||
|
- Invent voice corrections when no approved Norwegian edition was provided
|
||||||
|
- Rewrite the general voice profile (that is `voice-trainer`'s job)
|
||||||
|
- Silently overwrite identity-level traits without operator confirmation
|
||||||
|
- Declare the draft «sounds like him» — that verdict is the persona sweep's/operator's
|
||||||
|
- Add material to fix a weakness (close gaps by tightening — rule 6)
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- `${CLAUDE_PLUGIN_ROOT}/references/longform-quality-rules.md` — canonical
|
||||||
|
AI-slop ban-list (rule 3) + tighten-don't-expand (rule 6)
|
||||||
|
- `${CLAUDE_PLUGIN_ROOT}/agents/voice-trainer.md` — the general voice profile
|
||||||
|
builder (distinct role; do not duplicate)
|
||||||
|
- `${CLAUDE_PLUGIN_ROOT}/agents/persona-reviewer.md` — the resonance gate that
|
||||||
|
owns the «does it land / sound like him» verdict
|
||||||
|
- The approved Norwegian editions in the series folder — the gold standard
|
||||||
|
(path passed by the caller; the English voice-samples are NOT this)
|
||||||
|
|
@ -38,8 +38,20 @@ This command is **fundamentally different** from the short-form commands:
|
||||||
ships the *schema* (`config/edition-state.template.json`) and this command;
|
ships the *schema* (`config/edition-state.template.json`) and this command;
|
||||||
the edition's actual state + drafts live with the series.
|
the edition's actual state + drafts live with the series.
|
||||||
- **Multi-session by design.** A single edition spans several sessions. Every
|
- **Multi-session by design.** A single edition spans several sessions. Every
|
||||||
phase transition rewrites `edition-state.json` + the edition-HANDOVER so the
|
phase transition rewrites two files: **machine state** →
|
||||||
next session resumes exactly where this one stopped.
|
`edition-state.json` (currentPhase, per-article status, fact-check log,
|
||||||
|
persona verdicts), and **narrative state** → `<serie>/STATE.md` (overwritten,
|
||||||
|
not appended — where we are + the one next step). The next session resumes from
|
||||||
|
these exactly where this one stopped.
|
||||||
|
|
||||||
|
> **No edition-HANDOVER (ONE-system).** This command does **not** use a separate
|
||||||
|
> `edition-HANDOVER.md`. Per the global continuity rule, the cwd-nearest
|
||||||
|
> `STATE.md` (auto-injected by the `session-start` hook) is the authoritative
|
||||||
|
> narrative state-bearer; a plugin may not invent its own handover mechanism.
|
||||||
|
> Narrative status lives in `<serie>/STATE.md` (overwrite each phase); machine
|
||||||
|
> state lives in `edition-state.json`. There is no `§4`/`§5`/`§6` handover —
|
||||||
|
> those records moved into `edition-state.json` (fact-check log, persona
|
||||||
|
> verdicts) and `STATE.md` (next-step pointer).
|
||||||
|
|
||||||
## Architecture principle — all orchestration runs in the FOREGROUND from this command layer
|
## Architecture principle — all orchestration runs in the FOREGROUND from this command layer
|
||||||
|
|
||||||
|
|
@ -68,13 +80,13 @@ single most important corrections from the Seres process (plan §0.4, principle
|
||||||
|
|
||||||
| Step | Phase | What | Tools |
|
| Step | Phase | What | Tools |
|
||||||
|------|-------|------|-------|
|
|------|-------|------|-------|
|
||||||
| 0 | **Load context** | edition-state/HANDOVER, voice profile, persona library, series brief | `Read` |
|
| 0 | **Load context** | edition-state + `<serie>/STATE.md`, 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` |
|
| 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)** |
|
| 2 | **Research** | parallel scoped mandates → verified notes; triangulation | **`Task` fan-out (foreground)** |
|
||||||
| 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) |
|
| 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` |
|
| 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` |
|
| 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` |
|
| 4 | **Consistency + quality** | threads, premise→conclusion arc, leader-takeaway, AI-slop removal, de-AI/voice scrub, formatting dose | inline + `references/longform-quality-rules.md` + **`voice-scrubber`** |
|
||||||
| 5 | **Fact-check sweep** | risk-sorted (🔴/🟡/🟢), guilty-until-disproven, verification log | **`fact-checker` (parallel)** |
|
| 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) |
|
| 6 | **Persona sweep — BEFORE lock** | reader jury, primær wins, convergence to clean YES | **`persona-reviewer`** (resonance mode) |
|
||||||
| 7 | **Annotation (optional)** | render annotatable review HTML for a manual pass | `render/build-html.mjs` |
|
| 7 | **Annotation (optional)** | render annotatable review HTML for a manual pass | `render/build-html.mjs` |
|
||||||
|
|
@ -88,8 +100,8 @@ single most important corrections from the Seres process (plan §0.4, principle
|
||||||
> BEFORE prose)** → **spine prose (operator gate BEFORE full expansion)** →
|
> BEFORE prose)** → **spine prose (operator gate BEFORE full expansion)** →
|
||||||
> full prose draft → consistency/quality → fact-check sweep → pre-lock persona
|
> full prose draft → consistency/quality → fact-check sweep → pre-lock persona
|
||||||
> sweep → optional annotation → LOCK/delivery → post-lock hook gate →
|
> sweep → optional annotation → LOCK/delivery → post-lock hook gate →
|
||||||
> scheduling, persisting each phase to `edition-state.json` and the HANDOVER
|
> scheduling, persisting each phase to `edition-state.json` (machine) and
|
||||||
> and stopping cleanly between sessions.
|
> `<serie>/STATE.md` (narrative) and stopping cleanly between sessions.
|
||||||
|
|
||||||
> **Why two gates BEFORE prose (v2.1).** Spine errors are the dearest failure
|
> **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
|
> mode in long-form: catching one at the skeleton stage costs 5–15 min, at the
|
||||||
|
|
@ -126,13 +138,17 @@ the edition left off before doing anything.
|
||||||
`${CLAUDE_PLUGIN_ROOT}/config/edition-state.template.json` (read it if you are
|
`${CLAUDE_PLUGIN_ROOT}/config/edition-state.template.json` (read it if you are
|
||||||
initializing a new edition). If no state file exists, this is a fresh edition —
|
initializing a new edition). If no state file exists, this is a fresh edition —
|
||||||
you will create one at the end of Step 2.
|
you will create one at the end of Step 2.
|
||||||
3. **Read the edition-HANDOVER** (`<serie>/HANDOVER.md` or
|
3. **Read `<serie>/STATE.md`** — the narrative production state (where we are +
|
||||||
`<serie>/linkedin/edition-HANDOVER.md`) — the narrative state (§1 where we
|
the one next step). The `session-start` hook auto-injects the cwd-nearest
|
||||||
are, §4 immutable rules + fact-check log, §6 next session). The structure is
|
`STATE.md`, so when the session was started in the series folder it is already
|
||||||
defined by `${CLAUDE_PLUGIN_ROOT}/config/edition-HANDOVER.template.md` (copy +
|
in context; otherwise read it explicitly. This is the authoritative
|
||||||
fill it when starting a new edition). This is the *production* HANDOVER for the
|
narrative bearer (ONE-system) — there is no `edition-HANDOVER.md`. The durable
|
||||||
edition — **distinct** from the plugin's `docs/BUILD-HANDOVER.local.md`, which
|
records that used to live in the handover now live in `edition-state.json`
|
||||||
governs building the plugin itself. Do not confuse or merge them.
|
(immutable rules, fact-check log, persona verdicts). If `<serie>/STATE.md`
|
||||||
|
does not exist yet, this is a fresh edition — you will write it at the end of
|
||||||
|
Step 2. Do not confuse `<serie>/STATE.md` (this edition's production state)
|
||||||
|
with the plugin's own `STATE.md` / `docs/BUILD-HANDOVER.local.md` (which govern
|
||||||
|
building the plugin itself).
|
||||||
4. **Read the voice profile** — `assets/voice-samples/authentic-voice-samples.md`
|
4. **Read the voice profile** — `assets/voice-samples/authentic-voice-samples.md`
|
||||||
and anything else under `assets/voice-samples/`. Long-form must match the
|
and anything else under `assets/voice-samples/`. Long-form must match the
|
||||||
author's voice; this is the reference for every drafting and review phase.
|
author's voice; this is the reference for every drafting and review phase.
|
||||||
|
|
@ -140,8 +156,8 @@ the edition left off before doing anything.
|
||||||
if it exists, else `${CLAUDE_PLUGIN_ROOT}/config/personas.template.md`. You
|
if it exists, else `${CLAUDE_PLUGIN_ROOT}/config/personas.template.md`. You
|
||||||
will select the active personas + mark the primær in Step 1.
|
will select the active personas + mark the primær in Step 1.
|
||||||
6. **Read the series brief** — whatever the series folder defines as its brief /
|
6. **Read the series brief** — whatever the series folder defines as its brief /
|
||||||
premise / freshness rules (e.g. `<serie>/brief.md` or the HANDOVER §3–§5).
|
premise / freshness rules (e.g. `<serie>/brief.md`, or the resolved brief
|
||||||
This anchors angle and scope.
|
recorded in `edition-state.json`). This anchors angle and scope.
|
||||||
|
|
||||||
### Deterministic resumption — `currentPhase` → resume step
|
### Deterministic resumption — `currentPhase` → resume step
|
||||||
|
|
||||||
|
|
@ -174,16 +190,16 @@ Look up `edition-state.json` → `articles.<currentArticle>` (and the top-level
|
||||||
The phase identifiers are the canonical ones defined in
|
The phase identifiers are the canonical ones defined in
|
||||||
`${CLAUDE_PLUGIN_ROOT}/config/edition-state.template.json` (`_doc.phases`); the
|
`${CLAUDE_PLUGIN_ROOT}/config/edition-state.template.json` (`_doc.phases`); the
|
||||||
Steps below write exactly these strings. If `currentPhase` is missing or
|
Steps below write exactly these strings. If `currentPhase` is missing or
|
||||||
unrecognized, do NOT guess — read the edition-HANDOVER §6 next-session pointer and
|
unrecognized, do NOT guess — read the next-step pointer in `<serie>/STATE.md` and
|
||||||
confirm with the operator before proceeding.
|
confirm with the operator before proceeding.
|
||||||
|
|
||||||
**Draft-cursor note (Step 3b only).** `draft` is the one phase that can be
|
**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
|
*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
|
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
|
records a section-level cursor in `edition-state.json` and a "draft resumes at
|
||||||
section <X>" pointer in HANDOVER §6. On resume with `currentPhase: "draft"`,
|
section <X>" line in `<serie>/STATE.md`. On resume with `currentPhase: "draft"`,
|
||||||
check for that cursor first — if present, re-enter **Step 3b** at the cursor and
|
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
|
finish the prose expansion before Step 4; only when `STATE.md` records "draft
|
||||||
complete" (no open cursor) do you resume at **Step 4**.
|
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
|
Step 3a (spine prose) is short enough that it does NOT need a cursor: if 3a
|
||||||
|
|
@ -212,7 +228,7 @@ do not fabricate either.
|
||||||
## Step 1: Brief + calibration
|
## Step 1: Brief + calibration
|
||||||
|
|
||||||
Establish the edition brief with **at most ~3 calibration questions**. Infer
|
Establish the edition brief with **at most ~3 calibration questions**. Infer
|
||||||
everything you can from Step 0 (series brief, HANDOVER, prior edition); only ask
|
everything you can from Step 0 (series brief, STATE.md, prior edition); only ask
|
||||||
what genuinely changes the work.
|
what genuinely changes the work.
|
||||||
|
|
||||||
Settle these dimensions (most should come from context, not questions):
|
Settle these dimensions (most should come from context, not questions):
|
||||||
|
|
@ -296,8 +312,8 @@ Edition brief
|
||||||
5. **Persist + checkpoint state.** Write the resolved brief (Step 1) and the
|
5. **Persist + checkpoint state.** Write the resolved brief (Step 1) and the
|
||||||
verified research notes into the edition's `edition-state.json`
|
verified research notes into the edition's `edition-state.json`
|
||||||
(`currentPhase: "research"`, article status `in-progress`) and append a
|
(`currentPhase: "research"`, article status `in-progress`) and append a
|
||||||
"research complete → next: skeleton + section pitch (BEFORE prose)" pointer to
|
"research complete → next: skeleton + section pitch (BEFORE prose)" next-step
|
||||||
the edition-HANDOVER §6. If this is a fresh edition, initialize
|
line to `<serie>/STATE.md` (overwrite). If this is a fresh edition, initialize
|
||||||
`edition-state.json` from the template schema first. Stop cleanly here if
|
`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
|
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).
|
Step 2.5 may run inline (it is short and operator-interactive).
|
||||||
|
|
@ -370,15 +386,33 @@ Next: Step 2.5 — Skeleton + section pitch (operator + persona gate BEFORE pros
|
||||||
2. …
|
2. …
|
||||||
```
|
```
|
||||||
|
|
||||||
4. **Operator-gate (first round).** Present the skeleton + pitches to the
|
4. **Operator-gate (render + annotate — primary flow).** The operator review is
|
||||||
operator with `AskUserQuestion`. Three options:
|
**HTML annotation**, not a multiple-choice prompt — and this holds for *every*
|
||||||
|
write deliverable, the skeleton included, not just the final POST.html. Render
|
||||||
|
the skeleton to an annotatable page and let the operator annotate in the browser:
|
||||||
|
|
||||||
- **JA** — skeleton is right, proceed to the persona-skjelett-sweep (step 5).
|
1. The skeleton is already at `<serie>/NN-skjelett.md` (step 3).
|
||||||
- **REVIDER** — operator gives direction; revise the skeleton inline and
|
2. Render it to review HTML with the plugin-owned renderer (cwd = series folder):
|
||||||
re-present. Loop until JA or NEI.
|
```bash
|
||||||
|
cd <serie-mappe> && node "${CLAUDE_PLUGIN_ROOT}/render/build-html.mjs" NN-skjelett.md
|
||||||
|
```
|
||||||
|
Check the exit code (N3 — non-zero = no HTML produced) and confirm
|
||||||
|
`<serie-mappe>/review/NN-skjelett.html` exists before handing it off.
|
||||||
|
3. Surface `<serie-mappe>/review/NN-skjelett.html` to the operator as a
|
||||||
|
`file://` link (use `SendUserFile` if available, else a markdown `file://`
|
||||||
|
link) for the annotation pass.
|
||||||
|
4. The operator annotates in the browser and pastes the annotated markdown
|
||||||
|
back. Fold the notes into `<serie>/NN-skjelett.md` by tightening (rule 6).
|
||||||
|
5. **Receipt, not gate.** After folding in the annotations, use
|
||||||
|
`AskUserQuestion` only as a *receipt* — «skeleton revised per your notes —
|
||||||
|
JA proceed, or another round?». `AskUserQuestion` (JA / REVIDER / NEI) is
|
||||||
|
also the **fallback** gate when rendering is unavailable; it is not the
|
||||||
|
primary flow:
|
||||||
|
- **JA** — proceed to the persona-skjelett-sweep (step 5).
|
||||||
|
- **REVIDER** — another annotation round; revise and re-render.
|
||||||
- **NEI** — the skeleton is wrong at a load-bearing level (premise unsound,
|
- **NEI** — the skeleton is wrong at a load-bearing level (premise unsound,
|
||||||
argument-line incoherent). Return to brief calibration (Step 1) or
|
argument-line incoherent). Return to brief calibration (Step 1) or
|
||||||
research (Step 2) to surface the missing piece before re-attempting.
|
research (Step 2) to surface the missing piece.
|
||||||
|
|
||||||
Do not proceed past this gate without an explicit JA. The pipeline may not
|
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
|
advance to Step 3a (spine prose) until both this operator-gate AND the
|
||||||
|
|
@ -430,7 +464,7 @@ Next: Step 2.5 — Skeleton + section pitch (operator + persona gate BEFORE pros
|
||||||
- `currentPhase: "skeleton-pitch"` in `edition-state.json` (the marker that
|
- `currentPhase: "skeleton-pitch"` in `edition-state.json` (the marker that
|
||||||
Step 2.5 is complete and the gate has passed).
|
Step 2.5 is complete and the gate has passed).
|
||||||
- A "skeleton + pitches PASS (primær JA) → next: Step 3a (spine prose)"
|
- A "skeleton + pitches PASS (primær JA) → next: Step 3a (spine prose)"
|
||||||
pointer in HANDOVER §6.
|
next-step line in `<serie>/STATE.md` (overwrite).
|
||||||
|
|
||||||
```
|
```
|
||||||
Skeleton + section pitch (BEFORE prose) — complete.
|
Skeleton + section pitch (BEFORE prose) — complete.
|
||||||
|
|
@ -490,15 +524,26 @@ Typically ~20–30 % of the edition's final length.
|
||||||
review HTML and Step 8's POST.html require `currentPhase: "draft"` — i.e.
|
review HTML and Step 8's POST.html require `currentPhase: "draft"` — i.e.
|
||||||
Step 3b complete).
|
Step 3b complete).
|
||||||
|
|
||||||
4. **Operator-gate.** Present the spine draft to the operator with
|
4. **Operator-gate (render + annotate — primary flow).** Render the spine draft
|
||||||
`AskUserQuestion`. The gate question is *narrow*: «Is the axis right now
|
and let the operator annotate it in the browser. The gate question stays
|
||||||
that there is prose on it?» Three options:
|
*narrow*: «Is the axis right now that there is prose on it?»
|
||||||
|
|
||||||
|
1. Spine prose is written to `<serie>/NN-utkast.md` (step 3). Render it to a
|
||||||
|
review page (cwd = series folder):
|
||||||
|
```bash
|
||||||
|
cd <serie-mappe> && node "${CLAUDE_PLUGIN_ROOT}/render/build-html.mjs" NN-utkast.md
|
||||||
|
```
|
||||||
|
Check the exit code and confirm `<serie-mappe>/review/NN-utkast.html` exists.
|
||||||
|
2. Surface the `file://` link (`SendUserFile` if available, else a markdown
|
||||||
|
`file://` link).
|
||||||
|
3. The operator annotates and pastes back; fold the notes in by tightening
|
||||||
|
(rule 6 of `references/longform-quality-rules.md`).
|
||||||
|
4. **Receipt, not gate.** `AskUserQuestion` as a receipt — «spine revised per
|
||||||
|
your notes — JA proceed to expansion, or another round?» (also the fallback
|
||||||
|
gate when rendering is unavailable):
|
||||||
- **JA** — the axis lands as prose; proceed to Step 3b (full expansion).
|
- **JA** — the axis lands as prose; proceed to Step 3b (full expansion).
|
||||||
- **REVIDER** — operator gives direction; tighten the spine paragraphs and
|
- **REVIDER** — tighten the spine paragraphs and re-render. Stay in 3a; do
|
||||||
re-present. Stay in 3a; do NOT slip into expansion. (Closing gaps by
|
NOT slip into expansion.
|
||||||
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
|
- **NEI** — the axis still fails as prose. Return to Step 2.5 (revise
|
||||||
skeleton + pitches), re-run the persona-skjelett-sweep, and re-write
|
skeleton + pitches), re-run the persona-skjelett-sweep, and re-write
|
||||||
spine prose against the corrected skeleton. Do not paper over a NEI by
|
spine prose against the corrected skeleton. Do not paper over a NEI by
|
||||||
|
|
@ -512,8 +557,8 @@ Typically ~20–30 % of the edition's final length.
|
||||||
with the expanded prose).
|
with the expanded prose).
|
||||||
- `currentPhase: "spine-prose"` in `edition-state.json` (the marker that 3a
|
- `currentPhase: "spine-prose"` in `edition-state.json` (the marker that 3a
|
||||||
is complete and the gate has passed).
|
is complete and the gate has passed).
|
||||||
- A "spine prose JA → next: Step 3b (full prose expansion)" pointer in
|
- A "spine prose JA → next: Step 3b (full prose expansion)" next-step line in
|
||||||
HANDOVER §6.
|
`<serie>/STATE.md` (overwrite).
|
||||||
|
|
||||||
```
|
```
|
||||||
Spine prose (BEFORE full expansion) — complete.
|
Spine prose (BEFORE full expansion) — complete.
|
||||||
|
|
@ -538,8 +583,8 @@ turning-points the spine already named.
|
||||||
> single session's context budget. If you approach the budget mid-expansion,
|
> single session's context budget. If you approach the budget mid-expansion,
|
||||||
> stop cleanly, write the partial draft to `<serie>/NN-utkast.md` (the
|
> stop cleanly, write the partial draft to `<serie>/NN-utkast.md` (the
|
||||||
> canonical draft path), record `currentPhase: "draft"` **with a section-level
|
> canonical draft path), record `currentPhase: "draft"` **with a section-level
|
||||||
> cursor** in `edition-state.json`, and append a precise "draft resumes at
|
> cursor** in `edition-state.json`, and write a precise "draft resumes at
|
||||||
> section <X>" pointer to the edition-HANDOVER §6. The next session re-reads
|
> section <X>" line to `<serie>/STATE.md` (overwrite). The next session re-reads
|
||||||
> Step 0, picks up the cursor, and continues. Never start the consistency
|
> 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
|
> pass (Step 4) on a half-written expansion. (Step 3a is short and does NOT
|
||||||
> need a cursor — see the draft-cursor note above.)
|
> need a cursor — see the draft-cursor note above.)
|
||||||
|
|
@ -581,8 +626,8 @@ turning-points the spine already named.
|
||||||
spine-prose state — this is the SAME canonical filename Steps 7 and 8
|
spine-prose state — this is the SAME canonical filename Steps 7 and 8
|
||||||
render from; `render/build-html.mjs` and `render/build-linkedin.mjs`
|
render from; `render/build-html.mjs` and `render/build-linkedin.mjs`
|
||||||
silently skip any draft without an `NN` prefix). Set
|
silently skip any draft without an `NN` prefix). Set
|
||||||
`currentPhase: "draft"` in `edition-state.json`, and append a "draft
|
`currentPhase: "draft"` in `edition-state.json`, and write a "draft
|
||||||
complete → next: consistency/quality" pointer to the HANDOVER §6.
|
complete → next: consistency/quality" line to `<serie>/STATE.md` (overwrite).
|
||||||
|
|
||||||
```
|
```
|
||||||
Full prose expansion — complete (or: partial — resumes at section <X>).
|
Full prose expansion — complete (or: partial — resumes at section <X>).
|
||||||
|
|
@ -629,9 +674,25 @@ checklist (full detail + pass/flag criteria in the reference file):
|
||||||
7. **Stramming, ikke utvidelse** (rule 6) — close gaps by tightening; hold the
|
7. **Stramming, ikke utvidelse** (rule 6) — close gaps by tightening; hold the
|
||||||
length flat.
|
length flat.
|
||||||
|
|
||||||
|
**De-AI / voice scrub (sub-pass — `voice-scrubber`).** After the rule pass, run
|
||||||
|
the draft through `voice-scrubber` (Opus) — `Task`, `subagent_type:
|
||||||
|
linkedin-thought-leadership:voice-scrubber`, from THIS command layer in the
|
||||||
|
foreground (principle 4). Pass it the draft path AND the paths to the **approved
|
||||||
|
Norwegian editions** as the gold standard (e.g. earlier parts' locked
|
||||||
|
`linkedin/NN/POST.html` or their approved `NN-utkast.md`). **Do NOT** point it at
|
||||||
|
`assets/voice-samples/authentic-voice-samples.md` — that corpus is English
|
||||||
|
short-form and forbids the em-dash; using it as the gold standard would degrade
|
||||||
|
the Norwegian chronicle voice. The scrubber runs two passes: Pass 1 strips
|
||||||
|
AI-tells (objective — «la meg være ærlig», reflex rule-of-three, em-dash-spam,
|
||||||
|
self-referential overhead, modell-/navne-katalog), Pass 2 corrects drift toward
|
||||||
|
the chronicle voice (calibrated to the gold standard). Fold its scrubbed draft +
|
||||||
|
change log back **by tightening**; route its flagged items (intentional evolution,
|
||||||
|
modell-/navne-katalog collapse) to the operator. Voice-MATCH remains
|
||||||
|
non-self-certified — that verdict stays with the Step 6 persona sweep / operator.
|
||||||
|
|
||||||
After the pass, set `currentPhase: "consistency-quality"` in `edition-state.json`
|
After the pass, set `currentPhase: "consistency-quality"` in `edition-state.json`
|
||||||
and append a "quality pass complete → next: fact-check sweep" pointer to the
|
and write a "quality pass complete → next: fact-check sweep" line to
|
||||||
HANDOVER §6.
|
`<serie>/STATE.md` (overwrite).
|
||||||
|
|
||||||
```
|
```
|
||||||
Consistency + quality pass complete.
|
Consistency + quality pass complete.
|
||||||
|
|
@ -703,18 +764,18 @@ because it "feels" right or because it sits in your own research notes.
|
||||||
**freshness flag** to re-verify on publish day — a checklist item, not a text
|
**freshness flag** to re-verify on publish day — a checklist item, not a text
|
||||||
weakness.
|
weakness.
|
||||||
|
|
||||||
6. **Persist + checkpoint state.** Write the merged verification log into the
|
6. **Persist + checkpoint state.** Write the merged verification log into
|
||||||
edition-HANDOVER §4 (immutable rules + fact-check log — the durable record of
|
`edition-state.json` → `articles.NN.factcheckLog` (the durable, machine-readable
|
||||||
what was checked), set `currentPhase: "factcheck-sweep"` in `edition-state.json`,
|
record of what was checked — this is where the old HANDOVER §4 log now lives),
|
||||||
and append a "fact-check complete → next: persona sweep (BEFORE lock)" pointer
|
set `currentPhase: "factcheck-sweep"`, and write a "fact-check complete → next:
|
||||||
to the HANDOVER §6.
|
persona sweep (BEFORE lock)" line to `<serie>/STATE.md` (overwrite).
|
||||||
|
|
||||||
```
|
```
|
||||||
Fact-check sweep complete.
|
Fact-check sweep complete.
|
||||||
- Claims checked: <N> across <N> parallel blocks
|
- Claims checked: <N> across <N> parallel blocks
|
||||||
- 🔴 High risk: <N> → all resolved (sourced/softened/cut)
|
- 🔴 High risk: <N> → all resolved (sourced/softened/cut)
|
||||||
- 🟡 Unverified: <N> → <resolved / framed as opinion>
|
- 🟡 Unverified: <N> → <resolved / framed as opinion>
|
||||||
- 🟢 Verified: <N> (sources logged to HANDOVER §4)
|
- 🟢 Verified: <N> (sources logged to edition-state.json factcheckLog)
|
||||||
- Freshness flags (re-verify on publish day): <N or none>
|
- Freshness flags (re-verify on publish day): <N or none>
|
||||||
Gate: [PASS — zero unresolved 🔴] (else REWORK/BLOCK with the open claims)
|
Gate: [PASS — zero unresolved 🔴] (else REWORK/BLOCK with the open claims)
|
||||||
Next: Step 6 — Persona sweep (reader jury, BEFORE lock).
|
Next: Step 6 — Persona sweep (reader jury, BEFORE lock).
|
||||||
|
|
@ -769,9 +830,10 @@ reopening locked texts — the biggest single process error of the series (plan
|
||||||
the personas whose verdicts are still open.
|
the personas whose verdicts are still open.
|
||||||
|
|
||||||
5. **Persist + checkpoint state.** Record the final per-persona verdicts and the
|
5. **Persist + checkpoint state.** Record the final per-persona verdicts and the
|
||||||
resolved flags in the edition-HANDOVER §5 (method / persona calibration), set
|
resolved flags in `edition-state.json` → `articles.NN.personaSweep.resonance`
|
||||||
`currentPhase: "persona-sweep-prelock"` in `edition-state.json`, and append a "persona sweep
|
(where the old HANDOVER §5 calibration now lives), set
|
||||||
PASS (primær JA) → next: lock/delivery" pointer to the HANDOVER §6.
|
`currentPhase: "persona-sweep-prelock"`, and write a "persona sweep
|
||||||
|
PASS (primær JA) → next: lock/delivery" line to `<serie>/STATE.md` (overwrite).
|
||||||
|
|
||||||
```
|
```
|
||||||
Persona sweep complete (BEFORE lock).
|
Persona sweep complete (BEFORE lock).
|
||||||
|
|
@ -821,8 +883,8 @@ editor is satisfied with the in-session draft. It does not gate lock.
|
||||||
substantive, re-run the affected sweep (Step 5 or 6) before proceeding.
|
substantive, re-run the affected sweep (Step 5 or 6) before proceeding.
|
||||||
|
|
||||||
4. **Persist.** Set `currentPhase: "annotation"` in `edition-state.json` and
|
4. **Persist.** Set `currentPhase: "annotation"` in `edition-state.json` and
|
||||||
append an "annotation rendered (optional) → next: lock/delivery" pointer to
|
write an "annotation rendered (optional) → next: lock/delivery" line to
|
||||||
the HANDOVER §6. If skipped, note "annotation skipped" and move on.
|
`<serie>/STATE.md` (overwrite). If skipped, note "annotation skipped" and move on.
|
||||||
|
|
||||||
```
|
```
|
||||||
Annotation (optional).
|
Annotation (optional).
|
||||||
|
|
@ -939,7 +1001,7 @@ the post-lock conversion sweep, distinct from the pre-lock resonance sweep
|
||||||
conversion check. Loop until JA. `[GATE]`
|
conversion check. Loop until JA. `[GATE]`
|
||||||
|
|
||||||
4. **Persist.** Record the conversion verdict in
|
4. **Persist.** Record the conversion verdict in
|
||||||
`edition-state.json` → `articles.NN.personaSweep.conversion` (and HANDOVER §5),
|
`edition-state.json` → `articles.NN.personaSweep.conversion`,
|
||||||
and set `currentPhase: "hook-conversion-gate"`.
|
and set `currentPhase: "hook-conversion-gate"`.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
@ -984,9 +1046,9 @@ now a first-class scheduled post.
|
||||||
|
|
||||||
3. **Persist + close the edition.** Set the article's `status: "scheduled"`,
|
3. **Persist + close the edition.** Set the article's `status: "scheduled"`,
|
||||||
`scheduled: "<YYYY-MM-DD HH:MM>"`, and `currentPhase: "scheduling"` in
|
`scheduled: "<YYYY-MM-DD HH:MM>"`, and `currentPhase: "scheduling"` in
|
||||||
`edition-state.json`. Append a closing "edition scheduled → mark live via
|
`edition-state.json`. Write a closing "edition scheduled → mark live via
|
||||||
`/linkedin:calendar` on <date>" pointer to the HANDOVER §6. The pipeline is
|
`/linkedin:calendar` on <date>" line to `<serie>/STATE.md` (overwrite). The
|
||||||
complete.
|
pipeline is complete.
|
||||||
|
|
||||||
```
|
```
|
||||||
Scheduling.
|
Scheduling.
|
||||||
|
|
@ -1003,10 +1065,10 @@ Edition complete. Visible in /linkedin:calendar; mark live via /linkedin:calenda
|
||||||
- `${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-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-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-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}/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/fact-checker.md` — Step 5 fact-check agent (risk-sorted, guilty-until-disproven)
|
||||||
- `${CLAUDE_PLUGIN_ROOT}/agents/persona-reviewer.md` — Step 2.5/6/9 reader jury (skeleton + resonance + conversion modes)
|
- `${CLAUDE_PLUGIN_ROOT}/agents/persona-reviewer.md` — Step 2.5/6/9 reader jury (skeleton + resonance + conversion modes)
|
||||||
|
- `${CLAUDE_PLUGIN_ROOT}/agents/voice-scrubber.md` — Step 4 de-AI / Norwegian-chronicle voice scrub (gold standard = approved Norwegian editions, NOT the English post corpus)
|
||||||
- `${CLAUDE_PLUGIN_ROOT}/commands/react.md` — multi-source synthesis discipline (reused in Step 2)
|
- `${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}/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}/references/longform-quality-rules.md` — canonical long-form rules (Steps 2.5, 3a, 3b, 4–9 all reference)
|
||||||
|
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
<!--
|
|
||||||
TEMPLATE — edition-HANDOVER.md (narrative production state for one edition)
|
|
||||||
|
|
||||||
Purpose : the human-readable narrative companion to edition-state.json. Where
|
|
||||||
edition-state.json is the machine-readable resumption state (currentPhase,
|
|
||||||
per-article status), this HANDOVER carries the *narrative* state a human
|
|
||||||
(or the next session) reads to understand where the edition is, what is
|
|
||||||
immutable, and what happens next. /linkedin:newsletter Step 0 reads it;
|
|
||||||
every phase appends to §6.
|
|
||||||
Decision: G — production lives in the series root, NOT the plugin. Copy this to
|
|
||||||
<serie>/linkedin/edition-HANDOVER.md (or <serie>/HANDOVER.md) and fill in.
|
|
||||||
DISTINCT from the plugin's own docs/BUILD-HANDOVER.local.md (which governs building
|
|
||||||
the plugin). Never merge the two.
|
|
||||||
|
|
||||||
Section numbering is referenced by name in commands/newsletter.md:
|
|
||||||
§1 where we are · §3–§5 brief/rules/calibration · §4 immutable rules + fact-check
|
|
||||||
log · §5 persona calibration + conversion verdict · §6 next-session pointer.
|
|
||||||
-->
|
|
||||||
|
|
||||||
# Edition HANDOVER — <series title>, article <NN> "<edition title>"
|
|
||||||
|
|
||||||
## §1 — Where we are
|
|
||||||
- Current phase: <currentPhase, mirrors edition-state.json>
|
|
||||||
- Article status: <pending | in-progress | locked | scheduled>
|
|
||||||
- One-line state: <e.g. "draft complete, consistency pass next" or "locked, awaiting hook gate">
|
|
||||||
|
|
||||||
## §2 — Premise & angle
|
|
||||||
- Premise (one clear claim): <…>
|
|
||||||
- Angle / dramaturgical spine: <…>
|
|
||||||
- Leader-takeaway (the one thing a busy reader keeps): <…>
|
|
||||||
|
|
||||||
## §3 — Brief & scope
|
|
||||||
- Audience personas (active set; mark primær): <persona A (PRIMÆR), persona B, …>
|
|
||||||
- Key points (2–4): <…>
|
|
||||||
- Tone / voice anchor: <reference to assets/voice-samples + any edition-specific note>
|
|
||||||
- Out of scope for this edition: <…>
|
|
||||||
|
|
||||||
## §4 — Immutable rules + fact-check log
|
|
||||||
> Rules locked for this edition (do not relitigate mid-pipeline):
|
|
||||||
- <immutable rule 1 — e.g. "no vendor names in the hook">
|
|
||||||
- <immutable rule 2>
|
|
||||||
|
|
||||||
> Fact-check log (Step 5 — guilty-until-disproven; 🔴 must be empty before lock):
|
|
||||||
| Claim | Risk | Source / verification | Status |
|
|
||||||
|-------|------|-----------------------|--------|
|
|
||||||
| <claim> | 🔴/🟡/🟢 | <primary source> | open / resolved |
|
|
||||||
|
|
||||||
## §5 — Persona calibration + verdicts
|
|
||||||
- Pre-lock resonance sweep (Step 6): primær <name> → <JA / NEI + one-line reason>
|
|
||||||
- Method/persona calibration notes: <any axis tuning, secondary-NO signals>
|
|
||||||
- Post-lock conversion sweep (Step 9): primær <name> mode konverter → <JA / NEI>
|
|
||||||
|
|
||||||
## §6 — Next session
|
|
||||||
- Next step: Step <N> — <name> (per the Step 0 resumption table)
|
|
||||||
- Precise pointer: <e.g. "draft resumes at section 3" or "render POST.html, then hook gate">
|
|
||||||
- Open questions for the operator: <…, or "none">
|
|
||||||
|
|
@ -2,10 +2,10 @@
|
||||||
"_doc": {
|
"_doc": {
|
||||||
"purpose": "Schema for edition-state.json — deterministic resumption state for a newsletter edition in production. Holds the current phase + per-article status so /linkedin:newsletter (Step 0) can resume exactly where a prior session stopped.",
|
"purpose": "Schema for edition-state.json — deterministic resumption state for a newsletter edition in production. Holds the current phase + per-article status so /linkedin:newsletter (Step 0) can resume exactly where a prior session stopped.",
|
||||||
"decision": "G — production state lives in the serie-mappe (e.g. /Users/ktg/repos/maskinrommet/serier/<slug>/linkedin/edition-state.json), NOT in the plugin. This file is the schema-defining TEMPLATE only; copy + fill it in the serie-mappe when producing an edition.",
|
"decision": "G — production state lives in the serie-mappe (e.g. /Users/ktg/repos/maskinrommet/serier/<slug>/linkedin/edition-state.json), NOT in the plugin. This file is the schema-defining TEMPLATE only; copy + fill it in the serie-mappe when producing an edition.",
|
||||||
"complements": "edition-config.json (static: calendar, freshness, captions) and the human-readable edition-HANDOVER.md (narrative state, fasit §5.2). edition-state.json is the lightweight machine-readable companion for deterministic resumption.",
|
"complements": "edition-config.json (static: calendar, freshness, captions) and <serie>/STATE.md (human-readable narrative state, overwritten each phase per the ONE-system continuity rule — there is no edition-HANDOVER.md). edition-state.json is the machine-readable companion: deterministic resumption + the durable fact-check log, immutable rules, and persona verdicts that the old HANDOVER §4/§5 used to carry.",
|
||||||
"lifecycle": "/linkedin:newsletter reads this in Step 0 and rewrites it at every phase transition. Article keys mirror edition-config.json (zero-padded strings: \"01\", \"02\", ..., or \"samle\").",
|
"lifecycle": "/linkedin:newsletter reads this in Step 0 and rewrites it at every phase transition. Article keys mirror edition-config.json (zero-padded strings: \"01\", \"02\", ..., or \"samle\").",
|
||||||
"phases": [
|
"phases": [
|
||||||
"load-context — read state/HANDOVER, voice profile, persona library, series brief (Step 0)",
|
"load-context — read <serie>/STATE.md, voice profile, persona library, series brief (Step 0)",
|
||||||
"brief-calibration — angle, voice, audience personas, key points, leader-takeaway (Step 1)",
|
"brief-calibration — angle, voice, audience personas, key points, leader-takeaway (Step 1)",
|
||||||
"research — parallel scoped mandates → verified notes, triangulation (Step 2)",
|
"research — parallel scoped mandates → verified notes, triangulation (Step 2)",
|
||||||
"skeleton-pitch — five-line skeleton (premise/problem/recommendation/payoff/forward) + section pitches, operator gate + persona-skjelett-sweep BEFORE prose (Step 2.5)",
|
"skeleton-pitch — five-line skeleton (premise/problem/recommendation/payoff/forward) + section pitches, operator gate + persona-skjelett-sweep BEFORE prose (Step 2.5)",
|
||||||
|
|
@ -34,8 +34,10 @@
|
||||||
"title": "<Article 1 title>",
|
"title": "<Article 1 title>",
|
||||||
"phase": "load-context",
|
"phase": "load-context",
|
||||||
"status": "pending",
|
"status": "pending",
|
||||||
|
"immutableRules": null,
|
||||||
"factcheckLog": null,
|
"factcheckLog": null,
|
||||||
"personaSweep": {
|
"personaSweep": {
|
||||||
|
"skeleton": null,
|
||||||
"resonance": null,
|
"resonance": null,
|
||||||
"conversion": null
|
"conversion": null
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,27 @@ trim, or extend them per series.
|
||||||
BEFORE lock — «does the point land for this reader?») and conversion mode
|
BEFORE lock — «does the point land for this reader?») and conversion mode
|
||||||
(Step 9, after lock — binary «would YOU click?» on the hook only).
|
(Step 9, after lock — binary «would YOU click?» on the hook only).
|
||||||
|
|
||||||
|
### The click-gate is blocking (bar = primær ekte JA)
|
||||||
|
|
||||||
|
The persona sweep is not advisory — it returns a **blocking verdict**
|
||||||
|
(PASS / REWORK / BLOCK), and the bar is the **primær reader's genuine, unqualified
|
||||||
|
JA**. The three Seres seed personas are the canonical set: **A = IT-divisjonsdirektør**
|
||||||
|
(sekundær), **B = KI-seksjonsleder** (sekundær), **C = Linjeleder** (PRIMÆR — trumfer).
|
||||||
|
|
||||||
|
- **Bar = C ekte JA.** A clean, unqualified yes from the primær. **«JA med store
|
||||||
|
forbehold» = NEI.**
|
||||||
|
- ⛔ **Hard fail (= omskriv, ikke annotér):** the verdict is BLOCK, regardless of
|
||||||
|
the other axes, when the primær —
|
||||||
|
- «mistet meg» (disengaged before the takeaway), or
|
||||||
|
- does not own the action (the takeaway is someone else's job), or
|
||||||
|
- hits a **sjargong-mur** (a wall of technical vocabulary their `sjargong`
|
||||||
|
rejects), or
|
||||||
|
- hits a **modell-/navne-katalog** (product/model/benchmark names listed for
|
||||||
|
completeness).
|
||||||
|
- These are **rewrite triggers**, not annotations the editor can wave through. A
|
||||||
|
*sekundær* NO from a role/expertise ceiling stays a SIGNAL the gate works —
|
||||||
|
never distort the text to chase it.
|
||||||
|
|
||||||
Each persona documents five fields. Keep the lowercase field keys exactly — the
|
Each persona documents five fields. Keep the lowercase field keys exactly — the
|
||||||
pipeline and the structural check key off them:
|
pipeline and the structural check key off them:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,16 @@ cp config/user-profile.template.md config/user-profile.local.md
|
||||||
- [What you never do]
|
- [What you never do]
|
||||||
- [Another thing to avoid]
|
- [Another thing to avoid]
|
||||||
|
|
||||||
|
**Universal anti-patterns (keep these — they hold for every author):**
|
||||||
|
- **Modell-/navne-katalog.** Do not reel off product names, model names, or
|
||||||
|
benchmarks for completeness. Pick ONE concrete, verifiable (preferably local)
|
||||||
|
case over a list — a name-dump is a jargon wall to a non-technical reader.
|
||||||
|
- **Fullstendighet over leser-handling.** Serve what the primary reader can DO
|
||||||
|
from their chair, not everything the author knows. Completeness is not a virtue.
|
||||||
|
- **Selvrefererende overhead-åpning.** No meta-commentary about what the text will
|
||||||
|
or will not do, no warm-ups. Start on the reader's problem.
|
||||||
|
- **«ikke bare X, men Y», reflex rule-of-three, tacked-on summaries, hedging.**
|
||||||
|
|
||||||
**Language:** [English / Norwegian / Other]
|
**Language:** [English / Norwegian / Other]
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,12 @@ they will do about it.
|
||||||
about it.
|
about it.
|
||||||
- If the reader cannot state the takeaway in one sentence, the text is not done —
|
- If the reader cannot state the takeaway in one sentence, the text is not done —
|
||||||
tighten until they can.
|
tighten until they can.
|
||||||
|
- **Serve what the reader can DO, not what the author knows.** The text exists to
|
||||||
|
give the *primær* reader (the non-technical line manager) something they can act
|
||||||
|
on from their own chair — not to demonstrate the author's breadth. Completeness
|
||||||
|
is not a virtue: if a passage exists to be thorough rather than to move the
|
||||||
|
reader's decision forward, cut it. Choose ONE concrete, verifiable (preferably
|
||||||
|
Norwegian) case over an exhaustive list.
|
||||||
|
|
||||||
**Pass/flag:** PASS when the one-takeaway + one-action is stated and unmistakable;
|
**Pass/flag:** PASS when the one-takeaway + one-action is stated and unmistakable;
|
||||||
FLAG when the text carries two competing takeaways or ends without a concrete
|
FLAG when the text carries two competing takeaways or ends without a concrete
|
||||||
|
|
@ -61,8 +67,20 @@ Norwegian):
|
||||||
content actually enumerates three things)
|
content actually enumerates three things)
|
||||||
- «i en stadig mer kompleks verden» (and equivalent throat-clearing openers)
|
- «i en stadig mer kompleks verden» (and equivalent throat-clearing openers)
|
||||||
- tacked-on summary sentences that restate what was just said
|
- tacked-on summary sentences that restate what was just said
|
||||||
|
- **modell-/navne-katalog** — reeling off product names, model names, or
|
||||||
|
benchmarks (Qwen3-14B, Ministral 3, SWE-bench, Arena, «parametere», «vekter»)
|
||||||
|
for completeness' sake. A list of names is a jargon wall to the primær reader;
|
||||||
|
pick ONE concrete, verifiable case instead (see rule 1). This is a **hard fail
|
||||||
|
for the primær persona**, not a stylistic nit — it is the failure mode that
|
||||||
|
nearly shipped in the Seres process.
|
||||||
|
- **selvrefererende overhead-åpning** — meta-commentary about what the text will
|
||||||
|
or will not do, warm-ups, and openers like «Det er bra. Det er ikke det denne
|
||||||
|
teksten handler om». Start on the reader's problem, not on the text's own
|
||||||
|
framing.
|
||||||
|
|
||||||
**Pass/flag:** PASS when none appear; FLAG (with count) and remove each occurrence.
|
**Pass/flag:** PASS when none appear; FLAG (with count) and remove each
|
||||||
|
occurrence. A modell-/navne-katalog or a sjargong-mur is a hard fail (treat as
|
||||||
|
BLOCK-level for the primær reader in the persona sweep), not a soft flag.
|
||||||
|
|
||||||
### 4. Generell, ikke etat-/person-spesifikk (general, not org-/person-specific)
|
### 4. Generell, ikke etat-/person-spesifikk (general, not org-/person-specific)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue