diff --git a/docs/okf-ingestion/plan.md b/docs/okf-ingestion/plan.md index 83d461e..b9e80cc 100644 --- a/docs/okf-ingestion/plan.md +++ b/docs/okf-ingestion/plan.md @@ -273,3 +273,69 @@ the other's approval. The guard plan's own interop blocker (Python↔Node) is tr - Spec owner: `portfolio-optimiser-commons/ingest-spec.md` - This repo: `docs/okf-convergence-brief.md` (Stage-1 OKF conformance, `brain/` bundle), `docs/ingestion-guard/plan.md` (separate, `planned`), `docs/second-brain/architecture.md` + +## 10. Trinn E — consolidated positions (preserved before postbox teardown, 2026-07-21) + +The OKF adoption round closed at trinn F (consensus). Our trinn E answer lived in the interim +postbox (`~/repos/_okf-interim/svar/linkedin-studio.md`), which is now torn down. Its durable +substance is preserved here; everything below was verified against code on 2026-07-20. The +technical requirements (R1–R5) already live in §4; this section captures the round-positional and +follow-up material that existed only in the postbox. + +**Our §7 register row (status + position).** +- Status stays **`planned`**, not `blocked on phase 4 scope` — verified: the only Python in this + repo is `hooks/scripts/compile-hooks.py`, a build-time script never on a data path; we do not + run door A and would gain nothing from parity. +- We do **not** need door-A stamping (`generated` / `ingest_manifest`). The negative requirement + holds: inject nothing, normalize nothing. +- Unforgeability must live **outside the file** — our content-address `mintContentId` (byte-exact + sha256, `scripts/brain/src/id.ts:53-55`) is unforgeable without the writer forming an opinion + about the frontmatter. If the writer inspects the string to enforce a stamp, passthrough (R2) is + gone in the same move. +- §5 must tolerate extension keys (R2, unchanged); the mandatory reserved-key prefix is limited to + **stamped, extracted** concepts, not concepts as such. + +**D1 (frontmatter/stamp) — we are affected, not owner.** The ratified D1 **matches our ask**: +enforcement moved to `check_bundle` (per-file outcome); the door-C writer rejects the *complete* +ownership stamp (`generated:true` **and** `ingest_manifest` together), not the five names, so +round-trip for legitimate door C is preserved; the mandatory prefix binds stamped (door-A) files +alone. We accept commons' point that passthrough makes §5's key contract unenforceable at the +writer by construction — that is the right outcome, since the writer cannot make the +stamped-vs-curated distinction without reading what it promised not to read. + +**D3 (`partial`) — accepted with one caveat, now resolved.** We accepted the definition and flagged +that "comparable path" was undefined (it decided our value outright: `brain/` writing through the +library while trend-store / specifics-bank stay standalone JSON — `scripts/trends/src/store.ts:126-141`). +The ratified definition (trinn F) is: comparable path = would have gone through the same door +(A/B/C). Under that, our JSON/CSV/domain-store paths are not comparable and do not force us +`partial`. **Our status today is `planned`, not `partial`** — zero production paths go through the +library; we do not emit `partial` (now a transitory value carrying owner + next step) until it is +ratified. + +**Durable technical additions (would otherwise be lost with the postbox).** +- **Empty vocabulary must mean "don't snap", not "snap to default".** Verified: + `node okr/scripts/okf-check.mjs --strict-ingest` collapses our three real types + (`Profile` / `Operations` / `PendingDiff`) to `DEFAULT_TYPE='Dokument'` + (`okr/lib/okf-vocab.mjs:26`), erasing the distinction our conformance test rests on + (`scripts/brain/tests/okf-conform.test.ts:15-20`). Vocabulary is per-bundle, never spec-global. + Ask: absence of an injected vocab list is a legal state (= "don't snap"), not "snap all to default". +- **Supporting evidence, and it is not ours:** `okf-check.mjs:21` names the constant `RECOMMENDED`, + not `REQUIRED` — the de-facto checker all nine repos read already treats §5 keys beyond `type` as + warnings, not requirements. Making the prefix mandatory would turn a green bundle red with zero + byte change, contradicting the tool that defined conformance in practice during the round. +- **`type` vocabulary is three values, not five** (corrects trinn C §5): only `Profile` + (`scripts/brain/src/profile.ts:48-50`), `Operations` (`scaffold.ts:56-58`), `PendingDiff` + (`cli.ts:252`) are emitted by code; `JournalEntry` / `TributarySummary` exist only as "e.g." in a + design note (`docs/okf-convergence-brief.md:101`), never in code. +- **Index `preserve-unowned` boundary.** We have a fourth index mode — create-if-absent, no managed + lines, whole file hand-editable (`scripts/brain/src/scaffold.ts:33-36,126-141`). Concrete + requirement for eventual adoption: `write_index(mode="preserve-unowned")` against an existing file + with no managed lines must leave it **byte-untouched**, not normalize the frame "while it is there + anyway" — else we lose a file the operator hand-writes. +- **Layer 1 = the evolving set, not a frozen snapshot** (also §8 item 3). Since §5 added + `read_concept`, `navigate_bundle`, and `routeLevel` after Q3 was asked, "the layer-1 primitives" + must read as the set as it stands, not a snapshot: our invariant is `serialize ∘ parse = identity` + (`scripts/brain/tests/ingest.test.ts:102`), and a Node half with a writer but no reader gives us + half the invariant. Derived (not a new ask): the shared golden fixtures for `resolve_link` must + cover all four orthogonal axes across runtime — our R5 stated the fixture requirement for the + writer's frame alone, which is now too narrow.