ktg-plugin-marketplace/plugins/linkedin-studio/docs/plan-fullspektrum-innholdsmotor.md
Kjell Tore Guttormsen 433c2efb3d fix(linkedin-studio): S11 — model-name declaration drift + model-consistency lint guard
Cold full-brief re-review (S10) reached a class the S7->S9 algorithm-stat lens
never did:

BLOCKER — post-feedback-monitor published as Haiku in four surfaces
(README:259, skills/linkedin-studio:159 with wrong color Green too,
skills/linkedin-analytics:41, agents-capability-matrix:20) while
agents/post-feedback-monitor.md runs Opus. v4.0.0's Opus promotion never
reached the user-facing tables. Synced all to Opus/Lime. Refreshed
agents-capability-matrix.md (frozen at the v2.0 14-agent era): header 14->19,
+5 missing longform agents, tier counts Opus 2->8 / Haiku 1->0, longform-gate
diagram updated to the real 8-Opus-agent chain.

MAJOR — de-branded docs/plan-fullspektrum-innholdsmotor.md:70 (model brand +
jan-2026 asserted as fact -> no-name/no-month relevance-model phrasing). It was
the only tracked survivor; the rest live in gitignored ROADMAP.md /
.claude/research/ (not shipped, out of honesty scope).

META — added Section 10 model-consistency guard
(scripts/check-model-consistency.mjs): each agents/*.md model: must match every
surface declaration AND the canonical rosters must list all 19 agents.
Permanent non-vacuity self-test + e2e mutation-proven.

Pre-patch sweep confirmed post-feedback-monitor was the sole drifted agent
(89 model rows, 0 other mismatches). test-runner.sh 68/0/0, node --test 94/94.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 15:05:37 +02:00

473 lines
50 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Plan — LTL som fullspektrum LinkedIn-innholdsmotor
> **Type:** Renoverings- og byggeplan for `linkedin-studio`-pluginen («LTL»).
> **Skrevet:** 2026-05-26. **Status:** Til godkjenning før bygging. **Versjonsmål:** v1.2.0 → v2.0.0.
> **Følger av:** [brief-fullspektrum-innholdsmotor.md](./brief-fullspektrum-innholdsmotor.md) (samme mappe).
>
> **LES §0 FØRST.** Denne planen utføres sesjon-for-sesjon. Hver sesjon starter med tom kontekst (etter `/clear`) og har KUN denne fila + `BUILD-HANDOVER.local.md` + kildene §0 peker til. Derfor er alle navn, stier og begreper definert eksplisitt i §0 — ingenting forutsettes kjent.
---
## 0. Orientering for en ny sesjon
Denne seksjonen gjør planen selvstendig. Hvis et begrep brukes senere uten forklaring, slå det opp her.
### 0.1 Repoer og absolutte stier
| Det | Hva | Absolutt sti | Rolle her |
|-----|-----|--------------|-----------|
| **LTL-pluginen** | Claude Code-plugin for LinkedIn thought leadership. v1.2.0. 27 kommandoer, 16 agenter, 9 hooks, 6 skills. | `/Users/ktg/.claude/plugins/marketplaces/ktg-plugin-marketplace/plugins/linkedin-studio/` | **DETTE er repoet vi bygger i.** All plugin-endring skjer her. |
| **Marketplace-rot** | Open-source plugin-marketplace (flere plugins + `shared/`). Distribueres via Forgejo: `git.fromaitochitta.com/open/ktg-plugin-marketplace` (aldri GitHub). | `/Users/ktg/.claude/plugins/marketplaces/ktg-plugin-marketplace/` | Rot-`README.md` må oppdateres ved feature-endring (doc-plikt). |
| **maskinrommet** | Privat, lokalt repo (INGEN git-remote) der operatøren produserer alt LinkedIn-innhold. Inneholder `tools/` (4 render-skript + `fonts/`) og `serier/<slug>/` (én innholdsserie per mappe). | `/Users/ktg/repos/maskinrommet/` | **Annet repo enn pluginen.** Skriving hit krever eksplisitt instruks (cross-repo). Vi leser render-skriptene herfra i S1. |
| **Voyage-pluginen** | En annen plugin i samme marketplace. Implementerer en kontrakt-drevet, multi-sesjons pipeline for KODE-prosjekter: kommandoene `/trekbrief``/trekresearch``/trekplan``/trekexecute``/trekreview`, med parallelle spesialist-agenter og adversarielle reviewere. | `/Users/ktg/.claude/plugins/marketplaces/ktg-plugin-marketplace/plugins/voyage/` | **Referanse/inspirasjon, IKKE avhengighet.** Vi løfter *mønsteret* (faset pipeline, parallelle agenter, adversariell review før lås, multi-sesjon), men kopierer ALDRI koden — Voyage er kode-spesifikk (`file:line`, kode-reviewere, RULE_CATALOGUE). Les den for mønster-inspirasjon. |
| **svv-memory** | Memory-filer skrevet under produksjonen av Seres-serien (se 0.2). Kilden til prosess-erfaringen denne planen generaliserer. | `/Users/ktg/.claude/projects/-Users-ktg-repos-svv/memory/` | Les ved behov for dyp prosess-kontekst (se nøkkelfiler i 0.4). |
### 0.2 Hva «Seres-serien» er
Operatøren (Kjell Tore Guttormsen) produserte en kronikkserie på 6 deler — internt kalt «Seres-serien» eller «silvija-seres-motsvar» — i ~10 arbeidsøkter i mai 2026. Den utgjør de første utgavene av LinkedIn-nyhetsbrevet «Maskinrommet» (0.3). Serien ligger i `/Users/ktg/repos/maskinrommet/serier/silvija-seres-motsvar/`. Produksjonen avdekket en research- og review-tung prosess (0.4) som denne planen generaliserer til en gjenbrukbar pipeline. **«Seres-erfaringen»** = lærdommene derfra. Når planen sier «Seres beviste/avdekket X», betyr det «erfaringen fra denne serien viste X», dokumentert i svv-memory (0.1).
### 0.3 «Maskinrommet»-nyhetsbrevet
Operatørens ukentlige LinkedIn-nyhetsbrev, etablert 2026-05-25 (URL: `linkedin.com/newsletters/maskinrommet-7464605936645509120`). Status ved planskriving: ~30 abonnenter, 6 editions (Seres-serien) ferdig produsert og klare for utrulling. **LinkedIn-fakta** (verifisert): det finnes INGEN API for nyhetsbrev/long-form — publisering skjer ved manuell innliming av rik tekst i LinkedIns editor. Men LinkedIn har **native planlegging** (dato + klokkeslett i 15-min-intervaller), så hele utrullingen kan forhåndsplanlegges. Cover-bilde: 1920×1080. En **edition** = én utgave = én kronikk/artikkel + distribusjonspakke (hook-tekst, hashtags, første kommentar, cover).
### 0.4 De 16 prosessfasene (Seres-erfaringen, kondensert)
Dette er den faktiske flyten som ga kvalitet i Seres-produksjonen. Den nye nyhetsbrev-kommandoen (§5) er en kondensering av denne. Kilde: `…/svv/memory/project_kronikk_produksjonsprosess.md`.
1. **Kalibrerings-intervju** — tid/målgruppe/mål; ~3 spørsmål før skriving.
2. **Front-loadet kontekst** — brief + research + sitatbank lest FØR skriving (suksessfaktor).
3. **Research + verifiseringsplikt** — hver påstand mot primærkilde.
4. **Serie-overgripende regler** etableres (stil/term/tone-låser).
5. **Utkast** via Opus-subagent — én artikkel om gangen, med leserekkefølge-kontekst.
6. **Kritisk-leser-simulering** — «fortjener dette publisering?» → konkret kritikk, ikke skryt.
7. **Gap-tabell + gap-lukking** — hvert gap lukkes med *tightening/bytte, ikke utvidelse*; lengde flat.
8. **Annoterings-loop** — render annoterbar review-HTML (verktøyet `build-html.mjs`, 0.6), marker → kommenter → eksporter.
9. **Konsistens-pass** — tråder, pronomen-ordning, kryss-referanser, tall, dramaturgi.
10. **Kvalitets-sweep** — ett klart leder-poeng + én konkret handling per tekst; premiss→konklusjon-bue (0.5).
11. **Faktasjekk-sweep** — EGET steg; parallelle agenter; alle påstander «skyldig til motbevist» (0.5).
12. **Lesbarhets-/formaterings-sweep** — MINIMALT (0.5, formaterings-dose).
13. **Persona-/audience-sweep** — leser-jury tester om teksten LANDER (0.5).
14. **Verifiserings-loop** — kjør personaene PÅ NYTT mot oppdatert tekst til rent JA (0.5, konvergens-loop).
15. **LÅS → leveranse** — POST.html (0.5) og/eller avis-PDF.
16. **Distribusjons-/hook-gate** — konverterings-gate på distribusjonsteksten, ETTER lås (0.5).
**Den enkeltstående største prosessfeilen i Seres:** persona-sweepen (fase 13) ble opprinnelig kjørt ETTER at tekstene var låst (fase 15), noe som tvang gjenåpning av låste tekster. Den generaliserte malen MÅ derfor ha persona-sweep FØR lås. (Dette er grunnen til rekkefølgen i prinsipp 5, §3.)
Nøkkelfiler i svv-memory for dypere kontekst: `project_kronikk_produksjonsprosess.md` (fasene + Voyage-mapping), `project_kronikk_faktasjekk_sweep.md`, `feedback_persona_audience_sweep.md`, `feedback_hook_post_persona_gate.md`, `feedback_post_html_single_sheet.md`, `project_maskinrommet_newsletter.md`.
### 0.5 Ordliste (begreper brukt senere)
- **Edition** — én utgave av nyhetsbrevet (0.3).
- **Faktasjekk-sweep** — eget steg der hver faktapåstand (tall, navngitte eksempler, sitater, datoer, hvem-gjorde-hva) verifiseres mot primærkilde, etter prinsippet «**skyldig til motbevist**» (antas feil til den er verifisert; aldri fyll hull med gjetninger). I Seres ble ~15 feil fanget.
- **«Altinn-feilen»** — det konkrete funnet som beviste at faktasjekk må være et eget steg: i et utkast ble Altinn brukt som eksempel på «bygd i eget hus / internt eierskap», men Accenture var i realiteten hovedleverandør — altså nær et mot-eksempel. Verken research-filene eller en subagents resonnement fanget det; operatørens egen hukommelse gjorde. Lærdom: vær kritisk til ALT, også det som «føles» riktig og det som står i egne research-notater.
- **Persona-/audience-sweep** — en adversariell **leser-jury**: navngitte leser-personaer (definert fra målgruppen) leser den ferdige teksten *read-only* og dømmer om den LANDER (ikke om den er «riktig»). Personaene skriver ALDRI tekst — de gir retning; redaktøren (hovedkonteksten) holder pennen. Dette er kronikk-ekvivalenten til Voyages adversarielle kode-reviewere.
- **«Primær trumfer»** — én persona er utpekt som primærleser. Ved konflikt mellom personaer vekter primær høyest. En *sekundær*-NEI på grunn av rolle-mismatch eller ekspertise-tak («dette vet jeg alt om fra før») er et SIGNAL om at gaten virker, ikke en svikt — godta den, ikke forvreng primærteksten for å jage den. En *primær*-NEI godtas derimot ikke.
- **Konvergens-loop (LØST / DELVIS / IKKE)** — etter at jury-flagg er foldet inn i teksten, kjøres personaene PÅ NYTT for å bekrefte at endringene faktisk landet (ikke bare at teksten ble endret). Hvert tidligere flagg dømmes LØST / DELVIS LØST / IKKE LØST, til rent JA fra primær. I Seres tok dette 2 runder.
- **Hook-/konverterings-gate** — en EGEN persona-gate, men på **distribusjonsteksten** (feed-hooken / «Tell your network»-teksten), spisset for konvertering: binær JA/NEI på «ville DU klikket videre?» — ikke «er den god». Kjøres ETTER lås (teksten bak er ferdig). **«Hold tilbake leveransen, ikke konklusjonen»**: en hook som gir bort tallet/caset/listen/grepet i feeden får ros, men ingen klikk; hold igjen beviset og la et åpent spørsmål peke inn i artikkelen. Konklusjonen kan stå.
- **POST.html «alt på ett sted»** — ett selvforsynt publiseringsark per edition, generert av `build-linkedin.mjs` (0.6). Inneholder i publiseringsrekkefølge: dato + klokkeslett (+ ev. ferskvare-banner), tittel/SEO, cover-filnavn + credit + caption, delingstekst inkl. hashtags, første kommentar, ev. carousel-referanse, og brødteksten som rik tekst klar til innliming. Formålet: legg inn én edition i én operasjon uten å hoppe mellom filer.
- **Ferskvare-flagg** — markering i POST.html av tids-sensitive tall (f.eks. en selskaps-verdsettelse) som MÅ re-verifiseres på publiseringsdagen. En publiseringsdag-sjekkliste, ikke en tekstsvakhet.
- **voice-profil / voice-samples** — operatørens skrivestemme. Lagret i `config/user-profile.local.md` + `assets/voice-samples/` i pluginen. **Leses ALLTID før innholdsproduksjon** (eksisterende LTL-regel).
- **Relevans-/rangeringsmodell** — LinkedIns 2026 relevans-/rangeringsmodell (modellnavn og oppdateringsdato ikke publiserbart som faktum; se `references/algorithm-signals-reference.md`). LTL optimaliserer innhold mot dens signaler.
- **5x5x5** — eksisterende LTL-engasjementstaktikk (kommenter/engasjer i et mønster rundt egen post). Ikke relevant for langform.
- **CEA** — kommenteringsmetode i `comment-strategist`-agenten. Ikke relevant for langform.
- **PreToolUse-gate / content-gatekeeper / voice-guardian** — eksisterende LTL-hooks som gir rådgivende kvalitets-/stemme-advarsler når kortform-innhold skrives. Kalibrert for feed-poster.
### 0.6 Render-skriptene (i `maskinrommet/tools/`, flyttes til pluginen i S1)
Fire zero-/lav-avhengighets Node-skript. Felles invariant: kjøres ALLTID med `cwd` = serie-mappa (output skrives relativt til `process.cwd()`); fonts lastes via skriptets `__dirname`. Kontrakt:
| Skript | Kall | Output | Avhengighet |
|--------|------|--------|-------------|
| `build-html.mjs` | `node …/build-html.mjs utkast/NN-*.md` | `review/NN-*.html` — selvstendig annoterbar HTML (marker → intent → kommentar → localStorage → eksport). **Dette er annoteringsverktøyet** (beslutning H, §7.5). | Zero-dep |
| `build-linkedin.mjs` | `node …/build-linkedin.mjs utkast/0*.md` | `linkedin/NN/POST.html` + `linkedin/samle/POST.html` (0.5). Leser også `linkedin/edition-delingstekst.md`. **NB: har i dag hardkodet Seres-kalender/captions/ferskvare** — generaliseres i S2. | Zero-dep |
| `build-carousel.mjs` | `node …/build-carousel.mjs linkedin/NN/carousel.md` | `carousel.pdf` (1080×1350) | Krever `weasyprint` på PATH |
| `build-pdf.mjs` | `node …/build-pdf.mjs utkast/NN-*.md` | `pdf/NN-*.pdf` (avis-A4) | Krever `weasyprint` på PATH |
### 0.7 «Auditen» (gjennomført i sesjon S0, frosset inn i §4)
Før denne planen ble alle 27 kommandoene og 16 agentene i LTL lest og vurdert for overlapp, redundans og langform-relevans (sesjon S0, 2026-05-26). Konklusjonene er **frosset inn i §4 og §6** — en ny sesjon skal stole på dem og trenger IKKE kjøre auditen på nytt. Vil du verifisere ett enkelt konsoliderings-grep, les den aktuelle kommando-/agent-fila direkte (alle ligger i `commands/` og `agents/` i pluginen).
---
## 1. Sammendrag
LTL skal eie **hele kjeden for ALT LinkedIn-innhold** — fra kortform-post til nyhetsbrev-edition (0.3) — med samme kvalitetsnivå som Seres-erfaringen (0.2) viste er mulig. Pluginens svakeste område i dag er langform/nyhetsbrev: det finnes kun som referansestoff (`references/newsletter-strategy-guide.md`) og en nedstrøms-adaptasjonssnutt i `commands/multiplatform.md`, ikke som en førsteklasses idé→leveranse-flyt.
**Kjerneinnsikten fra auditen (0.7):** Vi kan legge til full langform-kapabilitet **og gjøre pluginen enklere samtidig**. Langform krever +1 kommando og +2 agenter, men auditen avdekket nok reell redundans til at vi netto **reduserer** overflaten gjennom konsolidering (§4). Resultatet: en plugin med færre, klarere kommandoer/agenter — pluss en ny tung kapabilitet.
**Den nye kapabiliteten** løfter mønstrene fra Voyage-pluginen (0.1) — faset pipeline, parallelle research-agenter, adversariell review, multi-sesjon — inn i LTL uten å kopiere Voyages kode. Leser-personaer (0.5) erstatter Voyages kode-reviewere; faktasjekk (0.5) blir et eget steg; persona-sweep kjøres FØR lås (0.4).
---
## 2. Beslutninger landet
Alle åpne beslutninger fra briefen (§8 der) pluss tre som dukket opp under planlegging. Disse er LÅST — en ny sesjon endrer dem ikke uten eksplisitt instruks fra operatøren.
| # | Beslutning | Valg | Kilde |
|---|-----------|------|-------|
| **A** | Kommando-struktur | **Én ny orkestrator-kommando** `/linkedin:newsletter` med interne faser + multi-sesjons-resumption. IKKE en suite med fem fase-kommandoer. IKKE en utvidelse av `commands/pipeline.md` (feil artefakt-kontrakt: pipeline er låst til feed-post-format). | Audit (0.7) + operatør |
| **B** | Agent-deling | **Bare langform nå.** De eksisterende kortform-kommandoene røres ikke. Å dele de nye agentene inn i kortform på «variabel intensitet» utsettes til et eget, senere spor. | Operatør |
| **C** | Render-eierskap | **Ship alle 4 render-skript (0.6) + fonts i pluginen** (under `render/`). Generaliser `build-linkedin.mjs`. maskinrommet blir konsument. Da får alle som laster ned LTL fra Forgejo hele produksjons-pipelinen. | Operatør |
| **D** | Persona-sett | **Hybrid:** et gjenbrukbart persona-bibliotek i `config/`, der relevante personaer velges og justeres per prosjekt; primær (0.5) merkes per prosjekt. | Operatør |
| **E** | Faktasjekk-omfang | **Eget steg** (ikke integrert i research eller review). «Altinn-feilen» (0.5) beviste at research-notatene bommer; faktasjekk må være en dedikert sweep. | Seres-erfaring (0.2) |
| **F** | Renovering | **Konsolider redundans i samme runde** som langform bygges, slik at netto kommando-/agent-antall går NED (§4). | Audit (0.7) + operatør |
| **G** | Produksjons-state | Edition-state/HANDOVER for en pågående nyhetsbrev-produksjon bor i **serie-mappa** (i maskinrommet), ikke i pluginens state-fil. Pluginen er en stateless motor; editions registreres i plugin-state KUN for kalender/scheduling. | Arkitektur (separasjon) |
| **H** | Annoterings-renderer | `build-html.mjs` (0.6) generaliseres til en **førsteklasses plugin-kapabilitet for ALLE artefakter** (plan/brief/post/edition), ikke bare kronikker: tabeller, alle overskriftsnivåer, inline-kode, generisk frontmatter. Reference-impl ble produsert i sesjon S0b (§7.5). | Operatør |
---
## 3. Arkitektur-prinsipper
1. **Pluginen er motoren, maskinrommet er arbeidsbenken.** Innhold + produksjons-state for en serie bor i `/Users/ktg/repos/maskinrommet/serier/<slug>/` (0.1). Pluginen (0.1) leverer kommandoen, agentene, persona-biblioteket og render-skriptene. Ett unntak fra den tidligere modellen: render-skriptene flyttes INN i pluginen (beslutning C), men kjøres alltid med `cwd` = serie-mappa (0.6).
2. **Gjenbruk mønstre, ikke kode.** Kopier *formen* på det som finnes: LTL-kommando-malen (YAML-frontmatter + nummererte `Step 0..N` + en `## Reference Files`-seksjon — se f.eks. `commands/pipeline.md`), agent-frontmatter-stilen (se f.eks. `agents/differentiation-checker.md`), hook-kompileringen (`hooks/hooks.template.json` + `hooks/prompts/*.md` + `python3 hooks/scripts/compile-hooks.py`), og det deterministiske state-mønsteret (`hooks/scripts/state-updater.mjs` + `queue-manager.mjs`). Fra Voyage-pluginen (0.1) løftes pipeline-*mønsteret* — ikke koden.
3. **Langform-kvalitet håndheves av pipeline-fasene, ikke av PreToolUse-gaten.** De eksisterende kortform-hookene (content-gatekeeper / voice-guardian, 0.5) er kalibrert for feed-poster og forblir kortform-only (beslutning B). Langform får sin egen, tyngre review-maskineri: faktasjekk-sweep + persona-sweep + hook-gate (0.5). Langform-utkast trenger derfor IKKE ligge under `assets/drafts/` (der kortform-gatene fyrer) — de bor i serie-mappa i maskinrommet.
4. **All agent-orkestrering skjer i forgrunn fra kommando-laget.** Research-, faktasjekk- og persona-fan-out gjøres via `Task`-kall fra selve kommandoen — ALDRI fra en nestet bakgrunns-agent. (Erfaring: en agent som spawnes i bakgrunn mister tilgang til `Task`/Agent-verktøyet og degraderer stille til gjetning i stedet for å parallellisere.)
5. **Persona-sweep FØR lås.** Dette adresserer den største prosessfeilen i Seres (0.4). Den faste rekkefølgen er: utkast → konsistens → kvalitet → faktasjekk → persona-sweep → fold inn → LÅS → leveranse → hook-gate.
6. **Forenkling er en førsteklasses leveranse**, ikke en bivirkning. Hvert nytt element måles mot om det øker eller senker total kompleksitet i pluginen.
---
## 4. Del 1 — Renovering (konsolidering)
Auditen (0.7) fant reell redundans. Grepene under reduserer overflaten og fjerner konkurrenter til den nye nyhetsbrev-kommandoen. Alle er **korreksjon-i-scope** (slå sammen / deleger eksisterende kapabilitet) — ingen ny funksjonalitet. Stol på funnene; vil du etterprøve ett grep, les de navngitte filene i `commands/` eller `agents/`.
### 4.1 Kommando-konsolidering (27 → ~23)
| Grep | Kommandoer (filer i `commands/`) | Begrunnelse | Risiko |
|------|-----------|-------------|--------|
| **SLÅ SAMMEN** | `templates.md` → en modus i `quick.md` | Begge bygger på de samme 8 posttypene, samme hooks-bank og samme tegnmål. Klareste redundansen i katalogen. | Lav |
| **SLÅ SAMMEN** | `publish.md` → en handling i `calendar.md` | Begge leser samme kø (`queue.json`), viser overlappende lister; `calendar` ruter allerede til `publish`. | Lav |
| **SLÅ SAMMEN** | `collab.md` + `speaking.md` → ny `outreach.md` | Strukturell tvilling: samme outreach-/pitch-paradigme og samme pipeline-tabell. Fjerner ~2530 KB duplisert tekst. | Middels |
| **ABSORBER** | `authority.md` → en seksjon i `strategy.md` | `authority` har ingen unik kjerne; den er sammensatt av biter fra strategy/audit/profile/multiplatform. | Lav |
| **DEDUPLISER** | «trajectory»-logikk → bo kun i `strategy.md`; `audit.md` refererer dit | Identisk STATUS-tabell vedlikeholdes i dag to steder. | Lav |
| **KANON** | `profile.md` blir kanonkilde for profil-alignment; `audit.md`/`analyze.md` peker dit | Samme profil-sjekk er re-implementert 4 steder. | Lav |
| **TRIM** | analyse-delen (Step 6) i `import.md` → deleger til `report.md` | To rapport-generatorer kjører samme `trends`-CLI. | Lav |
| **RECONCILE** | Flytt newsletter/blog-stien UT av `multiplatform.md` | Unngå to inngangsdører til langform når `/linkedin:newsletter` finnes. **Må skje sammen med Del 2 (S11).** | Middels |
| **GATE** | I routeren `linkedin.md`: vis `monetize`/`outreach`/`collab` som «låses opp ved ~1K følgere» | Disse er aspirasjonelle for operatørens nåværende nivå (~30 følgere); skjuler kompleksitet uten å slette filer. | Lav |
### 4.2 Agent-konsolidering (16 → ~12, deretter +2 langform = ~14)
| Grep | Agenter (filer i `agents/`) | Resultat |
|------|---------|----------|
| **SLÅ SAMMEN** | `analytics-interpreter` + `performance-reporter` | 1 `analytics`-agent med to moduser (tolk / rapporter). Identiske datakilder. |
| **SLÅ SAMMEN** | `engagement-coach` + `comment-strategist` | 1 `engagement`-agent (5x5x5 + first-hour + CEA-kommentering). |
| **AVVIKLE → script** | `content-tracker` | Ren deterministisk plan-vs-kø-diff; hører hjemme i `calendar`/`state-updater.mjs`, ikke en LLM-agent. |
| **AVVIKLE → script** | `personalization-scorer` | Ren placeholder-deteksjon; `hooks/scripts/personalization-score.mjs` finnes allerede. |
| **VURDER** | `video-scripter``content-repurposer` | Marginal sammenslåing; la stå hvis dybden forsvarer egen fil (avgjøres i S19). |
**Nettoeffekt:** De 2 nye langform-agentene (`fact-checker`, `persona-reviewer`, §6) **finansieres** ved å avvikle de 2 deterministiske agentene. Pluss de to sammenslåingene → fra 16 mot ~14 agenter med klarere ansvarslinjer.
---
## 5. Del 2 — Langform-kapabiliteten (`/linkedin:newsletter`)
Én ny kommando-fil (`commands/newsletter.md`), med interne faser og multi-sesjons-resumption. Følger den eksisterende LTL-kommando-malen (prinsipp 2, §3). Re-kjøring av kommandoen oppdager edition-state (5.2) og fortsetter der forrige økt slapp.
### 5.1 Faser (kondensering av de 16 fasene i 0.4)
| Step | Fase | Hva | Agenter/verktøy |
|------|------|-----|-----------------|
| 0 | **Load context** | Les edition-state/HANDOVER (5.2) for resumption, voice-profil (0.5), persona-bibliotek (6.1), serie-brief | Read |
| 1 | **Brief + kalibrering** | Vinkel, stemme, målgruppe-personaer (merk primær, 0.5), nøkkelpoeng, tone, leder-takeaway. Maks ~3 kalibrerings-spørsmål | AskUserQuestion |
| 2 | **Research** | Parallelle, avgrensede mandater → verifiserte notater. Triangulering | **Task-fan-out** i forgrunn (prinsipp 4, §3) |
| 3 | **Utkast** | Dramaturgisk rekkefølge, voice-matchet. Kan spenne flere sesjoner med vedlikeholdt HANDOVER | `content-repurposer` (utvidet) + Task |
| 4 | **Konsistens + kvalitet** | Tråder, premiss→konklusjon-bue, leder-takeaway, AI-slop-fjerning, formaterings-dose (alt i §8) | inline + `references/longform-quality-rules.md` |
| 5 | **Faktasjekk-sweep** | Risikosortert (🔴/🟡/🟢), «skyldig til motbevist», verifiseringslogg (0.5) | **`fact-checker`** (ny, parallell — 6.2) |
| 6 | **Persona-sweep — FØR lås** | Leser-jury, primær trumfer, konvergens-loop til rent JA (0.5) | **`persona-reviewer`** (ny, kjøres én gang per persona — 6.3) |
| 7 | **Annotering (valgfritt)** | Render annoterbar review-HTML for et manuelt pass | `render/build-html.mjs` (§7.5) |
| 8 | **LÅS → leveranse** | POST.html «alt på ett sted» (0.5) | `render/build-linkedin.mjs` (0.6) |
| 9 | **Hook-/konverterings-gate** | Persona-gate på distribusjonsteksten: «ville DU klikket?» — etter lås (0.5) | **`persona-reviewer`** i konverterings-modus (6.3) |
| 10 | **Planlegging** | Registrer edition i pluginens kø/state for native scheduling (0.3) | `hooks/scripts/queue-manager.mjs` |
### 5.2 Edition-state / HANDOVER (beslutning G)
Produksjons-state for en pågående edition bor i serie-mappa (`/Users/ktg/repos/maskinrommet/serier/<slug>/`), ikke i pluginen. Følger HANDOVER-mønsteret fra Seres (referansefil: `/Users/ktg/repos/maskinrommet/serier/silvija-seres-motsvar/HANDOVER.md`):
- **§1 Hvor vi er nå** — status + låst artikkel-tabell
- **§2 Publiseringskalender** — datoer
- **§3 Leveransen** — POST.html-kontrakt + filkart over serie-mappa
- **§4 Ufravikelige regler** — stil-/fakta-låser + faktasjekk-logg
- **§5 Metode** — persona-kalibrering, gjenbrukbar prosess
- **§6 Neste sesjon** — peker på neste handling
Kommandoen leser denne i Step 0 og oppdaterer den ved hver fase-overgang. Et lett `edition-state.json` (gjeldende fase + per-artikkel-status) kan komplettere for deterministisk resumption.
**Merk skillet mellom to HANDOVER-er:** (a) `docs/BUILD-HANDOVER.local.md` i pluginen styrer *byggingen av selve pluginen* (§9.2); (b) edition-HANDOVER i serie-mappa styrer *produksjonen av en nyhetsbrev-utgave*. De er ikke samme fil og blandes ikke.
### 5.3 Skill-plassering
Ingen ny skill opprettes. Langform legges som trigger/innhold i den eksisterende skillen `skills/linkedin-content-creation/SKILL.md` (som allerede dekker post/quick/batch/pipeline/templates/multiplatform).
---
## 6. Del 3 — Delte byggeklosser
### 6.1 Persona-bibliotek (beslutning D — hybrid)
- **`config/personas.template.md`** (+ en aktiv `config/personas.local.md`, gitignored via `*.local.md`): gjenbrukbare leser-profiler. Frø-personaene fra Seres (0.2): IT-divisjonsdirektør, KI-seksjonsleder, og linjeleder (primær).
- Per persona dokumenteres: rolle, hva som kobler dem av, hva som overbeviser dem, ekspertise-nivå, sjargong-toleranse.
- **Per-prosjekt-override:** `/linkedin:newsletter` velger relevante personaer fra biblioteket i Step 1 og merker primær i edition-briefen. (Om «primær trumfer», sekundær-NEI som signal osv., se 0.5.)
### 6.2 `fact-checker`-agent (ny — `agents/fact-checker.md`)
- **Modell:** Opus (verifiserings-resonnering; tillit-kritisk). **Tools:** `Read`, `WebSearch`.
- **Mandat:** Gitt en bolk faktapåstander → verifiser hver mot primær-/troverdig kilde, etter «skyldig til motbevist» (0.5). Aldri fyll hull med gjetninger — flagg uverifisert eksplisitt. Returner en verifiseringslogg + risikosortering 🔴/🟡/🟢.
- **Orkestrering:** `/linkedin:newsletter` (Step 5) lister alle påstander og fan-outer N parallelle `fact-checker`-kall (én per bolk) i forgrunn (prinsipp 4, §3), og samler loggene.
- **Prompt-arketype:** kopier gate-strukturen fra `agents/differentiation-checker.md` (søk → vurder → gate-utfall; «søk før du dømmer» er ikke-forhandlbart) — men endre mandatet fra *originalitet* til *faktuell korrekthet*. (Bygg en ny fil; ikke utvid differentiation-checker — de to svarer på ortogonale spørsmål.)
### 6.3 `persona-reviewer`-agent (ny, parameterisert — `agents/persona-reviewer.md`)
- **Modell:** Opus (nyansert leser-simulering). **Tools:** `Read`.
- **Mandat:** Les én persona-definisjon (fra 6.1) + teksten → døm på 6 akser: (1) holder hooken? (2) resonans — angår dette MEG? (3) tone — respektert vs. belært? (4) troverdighet — avvist som hype? (5) leder-takeaway + konkret handling? (6) lengde/driv? Returner topp-5 flagg med **retning, ikke ferdig omskriving**. Juryen skriver ALDRI tekst (0.5).
- **To moduser i SAMME agent-fil** (parameter i kallet):
- **Resonans-modus** (Step 6, FØR lås): «lander poenget for denne leseren?»
- **Konverterings-modus** (Step 9, etter lås): binær JA/NEI på «ville DU klikket?» — kun på hook/distribusjonsteksten, ikke artikkelen bak (0.5).
- **Konvergens-loop** (0.5): kommandoen kjører agenten på nytt mot oppdatert tekst og lar hver persona dømme LØST/DELVIS/IKKE per tidligere flagg, til rent JA fra primær.
### 6.4 Research-fan-out (ingen ny agent)
`/linkedin:newsletter` (Step 2) spawner parallelle `Task`-kall med inline-mandater (ett per delspørsmål), samler og triangulerer i forgrunn (prinsipp 4, §3). Ingen egen research-agent opprettes. Gjenbruk URL-fetch/multi-kilde-syntese-disiplinen som allerede finnes i `commands/react.md` der det er relevant.
---
## 7. Del 4 — Render-migrering (beslutning C)
### 7.1 Flytt render inn i pluginen
- Opprett mappen `render/` i pluginen og legg inn alle 4 skriptene (0.6) + `fonts/` + en `OFL.txt` (fontene Inter/JetBrains Mono/Source Serif 4/Newsreader er OFL-lisensierte og kan redistribueres — `shared/playground-design-system` i marketplace-en self-hoster allerede tre av dem, så praksisen er etablert).
- **cwd-modellen bevares:** kommandoen kjører `node ${CLAUDE_PLUGIN_ROOT}/render/build-linkedin.mjs <input>` med `cwd` = serie-mappa. Output følger `cwd`, fonts følger `__dirname` (pluginens `render/fonts/`). (`${CLAUDE_PLUGIN_ROOT}` peker til plugin-install-mappa og brukes allerede i eksisterende kommandoer, f.eks. for `clipboard-helper.mjs`.)
### 7.2 Generaliser `build-linkedin.mjs`
Skriptet har i dag hardkodet Seres-spesifikk kalender, captions og ferskvare-flagg. Generaliser det til å lese en **edition-config** (f.eks. `linkedin/edition-config.json` i serie-mappa) for disse verdiene. Endringen gjøres i pluginen (skriptet bor nå der); maskinrommet leverer config-fila per serie.
### 7.3 maskinrommet blir konsument
- `maskinrommet/tools/`-kopiene fjernes; maskinrommet kaller pluginens render-skript i stedet.
- **Dette er et eget arbeidsspor i maskinrommet-repoet** (`/Users/ktg/repos/maskinrommet/` — et ANNET repo, 0.1) og krever eksplisitt instruks fra operatøren når vi kommer dit. Planen beskriver det; selve utførelsen der gjøres separat. Pluginen fungerer uansett alene.
### 7.4 Graceful degradation (weasyprint)
- `build-html` + `build-linkedin` er zero-dep og virker alltid.
- `build-pdf` + `build-carousel` krever `weasyprint` (eksternt Python-verktøy, kan ikke bundles) på PATH → detekter, og gi en tydelig installasjons-instruks hvis det mangler. Pipelinen stopper aldri på manglende weasyprint; den hopper over PDF-stegene med en advarsel.
### 7.5 Annoterings-renderer som førsteklasses kapabilitet (beslutning H)
`build-html.mjs` (0.6) ER annoteringsverktøyet (marker → Endre/Legg til/Fjern/Avklar/Risiko → kommentar → sidepanel → localStorage → eksport av annoterings-markdown). I dag er det kronikk-spesifikt: kun `##`/`###`-overskrifter, ingen tabell-støtte, ingen inline-kode, og frontmatter forutsetter kronikk-felter. Sesjon S0b beviste mangelen — for å annotere *denne planen* (full av tabeller) måtte rendereren utvides.
- **Generaliser** `render/build-html.mjs` til å rendre et hvilket som helst markdown-artefakt: tabeller, alle overskriftsnivåer (`#``####`), inline `` `kode` ``, og generisk frontmatter/tittel. Selve annoterings-motoren (CSS + klient-JS) er allerede artefakt-uavhengig og gjenbrukes ordrett.
- **Bruksområde:** planer, briefer, ferdige poster, nyhetsbrev-editions, carousel-utkast — alt operatøren eller en Forgejo-nedlaster vil ha tilbakemelding på.
- **Reference-implementasjon (S0b):** en engangs-generator som henter motoren ut av `build-html.mjs` ved kjøring og legger til tabell-/overskrift-/kode-parsing. Lå i `/private/tmp/claude-ltl-review/gen.mjs` i den sesjonen (kan være slettet — den er ikke kilden, kun et bevis på at det virker). **Plugin-versjonen skal embedde motoren** (CSS + klient-JS) direkte i `render/build-html.mjs` — ingen runtime-avhengighet til maskinrommet eller til en temp-fil.
- **Integrasjon:** Step 7 i nyhetsbrev-pipelinen (§5.1) kaller denne. Genererte review-filer legges i `docs/review/` (gitignored — annoteringene lever uansett i nettleserens localStorage, ikke i fila).
- **Zero-dep** — virker alltid, ingen weasyprint.
---
## 8. Kvalitetsregler for langform
Disse stammer fra Seres-erfaringen (0.2) og skal kodes inn i `references/longform-quality-rules.md` + i `/linkedin:newsletter` og agentene:
- **Leder-takeaway:** hver tekst skal lande ÉN klar takeaway + én konkret handling. Beskjær referanser hardt; hands-on-troverdighet slår sitat-dynge.
- **Premiss→konklusjon-bue:** etabler ett klart premiss tidlig (ingress + første avsnitt); la avslutningen GRIPE premisset konkret og vri det framover (retning + ett håndfast grep), ikke bare oppsummere.
- **AI-slop-fraser (forbudt):** «her må jeg være ærlig» / «for å være ærlig»; «ikke bare X, men Y»; unødig tre-listing; «i en stadig mer kompleks verden»; påklistrede oppsummeringssetninger.
- **Generell, ikke etat-/person-spesifikk:** ingen personlige etat-anekdoter; presenter muligheter, ikke provokasjoner. Maks én strukturell forankrings-referanse per tekst (ikke gjentatt kritikk av en navngitt person).
- **Formaterings-dose (minimal):** fet = maks ett poeng per bolk; korte lister (24) kun der teksten allerede ramser opp — aldri gjør bærende resonnement til kulepunkter; tabeller sparsomt. «Ingen artikkel skal ligne en PowerPoint-utskrift.»
- **Gap lukkes med tightening/bytte, ikke utvidelse** — bytt svakere mot skarpere, hold lengden flat.
- **Kalibrering per sweep er et brukervalg, ikke default:** før hver faktasjekk-/persona-sweep avklares fold-inn-aggressivitet (konservativ vs. aggressiv), sjargong-håndtering, og persona-vekting ved konflikt.
---
## 9. Fasing og sesjons-dekomponering
### 9.1 Faser
Kritisk sti er langform-kapabiliteten (operatøren har 6 editions i pipen og vil produsere neste serie raskere). Konsolidering som ikke blokkerer langform kommer etterpå.
| Fase | Innhold | Avhengighet | Risiko |
|------|---------|-------------|--------|
| **1 — Fundament** | Render-migrering (§7) + persona-bibliotek (§6.1) + `fact-checker` + `persona-reviewer` (§6.2/§6.3) + edition-state-skjema (§5.2). Finansier agentene ved å avvikle `content-tracker` + `personalization-scorer` (§4.2). | — | Middels |
| **2 — Kapabiliteten** | `commands/newsletter.md` med alle faser (§5) + reconcile av newsletter-stien ut av `multiplatform.md` (§4.1). | Fase 1 | Middels |
| **3 — Dogfood** | Produser en ekte edition gjennom pipelinen. Åpne review-HTML i nettleser og gå gjennom kjerne-flytene. Fang og fiks friksjon FØR release. | Fase 2 | Lav |
| **4 — Renovering** | Resterende kommando-/agent-konsolidering (§4): templates→quick, publish→calendar, collab+speaking→outreach, authority→strategy, analytics/engagement-merge, router-gating. | Uavhengig | Middels |
Fase 4 kan kjøres parallelt med eller etter Fase 23. Hver konsolidering er en egen liten, testbar endring. v2.0.0 markerer fullført Fase 4.
### 9.2 Sesjons-dekomponering
Arbeidet spenner mange sesjoner. Hver sesjon = ÉN sammenhengende, testbar leveranse, holdt **innenfor 35% kontekst** (godt før compact). Én oppgave per sesjon — aldri start neste før HANDOVER (§9.3) er oppdatert. «S0» og «S0b» under er allerede gjort (planlegging); S1 er første bygge-sesjon.
| Sesjon | Fase | Leveranse | Verifisering (se §10) |
|--------|------|-----------|--------------|
| **S1** | 1 | Opprett `render/`; kopier de 4 skriptene + `fonts/` + OFL fra `/Users/ktg/repos/maskinrommet/tools/` INN i pluginen. (Ikke rør maskinrommet.) | Antakelse-test 13 |
| **S1a** | 1 | Generaliser annoterings-rendereren `render/build-html.mjs` (beslutning H): tabeller, `#``####`, inline-kode, generisk artefakt. Embed motoren. | Rendrer denne planen + en post + en brief rent; tabeller intakt |
| **S2** | 1 | Generaliser `render/build-linkedin.mjs` → leser `edition-config.json` (§7.2). | Antakelse-test 5 |
| **S3** | 1 | `config/personas.template.md` + frø-personaene (§6.1). | Fil finnes, 3 personaer, primær merket |
| **S4** | 1 | `agents/fact-checker.md` (§6.2) + test på prøvepåstander. | Returnerer verifiseringslogg + 🔴/🟡/🟢 |
| **S5** | 1 | `agents/persona-reviewer.md` (§6.3, 2 moduser) + test. | Returnerer 6-akse-flagg / JA-NEI |
| **S6** | 1 | Edition-state-skjema (§5.2) + avvikle `content-tracker` + `personalization-scorer` (§4.2). | `ls agents/` ned med 2; funksjon bevart |
| **S7** | 2 | `commands/newsletter.md` skjelett — Step 02 (§5.1). | Antakelse-test 4 (research-fan-out kjører) |
| **S8** | 2 | newsletter.md Step 34 (utkast + konsistens/kvalitet). | Utkast genereres voice-matchet |
| **S9** | 2 | newsletter.md Step 56 (faktasjekk + persona-sweep). | Begge agenter kalles parallelt; sweep FØR lås |
| **S10** | 2 | newsletter.md Step 710 (annotering, lås/leveranse, hook-gate, planlegging). | POST.html produseres; hook-gate etter lås |
| **S11** | 2 | Reconcile newsletter-sti ut av `multiplatform.md` (§4.1) + skill-trigger (§5.3) + router-rad i `linkedin.md`. | Kun ÉN inngang til newsletter |
| **S12** | 2 | `references/longform-quality-rules.md` (§8) + resumption-wiring (Step 0 leser edition-state). | Avbryt/gjenoppta-test |
| **S13** | 3 | Dogfood: produser en ekte edition ende-til-ende; logg friksjon. | Edition i serie-mappa; review-HTML i nettleser |
| **S14** | 3 | Fiks dogfood-friksjon. | Friksjonsliste lukket |
| **S15** | 4 | `templates.md` → modus i `quick.md` (§4.1). | quick dekker begge; templates fjernet |
| **S16** | 4 | `publish.md` → handling i `calendar.md` (§4.1). | calendar dekker publish |
| **S17** | 4 | `collab.md` + `speaking.md` → ny `outreach.md` (§4.1). | outreach dekker begge |
| **S18** | 4 | `authority.md``strategy.md` + trajectory-dedup + `profile.md` kanon (§4.1). | strategy dekker authority |
| **S19** | 4 | Agent-merge: analytics (2→1) + engagement (2→1) (§4.2). | `ls agents/` ned med 2 |
| **S20** | 4 | `import.md`-trim + router-gating (§4.1) + sluttdoc-pass → **v2.0.0**. | `ls commands/` verifisert ned; alle 3 doc-nivåer oppdatert |
Tabellen er veiledende. Hvis en sesjon nærmer seg 35% kontekst før leveransen er ferdig: splitt den, oppdater HANDOVER med delvis status, og la neste sesjon fullføre.
### 9.3 Bygge-protokoll (multi-sesjon)
**Single source of truth:** `docs/BUILD-HANDOVER.local.md` i pluginen (gitignored). Holder: hvor vi er nå, hva forrige sesjon gjorde/verifiserte, NESTE SESJON-oppgaven, ufravikelige regler, og en sesjons-logg. (Forveksles ikke med edition-HANDOVER i serie-mappa, §5.2.)
**Kontekst-budsjett:** Hver sesjon holdes innenfor 35% kontekst (før compact). Nærmer du deg: avslutt rent, ikke start nytt steg.
**Siste handling i HVER sesjon (ufravikelig):** Oppdater `BUILD-HANDOVER.local.md` — status, hva ble gjort og verifisert, og en presis NESTE SESJON-oppgave. Skriv aldri «gå til X» med mindre X eksisterer og er testet.
**Modell:** Opus 4.7 på alt. Ikke degrader til en mindre modell — vent heller på tilgjengelighet.
**Fast resume-kommando** (operatøren limer inn etter hver `/clear`, identisk hver gang):
```
Fortsett byggingen av LTL fullspektrum-innholdsmotor. Les
docs/BUILD-HANDOVER.local.md (single source of truth) og
docs/plan-fullspektrum-innholdsmotor.md. Utfør oppgaven merket
«NESTE SESJON» i HANDOVER, og BARE den. Hold deg innenfor 35%
kontekst. Siste handling: oppdater BUILD-HANDOVER.local.md.
Ikke push uten at jeg ber om det.
```
**Disiplin:** Én oppgave per sesjon. Test før HANDOVER oppdateres. Ikke utvid scope utover NESTE SESJON-oppgaven. Cross-repo-arbeid (maskinrommet, §7.3) krever eksplisitt instruks før utførelse.
---
## 10. Verifisering — hvordan en sesjon vet at den er ferdig
Dette er kjernen i at planen holder uten drift: hver sesjon har en **Definition of Done (DoD)** som er binær og kjørbar, og som sesjonen MÅ evaluere på seg selv før den oppdaterer HANDOVER.
### 10.0 Prinsipp: hva «ferdig» betyr
«Ferdig» = hvert DoD-punkt for sesjonen er objektivt bekreftet. Tre typer punkter, etter hvordan de bekreftes:
- **Deterministisk** — bekreftes med en kommando (filen finnes, `wc -l` stemmer, `node --test` grønt, `grep` gir forventet treff). Claude kjører kommandoen og leser utfallet. Ingen skjønn.
- **Kjent-svar-fixture** — for agenter/skript der output er strukturert: lag FØRST en liten fixture med fasit (jf. husregelen «ingen produksjonskode uten en feilende test først»), kjør, og sammenlign output mot fasit. Claude evaluerer mot fasiten, ikke mot egen magefølelse.
- **Subjektiv kvalitet — SELV-SERTIFISERES ALDRI.** Om en tekst «lander», treffer voice, er original eller prosakvalitet er skjønn. Claude skal ALDRI sette grønn hake på dette selv. Det rutes til én av to:
- en **gate-mekanisme** som produserer et eksplisitt verdikt (f.eks. `persona-reviewer` returnerer rent JA fra primær; `voice-trainer` bekrefter voice-match; `fact-checker` returnerer 0 åpne 🔴), eller
- **operatøren**, via den annoterbare review-HTML-en (§7.5).
- Et DoD-punkt av denne typen merkes `[GATE: <hvem>]` eller `[OPERATØR]` og regnes som uoppfylt til gaten/operatøren har gitt verdikt. En sesjon er ikke ferdig fordi Claude «mener» kvaliteten er god.
Hvis et DoD-punkt ikke kan bekreftes: sesjonen er IKKE ferdig. Skriv den faktiske statusen i HANDOVER (hva som gjenstår), ikke en grønn hake.
### 10.1 Nøkkelantakelser (test umiddelbart i sesjonen som rører dem)
1. **Render kjørbar fra pluginen med riktig cwd.** `cd <serie-mappe> && node <plugin>/render/build-linkedin.mjs utkast/01-*.md``linkedin/01/POST.html` + `linkedin/samle/POST.html` finnes i serie-mappa. *(Deterministisk.)*
2. **Bundlede fonts resolver via `__dirname`.** `build-pdf` produserer PDF med Newsreader/Inter fra plugin-lokasjonen, ikke fallback. *(Deterministisk: inspiser PDF-metadata / visuell sjekk.)*
3. **`${CLAUDE_PLUGIN_ROOT}` eksponert i kommando-Bash.** Et Step som ekko-er stien resolver til plugin-install-mappa. *(Deterministisk.)*
4. **Task-fan-out i forgrunn beholder Task-verktøyet.** Kommandoen spawner 2+ parallelle research-`Task`-kall og får strukturerte svar (ikke degradert). *(Deterministisk: tell parallelle kall + svar.)*
5. **Generalisert `build-linkedin` leser edition-config.** Endre `edition-config.json` → POST.html-output endres uten kode-endring. *(Deterministisk: diff to kjøringer.)*
### 10.2 DoD-arketyper
Hver sesjon arver én arketype + sine egne spesifikke verdier (§10.3).
- **A — Render-flytting (S1):** (a) `ls render/` viser 4 skript + `fonts/` + `OFL.txt`; (b) nøkkelantakelse 13 grønne; (c) zero-dep-skriptene kjører uten `npm install`.
- **B — Skript-generalisering (S1a, S2):** (a) ny `node --test`-fil skrevet FØRST, feiler før endring; (b) etter endring: testen grønn; (c) **regresjon**: en kjent input gir uendret output for det gamle bruksmønsteret (diff = tom).
- **C — Template/config-fil (S3, S6-skjema):** (a) filen finnes; (b) påkrevde felter til stede (`grep`); (c) parser uten feil (`node -e` som leser den).
- **D — Ny agent (S4, S5):** (a) fil finnes med gyldig frontmatter (`model: opus`, `tools`, `description` — sjekk med `grep`/parse); (b) **kjent-svar-fixture skrevet FØRST** (f.eks. 3 påstander: én sann/én falsk/én uverifiserbar → forventet 🟢/🔴/🟡); (c) agent-kjøring mot fixturen matcher fasit-formen og -dommen; (d) `[GATE]` agenten skriver ALDRI om tekst selv (verifiser at output er flagg/retning, ikke ny copy).
- **E — Kommando-steg (S7S10, S12):** (a) steget kjører på en dummy-serie-fixture og produserer det spesifiserte artefaktet (fil finnes / forventet form); (b) resumption der relevant: avbryt → re-kjør → fortsetter fra riktig steg via edition-state (deterministisk); (c) subjektive steg (utkast, persona-sweep) er `[GATE]`/`[OPERATØR]`, ikke selv-sertifisert.
- **F — Konsolidering (S11, S15S20):** (a) **kapabilitets-sjekkliste**: hver enkeltfunksjon i forgjenger-fila er enumerert og verifisert til stede i målet (punkt for punkt); (b) forgjenger-fil fjernet; (c) `ls commands/ | wc -l` / `ls agents/ | wc -l` viser forventet, lavere tall; (d) **ingen daudlenker**: `grep -rn "<gammelt-navn>" commands/ agents/ skills/ hooks/ README.md` gir kun tilsiktede treff; (e) router (`linkedin.md`) oppdatert.
- **G — Dogfood (S13S14):** (a) en ekte edition produsert ende-til-ende (filer i serie-mappa); (b) rekkefølge-bevis: edition-HANDOVER viser persona-sweep FØR lås; (c) friksjon logget i HANDOVER; (d) for S14: hvert lukket friksjonspunkt re-testet med en konkret sjekk, ikke bare «fikset».
### 10.3 DoD per sesjon (konkret)
| Sesjon | Arketype | Spesifikt «suksess ser slik ut» |
|--------|----------|-------------------------------|
| S1 | A | 4 skript + fonts + OFL i `render/`; antakelse 13 grønne |
| S1a | B | `node --test` for tabell/`#``####`/inline-kode grønn; rendrer denne planen med 9 tabeller intakt; gammel kronikk rendrer uendret (regresjon) |
| S2 | B | Test for edition-config-lesing grønn; antakelse 5 (diff to configs); gammel Seres-input gir uendret POST.html om config matcher dagens hardkoding (regresjon) |
| S3 | C | `personas.template.md` finnes; 3 personaer med alle felt (rolle/avkobler/overbeviser/ekspertise/sjargong); primær merket; parser OK |
| S4 | D | `fact-checker.md` + fixture med 3 påstander → output 🟢/🔴/🟡 matcher fasit; flagger uverifiserbar som 🟡 (ikke gjetter) |
| S5 | D | `persona-reviewer.md` + fixture: returnerer ≤5 flagg på 6 akser med retning; INGEN omskrevet copy; begge moduser gir riktig form |
| S6 | C+F | edition-state-skjema parser; `content-tracker`+`personalization-scorer` fjernet; `ls agents/`=14→ (forventet); funksjon dekket av script (kjør scriptet) |
| S7 | E | newsletter.md Step 02 kjører på dummy-serie; antakelse 4 (parallell fan-out) |
| S8 | E | Step 34 produserer utkast-fil; `[OPERATØR]`/`[GATE: voice-trainer]` for voice-match — ikke selv-sertifisert |
| S9 | E | Step 56: `fact-checker` + `persona-reviewer` kalles parallelt; sweep skjer FØR lås (rekkefølge-assert); `[GATE]` rent JA fra primær kreves for å gå videre |
| S10 | E | Step 710: POST.html produsert av render; hook-gate kjører ETTER lås (rekkefølge-assert); edition registrert i kø |
| S11 | F | Newsletter-sti fjernet fra `multiplatform.md` (kun én inngang — `grep`); skill-trigger lagt til; router-rad lagt til |
| S12 | C+E | `longform-quality-rules.md` finnes m/ alle regler i §8; resumption: avbryt etter Step 6 → re-kjør → fortsetter fra Step 7 |
| S13 | G | Ekte edition i serie-mappa; edition-HANDOVER viser sweep-før-lås; review-HTML åpnet; friksjon logget |
| S14 | G | Hvert friksjonspunkt fra S13 re-testet med konkret sjekk; restliste tom eller eksplisitt deferert |
| S15 | F | `quick.md` dekker alle 8 templates-typer (sjekkliste); `templates.md` fjernet; `ls commands/` ned 1; ingen daudlenker |
| S16 | F | `calendar.md` dekker publish-handlingen (sjekkliste); `publish.md` fjernet; ned 1; ingen daudlenker |
| S17 | F | `outreach.md` dekker collab+speaking (sjekkliste m/ hver funksjon); begge forgjengere fjernet; ned 1 netto; ingen daudlenker |
| S18 | F | `strategy.md` dekker authority + trajectory; `audit`/`analyze` peker til `profile` som kanon; `authority.md` fjernet; ingen daudlenker |
| S19 | F | analytics (2→1) + engagement (2→1); `ls agents/` ned 2; hver modus i den slåtte agenten dekker forgjengernes funksjoner (sjekkliste) |
| S20 | F | `import.md` analyse delegert til `report`; router-gating på plass; **v2.0.0** i alle versjons-referanser (`grep`); alle 3 doc-nivåer oppdatert |
### 10.4 Selv-evaluerings-protokoll (kjøres ved hver sesjonsslutt)
1. Hent sesjonens DoD fra §10.3 (+ arketypen i §10.2).
2. Gå gjennom hvert punkt og kjør sjekken. Skriv utfall: ✅ (bekreftet med kommando/fixture), 🔶 (`[GATE]`/`[OPERATØR]` — venter på verdikt), eller ❌ (feilet/ikke gjort).
3. **Ærlighetsregel:** Aldri ✅ på et punkt du ikke faktisk har kjørt. Aldri ✅ på subjektiv kvalitet — den er 🔶 til gate/operatør har dømt.
4. Skriv resultatet i HANDOVER-ens sesjons-logg, og sett NESTE SESJON. Er noe ❌/🔶 som blokkerer: NESTE SESJON er å lukke det, ikke å gå videre.
5. Bare når alle DoD-punkter er ✅ (eller bevisst 🔶-deferert med operatørens viten) regnes sesjonen som ferdig.
### 10.5 Doc-plikt (obligatorisk ved push)
Enhver feature-endring oppdaterer i SAMME commit: plugin-`README.md`, plugin-`CLAUDE.md`, og rot-`README.md` (`/Users/ktg/.claude/plugins/marketplaces/ktg-plugin-marketplace/README.md`).
---
## 11. Risikoer og åpne spørsmål
| # | Risiko / spørsmål | Håndtering |
|---|-------------------|------------|
| R1 | **Cross-repo render-migrering** berører maskinrommet (§7.3, annet repo). | Krev eksplisitt instruks før endring der. Pluginen virker alene uansett. |
| R2 | **weasyprint kan ikke bundles.** | Graceful degradation (§7.4). Zero-dep-skriptene dekker kjerne-leveransen (POST.html). |
| R3 | **Font-vekt** øker plugin-størrelsen. | Verifiser total størrelse i S1; OFL-lisens vedlegges. Akseptabelt for kapabiliteten. |
| R4 | **Konsolidering kan bryte eksisterende arbeidsflyt** (sammenslåtte kommandoer). | Hver merge er egen testbar endring med kapabilitets-sjekkliste; router oppdateres. |
| R5 | **Opus-kostnad** ved mange parallelle fact-checker/persona-kall. | Forventet og akseptert (operatørens preferanse: Opus på alt; tillit-kritisk arbeid). Eskalér til operatør hvis volumet blir et problem. |
| Q1 | `edition-config.json` som JSON eller frontmatter-md? | Avklares i S2 (JSON anbefales for deterministisk parsing). |
| Q2 | Skal `video-scripter` absorberes i `content-repurposer`? | Marginal; avgjøres i S19 etter nærlesning. |
| Q3 | Konsolidering av de eksisterende kommandoene utover §4 (større refaktor)? | Utenfor denne planens scope. Noteres som mulig fremtidig spor. |
---
## 12. Filmanifest
Alle stier relativt til pluginen `/Users/ktg/.claude/plugins/marketplaces/ktg-plugin-marketplace/plugins/linkedin-studio/` med mindre annet er angitt.
**Nye filer:**
- `commands/newsletter.md` — orkestrator-kommandoen (§5)
- `commands/outreach.md` — fra sammenslåing av collab + speaking (§4.1)
- `agents/fact-checker.md` — ny agent, Opus (§6.2)
- `agents/persona-reviewer.md` — ny agent, Opus, 2 moduser (§6.3)
- `config/personas.template.md` — persona-bibliotek (§6.1)
- `render/build-linkedin.mjs`, `render/build-carousel.mjs`, `render/build-html.mjs`, `render/build-pdf.mjs` — flyttet fra maskinrommet (§7); `build-linkedin` generalisert (§7.2); `build-html` generalisert til artefakt-annoterings-renderer (§7.5)
- `render/fonts/` + `render/OFL.txt`
- `references/longform-quality-rules.md` — kodede kvalitetsregler (§8)
**Endrede filer:**
- `commands/linkedin.md` (router) — ny rad for newsletter + nivå-gating av aspirasjonelle kommandoer (§4.1)
- `commands/quick.md`, `calendar.md`, `strategy.md`, `import.md`, `multiplatform.md`, `profile.md`, `audit.md`, `analyze.md` — konsolidering (§4.1)
- `agents/analytics-interpreter.md` (+ avvikle `performance-reporter`), `agents/engagement-coach.md` (+ avvikle `comment-strategist`) — sammenslåing (§4.2)
- `skills/linkedin-content-creation/SKILL.md` — langform-trigger (§5.3)
- `hooks/hooks.template.json` + kjør `python3 hooks/scripts/compile-hooks.py` — ev. SessionStart-resumption for editions
- `.gitignore``docs/review/` lagt til (genererte annoterings-artefakter) ✓ gjort i S0b
- `README.md`, `CLAUDE.md` (plugin) + rot-`README.md` — doc-plikt ved hver push
**Fjernede filer (konsolidering, §4):**
- `agents/content-tracker.md`, `agents/personalization-scorer.md` (→ deterministisk script)
- `agents/performance-reporter.md`, `agents/comment-strategist.md` (slått inn i analytics/engagement)
- `commands/templates.md`, `commands/publish.md`, `commands/authority.md` (slått inn i quick/calendar/strategy)
- `commands/collab.md`, `commands/speaking.md` (→ `commands/outreach.md`)
**Cross-repo (eget spor i `/Users/ktg/repos/maskinrommet/`, krever eksplisitt instruks — §7.3):**
- `maskinrommet/tools/` — kopiene fjernes; maskinrommet kaller pluginens render
- `maskinrommet/serier/<slug>/linkedin/edition-config.json` — ny per-serie config