Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
8719738
feat(memory): add V1 migration audit and deprecation guidance
AnzoBenjamin Sep 12, 2026
aa60102
docs(memory): define V1 removal readiness gates
AnzoBenjamin Sep 12, 2026
2946c98
feat(memory): harden V1 evidence handling and migration audit
AnzoBenjamin Sep 13, 2026
722c510
test(memory): fix coordinator test contract + refactor marker ownersh…
AnzoBenjamin Sep 13, 2026
eb1e79e
fix(memory): compare migration drafts order-insensitively
AnzoBenjamin Sep 13, 2026
99affaf
test(memory): real-SQLite import+audit round-trip for key-order
AnzoBenjamin Sep 13, 2026
d9c4c09
test(memory): move SQLite migration round-trip test to cli package
AnzoBenjamin Sep 13, 2026
ce3a178
docs(memory): note order-insensitive migration audit + SQLite round-t…
AnzoBenjamin Sep 13, 2026
cfb126d
feat(memory): add SQLite secure-open gate and bounded projection replay
AnzoBenjamin Sep 13, 2026
9c13f25
chore: updating the relevant docs
AnzoBenjamin Sep 13, 2026
afd2292
fix(gate): resolve deleted-before-snapshot files to missing marker
AnzoBenjamin Sep 13, 2026
acbc8ce
test(gate): create aux-triple fixture on disk so seeded findings surv…
AnzoBenjamin Sep 13, 2026
bb38cba
fix(gate): retire stale owed-reviewer reference on prune
AnzoBenjamin Sep 13, 2026
36ca9e0
test(gate): align reviewer-marker parity mirror with missing-file pro…
AnzoBenjamin Sep 13, 2026
cf5d8f4
test(gate): robust hoisted-const slice and visible symlink-skip loggi…
AnzoBenjamin Sep 14, 2026
f62d761
test(gate,cli): fix flaky status-bar act and fail-fast slice guard
AnzoBenjamin Sep 14, 2026
543bae8
docs(cli): document OpenTUI reconciler act wrapping convention in kno…
AnzoBenjamin Sep 14, 2026
765f5f8
docs(memory-v2): record R7-T3 harness-limitation blocker and finalize…
AnzoBenjamin Sep 14, 2026
64a9348
fix(spawn): omit-for-manual snapshot_id and calm spawn error noise
AnzoBenjamin Sep 14, 2026
9d4a8f3
docs(agents): label manual reviewer echoes unattested + refresh knowl…
AnzoBenjamin Sep 15, 2026
895e2b7
test(specialists): pin optional snapshot_id omit-for-manual contract
AnzoBenjamin Sep 15, 2026
fd7e978
test(quality-prompts): fix stale snapshot_id contract comment
AnzoBenjamin Sep 15, 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
9 changes: 9 additions & 0 deletions .agents/sessions/dynamic-cross-session-memory/LESSONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,12 @@ Raw SQLite database bytes are not a valid reopen-idempotence contract under WAL
- Export retry idempotency requires EEXIST handling that compares existing content rather than failing deterministically on identical checksums.
- finishTurn must be bounded against the run abort signal; an unbounded await on a hung SQLite store can delay run termination indefinitely.
- Post-abort tool observations need a generation gate; isCurrent(undefined) returning true unconditionally allows commits after invalidate.


<!-- update_plan_status:appended -->
## Specialist-token / clean-tree limitation — 2026-09-14T09:12:00.000Z

- Reviewer-family specialists (`compatibility-reviewer`, `migration-reviewer`, `reliability-reviewer`, `performance-specialist`, `accessibility-reviewer`, `ux-visual-reviewer`, `dependency-reviewer`, `product-reviewer`, `evaluator`) require `params.snapshot_id` matching `^v3:[a-f0-9]{64}$`. That token is `hashGateSnapshotDetails(files-v4 details of PENDING files)` = `'v3:' + sha256(details)`. With a CLEAN worktree there are no pending files, so the fingerprint is a constant and `gate-state.ts` documents it "never mints a receipt, for any kind" (`'no-diff'` = constant by construction).
- Consequence: R7-T3-style "one frozen bundle, every specialist carries the SAME gate-assigned token" is UNREPRESENTABLE on a fully-committed clean tree. It is a harness-design limitation, not a flaky failure. Only `security-reviewer` (looser `changed_files` + `snapshot_fingerprint` contract) can run post-commit.
- Anti-pattern to avoid: manufacturing a throwaway dirty edit purely to mint a token is evidence theater — the receipts attest the synthetic delta, not the shipped artifact, and go stale on revert. Never launder a same-shaped token into false credit.
- Correct disposition: mark such a task BLOCKED (not done) with a repro; proceed with dependent finalization only under an explicitly-labeled evidence-substituted basis; file the fix (a `committed-surface` snapshot mode minting `v3:<64hex>` deterministically from the committed tree at HEAD, gated to clean worktree + non-empty fileset) as the real unblocker.
5 changes: 3 additions & 2 deletions .agents/sessions/dynamic-cross-session-memory/PLAN.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# PLAN — Dynamic Cross-Session Memory V2 Repair

