OpenMind v2 Phase 2: Workspace Asset, Revision, Segment & Evidence foundation#8
Merged
Merged
Conversation
…foundation (#8) Build the canonical engineering-content model beneath the retrieval index: every indexed file becomes an Asset, every observed version an immutable Revision, each revision divided into deterministic Segments, each with source-locatable Evidence. Chroma becomes a projection; the durable source of identity is SQLite + an immutable content-addressed blob store. Schema - v0003_asset_model migration: assets / asset_revisions / segments / evidence + indexes; FK cascade to projects; (asset_id, content_hash) intentionally NOT unique so an A->B->A revert is representable. v0001/v0002 untouched (frozen). Head 2 -> 3; a Phase 1 database upgrades additively with no data loss. Content store (openmind/content_store.py) - Immutable SHA-256 content-addressed blobs at data/<ws>/objects/<2hex>/<hash>; atomic tmp+os.replace (unique temp per call), reuse, corruption raises ContentCorruption. The DB stores only the hash, never an absolute path. Segmentation (openmind/segmentation.py) - Deterministic Segment + Evidence drafts sharing boundary primitives with rag.chunk_file (javaparse + line-range split) which is left BYTE-FOR-BYTE unchanged, so retrieval, chunk ids and search response cannot regress. Java: type (derived summary) / method / constructor; generic: line-range. Evidence content_hash is recomputable from the immutable blob by line range. Ingestion (openmind/jobs.py) - db.commit_revision is the single transactional writer: no partial revision ever becomes current. The asset revision commits BEFORE the file_index row, so a crash in that window re-indexes the file rather than stranding a stale asset. - Unchanged re-ingest creates no revision and never re-embeds; a Phase 1 workspace backfills Assets on first ingest WITHOUT re-embedding (asserted with an embedding-call spy). Removed files are marked removed (history preserved); reappearing keys reactivate the same Asset. - Filtered ingests (asset add / ingest --path) now skip whole-project artifact rebuilds and scope the prune to the filter root, fixing a latent bug where a subtree ingest would corrupt the glossary/structure from a partial file set. - Additive progress counters; local Git HEAD provenance (no subprocess/network). Service + adapters - AssetService (runtime.assets, ServiceContainer.assets): workspace-scoped reads, snapshot-based evidence recovery (available/corrupt vs matches/changed/missing), single-file sync. Typed errors AssetNotFound / RevisionNotFound / SegmentNotFound / EvidenceNotFound / ContentCorruption. - CLI `asset` group (list/show/revisions/segments/evidence/add) + asset counts on `status`. Additive read-only REST under /projects/{id}/...; four additive read-only MCP tools. The nine core MCP tools, all REST routes and the /projects naming are unchanged. Lifecycle - terminate clears Asset rows + content blobs (keeps workspace + paths); delete cascades Asset rows and reclaims blobs with the data dir. Delete-drain and janitor-race fixes preserved. Version / compatibility - Runtime version -> 1.2.0-dev (single constant). The .openmind artifact schema stays frozen at 1.1.0 (the Asset model is not exported yet). Skill bridge, glossary, structure, RAG search and existing databases all unchanged. Tests / CI / docs - New acceptance scripts: verify_content_store, verify_asset_model, verify_asset_cli, verify_asset_adapters (registered in run_acceptance; core suite now 28 scripts, all green). CI full gate + cross-platform smoke expanded with content-store, migration-to-v0003, and asset CLI/evidence checks. - docs/v2/phase-2-asset-model.md design doc; README, docs/cli.md and docs/database-migrations.md updated.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Phase 2 builds the canonical engineering-content foundation every later v2 capability needs. It transforms the storage model from paths + file index + vector chunks into the beginning of the v2 canonical model:
Chroma becomes a retrieval projection; the durable source of content identity is SQLite plus an immutable SHA-256 content-addressed blob store. This is a data-model foundation, not a feature release — no document parsing, Claim/Relation tables, Knowledge Graph or traceability (all still deferred).
Built directly on the Phase 1 boundaries (runtime, service container, migration runner, typed errors, CLI/FastAPI/MCP adapters); Phase 1 is not rewritten.
Schema (migration
v0003_asset_model)assets/asset_revisions/segments/evidence+ indexes; FK cascade toprojects;(asset_id, content_hash)intentionally not unique so an A→B→A revert is representable.v0001/v0002untouched (frozen, checksummed). Head 2 → 3. A Phase 1 database upgrades additively with no data loss; existing files backfill their Assets on the next ingest without re-embedding.Highlights
content_store.py): atomic writes, blob reuse, SHA-256 identity, explicit corruption detection; DB stores only the hash.segmentation.py) that leavesrag.chunk_filebyte-for-byte unchanged — retrieval, chunk ids and the search response cannot regress.db.commit_revisionis the single writer; no partial revision ever becomes current. The revision commits before thefile_indexrow, so a crash in that window re-indexes the file instead of stranding a stale Asset (fix from the adversarial review below).asset add/ingest --path) skip whole-project artifact rebuilds and scope the prune — fixing a latent bug where a subtree ingest corrupted the glossary from a partial file set. Full ingest is unchanged.AssetService(runtime.assets), CLIassetgroup +statuscounts, additive read-only REST under/projects/{id}/…, four additive read-only MCP tools. The nine core MCP tools, all REST routes and the/projectsnaming are unchanged.Measured incremental behavior (fixture, offline embedder)
removed; revisions/segments/evidence/blobs preservedCompatibility
REST routes ✓ · MCP 9 core tools ✓ ·
.openmindschema 1.1.0 (frozen; Asset model not exported yet) ✓ · skill bridge ✓ · glossary / structure / RAG search ✓ · existing databases migrate without loss ✓. Runtime version →1.2.0-dev(single constant); build is not labelled 2.0.0.Testing
Four new acceptance scripts registered in
scripts/run_acceptance.pyand gated in CI:verify_content_store,verify_asset_model,verify_asset_cli,verify_asset_adapters. Core suite now 28 scripts, all green (baseline was 24); local-tier delete-responsiveness 8/8. CI full gate + cross-platform smoke expanded with content-store, migration-to-v0003 and asset CLI/evidence checks. No paid API; offline hashing embedder throughout.Reviewer notes
An adversarial review (5 dimensions → per-finding refutation) was run over the diff. It confirmed exactly one real defect — the
file_index-before-Asset commit ordering — which is fixed in this branch (revision now commits first). Two non-reachable findings were hardened anyway (unique content-store temp name; evidence path-containment check). A regression test locks in the invariant "everyfile_indexentry has an in-sync active Asset."Design doc:
docs/v2/phase-2-asset-model.md.