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:
Kjell Tore Guttormsen 2026-05-28 20:50:56 +02:00
commit 4ed9717627
15 changed files with 494 additions and 152 deletions

View file

@ -9,7 +9,7 @@ plugins/
ai-psychosis/ v1.0.0 — Interaction awareness (sycophancy, reinforcement loops)
config-audit/ v3.1.0 — Configuration intelligence (health, opportunities, auto-fix, whats-active)
graceful-handoff/ v2.1.0 — Auto-trigger handoff via Stop hook (skill + JSON pipeline + 4-step model-aware context resolution)
linkedin-thought-leadership/ v2.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.
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

View file

@ -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.
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 515 minutes; the same error caught at the resonance stage (Step 6) costs 412 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.
- **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)
- **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

View file

@ -1,7 +1,7 @@
{
"name": "linkedin-thought-leadership",
"version": "2.1.0",
"description": "Full-spectrum LinkedIn content engine — feed posts, carousels, video scripts, and long-form newsletter editions — with the January 2026 360Brew algorithm baked in. v2.1 adds skeleton + spine-prose gates BEFORE prose to /linkedin:newsletter.",
"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.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": {
"name": "Kjell Tore Guttormsen"
},

View file

@ -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/),
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
### Summary

View file

@ -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
@ -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:profile` | 360Brew profile optimization |
## Agents (14)
## Agents (15)
| 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 |
| `post-feedback-monitor` | Haiku | Lime | Post-publish 48h monitoring |
| `video-scripter` | Sonnet | Violet | Video script creation with pacing |
| `fact-checker` | Opus | Brown | Factual-claim verification against primary sources (longform) |
| `persona-reviewer` | Opus | Olive | Reader-persona skeleton (v2.1, before prose) + resonance (before lock) + hook-conversion (after lock) gate (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, 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.

View file

@ -6,20 +6,21 @@
*AI-generated: all code produced by Claude Code through dialog-driven development. [Full disclosure →](../../README.md#ai-generated-code-disclosure)*
![Version](https://img.shields.io/badge/version-2.1.0-blue)
![Version](https://img.shields.io/badge/version-2.2.0-blue)
![Platform](https://img.shields.io/badge/platform-Claude_Code_Plugin-purple)
![Commands](https://img.shields.io/badge/commands-24-green)
![Agents](https://img.shields.io/badge/agents-14-orange)
![Agents](https://img.shields.io/badge/agents-15-orange)
![Hooks](https://img.shields.io/badge/hooks-9-red)
![Reference Docs](https://img.shields.io/badge/reference_docs-24-teal)
![License](https://img.shields.io/badge/license-MIT-lightgrey)
A comprehensive Claude Code plugin that turns LinkedIn from a chore into a full-spectrum content engine — short-form feed posts, carousels, video scripts, and long-form newsletter editions. v2.0.0 consolidated the surface (27 → 24 commands, 16 → 14 agents) and added `/linkedin:newsletter` as a multi-session long-form orchestrator with fact-check + persona-sweep gates BEFORE lock. **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
- [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.0.0](#whats-new-in-v200)
- [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
**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
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 |
|-------|-------|-------|----------------------|
@ -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 |
| `post-feedback-monitor` | Haiku | Lime | Post-publish 48h monitoring and real-time interventions |
| `video-scripter` | Sonnet | Violet | Video script creation with pacing and visual cues |
| `fact-checker` | Opus | Brown | Factual-claim verification against primary/credible sources (longform) |
| `persona-reviewer` | Opus | Olive | Reader-persona **skeleton** (v2.1, before prose) + **resonance** (before lock) + **hook-conversion** (after lock) gate (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, 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
@ -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`.
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**
> 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 |
|---------|------|-----------|
| **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.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). |

View file

@ -50,6 +50,30 @@ Before searching, identify:
- **Out of scope:** Opinions, predictions, and value judgments are NOT claims to
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)
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.
"Cannot verify" is a complete, acceptable answer.
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
blog post that summarized it.
5. **Precision matters.** "Exactly 37%" needs an exact source; a directional

View file

