From 85448f39bfe419f1f877b496d6991befc9d3498c Mon Sep 17 00:00:00 2001 From: aaron Date: Sun, 16 Aug 2026 18:47:25 -0400 Subject: [PATCH] fix: golden parity files are path-portable (WS1 #369 follow-up) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The compiled output embeds absolute template paths, so the committed goldens were machine-specific — the fast CI job red on any other checkout (the pack-vs-today equivalence half held; only the golden-file half failed). Goldens now normalize the repo root to on write and compare; the equivalence assertions stay raw byte equality. Verified from a second checkout at a disjoint path. Also documents the process miss: PR 391 auto-merged while the non-required fast check was still running. Follow-ups merge only after fast reports. --- .../test/scores/golden/compile-chained.md | 2 +- .../test/scores/golden/compile-score.md | 2 +- .../test/scores/golden_parity.test.ts | 23 +++++++++++++------ 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/packages/extension/test/scores/golden/compile-chained.md b/packages/extension/test/scores/golden/compile-chained.md index 2249162a..be54d3f9 100644 --- a/packages/extension/test/scores/golden/compile-chained.md +++ b/packages/extension/test/scores/golden/compile-chained.md @@ -43,7 +43,7 @@ gate's checks pass. 12. **solve** - emits: run, pulse — record via the matching `amicode_*` tool - executor: `local` - - vetted template (absolute): `/Users/aaron/armonia/repos/amicode/packages/extension/scores/pulse-designer/templates/solve.jl` + - vetted template (absolute): `/extension/scores/pulse-designer/templates/solve.jl` - Q `solve_params`: "Pulse duration T (ns), timesteps N, and max_iter?" — default: T = 10 ns, N = 50, max_iter = 60 13. **inspect** 14. **hardware** (optional) diff --git a/packages/extension/test/scores/golden/compile-score.md b/packages/extension/test/scores/golden/compile-score.md index d871689f..8addc42f 100644 --- a/packages/extension/test/scores/golden/compile-score.md +++ b/packages/extension/test/scores/golden/compile-score.md @@ -31,7 +31,7 @@ gate's checks pass. 6. **solve** - emits: run, pulse — record via the matching `amicode_*` tool - executor: `local` - - vetted template (absolute): `/Users/aaron/armonia/repos/amicode/packages/extension/scores/pulse-designer/templates/solve.jl` + - vetted template (absolute): `/extension/scores/pulse-designer/templates/solve.jl` - Q `solve_params`: "Pulse duration T (ns), timesteps N, and max_iter?" — default: T = 10 ns, N = 50, max_iter = 60 7. **inspect** 8. **hardware** (optional) diff --git a/packages/extension/test/scores/golden_parity.test.ts b/packages/extension/test/scores/golden_parity.test.ts index 49f6a2ba..254f6259 100644 --- a/packages/extension/test/scores/golden_parity.test.ts +++ b/packages/extension/test/scores/golden_parity.test.ts @@ -22,6 +22,14 @@ const SCORES_ROOT = path.resolve(__dirname, "..", "..", "scores"); const PACKS_ROOT = path.resolve(__dirname, "..", "..", "packs"); const GOLDEN_DIR = path.resolve(__dirname, "golden"); +// The compiled output embeds ABSOLUTE template paths, which differ per +// checkout. The goldens are therefore stored PATH-PORTABLE: the repo root is +// normalized to on both write and compare. The pack-vs-today +// equivalence assertions below stay RAW (same machine, strict byte equality); +// only the golden-file comparisons are normalized. +const WORKSPACE_ROOT = path.resolve(__dirname, "..", "..", ".."); +const portable = (s: string) => s.split(WORKSPACE_ROOT).join(""); + function today() { const load = loadRepertoire(SCORES_ROOT); const score0 = load.scores.find((s) => s.manifest.id === "pulse-designer"); @@ -44,8 +52,8 @@ function golden(name: string, content: string): string { const file = path.join(GOLDEN_DIR, name); if (process.env.GEN_GOLDEN) { fs.mkdirSync(GOLDEN_DIR, { recursive: true }); - fs.writeFileSync(file, content); - return content; + fs.writeFileSync(file, portable(content)); + return portable(content); } return fs.readFileSync(file, "utf8"); } @@ -74,15 +82,16 @@ describe("golden parity — the pack path is byte-identical to today's path", () it("compileScore(pulse-designer) === today === golden", () => { const t = todaySurfaces(); - expect(viaPack().primary && compileScore(viaPack().primary)).toBe(t.compileScore); - expect(t.compileScore).toBe(golden("compile-score.md", t.compileScore)); + const p = viaPack(); + expect(compileScore(p.primary)).toBe(t.compileScore); // raw byte equality + expect(portable(t.compileScore)).toBe(golden("compile-score.md", t.compileScore)); }); it("compileChainedScore(overture → pulse-designer) === today === golden", () => { const t = todaySurfaces(); const { primary, head } = viaPack(); - expect(compileChainedScore(head, primary)).toBe(t.compileChained); - expect(t.compileChained).toBe(golden("compile-chained.md", t.compileChained)); + expect(compileChainedScore(head, primary)).toBe(t.compileChained); // raw byte equality + expect(portable(t.compileChained)).toBe(golden("compile-chained.md", t.compileChained)); }); it("buildRouterSection over the pack's visible scores === today === golden", () => { @@ -91,6 +100,6 @@ describe("golden parity — the pack path is byte-identical to today's path", () // the router renders the repertoire in the order it is handed; the pack's // manifest order must reproduce today's effective order exactly expect(buildRouterSection(pack.scores)).toBe(t.router); - expect(t.router).toBe(golden("router-section.md", t.router)); + expect(portable(t.router)).toBe(golden("router-section.md", t.router)); }); });