Skip to content

fix: preserve subagent session ownership#261

Merged
Nek-12 merged 10 commits into
mainfrom
fix/subagent-followups
May 14, 2026
Merged

fix: preserve subagent session ownership#261
Nek-12 merged 10 commits into
mainfrom
fix/subagent-followups

Conversation

@Nek-12

@Nek-12 Nek-12 commented May 14, 2026

Copy link
Copy Markdown
Member

Summary

  • reapply persisted subagent role settings on resume without blocking continuation when roles are missing
  • update model-visible subagent catalog wording and backtick role labels
  • attach TUI to active headless sessions as read-only so the original builder run remains the runtime owner
  • preserve explicit --agent default/none/self clearing semantics for continued headless runs

Verification

  • ./scripts/test.sh ./...
  • ./scripts/build.sh --output ./bin/builder
  • git diff --check
  • push hook: formatting, go vet, go build, test

Summary by CodeRabbit

  • New Features

    • Attach to active sessions in read-only mode so interactive viewers don’t interrupt headless runs.
    • Explicit agent-role overrides are tracked so choosing/clearing a role is honored and persisted correctly.
    • UI now prevents edits when connected in read-only mode.
  • Documentation

    • Clarified headless/session continuation behavior and agent-role reapplication in docs.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@Nek-12 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 35 minutes and 7 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, 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 have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2ad55b98-6c99-4408-a52a-9253a29fab1c

📥 Commits

Reviewing files that changed from the base of the PR and between ac90337 and bf7fa1a.

📒 Files selected for processing (4)
  • cli/app/internal/worktreemutation/service.go
  • cli/app/internal/worktreemutation/service_test.go
  • server/sessionruntime/service.go
  • server/sessionruntime/service_test.go
📝 Walkthrough

Walkthrough

This PR adds read-only session attachments for externally-owned runtimes, an explicit AgentRoleSet override flag across CLI/server APIs, planner base/active fields for resumed-role handling, client-side read-only write gates, and tests updating planner/session runtime/attach behaviors.

Changes

Read-only attachment and explicit agent role tracking

Layer / File(s) Summary
API contracts and override flags
shared/serverapi/run_prompt.go, shared/serverapi/session_runtime.go
Adds RunPromptOverrides.AgentRoleSet, RunPromptOverrides.NeedsAuthState(), and adjusts override detection; activation responses include ReadOnly where applicable.
Server planner and tests
server/launch/planner.go, server/launch/planner_test.go
Adds BaseSettings/BaseSource to SessionPlan; PlanSession/ApplyRunPromptOverrides use base baseline for resumed roles, persist continuation when AgentRoleSet is set, and include extensive tests for resume/override scenarios.
Session launch auth-state gating
server/sessionlaunch/service.go, server/sessionlaunch/service_test.go
Auth-state is fetched only when overrides.NeedsAuthState() is true; tests add a failing auth-state reader and verify AgentRoleSet flows don't require auth state.
Server sessionruntime external detection & lifecycle
server/sessionruntime/service.go, server/sessionruntime/service_test.go
ActivateSessionRuntime returns ReadOnly: true when an external runtime is active; runtimeHandle gains closing flag and close/release paths mark closing before teardown.
Runtime attach and session lifecycle
cli/app/internal/runtimeattach/lease.go, cli/app/session_lifecycle.go
Lease activation short-circuits for read-only responses, Lease.ReadOnly added; read-only session actions resolved locally; persistence skipped when no controller lease.
Client UI read-only gating and wiring
cli/app/ui_runtime_client.go, cli/app/internal/worktreemutation/service.go, cli/app/ui_worktrees.go, cli/app/internal/worktreemutation/service_test.go
sessionRuntimeClient gains read-only state and ensureWritable gating; RuntimeControl supports ReadOnly gate and ErrReadOnlyRuntime; worktree service wires read-only predicate; tests ensure early rejection of mutations.
Misc tests: leases, lifecycle, planner helpers
cli/app/internal/runtimeattach/lease_test.go, cli/app/session_lifecycle_test.go, server/launch/planner_test.go
Adds lease recovery/read-only tests, resolveReadOnlySessionAction tests, and multiple planner tests validating resumed-role behavior and helper signature changes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

