Skip to content

A SQLite store and durable capture (story 28.7) - #221

Merged
fabbrik merged 5 commits into
mainfrom
feat/28-7-sqlite-durable-capture
Oct 30, 2026
Merged

fabbrik merged 5 commits into
mainfrom
feat/28-7-sqlite-durable-capture

Conversation

@fabbrik

@fabbrik fabbrik commented Oct 30, 2026

Copy link
Copy Markdown
Owner

Story 28.7 of Epic 28; closes story 26.2's gap.

  • AgentExperience.Storage.Sqlite (new package): UseSqlite(path); record store with lifecycle compare-and-set (BEGIN IMMEDIATE, WAL), holdout, provider holdout and injections; FTS5 text search with the any-term rule and coverage ranking; failure-signature search; reuse feedback. Passes the shared conformance suites. Erasure leaves no text behind in the FTS index or the file (secure_delete, index optimize, WAL checkpoint; the test scans the shadow tables and raw bytes). Directory 0700, file 0600; schema version checked on first use; migration explicit or opt-in on first use. Retrieval-quality SQLite column with its golden.
  • Durable capture: IExperienceRunStore (SQLite and PostgreSQL migration 0032, opt-in). Capture saves each completed, sanitized run off the caller's thread with a bounded wait; a failed save never fails the run. FinalizeAsync falls back to the run store, so a run can be finalized in a later process with the same verification and replay rules. A storage-denied finalization deletes the stored run; erasure leaves a run tombstone so a retry cannot resurrect it; ShouldPersistRun lets a host keep runs out.
  • Dogfood: CI triage --storage sqlite:<path> finalizes a failure in a later pass when its fix lands; quick start --sqlite.

Tests: Storage.Sqlite 244, Core 1348, MAF 1439, Release 198, Storage.Postgres 952-964 (default, RLS, encrypted), Upgrade 3 (both modes), contract 102.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GPXz56QPQAzDSyJTxbQTTy

fabbrik and others added 5 commits October 30, 2026 18:33
… and reuse feedback (story 28.7, part 1)

New package AgentExperience.Storage.Sqlite: one local file, UseSqlite(path), a journaled
schema migrator (WAL, busy timeout, foreign keys), erasure to a tombstone, the store
conformance suites in full, and a SQLite column in the retrieval benchmark.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GPXz56QPQAzDSyJTxbQTTy
…ess (story 28.7, part 2)

IExperienceRunStore in Abstractions, implemented by SqliteExperienceRunStore (registered by
UseSqlite) and PostgresExperienceRunStore (opt-in, migration 0032 with grants, row-level
security and an erasure trigger). The capture service writes each completed run through,
reporting a failed save without failing the run; finalization falls back to the run store and
marks the run finalized. Run store conformance suite on both stores; a two-provider round trip
on SQLite and PostgreSQL.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GPXz56QPQAzDSyJTxbQTTy
…e (story 28.7, part 3)

--storage sqlite:<path> in the CI triage experiment triages a failure still waiting for its
fix and finalizes its stored run in a later pass once the fix lands (scripted two-pass test).
The quick-start sample takes --sqlite <path>: a second process is handed the first one's
lesson. Migrating a new SQLite file creates its directory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GPXz56QPQAzDSyJTxbQTTy
Erasure rewrites the FTS5 index, runs with secure_delete and checkpoints the WAL; erased runs
become run-store tombstones a capture retry cannot overwrite (both stores); StorageDenied
deletes the stored run; run saves run off the caller's thread with a bounded wait, a host
predicate and SQLite's short busy timeout, and rethrow the caller's cancellation; new files are
owner-only; stores check the schema version once and first-use migration is async and caches
success only; CI triage bounds-checks the awaiting note; the package verifier says seven.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GPXz56QPQAzDSyJTxbQTTy
…s (story 28.7)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GPXz56QPQAzDSyJTxbQTTy
@fabbrik
fabbrik merged commit 24556dc into main Oct 30, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant