Skip to content

feat: split session record runtime handle - #423

Merged
delete-cloud merged 2 commits into
mainfrom
dogfood/session-record-runtime-handle
Jun 2, 2026
Merged

delete-cloud merged 2 commits into
mainfrom
dogfood/session-record-runtime-handle

Conversation

@delete-cloud

@delete-cloud delete-cloud commented Jun 2, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • accept ADR-0058 and record completed run-target skeleton follow-ups
  • add a PR-2 task packet for the session record/runtime handle split
  • introduce durable SessionRecord and process-local SessionRuntimeHandle while preserving the existing session store payload and public Session compatibility attributes
  • add focused persistence tests for record round-trip and runtime-only state isolation

Tests

  • uv run pytest tests/ui/test_session_persistence.py tests/ui/test_session_manager_runtime.py -k "session or runtime or resume or checkpoint" -v
  • uv run pytest tests/ui/test_session_manager_public_api.py tests/ui/test_http_server_failover.py -k "event or queue or owner or close or delete" -v
  • uv run ruff check src/coding_agent/server/session_manager.py tests/ui/test_session_persistence.py tests/ui/test_session_manager_runtime.py
  • git diff --check

Summary by CodeRabbit

  • Chores

    • Accepted ADR-0058 for local-daemon control plane executor architecture with completion criteria finalized.
    • Added task specifications for session management improvements and runtime state handling.
  • Tests

    • Added test coverage for session persistence, runtime state encapsulation, and session recovery.

@coderabbitai

coderabbitai Bot commented Jun 2, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

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

More reviews will be available in 51 minutes and 26 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

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.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fbe40c64-6713-4de3-9904-e2849e070f7a

📥 Commits

Reviewing files that changed from the base of the PR and between 2bd7bf7 and 6d14353.

📒 Files selected for processing (3)
  • coding-agent/.opencode/prompts/tasks/local-daemon-pr2-session-record-runtime-handle.md
  • coding-agent/src/coding_agent/server/session_manager.py
  • coding-agent/tests/ui/test_session_persistence.py
📝 Walkthrough

Walkthrough

This PR implements ADR-0058 by refactoring Session to separate durable metadata (SessionRecord) from process-local runtime state (SessionRuntimeHandle). Session now delegates runtime field access to the handle via magic methods, and persistence is updated to exclude runtime state while preserving backward compatibility.

Changes

Session State Separation for ADR-0058

Layer / File(s) Summary
ADR Acceptance and Task Definition
docs/adr/0058-local-daemon-control-plane-executor-architecture.md, .opencode/prompts/tasks/local-daemon-pr2-session-record-runtime-handle.md
ADR-0058 status changed to Accepted with completed checklist items. New task prompt defines scope to separate durable session metadata from process-local runtime handles while preserving existing APIs and persisted formats.
Session Model Contracts
src/coding_agent/server/session_manager.py
New SessionRuntimeHandle dataclass holds process-local runtime fields (task, approval state, event queues, context/adapter). New SessionRecord dataclass encapsulates durable metadata with to_store_data() / from_store_data() methods and backward-compatible execution binding fallback.
Session Runtime Delegation
src/coding_agent/server/session_manager.py
Session gains runtime_handle field and __getattribute__ / __setattr__ overrides to transparently delegate runtime field names to the handle. __post_init__ initializes the handle and removes delegated fields from the instance dict.
Session Persistence Refactoring
src/coding_agent/server/session_manager.py
to_store_data() delegates to to_record().to_store_data() to exclude runtime state. New to_record() method constructs SessionRecord. from_store_data() hydrates via SessionRecord.from_store_data(...).to_session() then resets transient fields.
Persistence Boundary Validation
tests/ui/test_session_persistence.py
Four new tests verify runtime state encapsulation: runtime fields accessed through runtime_handle not stored on Session, to_store_data() excludes runtime state, SessionRecord round-trips persisted metadata while clearing runtime state on hydration, and to_record() excludes process-local attributes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • delete-cloud/Coding-Agent-Loop#384: Modifies session_manager.py to adjust runtime-related session state (turn_status/failure details) during agent execution, intersecting with this PR's runtime-handle refactoring.

Poem

A rabbit hops through session splits with glee, 🐰
Durable records rest, while runtime roams free,
No handles persist—just metadata's store,
Tests verify bounds, the persistence door.
Delegation flows smooth through __getattr__ spree! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: splitting session record runtime handle into separate durable and process-local components.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dogfood/session-record-runtime-handle

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 and usage tips.

@delete-cloud
delete-cloud marked this pull request as ready for review June 2, 2026 13:37

@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.

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/server/session_manager.py (1)

857-889: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep approval_coordinator in sync when approval_store changes.

After this split, approval_store is still a public mutable field, but approval_coordinator now lives on runtime_handle. _hydrate_session() has to repair both manually, and any other session.approval_store = ... assignment will silently leave the coordinator bound to the old store. That breaks approval reads/writes against the replacement store while preserving the old public API shape.

