# 2026-06-17 — Knowledge ingestion phase 0: prerequisites (brokered half) Picked up the knowledge-ingestion epic. Phase 0 = the soul→knowledge promotion lane. Fritz chose **prerequisites-first** over a minimal manual cascade slice, so this session built the routing/autonomy substrate the promote primitive will sit on, not the cascade itself. ## Done **A1 — `mark_worlds` writable column (broker, Go).** The writer set already existed in code (`authorizedWorlds` / `worldAllows(&w.Allow, claims)`, used by `/auth/callback` + `/me/install`) but was never exposed through read-discovery — #189 deliberately made `mark_worlds` list *readable* worlds only. Added a 4th `writable: yes/no` column computed per row from the caller's claims, so a single call yields `{readable, writable}`. Append-only column → library table parser unaffected. `tools/demarkus-broker/internal/broker/mcp_tools_worlds.go` (+`yesNo`), `mcp_tools_list.go` (tool description), `mcp_tools_worlds_test.go`. Full broker suite + `pre-commit.sh` green. **B — `world.md` per-world descriptor (spec + seed).** Example at `plugins/claude-code-knowledge/examples/knowledge-system/world.md` + README wiring. Structured core: `descriptor_version`, `team`, `domain`, `partition_role` (hub|team|project|scratch), `autonomy_ceiling` (human-only|verify-then-auto|auto). Per-world well-known (`mark:///.well-known/demarkus/world.md`), distinct from root-global policy/template. No-descriptor worlds still work (writable-but-unlabeled, pick-list only, default human-only). Reader is plain `mark_fetch`. ## Key facts learned about the code - Plugins are **pure bash/awk hooks + markdown slash-commands + skills** — no Go on the promote path. The cascade (triage→distill→dedup→tag→gate→publish→back-stamp) is judgment-heavy model work → belongs in a slash command + skill driving MCP tools, matching the "agent as librarian / intelligence at the edge" invariant. Bash only for detection + back-stamp glue. - **Detection is one-way today:** knowledge reads `~/.demarkus/plugin-memory.conf` (`soul_is_configured`) to spot a sibling soul; memory does NOT detect knowledge. Mutual detection (plan's bridge) = a memory-side peek at `~/.demarkus/knowledge-systems` (the joined-slug registry written by `/knowledge-join`). Small, not yet built. - Broker authz: `worldAllows` is the writer predicate (per-world `Allow`: Emails carve-out, else Domains∧Groups); `readableWorlds` = every configured world (SSO org gate only). The two are kept deliberately separate so "all logins read, writes allow-listed" is expressible. ## Deferred - **A2** — plain-remote token-grant introspection (a demarkus-server surface reporting a token's `{operations, path-globs}`). Live target is brokered, so A1 unblocks routing now; A2 after the brokered path is proven. ## Next Remaining phase-0 prerequisites/work: the **promote primitive** (the cascade, as `/promote` command + skill, detection-gated) and the **coherence edge** (link-not-copy stub / version-stamped back-stamp). A1+B are now in place to route and cap autonomy. Dogfood still stands: promote `/plans/knowledge-ingestion.md` itself as the first run. Recorded progress in the plan under "## Build progress". ## Session 2 — the promote primitive Built the promote primitive (phase 0's core) on top of A1+B. Detection-gated bridge, split across both plugins, model-driven. **New files / changes:** - `plugins/claude-code/scripts/lib.sh` — `KNOWLEDGE_REGISTRY` const + `knowledge_endpoints()` / `knowledge_present()` (reverse-peek the knowledge registry; mutual detection; broker-unaware). - `plugins/claude-code/scripts/detect-knowledge.sh` — detection gate (mirrors detect-soul.sh). - `plugins/claude-code/commands/promote.md` — `/promote `: gate → read source → already-promoted check → knowledge cascade → back-stamp (stub | marker-only). One-directional back-stamp; directional reconciliation. - `plugins/claude-code-knowledge/skills/knowledge-promote/SKILL.md` — execution cascade (triage→distill→dedup→tag→route→gate→publish). First skill in the knowledge plugin (auto-discovered, no manifest entry needed). - `plugins/claude-code/tests/detect-knowledge_test.sh` — 5 tests, green. Full plugin regression green (memory + knowledge). **Gotchas captured:** - Skills + commands auto-discover from their dirs — no plugin.json entry (memory's manifest has no skills key yet soul-memory works). - `KNOWLEDGE_REGISTRY` is `readonly`, bound to HOME at source time → can't unit-test the function with a swapped HOME in one shell; test the *script* in fresh subprocesses with controlled HOME instead (what detect-knowledge_test.sh does). - shellcheck SC1091 (can't follow lib.sh) is info-level and identical on the established detect-soul.sh; no CI shellcheck config in .github. SC2317 in lib.sh:9 is pre-existing. **Next:** coherence edge active half (version-stamped invalidation + re-promotion-as-gated-update), then dogfood `/promote /plans/knowledge-ingestion.md`. Triggers beyond manual (signal/batch) and A2 still open. Plugin version bumps left for Fritz. ## Session 3 — coherence edge (folded into the promote branch) Active downward half of the coherence edge. All plugin work, on branch feat/knowledge-promote-primitive. **Changes:** - `commands/promote.md` — standardized back-stamp marker to a single greppable line `promoted: mark:///@v` (both stub + marker-only modes); back-stamp now adds the `promoted` metadata tag. Step-3 already-promoted check updated to the new format + framed as the upward leg. - `commands/soul-refresh.md` (new) — downward sync. Gate → find promoted docs (tag=promoted) → parse @vN → compare to live knowledge version → directional refresh: stub auto-refreshes down, marker-only surfaces for pull-down vs re-promote-upward. Dangling target surfaced not deleted. Related-but-distinct staleness deferred. - `context/session-guidance.md` — one line noting /promote + /soul-refresh activate only with a joined knowledge system. **Design notes:** - Hooks can't reach the broker, so the staleness check + refresh must be an agent-driven command, not a PostToolUse/recall hook. The plan called this out. - Reconciliation is strictly directional. /soul-refresh never two-way merges; local edits go up via /promote (which owns the gate + the cascade's update path), keeping the v0.5.0 plugin partition + the authority model intact. - No new bash → no new tests needed; full plugin regression still green (memory + knowledge). **Phase-0 prerequisites now all but A2 done.** Next candidates: signal/batch triggers, or the dogfood promote of the plan itself. Plugin version bumps (memory + knowledge) still pending Fritz's commit.