Skip to content

fix(pipeline): make managed (bubbles) trigger mode actually work - #277

Merged
ANonABento merged 1 commit into
mainfrom
managed-mode-fixes
Aug 22, 2026
Merged

fix(pipeline): make managed (bubbles) trigger mode actually work#277
ANonABento merged 1 commit into
mainfrom
managed-mode-fixes

Conversation

@ANonABento

Copy link
Copy Markdown
Owner

Four defects, all found by running a real claude agent through a real column. Each alone made managed mode useless for automation; together they made it look like it worked — the agent ran, streamed bubbles, and exited 0.

1. Every file edit was denied

managed_trigger_turn_args never passed --dangerously-skip-permissions, and a headless -p run has nobody to answer a permission prompt. The transcript is unambiguous:

Claude requested permissions to write to …/math.js, but you haven't granted it yet.

…repeatedly, then exit 0. An agent that changed nothing reported success.

Terminal mode has always passed the flag at command-build time. The shared ClaudeCliAdapter deliberately doesn't — chef sessions use it and are interactive — so this belongs on the trigger-only builder, where the run is unattended and sandboxed in its own worktree.

2. The pipeline never advanced

The managed path stopped at agent_status = completed and never called mark_complete. So a column with agent_complete + auto_advance worked in terminal mode and silently stalled in managed mode: finished agent, task sitting in place.

Now completes behind the same moved-columns guard the terminal path uses, and only once the queued-input replay chain ends — a pending message means the agent isn't done.

3. Uncommitted work would have been lost

Advancing into a terminal column deletes the worktree. auto_commit_completed_worktree existed but this path never called it — so fixing (2) alone would have turned a stall into data loss. It now runs before completion.

Worth being precise: I initially read the missing work as a rescue bug. It wasn't — the agent had been blocked by (1) and never wrote anything, so there was nothing to rescue. The rescue only proved necessary once permissions were fixed and the agent could actually edit.

4. An attached agent's MCP flags were dropped

spawn_managed_trigger_task ignored cli_args entirely, so an agent whose dossier advertised tools ran with none. Now threaded through, including into the replay turn.

Ordering matters: --allowedTools is declared <tools...> — variadic — and managed mode passes the prompt positionally. Appending the flags just before it makes claude swallow the prompt as a tool name and die with Input must be provided either through stdin or as a prompt argument (reproduced against 2.1.239). They're spliced in after --print, where a base flag closes the list. Terminal mode is unaffected — the prompt sits behind an explicit -p.

Also: codex no longer gets claude's MCP flags

roster::plan was emitting --mcp-config / --allowedTools for codex agents too. codex exec accepts neither (0.145.0), so that would break the launch rather than merely run toolless. Withheld, and the gap is logged.

Verified end to end on a real column

Isolated data dir, real repo, planted bug, a purpose-built stdio MCP server so "tools arrived" is observable rather than assumed:

check before after
permission denials many 0
MCP tool called no yes
column stuck in Fix Done
model haiku (column override beat agent's sonnet)
the fix lost return a + b, preserved via the rescue commit

Checks

cargo clippy -D warnings · cargo test --lib 564 (+4) · tsc · eslint · test:ipc · test:type-scale · vitest 444.

(The 6 kaitencode-mcp failures are the known local artifact of a running app intercepting the API — green on CI.)

Four defects, all found by running a real claude agent through a real
column. Each one alone made managed mode useless for automation; together
they made it look like it worked.

1. Every file edit was denied.

`managed_trigger_turn_args` never passed `--dangerously-skip-permissions`,
and a headless `-p` run has nobody to answer a permission prompt. The
transcript is unambiguous: "Claude requested permissions to write to
…/math.js, but you haven't granted it yet", repeatedly, then exit 0. An
agent that changed nothing reported success.

Terminal mode has always passed the flag at command-build time. The shared
`ClaudeCliAdapter` deliberately does not, because chef sessions use it and
are interactive — so this belongs on the trigger-only builder, where the
run is unattended and sandboxed in its own worktree.

2. The pipeline never advanced.

The managed path stopped at `agent_status = completed` and never called
`mark_complete`, so a column with `agent_complete` + `auto_advance` worked
in terminal mode and silently stalled in managed mode: finished agent,
task sitting in place. It now completes behind the same moved-columns
guard the terminal path uses, and only once the queued-input replay chain
has ended — a pending message means the agent isn't done.

3. Uncommitted work would have been lost.

Advancing into a terminal column deletes the worktree.
`auto_commit_completed_worktree` existed but this path never called it, so
fixing (2) would have turned a stall into data loss. It now runs before
completion. Made `pub(crate)` for that.

4. An attached agent's MCP flags were dropped.

`spawn_managed_trigger_task` ignored `cli_args` entirely, so an agent whose
dossier advertised tools ran with none of them. Now threaded through,
including into the replay turn so a queued message keeps them.

Where they go matters: `--allowedTools` is declared `<tools...>` — variadic
— and managed mode passes the prompt positionally, so appending the flags
just before it makes claude swallow the prompt as a tool name and die with
"Input must be provided either through stdin or as a prompt argument"
(reproduced against 2.1.239). They are spliced in after `--print`, where a
base flag closes the list. Terminal mode is unaffected; there the prompt
sits behind an explicit `-p`.

Also: `roster::plan` no longer emits claude's MCP flags for codex agents.
`codex exec` accepts neither `--mcp-config` nor `--allowedTools` (0.145.0),
so passing them would break the launch rather than merely run toolless.
The gap is logged instead.

Verified end to end on a real column: 0 permission denials, MCP tool
called, column advanced Todo → Fix → Done, the column's model override
(haiku) beat the agent's own (sonnet), and the fix landed on the branch via
the rescue commit.
@ANonABento
ANonABento merged commit 5740345 into main Aug 22, 2026
3 checks passed
@ANonABento
ANonABento deleted the managed-mode-fixes branch August 22, 2026 02:21
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