Skip to content

watch --execute on Windows: cmd.exe truncates the agent prompt at its first newline, so no issue is ever worked #2070

Closed

Description

@peaceatwar-stack

Summary

On Windows, squad triage --execute (watch/Ralph execute mode) dispatches a Copilot session that gets only the first line of the prompt. cmd.exe ends the command at the first newline, so the agent sees:

You are an AI agent on a software development team.

It answers that no task was given, exits 0 after about 8 seconds, and the round reports success. No issue ever gets worked, and each round still costs a Copilot request.

Environment

  • Squad CLI 0.13.0, WinGet package bradygaster.Squad (squad-win32-x64). The 0.13.1 release notes don't mention a fix.
  • Windows 11 Pro 10.0.26200
  • GitHub Copilot CLI 1.0.88 (npm global, copilot.cmd shim)
  • Default execute settings: agentCmd default (copilot), --yolo

Repro

  1. Open one issue labelled squad with no assignee.
  2. Run squad triage --execute --verbose on Windows.
  3. Verbose shows Execute: 1 total issues, 1 eligible / → #N …, then the round completes in about 10 to 15 s.
  4. Open that Copilot session's ~/.copilot/session-state/<id>/events.jsonl. The first user.message is only "You are an AI agent on a software development team.", and the assistant replies that no task was included.

It happened on every execute round we ran; all three sessions show the same truncated prompt.

Root cause

dist/cli/commands/watch/agent-spawn.js: spawnAgent() / spawnWithTimeout() use execFile(cmd, escapeArgs(args), { shell: IS_WINDOWS }). escapeForCmd() double-quotes arguments, but inside cmd.exe /d /s /c "…" a newline still ends the command, even inside quotes. The prompt from buildAgentPrompt() (charter prefix plus the issue list) is multi-line, so everything after the first line is lost.

There's a second limit waiting behind it: cmd.exe's 8,191-character command-line maximum. Collapsing the newlines to spaces would hit that once the charter and issue list grow.

Suggested fix

Keep the prompt off the cmd.exe command line on Windows. For example, write multi-line prompts to a temp file and pass a one-line -p that points at it, or avoid shell: true by resolving the copilot shim to its node entry point (e.g. cross-spawn). A local patch we're running now, in escapeArgs() on win32:

return args.map(spillMultiline).map(escapeForCmd);

function spillMultiline(arg) {
  if (typeof arg !== 'string' || !/[\r\n]/.test(arg)) return arg;
  const dir = join(tmpdir(), 'squad-prompts');
  mkdirSync(dir, { recursive: true });
  const file = join(dir, `prompt-${Date.now()}-${process.pid}-${Math.random().toString(36).slice(2, 8)}.md`);
  writeFileSync(file, arg, 'utf8');
  return `Your complete instructions are in the file ${file} - read that whole file first and follow it exactly as if it were this prompt.`;
}

Related: the round summary hides dispatches

watch/index.js reads execResult.data['executed'] for the 🚀 Executed: line, but ExecuteCapability.execute() returns data: { dispatched, success }. The summary therefore never shows that an agent was dispatched, only 🟡 Assigned: N, which made this failure look like "nothing eligible" until run with --verbose.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions