feat(linkedin-studio): N24 — promo-post-motor (hook-forge + shareability-gate) [skip-docs]

Step 9 (post-lock distribution gate) får to tillegg, begge scoped til utgave-promo:

1. Hook-forge (E#7): 5-8 krok-varianter for delingsteksten. 110-140-båndet
   håndheves PER VARIANT og MÅLES (perl -CSD; awk length/wc -c teller bytes og
   lyver på æ/ø/å). Utenfor båndet = diskvalifisert, ikke rangert lavere.
   Settet må spenne minst tre krok-typer, ellers er det omskrivinger, ikke valg.
   Hver variant må spores til en påstand kroppen faktisk gjør (ingen bait).
   Ingen predicted-engagement score — et tall som påstår å vite hva som sprer
   seg er oppfunnet (N22-defektklassen); operatøren rangerer.
   Valgt variant går GJENNOM randsone-gaten, aldri utenom.

2. Shareability-gate (E#8): konverter-modus får en ANDRE binær — deling.
   «Hvem deler dette til en kollega, og hvorfor?» + RESHARE/SAVE/SEND.
   Svaret må navngi en rolle og et avsender-motiv; «nyttig for alle i tech»
   er NEI. Blokkerende: to mislykkede omramminger => operatørvalg (pivot eller
   registrert foldIn), aldri en stille passering.

Ti suiter grønne: test-runner 300/0 (287->300, +13 ubetingede; floor 268->281)
· trends 300 · analytics 202 · hooks 191 · brain 134 · editions 72 · render 63
· specifics-bank 45 · tests 35 · contract-gate 33. Begge nye compound-predikater
mutasjonstestet mot faktisk fil (fjernet literal => rød).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RvtDSvQDUmjd5bXdAxUu6D
This commit is contained in:
Kjell Tore Guttormsen 2026-07-31 21:22:49 +02:00
commit 77426135a5
7 changed files with 337 additions and 56 deletions

View file

@ -5,14 +5,16 @@ description: |
judge whether it lands — not whether it is correct. Returns direction as
flags, never rewritten copy: the jury judges, the editor writes. Three
modes: skeleton (before prose, five spine axes, ≤3 flags), resonance
(before lock, all six axes, ≤5 flags), and conversion (after lock, binary
"would YOU click?" on the hook only).
(before lock, all six axes, ≤5 flags), and conversion (after lock, two
binaries on the distribution copy — "would YOU click?" and "would YOU
forward it, to whom, and why?").
Use when the user says:
- "does this skeleton argue what it claims to argue?", "skeleton check"
- "does this land for [persona]?", "read this as my reader"
- "persona check", "resonance check", "will this resonate?"
- "would my reader click this?", "conversion check on the hook"
- "would anyone share this?", "who forwards this to a colleague?"
- "is the takeaway clear for a leader?", "does the hook hold?"
- "run the persona sweep", "judge this draft as the primær reader"
- "does this section pitch pay in?", "is the spine right?"
@ -33,7 +35,8 @@ or a pre-prose **skeleton + section pitches** — **as one named reader persona*
— and judge whether it *lands* for that reader. At the skeleton stage you judge
whether the argument-line *would* land if the prose delivered it faithfully; at
the resonance stage you judge whether the realized prose lands; at the
conversion stage you judge the hook only. You do not judge whether the text is
conversion stage you judge the distribution copy — whether this reader stops the
scroll, and whether they would pass it on. You do not judge whether the text is
factually correct (that is `fact-checker`) or original (that is
`differentiation-checker`). You judge whether it **works for this reader**.
@ -83,11 +86,29 @@ is where the draft earns the right to be locked.
### Konverter-modus (after lock)
Runs at the post-lock conversion sweep (Step 9). Judge the **hook only**,
binary: «would YOU click?» — **JA / NEI**. No axis scoring, no flags, no copy.
Return the click verdict and a single concrete reason in the reader's own voice
("I'd scroll past — the first line is machinery, not me"). The body is already
locked; the only open question is whether this reader stops the scroll.
Runs at the post-lock distribution sweep (Step 9), and advisory inside the cold
package (Step 6.5). Judge the **distribution copy only** and return **two
binaries** — no axis scoring, no flags, no copy:
1. **Klikk** — «would YOU click?» — **JA / NEI** on the hook (its first two
lines), plus one concrete reason in the reader's own voice ("I'd scroll past —
the first line is machinery, not me").
2. **Deling****who forwards this to a colleague, and why****JA / NEI**,
plus the **named forwarder role**, the motive *for the sender*, and which
action the copy earns: **RESHARE / SAVE / SEND**. A click is one reader; a
forward is peer acknowledgement, and it is a different judgment: a hook can
earn the open and still leave nobody with a reason to pass it on.
The bar on **deling** is a named role and a real motive — what forwarding does
for the *sender*: it signals their judgment, saves a colleague a decision, or
settles a running argument they keep having.
**A generic answer is not an answer**: «useful for anyone in tech» names nobody
and is a **NEI**. Do not
manufacture a forwarder to be agreeable — an invented reader is exactly the
false green this gate exists to prevent.
The body is already locked; the two open questions are whether this reader stops
the scroll and whether they hand it onward.
## Review Process
@ -122,8 +143,11 @@ Read top to bottom, read-only, once, the way this reader actually would.
- **Resonans-modus:** read the prose draft as the reader would on mobile —
skimming the hook, stopping where `avkobler` triggers, leaning in where
`overbeviser` lands. Note where this specific reader would disengage.
- **Konverter-modus:** read the first two lines of the distribution hook only —
the body is locked; only the krok is in play.
- **Konverter-modus:** read the distribution copy only — the first two lines of
the hook (for klikk) and the promise that copy makes about the edition (for
deling). The body is locked; only the distribution copy is in play. Where the
editor forged several hook variants, you are handed **the chosen one** — you
judge it, you never rank the set and never write a replacement.
### Step 3: Judge on axes (mode-dependent)
@ -138,7 +162,7 @@ Read top to bottom, read-only, once, the way this reader actually would.
(lands), **DELVIS** (partly), or **IKKE** (fails), each with a one-line reason
grounded in the persona's fields. Do not invent a seventh axis; do not skip
one.
- **Konverter-modus** — no axis scoring. Skip to Step 5.
- **Konverter-modus** — no axis scoring, on either binary. Skip to Step 5.
### Step 4: Sort to flags (mode-dependent cap)
@ -151,7 +175,8 @@ resonans), the primær's blockers before a sekundary's nice-to-haves.
three load-bearing problems and stop.
- **Resonans-modus:** **cap at five.** The axis that passes cleanest does not
need a flag.
- **Konverter-modus:** no flags. Only the binary verdict + one reason.
- **Konverter-modus:** no flags. Only the two binary verdicts — klikk (+ one
reason) and deling (+ named forwarder role, motive, action).
Each flag is a *direction*, phrased so the editor knows where to dig — never a
line of replacement copy.
@ -169,8 +194,10 @@ gate ladder (see Verdict Tokens below).
re-judge the same six axes. Loop until the primær returns a clean JA. You
re-judge every round; you never write the fix.
- **Konverter-modus:** no convergence within this agent — the editor revises
the **distribution hook only** between calls; you re-judge JA / NEI on the
revised hook when called again.
the **distribution copy only** between calls (a sharpened krok, the next forge
variant, or a re-framed promise); you re-judge both binaries on the revised
copy when called again. Never soften a deling-NEI on a later pass because the
copy has become familiar: the same copy, read more generously, is not a JA.
## The Five Spine Axes (skjelett mode)
@ -244,8 +271,11 @@ does not).
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.
**Conversion mode** has no gate ladder — only the two binaries: the click verdict
(JA / NEI) with one reason, and the deling verdict (JA / NEI) with a named
forwarder role, the sender's motive and the RESHARE / SAVE / SEND action. Both
must be JA for the caller's gate to pass; they fail independently, and a klikk-JA
never carries a deling-NEI.
### Hard-fail conditions (blocking — rewrite, do NOT annotate)
@ -349,10 +379,15 @@ the skeleton + pitches (NOT prose — there is none yet) and re-runs this sweep.
```
## Persona Conversion Check — [persona name] ([primær | sekundær])
**Mode:** konverter (after lock — hook only)
**Mode:** konverter (after lock — distribution copy: klikk + deling)
**Would YOU click?** [JA | NEI]
**Reason (this reader's voice):** [one concrete line — what stops or starts the scroll]
**Would YOU forward it — who, and why?** [JA | NEI]
**Forwarder (named role):** [the role this reader would send it to — "nobody" if NEI]
**Motive (what it does for the sender):** [signals judgment / saves a decision / settles an argument — one line, in this reader's voice]
**Action earned:** [RESHARE | SAVE | SEND | none]
```
## Key Principles
@ -370,12 +405,14 @@ the skeleton + pitches (NOT prose — there is none yet) and re-runs this sweep.
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
(binary verdict + one reason). Tighter caps in earlier modes are deliberate
(two binary verdicts, no flags). Tighter caps in earlier modes are deliberate
— the spine should be tight.
6. **Ground every flag in the persona.** "Hits `avkobler`" beats "weak hook."
Tie each judgment to rolle / avkobler / overbeviser / ekspertise / sjargong.
7. **Conversion is binary.** In konverter-modus, judge the hook only — JA/NEI and
one reason. No axes, no flags, no copy.
7. **Conversion is two binaries.** In konverter-modus, judge the distribution copy
— klikk (JA/NEI + one reason) and deling (JA/NEI + named forwarder role +
motive + RESHARE/SAVE/SEND). No axes, no flags, no copy. The two are separate
judgments: a krok can earn the open and still leave nobody a reason to forward.
8. **Skjelett judges the promise, not the prose.** There is no prose yet. Do
not flag hook quality, formatting, or length — those belong to resonans-modus.
Do flag a premise the reader cannot accept, a recommendation that dissolves
@ -392,7 +429,11 @@ the skeleton + pitches (NOT prose — there is none yet) and re-runs this sweep.
skjelett, seventh in resonans)
- Score factual accuracy or originality (wrong agent)
- Give vague flags ("make it punchier") instead of persona-grounded direction
- Run axis scoring in konverter-modus, or skip the binary click verdict
- Run axis scoring in konverter-modus, or skip either binary (klikk, deling)
- Write or rank the hook-forge variants — the forge is the editor's pen; you are
handed the chosen krok and judge that one
- Manufacture a forwarder to reach a deling-JA, or accept a role nobody could
name ("anyone in the field") as an answer to who forwards it
- Use resonans axes (Krok, Tone, Lengde/driv) in skjelett-modus — there is no
prose to judge them against
- Soften a primær BLOCK (skjelett: Premiss/Anbefaling MANGLER; resonans: Krok/

View file

@ -171,7 +171,7 @@ contains ONLY the cold-contract inputs. Map `--type` to archetypes:
| `language` | `linkedin-studio:language-reviewer` | — | frozen draft + contract |
| `fact` | `linkedin-studio:fact-reviewer` | — | frozen draft + contract |
| `persona-resonance` | `linkedin-studio:persona-reviewer` | `mode: resonans`, one call **per active persona** | frozen draft + persona block |
| `persona-conversion` | `linkedin-studio:persona-reviewer` | `mode: konverter`, **primær only** (hook only) | distribution hook / first two lines |
| `persona-conversion` | `linkedin-studio:persona-reviewer` | `mode: konverter`, **primær only** (klikk + deling) | distribution copy: hook / first two lines + the promise it makes |
`all` = every row above (resonance fans out one call per active persona;
conversion runs the primær). **Cold-prompt template** for each call:
@ -215,7 +215,7 @@ yourself or pick winners between reviewers — surface them, the operator gates.
| # | F-kat | 🔴/🟡/🟢 | Påstand | Kilde / retning |
… + Pivot-risk: <claims that look freshly added, or "none">
### persona-resonance — <per persona: JA/NEI + ≤5 flags>
### persona-conversion — <primær JA/NEI on the hook>
### persona-conversion — <primær klikk JA/NEI on the hook + deling JA/NEI (forwarder role, motive, RESHARE/SAVE/SEND)>
## Cross-archetype signal
- BLOCK / 🔴 total: <N> REWORK total: <N> primær resonance: JA/NEI primær conversion: JA/NEI

View file

@ -877,7 +877,7 @@ Next: Step 2.5 — Skeleton + section pitch (operator + persona gate BEFORE pros
`<serie>/NN-skjelett.md`, and **`mode: skjelett`** (the before-prose mode —
five spine axes, ≤3 flags as direction, HOLDER/TVILER/MANGLER scoring).
This is NOT resonans mode (Step 6 — that runs on full prose) and NOT
konverter mode (Step 9 — that judges the hook only).
konverter mode (Step 9 — that judges the distribution copy: klikk + deling).
8. **Collect skjelett verdicts and gate.** Each call returns per-axis flags
(HOLDER/TVILER/MANGLER), ≤3 direction-only flags, a section-pitch check
@ -1617,7 +1617,7 @@ command runs — see `${CLAUDE_PLUGIN_ROOT}/commands/headless-review.md` for the
- `linkedin-studio:language-reviewer` — language quality (L1L5; grades against `edition-state.language`, Norwegian-specific rules when `language: no`)
- `linkedin-studio:fact-reviewer` — cold re-verification (F1F4, 🔴/🟡/🟢, incl. pivot premises)
- `linkedin-studio:persona-reviewer` `mode: resonans` — **one call per active persona**
- `linkedin-studio:persona-reviewer` `mode: konverter`**primær only** (hook)
- `linkedin-studio:persona-reviewer` `mode: konverter`**primær only** (hook + share; advisory here, blocking at Step 9)
Each call's prompt carries ONLY the cold-contract inputs (frozen draft path,
`language`, contract path if it ships, persona for the persona modes) + the
@ -2061,18 +2061,22 @@ Next: Step 9 — Hook / conversion gate (post-lock).
The locked edition still has to earn the feed. Before it ships, the
**feed-facing surfaces** the reader actually meets — the **delingstekst hook**,
the **samle post**, the **carousel slide text**, and the **edition title**
face two final gates: a **randsone fact + language gate** (so nothing false or
clumsy reaches the feed in the most-read, most-requoted copy — C-4/C-9) and the
**hook conversion binary** (would the primær persona, scrolling, actually stop
and open this?). Both operate on **distribution copy only** — the post-lock
sweep, distinct from the pre-lock resonance sweep (Step 6), never the locked
body. Until N9 only the hook's click-worth was judged; the hook's *truth and
language*, the samle post, the carousel slides and the title reached the feed
ungated.
face a **hook-forge** (the krok competes against alternatives instead of shipping
the one the draft happened to end on) and three gates: a **randsone fact +
language gate** (so nothing false or clumsy reaches the feed in the most-read,
most-requoted copy — C-4/C-9), the **hook conversion binary** (would the primær
persona, scrolling, actually stop and open this?), and the **shareability gate**
(would that reader pass it on — and to whom?). All operate on **distribution copy
only** — the post-lock sweep, distinct from the pre-lock resonance sweep (Step 6),
never the locked body. Until N9 only the hook's click-worth was judged; the hook's
*truth and language*, the samle post, the carousel slides and the title reached
the feed ungated — and until N24 the hook shipped unchallenged and nobody asked
who would forward the edition.
> **Order assertion (enforced).** This gate (Step 9) runs AFTER lock (Step 8) — it
> operates on the **distribution copy** of an already-locked edition and must never
> reopen the locked body. Both the randsone fact/language gate and the hook binary
> reopen the locked body. The hook-forge, the randsone fact/language gate, the hook
> binary and the shareability gate all
> revise only distribution surfaces (delingstekst, samle, carousel text,
> distribution title) and re-render via Step 8's `build-linkedin.mjs` /
> `build-carousel.mjs` — never the edition text. A defect that traces into the
@ -2101,7 +2105,38 @@ lock invariant without breaking phase order.
- the **edition title** — the edition's own headline (its distribution / feed
title), never strength-gated before now.
2. **Randsone fact + language gate (scoped — C-4/C-9).** Run two scoped reviewers
2. **Hook-forge — forge the alternatives before gating one (E#7).** The hook that
exists is the one the draft happened to end on; it has never competed against
anything. Forge **five to eight hook variants** for the delingstekst krok, then
let the operator choose — the gates below judge the chosen krok, not the accident.
- **Measure the band, per variant.** Each variant's opening line must land in
**110140 characters** (the mobile "…see more" cutoff — the hook rule the
short-form surfaces already hold). Measure it, never estimate it:
`perl -CSD -ne 'chomp; printf "%d\n", length($_)'`. Norwegian æ/ø/å are
multibyte, so `awk length` and `wc -c` count BYTES and over-report. A variant
outside the band is **disqualified, not ranked lower** — the cutoff is
physical, not a preference, and it is enforced per variant, never on the set.
- **Span the hook types.** Name each variant's type from
`${CLAUDE_PLUGIN_ROOT}/references/engagement-frameworks.md`. The surviving set
must cover **at least three distinct hook types** — otherwise the forge
produced rewordings of one idea and the operator has no real choice.
- **Trace every variant to the locked body.** A variant must rest on
**a claim the locked body actually makes**. One that promises what the
edition does not deliver is disqualified — it is bait, and the randsone fact
gate below would 🔴 it anyway.
- **Carry only what can be checked.** Each variant ships with its measured
length, its hook type and its body-trace — and
**no predicted-engagement score**. A number claiming to know which krok will
travel is invented; the ranking is the operator's, on variants the plugin can
honestly describe.
- **Fewer than five survivors → forge again.** Presenting three survivors as
"the set" hides that the band or the body constrained the forge.
- The operator picks one via `AskUserQuestion` — the gate that already exists
here. The chosen variant becomes the delingstekst hook and goes
**through the randsone gate, never around it**: the same fact, language and
length rules as any other distribution copy. `[GATE]`
3. **Randsone fact + language gate (scoped — C-4/C-9).** Run two scoped reviewers
over *only* these surfaces (never the locked body), issued from THIS command
layer in the foreground, `subagent_type` namespaced:
- `linkedin-studio:fact-reviewer`**F1** (verifiable claims) + **F3** (number
@ -2114,7 +2149,7 @@ lock invariant without breaking phase order.
Pass each reviewer only the four surfaces + the sources they cite + `language`.
This is a **scoped mini-pass**, not a re-review of the article. `[GATE]`
3. **Title-strength gate (C-9).** The edition's own title was never strength-gated —
4. **Title-strength gate (C-9).** The edition's own title was never strength-gated —
only the hook's two lines were. Judge the **title-strength** of the **edition
title** here: does it earn the open on its own, or is it a generic label? The
strongest candidate becomes the distribution title. The verdict is **binding on
@ -2122,7 +2157,7 @@ lock invariant without breaking phase order.
canonical (locked) title** — changing that is a body edit → STOP, run
`/linkedin:pivot`; never edit the locked title in place.
4. **Resolve the randsone gate.**
5. **Resolve the randsone gate.**
- **Fact 🔴 / L-BLOCK on a distribution surface** → revise that surface **by
tightening** (hook, samle, carousel text, or distribution title — all
distribution copy), **re-render** the affected artifact (POST.html via Step 8's
@ -2132,32 +2167,63 @@ lock invariant without breaking phase order.
pivot: STOP, run `/linkedin:pivot`. The randsone gate never reopens the locked
body in place — the same invariant as the conversion loop. `[GATE]`
5. **Run the hook conversion binary** (`subagent_type:
linkedin-studio:persona-reviewer`, **`mode: konverter`** — the after-lock,
hook-only mode, NOT resonans) for the **primær** persona only. The agent returns
a single binary verdict, **JA / NEI**, on «would YOU click?» — no axis scoring,
no flags, no rewritten copy (the jury judges, the editor writes).
- **JA** → the hook converts. Proceed to Step 10.
6. **Run the distribution binaries** (`subagent_type:
linkedin-studio:persona-reviewer`, **`mode: konverter`** — the after-lock
distribution mode, NOT resonans) for the **primær** persona only, on the chosen
forge variant. The agent returns **two binary verdicts****klikk** («would YOU
click?») and **deling** (item 7) — no axis scoring, no flags, no rewritten copy
(the jury judges, the editor writes; the forge is the editor's pen).
- **JA** → the hook converts. Proceed to the shareability gate.
- **NEI** → revise the **delingstekst hook only** (sharpen the krok by tightening,
body frozen), **re-render POST.html** via `build-linkedin.mjs`, and re-run the
conversion check. Loop until JA. `[GATE]`
or take the next forge variant — body frozen), **re-render POST.html** via
`build-linkedin.mjs`, and re-run the conversion check. Loop until JA. `[GATE]`
6. **Persist.** Record the randsone-gate result in `edition-state.json`
7. **Shareability gate — «hvem deler dette til en kollega, og hvorfor?» (E#8).**
A click is one reader; a forward is peer acknowledgement, and it is the signal
the edition was written to earn. The `konverter` call's second binary is the
**deling verdict**: judged by the primær persona on the same distribution copy —
**who forwards this to a colleague, and why** — plus which action the edition
actually earns from that reader: **RESHARE / SAVE / SEND**.
- **A plausible answer names a role and a motive.** It must name a role the
reader could actually point at, and what forwarding does *for the sender*
signals their judgment, saves a colleague a decision, settles a running
argument. «Useful for anyone in tech» names nobody: that is a **NEI**.
- **NEI → revise the distribution copy** (the promise may simply be framed for a
reader nobody forwards to), re-render, re-check. Body frozen, as everywhere in
this step.
- **Two failed re-framings → stop; do not lower the bar.** If the honest reason
is that the edition offers nothing a reader would pass on, that is a
body-level finding, not a copy problem: put it to the operator as a choice —
run `/linkedin:pivot`, or ship and record it as an `articles.NN.foldIns` row
for the Step 11 retro. There is **never a silent pass**: this gate is resolved
by a fix or by a recorded operator decision, never by re-reading the same copy
more generously. `[GATE]`
8. **Persist.** Record the forge in `edition-state.json`
`articles.NN.hookForge` (each variant with its measured length, hook type,
body-trace and disqualification reason if any, plus which one the operator
chose), the randsone-gate result in
`articles.NN.randsoneGate` (per-surface fact/language verdicts + title-strength +
what was revised) and the conversion verdict in
`articles.NN.personaSweep.conversion`; set `currentPhase: "hook-conversion-gate"`.
what was revised), the click verdict in
`articles.NN.personaSweep.conversion` and the share verdict in
`articles.NN.personaSweep.deling` (verdict + the named forwarder role + the
RESHARE/SAVE/SEND action, or the recorded operator decision);
set `currentPhase: "hook-conversion-gate"`.
**↳ Phase transition** — run the protocol (Step 0) for `hook-conversion-gate`,
`--next "Step 10 — scheduling"`.
```
Randsone + conversion gate (post-lock, distribution copy only).
Forge + randsone + conversion + shareability gate (post-lock, distribution copy only).
- Hook-forge: <N> forged / <N> disqualified (band <N>, body-trace <N>) · types spanned: <N> → chose #<k> (<measured> chars, <type>)
- Surfaces gated: delingstekst hook · samle post · carousel slide text · edition title
- Fact (F1/F3): <N> 🔴 → resolved (or pivot if it traces to the body)
- Language (L1/L2): <N> BLOCK → tightened
- Title-strength: <verdict> (distribution title sharpened; canonical-title weakness → pivot)
- Conversion (primær, konverter): JA (else: NEI — revise hook, re-render, re-check)
- Deling (primær, konverter): JA — <role> sends it to <role> because <motive> · action: RESHARE|SAVE|SEND
(else: NEI — reframe the copy; twice failed → operator decision, never a silent pass)
- Body: untouched (locked in Step 8)
Gate: [PASS — randsone clean + JA] (else loop on distribution copy, or pivot)
Gate: [PASS — randsone clean + klikk JA + deling JA] (else loop on distribution copy, or pivot)
Next: Step 10 — Scheduling.
```

View file

@ -21,7 +21,7 @@
"annotation — optional annotatable review HTML for a manual pass (Step 7)",
"visual-assets — cover (+ optional inline figures) or carousel deck: brief → generate → operator-gate → approve, BEFORE lock so build-linkedin.mjs picks them up (Step 7.5)",
"lock-delivery — LOCK → POST.html all-in-one-place deliverable (Step 8)",
"hook-conversion-gate — persona gate on distribution text post-lock: would YOU click? (Step 9)",
"hook-conversion-gate — persona gate on distribution text post-lock: hook-forge, would YOU click?, and who forwards this and why (Step 9)",
"scheduling — register edition in plugin queue/state for native LinkedIn scheduling (Step 10)",
"retro — close the loop (≤5 min, AFTER scheduling): promote the pending articles.NN.foldIns with an explicit operator JA/NEI (mechanical → a contract-gate rule; judgment → the language-rules file / craft checklist), summarize the MEASURED effort from articles.NN.phaseLog, and ask ONE process-friction question. The corrections made in this edition become enforced before the next one starts (Step 11)"
],

View file

@ -35,7 +35,8 @@ trim, or extend them per series.
NO is **not** accepted: the text is revised until the primær reaches a clean YES.
- **Two sweep modes** (same `persona-reviewer` agent): resonance mode (Step 6,
BEFORE lock — «does the point land for this reader?») and conversion mode
(Step 9, after lock — binary «would YOU click?» on the hook only).
(Step 9, after lock — two binaries on the distribution copy: «would YOU click?»
and «who forwards this to a colleague, and why?»).
### Per-artifact personas (one or more personas per edition)

View file

@ -174,7 +174,7 @@ to a finished draft and call it gated).
| Step 4 — Consistency + quality | Primary enforcement: apply rules 16, calibrate per rule 7, report a pass/flag per rule. Rule 8 is verified as historical fact (skeleton existed + was gated). |
| Step 5 — Fact-check sweep | Fixes obey rule 6 (tighten, don't expand). |
| Step 6 — Persona sweep (pre-lock) | Rework obeys rule 6; the leader-takeaway (rule 1) and arc (rule 2) are what the reader jury judges for resonance. A draft that passed rule 8 typically lands here with far fewer spine-level reworks. |
| Step 9 — Hook / conversion gate | Hook revisions obey rule 6 (sharpen the krok by tightening, body stays locked). |
| Step 9 — Hook / conversion gate | Hook revisions obey rule 6 (sharpen the krok by tightening, body stays locked). The hook-forge is not an exception: every variant is cut to the same 110140 band, so choosing between kroks swaps rather than expands. |
## Self-certification boundary

View file

@ -3079,6 +3079,170 @@ fi
echo ""
# --- Section 16z: Promo-Post Engine - hook-forge + shareability gate (N24 / E#7, E#8) ---
echo "--- Promo-Post Engine: hook-forge + shareability gate (N24) ---"
# The edition's promo post is the acknowledgement engine: a peer forwarding it to a peer is the
# signal the edition was written to earn. Two things were missing at Step 9 and both fail QUIETLY:
# (E#7 forge) the shipped krok was the one the draft happened to end on - it never competed
# against an alternative. The forge produces five to eight variants, enforces the
# mobile cutoff PER VARIANT (measured, not estimated), spans at least three hook
# types so the choice is real, and traces every variant to the locked body so a
# variant cannot promise what the edition does not deliver.
# (E#7 honesty) the forge carries ONLY checkable marks - measured length, hook type, body-trace.
# A predicted-engagement score would be an invented composite, which is the exact
# defect class N22 removed (fabricated percentiles / Velocity Score). This check is
# the one most likely to erode, because a ranked list LOOKS more helpful.
# (E#8 deling) a click is one reader; a forward is the acknowledgement. The gate asks who
# forwards this and why, demands a named role and a sender-motive, and CANNOT be
# resolved by re-reading the same copy more generously (never a silent pass).
# (invariant) the forged variant goes THROUGH the N9 randsone gate, never around it - a forge
# that bypassed the fact/language pass would reopen the hole N9 closed.
# Both predicates are compound, so both carry a non-vacuity self-test (mirrors 16p/16y). All
# checks are UNCONDITIONAL .md greps -> they raise the deps-absent floor.
NL_N24="commands/newsletter.md"
PR_N24="agents/persona-reviewer.md"
STEP9_N24=$(awk '/^## Step 9:/{f=1} /^## Step 10:/{f=0} f' "$NL_N24")
forge_honest() { # $1 = text; honest iff it forges a SET, cuts on the band, and refuses an invented score
echo "$1" | grep -qiF "five to eight hook variants" \
&& echo "$1" | grep -qiF "disqualified, not ranked lower" \
&& echo "$1" | grep -qiF "no predicted-engagement score"
}
deling_gated() { # $1 = text; gated iff it asks the named-forwarder question, names the actions, and cannot self-resolve
# -qiF throughout: these are concepts in running prose, where sentence position decides the
# casing (N23 lesson - do not bend the prose to fit the lint).
echo "$1" | grep -qiF "who forwards this to a colleague, and why" \
&& echo "$1" | grep -qiF "RESHARE / SAVE / SEND" \
&& echo "$1" | grep -qiF "never a silent pass"
}
FORGE_SELFTEST_N24=1
if ! forge_honest "forge five to eight hook variants; a variant outside the band is disqualified, not ranked lower, and carries no predicted-engagement score"; then
FORGE_SELFTEST_N24=0; echo " non-vacuity FAIL: a fully-wired hook-forge probe was not detected"
fi
while IFS= read -r probe; do
[ -z "$probe" ] && continue
if forge_honest "$probe"; then
FORGE_SELFTEST_N24=0; echo " false-positive FAIL: under-wired forge probe accepted -> $probe"
fi
done <<'NEGATIVE16Z1'
forge five to eight hook variants and rank them by predicted engagement, best first
five to eight hook variants, each disqualified, not ranked lower when out of band, scored 1-10 for reach
generate a few hook options and let the operator pick the strongest one
variants outside the band are disqualified, not ranked lower, and carry no predicted-engagement score
NEGATIVE16Z1
if [ "$FORGE_SELFTEST_N24" -eq 1 ]; then
pass "hook-forge self-test: predicate needs the variant SET + band-cutoff + no invented score (1 accepted, 4 under-wired rejected)"
else
fail "hook-forge self-test failed - the N24 forge lint is vacuous or over-eager"
fi
DELING_SELFTEST_N24=1
if ! deling_gated "the gate asks who forwards this to a colleague, and why, records RESHARE / SAVE / SEND, and allows never a silent pass"; then
DELING_SELFTEST_N24=0; echo " non-vacuity FAIL: a fully-gated shareability probe was not detected"
fi
while IFS= read -r probe; do
[ -z "$probe" ] && continue
if deling_gated "$probe"; then
DELING_SELFTEST_N24=0; echo " false-positive FAIL: under-gated deling probe accepted -> $probe"
fi
done <<'NEGATIVE16Z2'
ask who forwards this to a colleague, and why, then record RESHARE / SAVE / SEND and move on
judge whether the post is shareable and saveable; never a silent pass
who forwards this to a colleague, and why - answer it, and never a silent pass
NEGATIVE16Z2
if [ "$DELING_SELFTEST_N24" -eq 1 ]; then
pass "shareability-gate self-test: predicate needs the named-forwarder question + the three actions + no silent pass (1 accepted, 3 under-gated rejected)"
else
fail "shareability-gate self-test failed - the N24 deling lint is vacuous or over-eager"
fi
# (E#7 forge) Step 9 forges a variant SET and cuts on the band instead of inventing a score
if forge_honest "$STEP9_N24"; then
pass "newsletter.md Step 9 forges five to eight variants, cuts out-of-band, and invents no score (E#7)"
else
fail "newsletter.md Step 9 has no honest hook-forge - the krok still ships unchallenged, or is ranked by an invented number (E#7)"
fi
# (E#7 measurement) the band is MEASURED per variant, with the multibyte-safe counter
if echo "$STEP9_N24" | grep -qF "perl -CSD" \
&& echo "$STEP9_N24" | grep -qiF "enforced per variant, never on the set"; then
pass "Step 9 measures the hook band per variant with the multibyte-safe counter (awk length lies on ae/oe/aa)"
else
fail "Step 9 does not measure the band per variant - byte-counting over-reports Norwegian hooks (E#7)"
fi
# (E#7 real choice) the surviving set must span hook types, or the forge produced rewordings
if echo "$STEP9_N24" | grep -qiF "at least three distinct hook types"; then
pass "Step 9 requires the surviving variants to span at least three hook types (a real choice, not rewordings)"
else
fail "Step 9 does not require type-spanning variants - eight rewordings of one idea is not a choice (E#7)"
fi
# (E#7 no bait) every variant traces to a claim the LOCKED body makes
if echo "$STEP9_N24" | grep -qiF "a claim the locked body actually makes"; then
pass "Step 9 disqualifies a variant that promises what the locked body does not deliver (no bait krok)"
else
fail "Step 9 lets a hook variant promise what the edition never delivers - bait reaches the feed (E#7)"
fi
# (invariant) the chosen variant is gated, not exempted - it re-enters the N9 randsone pass
if echo "$STEP9_N24" | grep -qiF "through the randsone gate, never around it"; then
pass "Step 9 routes the chosen forge variant through the randsone gate (N9 hole stays closed)"
else
fail "Step 9 does not route forged variants through the randsone gate - a forged hook could reach the feed ungated (N9)"
fi
# (E#8 deling) the shareability gate is present at Step 9, with the whole predicate
if deling_gated "$STEP9_N24"; then
pass "newsletter.md Step 9 runs the shareability gate: named forwarder + RESHARE/SAVE/SEND + no silent pass (E#8)"
else
fail "newsletter.md Step 9 missing the shareability gate - nobody asks who would forward the edition (E#8)"
fi
# (E#8 escape hatch) a twice-failed reframe becomes an OPERATOR decision, never a lowered bar
if echo "$STEP9_N24" | grep -qiF "body-level finding" \
&& echo "$STEP9_N24" | grep -qF "/linkedin:pivot"; then
pass "Step 9 routes an unshareable edition to an operator decision (pivot or recorded fold-in), not to a softer read"
else
fail "Step 9 has no honest exit for an unshareable edition - the gate would resolve itself by lowering the bar (E#8)"
fi
# (E#8 persistence) both new results are persisted where the resumption protocol can see them
if echo "$STEP9_N24" | grep -qF "articles.NN.hookForge" \
&& echo "$STEP9_N24" | grep -qF "articles.NN.personaSweep.deling"; then
pass "Step 9 persists the forge and the share verdict to edition-state (resumable, auditable)"
else
fail "Step 9 does not persist hookForge / personaSweep.deling - the gate leaves no trace (E#7/E#8)"
fi
# (E#8 agent contract) konverter-modus carries the SECOND binary, with role + motive + action
if grep -qiF "who forwards this to a colleague, and why" "$PR_N24" 2>/dev/null \
&& grep -qiF "named forwarder role" "$PR_N24" 2>/dev/null \
&& grep -qiF "RESHARE / SAVE / SEND" "$PR_N24" 2>/dev/null; then
pass "persona-reviewer konverter-modus returns the deling binary with a named role and an action (E#8)"
else
fail "$PR_N24 konverter-modus has no share verdict - Step 9's gate has no judge (E#8)"
fi
# (E#8 anti-flattery) a manufactured forwarder is the false green this gate exists to prevent
if grep -qiF "A generic answer is not an answer" "$PR_N24" 2>/dev/null; then
pass "persona-reviewer refuses a generic forwarder ('anyone in tech' names nobody)"
else
fail "$PR_N24 accepts a generic answer to who-forwards-this - the gate would pass on flattery (E#8)"
fi
# (E#7 role separation) the jury judges the chosen krok; the forge stays the editor's pen
if grep -qiF "the forge is the editor's pen" "$PR_N24" 2>/dev/null; then
pass "persona-reviewer does not write or rank the forge variants (the jury judges, the editor writes)"
else
fail "$PR_N24 may rank or rewrite forge variants - that breaks the jury/editor separation (E#7)"
fi
echo ""
# --- Section 18: Assertion-Count Anti-Erosion (SC6) ---
# The lint self-modifies its own checks, so a green run could mask a silently dropped
# assertion. Pin the total pass()+fail() invocations as a monotonic floor; the count
@ -3159,12 +3323,21 @@ echo ""
# wiring grep + always-present/refusal-included grep + report leads-with-baseline/no-eyeball
# compound grep + normal-variation-not-trend grep + report refusal-honest compound grep +
# WoW-loses-to-baseline grep + analyze verify-before-diagnose grep + analyze never-upgrade-
# refusal grep) = 251.
# refusal grep) = 251; +17 for N23's seventeen UNCONDITIONAL Section-16y checks (regeneration-gate
# self-test + template four-section grep + template distillate/defers grep + setup Step-3g grep +
# setup menu-reachability grep + setup delegation grep + brain-block one-file count + advisor
# distillation grep + advisor declared-over-inferred grep + two per-surface gate greps + five
# consumption greps + absent-brief graceful grep) = 268; +13 for N24's thirteen UNCONDITIONAL
# Section-16z checks (hook-forge self-test + shareability-gate self-test + Step-9 forge_honest
# compound grep + Step-9 per-variant measurement grep + Step-9 type-span grep + Step-9 body-trace
# grep + Step-9 randsone-routing grep + Step-9 deling_gated compound grep + Step-9 operator-exit
# grep + Step-9 persistence grep + persona-reviewer deling-binary compound grep + persona-reviewer
# generic-answer refusal grep + persona-reviewer forge/editor separation grep) = 281.
# NB: the floor tracks the deps-absent MINIMUM (conditional TS suites warn-skip and drop
# the count), so it is bumped only by UNCONDITIONAL new checks — NOT pinned to the
# deps-present TOTAL_CHECKS (that would zero the warn-skip margin and false-fail a fresh
# clone). Runs last so TOTAL_CHECKS sees every prior check.
ASSERT_BASELINE_FLOOR=268
ASSERT_BASELINE_FLOOR=281
TOTAL_CHECKS=$((PASS + FAIL))
if [ "$TOTAL_CHECKS" -ge "$ASSERT_BASELINE_FLOOR" ]; then
pass "assertion-count anti-erosion: $TOTAL_CHECKS checks >= baseline floor $ASSERT_BASELINE_FLOOR"