diff --git a/.changeset/fix-copilot-message-flag.md b/.changeset/fix-copilot-message-flag.md new file mode 100644 index 000000000..3d2cff7b3 --- /dev/null +++ b/.changeset/fix-copilot-message-flag.md @@ -0,0 +1,11 @@ +--- +'@bradygaster/squad-cli': patch +'@bradygaster/squad-sdk': patch +--- + +Fix obsolete --message flag in watch and loop commands + +Replace `--message` with `-p` across all watch capabilities and loop command. +Use `copilot` directly on Windows to avoid .cmd console window issues, +fall back to `gh copilot` on other platforms. Fix TOKEN_PATH typo in +comms-teams.ts (pre-existing bug from #906). diff --git a/packages/squad-cli/src/cli/commands/loop.ts b/packages/squad-cli/src/cli/commands/loop.ts index 23fd71d8f..46c36d433 100644 --- a/packages/squad-cli/src/cli/commands/loop.ts +++ b/packages/squad-cli/src/cli/commands/loop.ts @@ -136,13 +136,13 @@ function buildLoopAgentCommand( ): { cmd: string; args: string[] } { if (options.agentCmd) { const parts = options.agentCmd.trim().split(/\s+/); - return { cmd: parts[0]!, args: [...parts.slice(1), '--message', prompt] }; + return { cmd: parts[0]!, args: [...parts.slice(1), '-p', prompt] }; } - const args = ['copilot', '--message', prompt]; + const args = ['-p', prompt]; if (options.copilotFlags) { args.push(...options.copilotFlags.trim().split(/\s+/)); } - return { cmd: 'gh', args }; + return { cmd: 'copilot', args }; } // ── Capability Phase Runner ────────────────────────────────────── @@ -244,10 +244,10 @@ function createNoopAdapter(): ReturnType { // ── gh Copilot Preflight ───────────────────────────────────────── -/** Verify `gh` CLI with copilot extension is available. */ -async function checkGhCopilot(): Promise { +/** Verify the copilot CLI is available. */ +async function checkCopilotCli(): Promise { return new Promise((resolve, reject) => { - execFile('gh', ['copilot', '--version'], (err) => { + execFile('copilot', ['--version'], (err) => { if (err) reject(err); else resolve(); }); @@ -313,12 +313,12 @@ export async function runLoop(dest: string, options: LoopConfig): Promise fatal('timeout must be a positive number of minutes'); } - // Preflight: verify gh copilot is available (skip if user overrides the agent command) + // Preflight: verify copilot CLI is available (skip if user overrides the agent command) if (!options.agentCmd) { try { - await checkGhCopilot(); + await checkCopilotCli(); } catch { - fatal('gh CLI with copilot extension required. Install from https://cli.github.com/ and run `gh extension install github/gh-copilot`'); + fatal('Copilot CLI required. Install from https://cli.github.com/ and run `gh extension install github/gh-copilot`'); } } diff --git a/packages/squad-cli/src/cli/commands/watch/capabilities/decision-hygiene.ts b/packages/squad-cli/src/cli/commands/watch/capabilities/decision-hygiene.ts index 450ab2584..f47aefbd8 100644 --- a/packages/squad-cli/src/cli/commands/watch/capabilities/decision-hygiene.ts +++ b/packages/squad-cli/src/cli/commands/watch/capabilities/decision-hygiene.ts @@ -12,11 +12,11 @@ const storage = new FSStorageProvider(); function buildAgentCommand(prompt: string, context: WatchContext): { cmd: string; args: string[] } { if (context.agentCmd) { const parts = context.agentCmd.trim().split(/\s+/); - return { cmd: parts[0]!, args: [...parts.slice(1), '--message', prompt] }; + return { cmd: parts[0]!, args: [...parts.slice(1), '-p', prompt] }; } - const args = ['copilot', '--message', prompt]; + const args = ['-p', prompt]; if (context.copilotFlags) args.push(...context.copilotFlags.trim().split(/\s+/)); - return { cmd: 'gh', args }; + return { cmd: 'copilot', args }; } function spawnWithTimeout(cmd: string, args: string[], cwd: string, timeoutMs: number): Promise { diff --git a/packages/squad-cli/src/cli/commands/watch/capabilities/execute.ts b/packages/squad-cli/src/cli/commands/watch/capabilities/execute.ts index 0c4171a0b..e583926c8 100644 --- a/packages/squad-cli/src/cli/commands/watch/capabilities/execute.ts +++ b/packages/squad-cli/src/cli/commands/watch/capabilities/execute.ts @@ -53,14 +53,14 @@ function buildAgentCommand( if (context.agentCmd) { const parts = context.agentCmd.trim().split(/\s+/); const cmd = parts[0]!; - const args = [...parts.slice(1), '--message', prompt]; + const args = [...parts.slice(1), '-p', prompt]; return { cmd, args }; } - const args = ['copilot', '--message', prompt]; + const args = ['-p', prompt]; if (context.copilotFlags) { args.push(...context.copilotFlags.trim().split(/\s+/)); } - return { cmd: 'gh', args }; + return { cmd: 'copilot', args }; } /** Labels that indicate an issue should not be auto-executed. */ @@ -202,7 +202,7 @@ export class ExecuteCapability implements WatchCapability { try { const timeout = ((context.config['timeout'] as number) ?? 30) * 60_000; - vlog.log(`Execute: agentCmd=${context.agentCmd ?? 'gh copilot'}, timeout=${timeout / 60_000}m`); + vlog.log(`Execute: agentCmd=${context.agentCmd ?? 'copilot'}, timeout=${timeout / 60_000}m`); // Fetch open issues with squad label const sdkItems = await context.adapter.listWorkItems({ tags: ['squad'], state: 'open', limit: 50 }); diff --git a/packages/squad-cli/src/cli/commands/watch/capabilities/monitor-email.ts b/packages/squad-cli/src/cli/commands/watch/capabilities/monitor-email.ts index c35453fcf..14f5d9c73 100644 --- a/packages/squad-cli/src/cli/commands/watch/capabilities/monitor-email.ts +++ b/packages/squad-cli/src/cli/commands/watch/capabilities/monitor-email.ts @@ -8,11 +8,11 @@ import type { WatchCapability, WatchContext, PreflightResult, CapabilityResult } function buildAgentCommand(prompt: string, context: WatchContext): { cmd: string; args: string[] } { if (context.agentCmd) { const parts = context.agentCmd.trim().split(/\s+/); - return { cmd: parts[0]!, args: [...parts.slice(1), '--message', prompt] }; + return { cmd: parts[0]!, args: [...parts.slice(1), '-p', prompt] }; } - const args = ['copilot', '--message', prompt]; + const args = ['-p', prompt]; if (context.copilotFlags) args.push(...context.copilotFlags.trim().split(/\s+/)); - return { cmd: 'gh', args }; + return { cmd: 'copilot', args }; } function spawnWithTimeout(cmd: string, args: string[], cwd: string, timeoutMs: number): Promise { diff --git a/packages/squad-cli/src/cli/commands/watch/capabilities/monitor-teams.ts b/packages/squad-cli/src/cli/commands/watch/capabilities/monitor-teams.ts index d084b4717..e5162557a 100644 --- a/packages/squad-cli/src/cli/commands/watch/capabilities/monitor-teams.ts +++ b/packages/squad-cli/src/cli/commands/watch/capabilities/monitor-teams.ts @@ -9,11 +9,11 @@ import type { WatchCapability, WatchContext, PreflightResult, CapabilityResult } function buildAgentCommand(prompt: string, context: WatchContext): { cmd: string; args: string[] } { if (context.agentCmd) { const parts = context.agentCmd.trim().split(/\s+/); - return { cmd: parts[0]!, args: [...parts.slice(1), '--message', prompt] }; + return { cmd: parts[0]!, args: [...parts.slice(1), '-p', prompt] }; } - const args = ['copilot', '--message', prompt]; + const args = ['-p', prompt]; if (context.copilotFlags) args.push(...context.copilotFlags.trim().split(/\s+/)); - return { cmd: 'gh', args }; + return { cmd: 'copilot', args }; } function spawnWithTimeout(cmd: string, args: string[], cwd: string, timeoutMs: number): Promise { diff --git a/packages/squad-cli/src/cli/commands/watch/capabilities/retro.ts b/packages/squad-cli/src/cli/commands/watch/capabilities/retro.ts index 4fab3395c..85be72b41 100644 --- a/packages/squad-cli/src/cli/commands/watch/capabilities/retro.ts +++ b/packages/squad-cli/src/cli/commands/watch/capabilities/retro.ts @@ -12,11 +12,11 @@ const storage = new FSStorageProvider(); function buildAgentCommand(prompt: string, context: WatchContext): { cmd: string; args: string[] } { if (context.agentCmd) { const parts = context.agentCmd.trim().split(/\s+/); - return { cmd: parts[0]!, args: [...parts.slice(1), '--message', prompt] }; + return { cmd: parts[0]!, args: [...parts.slice(1), '-p', prompt] }; } - const args = ['copilot', '--message', prompt]; + const args = ['-p', prompt]; if (context.copilotFlags) args.push(...context.copilotFlags.trim().split(/\s+/)); - return { cmd: 'gh', args }; + return { cmd: 'copilot', args }; } function spawnWithTimeout(cmd: string, args: string[], cwd: string, timeoutMs: number): Promise { diff --git a/packages/squad-cli/src/cli/commands/watch/capabilities/wave-dispatch.ts b/packages/squad-cli/src/cli/commands/watch/capabilities/wave-dispatch.ts index e10f30dfb..0169ef998 100644 --- a/packages/squad-cli/src/cli/commands/watch/capabilities/wave-dispatch.ts +++ b/packages/squad-cli/src/cli/commands/watch/capabilities/wave-dispatch.ts @@ -37,11 +37,11 @@ function parseSubTasks(body: string | undefined): SubTask[] { function buildAgentCommand(prompt: string, context: WatchContext): { cmd: string; args: string[] } { if (context.agentCmd) { const parts = context.agentCmd.trim().split(/\s+/); - return { cmd: parts[0]!, args: [...parts.slice(1), '--message', prompt] }; + return { cmd: parts[0]!, args: [...parts.slice(1), '-p', prompt] }; } - const args = ['copilot', '--message', prompt]; + const args = ['-p', prompt]; if (context.copilotFlags) args.push(...context.copilotFlags.trim().split(/\s+/)); - return { cmd: 'gh', args }; + return { cmd: 'copilot', args }; } function executeSubTask( diff --git a/packages/squad-cli/src/cli/commands/watch/index.ts b/packages/squad-cli/src/cli/commands/watch/index.ts index 764fdf993..9afea3def 100644 --- a/packages/squad-cli/src/cli/commands/watch/index.ts +++ b/packages/squad-cli/src/cli/commands/watch/index.ts @@ -609,11 +609,11 @@ export function buildAgentCommand( const prompt = `Work on issue #${issue.number}: ${issue.title}. Read the issue body for full details.`; if (options.agentCmd) { const parts = options.agentCmd.trim().split(/\s+/); - return { cmd: parts[0]!, args: [...parts.slice(1), '--message', prompt] }; + return { cmd: parts[0]!, args: [...parts.slice(1), '-p', prompt] }; } - const args = ['copilot', '--message', prompt]; + const args = ['-p', prompt]; if (options.copilotFlags) args.push(...options.copilotFlags.trim().split(/\s+/)); - return { cmd: 'gh', args }; + return { cmd: 'copilot', args }; } export async function selfPull(teamRoot: string): Promise { diff --git a/packages/squad-sdk/src/platform/comms-teams.ts b/packages/squad-sdk/src/platform/comms-teams.ts index 0c4497c0b..eb4c1a557 100644 --- a/packages/squad-sdk/src/platform/comms-teams.ts +++ b/packages/squad-sdk/src/platform/comms-teams.ts @@ -103,7 +103,7 @@ function saveTokens(tenantId: string, clientId: string, tokens: StoredTokens): v // Ensure permissions are correct even if file already existed if (platform() === 'win32') { - execFile('icacls', [TOKEN_PATH, '/inheritance:r', '/grant:r', `${process.env.USERNAME ?? 'CURRENT_USER'}:(R,W)`], (err) => { + execFile('icacls', [tokenPath, '/inheritance:r', '/grant:r', `${process.env.USERNAME ?? 'CURRENT_USER'}:(R,W)`], (err) => { if (err) console.warn('⚠️ Could not restrict token file permissions:', err.message); }); } else { diff --git a/test/cli/watch-capabilities.test.ts b/test/cli/watch-capabilities.test.ts index d38c12e0b..361e4927d 100644 --- a/test/cli/watch-capabilities.test.ts +++ b/test/cli/watch-capabilities.test.ts @@ -356,7 +356,7 @@ describe('Watch Capabilities', () => { await cap.execute(ctx); expect(mockExecFile).toHaveBeenCalledWith( 'my-agent', - expect.arrayContaining(['--flag', '--message']), + expect.arrayContaining(['--flag', '-p']), expect.any(Object), expect.any(Function), ); diff --git a/test/cli/watch-execute.test.ts b/test/cli/watch-execute.test.ts index 7ba5e1ae3..2d9e7c0fc 100644 --- a/test/cli/watch-execute.test.ts +++ b/test/cli/watch-execute.test.ts @@ -26,9 +26,8 @@ describe('CLI: watch execute mode', () => { const { cmd, args } = buildAgentCommand(issue, teamRoot, options); - expect(cmd).toBe('gh'); - expect(args).toContain('copilot'); - expect(args).toContain('--message'); + expect(cmd).toBe('copilot'); + expect(args).toContain('-p'); expect(args.some((a) => a.includes('issue #42'))).toBe(true); }); @@ -45,7 +44,7 @@ describe('CLI: watch execute mode', () => { const { cmd, args } = buildAgentCommand(issue, teamRoot, options); - expect(cmd).toBe('gh'); + expect(cmd).toBe('copilot'); expect(args).toContain('--model'); expect(args).toContain('gpt-4'); expect(args).toContain('--yolo'); @@ -67,7 +66,7 @@ describe('CLI: watch execute mode', () => { expect(cmd).toBe('custom-agent'); expect(args).toContain('--flag'); expect(args).toContain('value'); - expect(args).toContain('--message'); + expect(args).toContain('-p'); }); });