# 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 ```bash cd scripts/specifics-bank && npm install ``` ## Use ```bash # 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 ` 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`. `--type` ∈ `number | 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.ts` — `renderKilder`, the read-only `NN-kilder.md` sources artifact, rendered deterministically from the slot-map + the bank. ```bash # Gate one edition's binding (exit 1 = BLOCK) node --import tsx src/cli.ts validate-binding --edition "/linkedin/edition-state.json" # Render the sources ledger node --import tsx src/cli.ts render-kilder --edition "/linkedin/edition-state.json" --out "/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 ```bash npm test # node:test, deterministic (callers supply capturedAt) npm run build # tsc — must stay clean ```