linkedin-studio/scripts/contract-gate/README.md
Kjell Tore Guttormsen ff3467de79 feat(linkedin-studio): accumulation binding — ratify + §E foldIns (fix #1 slice 2)
Slice 2 av fix #1 («rettelser fester seg»): binder rules.ts til den menneskelige
sannhetskilden (skrivekontrakt §E), så en korreksjon gjort én gang håndheves for
alltid i stedet for å gjenoppdages hver utgave (diagnose-gap 2).

- ratify.ts: importerer RULES direkte (ingen skjør tekst-parsing), krever en
  bijeksjon mot §E gate-bindings-manifestet (id ↔ ref ↔ severity) + dangling-
  §-anker-sjekk. CLI: `--ratify [kontrakt]` / `npm run ratify`. Sti: arg > env
  MASKINROMMET_CONTRACT > default (relativt til modulen).
- edition-state.template: foldIns[] fangst-kø (per-artikkel proveniens,
  pending|promoted|rejected, mekanisk→rules.ts / dømmekraft→§C2).
- 12 nye tester (33 totalt), tsc rent. Live-kontrakt-integrasjonstest ratify-er
  det ekte §E-manifestet rent (10 regler bundet 1:1).

Companion: skrivekontrakt §E (JA-promoter-prosedyre + manifest) i maskinrommet.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 17:48:20 +02:00

104 lines
5.3 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.

# Contract-gate — §B/§C1 mekanisk binding-gate
Deterministisk gate som håndhever den **mekaniske** halvdelen av Maskinrommet-skrivekontrakten
(`maskinrommet/docs/skrivekontrakt.md`: §B de ti reglene, §C1 regelsjekk-gaten, §C2 prosa-håndverk)
**før et utkast leveres til operatøren** — så de samme mekaniske korreksjonene aldri når KTG to ganger.
Dette er fix #1 (§C2 bindende + akkumulerende). **Slice 1** = denne gaten: den binder *utkast* til
reglene — bevisst _bindende_, ren string/regex-evaluering, ingen AI, ingen nettverk, så den ikke kan
hoppes over eller snakkes rundt, og kjører på millisekunder. **Slice 2** = `ratify` + §E: den binder
*reglene* (`rules.ts`) til den menneskelige sannhetskilden (kontrakten). Se [Akkumulering](#akkumulering-slice-2).
## Hva gaten gjør (og ikke gjør)
Tre-nivå-modellen fra diagnosen — denne gaten er **nivå 1**:
| Nivå | Hva | Hvem | Hvor |
|------|-----|------|------|
| **1 — rent mekanisk** | §B/§C1-grep + tellinger | **denne gaten** (BLOCK/WARN) | her |
| 2 — AI-mekanisk | §C1 pkt 1/8/9 | `voice-scrubber` (fikser før handoff) | Step 4 |
| 3 — ekte dømmekraft | §C2 narrativ-arkitektur | `editorial-reviewer` (flagg til KTG) | Step 5.5 |
**Klassifiseringsprinsipp:** BLOCK bare det gaten kan _bevise_ med ~null false positives.
Alt som krever dom → WARN (blokkerer ikke). Ekte dømmekraft / ekstern data er ikke her i det
hele tatt (blir hos nivå 2/3).
### Regler (seed)
| Regel | Ref | Severity |
|-------|-----|----------|
| Modell-stråmann (4 eksakte fraser) | §B-3 | **BLOCK** |
| Serie-tese «er ikke modellen» | §B-10 | **BLOCK** |
| `_understrek_`-emfase | §C1 | **BLOCK** |
| Metafor-ord (tak/lodd/reise/landskap) | §B-2 | WARN |
| Bar «modell» (alle treff) | §B-3 | WARN |
| «KI-en» som subjekt (>3×) | hygiene | WARN |
| PS-blokk | §B-9 | WARN |
| Tankestrek-tetthet (>1/50 ord) | §C2 | WARN |
| Versal-tic (emfase-ord, ikke akronymer) | §C2 | WARN |
| AI-tells (navngitte fraser) | §B-8 | WARN |
Reglene er **data** (`src/rules.ts`), ikke hardkodet logikk — det er det som gjør
akkumuleringen (slice 2) ren: en ny regel = én rad i `skrivekontrakt.md` + én post her.
### Bevisst utsatt (dokumenterte gap, ikke stille utelatelser)
- **§C2 «postulerte tall»** (tall uten hedge/kilde) — krever hedge-nærhet-heuristikk med
ikke-triviell false-positive-risiko.
- **§C2 «ordrette gjentakelser»** (n-gram gjentatt >2×) — krever n-gram-analyse; kontraktens
navngitte fraser er utgave-spesifikke.
Begge hører hjemme i en senere slice når heuristikken kan gjøres tillitsverdig.
## Kjøre
```bash
cd scripts/contract-gate
npm install # engangs (tsx + typescript)
node --import tsx src/cli.ts <utkast.md> # kvittering + exit 0/1
node --import tsx src/cli.ts <utkast.md> --json # maskinlesbart
npm run ratify # slice 2: rules.ts ↔ §E-manifest i sync?
npm test # 33 tester (gate + ratify)
```
Exit: `0` = passert (ingen BLOCK, handoff tillatt), `1` = blokkert, `2` = bruksfeil.
WARN feiler aldri gaten — de surfaces for KTGs dom.
## Validering (6 ekte utgaver, juni 2026)
- **0 BLOCK** på publiserte Del 25 → false-blokkerer ikke ekte arbeid.
- **Del 6 (WIP):** fanget et ekte Regel-10-brudd («Den knappe ressursen er ikke modellen» i
brødteksten) automatisk — slog-drepingen i praksis.
- **Del 1:** blokkerer på samme frase, men ble publisert **før** Regel 10 ble kodifisert (01.06) —
historisk artefakt, ikke gate-feil.
- Versal-tic-redesignet (denylist av emfase-ord, ikke allowlist av akronymer) fjernet
NAV/DFØ/NPM-false-positivene som ekte data avslørte.
## Akkumulering (slice 2)
Slice 1 binder *utkast* til reglene. Slice 2 binder *reglene* til kontrakten — så «rettelser fester
seg» blir mekanisk, ikke håpet-på. Diagnosens gap 2 («rettelser fester seg ikke») lukkes ved at hver
korreksjon KTG gjør får et varig, håndhevet hjem.
**Ruta** (full prosedyre i `maskinrommet/docs/skrivekontrakt.md` §E):
1. **Fang** korreksjonen i utgave-staten (`articles.NN.foldIns[]`) — ingenting mistes.
2. **Klassifiser:** mekanisk (eksakt frase / ord / markdown / telling) → `rules.ts`-regel + §B/§C1/§C2-rad;
dømmekraft → kun §C2-boks (blir hos `editorial-reviewer`, ingen gate-regel).
3. **JA-promoter:** KTG svarer JA/NEI. NEI → `rejected` (beholdes). JA → promotér.
4. **Promotér atomisk:** `rules.ts`-entry + kontrakt-rad + §E-manifest-rad (id·ref·severity·proveniens)
+ merk fold-in `promoted`.
5. **Ratify:** `npm run ratify` MÅ være grønn før promoteringen teller.
**Bindingen** (`src/ratify.ts`): importerer `RULES` direkte (ingen skjør tekst-parsing) og krever en
**bijeksjon** mot gate-bindings-manifestet i §E — hver regel ↔ nøyaktig én manifest-rad, med `ref` +
`severity` identisk, og hver `§`-anker en ekte seksjon. En regel i `rules.ts` uten manifest-rad (gaten
håndhever noe udokumentert), eller en manifest-rad uten regel (en «regel» ingen håndhever), feiler:
```
$ npm run ratify
✓ I sync — 10 regler bundet 1:1 til §E-manifestet (ref + severity stemmer).
```
Kontrakt-sti: argument > `MASKINROMMET_CONTRACT` > default (relativt til modulen). Mangler kontrakten
(fersk klon uten maskinrommet) → exit 2 med klar beskjed; den ekte-kontrakt-testen skippes da.