Repository navigation
fix: launch git-hook TS scripts with node --import tsx - #2597
Conversation
bunx tsx opens an IPC socket before running the script, so the pre-commit fences die with listen EPERM wherever socket binding is denied. node --import tsx runs the same script on Node without it. Refs: EXSC-1219 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 44 minutes. View limit details
No actionable comments were generated in the recent review. WalkthroughThe lint fences and pre-push validator now use ChangesFence command execution
Estimated code review effort: 2 (Simple) | ~10 minutes Change: Bug fix Possibly related PRs
Merge Risk:
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🤖 [Automated QA Review] Approved — PR #2597: pre-commit fences now launch via node --import tsx; lockstep scripts, ordering and tests verified, no findings
|
The independent review found 1 minor nit. None is fixed unless you pick it.
Reply |
The pre-push hook ran validateScripts.ts through the tsx CLI, which binds an IPC socket under $TMPDIR, so pushes failed in sandboxes that deny socket listen. The fence tests now spawn the staged command with a TMPDIR too long for a socket path instead of pinning the command string, and the two CI fence jobs set up Node 22 so `node --import` never runs on an older runner Node or on Bun's node shim. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🤖 [Automated QA Review] Approved — PR #2597: full report in the Zeus PR comment.
🔍 QA Review — EXSC-1219 · PR #2597 (🔁 Re-review, head
|
thesems
left a comment
There was a problem hiding this comment.
LGTM. One thing to sort out on rebase: #2607 moves every workflow to setup-node with .nvmrc (Node 26). This PR adds a node-version: 22 step in enforceProposalFunnel.yml and validateScripts.yml. If it lands second, those jobs run on Node 22 while engines says >=26. Suggest dropping the step here, or using node-version-file: .nvmrc.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
b1ad022
|
Thanks — switched both |
There was a problem hiding this comment.
🤖 [Automated QA Review] Approved — PR #2597: the new setup-node steps give the node --import fences a pinned Node from .nvmrc
thesems
left a comment
There was a problem hiding this comment.
LGTM. The Node-version follow-up is addressed, and the focused hook/fence tests pass (69/69). No blocking findings.
Lengthen the TMPDIR segment to 200 chars so a socket-binding launcher fails on macOS (recent Node binds up to ~250 bytes there), and assert the node-runtime fence's summary line so a silent exit 0 cannot pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3816f27
There was a problem hiding this comment.
🤖 [Automated QA Review] Approved — PR #2597: no-socket regression tests now fail on macOS and Linux; reviewer nits resolved
…8) (#2645) * test(fence): call withheldEnv in the no-IPC-socket fence test #2618 renamed spawnEnv to withheldEnv while #2597 added a test calling spawnEnv, so main fails with "spawnEnv is not defined". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(fence): build the no-IPC-socket child env with freshChildEnv A copy of the test env carries the developer's NODE_OPTIONS into the child, where --inspect would print to stderr and fail the assertion. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(fence): build fence-test child envs with freshChildEnv Both fence suites now spawn their direct `node --import tsx` children from freshChildEnv, and propose-funnel-fence drops its local spawnEnv helper. The `bun lint:funnel` spawn keeps withheldEnv because bun reloads `.env` for unset names. The node-runtime refusal case pins NODE_ENV=test, which it previously inherited from `bun test`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Which Linear task belongs to this PR?
EXSC-1219
Why did I implement it this way?
Why it is implemented this way
The tsx CLI (whether launched as
bunx tsx,npx tsxor a globaltsx) opens a Unix-socket IPC server ($TMPDIR/tsx-<uid>/<pid>.pipe) before it runs the script. In sandboxes that deny socket binding, everything a git hook launches that way exits withlisten EPERM: the two lint-staged fences block every.ts/.jscommit, and the pre-push validator blocks every push.node --import tsxruns the same script on Node through the tsx loader, which opens no socket.The diff:
package.json: the lint-staged entries forscript/deploy/safe/funnel-fence.tsandscript/utils/node-runtime-fence.tsstart withnode --import tsx. They are still the third and fourth steps, afterprettier --writeandoxlintand beforetypecheck-files.sh.lint:funnelandlint:node-runtimeare changed the same way and are still exactly the lint-staged command plus.andscript tasks..husky/pre-push:validateScripts.tslaunches withnode --import tsx.enforceProposalFunnel.yml,validateScripts.yml: asetup-nodestep (Node 22) before the fence runs.node --importneeds Node ≥20.6, and on a runner with no Node,bun runputs its ownnodeshim on PATH and would run the fence on Bun.TMPDIRset to a path longer than a Unix socket path may be (104 bytes on macOS, 108 on Linux) and asserts a clean run. Any launcher that binds a socket fails it: with the entries switched back tobunx tsx, both tests fail withlisten EINVAL..agents/rules/200-typescript.md: the launcher exception covers what git hooks run, and names the tsx CLI (notbunx) as what opens the socket.How each criterion is met:
lint:funnel/lint:node-runtimeequality tests check it.Run locally:
bun test script/deploy/safe/propose-funnel-fence.test.ts script/utils/node-runtime-fence.test.ts script/utils/validateScriptsWorkflow.test.ts: all pass.node --import tsx ./script/utils/validateScripts.ts --base origin/main --head HEADwith an unbindableTMPDIR: passes.bash script/utils/typecheck-files.sh,bunx oxlint --type-aware,bunx prettier --checkon the changed files, andactionlinton the two workflows: clean.The other
bunx tsxpackage scripts are left as they are, as the ticket specifies.Checklist before requesting a review
Checklist for reviewer (DO NOT DEPLOY and contracts BEFORE CHECKING THIS!!!)
🤖 Generated with Claude Code