llm-ingestion-okf/docs/plan/phase-4-node-half.md
Kjell Tore Guttormsen b0ad2aedfb docs(plan): add detailed phase 1-4 implementation plans
Phase 1 (Door A): ingest-spec v1 implementation + §11 golden fixtures,
pinned to the current spec revision, with TDD order and byte-exact
verification criteria. Phase 2 (Doors B/C): guard-gated inbox and
external bundle import. Phase 3: configurable bundle contract via a
profile object, default profile locked to the golden suite. Phase 4:
zero-dep Node half, coordination-first with owner sign-offs.

Each plan carries explicit key assumptions with tests and a
verification section.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QeqhJpYQyghASjiJo5EhGg
2026-07-16 10:58:08 +02:00

103 lines
6 KiB
Markdown

# Phase 4 plan — the Node half (`node/`)
Status: approved roadmap phase (see `CLAUDE.md`); details settled here before code.
Depends on: Phase 3 (the profile object must be able to express the second-brain
contract; that expressiveness is checked during Phase 3's split-table step).
Hard precondition: the coordination steps below — this phase does not start with
code, it starts with agreements.
## Goal
A zero-dependency Node/ESM package under `node/` for the second-brain world:
bundle check, index generation, inbox split/frontmatter/write, and document
conversion (docx/pdf/eml/html → md). Importable as a library AND invokable as a
CLI (`node <path> <args>`, exit code + stdout — the established plugin
invocation pattern), consumed by vendoring per plugin, not npm publishing.
The Python and Node halves share the OKF contract and the fixture suite, never
code.
## Coordination first (ordered, each with an owner sign-off)
1. **okr agreement.** The reference implementations (`okf-check.mjs`,
`okf-index.mjs`, the inbox libraries and vocabulary/link modules) are lifted
only in agreement with okr; their test suite is ported alongside the code as
the seed corpus. Known deviations between okr's current behavior and the
catalog spec are resolved WITH the convention owner before the lift — the
library implements the agreed contract, not one repo's drift.
2. **Catalog stays convention owner.** The second-brain spec remains in the
marketplace catalog; this repo implements it. After the lift, the catalog
re-pins its shared check gate to this repo's copy — acceptance is behavior
parity on the shared fixture suite, and the re-pin follows the marketplace's
release-tag pinning discipline.
3. **linkedin-studio stays plugin-local.** Its `ingest/published/`
provenance-record grammar has a different lifecycle by design and is NOT
normalized into this library. Explicit non-goal, agreed up front.
4. **Persist gate = guard-as-contract.** There is no Node guard today. The Node
half documents and enforces the guard's *contract* at its persist seam
(fail-closed hook point, no content-safety logic of its own) so a future Node
guard from the security repo can drop in. No security reimplementation in
either runtime.
5. **ms-ai-architect as greenfield consumer.** Its designed-but-unbuilt needs
(writer, index generator, checker, retrieval support) are the acceptance
sketch for the package's API surface.
## Deliverables
1. **`node/` package skeleton:** ESM, `package.json` with NO `dependencies`,
`node:` builtins only, `node:test` for tests, no build step (vendorable as
plain files).
2. **Bundle check** (`okf check`): the catalog spec's rules — `type:` required,
per-level `index.md` without frontmatter, root `okf_version`, canonical
`resource` field, preserve-unknown / tolerate-broken posture.
3. **Index generation** (`okf index`): per-level index maintenance matching the
reference behavior.
4. **Inbox primitives:** split, frontmatter emit/parse, relations, write — the
lifted library modules under this repo's test suite.
5. **Document conversion** (`okf convert`): docx/pdf/eml/html → md. Conversion
parsers cannot be zero-dep; this mirrors the Python `[extract]` pattern —
the core package stays dependency-free, the conversion module lazy-loads
optional parsers and rejects those types fail-fast when they are absent.
Which parsers, and whether they are vendored or peer-installed, is settled in
coordination step 1 (okr had concrete candidates).
6. **CLI:** one entry (`node/bin/okf.mjs check|index|inbox|convert …`),
deterministic stdout, meaningful exit codes, no interactive prompts.
7. **Shared fixture suite:** cross-runtime fixtures for the second-brain
contract, consumed by BOTH the Node tests and (via the Phase 3 profile) the
Python tests, so the halves cannot silently diverge.
## Key assumptions (each with its test)
| # | Assumption | Test |
|---|---|---|
| D1 | okr's reference code + tests transfer cleanly to this repo's layout | Ported suite green before any behavior change; parity run against okr's copy on the shared fixtures |
| D2 | The catalog spec is the single contract both halves implement | Phase 3 profile expresses it; cross-runtime fixture suite passes in both runtimes |
| D3 | Zero-dep core is compatible with doc conversion | Lazy-load pattern proven by a test run WITHOUT optional parsers installed: core commands work, `convert` fails fast with a clear message |
| D4 | Vendoring workflow works for consumers | Dry-run: copy `node/` into a scratch plugin layout, run the CLI from there, exit codes intact |
## Non-goals
- npm publishing (vendoring only), bundling/transpiling, TypeScript build chain.
- Normalizing linkedin-studio's published-record grammar.
- A Node guard, or ANY content-safety logic — guard-as-contract until the
security repo ships a Node implementation.
- Python↔Node code sharing of any kind (contract and fixtures only).
## Verification
1. `node --test node/` green; ported reference tests included.
2. Zero-dep proof: `package.json` has no `dependencies`/`optionalDependencies`;
grep for non-`node:` imports in core modules returns nothing (conversion
module exempted, lazy-load only).
3. Parity: this repo's check gate and the currently vendored reference copy
produce identical verdicts on the full shared fixture suite (scripted
comparison, part of CI until the catalog re-pins).
4. Cross-runtime agreement: Python (Phase 3 profile) and Node checkers give the
same accept/reject verdict per shared fixture (scripted matrix run).
5. CLI contract: each subcommand exercised via `node node/bin/okf.mjs …` in
tests; exit codes asserted (0 clean, non-zero on violation), stdout
deterministic (two runs diff-empty).
6. D3 test: suite run in an environment without optional parsers — core green,
`convert` on a docx fails fast naming the missing parser.
7. Coordination artifacts: each of the five steps above has a recorded sign-off
before its dependent code lands (tracked in the session state, summarized in
the commit history).