Skip to content

fix: restore durable ACP session continuity - #307

Merged
pedronauck merged 4 commits into
mainfrom
session-fixes
Aug 4, 2026
Merged

pedronauck merged 4 commits into
mainfrom
session-fixes

Conversation

@pedronauck

@pedronauck pedronauck commented Aug 4, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Restore stopped ACP sessions as durable conversations: a normal prompt now starts a new provider process when needed, loads the retained provider history, and continues under the same Compozy session ID and transcript.
  • Persist each session's selected provider, model, reasoning effort, and speed across stop and daemon restart, with explicit selected/effective runtime semantics and optimistic concurrency.
  • Remove the misleading Use as Goal message action and eliminate the assistant-ui double-unmount error when a window closes while its session is still running.

Why

Four behaviors were breaking the core promise of durable sessions:

  1. A session that stopped on its own became read-only in the Web UI even though its transcript and identity still existed. Manual stop and autonomous stop also behaved differently.
  2. The runtime selector was local UI state. Reopening a stopped session or restarting the daemon silently displayed the default runtime instead of the provider/model/reasoning choice made for that session.
  3. Assistant messages exposed Use as Goal, but Goal creation is owned by the /goal command and the action had no coherent product contract.
  4. Closing a Web window during a running turn could unmount the same assistant-ui resource fiber twice and trigger the ReadonlyThreadProvider error boundary.

This change makes the daemon's durable session record the single authority for continuation and next-prompt runtime intent, then projects that truth consistently through CLI, HTTP, UDS, native tools, extensions, generated SDK contracts, and Web.

What changed

Stopped-session continuation

  • A normal prompt is now the only operation that moves a durable stopped session back toward execution.
  • Prompt admission is keyed by the durable session ID before an in-memory session exists, so concurrent requests cannot dereference a missing active session or start duplicate provider processes.
  • The manager serializes restore work, transitions stopped -> starting -> active, recreates the ACP process, loads the stored provider session/history, and submits the prompt against the same Compozy session.
  • The canonical transcript and session directory remain append-only. Continuation does not create a replacement catalog row or a second logical conversation.
  • Manual stop, provider completion, daemon restart repair, and other stopped states now converge on the same prompt-continuation contract.
  • session resume deliberately remains a live attach operation. It never starts a stopped provider process; recap, history, status, repair, and a subsequent normal prompt are the stopped-session paths.
  • Queue, interrupt, steer, attach, and other control operations do not implicitly restart stopped work.

Durable runtime selection

Session reads now expose three distinct concepts:

Field Meaning
runtime.selected Durable default intent for the next prompt. It survives stop and daemon restart.
runtime.effective Runtime already applied to the current provider process, when one exists.
runtime.selection_revision Compare-and-swap revision used to reject stale writes instead of silently overwriting a newer choice.
  • Added append-only SQLite migration 00048_schema.sql for the selected provider, model, reasoning effort, speed, and revision on the session row.
  • Added PUT /api/workspaces/{workspace_id}/sessions/{session_id}/runtime to set a complete selection and DELETE on the same route to clear it.
  • Both mutations accept expected_revision; stale revisions return 409 Conflict and require a fresh session read before retrying.
  • Added compozy session runtime set and compozy session runtime clear, including structured output and revision fencing.
  • Added native tools compozy__session_runtime_set and compozy__session_runtime_clear.
  • Added extension Host API methods sessions/runtime/set and sessions/runtime/clear, workspace binding, permission declarations, generated Go contracts, and TypeScript/OpenAPI projections.
  • Prompt runtime precedence is explicit runtime snapshot, then durable selected, then current effective. Already queued prompts retain their immutable accepted runtime snapshot.
  • No new config.toml key or default was introduced; this is session-scoped runtime data, not global or workspace configuration.

Web behavior

  • The composer remains available for stopped sessions so sending a normal message performs the daemon-owned continuation flow.
  • The runtime selector now initializes from the session payload and saves changes immediately to the daemon.
  • Runtime writes are serialized and optimistic: the UI updates promptly, carries the current selection revision, and reconciles with authoritative server state without letting slower responses overwrite newer choices.
  • Reopening a session after stop or daemon restart shows its persisted selected runtime instead of the agent/global default.
  • Existing prompt snapshots and queued input remain independent from later selector changes.
  • Session window teardown no longer gives assistant-ui two owners for the same read-only thread resource. The dependency patch makes resource unmount idempotent, and the Web provider tree no longer recreates identity wrappers that could trigger the second cleanup.

Message actions

  • Removed Use as Goal from settled assistant messages, related logic, stories, design prototypes, and obsolete QA coverage.
  • Kept Copy and settled-message metadata focused.
  • /goal remains the supported Goal entry point through the composer command path.

Contracts, docs, and generated artifacts

  • Regenerated OpenAPI, Web types, TypeScript extension contracts, Go SDK contracts, SQLC output, native-tool catalog data, and CLI reference pages.
  • Updated the official Compozy skill references for runtime operations, native tools, and extension authoring.
  • Updated Quick Start, Web UI, session lifecycle, resume/replay, migration, and CLI docs to distinguish normal-prompt restart from live-only attach.
  • Updated QA journeys/scenarios, retired the obsolete Use as Goal charter, added durable-session charters, recorded the stopped-prompt regression, and published the acceptance report.

Database migration

  • Adds migration 00048_schema.sql and updates the declarative session schema plus Atlas checksum.
  • The new columns are session-scoped and are written/read through the owning global session catalog row.
  • This is a greenfield-alpha hard cut: there are no aliases, dual fields, schema fallbacks, or legacy compatibility paths.

Release notes

🐛 Bug Fixes

  • Restore durable stopped ACP sessions, preserve per-session runtime selection across restarts, remove the unsupported Use as Goal action, and prevent running session windows from double-unmounting assistant-ui resources.

