Parent: #163
Goal
Mirror the existing runner JSONL milestones into the durable SQLite/WAL event log without changing the runner's visible behavior.
This is the bridge from the current loop runner to the future event-sourced maestro. The current JSONL event stream remains the operator-facing behavior; the new durable event log becomes a replayable spine that can reconstruct task timelines after restart.
Scope
Expected owned surface:
src/forge_loop/eventlog/
- the narrow runner/tick/event-emission modules needed to mirror existing milestones;
- tests around the mirror path and replay.
Use the existing SqliteEventLog, EventKind, and projection cursor contracts. Extend them only where the mirror needs stable event kinds or metadata.
Milestones To Mirror
Cover these runner milestones if the current code emits them:
- tick start/end;
- issue selected / task planned;
- worker dispatched;
- worker heartbeat or observed progress, if available;
- worker terminal states: completed, failed, timed out, stale, compensated;
- critic result;
- PR opened;
- PR merged or merge blocked;
- worktree reaped;
- loop halt / max ticks reached.
If one of these is not available yet, document the gap in the test name or event payload rather than fabricating behavior.
Required Behavior
- Mirroring is opt-in or safely defaulted so existing JSONL behavior is preserved.
- Every mirrored event has a stable idempotency key derived from issue/tick/worker/PR/event kind.
- Re-running the same mirror step does not duplicate durable events.
- Reopening the SQLite database and replaying from sequence
0 reconstructs the same task timeline.
- Projection cursor helpers can remember the latest mirrored sequence.
Acceptance Tests
- Add a test that feeds representative legacy runner events into the mirror and verifies durable event kinds/payloads.
- Add an idempotency test for repeated mirror calls.
- Add a reopen/replay test that reconstructs a task timeline from SQLite only.
- Add a regression test that the legacy JSONL event file is still written when durable mirroring is enabled.
Non-goals
- Do not rewrite the runner.
- Do not remove JSONL event output.
- Do not add external services.
- Do not build full Temporal-style replay semantics yet.
Verification
Run at minimum:
env -u VIRTUAL_ENV uv run --extra dev pytest tests/test_eventlog_sqlite.py -q
- New mirror/replay tests.
env -u VIRTUAL_ENV uv run --extra dev ruff check <changed files>
env -u VIRTUAL_ENV uv run --extra dev ruff format --check <changed files>
Customer Story
A forge-loop operator running autonomous work across multiple sessions benefits because current runner activity becomes replayable before the runner is rewritten.
Source
Expanded during Forge self-dogfood sprint planning on 2026-06-02.
Parent: #163
Goal
Mirror the existing runner JSONL milestones into the durable SQLite/WAL event log without changing the runner's visible behavior.
This is the bridge from the current loop runner to the future event-sourced maestro. The current JSONL event stream remains the operator-facing behavior; the new durable event log becomes a replayable spine that can reconstruct task timelines after restart.
Scope
Expected owned surface:
src/forge_loop/eventlog/Use the existing
SqliteEventLog,EventKind, and projection cursor contracts. Extend them only where the mirror needs stable event kinds or metadata.Milestones To Mirror
Cover these runner milestones if the current code emits them:
If one of these is not available yet, document the gap in the test name or event payload rather than fabricating behavior.
Required Behavior
0reconstructs the same task timeline.Acceptance Tests
Non-goals
Verification
Run at minimum:
env -u VIRTUAL_ENV uv run --extra dev pytest tests/test_eventlog_sqlite.py -qenv -u VIRTUAL_ENV uv run --extra dev ruff check <changed files>env -u VIRTUAL_ENV uv run --extra dev ruff format --check <changed files>Customer Story
A forge-loop operator running autonomous work across multiple sessions benefits because current runner activity becomes replayable before the runner is rewritten.
Source
Expanded during Forge self-dogfood sprint planning on 2026-06-02.