Corpus layout
Every second-level content dir name is declared once in scripts/lib/layout.py (SEGMENTS). Scripts compose paths through that module — re-spelling "evidence/claims" at a call site is the bug class this module exists to kill. layout.seg() raises on undeclared names, so a new dir must be added to SEGMENTS first (plus the coordination points in "Adding a directory" below).
Corpus root resolution is fabric_config.CORPUS_ROOT (VAULT_ROOT is a legacy alias for the same value).
The tree
| Path | Artifact | Producer(s) | Consumers |
|---|---|---|---|
evidence/raw/<slug>/ | immutable captures (docs + git/ PRs/issues/commits + chats/ sessions + obsidian/ harvests) | capture, capture-git, capture-chat, hooks | ingest (--changed), threads index, lint SOURCE-DRIFT, review --verify-locators |
evidence/raw/<slug>/git/pr-N.md | kind: pr-record source (github route: source_repo, pr, pr_state, merged_at; thread graph node) | capture-git | ingest --changed, threads index |
evidence/raw/<slug>/git/issue-N.md | issues (same shape as pr-record minus merge fields) | capture-git | ingest --changed, threads index |
evidence/raw/<slug>/git/commit-<sha>.md | kind: commit source (local route: sha + date + message body, metadata only) | capture-git | ingest --changed |
evidence/raw/<slug>/chats/session-*.md | kind: chat-session source (session, harness, session_started, files_touched, related_sessions) | capture-chat | ingest --changed, threads index, mine chats |
evidence/raw/<slug>/issues/issue-N.md | kind: issue-record source (tracker capture, #176 — issue, issue_state, closed_at; the rationale channel) | capture issues | ingest --changed, threads index, query lineage |
evidence/raw/<scope>-okf/ | imported OKF bundles | okf import | ingest --pending <scope>-okf |
evidence/sources/src-*.md | source records (sha256, resource locator) | ingest, okf import | review, propose-domains, lint, threads |
evidence/source-summaries/sum-*.md | faithful summaries with locators | ingest | retrieval, lint SOURCE-EMPTY |
evidence/claims/claim-<slug>-NNN.md | atomic claims with source_refs | ingest | query, context, synthesize, export, lint, judgment, embed index |
evidence/insights/ | chat-mined insight pages (type: synthesis) | mine-chats | review scan |
evidence/traces/change-sets/<date>-<slug>/ | staging manifests + diffs (human gate) | ingest | apply-changeset, sync PR body |
evidence/traces/wiki-runs/ | wiki-generation run checkpoints | wiki-generate | resume protocol |
evidence/_inbox/<scope>-okf/ | quarantine for foreign-bundle content needing review | okf import | human |
evidence/experiments/ | typed experiment records (with baselines) | — (reserved; policy + template exist) | lint, sync plane |
patterns/ + patterns/_inbox/ + patterns/_rejected/ | canonical patterns; staged candidates; rejection tombstones | mine-chats --propose (staging), promote-patterns --apply, promote | mining suppression, context, gate |
anti-patterns/ | canonical anti-patterns (type: anti-pattern) | promote-patterns --apply | promote.py, lint, retrieval |
skills/ | durable procedures promoted as fabric skills | promotion pipeline | context |
concepts/ | unbound concepts (declares no ontology domain) | synthesize | export, harvest-questions, retrieval |
domains/<name>/concepts/ | domain-bound concepts (S1 homes) | synthesize, relocate-concepts | export, harvest-questions, retrieval |
domains/<name>/questions/ | domain-bound promoted questions (S1 homes) | promote-questions | query gaps, gate |
domains/<name>/syntheses/ | reserved (S1 trio; query --save routes here when domain-bound) | query --save (reserved) | humans |
domains/ontology.md | domain vocabulary (human-gated merges) | promote-domains | domain detection, lint scope |
projects/<slug>/ | namespace pages: README, decisions/, experience-events/ee-*.md, commitments/, receipts/ | bootstrap-project, log-experience, wf context | mine-promotions, context precedence, lint SCOPE |
registry/catalog.json | page index (derived) | rebuild-index | query, context, dispatch status |
registry/threads.json | PR/issue/chat thread graph (derived) | rebuild-index | query, thread, mining |
registry/log.md | append-only operation timeline (OKF §9) | ingest, promote, okf import, sync | lint §9, doctor |
registry/promotions/ | promotion dossiers (human-gated) | mine-promotions | promote, gate |
registry/effects/*.effects.json | judged-effect verdict artifacts (machine, never beside pages) | verify-effects | ingest agent |
registry/receipts/ | context delivery receipts | wf context --write-receipt | gate --deliveries, mining |
registry/pending-gate.md | cached gate report for session start | wf gate (via hooks) | agents |
registry/conflicts/ | sync conflict records | sync pull | lint SYNC-CONFLICT |
registry/question-proposals/ | harvested open questions (gated) | harvest-questions | promote-questions |
registry/wiki-graph.json | machine edge layer behind the wiki | export | machine contract |
registry/wiki-export-manifest.json | obsidian export ledger | obsidian bridge | harvest-before-export |
global/entities/ | entity index pages (derived, gitignored) | build-entity-index | dispatch status |
global/graphs/ | per-repo graphify graphs + hashes | graphify-bridge | --diff staleness, deep dives |
syntheses/ | saved query answers (excluded from retrieval) | query --save | humans |
questions/ | promoted question pages (open → answered) | promote-questions | query gaps, gate |
wiki/ | human-facing generated wiki (output vault) | export-wiki, wiki-generate | humans / Obsidian |
Naming prefixes (the join contract)
src- / sum- / claim-<raw-rel-slug> (≤80 chars, shared by layout.claims_for_source) / ee- / pattern- / anti-pattern- / concept- / promotion- / tombstone- / entity- / question- / change-set- / receipt- — declared in layout.PREFIXES. Producers and consumers both derive slugs through layout helpers; the claim↔source join depends on claim- + the raw rel path, so raw paths under evidence/raw/ should never be renamed casually.
Rules
- Raw is immutable —
evidence/raw/is never edited in place; re-capture. - Machine artifacts never sit beside pages — only
.mdpages live in content dirs; json/verdict artifacts go toregistry/subdirs (effects, receipts, indexes)..last-capturemarkers inside raw are the one sanctioned exception (state for the sha256-gated capture loop). - Immutable vs derived: raw/ + sources/ = recorded evidence; claims/ + concepts/ = derived atoms; registry/ + global/entities = derived indexes. Derived content is regenerable; recorded evidence is not.
- Type decides the dir — anti-pattern candidates in
patterns/_inbox/apply toanti-patterns/(notpatterns/); promoted dossiers land inregistry/promotions/. - Sync planes (
sync_lib/policy.py): evidence-plane (raw, sources, summaries, insights, traces, inbox) vs atom-plane (claims, patterns, concepts, projects). Layout changes must keep both classified.
Adding a directory
coordination checklist (all deterministic, 0 tokens):
layout.SEGMENTS(+ accessor +PREFIXESif the page type has an id shape)scripts/cmd/lint.py—VALID_TYPES(if a new page type),CONCEPT_DIR_PREFIXESscripts/lib/wf_common.py—SKIP_PARTSif non-conceptscripts/lib/sync_lib/policy.py— plane classificationscripts/cmd/rebuild-index.py—scan_vaultcategoryscripts/harness/hooks.py—_FABRIC_OUTPUT_DIRS(drift capture matching)scripts/okf-base.yaml— okflint per-type fields; export scope roots inscripts/cmd/okf_export.py
History
- 2026-10-02 (#157 S3 decision):
evidence/plane naming — the name stays; the plane separation stays in policy. Claims (canonical atoms) live under "evidence" but classify to the atom-plane (sync_lib/policy.py), and every consumer derives paths throughlayout— the directory name is physical, not semantic, and never user-facing. Tier-3 re-layout (claims →claims/at the corpus root) remains a one-constant change + the coordination checklist, parked until a real driver appears: the move churns 6284 catalog paths, 16 seam refs, and every existing OKF bundle/clone for zero retrieval benefit (path-scope is never shown to users; classification already disambiguates the planes). - 2026-10-01 (S1/#159): physical domain homes —
domains/<domain>/{concepts,questions,syntheses}; binding is frontmatterdomain:(canonicalized through the ontology alias map); relocation viascripts/cmd/relocate-concepts.py(deterministic, idempotent). - 2026-10-01: layout.py introduced (Tier-2 single truth); anti-pattern apply-path bug fixed (candidates were unconditionally dropped into patterns/); promote-queue update made fail-soft; effects verdicts moved to registry/effects/; canonical layout doc created (this file).