Skip to content

fix(checkpoint): reconcile active run timeline - #694

Merged
delete-cloud merged 2 commits into
mainfrom
fix/checkpoint-active-timeline
Aug 5, 2026
Merged

delete-cloud merged 2 commits into
mainfrom
fix/checkpoint-active-timeline

Conversation

@delete-cloud

@delete-cloud delete-cloud commented Aug 5, 2026 •

Copy link
Copy Markdown
Owner

Goal

Restore a checkpoint without replaying, resuming, or reporting runs created after that checkpoint, while preserving superseded runs and events for audit.

Task packet: coding-agent/.opencode/prompts/tasks/checkpoint-active-run-timeline.md
ADR: coding-agent/docs/adr/0075-checkpoint-restore-active-run-timeline.md

Changes

  • Persist superseded_by_checkpoint_id and superseded_at across JSONL, SQLite, and PostgreSQL runtime records.
  • Mark post-checkpoint active runs inside the existing fenced SQLite/PG restore transaction.
  • Separate audit run listing from the active timeline used by history, resume, result fallback, and ACP load.
  • Reconcile in-memory current_turn_id after restore.
  • Preserve direct run/event/display-event audit access.
  • Add migration, restore, query, HTTP, ACP, CLI, and WebUI regressions.
  • Record PM-0027 for future release checks.

Non-goals

  • Deleting superseded run/event audit data.
  • Atomic projection reconciliation for legacy JSONL restore.
  • Changing restore authorization or checkpoint payload format.

Verification

  • Persistence/restore/query: 64 passed.
  • HTTP/ACP focused: 43 passed.
  • Adapter/lifecycle PM-0026 gate: 95 passed.
  • CLI/ACP compat: 11 passed.
  • Session-manager restore: 7 passed.
  • WebUI: 14 files / 132 tests passed.
  • Touched Ruff check and format check passed.
  • git diff --check passed.
  • Independent verifier: PASS.
  • One reviewer P1 fix cycle closed ACP stdio delegation and stale current_turn_id.

Risk

Existing checkpoints infer the run boundary from started_at > checkpoint.created_at; checkpoint capture and restore are serialized with active turns by ADR-0010. Real PostgreSQL and production smoke remain deployment gates.

Rollback

Revert commit 066e7b1a33f28bf78515fea2e5396c68d731ad6e. The added nullable columns may remain safely unused after rollback; no run/event records are deleted.

Summary by CodeRabbit

  • New Features

    • Checkpoint restoration now removes superseded runs from active timelines while preserving their history for auditing.
    • Session results, resumes, replays, and UI displays now use the restored active run.
    • Subsequent runs after a restore are correctly recognized as current.
  • Bug Fixes

    • Fixed stale session summaries and displayed messages after restoring checkpoints.
    • Added support for preserving checkpoint history across runtime storage formats.
  • Documentation

    • Added architecture guidance and a postmortem documenting checkpoint timeline reconciliation.

Preserve superseded runs for audit while excluding them from active replay, resume, ACP, and result projections.

Task: coding-agent/.opencode/prompts/tasks/checkpoint-active-run-timeline.md
@coderabbitai

coderabbitai Bot commented Aug 5, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@delete-cloud, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 37 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bd398299-7718-4051-a96e-12c4b3e9dcb4

📥 Commits

Reviewing files that changed from the base of the PR and between 066e7b1 and f02cbce.

📒 Files selected for processing (11)
  • coding-agent/.opencode/prompts/tasks/checkpoint-active-run-timeline.md
  • coding-agent/docs/adr/0075-checkpoint-restore-active-run-timeline.md
  • coding-agent/postmortem/patterns/PM-0027-reconcile-runtime-projections-on-checkpoint-restore.md
  • coding-agent/src/coding_agent/server/session_manager.py
  • coding-agent/src/coding_agent/stores/durable_local.py
  • coding-agent/src/coding_agent/stores/runtime_store.py
  • coding-agent/tests/coding_agent/test_pg_durable_fencing.py
  • coding-agent/tests/coding_agent/test_pg_runtime_store.py
  • coding-agent/tests/coding_agent/test_sqlite_local_durable_fencing.py
  • coding-agent/tests/coding_agent/test_sqlite_runtime_store.py
  • coding-agent/tests/ui/test_session_manager_runtime.py
📝 Walkthrough

Walkthrough

