Status: Phases 0–5, the embedded retention/GC subset of Phase 8, and the
local Phase 9 operational/qualification slice are implemented. The CLI
publishes a SQLite query index by default alongside permanent graph.json
(--store json opts out); redb is a library-only adapter. PostgreSQL,
DynamoDB, hosted operation, distributed leases/GC, and service quotas remain
explicitly deferred until their phases are complete.
At completion, Compass has:
- a backend-neutral
compass-storecrate whose first boundary is a scoped namespace and whose complete address is(namespace, partition, key); - a permanent
JsonGraphEngineforgraph.json; - a
StoreGraphEngineusing immutable content-addressed graph snapshots; - SQLite and redb embedded adapters;
- PostgreSQL and DynamoDB remote adapters;
- atomic local and store-native publication;
- bounded graph reads that do not require full JSON deserialization;
- adapter conformance, cross-engine differential tests, fault injection, garbage collection, backup, and recovery coverage; and
- measured performance evidence before any release claim.
The current local release boundary is intentionally smaller than the eventual
cloud program: logical formats are versioned and validated, while physical
adapter files and query caches can be rebuilt. See the operations guide
for locations, backups, restore, quotas, recovery, and the first 0.3.x
upgrade window.
The first implementation is intentionally smaller than the full program above and is independently mergeable:
compass-storeexposes the namespace-first(namespace, partition, key)contract, bounded ordered scans, conditional writes, immutable writes, and a versioned SQLite realization in one package. The contract does not expose SQL or require a particular backend, so redb, PostgreSQL, DynamoDB, or a service adapter can implement the same trait later.- Every committed local generation contains
graph.json. Builds using the default SQLite storage (or explicit--store sqlite) additionally contain a typedstore.ref; one shared.compass-store/compass-store.sqlite3lives outside the generation directories. The store contains immutable digest-addressed projected trees, manifests, and a CAS-protected selector, but no legacy complete-graph payload. WAL is checkpointed before the BuildGuard switch; streamed canonicalgraph.jsonbytes bind the manifest; and the reference is checked before a store query runs. - Typed code-query opening uses an adjacent validated
store.refby default and supports explicit--engine default|json|store.jsonalways selects the permanent JSON engine;storerequires a published database and reference and executes directly through projected immutable indexes. A default query falls back to JSON only when no store reference is present.
Acceptance criteria for this slice are deliberately concrete:
cargo test -p compass-store --lockedpasses namespace isolation, lexicographic scans/cursors, CAS, immutable retry, snapshot validation, and reopen tests.cargo test -p compass-query --test store_engine --lockedproves default sidecar selection, explicit JSON/store selection, immutable snapshot authority, selection, reference failures, pinned readers, cache identity, and JSON-equivalent typed query results.- The core publication regression test proves the shared database and
generation reference are present, reopenable, digest-valid, and
byte-identical to canonical
graph.jsonafter a local build. - Deleting or corrupting the sidecar never changes the JSON artifact; default
query opening falls back only when the sidecar is absent, while an active
Phase 2 snapshot without a matching
store.refand explicit store selection fail with typed errors.
The local slice does not claim PostgreSQL/DynamoDB adapters, remote retry semantics, distributed leases, or hosted quotas. Its local performance claims are limited to the documented Django qualification. The optional redb adapter is delivered in the Phase 5 slice below; it is not linked into the released CLI by default.
The first executable Phase 2 slice is intentionally independent of a durable
adapter. compass-graph now exposes a deterministic immutable snapshot builder
and reader over the namespace-first compass-store::Store contract. It writes
content-addressed compact tree objects, a typed manifest, and a CAS-protected
active selector using the memory reference store. The layout includes metadata,
nodes, edges, directional adjacency, files/source anchors, names, terms,
communities, and diagnostics roots.
The reader validates schema majors, object digests, tree ordering, root/index
identity, graph counts, and the complete typed graph before returning data. It
provides bounded point reads, ordered node/edge scans, directional adjacency,
and canonical JSON export. Repeated builds are idempotent and report immutable
object reuse; prepared content never becomes active until the selector CAS.
The permanent graph.json engine remains unchanged. Phase 3 persists these
same objects in the SQLite sidecar and verifies their canonical export before
the generation is sealed.
The slice's acceptance evidence is in
crates/compass-graph/tests/store_snapshot.rs: deterministic identity across
record insertion order and operational generation IDs, immutable object reuse,
selector-before-commit behavior, bounded reads, directional multiplicity, key
vectors, and fail-closed tamper detection. Persistent SQLite publication and
CLI generation checks are covered by the Phase 3 tests below; full
JsonGraphEngine versus streaming store-engine differential qualification and
measured performance claims remain follow-on work.
Every phase follows these rules independently:
- Keep phases mergeable. A phase must leave the default branch usable and tested. Feature flags or internal configuration may hide unfinished paths, but an incomplete path must fail explicitly rather than silently change engines.
- Preserve JSON.
graph.jsonremains a supported engine and canonical export. No phase may call it “legacy,” “fallback pending removal,” or “deprecated.” - Hard-cut only internal formats. Unreleased store schemas, namespace encodings, and disposable query caches may be invalidated and rebuilt. Public graph, CLI, CompassQL, MCP, and historical contracts need their normal compatibility process.
- Prove semantics before speed. Cross-engine graph equivalence and adapter conformance land before query routing or performance claims.
- Bound all work. Every API and test covers item, byte, depth, frontier, response, deadline, retry, and concurrency limits relevant to it.
- Keep local operation native. Default builds and tests require no cloud account, service credentials, Python, vector database, or live network.
- Test the lowest owner. Store semantics live in
compass-store, graph layout incompass-graph, publication incompass-coreandcompass-files, query behavior incompass-query, and public command effects incompass-cli. - Use one target directory per checkout. Every compiling Cargo command
sets
CARGO_TARGET_DIRunder/Volumes/Workspace/crabbuild-targetas required byAGENTS.md.
Phase 0 portable store contract + memory reference
|
+--> Phase 1 graph-engine read boundary + permanent JSON engine
| |
| v
+--> Phase 2 immutable graph snapshot layout + memory store engine
|
v
Phase 3 SQLite adapter + optional local publication
|
v
Phase 4 explicit store-backed query routing
/ \
v v
Phase 5 Phase 6
redb PostgreSQL
|
v
Phase 7
DynamoDB
\ | /
\ v /
Phase 8
multi-tenant operations
|
v
Phase 9
qualification and release
Phases 5 and 6 can proceed independently after Phase 4. Phase 7 can begin after the conformance harness and graph layout are stable, but it should not be declared production-ready before the remote operational patterns in Phase 6 have been exercised.
A phase is complete only when:
- its acceptance criteria are represented by automated tests or a checked qualification artifact;
- unknown major versions and unsupported capabilities fail explicitly;
- failure and interruption paths clean up or leave only unreachable immutable content;
- deterministic result ordering is asserted, not inferred;
- public errors are typed, bounded, actionable, and free of secrets;
- relevant docs identify behavior as available only after the implementation lands;
git diffandgit status --shortcontain no unrelated or generated noise; and- the implementer reports which repository baseline and surface-specific gates ran, and why any applicable gate did not run.
The normal final Rust baseline is:
CARGO_TARGET_DIR=/Volumes/Workspace/crabbuild-target/compass-<checkout> \
cargo fmt --all -- --check
CARGO_TARGET_DIR=/Volumes/Workspace/crabbuild-target/compass-<checkout> \
cargo clippy --workspace --lib --bins --locked -- -D warnings
CARGO_TARGET_DIR=/Volumes/Workspace/crabbuild-target/compass-<checkout> \
cargo test --workspace --lib --bins --lockedUse the actual unique checkout name. Verify /Volumes/Workspace is mounted and
writable before running Cargo; do not fall back to a local target/.
There is no safe backend work until address encoding, ordering, limits, consistency, conditional writes, cursor behavior, and error semantics are executable. This phase creates the lowest-level contract without graph logic or database dependencies. A deterministic in-memory implementation is the reference model used by every later adapter.
- new
crates/compass-store/package; - root workspace membership and workspace dependency wiring;
compass-storeunit and public-contract tests; and- no changes to CLI behavior or generated artifacts.
- Create
compass-storewith#![forbid(unsafe_code)]and the workspace lint policy. - Define bounded newtypes for
NamespaceId,PartitionKey,Key,Value,VersionToken, andCursor. - Freeze the versioned, length-prefixed binary key encoding and checked-in golden vectors, including binary zeroes, maximum lengths, and prefix boundaries.
- Freeze the portable v1 maxima proposed by the design. Record why each fits all four planned adapters.
- Define object-safe asynchronous
Store, namespace-scopedNamespaceStore, and backend-neutralStoreFactoryrequirements. The crate must not create or require one specific async runtime or a universal connection-string format. - Implement
get, ordered one-partitionscan, conditionalput, conditionaldelete, andput_immutablesemantics. - Define
StoreCapabilities, operation budgets/deadlines, read consistency, page accounting, and the complete typed error taxonomy. - Implement a deterministic memory store with fault injection, clock injection, and controllable conflicts. It must model semantics, not attempt to model SQLite or DynamoDB latency.
- Build a reusable adapter conformance module. Adapter crates must be able to invoke it without copying tests.
- Add property tests for ordering and encode/decode round trips with bounded generators. Seed failures must be reproducible.
- Add crate-level documentation stating that namespaces are isolation identifiers but not authorization claims.
- namespace A cannot read, scan, overwrite, or delete namespace B;
- partitions with identical keys remain isolated;
- keys are returned in unsigned lexicographic byte order;
- page item and byte ceilings stop before overflow and produce a valid cursor;
- resuming a cursor returns every matching entry exactly once;
- a cursor fails when reused with another range, partition, namespace, consistency, or store identity;
- concurrent
Missingwrites have exactly one winner; - concurrent
Versionwrites have exactly one winner per observed version; put_immutableaccepts identical retries and rejects different bytes;- limits fail before allocation or mutation;
- deadline and cancellation stop work without a detached mutation;
- errors redact values, keys, source text, and credentials; and
- unsupported capabilities fail before any write.
cargo test -p compass-store --lockedpasses and includes all required conformance behaviors.cargo clippy -p compass-store --all-targets --all-features --locked -- -D warningspasses.- Golden key vectors are identical on Linux, macOS, and Windows CI.
- A public API review confirms that no method scans a whole namespace, exposes raw SQL/backend expressions, promises cross-partition atomicity, or accepts unbounded values.
- The memory store passes the complete conformance suite under at least two deterministic fault schedules.
- No existing Compass command or file output changes in this phase.
The output is a new unused contract crate, so rollback is removal of the crate and workspace entry. Do not preserve an inadequate encoding for compatibility; change it before Phase 2 and update golden vectors with an explicit review.
Current query paths open graph.json and build in-memory lookup and adjacency
structures. Before a store engine exists, consumers need one immutable graph
read boundary. This phase moves current behavior behind that boundary while
keeping JSON results, files, and command behavior unchanged.
- Phase 0's bounded key/value vocabulary is available, but the JSON engine does not depend on a store backend.
- Existing
compass-model::GraphDocumentvalidation and query tests are the behavioral oracle.
compass-querygraph snapshot/read traits and planner inputs;- a JSON implementation wrapping existing load, validation, binary cache, and FTS behavior;
- narrow wiring in
compass-cliandcompass-mcp; and - query-engine implementation documentation.
- Inventory every graph consumer: typed search, code search, traversal, impact, affected, CompassQL, reports, MCP resources/tools, viewer export, clustering, and tests.
- Define an immutable
GraphEngine/GraphSnapshotcontract with bounded metadata, point lookup, ordered scans, incoming/outgoing adjacency, name and text candidates, community membership, projections, and JSON export. Its object-safe asynchronous/page surface must work for local and remote engines without owning an executor. - Define engine-independent cursors and result accounting where feasible. If a cursor is engine-specific, make it opaque, request-bound, and explicitly non-portable.
- Implement
JsonGraphEngineusing the current strict graph validation and disposable content cache. Preserve its path size checks and corruption behavior. - Refactor each query family to use the graph snapshot rather than reaching into JSON-specific indexes. Do not change query algorithms in the same step unless required for bounded streaming.
- Preserve deterministic tie-breaking and every current public diagnostic.
- Add a test-only recording engine that asserts query budgets, projection use, range direction, and absence of unbounded calls.
- Keep direct
--graph <path.json>and equivalent library entry points onJsonGraphEngine.
- every existing query fixture produces byte-for-byte equal JSON output and equivalent human output before and after the refactor;
- graph open still rejects oversize, malformed, invalid-major, and invalid cross-reference inputs;
- directed traversal and reverse traversal request the correct index direction;
- multiedges remain distinct and preserve edge IDs and source anchors;
- a limit error is not converted to an empty result;
- query ordering is stable across repeated runs; and
- opening an explicit JSON file never requires a database.
- Existing
compass-query,compass-cypher,compass-cli, andcompass-mcpcontract tests pass without approved snapshot changes. cargo test -p compass-cypher --test tck --locked,cargo test -p compass-query --test opencypher_tck --locked, andpython3 scripts/check_compassql_support.pypass.- The recording engine proves every public query supplies finite item/byte and traversal limits.
graph.jsonremains the complete portable authority and all public CLI output is unchanged in this phase.- Documentation names
JsonGraphEngineas permanent supported behavior.
Because the JSON implementation preserves the old semantics, rollback can restore direct JSON types without data migration. Do not proceed if the new trait requires a full graph allocation by definition; that would prevent the later store engine from improving cold-query memory.
This phase proves graph encoding, ordered indexes, structural sharing, and
publication semantics against the memory store before database behavior can
hide logical mistakes. It introduces StoreGraphEngine but does not publish a
user database.
- Phase 0 supplies the store contract and conformance model.
- Phase 1 supplies the graph read contract and JSON oracle.
- The design document supplies the manifest and required logical indexes.
compass-graphsnapshot builder and canonical graph-index encoders;compass-querystore graph engine;compass-modelonly for new typed internal snapshot records whose ownership review confirms they are shared graph contracts; and- cross-engine fixtures and differential tests.
- Freeze
compass.store.graph-snapshot/1,SnapshotManifest, root registry, value envelope, content digest, and snapshot identity projection. - Implement deterministic graph key encoders with golden vectors for nodes, edges, incoming/outgoing adjacency, files, names, terms, communities, and diagnostics.
- Integrate or implement the immutable ordered-map tree. Freeze content- defined chunking parameters and enforce maximum fanout, depth, object size, decoded size, and traversal reads.
- Stream canonical
GraphDocumentrecords into every required index. Reject duplicate logical keys and invalid references before publishing a manifest. - Use
put_immutablefor all content and manifest objects. - Implement manifest validation, root verification, and a prepared-snapshot result that is not active by construction.
- Implement the selector-CAS protocol in the memory store and concurrent reader semantics.
- Implement
StoreGraphEnginepoint reads, ordered iteration, adjacency, search candidates, projections, and streaming JSON export. - Add incremental rebuild from prior roots and measure object reuse in test fixtures for no-change, one-node, one-edge, rename, and delete updates.
- Add full differential tests between
JsonGraphEngineandStoreGraphEngineover generated bounded graphs as well as repository fixtures.
- identical validated graphs produce identical snapshot IDs and roots across repeated builds and insertion orders;
- operational timestamps, thread count, and host paths do not change snapshot identity;
- every logical graph field survives store-to-JSON round trip;
- outgoing and incoming indexes preserve direction;
- duplicate endpoint/kind edges preserve multiplicity through edge IDs;
- missing/corrupt tree objects fail as corruption or unavailable, never empty;
- a reader opened before selector CAS completes on the old snapshot;
- a reader opened after CAS observes only the new complete snapshot;
- two concurrent publishers produce one selector winner;
- no-change update writes no new content objects after idempotence checks;
- small updates reuse unchanged tree objects; and
- an interrupted prepare never becomes active.
- The memory-backed store engine passes every Phase 1 graph-engine contract test.
- Canonical JSON exported by both engines is byte-identical for all fixtures and bounded generated graphs.
- A checked qualification report records structural-sharing ratios for the five update cases; ratios are evidence, not yet release promises.
- Tree reads fail before exceeding configured depth, object, byte, or result limits.
- The snapshot layout has an explicit unknown-major failure test and no backend-specific field.
./scripts/qualify_code_graph_v1.sh --fixtures-onlypasses.
This is still an unpublished internal format. If the layout is insufficient, change its major or discard it; do not add a migration reader merely to retain test data. Phase 3 must not begin until cross-engine equivalence is complete.
SQLite is the first persistent adapter and exercises reopen, filesystem,
locking, crash, and durability behavior. Local builds selected with
the default SQLite storage (or --store sqlite) writes the store snapshot while
the JSON artifact remains a permanent independent engine. This isolates
write/publication risk from the
broader remote-adapter work.
- Phase 0's adapter conformance harness;
- Phase 2's immutable snapshot builder; and
- the existing
BuildGuardgeneration publication primitive.
- the SQLite adapter in
compass-storefor the initial local slice (a future split intocompass-store-sqliteremains an internal packaging choice); - local store path and file lifecycle in
compass-files; - snapshot preparation and
store.refstaging incompass-core; and - CLI contract tests for
initandupdateside effects.
- Implement the SQLite physical schema, binary ordering, metadata/format table, conditional writes, ordered scans, and capability report.
- Configure WAL, full synchronous durability, bounded busy timeout, bounded statement inputs/results, and coherent close/checkpoint behavior.
- Reuse atomic path, containment, permissions, symlink, and recovery helpers
from
compass-files. - Run the complete adapter conformance suite against a newly created and a reopened database.
- Add reopen/durability, WAL checkpoint, orphan-discovery, stale-format, and generation-publication tests. Fault-injected crash qualification remains a release gate for the larger Phase 3 evidence set.
- Define a typed, versioned
store.refcontaining store identity, namespace, snapshot ID, manifest digest, and graph digest but no machine-specific absolute path. - During
init,update,extract, orwatchwith default storage (or--store sqlite), prepare the SQLite snapshot and stagestore.refwithgraph.jsonand other output artifacts. The filesystem generation switch is the only local commit. - Keep
graph.jsonas the permanent compatible engine. The default query uses a validated adjacent store reference, while explicit JSON always opens the JSON reader; SQLite publication compares canonical graph identity before commit. - Make SQLite publication the default dual profile.
--store jsonopts out of the sidecar; selecting SQLite never removes JSON. - Retain two complete local generations and run bounded root-based object GC after coherent publication. Distributed lease-aware GC remains Phase 8.
- creation, reopen, write, read, scan, CAS, and delete pass conformance;
- acknowledged writes survive process reopen under the configured durability;
- copying or recovering SQLite accounts for WAL state;
- an interrupted database write cannot change the active filesystem generation;
- an interrupted filesystem switch leaves the prior generation readable;
- published
graph.jsonandstore.refselect equal graph digests; - a store database missing or corrupt after publication does not make the co-published JSON unreadable;
- concurrent local updates produce a guarded conflict rather than mixed artifacts;
- local paths cannot escape through symlinks or untrusted namespace text; and
- stale/unreleased SQLite formats fail with a rebuild instruction.
- the initial adapter's
cargo test -p compass-store --lockedpasses namespace/CAS/scan conformance, WAL reopen durability, orphan discovery, and stale-format checks; injected busy/interrupt qualification remains a separate release gate. compass init --store sqliteandcompass update --store sqliteCLI integration tests assert successful exit,graph.json,store.ref, complete manifest, and no visible partial generation.- Cross-engine comparison covers the published core fixture and CLI init/update generations and rejects publication on any canonical mismatch.
- The permanent
graph.jsonengine remains independently readable when the store is missing or corrupt. Default queries use the validated sidecar when present and fail closed when a published reference is corrupt; explicit--engine jsonremains independent. - The old disposable query SQLite cache may be hard-cut or rebuilt, but the new durable snapshot store uses a different format identity and location.
Disable SQLite publication and remove unpublished databases. Existing
graph.json generations remain valid. Do not attempt to repair a partially
published store by rewriting its immutable objects; rebuild a new snapshot.
After optional publication proves equivalence and durability, local readers
can explicitly select the co-published store snapshot. The local slice reads
the immutable Phase 2 snapshot, validates the active selector and store.ref,
and compares every typed code-query operation with the JSON engine. Typed
queries use projected point/name/term/adjacency reads without materializing or
cloning a complete GraphDocument. JSON remains selectable and is used by
default or whenever the caller explicitly selects it.
- Phase 3 has qualification evidence from real local build generations.
- Every current query family is already behind the Phase 1 graph read contract.
- engine selection in
compass-coreand thin CLI/MCP wiring; - store-aware plans and projection batching in
compass-query; - query cache lifecycle; and
- performance and differential qualification.
- Define deterministic engine selection:
- explicit JSON path selects
JsonGraphEngine; - a validated active generation with a valid
store.refselectsStoreGraphEngineby default; - an explicit
--engine json|storediagnostic option may override the default where the command surface review approves it.
- explicit JSON path selects
- Validate
store.ref, store identity, namespace, snapshot ID, manifest digest, and graph digest before executing a query. - Make store query plans use projections, bounded point-read batches, ordered adjacency ranges, and finite traversal frontiers.
- Port deterministic name/text ranking to portable indexes. Keep SQLite FTS only as a disposable, differential-tested accelerator.
- Make corruption and unavailability actionable. An automatic switch to JSON is permitted only before results are emitted, only when the selected local generation proves digest equivalence, and only with an explicit diagnostic.
- Remove assumptions that opening a current graph loads every node and edge.
- Add engine identity to safe diagnostics and telemetry, not to public result meaning.
- Benchmark complete cold command latency, including engine open and any accelerator build.
- Define a typed storage/materialization profile at the application boundary:
json,store, ordual. Preserve the existing output profile by default; exposestoreonly through a separately reviewed CLI/configuration change. Store-only generations must support bounded deterministic JSON export.
The shipped local slice implements items 1–8 for typed code queries and the dual local profile. It pins opened readers, uses backend-neutral candidate ordering and tokenization, and records Django build/query/RSS qualification. Store-only publication and broader CompassQL/MCP projection plumbing remain separately gated.
- every public query produces the same ordered machine output under JSON and SQLite store engines;
- human output differs only by an approved diagnostic when engine recovery is exercised;
- partial results from one engine are never combined with retry results from another;
- an explicit JSON input never opens an adjacent store, while the default engine uses a validated adjacent store reference when present;
- stale
store.ref, wrong namespace, wrong digest, missing object, corrupt envelope, unsupported major, and store timeout each have distinct tests; - query item, byte, frontier, depth, and deadline limits are enforced on store plans;
- current graph updates do not invalidate readers already pinned to the prior immutable snapshot; and
- accelerator deletion changes latency only, not ordered results;
jsonpublishes the existing artifact set without requiring a database;dualpublishes equal JSON and store snapshots in one generation; andstoreavoids full JSON materialization but can export byte-identical canonical JSON on demand.
compass-querydifferential tests cover typed search, callers, callees, impact, explore, node trails, explicit JSON isolation, stale references, immutable snapshot authority, and reader pinning.- The default and explicit store query paths select the immutable snapshot only when its
active selector and
store.refvalidate; malformed or missing references fail closed, while explicit JSON remains independent. - The JSON engine's disposable
compass-code-index/2and the store term index share token and candidate-order semantics; store queries do not construct the disposable index. - Existing CompassQL TCK, OpenCypher TCK, CLI product tests, product-boundary check, and fixture-only code-graph qualification remain green.
Full cross-engine differential coverage for CompassQL/MCP and any additional
storage profiles remain follow-on gates. Typed projected-query and
PERFORMANCE.md cold-open/RSS measurements are complete for the local slice.
- Documentation clearly states that
graph.jsonis a compatible permanent engine, not a deprecated fallback.
Engine selection can return to JSON without converting data because each local generation still contains it. Keep store databases as disposable/unselected or rebuild them. A rollback must not remove the graph read abstraction.
redb provides a second local implementation with different concurrency and
physical-storage behavior. Its purpose is both a usable embedded option and a
test that the common contract did not accidentally become SQLite-shaped. The
implemented slice keeps redb in compass-store-redb, uses the same graph
snapshot builder and a backend-neutral query opening hook, and deliberately
does not add redb to the default CLI binary.
- Phase 0 conformance and Phase 2 graph differential suites are stable.
- Phase 4 graph-engine boundary can consume a backend-neutral
Storewithout changing graph meaning.
- new
compass-store-redbcrate; - backend-neutral local selection hook and adapter documentation; and
- adapter-specific durability, contention, and reopen tests.
- Add redb as a pinned workspace dependency after dependency-policy review.
- Implement the composite binary address encoding, read transactions, conditional write transactions, ordered scans, versions, and capabilities.
- Bound the single-writer queue and expose backpressure rather than allowing unbounded waiting tasks.
- Map commit durability and process reopen to the common acknowledgement contract.
- Run graph snapshot construction and every query family through redb.
- Add backend selection without changing namespace, manifest, graph-index, or JSON contracts.
- Document file backup and recovery separately from SQLite.
The shipped local slice implements all seven items for library consumers and
tests. Explicit CLI/backend configuration remains gated on packaging and
performance policy; graph.json and SQLite remain the supported local command
engines.
cargo test -p compass-store-redb --lockedruns the shared conformance, reopen/backup, binary-order, writer-gate, and graph-snapshot differential tests.cargo test -p compass-query --test store_engine --lockedexercisesopen_with_storeagainst redb for search, callers, callees, impact, explore, and node trails.- conformance under create, reopen, and contention; injected commit-failure schedules remain a follow-on fault-injection gate;
- byte ordering across composite namespace/partition/key boundaries;
- bounded single-writer backpressure and cancellation;
- reader snapshot stability during selector publication; and
- full graph/query differential coverage against JSON and SQLite.
- redb passes the unmodified shared adapter conformance suite, including deterministic reopen, ordering, CAS, immutable-write, and bounded writer backpressure tests.
- Memory, SQLite, and redb produce identical graph snapshot IDs, logical roots, JSON exports, and ordered query results for the same graph.
- A concurrent writer test proves the adapter rejects a full process-local writer gate rather than accumulating unbounded tasks.
- No redb type appears in
compass-store,compass-model, public graph schemas, or query result contracts. compass-query::open_with_storeruns all typed code-query families through a redb snapshot and matches JSON output; the local binary does not include redb unless packaging/product policy intentionally selects or exposes it.
Full injected commit-failure schedules, cross-process deadline cancellation, CompassQL/MCP differential coverage, and measured redb-versus-SQLite performance are explicit follow-on gates.
Remove the optional adapter and its configuration. The store and graph formats remain usable through SQLite and JSON, so there is no graph migration.
PostgreSQL proves that the contract works across a network, connection pool, server transactions, cancellation, and multiple service workers. This phase does not yet ship a multi-tenant Compass cloud product; it produces a hardened remote adapter and controlled service-boundary tests.
- Store and graph contracts are stable through Phase 4.
- Security review has defined endpoint, TLS, and credential configuration.
- CI can provide an isolated disposable PostgreSQL service without real credentials or persistent user data.
- new
compass-store-postgrescrate; - backend-neutral remote connection configuration at an application boundary;
- local mock/disposable-service integration tests; and
- security, operations, and adapter documentation.
- Add a bounded asynchronous PostgreSQL client and pool after dependency and feature review.
- Implement the binary composite primary key, format metadata, point reads, constrained ordered scans, conditional insert/update/delete, and versions.
- Set connection, acquisition, statement, response, and total operation deadlines. Wire cancellation so expired work does not continue unnoticed.
- Enforce TLS and endpoint policy appropriate to the configured deployment. Redact DSNs, credentials, query values, and repository identifiers.
- Run schema installation/migration through an explicit administrative path; ordinary graph callers cannot create arbitrary tables or schemas.
- Exercise concurrent publisher CAS from multiple processes and readers pinned before/after publication.
- Test connection loss after request send and before response. Immutable retries verify digest; CAS returns an indeterminate-safe diagnostic unless the selector can be strongly reread and resolved.
- Validate namespace isolation in application handles and, where configured, database permissions or row-level security as defense in depth.
- Record request counts, bytes, pool wait, query time, retries, and conflict rates with low-cardinality metrics.
- schema creation is restricted to the administrative path;
- CAS races from separate connections have exactly one winner;
- ordered scans survive service page boundaries without gaps or duplicates;
- connection acquisition, statement, response, and total deadlines each terminate with the correct error;
- an ambiguous connection failure is resolved by a strong reread or reported without an unsafe retry;
- primary and permitted replica routes meet the requested consistency; and
- namespace and cursor replay attacks fail without information disclosure.
- PostgreSQL passes the shared conformance suite against a disposable local CI service, including reopen, concurrent processes, cancellation, and injected connection failures.
- Tests prove every normal statement constrains namespace and partition; no unbounded table scan is available to graph callers.
- Two authenticated test principals cannot cross namespace boundaries through point reads, scans, cursors, diagnostics, or maintenance APIs.
- Store and JSON engines have identical query and export results.
- Secrets do not appear in snapshots, errors, logs, metric labels, or test artifacts.
- Default local Compass packaging and operation still require no PostgreSQL client configuration or network.
Remove or disable the remote adapter. Immutable snapshots remain exportable to JSON before teardown. Because the physical schema is adapter-private, no other backend must read PostgreSQL tables directly.
DynamoDB exercises the strictest partition-first deployment: exact partition key locality, paginated Query, conditional writes, capacity throttling, item limits, and eventually consistent secondary indexes. The adapter must use the base table's strong-read path for authoritative records and must not require global transactions.
- Phase 0 limits fit DynamoDB key and item constraints with measured envelope overhead.
- Phase 2 digest sharding avoids sequential or repository-wide hot partitions.
- Phase 6 has established remote cancellation, retry, and secret-handling patterns.
- new
compass-store-dynamodbcrate; - AWS endpoint, region, credential-source, retry, and capacity configuration at the application boundary;
- protocol mocks or a controlled local DynamoDB implementation; and
- cloud cost/capacity qualification artifacts.
- Add only the required AWS SDK features after dependency-size and build-time review. Keep the adapter out of default local packages unless selected.
- Encode
PK = (namespace, partition)andSK = keywith checked limits and golden test vectors. - Implement strongly consistent GetItem and base-table Query, conditional PutItem/UpdateItem/DeleteItem, digest verification, and opaque versions.
- Translate one Compass page across service 1 MiB pages without exceeding the caller's byte/item/deadline budget. Protect and bind continuation cursors.
- Handle throttling with bounded exponential backoff and jitter. Surface exhausted throttling separately from not found and conflict.
- Prohibit authoritative selector or manifest reads through an eventually consistent global secondary index.
- Measure partition distribution for large and adversarial graph fixtures. Revise the unreleased shard function if hot keys appear.
- Model ambiguous network outcomes: reread immutable content by digest; reread selectors strongly and compare the intended snapshot before reporting the final outcome.
- Add request, byte, consumed-capacity, retry, throttle, and projected-cost reporting without high-cardinality identifiers.
- Test only against controlled local resources or mocks in normal CI. A separately authorized qualification environment may run non-default cloud tests with synthetic data.
- item encoding reaches every portable length boundary without crossing a service key or item limit;
- service pagination maps to Compass pages without gaps, duplicates, false completion, or byte-budget overflow;
- conditional failures map to
Conflict, throttling toThrottled, and an absent strong read toNotFound; - retries stop at the request deadline and never repeat a non-idempotent write;
- a global secondary index cannot be selected for an authoritative read;
- hot-partition fixtures exercise the documented shard calculation; and
- ambiguous request outcomes resolve through strong selector or digest reads.
- The adapter passes the same conformance suite as memory, SQLite, redb, and PostgreSQL, with service pagination and throttling explicitly exercised.
- No value can exceed the portable limit after envelope and DynamoDB attribute overhead.
- Authoritative reads request strong consistency and tests fail if routed through an eventual-only index.
- Synthetic large graphs distribute content across the documented shard envelope; the report includes the hottest partition and request count.
- A throttled or partially paginated scan never returns a false complete page.
- Credentials and endpoints remain optional and explicit; offline Compass tests and structural extraction never contact AWS.
Disable the adapter and export retained snapshots through the graph engine before deleting deployment tables under a separately authorized operational procedure. Never put table deletion into ordinary Compass rollback code.
Passing CRUD conformance is insufficient for a cloud service. This phase adds the backend-neutral control plane: authenticated namespace scoping, quotas, leases, garbage collection, backup validation, recovery, and safe observability. It runs over PostgreSQL and DynamoDB and remains usable for embedded maintenance.
- At least one embedded and one remote adapter have passed conformance and graph differential qualification.
- Product/security owners have defined tenant, project, repository, and data- retention identities.
- a service/application crate chosen by architecture review, not
compass-storeitself; - namespace catalog and authorization integration;
- build/reader leases and active-selector orchestration;
- portable root-based GC and restore validation; and
- security, privacy, operations, and support documentation.
- Derive namespace IDs server-side from authenticated tenant, repository, data-plane, realm, and schema-major descriptors.
- Issue namespace-scoped handles after authorization. Remove raw namespace selection from user-controlled graph/query requests.
- Enforce quotas for concurrent builds, stored bytes, snapshots, query objects/bytes/frontier/time, response size, and backend capacity.
- Implement versioned build and reader leases with bounded renewal and explicit expiry. A crashed worker cannot hold data forever.
- Implement mark-and-sweep GC rooted at active selectors, retained local references, pins, history roots, and unexpired leases. Use checkpoints, safety windows, shard budgets, and conditional deletion.
- Add namespace deletion as a separately authorized, auditable, resumable workflow. It must enumerate explicit manifests/checkpoints rather than run an unbounded synchronous request.
- Implement backend-specific coherent backup procedures and a common restore validator that checks selector, manifest, all roots, digests, graph schema, and completion evidence before activation.
- Exercise disaster recovery into a new store identity and namespace. Opaque old version tokens and cursors must not be reused.
- Add low-cardinality metrics, structured audit records, correlation IDs, redaction tests, and per-tenant cost attribution without source disclosure.
- Threat-model confused deputy, namespace collision, cursor replay, quota bypass, malicious stored values, hot partitions, credential exposure, and cross-tenant accelerators.
- authenticated tenant A cannot derive or use tenant B's scoped handle;
- namespace display names and repository paths cannot alter physical identity through encoding ambiguity;
- quota exhaustion produces a typed limit result and no background overrun;
- expired leases stop protecting data, while live readers remain protected;
- GC preserves every reachable object and eventually removes only eligible orphans under deterministic fault schedules;
- interrupted GC and namespace deletion resume from bounded checkpoints;
- restore refuses missing, corrupt, wrong-major, wrong-namespace, and incomplete snapshots;
- accelerator data never crosses snapshot or namespace boundaries;
- audit and metrics contain no source, values, credentials, raw keys, or sensitive paths; and
- a compromised/untrusted stored envelope cannot force an oversized allocation or unsafe path.
- Security review signs off on namespace authorization, credentials, remote endpoint policy, cursor integrity, quotas, redaction, and deletion.
SECURITY.mdand security/privacy design docs describe all new trust, credential, network, storage, and disclosure boundaries.- GC fault tests prove no reachable-object deletion across every supported adapter.
- A documented backup/restore drill succeeds for SQLite, PostgreSQL, and DynamoDB qualification environments and produces equal canonical JSON.
- Service load tests demonstrate bounded resources during tenant concurrency, throttling, worker crashes, and large responses.
- Local Compass remains usable without enabling or configuring any service surface.
Stop accepting new remote publications, retain selectors and leases, export or back up reachable snapshots, then disable the service control plane. Data deletion requires its explicit audited workflow and is never implied by code rollback.
This phase converts implemented behavior into a supported product contract. Until it completes, store formats may still hard-cut and performance remains a development observation. Release requires compatibility, migration, security, performance, packaging, and operational evidence.
- All adapters intended for the release have passed conformance.
- Local store-backed queries have passed full JSON differential testing.
- Cloud operations are included only if Phase 8 is complete for that surface.
COMPATIBILITY.md,MIGRATION.md,CHANGELOG.md,PERFORMANCE.md,SECURITY.md,SUPPORT.md, command/configuration/output references, and operations guides;- packaging, install, upgrade, and downgrade tests; and
- release qualification artifacts.
- Declare exactly which store envelope, graph-snapshot layout, adapter physical formats, and configuration surfaces are public and which remain rebuildable implementation details.
- Decide the first supported upgrade window. Provide migration or explicit rebuild tooling for formats now declared durable.
- Document backend selection, locations/endpoints, credentials, TLS, durability, backup, restore, GC, quotas, and recovery.
- Document that
graph.jsonremains supported for direct input, publication, interchange, inspection, recovery, and deterministic export. - Run clean/no-change/small-change builds and complete cold-query benchmarks at documented graph sizes. Include peak memory, bytes, request counts, database size, write amplification, and GC.
- Run all cross-engine differential, adapter conformance, crash, corruption, concurrency, namespace isolation, and restore suites on the release commit.
- Validate packaging does not accidentally include cloud SDKs, credentials, or local database files in unrelated distributions.
- Add release-visible changes to
CHANGELOG.mdand user actions toMIGRATION.md.
The local release work closes the first support window without claiming cloud readiness:
compass store status|validate|backup|restorevalidates the co-published SQLite generation and writes digest-bound backup bundles;scripts/rebuild_compass_store.shprovides an explicit, rollback-preserving hard-cut rebuild path;compass-store-qualificationandscripts/qualify_compass_store_release.shmeasure SQLite/redb graph sizes, peak RSS, bytes, request counts, database size, write amplification, GC state, and CLI clean/no-change/small-change/cold-query behavior;- the harness compares canonical JSON, typed query responses, and CompassQL results and runs the adapter, corruption, concurrency, snapshot, packaging, and product-boundary gates; and
- the operations, compatibility, migration, security, support, and configuration references declare SQLite as the local CLI backend, redb as a library-only adapter, and PostgreSQL/DynamoDB as deferred service phases.
The generated qualification directory is external evidence and is never committed. Run the harness again on the final release commit after all docs and release metadata have settled.
- Canonical JSON exported from every released engine is byte-identical for the release qualification corpus.
- All public query and CompassQL outputs are equal across JSON and released store engines.
PERFORMANCE.mdcontains reproducible evidence for each performance claim; regressions outside agreed budgets block the default cutover.COMPATIBILITY.mdlists supported store/snapshot majors, backend/platform support, hard-cut boundaries, and the permanent JSON engine.- Backup and restore procedures have been executed, not only reviewed.
- The repository native baseline and every applicable surface gate pass on the release commit.
- No generated graph,
.compass/state, database, credentials, private source, or machine-specific path is committed.
In addition to targeted crate tests, run:
CARGO_TARGET_DIR=/Volumes/Workspace/crabbuild-target/compass-<checkout> \
cargo test -p compass-cli --test compass_product --locked
sh scripts/check_product_boundary.sh
CARGO_TARGET_DIR=/Volumes/Workspace/crabbuild-target/compass-<checkout> \
cargo test -p compass-cypher --test tck --locked
CARGO_TARGET_DIR=/Volumes/Workspace/crabbuild-target/compass-<checkout> \
cargo test -p compass-query --test opencypher_tck --locked
python3 scripts/check_compassql_support.py
./scripts/qualify_code_graph_v1.sh --fixtures-onlyRun repository qualification on external repositories only under
/Volumes/Workspace/Github and treat them as read-only, following
AGENTS.md.
Before public format declaration, rollback may rebuild store state and route local queries to JSON. After declaration, use the documented migration and support policy; do not silently invalidate durable cloud or user data. Query cutover can still return to the co-published JSON engine without changing public graph meaning.
Every pull request implementing part of a phase should include this information in its description:
Phase and bounded work package:
Owning crate(s):
Contract/version affected:
Failure modes added or changed:
Limits enforced:
JSON equivalence evidence:
Adapter conformance evidence:
Performance evidence or “no claim”:
Compatibility decision: hard cut | rebuildable | public-compatible
Security/network/credential impact:
Targeted checks run:
Baseline/gates run or reason omitted:
Rollback path:
Do not combine a store encoding change, a query semantic change, and a public CLI change in one work package unless the phase cannot be made coherent any other way.
The program is complete only when a reviewer can demonstrate this sequence without inspecting backend internals:
- build one graph and publish a coherent JSON plus store generation;
- query both engines and obtain equal ordered outputs;
- interrupt an update at each publication boundary and retain the old graph;
- complete an update and keep an already-open reader on its old snapshot;
- reopen every embedded backend and recover every remote backend from a coherent backup;
- race two publishers and observe one active-selector winner;
- exhaust scan, query, retry, throttle, and quota budgets without false empty results or background overruns;
- attempt cross-namespace access and receive denial without information disclosure;
- remove disposable accelerators and obtain the same results; and
- export deterministic
compass.graph/1JSON from every store backend.
- Compass store and graph-engine design
- Storage and history
- Extraction pipeline
- Query engine
- Workspace tour
- Compatibility policy
- Performance qualification
Next step: after the local release is accepted, start the separately scoped PostgreSQL service adapter only with endpoint, credential, TLS, quota, lease, and tenant-isolation evidence. Do not widen the local CLI backend implicitly.