diff --git a/.github/claude-canary-runtime/package-lock.json b/.github/claude-canary-runtime/package-lock.json index e78392daa..7716ef93f 100644 --- a/.github/claude-canary-runtime/package-lock.json +++ b/.github/claude-canary-runtime/package-lock.json @@ -11,7 +11,7 @@ "@anthropic-ai/claude-code": "2.1.214" }, "engines": { - "node": "22.16.0" + "node": "22.18.0" } }, "node_modules/@anthropic-ai/claude-code": { diff --git a/.github/claude-canary-runtime/package.json b/.github/claude-canary-runtime/package.json index 57076d892..50820742b 100644 --- a/.github/claude-canary-runtime/package.json +++ b/.github/claude-canary-runtime/package.json @@ -3,7 +3,7 @@ "version": "0.0.0", "private": true, "engines": { - "node": "22.16.0" + "node": "22.18.0" }, "dependencies": { "@anthropic-ai/claude-code": "2.1.214" diff --git a/.github/gitnexus-review-runtime/package-lock.json b/.github/gitnexus-review-runtime/package-lock.json index e805e759b..0677011c0 100644 --- a/.github/gitnexus-review-runtime/package-lock.json +++ b/.github/gitnexus-review-runtime/package-lock.json @@ -11,7 +11,7 @@ "gitnexus": "1.6.9" }, "engines": { - "node": "22.16.0" + "node": "22.18.0" } }, "node_modules/@emnapi/runtime": { diff --git a/.github/gitnexus-review-runtime/package.json b/.github/gitnexus-review-runtime/package.json index 237310bad..de0a1dd12 100644 --- a/.github/gitnexus-review-runtime/package.json +++ b/.github/gitnexus-review-runtime/package.json @@ -3,7 +3,7 @@ "private": true, "version": "1.0.0", "engines": { - "node": "22.16.0" + "node": "22.18.0" }, "dependencies": { "gitnexus": "1.6.9" diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index c78a407b9..d9aa33a4e 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -378,15 +378,16 @@ jobs: "$PREFIX/bin/gitnexus" --version fi - # Node engines-floor gate (#2372). The embedding resolvers statically named - # `module.registerHooks`, which only exists on Node >= 22.15 / >= 23.5, so on - # the supported floor (engines: >=22.0.0) those ESM modules failed to LINK — - # a class vitest/tsx transforms structurally mask, and the default - # `node-version: 22` (resolves to latest) never hits. Build the dist on 22.x, - # then import-link every module R1 names as a load surface on a pinned 22.14 - # so a regression fails here instead of shipping to users on that Node range. + # Node engines-floor gate (#2372). A module that statically names an API + # newer than the supported floor (e.g. `module.registerHooks`, added in + # 22.15) fails to LINK on the floor — a class vitest/tsx transforms + # structurally mask, and the default `node-version: 22` (resolves to latest) + # never hits. Build the dist on 22.x, then import-link every module R1 names + # as a load surface on the pinned engines floor (22.18.0, per package.json + # `engines: ^22.18.0 || >=24.11.0`) so a regression fails here instead of + # shipping to users on the minimum supported Node. node-floor-compat: - name: node floor compat (22.14) + name: node floor compat (22.18) runs-on: ubuntu-latest timeout-minutes: 15 steps: @@ -415,14 +416,14 @@ jobs: # (so no package-manager cache is needed). - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: - node-version: '22.14.0' + node-version: '22.18.0' package-manager-cache: false - - name: Import-link the built dist on Node 22.14 + - name: Import-link the built dist on Node 22.18 shell: bash run: | set -euo pipefail node --version - node --version | grep -q '^v22\.14\.' || { echo "expected Node 22.14.x" >&2; exit 1; } + node --version | grep -q '^v22\.18\.' || { echo "expected Node 22.18.x" >&2; exit 1; } for m in \ core/embeddings/runtime-install \ core/embeddings/onnxruntime-node-resolver \ @@ -556,7 +557,7 @@ jobs: persist-credentials: false - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: - node-version: '22.16.0' + node-version: '22.18.0' cache: npm cache-dependency-path: | gitnexus/package-lock.json diff --git a/.github/workflows/gitnexus-review-agent.yml b/.github/workflows/gitnexus-review-agent.yml index 8582403ad..88526871e 100644 --- a/.github/workflows/gitnexus-review-agent.yml +++ b/.github/workflows/gitnexus-review-agent.yml @@ -325,7 +325,7 @@ jobs: if: steps.context.outputs.ready == 'true' uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: - node-version: '22.16.0' + node-version: '22.18.0' - name: Install and preflight Claude subprocess isolation id: isolation @@ -377,7 +377,7 @@ jobs: .github/claude-canary-runtime/package-lock.json \ "${runtime_dir}/package-lock.json" printf '%s\n' 'registry=https://registry.npmjs.org/' 'audit=false' 'fund=false' > "${npmrc}" - test "$(node --version)" = 'v22.16.0' + test "$(node --version)" = 'v22.18.0' test "$(uname -m)" = 'x86_64' # The trusted lock and these independent receipts pin both the thin @@ -398,7 +398,7 @@ jobs: if ( lock.lockfileVersion !== 3 || lock.packages?.['']?.dependencies?.['@anthropic-ai/claude-code'] !== '2.1.214' || - lock.packages?.['']?.engines?.node !== '22.16.0' + lock.packages?.['']?.engines?.node !== '22.18.0' ) { throw new Error('Claude runtime lock root is not exact'); } @@ -506,7 +506,7 @@ jobs: install -m 0600 .github/gitnexus-review-runtime/package.json "${runtime_dir}/package.json" install -m 0600 .github/gitnexus-review-runtime/package-lock.json "${runtime_dir}/package-lock.json" printf '%s\n' 'registry=https://registry.npmjs.org/' 'audit=false' 'fund=false' > "${npmrc}" - test "$(node --version)" = 'v22.16.0' + test "$(node --version)" = 'v22.18.0' npm ci \ --prefix "${runtime_dir}" \ --userconfig "${npmrc}" \ @@ -1241,7 +1241,7 @@ jobs: CLAUDE_CONFIG_DIR: ${{ runner.temp }}/gitnexus-review-claude-config CLAUDE_WORKING_DIR: ${{ runner.temp }}/gitnexus-review-control NPM_CONFIG_IGNORE_SCRIPTS: 'true' - NODE_VERSION: '22.16.0' + NODE_VERSION: '22.18.0' with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} path_to_claude_code_executable: ${{ runner.temp }}/gitnexus-review-claude-runtime/node_modules/@anthropic-ai/claude-code/bin/claude.exe diff --git a/.github/workflows/gitnexus-skill-evolution.yml b/.github/workflows/gitnexus-skill-evolution.yml index 66e87ad18..8d9454d56 100644 --- a/.github/workflows/gitnexus-skill-evolution.yml +++ b/.github/workflows/gitnexus-skill-evolution.yml @@ -110,7 +110,7 @@ jobs: - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: - node-version: '22.16.0' + node-version: '22.18.0' cache: npm cache-dependency-path: | gitnexus/package-lock.json diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e9922cf19..4e9e17369 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,7 +13,7 @@ This project uses the [PolyForm Noncommercial License 1.0.0](https://polyformpro ## Development setup -**Prerequisites:** Node.js — `gitnexus/` requires `>=22.0.0` and `gitnexus-web/` requires `^20.19.0 || >=22.12.0` (enforced via the `engines` field in each package). Use `nvm install` to match the local version. +**Prerequisites:** Node.js — `gitnexus/` requires `^22.18.0 || >=24.11.0` and `gitnexus-web/` requires `^20.19.0 || >=22.12.0` (enforced via the `engines` field in each package). Use `nvm install` to match the local version. 1. Clone the repository. 2. **Shared package:** `cd gitnexus-shared && npm install && npm run build` diff --git a/gitnexus/test/unit/review-agent-workflow.test.ts b/gitnexus/test/unit/review-agent-workflow.test.ts index faf9513d6..35657e6ea 100644 --- a/gitnexus/test/unit/review-agent-workflow.test.ts +++ b/gitnexus/test/unit/review-agent-workflow.test.ts @@ -589,12 +589,12 @@ describe('gitnexus review-agent workflow security contract', () => { } expect(runtimePackage.dependencies?.gitnexus).toBe('1.6.9'); - expect(runtimePackage.engines?.node).toBe('22.16.0'); + expect(runtimePackage.engines?.node).toBe('22.18.0'); expect(runtimeLock.packages?.['node_modules/gitnexus']?.version).toBe('1.6.9'); expect(runtimeLock.packages?.['node_modules/gitnexus']?.integrity).toMatch(/^sha512-/); expect(workflow).not.toMatch(/gitnexus@(latest|next|beta)/); - expect(workflow).toContain("node-version: '22.16.0'"); - expect(workflow).toContain('test "$(node --version)" = \'v22.16.0\''); + expect(workflow).toContain("node-version: '22.18.0'"); + expect(workflow).toContain('test "$(node --version)" = \'v22.18.0\''); expect(workflow).toContain('npm ci'); expect(workflow).not.toContain('--package-lock=false'); expect(workflow).toContain( @@ -682,7 +682,7 @@ describe('gitnexus review-agent workflow security contract', () => { '${{ runner.temp }}/gitnexus-review-claude-runtime/node_modules/@anthropic-ai/claude-code/bin/claude.exe'; expect(claudeRuntimePackage.dependencies?.['@anthropic-ai/claude-code']).toBe('2.1.214'); - expect(claudeRuntimePackage.engines?.node).toBe('22.16.0'); + expect(claudeRuntimePackage.engines?.node).toBe('22.18.0'); expect(claudeRuntimeLock.lockfileVersion).toBe(3); expect(claudeRuntimeLock.packages?.['node_modules/@anthropic-ai/claude-code']).toMatchObject({ version: '2.1.214', @@ -1119,7 +1119,7 @@ describe('gitnexus review-agent workflow security contract', () => { 'CLAUDE_CONFIG_DIR: ${{ runner.temp }}/gitnexus-review-claude-config', ); expect(analyze).toContain('CLAUDE_WORKING_DIR: ${{ runner.temp }}/gitnexus-review-control'); - expect(analyze).toContain("NODE_VERSION: '22.16.0'"); + expect(analyze).toContain("NODE_VERSION: '22.18.0'"); expect(analyze).toContain('checkout-index --all --force'); expect(analyze).toContain('find "${review_dir}" -type l -print0'); expect(analyze).toContain('Escaping copied review symlink');