OMK storage layout v2
Scope: the canonical project and machine storage contract. Paths are generated by
src/evidence/storage/layout.ts; product modules must not assemble.omkroots themselves. This layout changes storage only and does not change report schemas, scoring, prompts, statistics, or length debiasing.
Principles
- Top-level names follow user-visible product domains:
eval,doctor, andobserve. - One durable measurement record owns one self-contained directory.
report.jsonis authoritative; rebuildable views live inderived/. - Lifecycle is visible in the path. Durable evidence, observations, governance, backups, and rebuildable
statedo not share a flat namespace. - Project-bound evidence defaults to
<project>/.omk. Machine tools, caches, tunnels, materialized trees, and cross-project indexes exist only under globalstate/. - Identity comes from report IDs and content digests, never from an absolute path. Moving a record does not change its report JSON or digest.
Project layout
.omk/
├── .gitignore
├── eval/
│ └── <record-id>/
│ ├── manifest.json
│ ├── report.json
│ └── derived/
│ ├── graph.json
│ └── card.md
├── doctor/
│ └── <record-id>/
│ ├── manifest.json
│ ├── report.json
│ └── derived/
│ ├── graph.json
│ └── card.md
├── observe/
│ ├── health/
│ │ └── <record-id>/
│ │ ├── manifest.json
│ │ └── report.json
│ ├── inbox/
│ │ ├── reports/
│ │ ├── captures/
│ │ └── review-state.json
│ ├── drafts/
│ └── archive/
│ └── source-records/
├── backups/
│ └── doctor-fix/
└── state/
├── jobs/
├── locks/
└── tmp/<record-id> is the collision-safe filesystem identity of one report bundle. A manifest carries the public report/run identity. Evaluation Core bundles also retain their sealed plan and execution/evaluation/analysis documents beside report.json; those documents remain part of the authenticated bundle.
The directory-skill authoring convention <skill>/.omk/eval-samples.{json,yaml} is intentionally unchanged.
Machine layout
OMK_HOME defaults to ~/.oh-my-knowledge and relocates this whole tree:
~/.oh-my-knowledge/
├── eval/
├── doctor/
├── observe/
├── backups/
└── state/
├── cache/
├── tools/
├── tunnels/
├── trees/
├── isolated-cwd/
│ └── resolved-inputs/
│ └── content/
├── artifact-index/
├── jobs/
├── locks/
└── tmp/
└── resource-leases/Project and machine durable data use the same domains. Machine-specific material never belongs in project .omk. Resolver-owned input copies live under state/isolated-cwd/resolved-inputs/; run-scoped resource copies and overlays live under state/tmp/resource-leases/ and are removed when their lease closes. Original Codex, Claude, and DSH traces stay at their source; OMK reads them rather than copying them into a project by default.
Lifecycle and Git policy
| Path | Meaning | Deleted by default? | Project Git policy |
|---|---|---|---|
eval/ | A/B evidence and release decisions | No | ignored |
doctor/ | skill health reports | No | ignored |
observe/health/ | health aggregated from real traces | No | ignored |
observe/inbox/ | candidate observations and human review state | No | ignored; may be sensitive |
observe/drafts/ | sample drafts derived from observations | No | ignored |
observe/archive/ | immutable source-record sidecars referenced by inbox reports | No | ignored; may be sensitive |
backups/ | recovery copies made before automatic edits | No | ignored |
state/ | jobs, locks, temporary files, and global rebuildable caches | Yes | ignored |
omk init writes an internal .omk/.gitignore that ignores eval/, doctor/, observe/, backups/, and state/, while leaving .gitignore trackable.
Compatibility boundary
File locks recover only an old owner proven to have exited on the local host. Empty or malformed owner metadata can belong to a live process paused immediately after exclusive creation; OMK preserves it and reports contention. Remove an unknown-owner orphan manually only after establishing that no writer remains.
Exclusive JSON publication requires same-directory hard-link support; replacement requires atomic rename. Filesystems without these capabilities (including some removable or network filesystems) fail explicitly and remove staging files. OMK does not fall back to publishing partial bytes. This capability boundary has not been tested on physical exFAT or NAS devices.
The v2 project-runtime tree is the only supported .omk layout. OMK neither reads old .omk roots nor provides a migration command for that tree, and never moves or deletes its old data automatically. Existing old .omk data remains untouched but invisible to v2 readers; users may back it up or remove it explicitly. Evaluation Core bundles use manifest v2 and report.json only. The explicitly selected knowledge workspace below has its own current versioned contracts.
Explicit knowledge workspace
The user chooses this workspace through settings or --workspace; it is separate from the project-runtime tree above. items/<identity-digest>.json uses knowledge-item-history v2. entities/<analysis-id>.json uses entity-analysis-history v2 with immutable revisions, exact source bindings, and write receipts. extraction-runs/<run-id>.json uses knowledge-extraction-run v5 for each invocation's system/input digests and source bindings, admission facts and stable write intents. Complete returned executor JSON outcomes are immutable sidecars at extraction-runs/outcomes/<run-id>/<attempt-id>.json, referenced by identity and digest; raw failure/refusal and usage flags are retained. library/<object-id>.json uses knowledge-library-object-history v1 to retain confirmed cross-window source links and organization history without copying knowledge bodies; see the library contract. Sources, topic tags, and artifact versions retain their own contracts. entity-links/<review-id>.json independently uses entity-link-invocation-history v1 for confirmed requests and invocation lifecycle, complete returned executor outcomes and failure evidence, immutable human decisions and recoverable library intent/receipts; see the cross-window review journal.
Human run sealing is a separate versioned disposition, not a supported legacy reader or migration. extraction-runs/seals/<current|legacy>/<run-id>/intent.json uses knowledge-extraction-seal-intent v1 and binds the declared operation/actor/reason, original raw-manifest SHA-256, and exact raw sidecar inventory. Its evidence/manifest.json and evidence/outcomes/<attempt-id>.json preserve byte sequences without normalization. Durable intent/copies precede the final identity check under .knowledge-write.lock and atomic publication of a knowledge-extraction-seal-marker v1 at the original manifest path, which remains occupied. Pending intent is not sealed; unknown acknowledgements preserve disk facts and require identical-operation replay. Execution/recovery refuse pending or sealed records; manifest projections still disclose pending dispositions. Explicit sealed-runs queries and quality v4 show human disposition with execution unknown; listings do not renew native-integrity or durability claims. The eligibility, offline declaration, capacity and old-process limits are specified in current entity storage contracts. No automatic unseal, call, refund, historical rescoring, or user-data migration occurs.
New automatic-extraction permissions can record the explicit generation policy and conversation-invocations/v1 ledger identity under the existing Schema v1. Immutable auto-extraction/attempt-<permission-id>-<attempt-id>.json receipts bind permission/run/attempt/request identities and any token reservation. They are exclusively published and fsynced before dispatch; mutable call/token counters reconcile from the ledger without refunds. Unpublished atomic staging files are not receipts. Each published invocation can have one immutable processing fact at auto-extraction/cooldowns/<thread-digest>-<run-id>-<attempt-id>.json, binding permission/run/attempt/request/source/policy identities and the native outcome reference. It records no-cooldown, required or invalid; the directory is bounded by the invocation-receipt count and 3000 entries. The post-archive hook records the first observed deadline before backoff; status, enable and dispatch reconcile missing facts from original archived outcomes, without extending an existing fact's timestamp after a lost acknowledgement. Valid known waits apply across permissions, while invalid values stop only their original permission and do not permanently block a fresh explicit grant. The state durably derives cooldown deadlines; local scheduling and actual dispatch both enforce them. Late results publish their original fact without rewriting a different owner, whose own gate reconciles the known wait. Dispatch rechecks abort and expiry after durable reservation; crossing the deadline during fsync blocks the effect without refunding that reservation. Limits accumulate across windows in that 24-hour grant. Existing permissions without a policy retain single-invocation authority and are not expanded by new defaults.
Source archives/deletion, run metadata/outcomes, entity and knowledge histories, topic tags, confirmed library links, automation state, and carrier publication share .knowledge-write.lock. Carrier final selection validation and publication stay inside that boundary; the complete composed tree passes capacity checks before publication, and failed staging is removed. Lock contention reports knowledge_workspace_busy. Only proven exited local owners are recovered, and storage-directory symlink redirects are rejected. File Schema versions are separate from prompt/wire/pipeline provenance. Current domain-response, strict and authored prompt-json identities come from the runtime-generated contract reference. Different prompt and wire identities do not share quality conclusions. Reading or idempotently resuming a supported run preserves its evidence without model dispatch or result upgrades; see current entity storage contracts.
Former runs/ v4 files are not read as supported runs, migrated or deleted. Only explicit opaque human sealing may preserve their raw bytes and replace their original path with the independent marker above. Their run details, resume, conversation/project batches and quality statistics are unavailable in the v5 reader. Existing current source snapshots, entity history v2, knowledge history v2 and their bindings remain readable in the same workspace; no empty-workspace replacement is required. Entity history v1 and unsupported run formats remain rejected, without compatibility readers. Newly extracted entities never automatically take over old knowledge bindings. Stored files can contain private excerpts and must be managed as local user data; they are not repository source assets.
Why these names
There is no top-level runs: it suggests disposable execution state, while evaluation and doctor records are durable evidence. There is no top-level measurements: it obscures the CLI domain users already know. There is no top-level observations: health reports and reviewable observations are sibling pipelines under the shared observe product domain. derived is used instead of projections because the directory holds rebuildable materializations owned by one authoritative report, not a distinct product domain.