4.0 KiB
M2.8 — M2 composition gate
| Field | Value |
|---|---|
| Phase | M2 — Projections |
| Size | M — 1–3 days |
| Status | ⬜ Not started |
| Flags | gate |
| Spec | inlined below |
| Blocks | all of M2 |
Goal
Prove the authority model: the log is sufficient, and both projections are genuinely derived.
Facts (inlined — no spec read needed)
The claim under test — poimen's own principle, applied here:
Nothing derived is authoritative. If it cannot be dropped and rebuilt byte-identically, it has hidden inputs and that is a bug.
The gate is destructive by design: it deletes the vault and truncates the database, rebuilds from the log alone, and diffs. Anything that survives only because it was already there is a hidden input, and this is the only test that finds it.
rm -rf vault/poimen
psql -c "delete from memory_node where project = 'poimen'"
mem rebuild --from-log --project poimen
git -C vault diff --exit-code # empty diff is the only pass
git diff --exit-code on a tracked vault is the assertion. It compares against
what was committed, so it also catches a projector change that was not intended.
Run it twice: once from empty (sufficiency) and once on top of itself (idempotence). Both must produce the same bytes.
Steps
verify/m2.8.shperforming the destructive rebuild above.- Assert the vault diff is empty and the database node counts match the log.
- Run
mem verifyand assert zero violations. - Second rebuild without clearing; assert still empty diff and unchanged row count.
- Assert no controller model calls (embeddings are allowed and expected).
- Commit
expected/m2.8.txtwith the count summary; diff against it.
Acceptance
- Vault rebuilt from nothing is byte-identical to the committed vault.
- Database node/edge counts match the log's records exactly.
mem verifyreports zero violations.- Second rebuild changes nothing.
Verify
Harness: disposable database, git-tracked vault, real log. Long-running; a nightly or on-demand job.
Integration test — verify/m2.8.sh, output diffed against expected/m2.8.txt:
a1_vault_from_empty— delete vault, rebuild,git diff --exit-codeempty.a2_db_from_empty— truncate, rebuild, counts per level equal the log's.a3_verify_clean—mem verifyexits 0.a4_rebuild_idempotent— rebuild again, diff still empty, row count unchanged.a5_no_controller_calls— assert zero calls to the chat route during rebuild (count via the record dir from M1.1, or a proxy).a6_projection_independence—--vault-onlythen--db-onlyproduces the same end state as a combined rebuild.a7_log_alone_suffices— move the log to a fresh checkout with no vault and no database, rebuild, diff against the committed vault. The strongest form of the claim.
Command: bash verify/m2.8.sh | diff - expected/m2.8.txt
False pass:
- Running the gate without deleting the vault first. A projector that only writes changed files produces an empty diff trivially, and the hidden input survives.
- Diffing an untracked vault.
git diffon untracked files reports nothing, so the assertion passes vacuously. The vault must be committed, or the script must compare against a committed golden tree explicitly. - Allowing controller calls "because it is easier". Rebuild then produces new memory text each run and the gate can never pass — at which point the usual fix is to weaken the gate.
Traps
- Treating a non-empty diff as a projector bug by default. It is equally likely to
be a hash bug: if
sha256includes a timestamp (M0.2), every rebuild produces new nodes and the vault churns. Check identity before blaming rendering. - Running against production data with the destructive script and no backup. The log is the record; if that is intact, everything is recoverable — which is exactly why the log must be tracked in git before this gate is first run.
Background: DESIGN.md — Authority model, Verification