Skip to content

fix(windows): Fix az CLI execution and ADO state mapping on Windows#1055

Open
michaeldevenney wants to merge 2 commits into
bradygaster:devfrom
michaeldevenney:mikedevenney/windows-ado-fixes
Open

fix(windows): Fix az CLI execution and ADO state mapping on Windows#1055
michaeldevenney wants to merge 2 commits into
bradygaster:devfrom
michaeldevenney:mikedevenney/windows-ado-fixes

Conversation

@michaeldevenney
Copy link
Copy Markdown

@michaeldevenney michaeldevenney commented Apr 29, 2026

What

Two packages, four bug fixes — all related to running squad watch on Windows with an Azure DevOps project.

Why

squad-cli / watch command:

On Windows, az is not a binary — it's a .cmd batch script. Node.js execFile without { shell: true } fails with ENOENT before any ADO operation can run. The watch command fails on startup with "az CLI not found" on every Windows machine.

squad-sdk / AzureDevOpsAdapter:

Three additional bugs were uncovered after fixing the launch issue:

  1. WIQL arg splitting: AZ_OPTS correctly sets shell: IS_WINDOWS, but cmd.exe re-parses the command line and splits args at spaces. WIQL queries contain spaces and get corrupted. Fix: quote any arg containing whitespace on Windows.

  2. Empty stdout crash: az boards query returns empty string (not []) when no work items match. JSON.parse('') throws SyntaxError: Unexpected end of JSON input. Fix: output || '[]' before parse.

  3. GitHub-style states in ADO: The state option passes 'open' directly into WIQL as [System.State] = 'open'. ADO has no open state — work items use Active, New, Resolved, etc. Every squad watch run with state: 'open' returns zero results silently. Fix: map 'open'NOT IN ('Closed','Resolved','Removed','Done') and 'closed'IN ('Closed','Resolved','Done').

How

packages/squad-cli/src/cli/commands/watch/index.ts

  • Added azCmd and azExecOpts constants (Windows shell guard)
  • Updated all three execFile/execFileSync call sites to use these constants

packages/squad-sdk/src/platform/azure-devops.ts

  • az() method: quote args containing whitespace on Windows before passing to execFileSync
  • listWorkItems(): added output || '[]' guard before JSON.parse
  • listWorkItems(): added state mapping for GitHub-style 'open'/'closed' → ADO WIQL

Testing

On Windows with platform: 'azure-devops' configured in .squad/config.json:

  1. squad watch — should start without "az CLI not found" error
  2. Work items should appear when state: 'open' is used (previously returned zero)
  3. Projects/orgs with spaces in their names should query correctly

Breaking Changes

None. All fixes are additive. macOS/Linux behavior is unchanged.


Relationship to #581

We're aware that #581 (ADO-Driven Squadding PRD) proposes a deeper architectural change — refactoring watch.ts to route through PlatformAdapter instead of calling the gh CLI directly. If that work lands, it will supersede the watch/index.ts portion of this PR.

This PR is intentionally tactical: it fixes four concrete bugs that affect every Windows user running squad watch against ADO today, without waiting on the larger platform-agnostic effort. The azure-devops.ts fixes (SDK layer) remain useful regardless of how watch.ts is eventually refactored.

- watch/index.ts: Use shell:true for execFile on Windows so az.cmd is found
- azure-devops.ts: Quote WIQL args with spaces under shell:true on Windows
- azure-devops.ts: Guard JSON.parse against empty az boards query output
- azure-devops.ts: Map GitHub-style 'open'/'closed' states to ADO WIQL equivalents

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@tamirdresher
Copy link
Copy Markdown
Collaborator

@michaeldevenney Hey Mike! I reviewed this PR - the 4 Windows+ADO fixes look solid (az CLI ENOENT, WIQL arg splitting, empty stdout guard, state mapping). Are you planning to mark this as ready for review soon? Also noting that CI checks haven't run yet - might want to trigger those. Let us know if you need any help getting this across the finish line!

@michaeldevenney michaeldevenney marked this pull request as ready for review May 7, 2026 14:03
Copilot AI review requested due to automatic review settings May 7, 2026 14:03
@michaeldevenney
Copy link
Copy Markdown
Author

@michaeldevenney Hey Mike! I reviewed this PR - the 4 Windows+ADO fixes look solid (az CLI ENOENT, WIQL arg splitting, empty stdout guard, state mapping). Are you planning to mark this as ready for review soon? Also noting that CI checks haven't run yet - might want to trigger those. Let us know if you need any help getting this across the finish line!

Hi Tamir, sorry for the delay, got wrapped up with something at work. Yes, this is ready for review. The CI checks appear to be waiting on approval from a maintainer.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes several Windows-specific failures when running squad watch against Azure DevOps by improving Azure CLI invocation/argument handling and by mapping GitHub-style state filters (open/closed) to Azure DevOps WIQL state conditions.

Changes:

  • Update the CLI watch command to run Azure CLI successfully on Windows by using shell: true for az invocations.
  • Harden AzureDevOpsAdapter.listWorkItems() by (a) quoting whitespace-containing args on Windows, (b) treating empty stdout as [], and (c) mapping open/closed to ADO WIQL equivalents.
  • Add a changeset bumping @bradygaster/squad-cli and @bradygaster/squad-sdk as patch releases.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
packages/squad-sdk/src/platform/azure-devops.ts Quotes az args on Windows to avoid WIQL splitting; maps open/closed to ADO WIQL; guards empty CLI output before JSON parse.
packages/squad-cli/src/cli/commands/watch/index.ts Uses shared azCmd/azExecOpts for Windows-safe Azure CLI checks and work item updates.
.changeset/windows-ado-fixes.md Patch changeset for CLI + SDK releases.

Comment thread packages/squad-cli/src/cli/commands/watch/index.ts Outdated
azCmd, azExecOpts, storage, and execFileAsync were declared between
two import blocks. TypeScript/ESM requires all import statements to
precede any executable code. Consolidate the full import block at the
top of the file, then declare the module-level constants below.

Addresses review feedback on PR bradygaster#1055.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@michaeldevenney
Copy link
Copy Markdown
Author

michaeldevenney commented May 7, 2026

Fixed the import issue — consolidated all import statements into a single block at the top of the file before any executable code. The four module-level constants (storage, execFileAsync, azCmd, azExecOpts) are now declared after the complete import block, which is where they belong per TypeScript/ESM semantics.

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.

4 participants