Skip to content

feat(mcp): coordinator agent with task visibility, pilot/co-pilot control, and expanded options#100

Draft
brooksc wants to merge 29 commits intojohannesjo:mainfrom
brooksc:feature/orchestrator-control-v2
Draft

feat(mcp): coordinator agent with task visibility, pilot/co-pilot control, and expanded options#100
brooksc wants to merge 29 commits intojohannesjo:mainfrom
brooksc:feature/orchestrator-control-v2

Conversation

@brooksc
Copy link
Copy Markdown
Contributor

@brooksc brooksc commented May 4, 2026

Overview

This PR builds on the initial coordinating agent implementation by @cledoux95 (PR #31) with substantial fixes and new capabilities.

The core motivation: I wanted to use a coordinator agent to drive parallel workstreams, but still be able to monitor each sub-task, answer questions when an agent gets stuck, and take over a task when I want to make a decision myself — then hand it back. Think of it like a pilot/co-pilot handoff: explicit, visible, and safe.


Credit

The foundation of this PR is @cledoux95's work in #31, which introduced the coordinating agent concept, the MCP server/client, and the create_task / send_prompt / wait_for_idle / merge_task tools. This PR would not exist without that work.


What's new / changed

Sub-task visibility (addresses the core UX gap)

In #31, sub-tasks created by the coordinator were not visible in the sidebar. The coordinator agent was essentially working in the dark. Now each sub-task spawned via create_task appears as its own sidebar panel, giving you full terminal visibility into what every agent is doing — exactly like a manually created task.

Pilot/co-pilot control handoff

Each coordinated sub-task shows a banner indicating who is driving:

  • "Orchestrator driving" (subtle grey bar) — the coordinator agent has control; you can observe but the agent is running
  • "You have control — orchestrator is paused" (amber warning bar) — you've taken over; the coordinator cannot send further prompts until you explicitly return control

You can click "Take Control" at any time to pause the coordinator for that task, interact with the agent yourself, then click "Return to Orchestrator" when done.

Expanded create_task options

The coordinator agent can now specify:

  • skipPermissions: true — passes --dangerously-skip-permissions to the sub-agent so it runs fully autonomously without tool-approval interruptions
  • gitIsolation: "worktree" | "direct" | "none" — controls git isolation mode (defaults to "worktree" as before)

Fixes to #31

Several bugs were found and fixed while integrating and testing:

Issue Fix
Hardcoded port 7777 — if the port was in use, the MCP server silently failed findFreePort(7777, 7800) tries ports sequentially until one is free
Missing --mcp-config arg — the coordinator agent was spawned without the MCP config flag, so it had no MCP tools and fell back to bash orchestration TaskAITerminal now passes --mcp-config <path> when task.mcpConfigPath is set
Double-spawn — the orchestrator backend called spawnAgent directly AND the renderer's TerminalView also called it, killing the backend spawn and losing the output subscription Removed backend spawnAgent call; orchestrator now uses onPtyEvent('spawn', ...) to subscribe to output each time the renderer spawns the agent — survives restarts too
MCP server not restarted after app restart — persisted coordinator tasks had no server to connect to after restart, causing fetch failed on all MCP tool calls On startup, App.tsx now awaits StartMCPServer for each persisted coordinator task before the agents are spawned, refreshing the config file with the new port/token
deleteTask wrong call signature — the orchestrator called deleteTask with positional args but the function now takes an options object Fixed to deleteTask({ agentIds, branchName, deleteBranch, projectRoot })
Missing REST input validation — the orchestrator API routes accepted arbitrary input Added type guards returning 400 for invalid name, prompt, projectId, skipPermissions, gitIsolation
waitForIdle hangs when human takes controlsetTaskControl('human') left pending waiters stuck until timeout setTaskControl now unblocks pending waitForIdle callers on any control change
mcp_control_changed missing from preload allowlist Added to ALLOWED_CHANNELS in preload.cjs
Better connection error messagesfetch failed gave no actionable info MCPClient now wraps network errors: "Cannot reach Parallel Code at http://127.0.0.1:PORT. Is the app running?"

Tests

Added 25 new tests across two files:

  • electron/mcp/prompt-detect.test.tsstripAnsi and chunkContainsAgentPrompt (the core of waitForIdle idle detection)
  • electron/mcp/orchestrator.test.ts — control handoff logic: sendPrompt blocked/unblocked, waitForIdle behavior under human control, PTY exit propagation

The tests caught the waitForIdle hang bug described above before it shipped.


Test plan

  • Create a new task with Coordinator mode enabled
  • Coordinator agent spawns sub-tasks; each appears as a new sidebar panel
  • Sub-task panels show the "Orchestrator driving" banner
  • Click Take Control — banner switches to amber "You have control"
  • Coordinator cannot send prompts while human has control (MCP tool returns error)
  • Click Return to Orchestrator — coordinator resumes
  • Kill and relaunch the app; open a coordinator task — MCP tools still work (no fetch failed)
  • create_task with skipPermissions: true spawns sub-agent without permission prompts
  • npm run check && npm test — all pass

🤖 Generated with Claude Code

brooksc and others added 10 commits May 2, 2026 16:10
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Enable a Claude Code agent to programmatically create and orchestrate
other tasks in Parallel Code. Adds an MCP server with 9 tools
(create_task, send_prompt, wait_for_idle, get_task_diff, merge_task,
etc.), a main-process orchestrator, REST API endpoints, and UI
support including coordinator mode toggle, sub-task status strip,
and "via Coordinator" sidebar labels.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cherry-picked from cledoux95/task/coordinating-agent (commit 6650b05).
Fixed console.log → console.warn to satisfy eslint no-console rule.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When main has new commits but no conflicts, highlight "Rebase onto main"
as the primary button. Only promote "Rebase with AI" to primary when
conflicts are actually detected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Address review issues from PR johannesjo#31:
- Try ports 7777-7800 when starting MCP remote server instead of
  hardcoding 7777, preventing silent failure when port is in use
- Validate REST body fields (name, prompt, timeoutMs, squash, message,
  cleanup) in orchestrator API routes, returning 400 on bad input

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds explicit control handoff between the orchestrating agent and the
human user, modelled on a pilot/co-pilot system where control is always
unambiguously held by one party.

Each sub-task created by a coordinator has a new runtime field
`controlledBy: 'orchestrator' | 'human'`. The task panel shows a
persistent banner so the user always knows who has the stick:

- Orchestrator driving: subtle bar + "Take Control" button
- Human in control: amber warning banner "You have control —
  orchestrator is paused" + "Return to Orchestrator" button

When the human holds control, the orchestrator's MCP tools are blocked:
- `send_prompt` throws immediately so the coordinator agent knows it
  cannot proceed and must wait or work on other tasks
- `wait_for_idle` resolves immediately so the coordinator is not left
  hanging; the status signals human control

Control returns to the orchestrator only via explicit user action —
never automatically. Returning control also fires any queued
`waitForIdle` resolvers so the coordinator can resume.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@brooksc brooksc force-pushed the feature/orchestrator-control-v2 branch from 2e523b0 to b436f19 Compare May 4, 2026 03:27
@brooksc
Copy link
Copy Markdown
Contributor Author

brooksc commented May 5, 2026

@cledoux95 as you initiated this I'd love to get your thoughts on my building further on your work.
@johannesjo this PR as is, is useful but I don't think it's ready yet.

Here's what I'm trying to solve for.

  • I have a medium size project where I'm using (surprise!) parallel claude code to build it
  • I'm using backlog.md to build up a healthy list of items that I curate.
  • Prior to this I'd switch to the browser to view backlog.md's kanban, copy a TASK-###, switch to parallel code, open a new task and paste it in. And repeat until I had 3-5 tasks running.

What I'm hoping to get to:

  1. I have the coordinator agent reviewing what's on the backlog and determining what's next.
  2. It fires off up to X (e.g. 5) paralell claude codes
  3. I can see them and interact with them, take control from the claude code, interact with it and return control
  4. The coordinator monitors for when an agent is done. Flags to me when there are questions I need to address. Review's it's final results and then tells it to commit and rebase.

1-3 is working here (although the take control/return control may need some work)
4 -- the agent has to be prompted to "go check on the agents" and it then does the commit/rebase nicely and closes the window.

I'm thinking I need some webhook or way for agentN to notify the coordinator when it's done (hook...?)

Anyway... this may take some time to polish. @johannesjo What do you think about adding a "Beta" section in settings, when you're ready to integrate it - it can live in Beta for a little while so others can opt-in and shake it out if they want. I think it'll take some time to live with this to continue to refine it. I'm using it myself going forward.

brooksc and others added 12 commits May 5, 2026 20:25
Add OrchestratedTask lifecycle flags, PendingNotification, CoordinatorState
to electron/mcp/types.ts and StagedNotification + Task.stagedNotification
to src/store/types.ts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add coordinator registry (registerCoordinator/deregisterCoordinator),
maybeQueueReviewNotification hooked into PTY exit and idle transitions,
stageBatch/formatNotificationText helpers, and ackNotification/markPromptDelivered
public methods to the Orchestrator class.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
8 tests covering startup-idle guard, first-idle notification, duplicate
dedup, idle→exited upgrade, ack semantics, idempotent ack, shortened delay
for non-zero exit, and orphaned sub-task notification.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wire MCP_CoordinatorRegistered, MCP_CoordinatorDeregistered,
MCP_CoordinatedTaskPromptDelivered, and MCP_CoordinatorNotificationAck
handlers to orchestrator methods in register.ts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tification listeners

- Register coordinator after StartMCPServer succeeds in createTask
- Deregister coordinator in closeTask's coordinatorMode block
- Listen for MCP_CoordinatorNotificationStaged and update Task.stagedNotification
- Export clearStagedNotification and setStagedNotificationUserEdited helpers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ists

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…vered signal

- Add coordinatedBy and stagedNotification props
- Auto-populate textarea with staged text; start 1s interval to auto-fire
  when autoFireAt elapses and coordinator PTY shows prompt marker
- Send MCP_CoordinatedTaskPromptDelivered after initial prompt auto-send
  for coordinated sub-tasks
- Track userEdited when user types content different from staged text
- Ack and clear staged notification on manual exact-match send
- Show hidden completion count badge when userEdited

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…l to PromptInput

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
mcpConfigPath was stored on the task but never injected into the agent's
args, so the coordinator's Claude started without --mcp-config. Tools were
only discoverable via .mcp.json auto-discovery, which requires explicit
approval in Claude Code unless skip-permissions is enabled.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…spawns agent

TerminalView kills the existing PTY (clearing all subscribers) when it mounts
for an orchestrated sub-task, then spawns a new one with the same agentId.
This lost the orchestrator's outputCb permanently, so it could never detect
when the sub-task became idle and therefore never staged a coordinator
notification.

Fix by listening for the 'spawn' PTY event and re-subscribing when a managed
agentId is respawned. Also clear the stale tail buffer and reset task.status
from 'exited' → 'running' so idle detection works correctly in the new session.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add signal_done MCP tool + --task-id CLI arg to MCP server/client
- Add POST /api/tasks/:taskId/done HTTP endpoint
- Orchestrator: signalDone(), setMCPServerInfo(), per-task MCP config,
  SUB_TASK_PREAMBLE prepended to sub-task prompts, 5s delay override
- register.ts: call setMCPServerInfo after remote server starts
- Store: persist mcpConfigPath on sub-tasks for --mcp-config passthrough
- Tests: two new signalDone unit tests (10 tests total, all pass)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@johannesjo
Copy link
Copy Markdown
Owner

johannesjo commented May 6, 2026

Thank you very much @brooksc (and @cledoux95 !) !! This is impressive work, and the integration fixes on top of #31 are exactly the kind of stuff that's painful to discover from the outside. I want to ship this, but I agree with you that it's not ready as a default-on feature, and I think your "Beta in Settings" instinct is the right framing. Let me make that concrete.

Yes to beta-gating, with a real flag. Specifically:

  • A single experimental.coordinatorMode setting, off by default.
  • When off, the MCP server module is not started (lazy import() on flag flip), the Coordinator option in NewTaskDialog is hidden, and the mcp_control_changed IPC channel isn't exposed to the renderer. Goal: zero footprint for users who don't opt in.
  • Coordinator-specific code lives in its own folders (electron/mcp/, src/components/coordinator/, a dedicated store slice), and the cross-cutting touches (TaskPanel, Sidebar) take a coordinator-aware prop rather than inlining the logic. This keeps future unrelated PRs from having to reason about coordinator state.

Three things I'd want addressed before I merge, even into beta:

  1. Post-restart MCP path – please add an integration test that confirms the port/token rotation actually rewrites the config the agent reads on next launch. That's the most fragile part by design and the unit tests don't cover it.
  2. skipPermissions guardrail--dangerously-skip-permissions is a real footgun. I'd like it to require both the beta flag and an explicit per-task confirmation in the UI, not just an MCP tool argument the coordinator can pass.
  3. Feature flag wraps startup + IPC registration, not just UI affordances – so toggling it off genuinely removes the surface area.

On your unsolved step #4 (coordinator noticing "agent done"): I think Claude Code's Stop / SubagentStop hooks are the right primitive here – a hook posting back to the local MCP server would replace the polling/manual-nudge loop with a real notify channel. Worth exploring before we promote out of beta; not a blocker for landing the beta itself.

Graduation criteria I'd want to hit before flipping the flag on by default:

  • Restart-with-running-coordinator works reliably across macOS and Linux.
  • No leaked PTY/zombie processes over a 24h session.
  • The "agent finished" notification is solved (hooks or equivalent).
  • A few weeks in beta with no P0 bugs from opt-in users.

If you're up for the gating work I'm happy to keep this open and help where useful. And to be clear: I do want to ship this – the pilot/co-pilot pattern is the right shape for human-in-the-loop orchestration, and you've already shaved off a lot of the rakes.

brooksc and others added 4 commits May 6, 2026 09:13
… log viewer

- Add wait_for_signal_done MCP tool — coordinator blocks until sub-task
  explicitly signals done (more reliable than PTY-idle detection)
- Track signalDoneAt on OrchestratedTask; expose in list_tasks/get_task_status
- Sub-task chips in coordinator panel turn green with checkmark when
  signal_done received
- MCP logs button always visible in coordinator sub-task strip; opens modal
  with timestamped log entries and refresh button
- Auto-delete per-task tmp MCP config file on sub-task close
- MCP_TaskStateSync listener in renderer store updates signalDoneReceived flag

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ndoff improvements

- Rename Orchestrator class and all files/identifiers to Coordinator
- Fix spawn settings (agentCommand/agentArgs/skipPermissions) threading through
  MCP_TaskCreated so sub-agents inherit --dangerously-skip-permissions correctly
- Fix per-task projectRoot snapshot to prevent singleton mutation across coordinators
- Fix waiter resolver leak on timeout (indexOf wrappedResolve not resolve)
- Gate MCP logs button on Verbose Logging setting
- Notify coordinator when control returns after a blocked send_prompt
- Notify coordinator when sub-task exits before prompt delivery (user closed early)
- Expand unit tests to 379 covering all new paths
- Add KNOWN-TODOS.md for unimplemented items
- Remove design docs and test plan (superseded)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Keep coordinator mode toggle in correct position after AgentSelector
- Take upstream steps-tracking checkbox attributes (stepsEnabled)
- Fix task possibly-undefined TypeScript error in setTaskControl

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@brooksc
Copy link
Copy Markdown
Contributor Author

brooksc commented May 7, 2026

@johannesjo — thanks for the detailed review, this is exactly the kind of feedback that makes it worth sharing early. Lots to respond to.


Where things stand: working e2e

Since the original PR I've built considerably more on top. Here's what's confirmed working end-to-end:

Coordinator creation & MCP tooling

  • "Coordinator mode" checkbox in New Task dialog; only one active coordinator per project enforced
  • MCP server starts automatically; coordinator agent sees: create_task, list_tasks, get_task_status, send_prompt, wait_for_idle, wait_for_signal_done, get_task_diff, get_task_output, merge_task, close_task
  • Sub-tasks get only signal_done (not create_task etc.) so there's no runaway recursion

Sub-task lifecycle

  • create_task spawns a worktree + agent, injects a [SUB-TASK MODE] preamble so the agent knows its role and constraints
  • Sub-task inherits the coordinator's agent command, args, and --dangerously-skip-permissions state
  • merge_task and close_task work cleanly, including worktree cleanup

Coordinator ↔ sub-agent notification — and why we didn't use Stop hooks

This is where we diverge from your suggestion, and I think for good reason. You suggested Stop/SubagentStop hooks posting back to the MCP server. The problem: Claude Code fires Stop any time the agent pauses — including when it hits a question mid-task or runs out of context. What we actually want is "agent has finished its assigned work and is ready for review."

Instead, sub-agents call the signal_done MCP tool explicitly when they're done. The coordinator receives a staged notification into its PromptInput textarea with a summary of which tasks completed, which branch to review, and whether there was a non-zero exit. The notification auto-fires after a quiet period (default 60s, faster on error) if the coordinator is idle — so the coordinator agent processes it automatically without manual nudging. This is the step 4 from the original description working.

Additional notification paths:

  • If the coordinator calls send_prompt while the user has taken control of a sub-task, it gets an error immediately (not a silent hang). When the user returns control, the coordinator gets a "Task X is back under your control" notification so it can retry without human prompting.
  • If the user closes a sub-task before its prompt even lands, the coordinator still gets notified — previously it would silently think 2 tasks were running when only 1 was.

Pilot / co-pilot control handoff — how it works and two open items

Each sub-task panel shows a banner indicating who's driving. When the coordinator has control the banner reads "Coordinator driving" in grey. Clicking "Take Control" blocks the coordinator's send_prompt from reaching that sub-task — the banner turns amber. Clicking "Return to Coordinator" restores it and automatically notifies the coordinator if it was blocked mid-action.

Two things to note as known gaps: first, the button labels ("Take Control" / "Return to Orchestrator") overstate what's happening — the coordinator agent keeps running, only its ability to write to that terminal is paused. "Pause coordinator" / "Resume coordinator" would be more accurate. Second, the sub-task's PromptInput and raw xterm terminal are not currently gated on control state, so a user could type simultaneously with a coordinator send_prompt. The fix is to disable input when the coordinator has control and surface "Pause coordinator" as the way to unlock it — making the model self-documenting rather than relying on reading the banner.

Unit test coverage
379 tests covering: notification staging, ack/dedup, batch formatting, idle detection, signal_done, waiter resolver leak-on-timeout, per-task projectRoot isolation, spawn settings inheritance, control handoff notification, early-close notification.


What isn't done yet

Beta gating — you're right that zero-footprint opt-in is the right approach. We haven't done the experimental.coordinatorMode flag, lazy MCP server import, or IPC registration gating. That's the right next piece and I'm happy to do it.

Settings dialog placement — with coordinator mode, Docker, verbose logging, and more to come, Settings is getting long. A tabbed settings dialog (General / Experimental) would be a natural home for the beta flag, but that's its own PR and should land independently of this one.

Docker + coordinator — currently mutually exclusive. Sub-tasks spawned by a coordinator run as native host processes, defeating Docker isolation. Two approaches documented in KNOWN-TODOS.md: same container via docker exec, or per-sub-task containers. Prerequisite decision: should coordinator mode force direct git isolation (no worktree)? Architecturally that's cleaner since coordinators don't commit code themselves.

Post-restart MCP path integration test — fair ask. The port/token rotation path is the right thing to test. Will add.

skipPermissions guardrail — also fair. Currently if the coordinator is started with skip-permissions, all sub-tasks inherit it. An explicit per-task confirmation in the UI is the right guardrail. One nuance: for the "40 tasks, spawn 2 at a time" workflow, the user probably wants to grant it once rather than 40 times — so I'd suggest a "propagate skip-permissions to sub-tasks" checkbox that requires explicit opt-in, separate from the per-task flow.

Minor items (in KNOWN-TODOS.md): orphaned sub-task badge UI, re-stage notification after user manually sends an edited prompt, configurable notification delay, control handoff input gating and button renaming.


Happy to tackle the beta gating as the next chunk. Does the experimental.coordinatorMode approach you outlined work as the gating mechanism, or do you have a different shape in mind for the flag?

brooksc and others added 2 commits May 6, 2026 22:00
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@brooksc brooksc marked this pull request as draft May 7, 2026 05:06
@brooksc brooksc force-pushed the feature/orchestrator-control-v2 branch from 4057d03 to 0be08ca Compare May 7, 2026 05:11
@johannesjo
Copy link
Copy Markdown
Owner

Thanks @brooksc — the depth of the response (and the 379 tests!) tells me where this is heading, and I'm on board with the shape. A few replies and a few new things I noticed reading the diff today.

signal_done over Stop/SubagentStop — agreed, you're right. Your reasoning on Stop firing for mid-task pauses is correct, and the auto-fire-on-quiet staging is a nicer fit than I'd given it credit for. Withdrawing that suggestion.

Beta gating shape: experimental.coordinatorMode works for me. Single boolean, persisted in app state, off by default. Worth doing as its own follow-up PR after the rest lands, or first-in-line — your call. I'd defer the tabbed Settings dialog as you suggested.

skipPermissions guardrail — the propagation checkbox is the right shape. Good refinement: a "propagate skip-permissions to sub-tasks" checkbox in the New Task dialog, defaulting off even when the coordinator itself was launched with skip-permissions. Don't auto-inherit silently. The 40-tasks-at-a-time workflow is real and worth optimizing for.

A few things I caught on a code pass that haven't come up yet:

  1. The post-restart fix described in the PR body isn't actually in the diff. The description says "App.tsx awaits StartMCPServer for each persisted coordinator task." `git grep StartMCPServer` finds it only in `src/store/tasks.ts` (the create-task path). `mcpConfigPath` is also absent from both `saveState` and `loadState` in `src/store/persistence.ts`, so on next launch `TaskAITerminal` skips `--mcp-config` entirely (it's gated on `props.task.mcpConfigPath` at `TaskAITerminal.tsx:223`) and the worktree's `.mcp.json` carries the previous run's token. Could you verify that test-plan item ("Kill and relaunch the app … MCP tools still work") is actually green today? My read is it would `fetch failed` on the first MCP call.

  2. `CLAUDE.md` mutation in the worktree is risky when combined with skip-permissions. `coordinator.ts` writes a `<!-- parallel-code-subtask-start -->` block into the worktree's `CLAUDE.md` and restores it via `setTimeout(..., 3000)` after first idle (`coordinator.ts:317,328`). A skip-permissions sub-agent that decides to `git add -A && git commit` early on will commit our injection. The `git restore` fallback runs with `stdio: 'ignore'` (line 322), so a failure is invisible. Could we use `--append-system-prompt` (if Claude Code supports it) or write to `.claude/settings.local.json` (already gitignored) instead of mutating a tracked file?

  3. `server.listen('0.0.0.0', ...)` + new mutating REST endpoints. Pre-existing for the mobile-remote feature, where token-bearer auth was guarding a read-mostly surface. With this PR, the same token now also gates `POST /api/tasks` (spawn worktree+process), `POST /api/tasks/:id/merge`, `DELETE /api/tasks/:id`, `POST /api/tasks/:id/prompt`. I think we should either (a) bind to 127.0.0.1 by default and only widen when the user explicitly enables remote mobile, or (b) scope the token so coordinator endpoints require an additional capability the mobile-remote token doesn't get. Option (a) is the smaller change.

  4. `waitForIdle` resolves silently on human takeover. `coordinator.ts:495` returns `Promise.resolve()` immediately when `controlMap.get(taskId) === 'human'`. The coordinator can't tell apart "agent went idle" from "human paused agent" — it just sees `{status: "running"}` afterwards and likely loops. Worth changing the resolved value to `{ reason: 'idle' | 'human_control' | 'exited' }` so the agent can branch on it.

  5. Token file permissions. `.mcp.json` (worktree, `register.ts:1075`), `parallel-code-mcp-*.json` (tmp, `register.ts:1067`), and the per-sub-task config (`coordinator.ts:374`) are all written with default umask = `0644`. On a shared machine, other local users can read the token. `{ mode: 0o600 }` everywhere we write a token-bearing config.

  6. Small things: `controlMap` accepts unknown taskIds (no `tasks.has` check in `setTaskControl`); `coordinatorTaskId: 'api'` is a magic-string sentinel that should be `undefined`; `get_task_diff` truncates at 50 KB without reporting the original size; the `gitIsolation` option mentioned in the PR description isn't in the `create_task` JSON schema in `server.ts`.

Item #1 is the only one that affects whether the test plan currently passes; the rest can ride along with the beta-gating PR. Excited about this — the pilot/co-pilot framing has aged well over the discussion.

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.

2 participants