ktg-plugin-marketplace/plugins/linkedin-studio/commands/pivot.md
Kjell Tore Guttormsen e69ea1f4c9 feat(linkedin-studio): v3.1.0 — Endring 9 adversarial review-pakke + per-artefakt personas
Cold, adversarial review package for the long-form pipeline + configurable
per-edition personas. Motivated by Del 4 (Security Champions pivot): the
in-session editor + persona sweep shared the drafting session's framing-bias,
so the shipped version was never independently re-reviewed.

Headless package (9a/9b):
- New Step 6.5 (headless-review) in /linkedin:newsletter, after the persona
  sweep, before lock — the independence layer the in-session gates can't be.
- New standalone /linkedin:headless-review command (run in a fresh session for
  maximum isolation; reconstructs frozen draft + contract + personas from disk).
- 3 new Opus archetypes, each with a cardinal context-isolation block that
  refuses drafting-session framing as "context pollution":
  - content-reviewer (argument integrity C1–C5, ≤8 flags)
  - language-reviewer (Norwegian language L1–L5, ≤10 flags)
  - fact-reviewer (cold re-verification F1–F4, risk-sort + pivot-risk, WebSearch)
- Deliberate redundancy with fact-checker / editorial-reviewer documented so
  the pairs are never de-duplicated.

Pivot-reopen (9c):
- New /linkedin:pivot command: logs articles.NN.pivots[], resets currentPhase,
  un-locks, marks gates to re-run.
- Pivot-detection gate in Step 8 lock precondition (>20% word-count change or
  >2 new sections re-opens cleared gates). Del 4 v8→v11 worked example.

Per-artifact personas (new requirement):
- articles.NN.personas with resolution order (edition-state → series file →
  plugin library → interactive). One or more readers configurable per edition.

Schema/docs:
- edition-state.template.json: additive personas[], pivots[], headlessReview,
  headless-review phase (16 phases); personaSweep.resonance.wordCount baseline.
- 3 fasit fixtures + 3 structural lint tests (Del 4 worked cases).
- Counts: 24→26 commands, 16→19 agents, 15→16 newsletter phases.
- README + CLAUDE.md (plugin + root) + CHANGELOG synced.

Verification: 35 agent-fixture + 59 hook + 20 render tests green. Backward-
compatible (additive state); reload required before the 3 new agents resolve.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 13:01:24 +02:00

7.9 KiB

name description allowed-tools
linkedin:pivot Re-open a long-form edition after a substantive late change (a "pivot") so the already-cleared quality gates re-run on the changed version before lock. Logs the pivot in edition-state, moves currentPhase back to the right earlier step, un-locks if needed, and marks which gates (fact-check, editorial, persona, headless) must re-pass. Includes the pivot-detection heuristic (>20% word-count change or >2 new sections). Use when the user says: "pivot", "I changed the angle", "I added a section", "re-open the edition", "the article changed after it was approved", "re-run the gates", "this needs re-review". Triggers on: "pivot", "linkedin pivot", "re-open edition", "added a section", "changed the angle", "pivot-reopen", "/linkedin:pivot".
Read
Glob
Grep
Bash
AskUserQuestion
Write

LinkedIn Pivot — re-open a cleared edition for re-review

A pivot is a substantive change to a long-form draft made after a gate had already cleared it — a new argument anchor, a new section, a changed thesis. The problem this command solves: the pipeline's gates (fact-check Step 5, editorial Step 5.5, persona Step 6, headless Step 6.5) ran on the pre-pivot version, so the changed text was never validated. Without an explicit re-open, a pivoted edition can sail into lock carrying an unverified premise or an unread argument.

Why this exists (Del 4, Endring 9c). Del 4 was LOCK-ready on an early version (v8). Then a "Security Champions" pivot added a ~260-word section and a ~270-word role-description section — roughly +42 % length, two new sections, a new axis. The pipeline had no pivot-mode, so the whole post-lock chain had to be re-opened by hand. This command makes the re-open a named ritual, not a manual scramble.

Command anatomy

/linkedin:pivot
  --article  NN                  (required; the edition article that changed)
  --reason   "<one line>"        (required; e.g. "Security Champions-anker")
  --to-phase draft | consistency-quality | factcheck-sweep   (optional; default from the heuristic)

The pivot-detection heuristic

Compare the current draft against the version that last cleared Step 6 (persona-sweep-prelock). A pivot-reopen is suggested/required when either:

  • word-count change > 20 %, or
  • > 2 new sections (top-level headings added since the cleared version).

This heuristic is also checked as a lock precondition in Step 8 of /linkedin:newsletter: if the draft has drifted past these bounds since Step 6 cleared, the lock STOPS and points the operator here. (Length-band drift itself — soft/hard caps — is logged friction F1, not yet a gate.)

Worked example (acceptance test — Del 4 v8 → v11). At v8 the persona sweep had cleared a ~1 400-word draft. The Security Champions message pushed it to ~1 992 words (+42 %, > 20 %) and added 2 sections (a new anchor + a role-description) — at the boundary of the "> 2 new sections" rule and well past the 20 % rule. The heuristic fires: /linkedin:pivot --article 04 --reason "Security Champions-anker" would log the pivot, move currentPhase back to draft (structural change → full re-treatment), and require fact-check + editorial + persona + headless to re-pass on v11 before lock. That is exactly the re-sweep the manual Del 4 run had to improvise.

Step 1 — Load state + locate the article

  1. Resolve the series root and read <serie>/linkedin/edition-state.json. Find articles.NN for the --article value. If it does not exist, stop and report.
  2. Read the current draft <serie>/NN-utkast.md and note currentPhase and locked.

Step 2 — Measure the pivot scope

  1. Current word count: cd <serie-mappe> && wc -w NN-utkast.md.
  2. Baseline word count: the word count of the version that last cleared Step 6, recorded by newsletter Step 6 in articles.NN.personaSweep.resonance.wordCount. If that field is absent (older state), ask the operator for the cleared-version word count, or treat the pivot as structural by default.
  3. Compute deltaPct = round((current - baseline) / baseline * 100) and count newSections = top-level headings now present that were not in the cleared version (a grep -c '^## ' delta is a reasonable proxy; confirm with the operator if ambiguous).
  4. Classify scope (drives the default --to-phase):
    • Structural (deltaPct > 20 % OR newSections > 2, or a new axis/thesis) → default to-phase: draft (Step 3b). The new material needs full prose expansion → consistency → fact-check → editorial → persona → headless.
    • Moderate (new examples/claims, no new sections, deltaPct ≤ 20 %) → default to-phase: factcheck-sweep (Step 5) so the new claims get verified, then editorial + persona + headless re-run.
    • The operator may override with explicit --to-phase.

Step 3 — Log the pivot + reset the phase (the ritual)

  1. Append a pivot entry to articles.NN.pivots[]:
    {
      "timestamp": "<ISO-8601>",
      "reason": "<--reason>",
      "fromPhase": "<currentPhase before this command>",
      "toPhase": "<resolved to-phase>",
      "wordCountBefore": <baseline>,
      "wordCountAfter": <current>,
      "deltaPct": <deltaPct>,
      "newSections": <newSections>,
      "gatesToRerun": ["factcheck-sweep", "editorial-review", "persona-sweep-prelock", "headless-review"]
    }
    
    gatesToRerun always spans every gate from the reset phase through Step 6.5 — a pivot invalidates the fact-check, the editorial craft pass, the persona resonance verdict, AND the headless package, because all of them judged the pre-pivot text.
  2. Reset currentPhase to the resolved toPhase, and set the article's phase to match.
  3. Un-lock if needed. If articles.NN.locked was true, set locked: false and status: "in-progress" — a pivot means the edition is no longer locked. Surface this plainly (the prior POST.html is now stale and will be re-rendered at the next lock).
  4. Invalidate the downstream verdicts so they cannot be mistaken for current: set personaSweep.resonance, editorialReview, and headlessReview.status back to a re-run state (e.g. headlessReview.status: "pending"), and note in each that they were invalidated by pivot <timestamp>. Leave the pivots[] log and factcheckLog history intact (history is durable).
  5. Update updatedAt and write edition-state.json.

Step 4 — Point the next step

Write a precise next-step line to <serie>/STATE.md (overwrite, ONE-system):

PIVOT logged (<reason>, +<deltaPct>%, <newSections> new sections) →
currentPhase reset to <toPhase>. Resume /linkedin:newsletter; it will re-run
fact-check (5) → editorial (5.5) → persona (6) → headless (6.5) on the pivoted
version BEFORE lock. Headless package: /linkedin:headless-review --article NN.

Do not run the gates yourself — /linkedin:newsletter owns the pipeline and will resume deterministically from the reset currentPhase and re-run every gate in gatesToRerun before it permits lock.

Pivot logged.
- Article NN: <reason>
- Scope: <structural|moderate>  (Δ <deltaPct>%, <newSections> new sections)
- currentPhase: <fromPhase> → <toPhase>   locked: <true→false | unchanged>
- Gates to re-run before lock: fact-check (5) · editorial (5.5) · persona (6) · headless (6.5)
Next: resume /linkedin:newsletter (re-runs the gates) → then lock.

Reference Files

  • ${CLAUDE_PLUGIN_ROOT}/commands/newsletter.md — the pipeline this re-opens; Step 8 lock-precondition runs the same heuristic; the resumption table replays from the reset currentPhase
  • ${CLAUDE_PLUGIN_ROOT}/commands/headless-review.md — the cold review package that must re-pass on the pivoted version
  • ${CLAUDE_PLUGIN_ROOT}/config/edition-state.template.jsonarticles.NN.pivots schema + the heuristic notes