fix(imagine): canonicalize dry-run worktree path so per-file attribution works on macOS#99
Merged
Merged
Conversation
…n macOS (symlinked tmpdir)
dryRun() attributes test failures to files by string-matching node --test's
`location:` diagnostic (a canonical realpath) against join(wt, testfile). On
macOS the sandbox worktree lives under tmpdir(), which is itself a symlink
(/var → /private/var, /tmp → /private/tmp), so the raw wt path never matched
the realpath'd locations: attribution failed, perFile was omitted, and
test/imagine.test.js "dryRun executes the suite in an ephemeral worktree and
removes it (pass + fail)" saw perFile === undefined instead of the expected
{ "test/pass.test.js": "pass", "test/fail.test.js": "fail" }.
Fix the code (not the test): realpathSync(wt) once after the worktree is
created and compare against that canonical root. On Linux (no symlinked tmpdir)
this is a no-op. Re-enable the full unit suite on macos-latest in smoke.yml.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01KfCEnSJzSG914yyVesjjD6
CodeWithJuber
marked this pull request as ready for review
July 19, 2026 20:03
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Fixes the one macOS-only test failure that the new CI matrix (#90) exposed — and it turned out to be a real production bug in
forge imagine --dry-run, not just a test artifact.Root cause.
dryRun()(src/imagine.js) attributes eachnot okblock to a test file by string-comparing node--test'slocation:diagnostic againstjoin(wt, testfile), wherewtis amkdtempSync(join(tmpdir(), …))worktree.node --testreportslocation:as a canonical realpath. On macOS,tmpdir()lives under a symlink (/var→/private/var,/tmp→/private/tmp), sowt(e.g./var/folders/…/wt/test/fail.test.js) never matched node's realpath'd/private/var/folders/…/wt/test/fail.test.js. Attribution failed,attributableflipped false, andperFilewas omitted entirely — soforge imagine --dry-run's pass/fail-per-file breakdown was silently broken for all macOS users. On Linux/tmpisn't a symlink, so it happened to match — which is why it was Linux-green, macOS-red, and invisible until the suite ran on macOS.Fix (code, not the assertion). Canonicalize the worktree root once with
realpathSync(wt)right after it's created, and compare againstjoin(wtReal, …). No-op on Linux; correct on macOS. The strictdeepEqualassertion in the test is unchanged.How it was found. Reproduced deterministically on Linux by pointing
TMPDIRat a symlink (mimicking macOS's/var→/private/var) — no macOS box or CI round-trip needed — which failedtest/imagine.test.js:176exactly as CI did.Re-enables macOS coverage.
.github/workflows/smoke.ymlnow runs the full unit suite onmacos-latestagain (theubuntu-onlystopgap gate + its TODO are removed).Verification
npm test(normal TMPDIR): 1057 tests, 0 fail.TMPDIR=<symlink> npm test(macOS repro): the previously-failingimaginetest now passes (11/11 in that file; full suite 0 fail).forge docs checkgreen.Checklist
npm testpasses (both normal and symlinked-tmpdir)npm run check/npm run typecheck/docs checkpassCHANGELOG.md[Unreleased]updatedRisk & rollback
realpathSynccall, no-op wheretmpdir()isn't a symlink; re-enables a CI step.🤖 Generated with Claude Code
https://claude.ai/code/session_01KfCEnSJzSG914yyVesjjD6
Generated by Claude Code