QA and verification

  • make gate-full passed for fingerprint c30e7d8ff334328907b6a562e27ebaedce64417c (.cache/gate/logs/full-1785876656.log). This includes code generation drift checks, installer check, source-size guard, Bun/Go lint, TypeScript checks, 4,309 Bun/Vitest tests, Web/site builds, 19,569 race-enabled Go tests, Go build, and architecture boundaries.
  • Focused manager and storage race suites covered stopped prompt admission, restore serialization, transition finalization, runtime selection revision conflicts, persistence, and restart continuity.
  • HTTP, UDS, CLI, native-tool, Host API, OpenAPI, SDK, adapter, store, and React canonical suites cover the new contract from daemon through Web.
  • Live-provider QA selected Claude Code / Claude Fable 5 / Max, stopped the session, restarted the daemon, confirmed HTTP and UDS readback, sent a normal prompt, and verified that the same session recalled earlier history.
  • Running-window QA closed a window during a real Claude turn, reopened it, observed current output, and collected no ReadonlyThreadProvider or resource-fiber teardown error.
  • Message-action QA confirmed that settled responses expose Copy only and that /goal status remains available.
  • The production-built documentation site passed a rendered walk across migration, Web UI, lifecycle, resume, and runtime set/clear pages, including direct reloads.
  • Five of five tracked journeys passed. One Blocks-Completion defect was found during QA (BUG-20260804-stopped-prompt-restart-panic), fixed in production admission code, and passed the canonical regression plus live retest.
  • QA evidence audit passed with zero blockers and zero warnings. Both runtime QA and documentation QA teardown records report "clean": true with no surviving daemon, Web, site, browser, watcher, or tmux process.

Full report: docs/qa/reports/2026-08-04-durable-acp-sessions.md

Review hardening

The first full CodeRabbit pass produced 13 inline threads and 7 review-body findings; React Doctor added one compiler finding. The validation pass then added 2 inline findings and 1 outside-diff finding. All 24 findings were verified against the current implementation and addressed. All 15 visible CodeRabbit inline threads now report isResolved: true through GitHub GraphQL; the React Doctor validation check reports 100/100.

Resume and shutdown concurrency

  • Resume ownership is finalized from a defer, so a panic or early exit cannot leave a stale in-flight resume entry that blocks future callers.
  • Shutdown now drains every captured resume run. Ordinary provider resume failures no longer make the drain return early while another resume goroutine remains active; only cancellation or deadline expiry terminates the wait.
  • Concurrent-resume tests now protect every fake-driver read/write with its mutex and use a deterministic waiter barrier instead of timing sleeps.
  • Added a regression proving that shutdown waits for all captured resume runs even when an earlier run fails.
  • Prompt admission's duplicated active-versus-persisted target resolution was consolidated into one helper, keeping runtime selection and workspace ownership identical for normal prompts and managed goals.

Runtime contract and capability boundaries

  • The extension Host API no longer imports the HTTP/API contract layer. It owns its runtime-selection wire payload and converts directly into the session-domain selection.
  • Stale Host API set and clear operations now return structured conflict code 409, matching HTTP, CLI, UDS, and native-tool compare-and-swap behavior.
  • The daemon adapter carries a compile-time assertion for SessionRuntimeSelectionManager.
  • Runtime set/clear native tools are exposed only when the session dependency implements the runtime-selection capability; a merely non-nil session manager is no longer enough.
  • Persisted runtime selections now declare their snake-case JSON keys explicitly.
  • Generated Go and TypeScript SDK contracts were regenerated after the extension-owned payload change.

Web lifecycle and stale-response protection

  • Runtime mutations carry a lifecycle-owned AbortSignal all the way into the HTTP adapter.
  • A superseded runtime write is aborted before the next write begins, and an unmounted session view aborts its outstanding request.
  • Success and error callbacks ignore aborted requests, preventing an old window or old session from reconciling the active cache.
  • Async store events carry workspace and session identity, so callbacks from one session cannot mutate another session's runtime state.
  • Runtime revisions are monotonic in the client store: an older session snapshot or persistence callback can update unrelated projection fields but cannot lower the selected runtime or selection_revision.
  • The runtime persistence function was moved out of unreachable post-return code, satisfying React Compiler; React Doctor reports 100/100 with zero findings.

Regression coverage strengthened

  • HTTP handler tests now verify forwarded session IDs, expected revisions, status codes, and structured error bodies for stale set and clear requests.
  • Host API tests assert provider, model, reasoning effort, speed, revision, stale conflicts, and unchanged durable state after rejection.
  • Active and stopped session tests prove successful clear increments the revision, removes the selection from metadata/catalog, preserves stopped state, and does not start ACP.
  • Integration coverage proves a prompt after stop reuses the pre-stop ACP session ID, not only the Compozy catalog row.
  • Store decoding tests prove blank selected-runtime columns decode to nil at revision zero.
  • CLI and conversion suites preserve non-default speed, reasoning, metadata, and default-speed behavior.
  • Web hook tests reuse the canonical promptability helper, restore console spies through finally, verify signal forwarding, and cover stale revision events through both snapshot and persistence paths.
  • The second CodeRabbit pass strengthened restart coverage with an explicit StateActive assertion and exact empty-prompt/missing-session errors.
  • Resume-drain synchronization no longer uses elapsed time: separate cases prove ordinary failures are ignored and a pending resume keeps the waiter blocked until completion.

Review verification

  • Focused Go race suites passed across session, store, API, CLI, daemon, and extension packages.
  • The session lifecycle integration test passed with the integration build tag and race detector.
  • Focused Web suites passed through Turborepo; Web lint and typecheck completed with zero issues.
  • React Doctor v0.9.4 completed at 100/100 with zero diagnostics.
  • The final full repository gate passed after all review changes, and the stopped-session Storybook state was captured with an enabled composer.

Compozy Impact Audit

  • Native tools: added compozy__session_runtime_set and compozy__session_runtime_clear; updated tool IDs, descriptors, schema/catalog digest fixtures, runtime toolset membership, binding groups, availability metadata, and native-tool tests. Existing prompt/status tools consume the expanded session runtime projection without fallback behavior.
  • Extensibility and hooks: added Host API methods sessions/runtime/set and sessions/runtime/clear, generated SDK contracts, workspace binding, access declarations, and MCP/native projections. Updated the official extension-authoring reference. No lifecycle hook, capability enrollment, MCP sidecar, or config.toml key/default changed; session runtime intent is managed through the new explicit session surfaces.
  • Workspace data isolation: selected runtime is session-scoped. HTTP and UDS routes resolve the owning workspace before mutation; Host API calls inherit the extension workspace binding; native tools resolve workspace/session identity; global-store reads and writes remain keyed by the durable session row. Session payload, catalog, Web cache, and event paths were checked so a selection cannot be read or mutated through another workspace.
  • Official Compozy skill: updated skills/compozy/references/runtime-operations.md, native-tools.md, and extension-authoring.md with stopped-session prompt continuation, selected/effective runtime semantics, revision fencing, the CLI/HTTP/UDS routes, native tool IDs, and Host API methods.

Review guide

