From 1f8d165f86491f5931ab27aa059066fdb0c18111 Mon Sep 17 00:00:00 2001 From: Tirth Kanani Date: Fri, 5 Jun 2026 16:19:31 +0100 Subject: [PATCH] fix(extract-import-map): preserve deterministic stderr order across concurrent loaders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses the regression flagged by ZebangCheng on #346: under the parallelised `buildResolutionContext`, `loadTsConfigs` / `loadGoModules` / `loadPhpAutoloads` ran concurrently but each wrote warnings to stderr inline as it iterated read results, so a fixture with both a malformed `tsconfig.json` and a malformed `composer.json` could emit `composer, tsconfig` instead of the pre-PR `tsconfig, composer` depending on I/O timing. Each loader now buffers its warnings into a returned array and the caller drains them in canonical order (tsconfig → go → php) after `Promise.all`, restoring byte-identical stderr output. Added a regression test that fixtures both malformed configs and asserts the tsconfig warning precedes the composer warning in stderr. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../test_extract_import_map.test.mjs | 52 +++++++++++++++++++ .../skills/understand/extract-import-map.mjs | 39 +++++++++++--- 2 files changed, 83 insertions(+), 8 deletions(-) diff --git a/tests/skill/understand/test_extract_import_map.test.mjs b/tests/skill/understand/test_extract_import_map.test.mjs index ee64136..a4be65a 100644 --- a/tests/skill/understand/test_extract_import_map.test.mjs +++ b/tests/skill/understand/test_extract_import_map.test.mjs @@ -1492,3 +1492,55 @@ describe('extract-import-map.mjs — tree-sitter init graceful failure', () => { expect(result.output.stats.totalEdges).toBe(0); }); }); + +describe('extract-import-map.mjs — deterministic stderr ordering across loaders', () => { + let projectRoot; + + afterEach(() => { + if (projectRoot) { + rmSync(projectRoot, { recursive: true, force: true }); + projectRoot = null; + } + }); + + // Regression for the parallel-loader stderr-order bug surfaced in + // PR #346 review: tsconfig / go.mod / composer.json loaders now run + // concurrently, but warnings must still emit in the pre-PR canonical + // order (tsconfig → go → php). If the loaders streamed warnings + // mid-flight, I/O timing could reorder them — the assertions below + // catch that regression. + it('emits warnings in canonical order (tsconfig, go, php) regardless of I/O timing', () => { + projectRoot = setupTree({ + 'tsconfig.json': '{ "compilerOptions": { "baseUrl": ".", ', // unterminated + 'composer.json': '{ "autoload": { "psr-4": { "App\\\\": "src/" }, ', // unterminated + 'src/index.ts': `import { foo } from './foo';\n`, + 'src/foo.ts': `export const foo = 1;\n`, + 'src/Http/Controller.php': + `