Skip to content

Chief: no permission request waits on an answer nobody can give - #22941

Merged
teamleaderleo merged 2 commits into
feat-cmux-nextfrom
chief-no-hang
Oct 21, 2026
Merged

teamleaderleo merged 2 commits into
feat-cmux-nextfrom
chief-no-hang

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Summary

The Chief must never wait on a permission answer that nobody can give. acpmux accepts an allow only from the person's cmux app. The app shows no tab for a Chief turn session. A subagent's prompt is shown only in its agent tab. A cloud peer refuses an allow that comes from this Mac. Before this PR, several paths left a request open with nobody told. The turn then waited until its 3-hour limit ("Using optchat: control · 34m").

  1. Relayed allow (typed "allow" or "1" that the Chief relays with control answer). When acpmux refuses the allow:
    • If the app shows a working Allow button (a local subagent with a workspace), the prompt stays open. The person gets one line in the chat, once per prompt: "a1 waits for your approval to run make deploy: use the Allow button in its workspace."
    • Otherwise the host denies the prompt and tells the person.
    • The note and the control description no longer tell the model to allow. chief agents allow says what still works.
    • Approval cards are gone since Chief: never ask for approvals; another person's turn is refused at once #22747. No path posts a question part, and the tests check this.
  2. Watchdog.
    • A request of a turn session that the host does not allow is denied at once, in every turn (the owner's turn included). Before, the host "left it to its harness" and nobody could answer it. The same applies to a turn session that no turn runs on any more (kept, adopted or ended).
    • The host watches every request it leaves open: a subagent or child prompt with no working button, or a deny that acpmux did not accept. Each one is denied after approval::PERMISSION_WAIT (120 s, on the brain's injected clock). The reason goes to host.log and to the trace (approver: "no approver", reason).
    • The turn idle watchdog now treats a turn that waits on a permission request as idle (TurnFold::awaits_permission). Before, it skipped every turn that had a running tool.
  3. Loop stop. These denials now count toward REPEATS_BEFORE_STOP: a deny after a refused allow, a turn-gate refusal of a Chief tool, and an overdue deny. The turn's stop line gives the reason.
  4. Codex. Codex has a per-MCP-tool approval_mode = "approve". But acpmux gives a Codex turn no optchat MCP server, so Chief tools run as chief <verb> shell commands. No per-tool setting covers those. The reason is documented on codex_turn_config, and the deny stays.

Tests

rbx --lane chief-no-hang --cwd Native/OptChat/optchat-chief -- cargo test --locked --test approval_gates: 17 passed. 9 of them are new and test behaviour at the brain/host boundary with the fake acpmux:

  • a relayed allow tells the person once and keeps the prompt
  • a relayed allow for a prompt the app does not show denies it
  • a prompt that waits 2 minutes is denied, with a trace entry
  • a prompt the app shows waits for the person, also when its workspace opens after the request
  • a turn session's request is refused at once, also for a stale turn session
  • denies after refused allows stop the turn
  • turn-gate refusals stop the turn
  • a turn that waits on a permission counts as idle

The idle test was checked against the old code: it fails ("no cancel 1").

cargo fmt --check: OK. cargo clippy --locked --all-targets -- -D warnings: clean. Full cargo test --locked: every test passes except turn_seal_binding::a_subagent_cannot_reach_owner_controls_on_the_shared_socket. That test also fails on unchanged origin/feat-cmux-next (63bd306) on the same builder, so this PR did not cause it.

Observed / Not run

  • Not run: a live Chief on a tagged build. Nothing here was observed against a real acpmux daemon or the app.
  • The immediate deny of a turn session's request overrides a person's own "ask" rule on the Chief's turn sessions. No app surface shows those sessions; check again if cmux NEXT: NIGHTLY's Chief runs on the app's acpmux, not a daemon of its own #22900 lands.
  • Not fixed: a request raised while the host was away, for example across a host restart. acpmux sends no notification for it, so only the turn idle watchdog covers it, and only for the turn session. A child or subagent prompt raised then gets only the reconcile note.

Changelog

  • Chief: a permission request nobody can answer no longer holds a turn; a relayed allow tells you where to approve, and unanswerable prompts are denied after 2 minutes.

- A relayed allow acpmux refuses (control answer): the person is told once
  where to allow when the app shows a working Allow button, else the prompt
  is denied and the person is told.
- A turn session's request the host does not allow is refused at once (no
  tab shows it), in any turn and for a turn session no turn runs on.
- Requests the host leaves open (a subagent or child prompt with no working
  button, a deny not delivered) are denied after 120 s (injected clock),
  logged and traced.
- Host-side denies of the turn's own requests and turn-gate refusals count
  toward stopping a looping turn.
- The idle watchdog counts a turn that waits on a permission as idle.
- Codex turns: documented why Chief tools still ask under policy ask.
@lawrencecchen lawrencecchen added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 21, 2026
@cursor

cursor Bot commented Oct 21, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot uses usage-based billing for this team and requires on-demand usage to be enabled.

A team admin can enable on-demand usage in the Cursor dashboard.

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review 6aa6ba4: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr22941 -f ref=chief-no-hang -f platform=macos -f backend_mode=local

@teamleaderleo

Copy link
Copy Markdown
Collaborator

Bead cx-3v9rb created for this PR by the cmux coordinator.

@lawrencecchen

Copy link
Copy Markdown
Contributor Author

Correctness review (separate subagent) and resolutions

There are no blockers. The findings and what each became:

  1. Major: a prompt the app shows could be denied after 120 s, when the workspace opens after the first request. Fixed. sub_workspace drops the watches for that session. The overdue deny also checks approval_shown again and skips such a subagent. New test: a_prompt_whose_workspace_opens_after_it_asked_waits_for_the_person.
  2. One request counted twice (a deny that was not delivered, then denied again when overdue). Fixed. An overdue entry that came from a deny that was not delivered does not count again.
  3. Every allow error was taken as "only the person can allow". Fixed. Only acpmux's person-required refusal ("approve this on the Mac app") takes that path. Other errors say that the prompt may already be answered. The "I denied it" line is posted only when the deny was delivered.
  4. The premise that the app shows no tab for a turn session. Kept. The app research (AgentTabs+ChiefHost.swift: the Chief's sessions are on its own acpmux daemon, and a turn session never gets a tab) shows that nobody can answer such a request. So the immediate deny stays, and it overrides a person's own "ask" rule for owner turns on the Chief's turn sessions. Follow-up: if cmux NEXT: NIGHTLY's Chief runs on the app's acpmux, not a daemon of its own #22900 moves the Chief to the app's acpmux, this premise must be checked again.
  5. The idle watchdog can stop a long tool that runs in parallel with a stuck request. Accepted. This is rare, and it gives one retry. The alternative is a 3-hour wait.
  6. The overdue deny runs only on a timeout of the run loop. Accepted. The outbox and wakes work the same way.
  7. tell_person_once posts only to the main conversation; approval_told is inserted before the conversation check. The insert order is fixed. Main conversation only: kept, because the desk receipts post there too.
  8. The stop line pointed to the app for turn sessions. Fixed. The reason is now "nobody can approve that here".
  9. The control description did not say that an allow can lead to a deny. Fixed.
  10. Deny could pick reject_always and write a lasting rule. Fixed. control answer deny uses reject_once, else a cancel.
  11. Tests. Noted. The race test was added (item 1).

Checks after the fixes, on rbx: cargo fmt --check OK. Clippy with -D warnings is clean. The approval_gates suite (17 tests), subagent_control, chief_turn_tools, harness and lib unit tests pass.

@lawrencecchen lawrencecchen added the ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds label Oct 21, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator

cmux-next guards / defaults-snapshot is red on 22 of 22 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

teamleaderleo added a commit that referenced this pull request Nov 4, 2026
…lined unseen

Leo, 2026-11-03 (relayed by Chief): "A Chief subagent's pending permission
prompt must show in Home as an Allow/Deny card, never be declined silently."

#33385 kept #22941's 120 s deadline even after a hidden subagent's Home card
was delivered, so a card nobody opened in two minutes was denied and
cancelled. Now an acknowledged card drops the deadline watch and the overdue
check skips a request with a live card or workspace. A hidden request Home
cannot draw (no single allow-once and reject-once option) opens its
subagent's workspace instead, whose tab answers it. The deadline still
covers requests with neither.

Builds on austinywang's #22639 (the Home Allow/Deny card), which reached
feat-cmux-next through #33385.

Co-authored-by: Austin Wang <38676809+austinywang@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
teamleaderleo added a commit that referenced this pull request Nov 4, 2026
…lined unseen

Leo, 2026-11-03 (relayed by Chief): "A Chief subagent's pending permission
prompt must show in Home as an Allow/Deny card, never be declined silently."

#33385 kept #22941's 120 s deadline even after a hidden subagent's Home card
was delivered, so a card nobody opened in two minutes was denied and
cancelled. Now an acknowledged card drops the deadline watch and the overdue
check skips a request with a live card or workspace. A hidden request Home
cannot draw (no single allow-once and reject-once option) opens its
subagent's workspace instead, whose tab answers it. The deadline still
covers requests with neither.

Builds on austinywang's #22639 (the Home Allow/Deny card), which reached
feat-cmux-next through #33385.

Co-authored-by: Austin Wang <38676809+austinywang@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
teamleaderleo added a commit that referenced this pull request Nov 4, 2026
…lined unseen (#34410)

* test(chief): a delivered Home card waits for the person; an uncardable hidden prompt opens its workspace (red)

Leo, 2026-11-03 (relayed by Chief): a Chief subagent's pending permission
prompt must show in Home as an Allow/Deny card, never be declined silently.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Chief: a subagent's prompt waits in Home for Allow or Deny, never declined unseen

Leo, 2026-11-03 (relayed by Chief): "A Chief subagent's pending permission
prompt must show in Home as an Allow/Deny card, never be declined silently."

#33385 kept #22941's 120 s deadline even after a hidden subagent's Home card
was delivered, so a card nobody opened in two minutes was denied and
cancelled. Now an acknowledged card drops the deadline watch and the overdue
check skips a request with a live card or workspace. A hidden request Home
cannot draw (no single allow-once and reject-once option) opens its
subagent's workspace instead, whose tab answers it. The deadline still
covers requests with neither.

Builds on austinywang's #22639 (the Home Allow/Deny card), which reached
feat-cmux-next through #33385.

Co-authored-by: Austin Wang <38676809+austinywang@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Austin Wang <38676809+austinywang@users.noreply.github.com>
Co-authored-by: cmux-bot[bot] <348531757+cmux-bot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-land Reviewed at this head; next-autoland merges it into feat-cmux-next when its only reds are base reds risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants