Skip to content

ID-68 {68.12} — Docs/Ledger Relocation: V2 Addendum (Warp-grounded verdict + routing taxonomy + ontology auto-sync)

ID-68 {68.12} — Docs/Ledger Relocation: V2 Addendum (Warp-grounded verdict + routing taxonomy + ontology auto-sync)

Section titled “ID-68 {68.12} — Docs/Ledger Relocation: V2 Addendum (Warp-grounded verdict + routing taxonomy + ontology auto-sync)”

Type: Investigation report (V2 addendum). NO implementation — investigation + design only. No code, test, ledger, skill, or workflow edits made. Authored: 02/06/2026 by a directed cmux research worker. Extends: RELOCATION-INVESTIGATION.md (S299), per Liam’s S301 feedback. Read that first — V2 does not restate its §1 codebase inventory; it tests, amends, and extends it. Companion (superseded framing): DOCS-RELOCATION-SUBTASK.md (S293 R-Split).


Liam ratified all 12 open questions (OQ-R1…OQ-R12) on 02/06/2026. They are closed — the §6′ table below records each disposition. Two headline rulings:

  • OQ-R10 — the partitioned routing taxonomy in §D2 is ratified policy, amending the S294 blanket override (“move everything under /docs + /.planning out”).
  • OQ-R12 (security re-examination, S-B adopted)SENSITIVITY is now a PRIMARY routing axis. The docs-site (internal KB, not customer docs — Warp precedent does not apply) + the recon-valuable spaces (reference, runbooks, specs→decisions render, product-functionality, generated) move to knowledge-hub-internal with a GATED Vercel deployment; ontology STAYS (sanitised public-safe build input + cross-repo published); design STAYS (public-safe); ledgers + raw spec source STAY (sanitised-public). The S299 §3 code→private-docs publish bridge is re-added, security-justified. Vercel Deployment Protection is CONFIRMED enabled (present-tense exposure closed). The §D2 rows carry per-row amended OQ-R12 (S301) notes.

