8000 agent.spawn pairs an explicit --pane with the ACTIVE workspace instead of the pane's owner, leaving the agent unaddressable · Issue #242 · amirlehmam/wmux · GitHub
[go: up one dir, main page]

Skip to content

agent.spawn pairs an explicit --pane with the ACTIVE workspace instead of the pane's owner, leaving the agent unaddressable #242

Closed

Description

@mkh63d

Summary

wmux agent spawn --pane <id> without --workspace records the agent under whatever workspace is currently active, never checking that the pane actually belongs to it. The agent starts and runs, but its surface is then unreachable through read-screen / current-workspace --surface, so anything driving agents over the CLI loses the ability to see what they are doing.

Found while orchestrating a multi-agent run: panes were created in the right workspace, the agents were tagged with a different one, and three waves were restarted chasing what looked like a cwd fault.

Where

src/main/index.ts, the agent.spawn pipe handler (~:1726):

let workspaceId = params.workspaceId;
if (!workspaceId) {
  const wins = BrowserWindow.getAllWindows();
  if (wins.length > 0) {
    workspaceId = await wins[0].webContents.executeJavaScript('window.__wmux_getActiveWorkspaceId?.()');
  }
}
if (!workspaceId) { respondError(-32000, 'No active workspace'); return; }

let paneId = params.paneId;          // <-- taken verbatim
if (!paneId) { /* distributeAgents fallback */ }
...
agentManager.spawn({ cmd, label, cwd, env, paneId, workspaceId });

The two are resolved independently. When paneId is supplied explicitly, nothing derives its owning workspace and nothing rejects a contradiction, so agentManager.spawn gets a (paneId, workspaceId) pair that does not exist in the split tree.

agent.spawn_batch immediately below resolves workspaceId the same way, so it looks like it has the same gap.

Repro

wmux 2.12.0, Windows 11 26200. Active workspace is "Personal-1"; the pane is created in "Admin".

# 1. pane in a NON-active workspace — layout grid honours --workspace correctly
wmux layout grid --count 2 --type terminal --workspace <ws-ADMIN>
#    -> newPaneIds[0] = pane-c386d74f-…   (confirmed present in Admin's list-panes)

# 2. spawn into that pane, no --workspace
wmux agent spawn --cmd "echo repro" --label repro --pane pane-c386d74f-…

# 3. what wmux recorded
wmux agent list
#    REPORTED workspaceId: ws-1fb8c544-…  (Personal-1, the ACTIVE one)
#    paneId:               pane-c386d74f-… (the Admin pane)

Expected: the agent is recorded under the workspace that owns the pane, or the call is rejected as contradictory.

Actual: the record pairs the Admin pane with the Personal-1 workspace.

Consequence

The surface becomes unaddressable:

wmux read-screen --surface surf-4e85e81f-…
Error: no terminal for surface surf-4e85e81f-… (markdown/browser pane, another window, or closed)

The agent is running fine — agent list shows it with a live PID, and focus-surface accepts it. Only the lookups that go through the workspace record fail, and the error message points at three causes none of which is the real one. For a CLI-driven orchestrator this is the difference between watching agents and flying blind; it also makes the failure look like a dead or misconfigured agent rather than a bookkeeping mismatch.

Suggested fix

When params.paneId is supplied, derive workspaceId from the pane rather than from the active workspace — the renderer already owns the split tree, so this is the same kind of lookup browser.* does with engineForSurface. If both are supplied and disagree, -32602 is more useful than a silently mismatched record.

Worth noting --workspace already exists on agent spawn and passing it explicitly avoids the problem — but the failure is silent when it is omitted, and --pane alone reads as fully specified.

Not a bug (checked while narrowing this down)

  • --cwd is parsed and forwarded correctly (src/cli/wmux.ts:504 → agent-manager.ts:79). I initially suspected it and could not reproduce any failure.
  • wmux layout grid --workspace honours the flag; the pane lands where asked.

Activity

  1. amirlehmam commented on Sep 18, 2026

    @amirlehmam
    Owner

    Fixed in 2.13.0. Your diagnosis was exactly right, including the line you pointed at — thank you for narrowing it that far, and for ruling out --cwd on the way.

    The fix. The pane is now authoritative whenever it is given. Resolution moved into a single module (src/main/agent-spawn-target.ts) that decides the pane and the workspace together instead of independently:

    • --pane alone → the workspace is derived from the pane that owns it, never from the focused one. --pane reads as fully specified because it now is.
    • --pane + --workspace disagreeing → -32602, naming both sides, rather than a record pairing a pane with a workspace that does not contain it.
    • an unknown pane → -32602, rather than what it did before: spawn the agent, broadcast an AGENT_UPDATE addressing a pane that does not exist, and report success.

    One thing that fell out of it: with a pane named, the active workspace is never consulted at all — so a fully specified spawn now works when there is no active workspace. It used to fail -32000 for a reason unrelated to the request.

    You were right about spawn_batch, and it was the mirror of what you found. __wmux_getPaneLoads always read the active workspace, so --workspace <other> was honoured for the record it wrote and ignored for the panes it picked: every agent landed in the active workspace's panes while being filed under the other one. Same mistake, opposite direction, so both now resolve through the one module. Related: wmux agent spawn-batch never parsed --workspace at all, so there was no way to tell main about one even after it learned to honour it — that flag exists now.

    Why it's shaped the way it is. The decision is pure with the renderer lookups injected, because the split tree lives in the Zustand store and main has no copy of it — every question is a round trip, and the part worth testing is the rule, not the asking. The impure half asks every window and takes the first real answer: a workspace is not a window (#143), and a miss here is not a benign fallback, it is telling a caller their live pane does not exist. 20 tests cover it, including your exact two-workspace repro.

    The error message you quoted stays as it is for the genuine cases, but the path that made it lie is gone.

  2. amirlehmam commented on Sep 18, 2026

    @amirlehmam
    Owner

    Shipped in v2.13.0 — zip and setup.exe both up. Thanks again for the precise write-up; the spawn_batch hunch was right and turned out to be the mirror case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      0