The highest-value review order is:

  1. internal/session/manager_prompt_admission.go, manager_resume_run.go, and manager_transition.go for stopped-session restore and concurrency.
  2. internal/store/session_runtime_selection.go, the global DB mappings, and migration 00048_schema.sql for durability and revision fencing.
  3. internal/api/core/handlers_session_runtime.go, CLI/native/Host API adapters, and generated contracts for cross-surface parity.
  4. web/src/systems/session/hooks/use-session-runtime-selection.ts, the runtime context/store, and session-running rules for Web synchronization.
  5. patches/@assistant-ui%[email protected] plus the session thread/window components for teardown ownership.
  6. The QA report and session docs for public behavior and migration wording.

Summary by CodeRabbit

  • New Features

    • Added persistent session runtime selection for provider, model, reasoning effort, speed, and revision tracking.
    • Added CLI, API, Host API, native tool, and web support for setting or clearing runtime preferences.
    • Sessions can automatically resume when prompted after being stopped.
  • Bug Fixes

    • Added revision conflict handling to prevent stale runtime updates.
    • Improved concurrent session resume behavior.
    • Prevented errors when unmounting already-unmounted interface resources.
    • Removed the “Use as Goal” message action.

@greptile-apps

greptile-apps Bot commented Aug 4, 2026 •

Copy link
Copy Markdown

Too many files changed for review. (197 files found, 100 file limit)

Bypass the limit by tagging @greptile-apps to review.

@vercel

vercel Bot commented Aug 4, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
compozy-site Ready Ready Preview Aug 4, 2026 8:58pm

Request Review

@coderabbitai

coderabbitai Bot commented Aug 4, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The PR adds durable session runtime selection with optimistic concurrency. It persists selected runtime state, exposes HTTP, Host API, CLI, native tool, and web operations, resumes stopped sessions during prompts, and removes the assistant “Use as Goal” action.

Changes

Durable runtime selection

Layer / File(s) Summary
Selection contracts and persistence
internal/store/..., internal/session/..., internal/api/contract/...
Session payloads, metadata, catalog records, SQL schema, and migrations now store selected runtime fields and selection_revision.
Session state and automatic resume
internal/session/...
Runtime selection uses persisted values. Prompts can resume stopped sessions. Concurrent resume requests share one startup run.
Session runtime mutation APIs
internal/api/..., internal/daemon/..., internal/extension/...
PUT and DELETE runtime operations validate revisions, persist changes, return updated sessions, and map stale revisions to HTTP 409.
Native tools and client integrations
internal/tools/..., internal/cli/..., sdk/go/contracts/...
CLI commands, native tools, Host API methods, permissions, and generated contracts support setting and clearing session runtime selections.
Web runtime selection state
web/src/systems/session/..., web/src/hooks/routes/...
Web runtime changes persist through a mutation hook, update caches, track revisions, and allow prompting stopped user sessions.
Assistant UI cleanup
web/src/components/assistant-ui/..., patches/...
The “Use as Goal” action and transcript provider remount key were removed. Repeated resource unmounts now no-op.
Generated contract relocation
sdk/go/contracts/types_019_gen.go–types_027_gen.go
Generated public contract declarations were reordered while adding session runtime types and preserving other contract models.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant WebClient
  participant SessionAPI
  participant SessionManager
  participant GlobalDB
  WebClient->>SessionAPI: Set runtime with expected revision
  SessionAPI->>SessionManager: SetRuntimeSelection
  SessionManager->>GlobalDB: Compare revision and persist selection
  GlobalDB-->>SessionManager: Updated session revision
  SessionManager-->>SessionAPI: Updated session info
  SessionAPI-->>WebClient: Session runtime payload
Loading

Possibly related PRs

  • compozy/compozy#267: Both PRs modify session runtime-selection and runtime configuration flows.
  • compozy/compozy#283: Both PRs modify runtime selection across session models, APIs, persistence, and prompt runtime handling.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.38% 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 summarizes the primary change: restoring durable ACP session continuity across stopped sessions and daemon restarts.
✨ 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 session-fixes

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.

@github-actions

github-actions Bot commented Aug 4, 2026 •

Copy link
Copy Markdown
Contributor

React Doctor found no new issues. 🎉

Reviewed by React Doctor for commit 0629952.

@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: 13

🧹 Nitpick comments (7)
internal/daemon/host_api_session_adapter.go (1)

42-43: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a compile-time assertion for the adapter capability.

hostAPISessionManagerAdapter now implements core.SessionRuntimeSelectionManager. Add an assertion near the type declaration. This detects an interface signature change at compile time.

Proposed change
 type hostAPISessionManagerAdapter struct {
 	core.SessionManager
 	exec             sandboxExecSessionManager
 	runtimeSelection core.SessionRuntimeSelectionManager
 }
+
+var _ core.SessionRuntimeSelectionManager = hostAPISessionManagerAdapter{}

As per coding guidelines, production Go must use compile-time interface assertions.

Also applies to: 105-126

🤖 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 `@internal/daemon/host_api_session_adapter.go` around lines 42 - 43, Add a
compile-time interface assertion adjacent to the hostAPISessionManagerAdapter
type declaration, verifying it implements core.SessionRuntimeSelectionManager.
Keep the assertion in production code and leave the adapter implementation
unchanged.

Source: Coding guidelines

internal/cli/session_test.go (1)

151-196: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the default runtime speed.

The command defaults omitted --speed to normal, but this test does not assert that value in SetSessionRuntimeRequest. Assert request.Runtime.Speed is contract.SpeedNormal.

As per path instructions, tests must verify meaningful business logic and behavior outcomes.

🤖 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 `@internal/cli/session_test.go` around lines 151 - 196, Update the
SetSessionRuntimeRequest validation in the “Should fetch the current revision
before setting runtime” test to also assert that request.Runtime.Speed equals
contract.SpeedNormal, while preserving the existing provider, model, reasoning
effort, ID, and revision checks.

Source: Path instructions

internal/api/core/conversions_parsers_test.go (1)

155-163: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert selected-runtime speed across conversion and persistence tests.

The tests omit SelectedRuntime.Speed. A regression that removes or changes this runtime selection field can pass.

  • internal/api/core/conversions_parsers_test.go#L155-L163: Assert payload.Runtime.Selected.Speed == contract.SpeedNormal.
  • internal/session/session_test.go#L241-L246: Set a non-default Speed in SelectedRuntime.
  • internal/session/session_test.go#L263-L315: Assert that Meta(), Info(), and ReadSessionMeta() retain that speed.

As per coding guidelines, edited Go tests must identify the invariant and update the existing canonical suite. As per path instructions, tests must verify behavior outcomes for critical paths.

🤖 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 `@internal/api/core/conversions_parsers_test.go` around lines 155 - 163, Extend
the selected-runtime assertions to cover Speed preservation: in
internal/api/core/conversions_parsers_test.go lines 155-163, assert
payload.Runtime.Selected.Speed equals contract.SpeedNormal; in
internal/session/session_test.go lines 241-246, initialize SelectedRuntime with
a non-default Speed; and in lines 263-315, assert Meta(), Info(), and
ReadSessionMeta() retain that speed.

Sources: Coding guidelines, Path instructions

internal/store/session_runtime_selection.go (1)

10-16: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Add snake_case JSON tags to SessionRuntimeSelection.

This struct is serialized to disk. SessionMeta.RuntimeSelection holds a *SessionRuntimeSelectionState, and that state marshals Selected into meta.json. The fields have no tags, so the persisted keys become Provider, Model, ReasoningEffort, and Speed. Every other persisted field in SessionRuntimeSelectionState and in internal/store/session_meta_types.go uses snake_case. Fix the format now, while migration 00048_schema.sql is still unreleased. If you add the tags after sessions write meta.json, the old PascalCase keys no longer decode and the durable selection is silently lost on reload.

♻️ Proposed tags
 type SessionRuntimeSelection struct {
-	Provider        string
-	Model           string
-	ReasoningEffort string
-	Speed           speedpkg.Speed
+	Provider        string         `json:"provider"`
+	Model           string         `json:"model,omitempty"`
+	ReasoningEffort string         `json:"reasoning_effort,omitempty"`
+	Speed           speedpkg.Speed `json:"speed,omitempty"`
 }
🤖 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 `@internal/store/session_runtime_selection.go` around lines 10 - 16, Add
snake_case JSON tags to all fields of SessionRuntimeSelection—Provider, Model,
ReasoningEffort, and Speed—so its persisted representation matches the existing
session metadata format before migration 00048_schema.sql is released.
internal/session/manager_prompt_admission.go (1)

88-115: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the shared prompt-target resolution.

Lines 92-116 repeat lines 49-73 of submitAdmittedGoalByTarget almost verbatim: active-session lookup, runtime resolution at admission, workspace resolution, and the persisted-metadata fallback. Extract one helper that returns the session, the workspace ID, and the resolved runtime selection, then call it from both functions. This keeps the two admission paths from diverging as runtime-selection rules evolve.

♻️ Proposed shape
func (m *Manager) resolvePromptTarget(
	ctx context.Context,
	req promptRequest,
) (session *Session, workspaceID string, runtime *RuntimeSelection, err error) {
	if active, ok := m.Get(req.target); ok {
		resolved, resolveErr := m.resolvePromptRuntimeAtAdmission(ctx, active, req.runtime)
		if resolveErr != nil {
			return nil, "", nil, resolveErr
		}
		workspaceID, err = sessionPromptWorkspaceID(active)
		if err != nil {
			return nil, "", nil, err
		}
		return active, workspaceID, resolved, nil
	}
	meta, err := m.readMetaWithContext(ctx, req.target)
	if err != nil {
		return nil, "", nil, err
	}
	resolved, err := normalizePromptRuntimeSelectionFromMeta(meta, req.runtime)
	if err != nil {
		return nil, "", nil, err
	}
	return nil, meta.WorkspaceID, resolved, nil
}
🤖 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 `@internal/session/manager_prompt_admission.go` around lines 88 - 115, Extract
the duplicated target-resolution logic from submitAdmittedPromptByTarget and
submitAdmittedGoalByTarget into a shared Manager helper that returns the
session, workspace ID, resolved runtime selection, and error. Preserve the
active-session and persisted-metadata fallback behavior, then update both
admission functions to call the helper and use its returned values.
internal/session/manager_resume.go (1)

35-37: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Release the resume run with defer.

finishSessionResume runs only on the normal return path. If m.resumeSession panics, run.done is never closed and the resumeRuns[target] entry is never deleted. Every concurrent waiter then blocks until its own context expires, and each later Resume for that session id receives the same stale run and blocks again for the lifetime of the manager. A deferred call removes that permanent-stall path. The named err return in the Resume signature also becomes unused after this refactor; drop it or use it.

🛡️ Proposed fix
-	resumed, resumeErr := m.resumeSession(ctx, target)
-	m.finishSessionResume(target, run, resumed, resumeErr)
-	return resumed, resumeErr
+	var resumed *Session
+	var resumeErr error
+	defer func() { m.finishSessionResume(target, run, resumed, resumeErr) }()
+	resumed, resumeErr = m.resumeSession(ctx, target)
+	return resumed, resumeErr
🤖 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 `@internal/session/manager_resume.go` around lines 35 - 37, Defer cleanup of
the resume run in Resume so finishSessionResume executes during both normal
returns and panics from m.resumeSession, ensuring run.done is closed and
resumeRuns[target] is removed. Update the Resume return handling accordingly,
and remove the now-unused named err return or otherwise use it consistently.
internal/session/additional_test.go (1)

388-402: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Wrap the new resume assertions in a Should subtest.

These lines add a new behavioral case: a prompt on a stopped session now resumes it. The assertions live in the parent function body instead of a named subtest. Move them into t.Run("Should resume a stopped session on prompt", ...) so the case is named and can run in parallel like the neighboring subtests.

As per coding guidelines: "Use Should … subtest names, default t.Parallel". As per path instructions: "MUST use t.Run("Should...") pattern for ALL test cases".