This change adds checkpoint-based runtime-run supersession across JSONL, SQLite, and PostgreSQL. Restore operations retain superseded runs and events for audit, while active-run queries exclude them across session, ACP, HTTP, CLI, and WebUI flows.

Changes

Checkpoint active-run timeline

Layer / File(s) Summary
Supersession contract and persistence
coding-agent/.opencode/prompts/tasks/checkpoint-active-run-timeline.md, coding-agent/docs/adr/0075-checkpoint-restore-active-run-timeline.md, coding-agent/postmortem/..., coding-agent/src/coding_agent/stores/runtime_store.py, coding-agent/src/coding_agent/stores/durable_*.py, coding-agent/tests/coding_agent/test_*runtime_store.py
AgentRunRecord stores optional checkpoint supersession metadata. JSONL, SQLite, and PostgreSQL persistence, migrations, serialization, and round-trip tests support the fields.
Checkpoint restore fencing
coding-agent/src/coding_agent/stores/durable_*.py, coding-agent/tests/coding_agent/test_*durable_fencing.py
SQLite and PostgreSQL restores mark later unsuperseded runs in the restored session. Tests cover checkpoint boundaries, existing supersession, other sessions, and retained events.
Active-run query integration
coding-agent/src/coding_agent/runs/query.py, coding-agent/src/coding_agent/server/..., coding-agent/src/coding_agent/acp/server.py, coding-agent/src/coding_agent/cli/local_runtime.py, coding-agent/tests/acp/*, coding-agent/tests/cli/*
Active-run queries exclude superseded runs. Session loading, result lookup, HTTP listings, ACP replay, and local CLI delegation use active-run queries.
Timeline and UI reconciliation
coding-agent/tests/coding_agent/test_runtime_query_service.py, coding-agent/tests/ui/test_http_server.py, coding-agent/webui/app/src/App.test.tsx
Tests verify audit access to superseded runs, active-run result reconstruction, checkpoint summary updates, and removal of rolled-back WebUI messages.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant SessionManager
  participant RuntimeStore
  participant RuntimeQueryService
  participant WebUI
  Client->>SessionManager: restore checkpoint
  SessionManager->>RuntimeStore: restore checkpoint and supersede later runs
  RuntimeStore-->>SessionManager: retain runs and events with metadata
  WebUI->>SessionManager: request active runtime runs
  SessionManager->>RuntimeQueryService: list active runtime runs
  RuntimeQueryService-->>WebUI: return non-superseded runs
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main checkpoint change: reconciling the active run timeline.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/checkpoint-active-timeline

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
coding-agent/src/coding_agent/stores/runtime_store.py (1)

1068-1086: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Claim paths do not exclude superseded runs, allowing post-checkpoint runs to still execute. restore_checkpoint_state marks a still-unclaimed run as superseded without changing its status field. All three claim_attached_executor_run implementations select candidates by status IN ('requested', 'expired') and executor metadata only, so a superseded run remains claimable. Once claimed, a worker executes it, replaying a run created after the restored checkpoint — the exact outcome the checkpoint-restore feature is meant to prevent.

  • coding-agent/src/coding_agent/stores/runtime_store.py#L1068-L1086: add AND superseded_at IS NULL to the candidate CTE's WHERE clause in PGRuntimeStore._CLAIM_ATTACHED_EXECUTOR_RUN_SQL. This also fixes durable_pg.py's fenced claim path, since it reuses this constant.
  • coding-agent/src/coding_agent/stores/runtime_store.py#L648-L699: add run.superseded_at is None to the candidate list comprehension in SQLiteRuntimeStore.claim_attached_executor_run.
  • coding-agent/src/coding_agent/stores/durable_local.py#L1031-L1101: add run.superseded_at is None to the candidate list comprehension in SQLiteLocalDurableStore.claim_attached_executor_run.
🐛 Proposed fix for the PostgreSQL claim query
     WITH candidate AS (
         SELECT run_id
         FROM agent_runs
         WHERE status IN ('requested', 'expired')
           AND metadata->>'executor_ref_kind' IN ('external_worker', 'local_attached')
           AND metadata->>'executor_kind' = $2
           AND ($1::text IS NULL OR session_id = $1)
+          AND superseded_at IS NULL
         ORDER BY started_at, run_id
         LIMIT 1
         FOR UPDATE SKIP LOCKED
     )
🐛 Proposed fix for the SQLite claim candidate filters
             candidates = [
                 run
                 for run in candidates
                 if run.metadata.get("executor_ref_kind")
                 in {"external_worker", "local_attached"}
                 and run.metadata.get("executor_kind") == executor_kind
+                and run.superseded_at is None
             ]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@coding-agent/src/coding_agent/stores/runtime_store.py` around lines 1068 -
1086, Claim candidate filters must exclude superseded runs. In
coding-agent/src/coding_agent/stores/runtime_store.py:1068-1086, update
PGRuntimeStore._CLAIM_ATTACHED_EXECUTOR_RUN_SQL to require superseded_at IS
NULL; this also covers durable_pg.py’s reused fenced path. In
coding-agent/src/coding_agent/stores/runtime_store.py:648-699 and
coding-agent/src/coding_agent/stores/durable_local.py:1031-1101, update the
candidate comprehensions in SQLiteRuntimeStore.claim_attached_executor_run and
SQLiteLocalDurableStore.claim_attached_executor_run to require run.superseded_at
is None.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@coding-agent/src/coding_agent/server/session_manager.py`:
- Around line 2952-2961: Update _restore_checkpoint() to persist the reconciled
session.current_turn_id through _restore_checkpoint_durable_state() before
completing the durable restore path. Ensure the value selected from
latest_active_run is materialized via Session.to_store_data() so checkpoint
reloads retain the current run ID.

---

Outside diff comments:
In `@coding-agent/src/coding_agent/stores/runtime_store.py`:
- Around line 1068-1086: Claim candidate filters must exclude superseded runs.
In coding-agent/src/coding_agent/stores/runtime_store.py:1068-1086, update
PGRuntimeStore._CLAIM_ATTACHED_EXECUTOR_RUN_SQL to require superseded_at IS
NULL; this also covers durable_pg.py’s reused fenced path. In
coding-agent/src/coding_agent/stores/runtime_store.py:648-699 and
coding-agent/src/coding_agent/stores/durable_local.py:1031-1101, update the
candidate comprehensions in SQLiteRuntimeStore.claim_attached_executor_run and
SQLiteLocalDurableStore.claim_attached_executor_run to require run.superseded_at
is None.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1c98bf15-0a7f-47ae-9869-2deba02952d8

📥 Commits

Reviewing files that changed from the base of the PR and between a9b0ea4 and 066e7b1.

📒 Files selected for processing (23)
  • coding-agent/.opencode/prompts/tasks/checkpoint-active-run-timeline.md
  • coding-agent/docs/adr/0075-checkpoint-restore-active-run-timeline.md
  • coding-agent/postmortem/index.yaml
  • coding-agent/postmortem/patterns/PM-0027-reconcile-runtime-projections-on-checkpoint-restore.md
  • coding-agent/src/coding_agent/acp/server.py
  • coding-agent/src/coding_agent/cli/local_runtime.py
  • coding-agent/src/coding_agent/runs/query.py
  • coding-agent/src/coding_agent/server/http_server.py
  • coding-agent/src/coding_agent/server/session_manager.py
  • coding-agent/src/coding_agent/stores/durable_local.py
  • coding-agent/src/coding_agent/stores/durable_pg.py
  • coding-agent/src/coding_agent/stores/runtime_store.py
  • coding-agent/tests/acp/test_compat_harness.py
  • coding-agent/tests/acp/test_server.py
  • coding-agent/tests/cli/test_local_runtime.py
  • coding-agent/tests/coding_agent/test_jsonl_runtime_store.py
  • coding-agent/tests/coding_agent/test_pg_durable_fencing.py
  • coding-agent/tests/coding_agent/test_pg_runtime_store.py
  • coding-agent/tests/coding_agent/test_runtime_query_service.py
  • coding-agent/tests/coding_agent/test_sqlite_local_durable_fencing.py
  • coding-agent/tests/coding_agent/test_sqlite_runtime_store.py
  • coding-agent/tests/ui/test_http_server.py
  • coding-agent/webui/app/src/App.test.tsx

Task packet: coding-agent/.opencode/prompts/tasks/checkpoint-active-run-timeline.md
@delete-cloud
delete-cloud merged commit 0c7fc19 into main Aug 5, 2026
2 checks passed
@delete-cloud
delete-cloud deleted the fix/checkpoint-active-timeline branch August 5, 2026 02:53
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