The previous approach symlinked workspace/node_modules → /tmp/node_modules,
which broke esbuild path resolution in pnpm monorepos. Tools like rwsdk's
directive scanner resolved paths through the symlink incorrectly, producing
paths like apps/web/tmp/node_modules/.pnpm/... instead of /tmp/node_modules/.pnpm/...
Mount the warm cache as a Docker bind mount directly at the workspace
node_modules path. This makes the filesystem layout identical to production
GitHub Actions. The original EBUSY concern is already mitigated by the git
shim (blocks git clean) and checkout patching (clean: false).
Adds a smoke test exercising esbuild resolution through pnpm workspace
symlinks to prevent regression.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: mount warm-modules at /tmp/node_modules for pnpm TypeScript compat
TypeScript resolves @types/* by walking up from realpath(). With pnpm's
.pnpm virtual store symlinked to /tmp/warm-modules, the upward walk never
finds a node_modules directory. Mounting at /tmp/node_modules instead means
TypeScript's walk from /tmp/node_modules/.pnpm/... naturally finds
/tmp/node_modules/@types/.
Closes#176
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: preserve git-tracked symlinks in workspace snapshot
copyWorkspace was using cp/fs.cpSync which dereference symlinks, causing
git mode 120000 entries to be dropped from the workspace commit. Now we
check lstat() before copying and recreate symlinks via symlinkSync.
Closes#178
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: add pnpm symlink smoke test reproducing #176 and #178
Adds a committed fixture at .github/fixtures/pnpm-symlinks/ with a
git-tracked symlink (mode 120000) and a TSX file that requires
@types/react resolution through pnpm's .pnpm virtual store.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>