Suggested fix
 def __setattr__(self, name: str, value: object) -> None:
+    if name == "approval_store":
+        object.__setattr__(self, name, value)
+        instance_dict = object.__getattribute__(self, "__dict__")
+        handle = instance_dict.get("runtime_handle")
+        if handle is not None:
+            handle.approval_coordinator = ApprovalCoordinator(
+                cast(ApprovalStore, value)
+            )
+        return
     if name in self._RUNTIME_HANDLE_FIELD_NAMES:
         instance_dict = object.__getattribute__(self, "__dict__")
         handle = instance_dict.get("runtime_handle")
         if handle is not None:
             setattr(handle, name, value)
             return
     object.__setattr__(self, name, value)

Also applies to: 915-922

🤖 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/server/session_manager.py` around lines 857 -
889, Make sure the ApprovalCoordinator is kept in sync whenever the public
approval_store is replaced: change approval_store into a property with a setter
(or add a small helper) that assigns the new ApprovalStore and then
rebinds/creates approval_coordinator both on the Session (approval_coordinator)
and inside runtime_handle (runtime_handle.approval_coordinator) so they point to
the new store; also update _hydrate_session() to set both approval_store and the
coordinator binding consistently (use the same helper/property to avoid
duplicate logic), and ensure any direct assignment like session.approval_store =
... goes through that setter so reads/writes use the replacement store.
🧹 Nitpick comments (1)
coding-agent/.opencode/prompts/tasks/local-daemon-pr2-session-record-runtime-handle.md (1)

44-47: ⚡ Quick win

Use the repo’s organized pytest suites in this task packet.

These target commands hard-code tests/ui/..., which drifts from the repo’s expected pytest organization and makes the task instructions inconsistent with the standard verification flow.

As per coding guidelines, "Run pytest for testing with organized test suites: tests/agentkit/, tests/coding_agent/, tests/cli/".

🤖 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/.opencode/prompts/tasks/local-daemon-pr2-session-record-runtime-handle.md`
around lines 44 - 47, Update the hard-coded test invocations in the "Target
tests" block to use the repo's organized pytest suites instead of specific
tests/ui paths: replace the `uv run pytest tests/ui/...` commands with `uv run
pytest tests/agentkit/ tests/coding_agent/ tests/cli/ -k "<filters>" -v`
(keeping the same -k filters for session/runtime/event semantics), and update
the ruff check to run against `src/coding_agent/server/session_manager.py` plus
the organized test suite directories instead of `tests/ui/...`; adjust the three
command lines shown in the diff so they reference the canonical suites rather
than tests/ui paths.
🤖 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.

Outside diff comments:
In `@coding-agent/src/coding_agent/server/session_manager.py`:
- Around line 857-889: Make sure the ApprovalCoordinator is kept in sync
whenever the public approval_store is replaced: change approval_store into a
property with a setter (or add a small helper) that assigns the new
ApprovalStore and then rebinds/creates approval_coordinator both on the Session
(approval_coordinator) and inside runtime_handle
(runtime_handle.approval_coordinator) so they point to the new store; also
update _hydrate_session() to set both approval_store and the coordinator binding
consistently (use the same helper/property to avoid duplicate logic), and ensure
any direct assignment like session.approval_store = ... goes through that setter
so reads/writes use the replacement store.

---

Nitpick comments:
In
`@coding-agent/.opencode/prompts/tasks/local-daemon-pr2-session-record-runtime-handle.md`:
- Around line 44-47: Update the hard-coded test invocations in the "Target
tests" block to use the repo's organized pytest suites instead of specific
tests/ui paths: replace the `uv run pytest tests/ui/...` commands with `uv run
pytest tests/agentkit/ tests/coding_agent/ tests/cli/ -k "<filters>" -v`
(keeping the same -k filters for session/runtime/event semantics), and update
the ruff check to run against `src/coding_agent/server/session_manager.py` plus
the organized test suite directories instead of `tests/ui/...`; adjust the three
command lines shown in the diff so they reference the canonical suites rather
than tests/ui paths.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b6f1fdd8-9506-4451-a058-88a75d6390f7

📥 Commits

Reviewing files that changed from the base of the PR and between 3305085 and 2bd7bf7.

📒 Files selected for processing (4)
  • coding-agent/.opencode/prompts/tasks/local-daemon-pr2-session-record-runtime-handle.md
  • coding-agent/docs/adr/0058-local-daemon-control-plane-executor-architecture.md
  • coding-agent/src/coding_agent/server/session_manager.py
  • coding-agent/tests/ui/test_session_persistence.py

@delete-cloud
delete-cloud merged commit ef4bcac into main Jun 2, 2026
1 check passed
@delete-cloud
delete-cloud deleted the dogfood/session-record-runtime-handle branch June 2, 2026 13:47
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