Skip to content

Chief: typed approval answers read loosely; allow all, for this turn or for 1h - #22755

Closed
teamleaderleo wants to merge 4 commits into
feat-cmux-nextfrom
cmux/paired-approvals
Closed

teamleaderleo wants to merge 4 commits into
feat-cmux-nextfrom
cmux/paired-approvals

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Leo answered a Chief approval from his phone with "allow", "allow..." and "ALLOW", and the Chief kept waiting. Only a bare allow/deny counted, each answer settled one card, and a single turn sent six cards.

  • A typed answer ignores case, punctuation and emoji. allow, ALLOW..., yes, ok, 👍 and ✅ allow; deny, no, 👎 and ❌ deny. Any other word in the message ("yes, and check CI", "hello?") keeps it a normal message.
  • allow all / deny all answer every pending card in that conversation.
  • allow for this turn also lets the rest of the running turn go through. It is cleared when the turn ends or when another participant's message is steered into the turn.
  • allow for 1h (also 30m, 2 hours, an hour; at most a day) also covers the owner's own gated turns (paired device, Home) until it expires, never another participant's turn.
  • One line confirms what was answered, e.g. "Allowed: run ls" or "Allowed for 1h: run ls".
  • The Chief's own send and control status are described in words ("send you “…” with a file from this Mac", "check on its subagents"), not as tool names or JSON.

The rest of the brief was already on base in #22640. Paired-device turns no longer ask by default (remote.ask is off, so they run like local turns). The Chief's own send/reply/status never ask. The card text is human-readable. The screenshot came from a Chief binary built before #22640: its "Approval needed: … every local effect waits for you … wants to run: {json}" text no longer exists in the tree.

Security: nothing new runs without the owner's word. Scoped allows are set only by the owner's own message (is_owner_message), stop/deny-repeat rules still win, a time window never covers another participant's turn, and deny never carries forward. Risk is normal: this changes how the owner's explicit answers are parsed. It does not change which turns are gated or who can answer.

Restarts that cut turns (brief item 4) were handed to lane update-survival with evidence: ChiefAcpmuxHeal.heal() → handOffReplaced() sends SIGTERM to the host right away after an in-place update, instead of handing off when the turn is idle.

Testing

Red: cargo test --manifest-path Native/OptChat/optchat-chief/Cargo.toml --test approval_gates at cb5e16f (test-only commit). It cannot compile there: approval::Reply/Scope don't exist yet, and the send/status descriptions differ. Green: the same command at the head, run by the optchat-chief tests (real daemon) job.

Observed / Not run

  • Observed: rustfmt on the changed files.
  • Not run locally: cargo build/test/clippy. Agents don't compile on the Mac, and the fleet ci-step allowlist refused scripts/ci/cargo-test-selected.sh, so this PR's CI job is the first compile and test run. The red result above is by construction; it was not executed.
  • The commits were made through the GitHub git-data API because local git on cosmic-gray was stuck in I/O wait, so the pre-push gate did not run. The change touches only Rust and README, which the gate's Swift checks don't cover.

Changelog

Fixed: Chief approvals accept "allow", "ALLOW...", "yes" or 👍 typed from a paired device, plus "allow all", "allow for this turn" and "allow for 1h", and confirm what was allowed.

Agent session: cosmic-gray

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Fixes Chief approval answers so a typed reply from a paired device is read loosely and can cover more than one pending request. Previously only a bare allow/deny counted, one answer settled one card, and a single turn sent six cards.

  • A typed answer ignores case, punctuation and emoji; any other word in the message keeps it a message.
  • allow all / deny all answer every pending approval in that conversation.
  • allow for this turn lets the rest of the running turn run, but only when the answer is to the turn's own request (a subagent's leftover card does not count); it is cleared when the turn ends or another participant joins.
  • allow for 1h (also 30m, 2 hours, an hour; durations add up, at most a day) covers the owner's own gated turns (paired device, Home) until it expires, never another participant's; a zero window is not an answer.
  • One line confirms what was answered, and the Chief's send and control status are described in words, not as tool JSON.

Security: nothing new runs without the owner's word; scoped allows are set only by the owner's own message, stop/deny-repeat rules still win, and a time window never covers another participant's turn.

Written for commit b8dcde5. Summary will update on new commits.

View guided diff Turn on auto-fix

teamleaderleo and others added 2 commits October 20, 2026 18:52
…r this turn, allow for 1h (red)

Leo, 2026-10-20: he answered "allow", "allow..." and "ALLOW" from his
phone, the turn kept waiting, and one turn sent six prompts. A typed answer is read
loosely (case, punctuation, emoji, yes/ok/no). It answers the oldest prompt or
all of them, can cover the rest of the turn or a time window, and gets a one-line
confirmation. The Chief's own send and status read are described in words,
never as tool JSON.

Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c01-a495-7013-b37d-abe71de99881&host=cosmic-gray
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…turn or for 1h; confirm in one line

Leo answered "allow", "allow..." and "ALLOW" from his phone and the
Chief kept waiting. Only a bare allow/deny counted, one answer settled one
card, and one turn sent six cards.

- A typed answer ignores case, punctuation and emoji, and accepts yes/ok/👍/✅
  and no/👎/❌. Anything else in the message keeps it a message.
- "allow all" / "deny all" answer every pending card. "allow for this
  turn" lets the rest of the turn run. "allow for 1h" (at most a day) lets
  the owner's own gated turns (paired device, Home) run until then, never
  another participant's. A non-owner joining the turn cancels the turn allow.
- One line confirms what was answered ("Allowed: run `ls`").
- The Chief's own send and status read are described by what they do ("send you
  “...”", "check on its subagents"), not by tool name.

Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c01-a495-7013-b37d-abe71de99881&host=cosmic-gray
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

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

Review 64bc2cb: 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=pr22755 -f ref=cmux/paired-approvals -f platform=macos -f backend_mode=local

teamleaderleo and others added 2 commits October 20, 2026 18:57
… asking; 1h 30m adds up; 0h is no answer (red)

Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c01-a495-7013-b37d-abe71de99881&host=cosmic-gray
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tions add up; a zero window is no answer

Review of #22755: "allow for this turn" typed to approve a leftover
subagent card set the turn allow for a running turn the owner never saw a
card from. "allow for 1h 30m" kept only 30m, and "allow for 0h" posted
"Allowed for 0m".

Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c01-a495-7013-b37d-abe71de99881&host=cosmic-gray
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Bead cx-1ieyt created for this PR by the cmux coordinator.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Closing: superseded by #22747 (merged 2026-10-21 01:55Z), which removes Chief approvals entirely. The owner's turns never ask, and another person's turn is refused at once, with no card and no allow/deny answer. This PR made the typed answers to those approvals looser and added scoped allows, so nothing is left for it to fix. The restart cause found here (ChiefAcpmuxHeal.heal() sends SIGTERM to the host with no idle handoff) went to lane update-survival. #22747 also fixed the resume-after-restart taint that made every turn ask.

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