autorelease

🚥 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 'fix: preserve subagent session ownership' accurately describes the main objective: ensuring session ownership is maintained when headless runs attach subagent roles, preventing read-only mode issues and preserving continuation semantics.
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 fix/subagent-followups

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.

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

🤖 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 `@cli/app/internal/runtimeattach/lease.go`:
- Around line 42-44: The Recover path currently ignores resp.ReadOnly and
converts that case into ErrEmptyControllerLease; update Recover (and the similar
block around lines 51-57) to mirror Activate's handling by returning
Lease{ReadOnly: true}, nil when resp.ReadOnly is true instead of returning
ErrEmptyControllerLease, ensuring the Lease struct's ReadOnly field is preserved
for downstream callers (reference Recover, Activate, Lease,
ErrEmptyControllerLease, and resp.ReadOnly to locate the spots to change).

In `@server/launch/planner.go`:
- Around line 93-110: The current code mutates baseActive.OpenAIBaseURL from
meta.Continuation.OpenAIBaseURL, causing BaseSettings to carry role-specific
state; instead, do not modify baseActive — keep baseActive =
EffectiveSettings(...) unchanged and derive any role-specific OpenAIBaseURL into
a separate local (e.g., roleURL) or only set continuation.OpenAIBaseURL after
applyPersistedSubagentRoleSettings/when determining active, so
applyPersistedSubagentRoleSettings and EffectiveSettings operate on the true
baseline; ensure SetContinuationContext receives continuation.OpenAIBaseURL from
the role-specific active value (not written back into baseActive) and add a
regression test that resumes a session with a role-specific openai_base_url then
clears or switches roles to verify workspace/base config remains correct.
- Around line 145-151: The code marks all role.Sources as "subagent"
unconditionally, which can label blocked/locked overrides as applied; update the
logic after calling sourceReportWithSubagentRoleSources so you only set
effectiveSources[key] = "subagent" for keys that were actually applied to
resolved (e.g., compare the resolved values vs the base/effectiveSource before
the role was applied or check that the locked setting didn’t prevent the
change—specifically for model compare resolved.ActiveSettings.Model to the
role’s model) and only then call applyReviewerInheritance and assign
effectiveSource.Sources = effectiveSources; apply the same fix in the other
similar block (lines ~219-233) that also uses
sourceReportWithSubagentRoleSources.
🪄 Autofix (Beta)

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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8e34db98-3436-41d0-948f-3037c4b75589

📥 Commits

Reviewing files that changed from the base of the PR and between cbbaba4 and cca0b0e.

📒 Files selected for processing (25)
  • cli/app/app.go
  • cli/app/internal/runtimeattach/activity.go
  • cli/app/internal/runtimeattach/activity_test.go
  • cli/app/internal/runtimeattach/lease.go
  • cli/app/internal/runtimeattach/lease_test.go
  • cli/app/launch_planner.go
  • cli/app/run_prompt.go
  • cli/app/runtime_attachment.go
  • cli/app/runtime_attachment_test.go
  • cli/app/session_lifecycle.go
  • cli/app/ui_runtime_client.go
  • cli/app/ui_runtime_client_control.go
  • cli/builder/main.go
  • cli/builder/main_test.go
  • docs/dev/decisions.md
  • docs/src/content/docs/headless.md
  • server/launch/planner.go
  • server/launch/planner_test.go
  • server/runtime/meta_context.go
  • server/runtime/subagents_test.go
  • server/sessionruntime/service.go
  • server/sessionruntime/service_test.go
  • shared/serverapi/run_prompt.go
  • shared/serverapi/run_prompt_test.go
  • shared/serverapi/session_runtime.go

Comment thread cli/app/internal/runtimeattach/lease.go
Comment thread server/launch/planner.go
Comment thread server/launch/planner.go Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cca0b0e1f6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/sessionruntime/service.go Outdated
Comment on lines +150 to +151
if s.externalSessionRuntimeActive(sessionID) {
return serverapi.SessionRuntimeActivateResponse{ReadOnly: true}, nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid returning read-only during local release handoff

The new externalSessionRuntimeActive short-circuit can misclassify a session as externally owned during normal local handoff: ReleaseSessionRuntime deletes s.handles[sessionID] before closeFn() unregisters the runtime, so a concurrent ActivateSessionRuntime can observe IsSessionRuntimeActive=true and handles[sessionID]==nil and incorrectly return ReadOnly=true. In that window, a legitimate reconnect/reattach can be forced into read-only mode even though no external controller actually exists.

Useful? React with 👍 / 👎.

Comment on lines +102 to +104
} else {
runtimeClient.SetReadOnly(true)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Block worktree mutations for read-only runtime attachments

Read-only attach only toggles sessionRuntimeClient via SetReadOnly(true), but worktree mutations bypass ensureWritable and still issue control RPCs using controllerLeaseIDValue (which remains the default placeholder lease). In a headless-owned read-only attach, /worktree create/switch/delete paths now fail with invalid-lease/recovery errors instead of a deterministic read-only rejection, which is a functional regression for those commands.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4c0ef0ef54

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/launch/planner.go Outdated
return base, source
}
resolved := cloneSettings(base)
_ = applyBuiltInRoleHeuristics(&resolved, normalizedRole, persistedRoleProviderID(base), allowModelOverride)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Derive persisted fast-role provider from effective role settings

The persisted-role resume path applies built-in role heuristics using persistedRoleProviderID(base) before any role/provider overrides are considered. When the base model is an alias and provider identity is only available via provider_override (or role-specific provider fields), persistedRoleProviderID can be empty, so resumed fast sessions skip fast heuristics (model/priority/context tuning) even though explicit --agent fast would apply them. This breaks the new “reapply persisted role on continue” behavior for provider-aliased configs.

Useful? React with 👍 / 👎.

