Skip to content

fix(gates): the new-code gates are unrunnable on Windows, so nobody runs them - #59

Merged
LMPrado-DZ23 merged 1 commit into
release/v3.8.55from
fix/newcode-gate-windows
Sep 20, 2026
Merged

LMPrado-DZ23 merged 1 commit into
release/v3.8.55from
fix/newcode-gate-windows

Conversation

@LMPrado-DZ23

Copy link
Copy Markdown
Owner

newCodeMode.withBaseWorktree lints the merge-base in a throwaway git worktree and links the repo's node_modules into it. That link was a "dir" symlink, which on Windows needs SeCreateSymbolicLinkPrivilege — an elevated shell or Developer Mode. Without it fs.symlinkSync throws EPERM and the gate dies before comparing anything:

Error: EPERM: operation not permitted, symlink '...\node_modules' -> '...'
    at withBaseWorktree (scripts/check/newCodeMode.mjs:79:31)

So check:complexity-ratchets, check:dead-code and check:file-size cannot be run locally at all on a Windows checkout.

Why this is worth a PR of its own

It is not hypothetical. Three separate agents shipped new-code regressions in this release line, each having run the gates locally and believed they passed — the gates had died on EPERM before reaching the comparison. #52 needed a second round for exactly this reason, and its author independently recommended this same fix.

A junction is the same thing for this purpose — a directory reparse point — and needs no privilege. Measured on the affected machine:

symlink dir: FALHA -> EPERM
junction   : OK

The change

The link goes through linkNodeModules, which picks "junction" on win32 and "dir" elsewhere, and turns a failure into a message naming what broke and why it matters instead of a bare errno.

Proof it runs end to end on Windows

Against a base with source files in scope — an earlier run reporting 0 changed files proves nothing, since it short-circuits before linking:

$ node scripts/check/check-complexity-ratchets.mjs --base-ref b581c39cfdcd
[complexity] OK (código novo) — 7 violações nos arquivos tocados (base 7)
[cognitive-complexity] OK (código novo) — 4 violações nos arquivos tocados (base 4)
exit=0

Tests

tests/unit/newcode-gate-node-modules-link.test.ts covers both halves:

  • the link resolves on whatever platform runs it — asserted by reading a file through it, because a link that exists but does not resolve leaves the linter blind;
  • the failure message is actionable;
  • statically, that win32 still picks "junction". That assertion earns its place: CI runs on Linux and could never catch this regression behaviourally.
Gate Result
tests/unit/newcode-gate-node-modules-link.test.ts 3 pass / 0 fail
eslint --max-warnings=0 exit 0
tsc -p tsconfig.typecheck-core.json exit 0, 0 errors

Run with isolated DATA_DIR / HOME / USERPROFILE / APPDATA.

🤖 Generated with Claude Code

…uns them

`newCodeMode.withBaseWorktree` lints the merge-base in a throwaway git worktree
and links the repo's node_modules into it. The link was a "dir" symlink, which
on Windows needs SeCreateSymbolicLinkPrivilege — an elevated shell or Developer
Mode. Without it `fs.symlinkSync` throws EPERM and the gate dies *before
comparing anything*:

  Error: EPERM: operation not permitted, symlink '...\node_modules' -> '...'
      at withBaseWorktree (scripts/check/newCodeMode.mjs:79:31)

So check:complexity-ratchets, check:dead-code and check:file-size cannot be run
locally at all on a Windows checkout, and a contributor there learns about a
regression only when CI says so. That is not hypothetical: three separate agents
shipped new-code regressions in this release line, each having run the gates
locally and seen them "pass".

A junction is the same thing for this purpose — a directory reparse point — and
needs no privilege. Measured on this machine:

  symlink dir: FALHA -> EPERM
  junction   : OK

The link now goes through `linkNodeModules`, which picks "junction" on win32 and
"dir" elsewhere, and turns a failure into a message that says what broke and why
it matters rather than a bare errno.

Proof it now runs end to end on Windows, against a base with source files in
scope (the earlier short-circuit on "0 changed files" proves nothing):

  $ node scripts/check/check-complexity-ratchets.mjs --base-ref b581c39
  [complexity] OK (código novo) — 7 violações nos arquivos tocados (base 7)
  [cognitive-complexity] OK (código novo) — 4 violações nos arquivos tocados (base 4)
  exit=0

tests/unit/newcode-gate-node-modules-link.test.ts covers both halves: the link
resolves on whatever platform runs it (reading a file *through* it, since a link
that exists but does not resolve leaves the linter blind), the failure message is
actionable, and — statically — that win32 still picks "junction". The static
assertion earns its place because CI runs on Linux and could never catch that
regression behaviourally.

Verification (isolated DATA_DIR/HOME/USERPROFILE/APPDATA):
  tests/unit/newcode-gate-node-modules-link.test.ts   3 pass / 0 fail
  eslint --max-warnings=0                             exit 0
  tsc -p tsconfig.typecheck-core.json                 exit 0, 0 errors

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 20, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 95f5da12-73e7-4ae4-a8c6-79f5adbd0362


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@LMPrado-DZ23
LMPrado-DZ23 merged commit e1a46d0 into release/v3.8.55 Sep 20, 2026
15 checks passed
LMPrado-DZ23 pushed a commit that referenced this pull request Sep 20, 2026
…ragments

check:changelog-integrity caught the CHANGELOG-eat pattern on this branch: the
merge of release/v3.8.55 recorded this branch's older CHANGELOG.md, dropping the
New Features header and 8 bullets that landed in #48, #50, #51, #52, #55, #57,
#58 and #59. No commit here ever edits that file, so the fix is to take the base
version wholesale. Verified identical to origin/release/v3.8.55 afterwards, and
the gate now reports "no base bullets lost".

Adds this PR's own entry as fragments instead, which is the convention that
exists precisely to stop this: one feature fragment for the Gemini CLI entry and
the new placeholder, one fix fragment for the two corrected cards.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants