Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
2544dd9
docs(05): capture phase context
hermanngeorge15 Oct 25, 2026
d46d83c
docs(state): record phase 5 context session
hermanngeorge15 Oct 25, 2026
ae657d7
docs(05): research portable export/import phase domain
hermanngeorge15 Oct 25, 2026
b90e833
docs(phase-5): add validation strategy
hermanngeorge15 Oct 25, 2026
e45113c
docs(05): create phase plan — 4 plans (D-14 redaction + store contrac…
hermanngeorge15 Oct 25, 2026
9e28973
docs(05): resolve plan-checker warnings, record planning complete
hermanngeorge15 Oct 25, 2026
00d8080
feat(05-01): redact storage-engine text on every service path (D-14)
hermanngeorge15 Oct 25, 2026
9ee42ed
feat(05-01): id-returning dedup probe and countable link insert (D-07…
hermanngeorge15 Oct 25, 2026
5994d38
feat(05-01): ImportedMemory + Store::insert_imported for restored row…
hermanngeorge15 Oct 25, 2026
3ca3138
docs(05-01): complete redaction + store-contract plan
hermanngeorge15 Oct 25, 2026
6524cf1
feat(05-02): agent-memory export streams format v1 JSONL to stdout (D…
hermanngeorge15 Oct 25, 2026
cffe7a2
feat(05-02): export --output writes a private temp file and renames i…
hermanngeorge15 Oct 25, 2026
2dcf27d
docs(05-02): complete export tracer + atomic --output plan
hermanngeorge15 Oct 25, 2026
9d937f4
feat(05-03): import --from jsonl recreates memories and links idempot…
hermanngeorge15 Oct 25, 2026
c7bc811
test(05-03): JSONL import kill-tests — phantom edges, expiry, pending…
hermanngeorge15 Oct 25, 2026
dc7822c
docs(05-03): complete import --from jsonl plan
hermanngeorge15 Oct 25, 2026
5a15d13
docs(05-04): README Export & import section (format v1, timestamp pol…
hermanngeorge15 Oct 25, 2026
6eb354a
test(05-04): CLI realism round trip for export/import over the spawne…
hermanngeorge15 Oct 25, 2026
033bd86
docs(05-04): complete contract docs + CLI realism plan
hermanngeorge15 Oct 25, 2026
5acea04
docs(05): add code review report
hermanngeorge15 Oct 25, 2026
80e905b
fix(05): import drops a post-remap self-link instead of mis-counting …
hermanngeorge15 Oct 25, 2026
c28fc04
fix(05): bound access_count on import and saturate the access bump (R…
hermanngeorge15 Oct 25, 2026
3c28202
fix(05): dedup probe ignores expired-but-unswept target rows (REVIEW …
hermanngeorge15 Oct 25, 2026
22cd8d7
test(05): redaction proofs for export and import_jsonl (REVIEW IN-02)
hermanngeorge15 Oct 25, 2026
621b29a
refactor(05): run_export reuses open_service and validates --output b…
hermanngeorge15 Oct 25, 2026
efcc1dd
docs(05): record review fixes in 05-REVIEW.md
hermanngeorge15 Oct 25, 2026
f3d1568
docs(05): verification report — 32/33, human_needed (concurrency back…
hermanngeorge15 Oct 25, 2026
62de54b
docs(05): gap-closure plan 05-05 — one-snapshot race test + live-Olla…
hermanngeorge15 Oct 25, 2026
30085a2
docs(05): sharpen 05-05 Task 2 verification (plan-checker warnings)
hermanngeorge15 Oct 25, 2026
6cb8893
test(05-05): held-out race proof — a link committed mid-export is inv…
hermanngeorge15 Oct 25, 2026
d52c1ff
docs(05-05): live-Ollama realism run recorded — export → import → swe…
hermanngeorge15 Oct 25, 2026
fe18db7
docs(05-05): complete gap-closure plan — race proof + live-Ollama rea…
hermanngeorge15 Oct 25, 2026
3bf0f09
docs(phase-5): complete phase execution — verification passed 35/35
hermanngeorge15 Oct 25, 2026
7785ad1
docs(project): evolve PROJECT.md after Phase 5 — validated reqs for P…
hermanngeorge15 Oct 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions .planning/PROJECT.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ An agent can persist a structured memory and retrieve the right one later — ac
- ✓ Pre-built binaries (macOS arm64/x86_64, Linux x86_64/aarch64 gnu) + Homebrew formula — Phase 2
- ✓ Input validation at the shared MemoryService seam — limit (1–200) and ttl_secs (1–3155760000) rejected as REST 400 / MCP invalid_params, never 500, never a silent clamp (API-02) — Validated in Phase 3 (v1.1)
- ✓ Exact tag matching via json_each equality on all three query paths — 'rustling' no longer matches tag=rust (API-03, behavioral change recorded for v0.1.0 notes) — Validated in Phase 3 (v1.1)
- ✓ `memory_update` merge-patch with same-transaction FTS re-mirror + vector re-embed; unknown id is clean not-found data (MCP-06) — Validated in Phase 4 (v1.1)
- ✓ Flat typed relations `memory_link`/`memory_unlink` (relates_to symmetric, supersedes/caused_by directed), opt-in 1-hop expansion, cascade on forget/TTL (MCP-07) — Validated in Phase 4 (v1.1)
- ✓ Migration 0003 with hygiene: frozen 0001/0002 fixture test, pre-migration online backup, friendly newer-schema refusal (STORE-05) — Validated in Phase 4 (v1.1)
- ✓ Decay-aware hybrid RRF search (`search_mode: "hybrid"`, k=60), keyword degrade byte-identical to v1.0, forgiving FTS5 query handling (SEARCH-04, SEARCH-05) — Validated in Phase 4 (v1.1)
- ✓ `agent-memory export` writes format-v1 JSONL (versioned header with embedding model/dim and counts, memory + link records keyed by export-local ids, no vectors), stdout or atomic 0600 `--output` (DIST-04) — Validated in Phase 5 (v1.1)
- ✓ `agent-memory import --from jsonl` restores idempotently into empty or non-empty databases with key→id link remapping, expired rows skipped and counted, rows landing `embedding_status = 0` for the sweep backfill, malformed files rejected as `InvalidArgument("line N: …")` with nothing written (INTEROP-02) — Validated in Phase 5 (v1.1)

### Active

Expand All @@ -53,7 +59,7 @@ An agent can persist a structured memory and retrieve the right one later — ac

## Context

- **Current state (v1.1 Phase 3 complete, 2026-07-12):** API hardening landed on the shipped v0.0.1 codebase (validation seam + exact tag matching, 7/7 must-haves verified); CI revived on GitHub-hosted `ubuntu-latest` (D-12); cross-compile spike answered the milestone's feasibility unknown — all 4 legs GREEN, Phase 6 adopts cargo-xwin 0.23.0/msvc with mingw-w64/gnu fallback and the musl CFLAGS shim proven. Next: Phase 4 (memory_update, relations, hybrid RRF).
- **Current state (v1.1 Phase 5 complete, 2026-10-25):** Phases 3–5 landed on the shipped v0.0.1 codebase: validation seam + exact tag matching (Phase 3); `memory_update`, flat typed relations, migration 0003 hygiene and decay-aware hybrid RRF (Phase 4, 28/28 must-haves); portable JSONL export/import with format v1 frozen, plus storage-error redaction on every service path (Phase 5, 35/35 must-haves, live-Ollama round trip observed). CI on GitHub-hosted `ubuntu-latest` (D-12); release pipeline on GitHub-hosted runners with SLSA provenance (quick task 261009-hc1). Suite: 287 passed / 0 failed / 2 ignored, 95.6 % line coverage. Next: Phase 6 (musl + Windows binaries on the spike-chosen toolchains, v0.1.0 release).
- **v1.0 baseline (shipped 2026-07-12):** v0.0.1 released publicly — GitHub Release with 4 checksummed target tarballs (macOS arm64/x86_64, Linux x86_64/aarch64 gnu) + Homebrew tap (`brew install unityinflow/tap/agent-memory`). ~5,400 LOC Rust across `agent-memory-core` + `agent-memory` crates; clippy `-D warnings` clean; >80% coverage CI gate; 25/25 STRIDE threats closed. Known v2 debt: musl binaries (sqlite-vec BSD typedefs), Windows (cfg(unix) refactor), REST boundary-value hardening, SEARCH-04 hybrid RRF, MCP-06 update/relations, DIST-04 export.
- **Ecosystem position:** Tool 10 of 20 in UnityInFlow. Phase 3. Its own `CLAUDE.md` marks it *"Planned — no strict blocking dependencies,"* so it can proceed in parallel with the active Phase 2 close-out (budget-breaker starter, kore v0.1.0).
- **Why it exists:** Every agent tool reinvents state storage (GSD has STATE.md, Superpowers has skill context, RTK has its own SQLite DB). Switching runtimes loses all project context. A standard MCP memory API works across tools and survives sessions.
Expand Down Expand Up @@ -91,6 +97,10 @@ An agent can persist a structured memory and retrieve the right one later — ac
| Two-tier error taxonomy at the store seam (InvalidQuery → 400/invalid_params; internal → 500/internal_error) | Bad client input must never read as a server fault, on either transport | ✓ Good — proven live at 4 layers (02-05) |
| Phase 6 Windows toolchain: cargo-xwin 0.23.0/msvc first, mingw-w64/gnu as proven fallback; musl via zigbuild + `-Du_int*_t` CFLAGS shim | Phase 3 spike ran all 4 legs GREEN in one hosted dispatch (run 29196226289) — feasibility unknown answered before distribution work | ✓ Verdict recorded in spike-cross-compile.yml header |
| CI on GitHub-hosted `ubuntu-latest` for this public repo (ecosystem D-02 exception) | OPS-02 makes org self-hosted runners unreachable from public repos; the gate was silently dead | ✓ Good — first green runs since going public (D-12) |
| Export/import are CLI-only in v0.1.0; malformed files are `InvalidArgument` in core (Phase 5 D-01/D-11) | An MCP export would route the corpus through the JSON-RPC stdout channel and a REST import is an arbitrary-file-read primitive; keeping the error in core preserves the two-tier taxonomy for any later transport | ✓ Good — strict all-or-nothing parser, nothing written on failure, 25-row malformed table |
| JSONL format v1 is a frozen one-way contract: header (format/version/model/dim/schema/counts), memory and link records, derived fields and vectors excluded (Phase 5 D-03..D-06) | A shipped tool's export is a compatibility contract from the first file written; vectors are model-pinned derived data the sweep rebuilds for free | ✓ Good — goldens pin the wire order; any change needs `version: 2` + a reader for 1 |
| Import identity stays `(source, mem_type, content)`, links remap through a key→id map, created_at/expires_at/access_count preserved, last_accessed refreshed, expired rows skipped-and-counted, rows land pending and never embed inline (Phase 5 D-07..D-10, D-13) | Zero new schema; a preserved stale `last_accessed` would make a restore unfindable by rank; one re-embed mechanism, zero mixing risk | ✓ Good — review-driven hardening: post-remap self-links dropped, `access_count` bounded + saturating bump, dedup probe ignores expired-but-unswept rows |
| Storage-engine error text is redacted at the `MemoryService` seam on every public method, both transports and CLI (Phase 5 D-14, closes 04-REVIEW IN-01) | One seam beats two transport mappers; `SEARCH_STORAGE_FAILURE` text kept byte-identical so Phase 4 goldens hold | ✓ Good — 10 fault-injection tests incl. export/import, `/health`, MCP |

## Evolution

Expand All @@ -110,4 +120,4 @@ This document evolves at phase transitions and milestone boundaries.
4. Update Context with current state

---
*Last updated: 2026-07-12 after v1.1 Phase 3 (API hardening & toolchain spikes complete)*
*Last updated: 2026-10-25 after v1.1 Phase 5 (portable export & import complete; Phase 4 validations recorded retroactively)*
8 changes: 4 additions & 4 deletions .planning/REQUIREMENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ Each maps to a roadmap phase. IDs continue from the v1.0 numbering (archived in

### Portability (DIST / INTEROP)

- [ ] **DIST-04**: User can export all memories to a versioned JSONL file (header records format version + embedding model/dim; embeddings excluded as derived data; relation edges included with export-local key remapping)
- [ ] **INTEROP-02**: User can import that JSONL on another machine — idempotent re-run, imported rows land `embedding_status = 0` and re-embed via the existing sweep backfill, expired items skipped and counted
- [x] **DIST-04**: User can export all memories to a versioned JSONL file (header records format version + embedding model/dim; embeddings excluded as derived data; relation edges included with export-local key remapping)
- [x] **INTEROP-02**: User can import that JSONL on another machine — idempotent re-run, imported rows land `embedding_status = 0` and re-embed via the existing sweep backfill, expired items skipped and counted

### Distribution (DIST)

Expand Down Expand Up @@ -69,8 +69,8 @@ Mapped by roadmap creation 2026-07-12. Coverage: 12/12 v1.1 requirements mapped
| STORE-05 | Phase 4 | Complete |
| SEARCH-04 | Phase 4 | Complete |
| SEARCH-05 | Phase 4 | Complete |
| DIST-04 | Phase 5 | Pending |
| INTEROP-02 | Phase 5 | Pending |
| DIST-04 | Phase 5 | Complete |
| INTEROP-02 | Phase 5 | Complete |
| DIST-05 | Phase 6 | Pending |
| DIST-03 | Phase 6 | Pending |
| DIST-06 | Phase 6 | Pending |
Expand Down
27 changes: 24 additions & 3 deletions .planning/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Full phase details: [milestones/v1.0-ROADMAP.md](milestones/v1.0-ROADMAP.md)

- [x] **Phase 3: API Hardening & Toolchain Spikes** - Out-of-bounds limit/ttl rejected as client errors and exact tag matching at the shared service seam, plus early Windows/musl cross-compile spikes answering the milestone's only feasibility unknown (completed 2026-07-12)
- [x] **Phase 4: Memory Update, Relations & Hybrid Search** - `memory_update` with same-transaction re-embed, flat typed links with cascade, migration 0003 hygiene, and decay-aware hybrid RRF as a parallel track (completed 2026-10-23)
- [ ] **Phase 5: Portable Export & Import** - Versioned JSONL export (link edges included, embeddings excluded) and idempotent cross-machine import with sweep-backfill re-embedding
- [x] **Phase 5: Portable Export & Import** - Versioned JSONL export (link edges included, embeddings excluded) and idempotent cross-machine import with sweep-backfill re-embedding (completed 2026-10-25)
- [ ] **Phase 6: Distribution & v0.1.0 Release** - musl + Windows binaries on the spike-chosen toolchains and the checksummed v0.1.0 release with Homebrew update and behavioral-change release notes

## Phase Details
Expand Down Expand Up @@ -104,7 +104,28 @@ Plans:
3. Imported rows land with `embedding_status = 0` and become semantically searchable after the existing sweep backfill re-embeds them — no embedding vectors travel in the file.
4. Expired items in the file are skipped and counted, and the import report states imported/skipped/duplicate counts; malformed files (bad header/version/rows) are rejected as client errors through the Phase 3 seam, never a 500 or crash.

**Plans**: TBD
**Plans**: 5/5 plans executed (4 executed + 1 gap closure)

Plans:
**Wave 1**

- [x] 05-01-PLAN.md — D-14 storage-error redaction on every service path (tracer: seam → REST `/health` + `POST` → MCP → README) + the store contract both later tracers consume: `Store::find_by_key`, `LinkOutcome::Linked { created }`, `ImportedMemory` / `Store::insert_imported` (INTEROP-02)

**Wave 2** *(blocked on Wave 1)*

- [x] 05-02-PLAN.md — `agent-memory export`: format v1 `Record` enum + golden tests, one-snapshot `Store::export_rows`, streaming `MemoryService::export`, stdout default + atomic 0600 `--output` (DIST-04)

**Wave 3** *(blocked on Wave 2)*

- [x] 05-03-PLAN.md — `agent-memory import --from jsonl`: strict two-pass `parse_jsonl` + `import_jsonl` with key→id remapping, expiry skip, pending re-embed, six-count report; PITFALLS 18/19 kill-tests + malformed-file table (INTEROP-02, DIST-04)

**Wave 4** *(blocked on Wave 3)*

- [x] 05-04-PLAN.md — README "Export & import" section (format v1 spec, timestamp policy, pending embeddings, backup-vs-export) + spawned-binary CLI round trip (DIST-04, INTEROP-02)

**Gap closure** *(from 05-VERIFICATION.md `human_verification` items — converts both human items into explicit, re-runnable evidence)*

- [x] 05-05-PLAN.md — Gap wave 5: held-out race test for the 05-02 one-snapshot backstop truth (`a_concurrent_link_committed_mid_export_cannot_produce_a_dangling_key`: a memory + link committed mid-export are invisible to that snapshot and present in the next) + recorded live-Ollama realism run (export A → import B → first-sweep backfill → hybrid paraphrase search, `05-05-realism.sh`) (DIST-04, INTEROP-02)

### Phase 6: Distribution & v0.1.0 Release

Expand All @@ -131,5 +152,5 @@ Phases execute in numeric order: 3 → 4 → 5 → 6
| 2. Semantic Search, Interop & Release | v1.0 | 5/5 | Complete | 2026-07-12 |
| 3. API Hardening & Toolchain Spikes | v1.1 | 2/2 | Complete | 2026-07-12 |
| 4. Memory Update, Relations & Hybrid Search | v1.1 | 7/7 | Complete | 2026-10-23 |
| 5. Portable Export & Import | v1.1 | 0/? | Not started | - |
| 5. Portable Export & Import | v1.1 | 5/5 | Complete | 2026-10-25 |
| 6. Distribution & v0.1.0 Release | v1.1 | 0/? | Not started | - |
51 changes: 35 additions & 16 deletions .planning/STATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@
gsd_state_version: 1.0
milestone: v1.1
milestone_name: Hardening & Interop
current_phase: 5
current_phase_name: Portable Export & Import
current_phase: 6
current_phase_name: Distribution & v0.1.0 Release
status: planning
stopped_at: Phase 04 complete, ready to plan Phase 5
last_updated: "2026-10-23T20:25:00.455Z"
last_activity: 2026-10-23
last_activity_desc: Phase 04 complete, transitioned to Phase 5
state_head: 4441bdafab5d420a1fbcf3ba348c0589d72bdc11
stopped_at: Phase 5 complete, ready to plan Phase 6
last_updated: "2026-10-25T13:51:46.548Z"
last_activity: 2026-10-25
last_activity_desc: Phase 5 complete, transitioned to Phase 6
state_head: fe18db796014dc9d885859771ee089ce7ba895df
progress:
total_phases: 4
completed_phases: 2
total_plans: 9
completed_plans: 9
completed_phases: 3
total_plans: 14
completed_plans: 14
---

# Project State
Expand All @@ -24,22 +24,22 @@ progress:
See: .planning/PROJECT.md (updated 2026-07-12)

**Core value:** An agent can persist a structured memory and retrieve the right one later — across sessions and tools — over a standard MCP interface, with no cloud.
**Current focus:** Phase 04 — Memory Update, Relations & Hybrid Search
**Current focus:** Phase 5 — Portable Export & Import

## Current Position

Phase: 5 — Portable Export & Import
Phase: 6 — Distribution & v0.1.0 Release
Plan: Not started
Status: Ready to plan
Last activity: 2026-10-23 - Completed quick task 261023-v6w: WR-04: reject memory_list expand_links without limit
Last activity: 2026-10-25 — Phase 5 complete, transitioned to Phase 6

Progress: [░░░░░░░░░░] 0% (0/4 v1.1 phases)

## Performance Metrics

**Velocity:**

- Total plans completed: 17
- Total plans completed: 22
- Average duration: ~28 min
- Total execution time: ~1.4 hours

Expand All @@ -51,6 +51,7 @@ Progress: [░░░░░░░░░░] 0% (0/4 v1.1 phases)
| 02 | 5 | - | - |
| 03 | 2 | - | - |
| 04 | 7 | - | - |
| 5 | 5 | - | - |

**Recent Trend:**

Expand All @@ -76,6 +77,11 @@ Progress: [░░░░░░░░░░] 0% (0/4 v1.1 phases)
| Phase 04 P05 | 10 min | 3 tasks | 12 files |
| Phase 04 P06 | 7 min | 3 tasks | 9 files |
| Phase 04 P07 | 12 min | 3 tasks | 7 files |
| Phase 05 P01 | 14 min | 3 tasks | 10 files |
| Phase 05 P02 | 13 min | 2 tasks | 8 files |
| Phase 05 P03 | 16min | 2 tasks | 6 files |
| Phase 05 P04 | 9 min | 2 tasks | 2 files |
| Phase 05 P05 | 6 min | 2 tasks | 2 files |

## Accumulated Context

Expand Down Expand Up @@ -123,6 +129,19 @@ Recent decisions affecting current work:
- [Phase 04]: 04-07: deny_unknown_fields added to UpdateArgs/UpdateBody only (new v0.1.0 surfaces, REVIEW WR-02); the [03-01] decision stands for the v0.0.1 DTOs, so the v0.1.0 release-notes delta for existing surfaces is unchanged. Over MCP, rmcp 1.8 reports the rejection as a tool error result (isError: true, "failed to deserialize parameters: unknown field ..."), not a JSON-RPC -32602; REST is a 400 {"error"}.
- [Phase 04]: 04-07: backup temp is pid-qualified and a process-wide BACKUP_LOCK serializes backups within one process, so same-process openers never share a temp; prune tolerates NotFound from a concurrent opener
- [Phase 04]: 04-07: WR-01 closed with verify-then-rename + tolerate-by-re-probe (no file lock, no new dep); cross-process exclusive lock stays deferred
- [Phase 05-01]: redact_storage_error(op, e) at the MemoryService seam on all nine methods (store, list, search, import, forget, link, unlink, update, sweep) via *_unredacted inner fns; transport mappers byte-identical; closes 04-REVIEW IN-01 (D-14)
- [Phase 05-01]: Store::exists -> Store::find_by_key(Option<i64>) with the same NULL-safe (source, mem_type, content) key (D-07); LinkOutcome::Linked { created: bool } from tx.changes() across 7 sites, storage-only not a wire change (D-12)
- [Phase 05-01]: ImportedMemory + Store::insert_imported (no embedding parameter, always embedding_status 0, last_accessed = now, created_at/access_count/expires_at preserved) behind one shared insert_row helper; importer skips expires_at <= now, sweep deletes < now (D-10, D-13)
- [Phase 5]: [Phase 05-02]: Format v1 frozen in export.rs as one strict tagged Record enum (record first, declaration order, deny_unknown_fields; header carries exported_rows/exported_links); wire order golden-tested; D-03 one-way rating recorded as pre-approved
- [Phase 5]: [Phase 05-02]: Store::export_rows streams every row from ONE pooled connection + ONE read transaction (rusqlite unchecked_transaction) — meta pin, counts, memories ORDER BY id, links ORDER BY from_id,to_id,kind — via a visitor, never a Vec; MemoryService::export flushes inside spawn_blocking and redacts with op export (tenth op string)
- [Phase 5]: [Phase 05-02]: Research correction: stdout export sink is BufWriter::new(std::io::stdout()) — StdoutLock is !Send and cannot be a Box<dyn Write + Send>; --output publishes via export_file::PendingExport ({target}.export-tmp-{pid} beside the target, create_new + 0600, sync_all then rename, one abort covers every failure)
- [Phase 5]: 05-03: jsonl importer is add-alongside beside gsd-state — two parser modules, two tolerance policies (strict vs tolerant), shared seam/dedup/writer lane; a third format forces an ImportSource enum
- [Phase 5]: 05-03: D-11 messages — HeaderProbe format/version are Option (non-header line 1 → 'first record must be the header'), serde's ' at line 1 column N' suffix stripped, InvalidArgument payload lifted before the 'line N:' prefix
- [Phase 5]: 05-03: import_jsonl runs passes 2+3 in ONE spawn_blocking hop with per-record writer transactions; parse_jsonl is the all-or-nothing gate; the jsonl path never calls the embedder
- [Phase 05]: 05-04: README Export & import section is one ## with ten ### subsections in plan order; sweep cadence documented as the shipped 'then hourly' (SWEEP_INTERVAL 3600 s); tests/cli.rs is realism-only (zero coverage by design, like tests/rest.rs) and pins the exact report strings
- [Phase 05]: 05-04: phase-end gates recorded — cargo llvm-cov 95.61% lines (floor 80), D-01 transport grep empty, sql/ + Cargo.lock + .github/ unchanged across all phase-5 commits
- [Phase 5]: [05-05]: Gap 1 (DIST-04 backstop truth 2.8) closed with a channel-ordered race test driving Store::export_rows directly — WAL snapshot isolation proven, no production change; every wait bounded by recv_timeout
- [Phase 5]: [05-05]: Gap 2 (INTEROP-02 live re-embed) closed by a recorded run of the real binary against local nomic-embed-text (05-05-realism.sh, exit 0: backfilled=3 on first sweep tick, search_mode hybrid, target rank 0) — stays a script, never a cargo test

### Pending Todos

Expand Down Expand Up @@ -164,8 +183,8 @@ Items acknowledged and carried forward:

## Session Continuity

Last session: 2026-10-23T20:12:50.720Z
Stopped at: Phase 04 complete, ready to plan Phase 5
Last session: 2026-10-25T13:42:17.195Z
Stopped at: Phase 5 complete, ready to plan Phase 6
Resume file: None

## Operator Next Steps
Expand Down
Loading
Loading