Other rulings folded in: retire documentation-inventory.md + doc-freshness.test.ts keeping a slim reference-doc-paths.test.ts (R8); Starlight sidebar + Pagefind replace the inventory and the same-commit write-coupling rule is removed (R9); docs/ontology/ stays in the code repo (R7); product-retros.json stays with the other 3 ledgers and the relocated evaluation lane becomes a code→ledger cross-repo writer via the docs-bridge GitHub App (R4); add ontology-sync.yml + add docs/ontology/** to the code→docs publish set (R11); sibling checkout + KH_DOCS_DIR and a GitHub App for cross-repo auth (R1/R2, detail deferred to implementation); R3/R5/R6 resolved by R10; R12 = Option S-B (docs-site + recon spaces → private gated; ontology/design + ledgers/specs stay sanitised-public; Vercel gating confirmed). The phased implementation design lives in RELOCATION-IMPLEMENTATION-PLAN.md.


S299 recommended Option A (two-repo split, sibling checkout, one KH_DOCS_DIR env var) and declared an “unavoidable structural cost”: sidecar→orthogonal trades zero-drift-by-construction for autonomy. V2 tests that claim against Warp’s actual code and finds it conditionally true, not unconditionally true — the cost is a function of the routing choice, and Warp engineered most of it away by partitioning content rather than moving all of it. Four concrete deltas:

  1. D1 verdict (amended). Warp did not leave the cost unavoidable. They keep lockstep-mutated content (engineering specs) inside the code repo and move only published-derived docs out, where an agent (docubot) auto-compensates drift on every PR. The cost only materialises for content you both move out and mutate in lockstep with code. S299’s “move everything under /docs + /.planning out” maximises that surface. (§D1)

  2. D2 routing taxonomy (now ratified S301 policy). A prescriptive per-doc-type destination table. The load-bearing principle, Warp-grounded and ratified (OQ-R10): build inputs + lockstep-mutated SDLC state stay in the code repo (sanitised); pure-published + durable-private + ephemeral move out. This amends the S294 blanket override. (§D2)

  3. D3 retire, don’t relocate (new). The Starlight autogenerated sidebar is the inventory — documentation-inventory.md retires. doc-freshness.test.ts is a different thing (a doc→code-path guard the docs-site build does not replace); retiring it loses a real guarantee for 3 docs. Precise loss + replacement specified. (§D3)

  4. D4 ontology sync is brownfield + a build-coupling S299 missed. Ontology sync was already built — the WP6 Markdown Ontology Harness (S236–S238): markdown register as source-of-truth, build-time codegen, and a 3-way parity test (markdown ↔ generated tuple ↔ live DB CHECK) that fails CI on drift. It does not mirror taxonomy-sync (inverted source-of-truth: ontology’s markdown lives in git, so it needs a guard, not an auto-commit workflow). The split-survival delta is one routing decision: docs/ontology/04-content-type.md is a code-repo prebuild generator source — moving it breaks bun build/bun dev, not just the docs-site — so the register stays in the code repo and the whole harness keeps working unchanged. No new workflow required. (§D4)

The §6 OQs are revised at the end — all 12 are ratified/closed (S301, 02/06/2026), incl. the OQ-R12 security re-examination (Option S-B; sensitivity-primary routing).


D1 — The “unavoidable structural cost” tested against Warp

Section titled “D1 — The “unavoidable structural cost” tested against Warp”
  • Blog: Open-sourcing our docs and the agents that maintain them (warp.dev).
  • Local Warp code repo: /Users/liamj/Documents/development/Warp — confirmed to be the code repo (warpdotdev/warp): Rust workspace Cargo.toml, README links out to https://docs.warp.dev. Top-level dirs: .agents/ .claude/ .warp/ .github/ app/ crates/ command-signatures-v2/ docker/ resources/ script/ specs/.
  • Mempalace provenance: a prior KH research doc — docs/research/docs-site-rebuild-research.md (716 lines, S51) — already inventoried Warp’s 6 docs skills at github.com/warpdotdev/docs/.agents/skills/ (24 skills total) and docubot’s 7-step composite action. Corroborates the repo evidence below.

D1.2 The concrete mechanism (claims confirmed against files)

Section titled “D1.2 The concrete mechanism (claims confirmed against files)”
Blog claimRepo evidence (code repo at /Users/liamj/Documents/development/Warp)Verdict
Docs live in a separate repoREADME → docs.warp.dev; no top-level docs/ or .planning/ (confirmed absent by ls)Confirmed
”Agents that maintain them” are in the docs repoThe 6 docs skills (review-docs-pr, update-changelog, sync-error-docs, missing_docs, check_for_broken_links, docs-seo-audit) are NOT in the code repo’s .agents/skills/ (20 skills, all engineering: create-pr, write-tech-spec, rust-unit-tests, …). They live in warpdotdev/docs/.agents/skills/ per mempalace.Confirmed
Docs “follow the code automatically” across the boundarydocubot: .github/workflows/docubot_reply_to_comment.yml + .github/actions/docubot/action.yml (action.yml:30 checks out warpdotdev/gitbook via token into a local path) + prompt.txt. The Warp CLI agent reads the invoking PR’s diff, edits the docs repo’s .md, opens a docubot/<slug> branch + PR there, posts the link back.Confirmed
Engineering specsWarp checks specs/GH<issue>/PRODUCT.md + TECH.md into the code repo (top-level specs/, authored by in-repo write-product-spec/write-tech-spec skills).Confirmed — specs do NOT move out
(Bonus) code public/private boundary.github/workflows/repo-sync.yml mirrors public warpdotdev/warp ↔ private warpdotdev/warp-internal. Prior art for KH’s own {68.9} flip.Confirmed

Repo-name note: the blog and mempalace name the docs repo warpdotdev/docs; the local code repo’s docubot action checks out warpdotdev/gitbook. The backing repo was renamed on open-sourcing; the mechanism (token-authed cross-repo checkout → agent edit → cross-repo PR) is identical and is what KH already ported as its own docubot.yml + .github/actions/docubot/ + scripts/docubot/run-agent.ts.

D1.3 Verdict — did Warp engineer the cost down, and how?

Section titled “D1.3 Verdict — did Warp engineer the cost down, and how?”

Yes — by partitioning content, not by moving all of it. Two named mechanisms:

  1. docubot (the drift-compensation agent). The cost S299 framed as “a spec and the code it describes land in one PR; after the split they land in two repos and can drift” is only paid for content that crosses the boundary. For everything Warp moves out (customer-facing docs), docubot regenerates the affected pages from each PR’s diff and opens a docs-repo PR automatically. The drift is detected and compensated at source-change time, per-PR — exactly the role S299 §4 re-attributed to KH’s ported sync-source-docs + docubot. KH already owns this tool. So for derived/published docs the cost is genuinely engineered down to “an agent opens a second PR for you,” not “a human must remember to update two repos.”

  2. Keeping lockstep-mutated content in the code repo (the cost-avoidance, not cost-compensation, mechanism). Warp’s engineering specs never leave the code repo. They are not published, not derived, and they mutate in lockstep with code — so Warp pays zero cross-repo drift cost on them by simply not splitting them out. The only content Warp moves out is the published, code-derived surface, where docubot handles drift.

Therefore the cost is not unconditionally unavoidable. It is unavoidable only for content that is simultaneously (a) moved out of the code repo and (b) mutated in lockstep with code. The cardinality of that set is a routing decision, not a law of nature:

  • Under S299’s blanket “move everything under /docs out” override, the lockstep-mutated set forced across the boundary is large: the ledgers (written essentially every session), the active docs/specs/ID-N-* dirs (written by the spec-driven skills), and — newly surfaced in §D4 — the ontology CV register (a code-repo build input). Each one is a recurring double-commit / cross-repo-bridge tax.
  • Under the Warp-grounded routing (§D2), that set shrinks to ~empty: ledgers, active specs, ontology register, the 3 freshness-guarded reference/runbook docs, and generated artefacts all stay in the code repo (sanitised). Only durable-private (.planning/.archive/), ephemeral (continuation-prompts, old audits), and pure-published prose move out — and the published surface’s drift is docubot’s job.

Grounded revision of S299 §4’s verdict: the sentence “moving from sidecar→orthogonal trades zero-drift-by-construction for autonomy” stays true for whatever you choose to move out. What S299 got wrong is implying the trade is total and forced. Warp’s evidence (specs/ in-repo; docubot per-PR; 6 maintenance skills in the docs repo only) shows the honest framing is: route lockstep-mutated content to the code repo so you never pay the trade on it; move only what is published-derived (drift auto-compensated) or private-historical (never mutated again). The “unavoidable cost” is real but bounded by the routing taxonomy, and the taxonomy is the actual deliverable of {68.12}.

Ratified (S301, OQ-R10): this partitioned routing is adopted policy and amends the S294 blanket override. The §D2 table is the binding relocation plan.


D2 — Doc-type routing taxonomy (ratified S301 policy)

Section titled “D2 — Doc-type routing taxonomy (ratified S301 policy)”

Status: ratified (OQ-R10, S301 02/06/2026). This table is the adopted relocation policy and amends the S294 blanket “move everything out” override — it is no longer a recommendation.

Routing principle (Warp-grounded + SENSITIVITY-primary, amended by OQ-R12 S301):

SENSITIVITY is the PRIMARY axis (OQ-R12). If an artefact has recon/attack value (architecture, runbooks, deploy/secrets, internal decisions, API/structure maps, product strategy) it is INTERNAL-ONLY and must not be world-readable in the public repo — it routes to the private knowledge-hub-internal regardless of build-coupling. Only genuinely public-safe artefacts (post-{68.11} sanitisation) may stay in the public code repo. Build-coupling is the secondary axis, applied within the public-safe set. STAYS-IN-CODE-REPO if the artefact is public-safe and (build input — a generator/CI/test reads it — or lockstep-mutated by the SDLC loop). Build inputs that are NOT public-safe are minimised + sanitised to public-safe, or fed cross-repo (§D4, §0.2.4 of the implementation plan). MOVES-TO-knowledge-hub-internal if it is internal-only (recon value) or durable-private (historical IP) or dev-internal prose not on any build/loop path. PUBLISHED-TO-DOCS-SITE is an orthogonal axis: a code-repo doc can stay canonical in the code repo and be published to the site via the code→docs bridge (this is already how the reference/runbooks/ontology spaces work via sync-manifest.json). EPHEMERAL if point-in-time and safe to retire/delete after a window.

Destinations are not mutually exclusive with publication: “stays-in-code-repo + published” means canonical in code repo, surfaced read-only on the site.

Tree / doc-typeDestinationLifecycleSync direction (if it crosses code↔docs)Why
docs/reference/*.json ledgers (task-list, product-backlog, product-roadmap, product-retros, umbrellas) + mirrors (tasks/ roadmap/ backlog/ retros/)stays-in-code-repodurablenone (already deny-listed from docs-site)SDLC write-path; loop writes every session; ledger-cli + 4 roundtrip guards read them. Already never published.
docs/specs/ID-N-*/ active spec source dirs (RESEARCH/PRODUCT/TECH/PLAN)stays-in-code-repo (sanitised-public) — amended OQ-R12 (S301)durablecode→private-docs (ratified-only decisions render now on the GATED internal site)Raw spec source stays public (sanitised, {68.11}); its published decisions render moves WITH the docs-site to the private gated site.
docs/runbooks/**moves-to-knowledge-hub-internal (private, GATED site) — amended OQ-R12 (S301)durablen/a (internal site, in-repo)HIGH sensitivity — deploy/secrets/DB-rebuild/CI playbooks (onprem-secrets-migration, database-rebuild-runbook, production-setup-guide, github-environments). Recon/attack value → internal-only. The one freshness-guarded runbook (taxonomy-change-runbook.md) decouples to a path-manifest (§0.2.4 of the plan).
docs/ontology/01..32-*.md CV registerstays-in-code-repo (sanitised public-safe) + cross-repo published — amended OQ-R12 (S301)durablecode→private-docs (ontology pulled to the internal site)Build input04-content-type.md is the prebuild codegen source (§D4); moving it breaks bun build. Stays, but sanitise the go-to-market prose in 03-layer-vocabulary/14-bid-states (keep schema-visible keys+labels).
docs/reference/*.md freshness-guarded (data-entry-points.md, classification-architecture.md)moves-to-knowledge-hub-internal (private, GATED site) — amended OQ-R12 (S301)durablen/a (internal site)HIGH sensitivitydata-entry-points is an attack-surface map; classification-architecture is AI internals. The freshness guard decouples from their prose to a code-repo path-manifest (§0.2.4 of the plan), so no private prose is read in public CI.
docs/reference/*.md other (state-of-the-product, skill-routing-map, test-philosophy, ai-visibility-policy, ux-principles, …)moves-to-knowledge-hub-internal (private, GATED site) — amended OQ-R12 (S301)durablen/a (internal site)HIGH sensitivity — architecture/AI-strategy/roadmap recon. Loop/agents read them via the sibling KH_DOCS_DIR checkout.
docs/reference/classification-prompt.mdstays-in-code-repodurable (regenerated)noneGENERATED by sync:taxonomy (build output). Lives with its generator. (Public-safety: review — it is a generated prompt; confirm no sensitive prose in OQ-R12 follow-up.)
docs/reference/documentation-inventory.mdretire (§D3)Superseded by the Starlight autogenerated sidebar + Pagefind.
docs/generated/** (codebase-stats, mcp-inventory, type-drift-*)moves-to-knowledge-hub-internal (private, GATED site) — amended OQ-R12 (S301)durable (regenerated)n/a (internal site; regeneratable from code)HIGH sensitivitymcp-inventory = full API surface, codebase-stats = structure map. Regenerated artefacts; render on the internal site only.
docs/design/** (Warm Meridian spec/philosophy/identity.pdf/audit)stays-in-code-repo (public-safe) + published — amended OQ-R12 (S301)durablecode→private-docs (design to the internal site)LOW sensitivity — visual identity only. Public-safe; cited by CLAUDE.md + .claude/checks/.
docs/product-functionality/**moves-to-knowledge-hub-internal (private, GATED site) — amended OQ-R12 (S301)durablen/a (internal site)MOD–HIGH sensitivity — capabilities, AI-integration internals, governance, bid-management = product strategy + functional recon.
docs/themes/** (orchestration assessments, workspace plans)moves-to-docs-repodurable-privatenone (not a docs-site space)Dev-internal strategy IP; not published, not a build input.
docs/workflow-evaluation/** + docs/reference/workflow-evaluation/moves-to-docs-repodurable-archivenone20+ archived sessions read by evaluate-workflow/evaluate-findings. The whole evaluation lane relocates as a unit (writes product-retros.json — which stays, so the evaluator runs against the code repo’s ledger; see OQ-R4).
docs/continuation-prompts/** (handoffs + sNNN-worker-reports/)ephemeral (move-to-docs-repo archive, prune after window)ephemeralnonePoint-in-time session state. The active handoff is transient; historical ones are archive-only.
docs/audits/** (point-in-time reports + eval JSONs)moves-to-docs-repodurable-private (mostly ephemeral)noneHistorical record; client-eval JSONs are IP-sensitive.
docs/research/** (investigations incl. docs-site-rebuild-research.md, coolify evals)moves-to-docs-repodurable-privatenoneInternal decision research; point-in-time.
docs/operations/** (cutover/re-ingestion reports)moves-to-docs-repodurable-private (mostly ephemeral)noneInternal ops record.
docs/handover-guides/** (gdpr-data-export.md)moves-to-docs-repodurablenoneInternal operational handover.
docs/testing/test-data/**stays-in-code-repo if used as fixtures; else movesdurablenoneVerify fixture consumption before routing. (Note: test-data/templates/ CSP file is {68.5}’s job — coordinate, don’t double-handle.)
docs/testing/{e2e,uat}/**moves-to-docs-repo unless referenced by Playwright configmixednoneTest prose/plans; relocate only the non-build-input parts.
docs/database/**n/agitignored (.gitignore:112) — never tracked, never public. No action.
.planning/.archive/** (1,269 tracked files in HEAD; sparse-checkout omits from this worktree)moves-to-docs-repo + history-purgedurable-privatenoneThe single biggest IP + client-name concentration. Move at HEAD and strip from all code-repo history ({68.10}).
.planning/codebase/** (7 architecture docs)retireephemeralRETIRED per S299/Liam (GitNexus + ast-dataflow supersede). Do not carry over.
.planning/knip-baseline.txtstays-in-code-repodurablenoneCI knip-gate baseline — a build input.
docs-site/** (Astro project + Vercel deployment)moves-to-knowledge-hub-internal + GATED deploymentamended OQ-R12 (S301)durablecode→private-docs (pulls sanitised ontology + code-derived schema/mcp/api-routes via sync-source-docs)Internal KB site, not customer docs (Warp precedent does NOT apply — §0.2.1). Moves WITH the recon-valuable spaces it renders; deploy behind Vercel Deployment Protection (CONFIRMED enabled — §0.2.2a). The 6 docs workflows + 6 docs skills + run-skill.ts/docubot move with it.

Ephemeral vs durable, made explicit (per brief):

  • Ephemeral (retire/prune): .planning/codebase/ (retire now); docs/continuation-prompts/ (prune after a session window); most docs/audits/ + docs/operations/ point-in-time reports (archive then prune).
  • Durable-but-private (move, keep): .planning/.archive/, docs/themes/, docs/research/, docs/workflow-evaluation/, docs/handover-guides/.
  • Durable + published (stay in code repo, surface on site): docs/reference/**, docs/runbooks/**, docs/ontology/**, docs/generated/**, docs/design/**, ratified docs/specs/**.

Net effect of this routing: the lockstep-mutated set that crosses the boundary is ~empty (ledgers, specs, ontology, freshness docs, generated artefacts all stay) → the “unavoidable structural cost” (double-commit / split-brain) is collapsed to the rare session that also edits moved private corpus. This is the §D1 verdict applied.


D3 — Retire (not relocate) documentation-inventory.md + doc-freshness.test.ts

Section titled “D3 — Retire (not relocate) documentation-inventory.md + doc-freshness.test.ts”

These are two independent artefacts the brief bundles. doc-freshness.test.ts does not read documentation-inventory.md at all (confirmed — it reads data-entry-points.md, classification-architecture.md, runbooks/taxonomy-change-runbook.md). Treat them separately.

D3.1 documentation-inventory.md — retire; the Starlight sidebar IS the inventory

Section titled “D3.1 documentation-inventory.md — retire; the Starlight sidebar IS the inventory”

What supersedes it. docs-site/astro.config.mjs:126-147 defines the sidebar as five autogenerated spacesautogenerate: { directory: 'product-functionality' | 'ontology' | 'reference' | 'runbooks' | 'decisions' }. Starlight rebuilds this nav from the content tree on every build — a live, always-current index with zero hand-maintenance. Plus Pagefind full-text search (PRODUCT Inv-8) over every published page. The hand-maintained documentation-inventory.md carries a write-coupling tax: keep-docs-in-sync/SKILL.md (:157-159) mandates “add an entry to documentation-inventory.md in the same commit” on every new doc — drift-prone and strictly inferior to an autogenerated nav. Retire.

Every consumer to repoint/remove on retirement (load-bearing subset; the remaining hits are cosmetic spec/ledger/continuation-prompt mentions):

ConsumerHow it uses the inventoryAction
.claude/skills/keep-docs-in-sync/SKILL.md:142-159”consult before authoring; add an entry in the same commit” — the write-couplingRemove the consult + same-commit-append rule; replace with “the autogenerated sidebar is the index.”
.github/actions/docubot/prompt.txt:39-41”Inventory check: before drafting a NEW doc, consult documentation-inventory.mdReplace with “search the live site / Pagefind for an existing page.”
__tests__/skills/keep-docs-in-sync-shape.test.ts:18Names the inventory in the skill-shape contractUpdate the shape contract when the skill rule is removed (this guard test runs on every bun run test — will fail if the SKILL.md changes without it).
CLAUDE.md:136”Full inventory of all reference docs: documentation-inventory.mdRepoint to the docs-site URL / sidebar.
docs/reference/skill-routing-map.mdReference mentionRepoint or drop.

The S299 §1.4 note (“docubot reads documentation-inventory.md”) is the prompt.txt:39 consumer above — confirmed and enumerated.

D3.2 doc-freshness.test.ts — retiring it loses a real guarantee the site does not provide

Section titled “D3.2 doc-freshness.test.ts — retiring it loses a real guarantee the site does not provide”

What it currently guards (__tests__/validation/doc-freshness.test.ts): for three docs, it asserts the code paths they cite still exist on disk and that key source files contain expected symbols:

  • data-entry-points.md — 10 known entry-point files exist + are referenced; and a code scan that any app/api/lib/mcp/tools file inserting into content_items is documented (an allow-listed completeness check).
  • classification-architecture.mdlib/ai/classify.ts contains classifyContent; classify.py/layer_inference.py exist; File-Reference-table paths exist.
  • runbooks/taxonomy-change-runbook.md — references sync:taxonomy; the 3 generator scripts
    • Scripts/Generated-artefacts table paths exist.

What the docs-site build provides (docs-site/package.json:9): check-broken-links (internal doc↔doc links + external HTTP — check-broken-links.ts:1-18), check-token-parity (the 6-token Warm-Meridian CSS mirror, app globals.css ↔ docs-site warm-meridian.css), astro check (Astro components + TS types). None of these validate a doc→code-path reference. Pagefind/sidebar index pages; they do not check that scripts/kb_pipeline/pipeline.py cited in a doc still exists.

What is genuinely lost on retirement: the only guard that catches a reference/runbook doc citing a deleted/renamed source file, plus the content_items-INSERT completeness scan. This is fundamentally a code-repo concern (it needs the code tree), so it cannot move to the docs repo without a cross-repo code checkout.

Replacement guard — recommended (small): because the three guarded docs stay in the code repo under §D2, keep a slimmed code-repo guard that retains only the path-existence assertions (doc cites XX exists on disk) and drops anything coupled to documentation-inventory.md framing. Net: retire the name and the inventory-adjacent parts; preserve ~40 lines of path-existence + the content_items completeness scan as a lean reference-doc-paths.test.ts. If Liam prefers full retirement, the loss is bounded (3 low-churn docs; drift caught at review) — but it is a real loss, not a no-op. Do not relocate it to the docs repo (no code tree there). See OQ-R8.


D4 — Ontology sync/drift: today’s mechanism + the split-survival delta

Section titled “D4 — Ontology sync/drift: today’s mechanism + the split-survival delta”

Brownfield correction (Liam, mid-session): ontology sync is not green-field. It was designed and partially implemented as the WP6 Markdown Ontology Harness (S236–S238, branch content-items-investigation). D4 is therefore reframed as (1) what the mechanism is today and (2) what must change to survive the split — not a from-scratch design. Sources mined: docs/specs/wp6-ontology-harness/TECH.md (the harness spec, last verified 14/05/2026), verifier-reports/B1-md-vs-db-drift.md, investigations/INV-{1,2,3}-*.md; traced to ID-9; mempalace consulted (the WP6 wave trail is documented in TECH.md’s footer, which is the authoritative history).

D4.1 What the ontology sync/drift mechanism IS today (it does NOT mirror taxonomy-sync)

Section titled “D4.1 What the ontology sync/drift mechanism IS today (it does NOT mirror taxonomy-sync)”

The harness already exists and is wired end-to-end. Its shape (TECH.md §3 architecture diagram):

docs/ontology/*.md (32 CV register files; frontmatter Zod-contracted)
├── build-time path (predev + prebuild) ──▶ scripts/generate-content-type-values.ts
│ └─▶ lib/ontology/content-type-values.generated.ts (frozen tuple, client-safe)
│ └─▶ content-type-registry.ts ─▶ lib/validation/schemas.ts VALID_CONTENT_TYPES
├── server/test path ──▶ lib/ontology/loader.ts (sync fs read, Zod-validates all 32 at load)
│ └─▶ __tests__/lib/ontology/markdown-parity.test.ts
│ (asserts: markdown ↔ generated tuple ↔ live DB CHECK — 3-way lockstep)
└── future automated markdown→DB sync ──▶ scripts/ontology-sync/parse-flow.py (STUB, not run)
ConcernHow it works todayFile / citation
Source of truthThe markdown register docs/ontology/*.md is the “single source-of-truth artefact” (TECH.md §1). The live DB CHECK is its lockstep partner, not its source.TECH.md §1, lib/ontology/schemas.ts (OntologyCVSchema.strict())
Codegen (compensation A)generate-content-type-values.ts reads 04-content-type.md → writes the frozen TS tuple. Wired predev/prebuild/build:vercel → regenerated on every build (S237 codegen split 13f30993 resolved a Turbopack node:fs client-bundle leak).scripts/generate-content-type-values.ts, package.json:12-13,59, TECH.md §5.3
Drift guard (compensation B)markdown-parity.test.ts asserts 3-way set-equality (markdown register ↔ generated tuple ↔ live DB CHECK via taxonomy_snapshot.json). Any of the three drifting fails CI (bun run test).__tests__/lib/ontology/{markdown,form-type}-parity.test.ts, TECH.md §5.4,§5.3.6
DB-side oracleThe parity test reads scripts/tests/fixtures/taxonomy_snapshot.json content_types[] — which is refreshed by bun run sync:taxonomy. So ontology’s DB oracle piggybacks on taxonomy-sync’s snapshot regen.TECH.md §4, scripts/generate-taxonomy-snapshot.ts:76-114
Future markdown→DB auto-syncparse-flow.py is a typed cocoindex stub, deliberately NOT executed (needs a DB target table + migration, deferred to land with application_types, Q-OQR1-16).scripts/ontology-sync/parse-flow.py, TECH.md §5.5,§2
Why the guard is load-bearingThe B1 verifier found the hand-authored register drifted hard from the live DB on first authoring: 17/29 CVs needed changes, 1 CRITICAL (CV03 layer-vocabulary baseline values were entirely invented). The parity test is the compensating control for exactly this.verifier-reports/B1-md-vs-db-drift.md §1

Does it mirror taxonomy-sync? No — and it does not need to. The two have inverted sources of truth, which dictates opposite mechanisms:

taxonomy-sync.ymlontology harness (today)
Source of truthDB (taxonomy/layer tables)Markdown register (docs/ontology/*.md)
Mechanismregenerate-and-commit: repository_dispatchbun run sync:taxonomy regenerates DB-derived artefacts → commit + push main → HMAC callbackregenerate-at-build + fail-on-drift: build-time codegen (every build) + parity test (every CI run)
DirectionDB → repo artefacts (push)markdown → TS tuple (codegen); DB is a validated peer, not a sink
Needs a workflow?Yes (DB mutations happen outside git, so a workflow must pull them into the repo)No — the register is edited in git, so the codegen + test already see every change at build/CI time

Because taxonomy’s source (the DB) mutates outside git, it needs a workflow to pull changes back into the repo. Ontology’s source (the markdown) mutates inside git, so there is nothing to “sync back” — the codegen + parity test already compensate drift on every build/CI run. The honest finding: ontology already has an appropriate drift-compensation mechanism; it is a detect-and-block guard, not an auto-commit workflow, and that is correct for its inverted source-of-truth. The true taxonomy-sync analogue (a markdown→DB push) is the deferred cocoindex flow (parse-flow.py), not anything missing from the sync layer.

D4.2 What must CHANGE for it to survive the docs/code split (the delta)

Section titled “D4.2 What must CHANGE for it to survive the docs/code split (the delta)”

The harness has one load-bearing cross-boundary dependency: docs/ontology/*.md is read by three code-repo consumers — the build-time codegen (generate-content-type-values.ts, on the prebuild/predev critical path), the runtime/test loader (loader.ts), and the future cocoindex flow (parse-flow.py, which localfs.walk_dirs docs/ontology/). If the register moves to the docs repo under S299’s blanket “move everything out”:

  1. bun build / bun dev / build:vercel break — the codegen’s readFile(SOURCE) dangles. This is a build-coupling S299 missed, and it is worse than the docs-site ../docs dangle S299 did catch, because it sits on the app’s critical build path, not a separate docs build. Same class as sync-manifest.json:"source_root":"../docs".
  2. markdown-parity.test.ts + loader.ts breakbun run test can no longer find the register; the 3-way drift guard goes dark.
  3. The future cocoindex flow would need a cross-repo source root before it can ever run.

The split-survival delta is therefore one routing decision, not new tooling: the ontology CV register is simultaneously a code build input, a code test fixture, and (future) a code-side cocoindex source with a live-DB lockstep contract. It is not pure-published prose. → docs/ontology/ STAYS in the code repo (sanitised), routed exactly like the ledgers and active specs in §D2. With that single decision:

  • The entire harness (codegen + loader + parity test + the deferred cocoindex flow) keeps working unchanged — every consumer and its source stay in the code repo.
  • No new workflow is required for split-survival. The existing build-codegen + parity-test mechanism is already split-immune once the register stays put.
  • No docs→code reverse bridge, no cross-repo token is introduced (the rejected alternative — moving the register out — would create the system’s only docs→code sync direction and still leave the prebuild codegen needing a cross-repo source; strictly more fragile, zero benefit).

Ratified enhancement (S301, OQ-R11): add an ontology-sync.yml that runs the codegen + parity on push to docs/ontology/**, catching register drift at edit time rather than on the next unrelated build/CI run. This is not required for split-survival (the parity test already runs on every bun run test in CI) but Liam adopted it as an edit-time early-warning. The same ruling adds docs/ontology/** to the code→docs publish pull set (§D4.3).

D4.3 Ontology-derived content reaching the docs-site (after the split)

Section titled “D4.3 Ontology-derived content reaching the docs-site (after the split)”

The docs-site already publishes an ontology space (sync-manifest.json:6, astro.config.mjs:131-134) by syncing ../docs/ontology. With the register staying in the code repo, the published view reaches the docs-site (in the docs repo) through the same code→docs bridge S299 §3 already specifies for sync-source-docs’s generated surfaces (schema-quick-reference/mcp-inventory/api-routes): the docs-site build cross-checks-out the code repo and pulls docs/ontology/**. Specify (amended OQ-R12 S-B): the docs-site now lives in knowledge-hub-internal; its build pulls sanitised docs/ontology/** (the one public-safe build-input space that stays) plus the code-derived schema/mcp-inventory/ api-routes surfaces from the public code repo via sync-source-docs + the R4 GitHub App. The canonical ontology register never leaves the public code repo; its rendered form is published on the gated internal site. (Under S-B, reference/generated themselves move private, so they are local to the docs-site, not cross-repo-pulled.) Asymmetry holds for the staying build-inputs: canonical-in-code, surfaced-on-the-gated-site.


§6′ — Open Questions (all ratified/closed, S301 02/06/2026)

Section titled “§6′ — Open Questions (all ratified/closed, S301 02/06/2026)”

Status legend: RATIFIED (Liam adopted the disposition) · RATIFIED-IN-PRINCIPLE (adopted; implementation detail deferred) · RESOLVED (dissolved by another ruling). All 12 are closed.

OQStatus (S301)Ratified disposition
OQ-R1 — sibling-checkout + KH_DOCS_DIR vs loop-from-docs-repoRATIFIED-IN-PRINCIPLESibling-checkout + KH_DOCS_DIR adopted; precise env-threading deferred to implementation. Scope is small because build inputs (ledgers/specs/ontology) stay in the code repo under §D2.
OQ-R2 — cross-repo auth: PAT vs GitHub AppRATIFIED-IN-PRINCIPLEGitHub App adopted for cross-repo auth (the code→docs publish bridge + the R4 code→ledger evaluator write-back share this one App token); detail deferred to implementation.
OQ-R3bun run test ownership of the 4 ledger roundtrip guards + doc-freshness.test.tsRESOLVED (by R10)Ledgers stay in the code repo → the 4 roundtrip guards stay put (no move). doc-freshness.test.ts retires, replaced by the slim reference-doc-paths.test.ts (R8). Nothing relocates to the docs repo.
OQ-R4 — evaluation-lane relocation + product-retros.json homeRATIFIEDproduct-retros.json stays in the code repo with the other 3 ledgers. The workflow-evaluation/ corpus + evaluate-* skills relocate to the docs repo and become a code→ledger cross-repo writer, using the same GitHub App token as the docs bridge (R2). No longer needs Liam.
OQ-R5 — double-commit acceptanceRESOLVED (by R10)Dissolved. Under §D2 the lockstep-mutated set stays in the code repo, so a typical session produces only a code commit; double-commit occurs only when a session also edits moved private corpus (rare).
OQ-R6docs/runbooks/ mirrored back for on-callRESOLVED (by R10)Moot — runbooks stay in the code repo (build/CI-cited). No mirroring needed.
OQ-R7 — ontology CV register homeRATIFIEDdocs/ontology/** stays in the code repo — it is the WP6 harness’s build input + test fixture + future cocoindex source with a live-DB lockstep contract. Moving it out breaks bun build AND markdown-parity.test.ts; the whole harness survives the split unchanged when it stays.
OQ-R8doc-freshness replacement guardRATIFIEDRetire doc-freshness.test.ts; keep a slim code-repo reference-doc-paths.test.ts carrying the path-existence assertions + the content_items-INSERT completeness scan. (§D3.2)
OQ-R9 — inventory write-coupling removalRATIFIEDThe autogenerated Starlight sidebar + Pagefind replace documentation-inventory.md; remove the “add an entry in the same commit” rule from keep-docs-in-sync/SKILL.md + docubot/prompt.txt + update keep-docs-in-sync-shape.test.ts. (§D3.1)
OQ-R10 — the routing principle (the load-bearing decision)RATIFIEDPartitioned routing adopted, amending the S294 blanket override: build inputs + lockstep-mutated SDLC state stay in the code repo (sanitised); only durable-private + ephemeral + pure-published-prose move out. The §D2 table is now policy. (§D1, §D2)
OQ-R11ontology-sync.yml + publish surfaceRATIFIEDAdd ontology-sync.yml (codegen + parity on push to docs/ontology/**) for edit-time drift feedback, and add docs/ontology/** to the code→docs publish pull set so the rendered register stays on the docs-site. Both adopted (not optional). (§D4.2-D4.3)
OQ-R12 — docs-site + published-corpus sensitivity routing (security re-examination)RATIFIED (Option S-B)SENSITIVITY is a PRIMARY routing axis. docs-site (internal KB — Warp precedent does NOT apply) + reference, runbooks, specs→decisions render, product-functionality, generatedmove to knowledge-hub-internal, GATED Vercel deployment. ontology STAYS (sanitised public-safe build input + cross-repo published); design STAYS (public-safe); ledgers + raw spec source STAY (sanitised-public — no ledger-write-path parameterisation). S299 §3 code→private-docs publish bridge re-added (security-justified) via the R4 GitHub App. Vercel Deployment Protection CONFIRMED enabled (present-tense exposure closed). Per-row §D2 amendments carry amended OQ-R12 (S301). Phased design: RELOCATION-IMPLEMENTATION-PLAN.md §0.2 + §1 (Option S-B).

OQ-R10 was the load-bearing decision and it is ratified: the S294 blanket “move everything out” override is amended to the partitioned §D2 routing. The lockstep-mutated rows (ledgers, specs, ontology, freshness docs, generated artefacts) stay in the code repo (sanitised) and publish to the site via the code→docs bridge, which collapses the “unavoidable structural cost” to the rare session that also edits moved private corpus. The companion build-breakage fixes the ruling requires are tracked in §D4.2 (ontology source) and S299 §1.3 (docs-site ../docs co-relocation). Implementation (Phase-0 design) is deferred to a separate go-ahead.


Primary (this investigation):

  • Warp blog — Open-sourcing our docs and the agents that maintain them, https://www.warp.dev/blog/open-sourcing-our-docs-and-the-agents-that-maintain-them.
  • Local Warp code repo /Users/liamj/Documents/development/Warp: .github/actions/docubot/action.yml:30 (cross-repo checkout of warpdotdev/gitbook), .github/workflows/docubot_reply_to_comment.yml, .github/actions/docubot/prompt.txt, .github/workflows/repo-sync.yml (public↔private code mirror), .agents/skills/ (20 engineering skills, no docs skills), top-level specs/ (specs in code repo).
  • Mempalace (default-wing search; wing filter known-broken): prior KH research doc docs/research/docs-site-rebuild-research.md (S51, 716 lines) — Warp’s 6 docs skills at warpdotdev/docs/.agents/skills/ (24 total) + docubot 7-step composite action.

Ontology harness — prior work mined for D4 (brownfield):

  • docs/specs/wp6-ontology-harness/TECH.md (the WP6 Markdown Ontology Harness spec; §1 goals, §3 architecture, §5.3 codegen, §5.4 parity test, §5.5 cocoindex stub; S236–S238 wave trail in the footer is the authoritative history).
  • docs/specs/wp6-ontology-harness/verifier-reports/B1-md-vs-db-drift.md (§1: 17/29 CVs drifted, 1 CRITICAL — the evidence the parity guard exists to catch).
  • docs/specs/wp6-ontology-harness/investigations/INV-{1,2,3}-*.md; traced to ID-9.

KH codebase (verified this session):

  • scripts/generate-content-type-values.ts (ontology generator; source docs/ontology/04-content-type.md), package.json:12-13,15,59 (predev/prebuild/ build:vercel wiring), __tests__/lib/ontology/{markdown,form-type}-parity.test.ts, lib/ontology/{loader,schemas,content-type-registry}.ts, scripts/ontology-sync/parse-flow.py (cocoindex stub, not executed).
  • .github/workflows/taxonomy-sync.yml (the contrasting auto-commit model; ontology does NOT mirror it — §D4.1).
  • docs-site/astro.config.mjs:126-147 (autogenerated 5-space sidebar), docs-site/package.json:9,13-14, docs-site/scripts/check-broken-links.ts, docs-site/scripts/check-token-parity.ts, docs-site/sync-manifest.json.
  • __tests__/validation/doc-freshness.test.ts, .claude/skills/keep-docs-in-sync/SKILL.md:142-159, .github/actions/docubot/prompt.txt:39-41, __tests__/skills/keep-docs-in-sync-shape.test.ts:18, CLAUDE.md:136.

Prior art (inherited from S299, unchanged): Passo.uno docs-as-code topologies (sidecar / orthogonal / federated / specialised); Antora multi-repo; withastro/starlight #2844, #956 (multi-repo not first-class); docusaurus #6086; Mintlify cross-repo checkout.