diff --git a/docs/okf-ingestion/plan.md b/docs/okf-ingestion/plan.md index 696055d..fcdae9a 100644 --- a/docs/okf-ingestion/plan.md +++ b/docs/okf-ingestion/plan.md @@ -16,7 +16,7 @@ > > **Separate, do not merge:** `docs/ingestion-guard/plan.md` (`planned`) is this repo's *security* wiring > plan. It shares persist points with this document by necessity, but is a distinct decision with a -> distinct dependency. §6 states the boundary. +> distinct dependency. §7 states the boundary. ## 1. Executive answer @@ -161,7 +161,47 @@ declare themselves generic by architecture. Note we carry the data-root resolver *path convention* is plugin-local even where the *idiom* is not; a shared library should take the idiom and leave the path. -## 6. Boundary against the guard plan +## 6. Bundle inventory and placement + +Operator decision, 2026-07-20: **user-owned OKF bundles live outside the plugin/repo tree and are only +referenced from it.** Plugin-generated bundles that are part of the plugin's own delivery stay. + +**We already comply — the migration happened in M0 (v0.6.0), before the decision existed.** Every +user-owned artifact resolves through `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/` +(`references/data-path-convention.md`), with an idempotent session-start migration. Nothing user-owned has +lived in the repo tree since. + +| Artifact | Path | OKF bundle? | Class | +|---|---|---|---| +| **Brain** | `/brain/` | **Yes** — the repo's only OKF bundle (`type` + per-level `index.md` + root `okf_version: 0.1`; `okf-check.mjs` exit 0, 2026-06-26) | **User-owned** — see boundary case below | +| Published-post tributary | `/ingest/{inbox,published}/` | No — deliberately excluded (§5) | User-owned | +| Trend store | `/trends/trends.json` | No — a single JSON file, not a markdown bundle | User-owned | +| Morning briefs | `/trends/morning-brief/.md` | No — dated briefs with frontmatter, no `index.md`, not concept files | User-owned | +| Specifics-bank | `/specifics-bank/specifics-bank.json` | No | User-owned | +| Analytics batches | `/posts/*.json` | No | User-owned | +| Reference docs (28) | `references/*.md` **in repo** | No — no `type`, no `index.md` | **Plugin-owned**, ships with the plugin, correctly in-tree | + +**Nothing breaks on migration, because there is nothing left to migrate.** The one caveat is historical: +pre-M0 installs kept data in-tree, and the session-start migration already handles that path. A second +caveat worth naming: `assets/drafts/queue.json` and `assets/analytics/` remain in-tree as gitignored +scratch — they are not bundles, but they are the last in-tree paths that hold user bytes, and they should +be revisited if the decision is ever tightened to "no user bytes in-tree at all." + +### The boundary case — and it says the taxonomy's axis is wrong + +The decision's table discriminates on **who writes**: plugin writes → plugin-owned → lives in the repo. +Our brain is **written by the plugin** (`consolidate`/fold, operator-gated at `--apply --confirm`) and +never hand-authored. By that table it is plugin-owned and belongs in the repo. **That conclusion is +exactly wrong** — it is the single most personal artifact we hold, it must survive plugin upgrade and +uninstall, and the repo is publicly distributed. + +The discriminator that gives the right answer everywhere in our inventory is **whose lifecycle the content +follows**, not whose hand writes the bytes. Our brain is machine-written and user-owned, and that +combination is not a rare corner — it is what any learning system produces. We suggest the axis be +lifecycle/ownership, with authorship as a non-determinative attribute. Otherwise every plugin that +*derives* user knowledge lands on the wrong side of a table it read correctly. + +## 7. Boundary against the guard plan `docs/ingestion-guard/plan.md` identifies four persist gates: trends `capture`, brain `writePublished`/`scanInbox`, newsletter→`ekstern` bindings, analytics `saveBatch`. Two of those (trends @@ -173,7 +213,7 @@ and in what shape.** They share a dependency in one place only — R1's seam is land — and that is noted as a seam requirement, not a security decision. Neither plan is a prerequisite for the other's approval. The guard plan's own interop blocker (Python↔Node) is tracked there. -## 7. Open questions for the library owners +## 8. Open questions for the library owners 1. Does R1 (model-mediated payload door) belong to door B, or is it a fourth door? It is neither an inbox scan nor an external bundle import. @@ -182,7 +222,7 @@ the other's approval. The guard plan's own interop blocker (Python↔Node) is tr 3. For phase 4: is the Node half expected to reach parity with door A only, or with whatever doors exist when it starts? Our adoption depends on R1, which is not door A. -## 8. References +## 9. References - Library: `https://git.fromaitochitta.com/open/llm-ingestion-okf` - Guard: `https://git.fromaitochitta.com/open/llm-ingestion-pipeline-security`