From 8d25dd908efa29e09535c81346db2374a58f770a Mon Sep 17 00:00:00 2001 From: Kjell Tore Guttormsen Date: Wed, 27 May 2026 22:30:42 +0200 Subject: [PATCH] feat(linkedin): longform quality rules + edition resumption wiring (S12) --- .../commands/newsletter.md | 116 +++++++++----- .../references/longform-quality-rules.md | 148 ++++++++++++++++++ 2 files changed, 221 insertions(+), 43 deletions(-) create mode 100644 plugins/linkedin-thought-leadership/references/longform-quality-rules.md diff --git a/plugins/linkedin-thought-leadership/commands/newsletter.md b/plugins/linkedin-thought-leadership/commands/newsletter.md index 26184f9..e844e93 100644 --- a/plugins/linkedin-thought-leadership/commands/newsletter.md +++ b/plugins/linkedin-thought-leadership/commands/newsletter.md @@ -109,11 +109,56 @@ the edition left off before doing anything. premise / freshness rules (e.g. `/brief.md` or the HANDOVER §3–§5). This anchors angle and scope. +### Deterministic resumption — `currentPhase` → resume step + +This command is multi-session: a session may be aborted (context budget, `/clear`, +interruption) at any phase. Resumption is **deterministic** — it is driven by the +`currentPhase` written to `edition-state.json`, never by re-asking the operator +where things stopped. Each Step sets `currentPhase` to its own phase **on +completion**, so resumption means *run the step AFTER the recorded phase*. + +Look up `edition-state.json` → `articles.` (and the top-level +`currentPhase`) in this table and **jump straight to the resume step**: + +| `currentPhase` (last completed) | Resume at | +|---------------------------------|-----------| +| *(no state file)* | **NEW edition** → Step 1 (init state at end of Step 2) | +| `load-context` | Step 1 — Brief + calibration | +| `brief-calibration` | Step 2 — Research | +| `research` | Step 3 — Draft | +| `draft` | Step 4 — Consistency + quality *(see draft-cursor note)* | +| `consistency-quality` | Step 5 — Fact-check sweep | +| `factcheck-sweep` | Step 6 — Persona sweep (pre-lock) | +| `persona-sweep-prelock` | Step 7 — Annotation (optional) → Step 8 | +| `annotation` | Step 8 — LOCK → delivery | +| `lock-delivery` | Step 9 — Hook / conversion gate | +| `hook-conversion-gate` | Step 10 — Scheduling | +| `scheduling` | **Edition complete** — nothing to resume (start the next article or edition) | + +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 +confirm with the operator before proceeding. + +**Draft-cursor note (Step 3 only).** `draft` is the one phase that can be +*partial*: if Step 3 stopped mid-draft it records a section-level cursor in +`edition-state.json` and a "draft resumes at section " pointer in HANDOVER §6. +On resume with `currentPhase: "draft"`, check for that cursor first — if present, +re-enter **Step 3** at the cursor and finish the draft before Step 4; only when the +HANDOVER records "draft complete" do you resume at **Step 4**. + +> **Resumption is the deterministic test (plan §10, archetype E).** Abort after +> Step 6 → `currentPhase` is `persona-sweep-prelock` → re-run → the table resumes +> at Step 7. No operator question, no re-doing the persona sweep. The same holds +> at every row. + Then display a short status: ``` Edition: — article "" -Resuming at phase: <currentPhase> (or: NEW edition — starting at load-context) +Last completed phase: <currentPhase> (or: NEW edition) +Resuming at: Step <N> — <step name> (from the resumption table above) Voice profile: loaded | MISSING Persona library: <N> personas loaded (active set chosen in Step 1) ``` @@ -278,53 +323,38 @@ Run the draft through the long-form quality rules. This is a *tightening* pass the gap between draft and final is closed by **swapping weaker for sharper and cutting, not by expansion**; hold the length flat (plan §8). -> **Inlined rules (forward-reference note).** The canonical long-form quality -> rules live in `references/longform-quality-rules.md` — but that file is not -> authored until plan step S12. So the rules are **inlined here now**. When S12 -> lands, this block is EXTRACTED to that reference file and replaced with a -> pointer; there is no dangling reference at any point. +> **Canonical rules live in one place.** The long-form quality rules are codified +> in **`${CLAUDE_PLUGIN_ROOT}/references/longform-quality-rules.md`** — read it +> now and apply it. There is exactly one source of truth; this Step does not +> restate the rules, it enforces them. (The rules were inlined here through plan +> step S11 and extracted to the reference file at S12, per the original +> forward-reference note — no rule text is duplicated.) -**Calibration first (a per-sweep user choice, not a default — plan §8):** before +**Calibration first (rule 7 — a per-sweep user choice, not a default):** before running this pass, confirm fold-in aggressiveness (conservative vs. aggressive), jargon handling, and — when it matters later — persona weighting on conflict. Ask once if the Step 1 brief did not already settle it. -Apply each rule and report a pass/flag per rule: +Apply the reference rules and report a **pass/flag per rule**. The operative +checklist (full detail + pass/flag criteria in the reference file): -1. **Threads.** Every thread opened in the ingress/body resolves by the - conclusion — no dropped setups, no orphaned promises. +1. **Threads** *(consistency)* — every thread opened in the ingress/body resolves + by the conclusion; no dropped setups, no orphaned promises. +2. **Leder-takeaway** (rule 1) — ONE takeaway + ONE concrete action; cut references + hard. +3. **Premiss→konklusjon-bue** (rule 2) — ingress-premise == conclusion-premise; the + close grips and twists forward, never just summarizes. +4. **AI-slop-fraser** (rule 3) — strip the Norwegian ban-list on sight (report a + removed-count). +5. **Generell, ikke etat-/person-spesifikk** (rule 4) — opportunities not + provocations; ≤1 structural anchor. +6. **Formaterings-dose** (rule 5) — minimal; no PowerPoint-printout. +7. **Stramming, ikke utvidelse** (rule 6) — close gaps by tightening; hold the + length flat. -2. **Premise→conclusion arc.** The premise set in the ingress (Step 3) is the same - premise the conclusion grips and twists forward. If the draft drifted to a - different premise, realign the conclusion or the ingress — do not leave two - premises. - -3. **Leader-takeaway.** The edition lands ONE clear takeaway + ONE concrete action. - Cut references hard; hands-on credibility beats a citation-pile. If the reader - cannot state the takeaway in one sentence, tighten until they can. - -4. **AI-slop removal (forbidden phrases — strip on sight).** These are the Seres - ban-list; they read as machine-written and must not appear: - - "her må jeg være ærlig" / "for å være ærlig" - - "ikke bare X, men Y" - - gratuitous three-item listing (rule-of-three as a tic) - - "i en stadig mer kompleks verden" - - tacked-on summary sentences that restate what was just said - -5. **General, not org-/person-specific.** No personal agency anecdotes; present - opportunities, not provocations. At most ONE structural anchoring reference per - text — never repeated criticism of a named person. - -6. **Formatting dose (minimal).** Bold = at most one point per section. Short lists - (2–4 items) only where the text already enumerates — never turn load-bearing - reasoning into bullets. Tables sparingly. *"No article should look like a - PowerPoint printout."* - -7. **Close gaps by tightening, not expanding.** Swap weaker passages for sharper - ones; keep the length flat. - -After the pass, set `currentPhase: "quality"` in `edition-state.json` and append a -"quality pass complete → next: fact-check sweep" pointer to the HANDOVER §6. +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. ``` Consistency + quality pass complete. @@ -398,7 +428,7 @@ because it "feels" right or because it sits in your own research notes. 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"` in `edition-state.json`, + 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. @@ -462,7 +492,7 @@ reopening locked texts — the biggest single process error of the series (plan 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"` in `edition-state.json`, and append a "persona sweep + `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. ``` diff --git a/plugins/linkedin-thought-leadership/references/longform-quality-rules.md b/plugins/linkedin-thought-leadership/references/longform-quality-rules.md new file mode 100644 index 0000000..875c4d3 --- /dev/null +++ b/plugins/linkedin-thought-leadership/references/longform-quality-rules.md @@ -0,0 +1,148 @@ +# Long-Form Quality Rules + +Canonical quality rules for long-form LinkedIn content (newsletter editions, +essays, series articles). These are enforced by the `/linkedin:newsletter` +pipeline — primarily in **Step 4 (Consistency + quality)**, reinforced by the +fact-check sweep (Step 5) and the persona sweeps (Steps 6 + 9). + +> **Provenance.** Distilled from the Seres series production (the operator's +> first full long-form run) and codified as the authoritative spec in plan §8. +> Source of truth: this file. `commands/newsletter.md` Step 4 points here rather +> than restating the rules — there is exactly one place to change them. + +> **Scope.** These rules are for **long-form only**. Short-form feed posts are +> governed by the `PreToolUse` content-gatekeeper / voice-guardian hooks, which +> are calibrated for feed posts and stay short-form-only (plan decision B). Long- +> form quality is enforced by pipeline *phases*, not by those hooks. + +--- + +## The rules + +### 1. Leder-takeaway (lead takeaway) + +Every text lands **ONE clear takeaway + ONE concrete action**. The reader should +be able to state, in a single sentence, what they now think differently and what +they will do about it. + +- Cut references hard. Hands-on credibility beats a citation-pile — a text that + shows you have done the work outweighs one that quotes everyone who has written + about it. +- If the reader cannot state the takeaway in one sentence, the text is not done — + tighten until they can. + +**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 +action. + +### 2. Premiss→konklusjon-bue (premise→conclusion arc) + +Establish **one clear premise early** (in the ingress + first paragraph), then let +the conclusion **grip that premise concretely and twist it forward** — give a +direction plus one tangible grip. The conclusion does not merely summarize. + +- The premise the conclusion grips must be the SAME premise the ingress set. If + the draft drifted to a different premise mid-text, realign the conclusion or the + ingress — never leave two premises standing. + +**Pass/flag:** PASS when ingress-premise == conclusion-premise and the close moves +it forward; FLAG when the conclusion only restates, or grips a premise the opening +never set. + +### 3. AI-slop-fraser (forbidden phrases — strip on sight) + +These phrases read as machine-written and are **banned**. They are the Seres +ban-list; strip them on sight (the list is Norwegian because the target text is +Norwegian): + +- «her må jeg være ærlig» / «for å være ærlig» +- «ikke bare X, men Y» (the not-just-X-but-Y construction as a tic) +- gratuitous three-item listing (rule-of-three used as a reflex, not because the + 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 + +**Pass/flag:** PASS when none appear; FLAG (with count) and remove each occurrence. + +### 4. Generell, ikke etat-/person-spesifikk (general, not org-/person-specific) + +Write for a broad reader, not as an internal memo or a grievance. + +- No personal agency anecdotes. +- Present **opportunities, not provocations**. +- At most **one** structural anchoring reference per text — never repeated + criticism of a named person or organization. + +**Pass/flag:** PASS when the text reads as generally useful and carries ≤1 +structural anchor; FLAG personal anecdotes, provocations, and any repeated naming. + +### 5. Formaterings-dose (minimal formatting dose) + +> *"No article should look like a PowerPoint printout."* + +- **Bold** = at most one point per section. +- Short lists (2–4 items) **only** where the text already enumerates — never turn + load-bearing reasoning into bullets. Prose carries the argument; lists carry + genuine enumerations. +- Tables sparingly. + +**Pass/flag:** PASS when formatting stays within these bounds; FLAG (and trim) when +bold is scattered, reasoning has been bulletized, or tables proliferate. + +### 6. Gap lukkes med stramming, ikke utvidelse (close gaps by tightening, not expanding) + +The gap between a draft and the final is closed by **swapping weaker passages for +sharper ones and cutting** — not by adding material. **Hold the length flat.** + +This rule holds across every later phase too: fact-check fixes (Step 5), persona +rework (Step 6), and hook revisions (Step 9) all close their gaps by tightening, +never by expansion. + +**Pass/flag:** target a **flat** length delta vs. the prior draft; FLAG when a +revision grew the word count to cover a weakness instead of sharpening it. + +### 7. Kalibrering per sweep (per-sweep calibration — a user choice, not a default) + +Before each quality / fact-check / persona sweep, **the operator calibrates** — +this is a per-sweep user choice, never a silent default: + +- **Fold-in aggressiveness** — conservative vs. aggressive when folding flags back + into the text. +- **Jargon handling** — keep, gloss, or cut domain jargon. +- **Persona weighting on conflict** — how to weigh a secondary persona's flag + against the primær when they disagree (the primær trumfer rule still governs the + final gate, but the calibration sets how hard a secondary signal is chased). + +Ask once if the Step 1 brief did not already settle it. Do not assume an +aggressiveness; the same draft can be tightened conservatively or aggressively and +the operator owns that dial. + +--- + +## How the pipeline uses these rules + +| Phase | Where the rules bite | +|-------|----------------------| +| Step 4 — Consistency + quality | Primary enforcement: apply rules 1–6, calibrate per rule 7, report a pass/flag per rule. | +| Step 5 — Fact-check sweep | Fixes obey rule 6 (tighten, don't expand). | +| Step 6 — Persona sweep (pre-lock) | Rework obeys rule 6; the leader-takeaway (rule 1) and arc (rule 2) are what the reader jury judges for resonance. | +| Step 9 — Hook / conversion gate | Hook revisions obey rule 6 (sharpen the krok by tightening, body stays locked). | + +## Self-certification boundary + +Whether a text *lands*, matches voice, is original, or reaches prose quality is +**subjective judgment** and is NEVER self-certified green by Claude (plan §10.0). +These rules give objective-where-possible checks (forbidden-phrase presence, +length delta, formatting counts, one-takeaway test), but the resonance verdict is +routed to the persona sweep (`[GATE]`) or the operator (`[OPERATØR]`), never +auto-passed. + +## Related + +- `commands/newsletter.md` — Step 4 applies these rules; the whole pipeline + references them. +- `agents/fact-checker.md` — Step 5 sweep (guilty-until-disproven). +- `agents/persona-reviewer.md` — Step 6 (resonance) + Step 9 (conversion) reader + jury. +- `config/personas.template.md` — the reader personas + "primær trumfer" rule. +- `references/newsletter-strategy-guide.md` — strategic context for long-form.