🤖 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 `@internal/session/additional_test.go` around lines 388 - 402, Move the
stopped-session resume assertions after the Prompt call into a t.Run("Should
resume a stopped session on prompt", ...) subtest, including the resumed-state
and driver-start-call checks. Follow the neighboring test structure by calling
t.Parallel() in the new subtest and keep the existing prompt/event behavior
intact.

Sources: Coding guidelines, Path instructions

🤖 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 `@internal/api/core/handlers_test.go`:
- Around line 724-785: Strengthen the runtime-selection error tests around
ClearRuntimeSelectionFn and the “Should require a compare-and-set revision” and
“Should reject a stale clear revision” cases. Assert that
ClearRuntimeSelectionFn receives the expected session ID and expected revision
0, then decode each error response and verify its contract-specific error value
in addition to the HTTP status. Preserve the existing success assertions.

In `@internal/daemon/native_tool_binding_groups.go`:
- Around line 64-71: Update the availability assigned to ToolIDSessionRuntimeSet
and ToolIDSessionRuntimeClear in the tool binding map to require the runtime
manager capability, specifically core.SessionRuntimeSelectionManager, rather
than the generic sessions availability. Keep their existing call bindings
unchanged and ensure both tools are hidden when that manager is unavailable.

In `@internal/extension/contract/host_api.go`:
- Line 172: Remove the extension runtime path’s dependency on
internal/api/contract: in internal/extension/contract/host_api.go:172, replace
apicontract.PromptRuntimeSelectionPayload with an extension-owned or lower-layer
contract type; in internal/extension/host_api_session_runtime.go:9, remove the
API contract import; and at lines 31-32 convert directly to
session.RuntimeSelection or reuse a conversion moved to a lower-layer package.

In `@internal/extension/host_api_test.go`:
- Around line 647-680: Extend the runtime selection test around the
sessions/runtime/set and sessions/runtime/clear calls to assert every selected
field—Provider, Model, ReasoningEffort, and Speed—along with the revision. Add a
subsequent set or clear request using a stale expected_revision, assert the
specific conflict error code with the test’s established error-assertion
helpers, and verify the selection and revision remain unchanged after the
rejected request.

In `@internal/session/additional_test.go`:
- Around line 452-472: Protect all fakeDriver shared-field accesses with
h.driver.mu: in internal/session/additional_test.go:452-472, lock around the
startHook assignment and add a barrier confirming the second Resume caller is
registered before closing releaseStart; at
internal/session/additional_test.go:371-373 and :400-402, lock before reading
len(h.driver.startCalls).

In `@internal/session/manager_integration_test.go`:
- Around line 61-75: Strengthen the stopped-session reuse test around
h.manager.Prompt by capture the ACP session ID before Stop, then assert
h.driver.startCalls[1].ResumeSessionID matches it after the resumed prompt. Keep
the existing event-count, session lookup, and CWD assertions unchanged.

In `@internal/session/manager_resume_run.go`:
- Around line 61-77: Update waitForSessionResumes to drain every captured
sessionResumeRun instead of returning immediately on the first resume error;
continue waiting through ordinary run.err failures, and only return the context
cancellation/deadline error once the context is done. Preserve the existing
nil-context validation and return successful completion after all runs finish
when the context remains active.

In `@internal/session/manager_transition_test.go`:
- Around line 331-368: Extend the canonical ClearRuntimeSelection tests in the
session manager suite with successful current-revision cases for both active and
stopped sessions. Using the existing session harness and catalog, assert each
clear removes SelectedRuntime, increments RuntimeSelectionRevision, and persists
the cleared metadata through the catalog, while preserving the stopped state and
avoiding an ACP start where applicable.

In `@internal/store/globaldb/global_db_session_test.go`:
- Around line 294-298: Update the test covering blank selected-runtime columns
and revision 0 to assert the decoded info has SelectedRuntime equal to nil and
RuntimeSelectionRevision equal to 0. Add these outcome assertions after decoding
the fixture, preserving the existing setup and other checks.

In `@web/src/hooks/routes/__tests__/use-session-page-controls.test.tsx`:
- Around line 35-37: Update the mock around canPromptSession in the session page
controls tests to reuse the canonical helper from session-running.ts instead of
duplicating its active/stopped logic. Keep the stopped-session coverage aligned
with production behavior, or move that invariant to the helper’s owning suite
while leaving this test focused on hook wiring.

In
`@web/src/systems/session/components/__tests__/session-chat-runtime-provider.test.tsx`:
- Around line 789-805: Wrap the assertions in the “Should unmount a running
readonly thread safely under StrictMode” test in a try/finally block, and move
consoleError.mockRestore() into finally so the console.error spy is restored
even when an assertion fails.

In `@web/src/systems/session/hooks/use-session-runtime-selection.ts`:
- Around line 18-19: Update useSetSessionRuntime and SetSessionRuntimeVariables
to carry an AbortSignal, create or reuse a lifecycle-owned AbortController for
the mutation, and pass its signal to setSessionRuntime alongside workspaceId,
id, and request. Ensure the controller is cleaned up or aborted with the hook
lifecycle.

In `@web/src/systems/session/stores/session-prompt-runtime-store.ts`:
- Around line 61-84: Update inputUpdated and runtimePersisted in
session-prompt-runtime-store.ts to ignore events with a lower selectionRevision
than the current input, preserving the current selected runtime and revision;
continue applying equal or newer revisions normally. Add a regression in
web/src/systems/session/stores/__tests__/session-prompt-runtime-store.test.ts
covering persistence at revision 4 followed by an input snapshot at revision 3,
asserting the selection and revision remain at 4.

---

Nitpick comments:
In `@internal/api/core/conversions_parsers_test.go`:
- Around line 155-163: Extend the selected-runtime assertions to cover Speed
preservation: in internal/api/core/conversions_parsers_test.go lines 155-163,
assert payload.Runtime.Selected.Speed equals contract.SpeedNormal; in
internal/session/session_test.go lines 241-246, initialize SelectedRuntime with
a non-default Speed; and in lines 263-315, assert Meta(), Info(), and
ReadSessionMeta() retain that speed.

In `@internal/cli/session_test.go`:
- Around line 151-196: Update the SetSessionRuntimeRequest validation in the
“Should fetch the current revision before setting runtime” test to also assert
that request.Runtime.Speed equals contract.SpeedNormal, while preserving the
existing provider, model, reasoning effort, ID, and revision checks.

In `@internal/daemon/host_api_session_adapter.go`:
- Around line 42-43: Add a compile-time interface assertion adjacent to the
hostAPISessionManagerAdapter type declaration, verifying it implements
core.SessionRuntimeSelectionManager. Keep the assertion in production code and
leave the adapter implementation unchanged.

In `@internal/session/additional_test.go`:
- Around line 388-402: Move the stopped-session resume assertions after the
Prompt call into a t.Run("Should resume a stopped session on prompt", ...)
subtest, including the resumed-state and driver-start-call checks. Follow the
neighboring test structure by calling t.Parallel() in the new subtest and keep
the existing prompt/event behavior intact.

In `@internal/session/manager_prompt_admission.go`:
- Around line 88-115: Extract the duplicated target-resolution logic from
submitAdmittedPromptByTarget and submitAdmittedGoalByTarget into a shared
Manager helper that returns the session, workspace ID, resolved runtime
selection, and error. Preserve the active-session and persisted-metadata
fallback behavior, then update both admission functions to call the helper and
use its returned values.

In `@internal/session/manager_resume.go`:
- Around line 35-37: Defer cleanup of the resume run in Resume so
finishSessionResume executes during both normal returns and panics from
m.resumeSession, ensuring run.done is closed and resumeRuns[target] is removed.
Update the Resume return handling accordingly, and remove the now-unused named
err return or otherwise use it consistently.

In `@internal/store/session_runtime_selection.go`:
- Around line 10-16: Add snake_case JSON tags to all fields of
SessionRuntimeSelection—Provider, Model, ReasoningEffort, and Speed—so its
persisted representation matches the existing session metadata format before
migration 00048_schema.sql is released.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 38ac7ada-353d-4e6e-8e42-48a333974374

📥 Commits

Reviewing files that changed from the base of the PR and between ee18fc0 and 9378bf0.

⛔ Files ignored due to path filters (50)
  • MIGRATION_GUIDE.md is excluded by !**/*.md
  • bun.lock is excluded by !**/*.lock, !**/*.lock
  • docs/design/opendesign/session/SESSION-REDESIGN-SPEC.md is excluded by !docs/design/**/*, !**/*.md
  • docs/design/opendesign/session/session-chat.html is excluded by !docs/design/**/*
  • docs/design/opendesign/session/session-design-system.html is excluded by !docs/design/**/*
  • docs/design/opendesign/session/session.css is excluded by !docs/design/**/*
  • docs/qa/bugs/BUG-20260804-stopped-prompt-restart-panic.md is excluded by !**/*.md
  • docs/qa/charters/CH-durable-session-docs-continuity.md is excluded by !**/*.md
  • docs/qa/charters/CH-message-actions-copy-timestamp.md is excluded by !**/*.md
  • docs/qa/charters/CH-running-session-window-close.md is excluded by !**/*.md
  • docs/qa/charters/CH-runtime-selection-restart-continuity.md is excluded by !**/*.md
  • docs/qa/charters/CH-stopped-session-prompt-continuity.md is excluded by !**/*.md
  • docs/qa/charters/CH-use-response-as-goal.md is excluded by !**/*.md
  • docs/qa/journeys/J-13-follow-a-live-run.md is excluded by !**/*.md
  • docs/qa/journeys/J-14-read-a-finished-transcript.md is excluded by !**/*.md
  • docs/qa/journeys/J-17-session-create-unified-selector.md is excluded by !**/*.md
  • docs/qa/reports/2026-08-04-durable-acp-sessions.md is excluded by !**/*.md
  • docs/qa/scenarios/ET-running-session-window-close-clean.md is excluded by !**/*.md
  • docs/qa/scenarios/ET-site-docs-first-session.md is excluded by !**/*.md
  • docs/qa/scenarios/ET-web-session-prompt-runtime-and-create-navigation.md is excluded by !**/*.md
  • docs/qa/scenarios/GL-use-response-as-goal.md is excluded by !**/*.md
  • docs/qa/scenarios/RT-018.md is excluded by !**/*.md
  • docs/qa/scenarios/RT-053.md is excluded by !**/*.md
  • docs/qa/scenarios/RT-059.md is excluded by !**/*.md
  • docs/qa/scenarios/RT-session-runtime-selection-continuity.md is excluded by !**/*.md
  • internal/store/globaldb/schema/migrations/atlas.sum is excluded by !**/*.sum, !**/*.sum
  • internal/tools/builtin/testdata/native-tool-catalog.json is excluded by !**/*.json
  • openapi/compozy.json is excluded by !**/*.json
  • package.json is excluded by !**/*.json
  • packages/site/content/docs/cli/session/index.mdx is excluded by !**/*.mdx
  • packages/site/content/docs/cli/session/meta.json is excluded by !**/*.json
  • packages/site/content/docs/cli/session/runtime/clear.mdx is excluded by !**/*.mdx
  • packages/site/content/docs/cli/session/runtime/index.mdx is excluded by !**/*.mdx
  • packages/site/content/docs/cli/session/runtime/meta.json is excluded by !**/*.json
  • packages/site/content/docs/cli/session/runtime/set.mdx is excluded by !**/*.mdx
  • packages/site/content/docs/getting-started/quick-start.mdx is excluded by !**/*.mdx
  • packages/site/content/docs/getting-started/web-ui.mdx is excluded by !**/*.mdx
  • packages/site/content/docs/index.mdx is excluded by !**/*.mdx
  • packages/site/content/docs/migration/index.mdx is excluded by !**/*.mdx
  • packages/site/content/docs/sessions/lifecycle.mdx is excluded by !**/*.mdx
  • packages/site/content/docs/sessions/resume.mdx is excluded by !**/*.mdx
  • sdk/typescript/src/generated/contracts.ts is excluded by !**/generated/**, !**/generated/**
  • skills/compozy/references/extension-authoring.md is excluded by !**/*.md
  • skills/compozy/references/native-tools.md is excluded by !**/*.md
  • skills/compozy/references/runtime-operations.md is excluded by !**/*.md
  • web/src/generated/compozy-openapi.d.ts is excluded by !**/generated/**, !**/generated/**, !**/*.d.ts
  • web/src/systems/agent/components/stories/agent-sessions-list.stories.tsx is excluded by !**/*.stories.tsx
  • web/src/systems/os/components/stories/attention-surfaces.stories.tsx is excluded by !**/*.stories.tsx
  • web/src/systems/session/components/assistant-ui/stories/session-thread.stories.tsx is excluded by !**/*.stories.tsx
  • web/src/systems/session/routes/agent-session.stories.tsx is excluded by !**/*.stories.tsx
📒 Files selected for processing (141)
  • internal/api/contract/session_runtime_payloads.go
  • internal/api/core/conversions.go
  • internal/api/core/conversions_parsers_test.go
  • internal/api/core/handlers_session_runtime.go
  • internal/api/core/handlers_test.go
  • internal/api/core/interfaces.go
  • internal/api/core/session_workspace.go
  • internal/api/core/test_helpers_test.go
  • internal/api/httpapi/handlers_test.go
  • internal/api/httpapi/session_routes.go
  • internal/api/spec/network_coordination_schema.go
  • internal/api/spec/registry_sessions.go
  • internal/api/spec/spec.go
  • internal/api/testutil/session_stub.go
  • internal/api/testutil/session_stub_runtime.go
  • internal/api/udsapi/handlers_test.go
  • internal/api/udsapi/session_routes.go
  • internal/cli/client_session_api.go
  • internal/cli/client_session_types.go
  • internal/cli/client_sessions.go
  • internal/cli/helpers_test.go
  • internal/cli/session_command.go
  • internal/cli/session_runtime.go
  • internal/cli/session_test.go
  • internal/daemon/host_api_session_adapter.go
  • internal/daemon/native_session_runtime.go
  • internal/daemon/native_tool_binding_groups.go
  • internal/daemon/native_tools_test.go
  • internal/daemon/sandbox_reconcile_session_projection.go
  • internal/extension/contract/host_api.go
  • internal/extension/contract/host_api_method_registry.go
  • internal/extension/contract/host_api_method_registry_access.go
  • internal/extension/contract/permissions.go
  • internal/extension/host_api.go
  • internal/extension/host_api_contract_types.go
  • internal/extension/host_api_methods.go
  • internal/extension/host_api_session_runtime.go
  • internal/extension/host_api_session_runtime_projection.go
  • internal/extension/host_api_test.go
  • internal/extension/host_api_workspace_binding.go
  • internal/extensionprotocol/host_api.go
  • internal/extensionprotocol/host_api_test.go
  • internal/mcp/serve_projection_decisions.go
  • internal/observe/reconcile.go
  • internal/observe/reconcile_test.go
  • internal/session/additional_test.go
  • internal/session/manager.go
  • internal/session/manager_busy_input.go
  • internal/session/manager_defaults.go
  • internal/session/manager_integration_test.go
  • internal/session/manager_prompt_admission.go
  • internal/session/manager_prompt_input_event.go
  • internal/session/manager_prompt_request.go
  • internal/session/manager_prompt_submit.go
  • internal/session/manager_resume.go
  • internal/session/manager_resume_run.go
  • internal/session/manager_runtime_selection.go
  • internal/session/manager_shutdown.go
  • internal/session/manager_start_meta.go
  • internal/session/manager_start_session.go
  • internal/session/manager_start_test.go
  • internal/session/manager_start_types.go
  • internal/session/manager_transition.go
  • internal/session/manager_transition_test.go
  • internal/session/manager_types.go
  • internal/session/provider_lifecycle_test.go
  • internal/session/query_metadata.go
  • internal/session/runtime.go
  • internal/session/session.go
  • internal/session/session_info.go
  • internal/session/session_meta.go
  • internal/session/session_test.go
  • internal/store/globaldb/global_db_session_input_queue_test.go
  • internal/store/globaldb/global_db_session_page.go
  • internal/store/globaldb/global_db_session_scan.go
  • internal/store/globaldb/global_db_session_test.go
  • internal/store/globaldb/global_db_session_update.go
  • internal/store/globaldb/global_db_test.go
  • internal/store/globaldb/queries/session_core.sql
  • internal/store/globaldb/schema/definitions/20_sessions.sql
  • internal/store/globaldb/schema/migrations/00048_schema.sql
  • internal/store/globaldb/session_core_mapping.go
  • internal/store/globaldb/session_runtime_selection_mapping.go
  • internal/store/globaldb/sqlcgen/models.go
  • internal/store/globaldb/sqlcgen/session_core.sql.go
  • internal/store/session_meta_types.go
  • internal/store/session_runtime.go
  • internal/store/session_runtime_selection.go
  • internal/store/types_session.go
  • internal/toolmeta/native_entries.go
  • internal/toolmeta/registry_test.go
  • internal/tools/builtin/builtin_test.go
  • internal/tools/builtin/session_runtime.go
  • internal/tools/builtin/sessions.go
  • internal/tools/builtin/toolsets.go
  • internal/tools/builtin_ids.go
  • patches/@assistant-ui%[email protected]
  • sdk/go/contracts/host_contracts_gen.go
  • sdk/go/contracts/host_methods_gen.go
  • sdk/go/contracts/types_019_gen.go
  • sdk/go/contracts/types_020_gen.go
  • sdk/go/contracts/types_021_gen.go
  • sdk/go/contracts/types_022_gen.go
  • sdk/go/contracts/types_023_gen.go
  • sdk/go/contracts/types_024_gen.go
  • sdk/go/contracts/types_025_gen.go
  • sdk/go/contracts/types_026_gen.go
  • sdk/go/contracts/types_027_gen.go
  • web/src/components/assistant-ui/__tests__/session-thread.test.tsx
  • web/src/components/assistant-ui/hooks/use-thread-provider-identity.ts
  • web/src/components/assistant-ui/message-actions.logic.ts
  • web/src/components/assistant-ui/message-actions.tsx
  • web/src/components/assistant-ui/session-assistant-message.tsx
  • web/src/components/assistant-ui/session-thread-messages.tsx
  • web/src/hooks/routes/__tests__/use-session-page-controls.test.tsx
  • web/src/hooks/routes/use-session-page-controls.ts
  • web/src/routes/_app/__tests__/-agent-session-deeplink.router.integration.test.tsx
  • web/src/systems/agent/lib/__tests__/fleet-signals.test.ts
  • web/src/systems/agent/routes/agent-detail-story-fixtures.ts
  • web/src/systems/os/apps/session/session-window-view.tsx
  • web/src/systems/os/components/__tests__/os-window-deck.test.tsx
  • web/src/systems/os/components/__tests__/sessions-modal.test.tsx
  • web/src/systems/os/lib/__tests__/attention-model.test.ts
  • web/src/systems/session/adapters/__tests__/session-api.test.ts
  • web/src/systems/session/adapters/session-api.ts
  • web/src/systems/session/components/__tests__/session-chat-runtime-provider.test.tsx
  • web/src/systems/session/contexts/session-prompt-runtime-context.tsx
  • web/src/systems/session/hooks/__tests__/use-session-actions.test.tsx
  • web/src/systems/session/hooks/__tests__/use-session-create-dialog.test.tsx
  • web/src/systems/session/hooks/__tests__/use-session-prompt-runtime.test.tsx
  • web/src/systems/session/hooks/__tests__/use-sessions.test.tsx
  • web/src/systems/session/hooks/use-session-prompt-runtime.ts
  • web/src/systems/session/hooks/use-session-runtime-selection.ts
  • web/src/systems/session/index.ts
  • web/src/systems/session/lib/session-running.ts
  • web/src/systems/session/mocks/fixtures.ts
  • web/src/systems/session/mocks/handlers.ts
  • web/src/systems/session/stores/__tests__/session-prompt-runtime-store.test.ts
  • web/src/systems/session/stores/session-prompt-runtime-store.ts
  • web/src/systems/session/types.ts
  • web/src/systems/workspace/mocks/fixtures.ts
💤 Files with no reviewable changes (1)
  • web/src/components/assistant-ui/hooks/use-thread-provider-identity.ts

Comment thread internal/api/core/handlers_test.go Outdated
Comment thread internal/daemon/native_tool_binding_groups.go
Comment thread internal/extension/contract/host_api.go Outdated
Comment thread internal/extension/host_api_test.go
Comment thread internal/session/additional_test.go Outdated
Comment thread internal/store/globaldb/global_db_session_test.go
Comment thread web/src/hooks/routes/__tests__/use-session-page-controls.test.tsx Outdated
Comment thread web/src/systems/session/hooks/use-session-runtime-selection.ts Outdated
Comment thread web/src/systems/session/stores/session-prompt-runtime-store.ts Outdated
coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 4, 2026

@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: 2

Caution

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

⚠️ Outside diff range comments (1)
internal/session/additional_test.go (1)

363-371: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert StateActive after restart.

The test checks that restarted.Get returns a session. It does not check resumed.Info().State. This test cannot distinguish an active session from another returned state.

Add the active-state assertion before cleanup.

Proposed test assertion
 		if !ok {
 			t.Fatalf("Get(%q) found = false, want resumed session", session.ID)
 		}
+		if got := resumed.Info().State; got != StateActive {
+			t.Fatalf("resumed state = %q, want %q", got, StateActive)
+		}
 		t.Cleanup(func() {

As per path instructions, tests must focus on state management and verify behavior outcomes.

🤖 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 `@internal/session/additional_test.go` around lines 363 - 371, Add an assertion
immediately after the successful restarted.Get call in the restart test to
verify resumed.Info().State equals StateActive, before registering cleanup. Keep
the existing session lookup and cleanup behavior unchanged.

Source: Path instructions

🤖 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 `@internal/session/additional_test.go`:
- Around line 385-390: Update the Prompt assertions in the test around
h.manager.Prompt to verify the specific expected errors rather than only
checking err != nil. Use the suite’s established error assertion helper and the
expected empty-prompt and missing-session error symbols for each call.
- Around line 569-579: Replace the time.After-based synchronization around
waitForSessionResumes with a deterministic wait-point observer that confirms the
goroutine has entered and is blocked in waitForSessionResumes before closing
pending.done. Split the failed-run and pending-run assertions as needed so the
test explicitly verifies shutdown waits for the pending resume and fails if that
behavior changes.

---

Outside diff comments:
In `@internal/session/additional_test.go`:
- Around line 363-371: Add an assertion immediately after the successful
restarted.Get call in the restart test to verify resumed.Info().State equals
StateActive, before registering cleanup. Keep the existing session lookup and
cleanup behavior unchanged.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 826f0495-3b4b-4eaa-ba44-e15a4335a5a1

📥 Commits

Reviewing files that changed from the base of the PR and between 9378bf0 and 8761fa7.

⛔ Files ignored due to path filters (3)
  • .codex/agents/explorer.toml is excluded by !**/*.toml, !.codex/**
  • CLAUDE.md is excluded by !**/*.md
  • sdk/typescript/src/generated/contracts.ts is excluded by !**/generated/**, !**/generated/**
📒 Files selected for processing (37)
  • internal/api/core/conversions_parsers_test.go
  • internal/api/core/handlers_test.go
  • internal/cli/session_test.go
  • internal/daemon/host_api_session_adapter.go
  • internal/daemon/native_tool_availability.go
  • internal/daemon/native_tool_binding_groups.go
  • internal/daemon/native_tool_bindings.go
  • internal/daemon/native_tools_test.go
  • internal/extension/contract/host_api.go
  • internal/extension/host_api_session_runtime.go
  • internal/extension/host_api_test.go
  • internal/session/additional_test.go
  • internal/session/manager_integration_test.go
  • internal/session/manager_prompt_admission.go
  • internal/session/manager_resume.go
  • internal/session/manager_resume_run.go
  • internal/session/manager_transition_test.go
  • internal/session/repair_event_payload.go
  • internal/session/session_test.go
  • internal/store/globaldb/global_db_session_test.go
  • internal/store/session_runtime_selection.go
  • sdk/go/contracts/types_020_gen.go
  • sdk/go/contracts/types_021_gen.go
  • sdk/go/contracts/types_022_gen.go
  • sdk/go/contracts/types_023_gen.go
  • sdk/go/contracts/types_024_gen.go
  • sdk/go/contracts/types_025_gen.go
  • sdk/go/contracts/types_026_gen.go
  • sdk/go/contracts/types_027_gen.go
  • web/src/hooks/routes/__tests__/use-session-page-controls.test.tsx
  • web/src/systems/session/components/__tests__/session-chat-runtime-provider.test.tsx
  • web/src/systems/session/hooks/__tests__/use-session-prompt-runtime.test.tsx
  • web/src/systems/session/hooks/__tests__/use-session-runtime-selection.test.tsx
  • web/src/systems/session/hooks/use-session-prompt-runtime.ts
  • web/src/systems/session/hooks/use-session-runtime-selection.ts
  • web/src/systems/session/stores/__tests__/session-prompt-runtime-store.test.ts
  • web/src/systems/session/stores/session-prompt-runtime-store.ts
🚧 Files skipped from review as they are similar to previous changes (20)
  • internal/cli/session_test.go
  • internal/session/manager_resume_run.go
  • internal/store/session_runtime_selection.go
  • web/src/systems/session/stores/tests/session-prompt-runtime-store.test.ts
  • internal/store/globaldb/global_db_session_test.go
  • internal/session/manager_prompt_admission.go
  • internal/daemon/native_tools_test.go
  • web/src/systems/session/hooks/tests/use-session-prompt-runtime.test.tsx
  • internal/api/core/conversions_parsers_test.go
  • web/src/hooks/routes/tests/use-session-page-controls.test.tsx
  • internal/daemon/host_api_session_adapter.go
  • web/src/systems/session/hooks/use-session-prompt-runtime.ts
  • internal/session/manager_transition_test.go
  • internal/session/manager_integration_test.go
  • internal/extension/host_api_session_runtime.go
  • sdk/go/contracts/types_025_gen.go
  • internal/session/manager_resume.go
  • internal/api/core/handlers_test.go
  • internal/extension/host_api_test.go
  • internal/session/session_test.go

Comment thread internal/session/additional_test.go Outdated
Comment thread internal/session/additional_test.go Outdated
coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 4, 2026
@pedronauck
pedronauck merged commit 170359a into main Aug 4, 2026
11 of 13 checks passed
@pedronauck
pedronauck deleted the session-fixes branch August 4, 2026 20:56

This branch was successfully deployed

1 active deployment
Preview — 06299528 Deployed Aug 4, 2026 by vercel[bot]
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