Comment on lines +79 to +80
if lease.ReadOnly {
return lease, nil, nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve lifecycle command behavior for read-only attachments

Returning leaseManager=nil for read-only attachments leaves the runtime plan without a controller lease ID, but lifecycle transitions still send session_id and therefore require a non-empty lease. In practice, attaching to an active headless session as read-only makes transition actions (for example /new, /resume, /open) fail with controller-lease validation errors instead of a deterministic read-only flow. This regression is triggered specifically in the new read-only attach path.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4bd46fcf75

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/sessionruntime/service.go Outdated
Comment on lines +151 to +152
if s.externalSessionRuntimeActive(sessionID) {
return serverapi.SessionRuntimeActivateResponse{ReadOnly: true}, nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Revalidate active runtime before returning read-only

ActivateSessionRuntime now short-circuits to ReadOnly=true based on externalSessionRuntimeActive, but that decision is made from two unsynchronized data sources and returned immediately. If the external/headless runtime exits in that tiny window, the caller still gets a read-only attach (no lease) instead of taking ownership, and the follow-up attach flow can fail because the runtime is already gone. This creates a timing-dependent failure when connecting around headless shutdown; the read-only response should be confirmed against current state (or retried) before returning.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e3a7f12406

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 28 to +30
func (o RunPromptOverrides) HasAny() bool {
return strings.TrimSpace(o.AgentRole) != "" ||
return o.AgentRoleSet ||
strings.TrimSpace(o.AgentRole) != "" ||

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Don’t treat default-role clear as auth-dependent override

HasAny now returns true when AgentRoleSet is true, which makes PlanLaunchSession fetch auth state before applying overrides (server/sessionlaunch/service.go, auth lookup gate). For --agent default|none|self this is only clearing persisted role and does not use provider capabilities, so a transient/invalid auth store now causes run planning to fail even though the operation should be local. This regresses continuation flows specifically when users explicitly clear role while auth state cannot be loaded.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 852c916425

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +247 to +248
default:
return resolvedSessionAction{}, errReadOnlyRuntime

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Handle logout in read-only session transitions

When a TUI attaches read-only to an active headless runtime, resolveReadOnlySessionAction falls into the default branch for UIActionLogout and returns errReadOnlyRuntime, so /logout exits with a read-only error instead of running the logout/reauth flow. This is a functional regression specific to read-only attachments: ui_input_controller_commands.go still emits UIActionLogout, but the new read-only transition switch only allows new/resume/open/exit.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 17e15785b6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/launch/planner.go
Comment on lines +175 to +179
if providerOverride := strings.TrimSpace(settings.ProviderOverride); providerOverride != "" {
return providerOverride
}
provider, err := llm.InferProviderFromModel(settings.Model)
if err != nil {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Include non-model provider cues for persisted fast role

When reapplying a persisted role, persistedRoleProviderID only checks provider_capabilities.provider_id, provider_override, then model-name inference. For aliased models (e.g. team aliases) without provider_override, this returns empty even if openai_base_url (or auth-selected provider) clearly implies OpenAI, so applyBuiltInRoleHeuristics skips fast-role tuning on resume. This makes persisted fast sessions behave differently from explicit --agent fast (no gpt-5.4-mini/priority-mode heuristic), which is a regression in the new role-resume behavior.

Useful? React with 👍 / 👎.

@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

🤖 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 `@cli/app/internal/worktreemutation/service.go`:
- Around line 122-124: The read-only guard currently inside
controlContextWithLease() causes non-mutating calls like List() to be blocked;
move the check into the mutation-only path by removing the ReadOnly check from
controlContextWithLease() and instead enforcing it at the start of runMutation()
so Create, Switch, and Delete operations return ErrReadOnlyRuntime while List
and other read-only flows that call controlContextWithLease() continue to work.
🪄 Autofix (Beta)

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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 162cf1e8-53be-4813-be21-4d23b1f8ec74

📥 Commits

Reviewing files that changed from the base of the PR and between cca0b0e and ac90337.

📒 Files selected for processing (14)
  • cli/app/internal/runtimeattach/lease.go
  • cli/app/internal/runtimeattach/lease_test.go
  • cli/app/internal/worktreemutation/service.go
  • cli/app/internal/worktreemutation/service_test.go
  • cli/app/session_lifecycle.go
  • cli/app/session_lifecycle_test.go
  • cli/app/ui_runtime_client.go
  • cli/app/ui_worktrees.go
  • server/launch/planner.go
  • server/launch/planner_test.go
  • server/sessionlaunch/service.go
  • server/sessionlaunch/service_test.go
  • server/sessionruntime/service.go
  • shared/serverapi/run_prompt.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • cli/app/internal/runtimeattach/lease.go
  • cli/app/ui_runtime_client.go
  • server/launch/planner.go

Comment thread cli/app/internal/worktreemutation/service.go Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c310dbe609

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +102 to +103
} else {
runtimeClient.SetReadOnly(true)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Provide usable lease path for read-only worktree listing

In the read-only attach branch, the runtime client is only marked via SetReadOnly(true) and keeps its default placeholder lease ID, so read-only sessions still issue /wt status list requests with a non-owner lease. worktreemutation.Service.List always sends ControllerLeaseID, and server-side worktree handling enforces RequireControllerLease, so these read-only status/list flows fail with invalid-lease errors instead of allowing deterministic read-only inspection (or a clear local read-only rejection).

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: af6949f09d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/sessionruntime/service.go Outdated
Comment on lines +604 to +605
if current.closing {
return nil, nil, activationClaimOwner, errors.Join(serverapi.ErrSessionAlreadyControlled, fmt.Errorf("session %q is closing its active controller", sessionID))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Allow takeover while release is still closing

Returning ErrSessionAlreadyControlled as soon as current.closing is set makes activation fail during legitimate handoff windows: ReleaseSessionRuntime now sets closing=true before closeFn() completes, but the CLI release path uses a fixed 3s timeout (cli/app/internal/runtimeattach/lease.go), so a slow shutdown can time out client-side and the very next /new//open attach attempt hits this branch and aborts instead of waiting/retrying ownership transfer. This introduces a timing-dependent regression for normal lifecycle transitions under slower runtime teardown.

Useful? React with 👍 / 👎.

@Nek-12 Nek-12 merged commit 9f94bff into main May 14, 2026
6 checks passed
@Nek-12 Nek-12 deleted the fix/subagent-followups branch May 14, 2026 23:43
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