From 28931d967901fd3c3fd6ca26729d1a0ec5eba5c1 Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Tue, 24 Feb 2026 17:57:05 -0800 Subject: [PATCH 1/2] Fix Windows compatibility in tier-check client conformance Two issues prevented client conformance tests from running on Windows: 1. Single-quote quoting in execSync: The --command argument was wrapped in single quotes, which cmd.exe treats as literal characters rather than string delimiters. This caused the CLI to receive only the first word of the command. Switched to execFileSync with an args array to bypass shell quoting entirely. 2. Backslash path separators in parseOutputDir: dirname() on Windows returns auth\scenario-name but reconcileWithExpected compares against auth/scenario-name, causing auth scenarios to be double-counted. Normalize backslashes to forward slashes in parsed scenario names. --- .../checks/test-conformance-results.ts | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/tier-check/checks/test-conformance-results.ts b/src/tier-check/checks/test-conformance-results.ts index 5ba9849..8b4e4c9 100644 --- a/src/tier-check/checks/test-conformance-results.ts +++ b/src/tier-check/checks/test-conformance-results.ts @@ -1,4 +1,4 @@ -import { execSync } from 'child_process'; +import { execFileSync } from 'child_process'; import { mkdtempSync, readFileSync, existsSync, globSync } from 'fs'; import { join, dirname } from 'path'; import { tmpdir } from 'os'; @@ -43,7 +43,7 @@ function parseOutputDir(outputDir: string): ConformanceResult { const checksFiles = globSync('**/checks.json', { cwd: outputDir }); for (const checksFile of checksFiles) { - const scenarioName = dirname(checksFile); + const scenarioName = dirname(checksFile).replace(/\\/g, '/'); const checksPath = join(outputDir, checksFile); try { @@ -181,8 +181,9 @@ export async function checkConformance(options: { const outputDir = mkdtempSync(join(tmpdir(), 'tier-check-server-')); try { - execSync( - `node dist/index.js server --url ${options.serverUrl} -o ${outputDir}`, + execFileSync( + process.execPath, + ['dist/index.js', 'server', '--url', options.serverUrl, '-o', outputDir], { cwd: process.cwd(), stdio: ['pipe', 'pipe', 'pipe'], @@ -221,8 +222,18 @@ export async function checkClientConformance(options: { const outputDir = mkdtempSync(join(tmpdir(), 'tier-check-client-')); try { - execSync( - `node dist/index.js client --command '${options.clientCmd}' --suite all -o ${outputDir}`, + execFileSync( + process.execPath, + [ + 'dist/index.js', + 'client', + '--command', + options.clientCmd, + '--suite', + 'all', + '-o', + outputDir + ], { cwd: process.cwd(), stdio: ['pipe', 'pipe', 'pipe'], From 9d46088680480974263d54130c9bf10f483727db Mon Sep 17 00:00:00 2001 From: Paul Carleton Date: Wed, 25 Mar 2026 12:01:22 +0000 Subject: [PATCH 2/2] fix: use process.argv[1] for CLI path in subprocess calls Combines the npx-compatibility fix from #175 with this PR's execFileSync approach. process.argv[1] resolves to the absolute path of the running CLI regardless of working directory, so tier-check works when invoked via npx or from any cwd. --- src/tier-check/checks/test-conformance-results.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/tier-check/checks/test-conformance-results.ts b/src/tier-check/checks/test-conformance-results.ts index 8b4e4c9..f68d879 100644 --- a/src/tier-check/checks/test-conformance-results.ts +++ b/src/tier-check/checks/test-conformance-results.ts @@ -183,9 +183,8 @@ export async function checkConformance(options: { try { execFileSync( process.execPath, - ['dist/index.js', 'server', '--url', options.serverUrl, '-o', outputDir], + [process.argv[1], 'server', '--url', options.serverUrl, '-o', outputDir], { - cwd: process.cwd(), stdio: ['pipe', 'pipe', 'pipe'], timeout: 120_000 } @@ -225,7 +224,7 @@ export async function checkClientConformance(options: { execFileSync( process.execPath, [ - 'dist/index.js', + process.argv[1], 'client', '--command', options.clientCmd, @@ -235,7 +234,6 @@ export async function checkClientConformance(options: { outputDir ], { - cwd: process.cwd(), stdio: ['pipe', 'pipe', 'pipe'], timeout: 120_000 }