@ -216,8 +216,11 @@ does not).
pitches and re-runs the sweep. *Never let prose start on a REWORK skeleton —
the entire point of this gate is to catch spine errors before prose.*
- **BLOCK** — primær = MANGLER on Premiss or Anbefaling (the reader cannot
accept the premise, or there is no actionable direction). Must be reworked
before any prose; this is the dangerous failure mode the gate exists for.
accept the premise, or there is no actionable direction), **OR a section pitch
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):**
@ -226,11 +229,34 @@ does not).
- **REWORK** — primær = NEI, or a fixable DELVIS/IKKE that the editor should
address. Provide the flags as direction; editor decides.
- **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)
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
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).
2. **One persona per run.** Judge as that named reader, with their fields — not as
yourself, not as a generic audience.
3. **Primær trumfer.** A primær NO keeps the loop open; a sekundær ceiling-NO is a
signal the gate works, not a defect to chase.
3. **Primær trumfer — and a hedged JA is a NEI.** A primær NO keeps the loop open;
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
whether it is true (fact-checker) or original (differentiation-checker).
5. **Flag cap matches the mode.** Skjelett ≤ 3, resonans ≤ 5, konverter = 0

View 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)

View file

@ -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;
the edition's actual state + drafts live with the series.
- **Multi-session by design.** A single edition spans several sessions. Every
phase transition rewrites `edition-state.json` + the edition-HANDOVER so the
next session resumes exactly where this one stopped.
phase transition rewrites two files: **machine state**
`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
@ -68,13 +80,13 @@ single most important corrections from the Seres process (plan §0.4, principle
| 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` |
| 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) |
| 3a | **Spine prose — BEFORE full expansion** | one paragraph per section carrying that section's pitch, nothing more. ~2030 % of final length. Operator-gate on whether the axis is right now that there is prose on it. | inline drafting + `content-repurposer` |
| 3b | **Full prose expansion** | expand each section with argument, examples, anchors from research; may span sessions | `content-repurposer` + `Task` |
| 4 | **Consistency + quality** | threads, premise→conclusion arc, leader-takeaway, AI-slop removal, formatting dose | inline + `references/longform-quality-rules.md` |
| 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)** |
| 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` |
@ -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)**
> full prose draft → consistency/quality → fact-check sweep → pre-lock persona
> sweep → optional annotation → LOCK/delivery → post-lock hook gate →
> scheduling, persisting each phase to `edition-state.json` and the HANDOVER
> and stopping cleanly between sessions.
> scheduling, persisting each phase to `edition-state.json` (machine) and
> `<serie>/STATE.md` (narrative) and stopping cleanly between sessions.
> **Why two gates BEFORE prose (v2.1).** Spine errors are the dearest failure
> mode in long-form: catching one at the skeleton stage costs 515 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
initializing a new edition). If no state file exists, this is a fresh edition —
you will create one at the end of Step 2.
3. **Read the edition-HANDOVER** (`<serie>/HANDOVER.md` or
`<serie>/linkedin/edition-HANDOVER.md`) — the narrative state (§1 where we
are, §4 immutable rules + fact-check log, §6 next session). The structure is
defined by `${CLAUDE_PLUGIN_ROOT}/config/edition-HANDOVER.template.md` (copy +
fill it when starting a new edition). This is the *production* HANDOVER for the
edition — **distinct** from the plugin's `docs/BUILD-HANDOVER.local.md`, which
governs building the plugin itself. Do not confuse or merge them.
3. **Read `<serie>/STATE.md`** — the narrative production state (where we are +
the one next step). The `session-start` hook auto-injects the cwd-nearest
`STATE.md`, so when the session was started in the series folder it is already
in context; otherwise read it explicitly. This is the authoritative
narrative bearer (ONE-system) — there is no `edition-HANDOVER.md`. The durable
records that used to live in the handover now live in `edition-state.json`
(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`
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.
@ -140,8 +156,8 @@ the edition left off before doing anything.
if it exists, else `${CLAUDE_PLUGIN_ROOT}/config/personas.template.md`. You
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 /
premise / freshness rules (e.g. `<serie>/brief.md` or the HANDOVER §3§5).
This anchors angle and scope.
premise / freshness rules (e.g. `<serie>/brief.md`, or the resolved brief
recorded in `edition-state.json`). This anchors angle and scope.
### 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
`${CLAUDE_PLUGIN_ROOT}/config/edition-state.template.json` (`_doc.phases`); the
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.
**Draft-cursor note (Step 3b only).** `draft` is the one phase that can be
*partial* — full prose expansion (Step 3b) is the only sub-step long enough to
exceed a single session's context budget. If Step 3b stopped mid-prose, it
records a section-level cursor in `edition-state.json` and a "draft resumes at
section <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
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**.
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
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.
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
verified research notes into the edition's `edition-state.json`
(`currentPhase: "research"`, article status `in-progress`) and append a
"research complete → next: skeleton + section pitch (BEFORE prose)" pointer to
the edition-HANDOVER §6. If this is a fresh edition, initialize
"research complete → next: skeleton + section pitch (BEFORE prose)" next-step
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
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).
@ -370,15 +386,33 @@ Next: Step 2.5 — Skeleton + section pitch (operator + persona gate BEFORE pros
2. …
```
4. **Operator-gate (first round).** Present the skeleton + pitches to the
operator with `AskUserQuestion`. Three options:
4. **Operator-gate (render + annotate — primary flow).** The operator review is
**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).
- **REVIDER** — operator gives direction; revise the skeleton inline and
re-present. Loop until JA or NEI.
- **NEI** — the skeleton is wrong at a load-bearing level (premise unsound,
argument-line incoherent). Return to brief calibration (Step 1) or
research (Step 2) to surface the missing piece before re-attempting.
1. The skeleton is already at `<serie>/NN-skjelett.md` (step 3).
2. Render it to review HTML with the plugin-owned renderer (cwd = series folder):
```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,
argument-line incoherent). Return to brief calibration (Step 1) or
research (Step 2) to surface the missing piece.
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
@ -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
Step 2.5 is complete and the gate has passed).
- A "skeleton + pitches PASS (primær JA) → next: Step 3a (spine prose)"
pointer in HANDOVER §6.
next-step line in `<serie>/STATE.md` (overwrite).
```
Skeleton + section pitch (BEFORE prose) — complete.
@ -490,19 +524,30 @@ Typically ~2030 % of the edition's final length.
review HTML and Step 8's POST.html require `currentPhase: "draft"` — i.e.
Step 3b complete).
4. **Operator-gate.** Present the spine draft to the operator with
`AskUserQuestion`. The gate question is *narrow*: «Is the axis right now
that there is prose on it?» Three options:
4. **Operator-gate (render + annotate — primary flow).** Render the spine draft
and let the operator annotate it in the browser. The gate question stays
*narrow*: «Is the axis right now that there is prose on it?»
- **JA** — the axis lands as prose; proceed to Step 3b (full expansion).
- **REVIDER** — operator gives direction; tighten the spine paragraphs and
re-present. Stay in 3a; do NOT slip into expansion. (Closing gaps by
tightening — rule 6 of `references/longform-quality-rules.md` — applies
here just as it does in Steps 49.)
- **NEI** — the axis still fails as prose. Return to Step 2.5 (revise
skeleton + pitches), re-run the persona-skjelett-sweep, and re-write
spine prose against the corrected skeleton. Do not paper over a NEI by
pressing forward into expansion.
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).
- **REVIDER** — tighten the spine paragraphs and re-render. Stay in 3a; do
NOT slip into expansion.
- **NEI** — the axis still fails as prose. Return to Step 2.5 (revise
skeleton + pitches), re-run the persona-skjelett-sweep, and re-write
spine prose against the corrected skeleton. Do not paper over a NEI by
pressing forward into expansion.
The pipeline may not advance to Step 3b without an explicit JA. `[OPERATØR]`
@ -512,8 +557,8 @@ Typically ~2030 % of the edition's final length.
with the expanded prose).
- `currentPhase: "spine-prose"` in `edition-state.json` (the marker that 3a
is complete and the gate has passed).
- A "spine prose JA → next: Step 3b (full prose expansion)" pointer in
HANDOVER §6.
- A "spine prose JA → next: Step 3b (full prose expansion)" next-step line in
`<serie>/STATE.md` (overwrite).
```
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,
> stop cleanly, write the partial draft to `<serie>/NN-utkast.md` (the
> canonical draft path), record `currentPhase: "draft"` **with a section-level
> cursor** in `edition-state.json`, and append a precise "draft resumes at
> section <X>" pointer to the edition-HANDOVER §6. The next session re-reads
> cursor** in `edition-state.json`, and write a precise "draft resumes at
> 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
> pass (Step 4) on a half-written expansion. (Step 3a is short and does NOT
> 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
render from; `render/build-html.mjs` and `render/build-linkedin.mjs`
silently skip any draft without an `NN` prefix). Set
`currentPhase: "draft"` in `edition-state.json`, and append a "draft
complete → next: consistency/quality" pointer to the HANDOVER §6.
`currentPhase: "draft"` in `edition-state.json`, and write a "draft
complete → next: consistency/quality" line to `<serie>/STATE.md` (overwrite).
```
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
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`
and append a "quality pass complete → next: fact-check sweep" pointer to the
HANDOVER §6.
and write a "quality pass complete → next: fact-check sweep" line to
`<serie>/STATE.md` (overwrite).
```
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
weakness.
6. **Persist + checkpoint state.** Write the merged verification log into the
edition-HANDOVER §4 (immutable rules + fact-check log — the durable record of
what was checked), set `currentPhase: "factcheck-sweep"` in `edition-state.json`,
and append a "fact-check complete → next: persona sweep (BEFORE lock)" pointer
to the HANDOVER §6.
6. **Persist + checkpoint state.** Write the merged verification log into
`edition-state.json``articles.NN.factcheckLog` (the durable, machine-readable
record of what was checked — this is where the old HANDOVER §4 log now lives),
set `currentPhase: "factcheck-sweep"`, and write a "fact-check complete → next:
persona sweep (BEFORE lock)" line to `<serie>/STATE.md` (overwrite).
```
Fact-check sweep complete.
- Claims checked: <N> across <N> parallel blocks
- 🔴 High risk: <N> → all resolved (sourced/softened/cut)
- 🟡 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>
Gate: [PASS — zero unresolved 🔴] (else REWORK/BLOCK with the open claims)
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.
5. **Persist + checkpoint state.** Record the final per-persona verdicts and the
resolved flags in the edition-HANDOVER §5 (method / persona calibration), set
`currentPhase: "persona-sweep-prelock"` in `edition-state.json`, and append a "persona sweep
PASS (primær JA) → next: lock/delivery" pointer to the HANDOVER §6.
resolved flags in `edition-state.json``articles.NN.personaSweep.resonance`
(where the old HANDOVER §5 calibration now lives), set
`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).
@ -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.
4. **Persist.** Set `currentPhase: "annotation"` in `edition-state.json` and
append an "annotation rendered (optional) → next: lock/delivery" pointer to
the HANDOVER §6. If skipped, note "annotation skipped" and move on.
write an "annotation rendered (optional) → next: lock/delivery" line to
`<serie>/STATE.md` (overwrite). If skipped, note "annotation skipped" and move on.
```
Annotation (optional).
@ -939,7 +1001,7 @@ the post-lock conversion sweep, distinct from the pre-lock resonance sweep
conversion check. Loop until JA. `[GATE]`
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"`.
```
@ -984,9 +1046,9 @@ now a first-class scheduled post.
3. **Persist + close the edition.** Set the article's `status: "scheduled"`,
`scheduled: "<YYYY-MM-DD HH:MM>"`, and `currentPhase: "scheduling"` in
`edition-state.json`. Append a closing "edition scheduled → mark live via
`/linkedin:calendar` on <date>" pointer to the HANDOVER §6. The pipeline is
complete.
`edition-state.json`. Write a closing "edition scheduled → mark live via
`/linkedin:calendar` on <date>" line to `<serie>/STATE.md` (overwrite). The
pipeline is complete.
```
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-config.template.json` — static delivery metadata schema (calendar, freshness, credit, captions) — Step 8
- `${CLAUDE_PLUGIN_ROOT}/config/edition-delingstekst.template.md` — distribution-copy grammar (`## Del N —` / `## Samle`) — Steps 8/9
- `${CLAUDE_PLUGIN_ROOT}/config/edition-HANDOVER.template.md` — narrative production-state structure (§1§6) — Step 0
- `${CLAUDE_PLUGIN_ROOT}/config/personas.template.md` — reusable reader personas + "primær trumfer" rule
- `${CLAUDE_PLUGIN_ROOT}/agents/fact-checker.md` — Step 5 fact-check agent (risk-sorted, guilty-until-disproven)
- `${CLAUDE_PLUGIN_ROOT}/agents/persona-reviewer.md` — Step 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}/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, 49 all reference)

View file

@ -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 (24): <…>
- 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">

View file

@ -2,10 +2,10 @@
"_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.",
"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\").",
"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)",
"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)",
@ -34,8 +34,10 @@
"title": "<Article 1 title>",
"phase": "load-context",
"status": "pending",
"immutableRules": null,
"factcheckLog": null,
"personaSweep": {
"skeleton": null,
"resonance": null,
"conversion": null
},

View file

@ -32,6 +32,27 @@ trim, or extend them per series.
BEFORE lock — «does the point land for this reader?») and conversion mode
(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
pipeline and the structural check key off them:

View file

@ -92,6 +92,16 @@ cp config/user-profile.template.md config/user-profile.local.md
- [What you never do]
- [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]
---

View file

@ -30,6 +30,12 @@ they will do about it.
about it.
- If the reader cannot state the takeaway in one sentence, the text is not done —
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;
FLAG when the text carries two competing takeaways or ends without a concrete
@ -61,8 +67,20 @@ Norwegian):
content actually enumerates three things)
- «i en stadig mer kompleks verden» (and equivalent throat-clearing openers)
- 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)