Skip to content

Commit 20535b7

Browse files
committed
Fix cross-platform test regressions and refresh seed artifact
1 parent af4783b commit 20535b7

9 files changed

Lines changed: 64 additions & 14 deletions

File tree

.github/workflows/AGENTS.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,38 @@ Result:
156156
# fail 0
157157
```
158158

159+
### 2026-08-28: Stale Artifact and Windows Test-Environment Regressions
160+
161+
Run `33228840410` failed in jobs `99037773532` (`tests (ubuntu-latest, 24.x)`)
162+
and `99037773651` (`tests (windows-latest, 24.x)`), step
163+
`Run tests (including 6 new language adapters + cross-platform paths)`, on
164+
commit `af4783ba77e63e62a4b29a204fc3bb7b67b0e1ff` from `main`. Build,
165+
typecheck, lint, config sync, security audit, native, and benchmark jobs passed.
166+
167+
Confirmed causes and fixes:
168+
169+
- `seed-resolution-evaluation.test.ts` failed on both platforms because commit
170+
`6a49d8b2` changed `src/retrieval/orchestrator.ts` without regenerating the
171+
checked source hash. `npm run benchmark:seed-resolution` refreshed the
172+
deterministic artifact.
173+
- `semantic-pipeline-regressions.test.ts` used LF-only multiline `indexOf`
174+
needles against a CRLF Windows checkout. Its shared source reader now
175+
normalizes CRLF and lone CR to LF before structural assertions.
176+
- `mcp-runtime-tool.test.ts` selected hosted Windows PowerShell 5 for one case,
177+
reintroducing the 30-second hang previously avoided by commit `a4625045`.
178+
The case now uses `pwsh.exe`; the existing stderr detector strips VT control
179+
sequences and recognizes PowerShell 7's concise `.ps1:<line>` error record.
180+
181+
The remaining Windows-only lifetime failures were traced with high confidence
182+
to `%TEMP%` using the `RUNNER~1` short-path alias. The production lifetime
183+
validator correctly rejects a requested path whose `realpath` differs, so the
184+
three test helpers now canonicalize each fresh `mkdtemp` directory with
185+
`realpath`. The production security boundary was not relaxed.
186+
187+
Focused local verification passed 213/213 tests across the seven affected test
188+
files. Hosted validation of all four fixes is still pending; no workflow YAML
189+
change was needed.
190+
159191
## Local Reproduction Caveats
160192

161193
Use the same Node major version as CI when you investigate native crashes. CI runs Node `20.x`, and local reproductions become unreliable if `node_modules` contains native artifacts built under Node `22`.

docs/benchmarks/seed-resolution-evaluation-v2.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
"caseCount": 4
88
},
99
"baseline": {
10-
"gitHead": "e93ee67311de91bebcb66511063a1d27dcbd3bb0",
11-
"evaluatedSourceDiffSha256": "1817d5a641ae2d4d05afcf63f7e7d8777c54b23e706fbd60ba94372aaddb1234",
10+
"gitHead": "af4783ba77e63e62a4b29a204fc3bb7b67b0e1ff",
11+
"evaluatedSourceDiffSha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
1212
"sourceHashes": {
1313
"src/context/engine.ts": "8f2f70e329bd99f0c00675ef556497e330fde5a6e2fa8fdf0c29041724c94ed3",
1414
"src/graph/slice/start-node-resolver.ts": "180a7020659ad3c52e4595bee0b1d2257e264b24bf9dbe4abc7bd29b46a67e70",
1515
"src/retrieval/identifier-extraction.ts": "475acdf8dc8f603e650137ab129a8dc1d15139c6711d87e4529f568b9de5da84",
16-
"src/retrieval/orchestrator.ts": "16da041a0f8a241006f3325a72c12c9b942d9c6d917a20d8e3d632945513d667",
16+
"src/retrieval/orchestrator.ts": "d297cb5dc326fcb114f9c1f34680c2460f5e73b9bddaca6f71e3f42bdb80f469",
1717
"src/retrieval/seed-resolver.ts": "662604e2076e58cd0f46055298f8296bf63ecb2e4433d714a2a76c714d41efdb"
1818
},
1919
"platform": "win32-x64",
@@ -393,8 +393,8 @@
393393
"sliceStartNodeRecall": 1
394394
},
395395
"observedMedianPolicyLatencyMs": {
396-
"contextRetrieval": 0.023,
397-
"sliceStartNodes": 0.0085
396+
"contextRetrieval": 0.0211,
397+
"sliceStartNodes": 0.0077
398398
},
399399
"reproduction": "npm run benchmark:seed-resolution",
400400
"check": "npm run build && node --experimental-strip-types scripts/evaluate-seed-resolution.ts --check"

src/mcp/tools/runtime.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import { access, mkdtemp, realpath, writeFile, rm } from "fs/promises";
99
import { join } from "path";
1010
import { tmpdir } from "os";
11+
import { stripVTControlCharacters } from "util";
1112
import { z } from "zod";
1213
import type { ToolContext } from "../../server.js";
1314
import { parseActionHandlerArgs } from "../../gateway/dispatch-spine.js";
@@ -301,15 +302,18 @@ const POWERSHELL_STDERR_ERROR_PATTERNS: RegExp[] = [
301302
/FullyQualifiedErrorId\s*:/,
302303
/\+\s*CategoryInfo\s*:/,
303304
/^At line:\d+ char:\d+/m,
305+
// PowerShell 7 ConciseView after VT control sequences are stripped.
306+
/^[^:\r\n]+:\s+.+\.ps1:\d+(?::\d+)?$/m,
304307
/is not recognized as (?:the name of )?a cmdlet/i,
305308
/cannot be retrieved because it has not been set/i,
306309
/Exception calling ["'][^"']+["']/,
307310
];
308311

309312
export function detectPowerShellStderrErrors(stderr: string): boolean {
310313
if (!stderr) return false;
314+
const normalized = stripVTControlCharacters(stderr);
311315
return POWERSHELL_STDERR_ERROR_PATTERNS.some((pattern) =>
312-
pattern.test(stderr),
316+
pattern.test(normalized),
313317
);
314318
}
315319

tests/integration/mcp-runtime-tool.test.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -402,10 +402,7 @@ describe("sdl.runtime.execute - MCP Tool Handler", () => {
402402
const result = await handleRuntimeExecute({
403403
repoId,
404404
runtime: "powershell",
405-
executable:
406-
expected.name === "non-terminating cmdlet error"
407-
? "powershell.exe"
408-
: "pwsh.exe",
405+
executable: "pwsh.exe",
409406
code: expected.code,
410407
persistOutput: false,
411408
outputMode: "minimal",

tests/unit/observability/lifetime-lock.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ const children = new Set<ChildProcessWithoutNullStreams>();
4545
const WORKER_TIMEOUT_MS = 5_000;
4646

4747
async function temporaryDirectory(): Promise<string> {
48-
const directory = await mkdtemp(join(tmpdir(), "sdl-lifetime-lock-"));
48+
const directory = await realpath(
49+
await mkdtemp(join(tmpdir(), "sdl-lifetime-lock-")),
50+
);
4951
temporaryDirectories.push(directory);
5052
return directory;
5153
}

tests/unit/observability/lifetime-publication.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
mkdtemp,
99
open,
1010
readFile,
11+
realpath,
1112
readdir,
1213
rename,
1314
rm,
@@ -55,7 +56,9 @@ function serialized(value: DurableLifetimeRoot): string {
5556
}
5657

5758
async function temporaryDirectory(): Promise<string> {
58-
const directory = await mkdtemp(join(tmpdir(), "sdl-lifetime-publication-"));
59+
const directory = await realpath(
60+
await mkdtemp(join(tmpdir(), "sdl-lifetime-publication-")),
61+
);
5962
temporaryDirectories.push(directory);
6063
return directory;
6164
}

tests/unit/observability/lifetime-store.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
lstat,
44
mkdtemp,
55
readFile,
6+
realpath,
67
readdir,
78
rm,
89
unlink,
@@ -50,7 +51,9 @@ function root(generation: number, updatedAt = ISO_1): DurableLifetimeRoot {
5051
}
5152

5253
async function temporaryDirectory(): Promise<string> {
53-
const directory = await mkdtemp(join(tmpdir(), "sdl-lifetime-store-"));
54+
const directory = await realpath(
55+
await mkdtemp(join(tmpdir(), "sdl-lifetime-store-")),
56+
);
5457
temporaryDirectories.push(directory);
5558
return directory;
5659
}

tests/unit/semantic-pipeline-regressions.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import { readFileSync } from "node:fs";
44
import { join } from "node:path";
55

66
function readSource(path: string): string {
7-
return readFileSync(join(process.cwd(), path), "utf8");
7+
return readFileSync(join(process.cwd(), path), "utf8").replace(
8+
/\r\n?/g,
9+
"\n",
10+
);
811
}
912

1013
describe("semantic pipeline regressions", () => {

tests/unit/tool-qa-regressions.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,12 @@ describe("SDL tool QA regressions", () => {
122122
),
123123
true,
124124
);
125+
assert.equal(
126+
detectPowerShellStderrErrors(
127+
"\u001b[31;1mGet-Item: \u001b[0mC:\\Temp\\code.ps1:1\u001b[0m",
128+
),
129+
true,
130+
);
125131
assert.equal(
126132
detectPowerShellStderrErrors("WARNING: package deprecated\n"),
127133
false,

0 commit comments

Comments
 (0)