Repository navigation
Store WorkflowRuns and filtered journals in SQLite #291
Description
Story
As a workflow user, I want a WorkflowRun and its filtered journal retained in one local SQLite database, so another process can find the run by ID and resume from durable data rather than an agent transcript or Git sidecar ref.
Scope
Build the first production persistence boundary from the identity contract merged in #289 / PR #341.
Each WorkflowRun owns one SQLite database. This issue owns:
- creation and lookup by public run ID;
- immutable definition identity, base pin, normalized props, execution attempts, status, and stop reason;
- append and replay of already-filtered durable journal events;
- schema versioning and explicit compatibility errors; and
- the storage interfaces used contextually by shared production code.
The database is the physical retention boundary for later versioned filesystem roots, Repository/Worktree metadata, and Agent-session mappings, but those remain logical stores implemented by their own stories. Arbitrary Workspace file content is not journal or training data merely because it shares a database file.
No required state lives only in an Agent transcript, process memory, branch name, document path, or refs/xmd/runs.
Acceptance
- A host-generated or authorized caller-selected run ID creates exactly one WorkflowRun.
- A later process finds the run by ID without consulting the document path or current Git branch.
- Definition identity, base pin, normalized props, attempts, status, and stop reason survive restart.
- Filtered journal entries append and replay in order with stable event identity.
- Existing journal secret filtering runs before insertion; this story adds no second filtering policy.
- Schema mismatch or corrupt storage fails explicitly and never creates an empty replacement while claiming continuation.
- Shared modules use contextual storage APIs and contain no SQLite or runtime detection.
- Tests cover creation, compatible lookup, incompatible ID reuse, restart, append failure, corruption, and concurrent ownership attempts.
Intentionally excluded
- DOFS mutation transactions (Commit Workspace mutations and journal results atomically #365).
- Public start/resume commands (Add the xmd workflow start/resume filesystem vertical slice #366).
- Lifecycle inspection and deletion (Add workflow inspection, cancellation, suspension, and deletion #367).
- History forks (Add versioned workflow history checkpoints and forks #368).
- Git refs, automatic remote backup, or training ingestion.
Dependencies
- Add contextual workflow runs with pinned commits #289 / PR 💥 Add expansion identity and pinned-commit workflow runs #341 supplies WorkflowRun and expansion identity.
- Reject secrets before journal persistence by default #199 supplies the existing pre-journal secret gate.
- PR 📝 Specify retained workflow Workspaces #358 supplies the retained Workspace architecture and observable contract.
- End goal: ✨ Compose and certify the supervised adversarial implementation workflow #181.
Activity
📝 Synchronize the living end-goal target with current XMD contracts
📝 Synchronize the living end-goal target with current XMD contracts
📝 Make the user's decision gate execution, and correct the result inv…
📝 Return the gate's sources, not a second copy of its answer
📝 State the handle boundary, the two text components, and the objecti…
[-]Persist the Workflow artifact ledger under refs/xmd/runs[/-][+]Persist the workflow-run artifact ledger under refs/xmd/runs[/+]💥 Replace invocation() with getExpansion() and derive expansion identity
💥 Replace invocation() with getExpansion() and derive expansion identity
💥 Add expansion identity and pinned-commit workflow runs (#341)
[-]Persist the workflow-run artifact ledger under refs/xmd/runs[/-][+]Store WorkflowRuns and filtered journals in SQLite[/+]🐛 Keep the Deno storage suites inside the Node typecheck (#291)
🐛 Commit only once the transaction's own scope has closed (#291)
🐛 Hold storage to its structure, its meanings, and its silence (#291)
♻️ Give each storage test one number (#291)
79 remaining items
📝 Synchronize the living end-goal target with current XMD contracts
📝 Make the user's decision gate execution, and correct the result inv…
📝 Return the gate's sources, not a second copy of its answer
📝 State the handle boundary, the two text components, and the objecti…
📝 Reconcile the living target with the settled workflow contracts
📝 Synchronize the living end-goal target with current XMD contracts
📝 Make the user's decision gate execution, and correct the result inv…
📝 Return the gate's sources, not a second copy of its answer
📝 State the handle boundary, the two text components, and the objecti…
📝 Reconcile the living target with the settled workflow contracts
📝 Synchronize the living end-goal target with current XMD contracts
📝 Make the user's decision gate execution, and correct the result inv…
📝 Return the gate's sources, not a second copy of its answer
📝 State the handle boundary, the two text components, and the objecti…
📝 Reconcile the living target with the settled workflow contracts