linkedin-studio/scripts/specifics-bank
Kjell Tore Guttormsen e38f71f418 fix(linkedin-studio): N24.5 — mekanisk gjeldssveip (plugin.json, CHANGELOG-dublett, de-niche, KTG, Step 9-nøkler) [skip-docs]
Fem grep-lokaliserte gjeldsposter fra STATE FUNN, pluss to anti-erosjons-lints
som gjør to av dem terminale i stedet for gjenoppdaget en gang til.

1. .claude-plugin/plugin.json description — v4.0.0-arvet release-notat med
   historiske tellinger («→ 19 agents», «→ 27 commands», «→ 29 commands»)
   erstattet av en beskrivelse av hva pluginen ER. Dette er teksten /plugin
   viser. Ingen tellinger i teksten: de drifter, og CHANGELOG.md eier historikken.

2. CHANGELOG hadde TO «## [0.6.0]»-overskrifter (2026-07-17 = ekte, 2026-02-07 i
   halen). Halens datert om til «## [0.6.0-legacy]». Sjette gangs gjenoppdagelse
   — derfor lint, se punkt 6.

3. De-niche: 7 «thought leader»-treff utenfor commands/ rettet — README (mot
   kommandoens egen frontmatter-ordlyd), skills/linkedin-networking (2:
   FUNN-listen navnga bare :9, men :185 var samme defekt), analytics-interpreter,
   analytics-tools-guide, collaborations-guide, linkedin-visual-style.
   BEVISST BEHOLDT: de 5 blocklist-linjene, de to negative eksemplene
   (opportunity-generation, det ironiske sitatet i video-strategy-guide), og
   network-builder:562 — et WebSearch-uttrykk som treffer hvordan ANDRE
   merker seg selv, allerede paret med «Creator».

4. Hardkodet «KTG» i generisk operatør-tiltale fjernet. FUNN navnga tre linjer i
   language-reviewer; klassen var 21 linjer over 4 agenter, newsletter.md,
   edition-state-templaten og specifics-bank sitt renderte NN-kilder.md-artefakt.
   BEVISST BEHOLDT som proveniens: CHANGELOG, tests/fixtures/* (de ER KTGs
   faktiske redaktørrunde, kalibreringsfasiten), adopter-notatene som ærlig
   flagger KTG-interne verktøy (contract-gate, specifics-bank), «KTG
   cover-directive» og «answers KTG's question» — attribusjon, ikke tiltale.

5. Step 9 persisterte tre nøkler templaten aldri deklarerte: randsoneGate (N9),
   hookForge + personaSweep.deling (N24). Nå deklarert i BÅDE artikkel-shapen og
   _doc. Additivt, schemaVersion forblir 1. _doc.hookForge bærer N22-invarianten
   videre: en variant har målt lengde / krok-type / kroppsspor og ALDRI en
   predikert engagement-score.

6. To nye ubetingede lints (Section 16aa), begge mutasjonstestet mot de FAKTISKE
   filene, ikke bare mot self-testen:
   - CHANGELOG-dublettvakt (+ in-memory non-vakuitets-self-test som skiller en
     ekte dublett fra en bevisst «-legacy»-overskrift)
   - Step 9-nøkkeldeklarasjon (shape + _doc)
   Mutasjon 1 (gjeninnfør dubletten) → rødt. Mutasjon 2 (fjern hookForge fra
   shapen) → rødt. Mutasjon 3 (fjern _doc.randsoneGate, fila fortsatt gyldig
   JSON) → rødt. Restaurert → grønt.

Ti suiter grønne: test-runner 300 → 303 (floor 281 → 284) · trends 300 ·
analytics 202 · hooks 191 · brain 134 · editions 72 · render 63 ·
specifics-bank 45 · tests 35 · contract-gate 33.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vMLTF7J13jJmgqwwJyivt
2026-07-31 21:46:35 +02:00
..
src fix(linkedin-studio): N24.5 — mekanisk gjeldssveip (plugin.json, CHANGELOG-dublett, de-niche, KTG, Step 9-nøkler) [skip-docs] 2026-07-31 21:46:35 +02:00
tests fix(linkedin-studio): N24.5 — mekanisk gjeldssveip (plugin.json, CHANGELOG-dublett, de-niche, KTG, Step 9-nøkler) [skip-docs] 2026-07-31 21:46:35 +02:00
package-lock.json feat(linkedin-studio): specifics-bank store — lived-specifics inventory (fix #2 slice 1) 2026-06-20 21:03:18 +02:00
package.json feat(linkedin-studio): specifics-bank store — lived-specifics inventory (fix #2 slice 1) 2026-06-20 21:03:18 +02:00
README.md feat(linkedin-studio): per-edition lived-specifics binding + kilder artifact (fix #2 slice 2) 2026-06-20 21:33:44 +02:00
tsconfig.json feat(linkedin-studio): specifics-bank store — lived-specifics inventory (fix #2 slice 1) 2026-06-20 21:03:18 +02:00

specifics-bank — the lived-specifics inventory (Fix #2, kilde-så-draft)

A deterministic, topic-tagged store of the operator's real, un-generatable raw material — the specific measured number, the named (anonymized-but-real) case, the thing that actually broke, the unfashionable opinion privately held, the moment they changed their mind. The point (retning §3, dream-spec «Lived-Specifics Extraction»): sourcing, not styling, is where authenticity is won. Drafts must draw from real inventory instead of inventing plausible filler, so every downstream voice gate polishes grounded content, not hollow content.

This is the store half (deterministic + tested). The elicitation half — a guided interview that refuses vague answers (escape hatches: mark a slot abstrakt or ekstern) — lives in the command layer (/linkedin:newsletter Step 1.5, slice 3). The bank never holds AI-generated lived experience; every content is the operator's own words.

Where the bank lives

${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/specifics-bank/specifics-bank.json

It sits in the per-user data dir (M0 data-path convention), outside the plugin install, so it survives plugin upgrades and reinstalls. It is the first concrete tributary of the broader profile-evolution / "second brain" architecture.

Setup

cd scripts/specifics-bank && npm install

Use

# Surface inventory the operator already has for an edition's topics
node --import tsx src/cli.ts query --tags "saksbehandling,produktivitet"

# Fold newly-elicited material back into the bank
node --import tsx src/cli.ts add --type number \
  --content "Saksbehandleren sparte to dager i uka." \
  --tags "saksbehandling,produktivitet" --source "seres/05"

# Inspect the whole bank
node --import tsx src/cli.ts list

Flags: --bank <path> overrides the default location; --json emits machine output for query/list. add defaults --verification to unverified (numbers stay guilty-until-checked — regel 6/7) and --source to manual.

--typenumber | named-case | what-broke | contrarian | mind-change | other.

Model

  • Dedupe key = sha256(normalizeContent(content)).slice(0,12) (lowercase + trimmed + whitespace-collapsed). Re-capturing the same material under a new edition's topic does not add a second entry — its topicTags are unioned in, enriching the record.
  • Query returns active specifics whose tags overlap, ranked by overlap (desc) then recency (capturedAt desc); archived material is kept but never offered.
  • Content is stored verbatim; only the id is normalized.

Per-edition binding (slice 2)

The bank is the global inventory; an edition binds its load-bearing claims to real material before any prose exists. That bridge lives here too:

  • binding.ts — the per-edition slot-map model + validateBinding, the «vaghet avvises» gate (a slot must be specific / abstrakt / ekstern; an unresolved slot, a dangling specific id, or an unjustified abstrakt → BLOCK; an unverified-number-backed slot → WARN per regel 6/7).
  • kilder.tsrenderKilder, the read-only NN-kilder.md sources artifact, rendered deterministically from the slot-map + the bank.
# Gate one edition's binding (exit 1 = BLOCK)
node --import tsx src/cli.ts validate-binding --edition "<abs>/linkedin/edition-state.json"
# Render the sources ledger
node --import tsx src/cli.ts render-kilder --edition "<abs>/linkedin/edition-state.json" --out "<abs>/linkedin/NN-kilder.md"

Design record + the Step 2 research re-scope spec: docs/fix2/slice2-binding.md. The elicitation interview that POPULATES the slot-map (Step 1.5) is slice 3.

Test

npm test     # node:test, deterministic (callers supply capturedAt)
npm run build # tsc — must stay clean