Session: `dynamic-cross-session-memory`
Status: ready for implementation
Status: implementation complete; R7-T2 green; R7-T3 blocked by harness limitation (see STATUS.md).

<!-- current-task: MEM2-R3-T1 Repair SDK migration/operator atomicity and trust boundaries -->
<!-- current-task: -->

## Execution rules

Expand Down Expand Up @@ -95,6 +95,7 @@ Status: ready for implementation
- Depends on: MEM2-R7-T2
- Build one fresh bundle and freeze mutations while security, compatibility, migration, reliability, and final code review run.
- Acceptance: every reviewer returns a structured non-blocking verdict with the matching fingerprint; quota/protocol failures are retried only against a fresh stable bundle and are never counted as approval.
- Status: BLOCKED by harness design — a fully-committed clean tree mints no gate-assigned `v3:<64-hex>` token, so reviewer-family specialists cannot be spawned against HEAD. See STATUS.md for the repro and the proposed `committed-surface` fingerprint mode.
- Validate: record fingerprint and receipt IDs in `STATUS.md`.

- [ ] MEM2-R7-T4 Finalize durable artifacts
Expand Down
81 changes: 78 additions & 3 deletions .agents/sessions/dynamic-cross-session-memory/STATUS.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# STATUS — Dynamic Cross-Session Memory V2 Repair

Status: ready for implementation; source work is incomplete and reviewer-blocked.
Current phase: R0contract freeze.
Current task: MEM2-R0-T1 Freeze and align canonical contracts.
Status: implementation complete; MEM2-R1-T2 resolved (typed-unsupported secure-open fallback); R7-T2 green; R7-T3 BLOCKED by harness limitation (see R7 gate entry at end).
Current phase: R7integration / finalization.
Current task: none active. R7-T3 is blocked pending the proposed `committed-surface` harness fix; R7-T4 durable-artifact finalization is dispositioned below.

## Implemented and locally validated before this plan refresh

Expand Down Expand Up @@ -138,3 +138,78 @@ All declared workflow items complete.
- reliability-reviewer: 4 findings repaired (export retry, bounded finishTurn, generation-gated observations, leaf error masking)

**Discovery coverage vertical slice** shipped: taskId + workspaceSnapshotId in schema, coordinator, spawn wiring, and 3 new tests.

<!-- update_plan_status:appended -->
## Plan tracking re-verified against live worktree — 2026-09-12

Re-verified the durable plan's stale tracking against the live worktree. Focused suites are green: MEM2-R3-T1 migration/operator/coordinator 96/96; MEM2-R1-T1 SQLite kernel 44/44. The only remaining gate is MEM2-R1-T2 (race-resistant SQLite open). Verified fact: race-free WAL/SHM open is provably impossible in pure JS with bun:sqlite (SQLite opens the -wal/-shm sidecars by derived pathname internally; bun:sqlite accepts a path string only — no fd, no dirfd-relative open). R1-T2 therefore resolves via its typed-unsupported fail-closed fallback (report a typed unavailable outcome, perform no SQLite mutation where race-resistance cannot be proven); full race closure is deferred pending explicit native-addon/dependency authorization (SPEC decision #9, option C).

<!-- update_plan_status:appended -->
## R1-T2 typed-unsupported secure-open + R7 integration matrix — 2026-09-13T19:33:12.321Z

MEM2-R1-T2 resolved via its typed-unsupported fail-closed fallback. Verified fact: race-free SQLite open is provably impossible in pure JS with bun:sqlite (path-only constructor; -wal/-shm sidecars open by derived pathname internally, no fd/dirfd support). Implemented a hybrid: a strict `requireSecureOpen` opt-in gate in `BunSQLiteMemoryRepository.open()` that fails closed with a typed non-retryable `unsupported-open` error and performs zero SQLite mutation, plus a default-on honest `openPosture: 'pathname-best-effort-unverified-open'` visibility field on the open result and `kernelHealth`. Default open path and all pre-existing pathname hardening are unchanged. No dependency added (SPEC #9 respected); full WAL/SHM race closure deferred pending native-addon authorization (option C).

Security review: LOOKS_GOOD, 0 findings (strict gate prevents all mutation; no path/SQL/secret leak; no false security claim; default path unregressed).

R7 integration matrix re-run against this state (all green):
- SDK Memory V2: 117/117 (coordinator, v1-migration, operator-service, contract, run-cancellation)
- CLI Memory V2: 201/201 across 9 files (SQLite repo 47 incl. 3 new strict-secure-open tests, contained-file-io, provider, roundtrip, memory-command, codebuff-client, env, slash-commands, memory-box)
- common Memory V2 contracts: 42/42
- agent-runtime: 39/39 (task-memory, memory-v2-context)
- Monorepo typecheck: 11/11 packages pass


<!-- update_plan_status:appended -->
## Projection replay cap + R2 verification — 2026-09-13T19:53:39.176Z

Addressed the gate advisory that rebuildProjections/replayProjections had no event cap. Added `MAX_REPLAY_EVENTS = 10_000` (consistent with `MAX_QUERY_EVENTS`); `replayProjections(database, maxEvents)` now stops the paged replay loop at the cap, and on truncation sets the projection cursor to the last replayed sequence and returns `truncated: true` rather than throwing or falsely claiming the canonical tail. `rebuildProjections()` surfaces `truncated: boolean` on its ok-result. v1→v2 `migrate()` passes `Number.MAX_SAFE_INTEGER` so migration replay stays complete; rollback-on-failure unchanged. Backward-compatible and additive.

R2 (SDK run/coordinator reliability) verified green: coordinator + run-cancellation 53/53.

Validation: SQLite focused suite 49/49 (2 new cap tests + 1 updated), V1→V2 round-trip 1/1, cli typecheck clean, Prettier clean.

<!-- update_plan_status:appended -->
## projectId index advisory evaluated — no change warranted — 2026-09-13T20:17:06.358Z

Evaluated the reviewer advisory that `scanQueryRows`/`readLastEventIdForProject` use unindexed `json_extract` projectId filters. Benchmarked at the current 10k-event cap (50 iterations each): 250-row filtered query mean 0.815ms unindexed vs 0.671ms with an expression index (within noise); tail query 0.009ms vs 0.008ms. EXPLAIN QUERY PLAN confirms the expression index is used when present, but the absolute cost is already sub-millisecond at the cap. Decision: no schema/index change now; revisit only if the event cap grows materially. Recorded as a data-backed no-change decision.


<!-- update_plan_status:appended -->
## R4/R6 verification + phantom-file gate fix + 'missing' marker constant — 2026-09-13T22:50:29.563Z

Re-verified the memory-v2 plan's remaining focused suites in the current tree: R4 provider/client authority (provider + env) 26/26; R6 coverage/prompt safety (agent-runtime task-memory + memory-v2-context + loop-agent-steps) 84/84; memory-retention eval 6/6. R1-T1 (SQLite 44/44), R1-T2 (typed-unsupported secure-open), R2 (coordinator 53/53), R3-T1 (migration/operator 96/96) all confirmed green. Only R7 finalization (stable exact-snapshot reviews) remains.

Also shipped the phantom-file gate fix (commits afd2292d8 + acbc8ce09): a pending gate file deleted before its first snapshot now resolves to the `missing` content marker (attested-by-absence), and open findings whose files are all missing are pruned at turn start — closing the scripts/perf-probe-tmp.ts review loop. Follow-up hardening: extracted the `'missing'` sentinel into a single in-handleSteps constant `GATE_FILE_MISSING_CONTENT_MARKER` shared by readGateFileContentMarker, collectDeletedFilesFromSnapshotDetails, the turn-start prune, and isCreditableContentMarker. Pure refactor; agents typecheck clean and gate/parity/serialization suites 255/255.


<!-- update_plan_status:appended -->
## Parity-mirror fix for missing-marker (pre-push green) — 2026-09-13T23:36:05.557Z

Fixed the pre-push hook failure that blocked the gate-improvement push: the test-local `gateFileMarker` mirror in `agents/e2e/reviewer-spawn-conditions.e2e.test.ts` had drifted from production `readGateFileContentMarker` (which now returns `'missing'` for a nonexistent path). Root-caused with a debugger: the parity oracle extracts only the `readGateFileContentMarker` function body, so the `GATE_FILE_MISSING_CONTENT_MARKER` const (declared earlier in `handleSteps`) was unbound in the synthetic `new Function` scope, making the ENOENT probe throw a ReferenceError surfaced as `unreadable:unknown`. Fixed two ways: (1) added the early `lstatSync` existence probe to the test mirror so it returns `missing` for nonexistent paths like production, and (2) updated `loadProductionGateFileContentMarker` to hoist the `GATE_FILE_MISSING_CONTENT_MARKER` declaration into the synthetic eval scope (following the `specialist-router-parity.test.ts` hoisted-constant precedent), preserving the const's single-source-of-truth and the drift-safety property. Validated: parity suite 19/19, full agents suite 1184 pass / 0 fail, agents typecheck clean.


<!-- update_plan_status:appended -->
## R7-T2 package-wide validation green — 2026-09-14T06:32:15.052Z

Re-ran MEM2-R7-T2 (package-wide validation + artifact smoke) on the current tree to produce a fresh green baseline before R7-T3. Results: monorepo typecheck 11/11; common 1245 pass; agent-runtime 1618 pass; sdk 1398 pass / 1 skip; cli 3093 pass / 15 skip / 2 fail; evals memory-retention 6/6. SDK build (ESM/CJS/types) and `smoke-test:dist` (CJS require + tree-sitter) passed; CLI binary build + `--version` probe passed. The 2 CLI failures are the known flaky `StatusBar` React-act tests (`renders the status label...` and `hides the scroll control...`), which pass 3/3 in isolation, were untouched by this work, and are unrelated to memory-v2 — a pre-existing flake, not an R7 blocker. R7-T2 acceptance met.


<!-- update_plan_status:appended -->
## R7-T3 BLOCKED (harness limitation) + R7-T4 disposition — 2026-09-14T09:12:00.000Z

**R7-T3 "obtain stable exact-snapshot reviews" — status: BLOCKED (not done).**

The memory-v2 feature is fully committed at HEAD `543bae880` with a clean worktree, so there is no pending gate-file set to fingerprint. Reviewer-family specialists (`compatibility-reviewer`, `migration-reviewer`, `reliability-reviewer`) require `params.snapshot_id` matching `^v3:[a-f0-9]{64}$`, and that token is minted by `hashGateSnapshotDetails(details)` = `'v3:' + sha256(files-v4 details of PENDING files)` (`agents/base2/gate-fingerprint.ts`, `isAttestableSnapshotFingerprint`). With no pending files that fingerprint is a constant, and `agents/base2/gate-state.ts` documents that a `'no-diff'` fingerprint "is a CONSTANT by construction" and that a non-attestable fingerprint "never mints a receipt, for any kind." So R7-T3's own rule — "every specialist spawn must carry the SAME gate-assigned `params.snapshot_id`" — is **unsatisfiable on a committed clean tree by construction**. It is not a flaky failure and not user error.

**Repro:** (1) `get_change_review_bundle` → `files=["cli/knowledge.md"]` and a bare-hex `snapshotId` that is evidence-only (changes every call, explicitly non-reusable per the params contract). (2) A reviewer-family spawn with `params.snapshot_id` = that bare hex / the truncated display form `v3:131ae03adb957` is rejected as "invalid params" (no legacy-format bypass exists). Only `security-reviewer` uses the looser `changed_files` + `snapshot_fingerprint` contract, which is why it alone ran.

**Equivalent-evidence package (NOT a frozen-bundle signoff):**
- R7-T2 green package-wide baseline at `543bae880` (above).
- `security-reviewer`: NON_BLOCKING with 2 low advisories (both accepted) — valid under its looser contract; run against the current bundle.
- Prior migration / compatibility / reliability receipts from **earlier dirty-tree gates over these exact files** — they attest to their edit snapshots, not to HEAD-as-shipped. Explicitly labeled as such.
- **No NEW frozen bundle is representable post-commit.**

**Proposed fix (the real unblocker):** add a `committed-surface` snapshot mode that mints `v3:<64hex>` deterministically from the committed tree at HEAD (enumerate reviewable files at HEAD with content markers; hash via the existing `buildGateSnapshotDetails(files, '')` + `hashGateSnapshotDetails`), gated to be usable only when the worktree is clean and the fileset is non-empty. This makes R7-T3 mechanically satisfiable for post-commit review without weakening the dirty-tree contract — an additive evidence *kind* (like the existing `'reviewed-diff'` vs `'no-diff'`), not a new trust model. **Do not mark R7-T3 done until this lands and a real bundle is frozen.**

**R7-T4 "finalize durable artifacts" — status: PROCEED, explicitly evidence-substituted.**
PLAN/STATUS/LESSONS now reflect the actual worktree, the R1-T2 supported/disabled platform decision, the R7-T2 receipts, and the deferred default-cutover/native-helper work; the PLAN current-task pointer is cleared. This is **explicitly NOT a frozen-bundle signoff** — it is an equivalent-evidence disposition pending the `committed-surface` fix. Do not claim "all four specialists attested the same snapshot": one did (security); three did not and could not.
2 changes: 1 addition & 1 deletion .agents/types/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -979,7 +979,7 @@ export interface SpawnAgentsParams {
push?: boolean
/** Remote used for fetch/push (git-committer) */
remote?: string
/** Assigned gate snapshot fingerprint (reviewer specialists) */
/** Optional gate-assigned snapshot token (reviewer specialists). Runtime-owned spawns pass the gate-assigned v3:… token; manual spawns omit this key entirely. */
snapshot_id?: string
/** Changed file paths to review (security-reviewer) */
changed_files?: string[]
Expand Down
Loading
Loading