fix(cli): steer docs, skills, and hooks through a CLI-neutral project-local runner (#1939)#1945
Conversation
Prefer global gitnexus or pnpm dlx in hooks and generated AI context, warn when npm 11.x would use the broken npx path, and document workarounds for the arborist node.target null failure mode. Co-authored-by: Cursor <cursoragent@cursor.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
CI Report✅ All checks passed Pipeline Status
Test Results
✅ All 10850 tests passed 11 test(s) skipped — expand for details
Code CoverageTests
📋 View full run · Generated by CI |
magyargergo
left a comment
There was a problem hiding this comment.
PR Tri-Review — #1945 fix(cli): steer npm 11 users away from npx install crash
Verdict: not production-ready · Merge state: checks failing · Branch hygiene: clean feature/fix PR (single commit, no merge-from-main).
Methods & engines (read first). This was a two-method, both-Claude review: the GitNexus swarm (risk-architect, test/CI-verifier) + Compound-Engineering personas (correctness, adversarial, maintainability) — five lanes, but all the same engine. The Codex lane (the only independent engine) was dispatched, but its background job never registered/returned, so there is no independent-engine corroboration here; treat cross-lane agreement as "consistent across personas," not independent confirmation. The coordinator independently reproduced the blocking findings.
Headline (blocking — P0): the PR turns CI red on all three OS runners
test/unit/setup-antigravity.test.ts has 3 failing tests (AfterTool emits stale-index hint…, ignores unknown tool names without crashing, does not crash on empty stdin). Reproduced locally: npx vitest run test/unit/setup-antigravity.test.ts → 3 failed | 14 passed. The antigravity hook's new top-level require('./resolve-analyze-cmd.cjs') (gitnexus-antigravity-hook.cjs:28) is unsatisfied — the source hooks/antigravity/ dir doesn't contain the helper and the test's stageAdapter() doesn't copy it — so the staged adapter crashes with MODULE_NOT_FOUND. The 4 sibling adapter tests that still pass only assert stdout.trim()==='' (setup-antigravity.test.ts:339–452), which a crash also satisfies, so the suite under-reports its own breakage. (See inline comment.)
Other inline findings
- [P2] Module-load side effect on every CLI start (incl.
gitnexus mcp).warnIfNpm11NpxRisk()runs atindex.ts:14top level, spawningwhich/where(+npm --version) — up to 3 synchronous 5s-timeout subprocesses — before command dispatch. Reproduced:GITNEXUS_INVOCATION=npx node dist/cli/index.js --versionemits the warning. Re-adds load-time work to themcppath the file header says was optimized, and to the high-frequencyaugmenthook. Adversarial refuted the scarier variant: the write is stderr-only, so JSON-RPC/stdout is not corrupted. - [P2] Version pinning is inconsistent and largely illusory. The plugin copy hardcodes
gitnexus@latest(gitnexus-claude-plugin/hooks/resolve-analyze-cmd.cjs:8) while the TS/in-repo copies pingitnexus@<version>; and the in-repo.cjs'spackage.jsonread resolves to a non-existent path oncesetup.tscopies it to~/.claude/hooks/gitnexus/, so it silently falls back tolatestin production too. The "Keep in sync" comment is already false, and a@lateststale-index hint can re-suggest the npx path #1939 steers users away from. (Consistent across risk + correctness + maintainability — same engine.)
Notable, lower-priority (body only)
- [P2]
ai-context.ts:131bakes machine-local resolution into git-tracked docs.formatAnalyzeCommand()resolves on the analyzing machine and the result is written into the committedAGENTS.md/CLAUDE.mdstale-index hint (verified: both tracked; the default regeneration path rewrites that line). Teammates on a different setup get a wrong command, and the pinned version churns the tracked files on every analyze/version-bump — the same volatile-content churn class as #1706 (symbol-count churn in committed AI-context files; now closed). Single-lane (correctness) + coordinator-verified. - [P3] The runtime npm-11 warning may never reach its audience. #1939 crashes during
npxinstall (before gitnexus runs); a successfulnpxinstall puts gitnexus on PATH, soresolveInvocationMode()returnsgitnexusand the warning is gated off (resolve-invocation.ts:94). README/install guidance is the effective channel. - Test gaps. No assertion that the Claude install path copies
resolve-analyze-cmd.cjs, and that copy is silently swallowed (setup.ts:400–407, emptycatch);warnIfNpm11NpxRisksuppression branches (mode≠npx, npm<11, npm=null) untested and the module-levelnpm11Warnedflag (resolve-invocation.ts:23) is never reset (order-dependent); no parity test across the 3 resolver copies; the Windows.cmd/.batwrapper branch isn't in the cross-platform matrix. - [P3] Windows
.exe-only shims (Volta/scoop) aren't matched by the.cmd/.batfilter → suboptimal (not broken) hint. [P3]resolve-invocation.ts:13throws at module load ifpackage.json#versionis missing — unreachable in normaltscpackaging (refuted as a live crash) but a behavior change vs. the graceful CJSlatestfallback.
Credit (validated by the review)
env-var parsing/precedence correct; getNpmMajorVersion() null-safe (handles garbage/prerelease); CRLF trimmed per line; the hook-test-helpers env-merge is correct and in fact required for forced-mode children; quality / typecheck / lint / format + packaged install smoke all green. The preference chain (global → pnpm dlx → pinned npx) is a sound design.
CI: CI Gate + tests (ubuntu/macos/windows) failing (the P0 above); all other checks pass.
Coverage limit: the lanes and I read the changed-path suites and the new module; the full ~2000-test suite was not run, so an unrelated flake elsewhere isn't excluded — but every test touching the changed code is accounted for, and the 3 failures are the only PR-caused CI failures.
Automated multi-tool digest (two Claude methods; Codex unavailable). Verify each item before acting.
…arden load checks
The antigravity adapter gained a top-level require('./resolve-analyze-cmd.cjs')
but stageAdapter() did not copy it, so the spawned adapter crashed with
MODULE_NOT_FOUND. Three load-sensitive tests failed; four silent-path tests
false-passed on empty stdout.
Stage the helper alongside the other sibling helpers, and assert status===0 and
no MODULE_NOT_FOUND on the four silent-path tests so a non-loading hook can never
pass green again. Force a deterministic invocation mode in the stale-index test
so the emitted analyze command no longer varies by CI-runner PATH.
Co-authored-by: Cursor <cursoragent@cursor.com>
…rce CJS helper NPX_REF becomes a literal `gitnexus@latest` in resolve-invocation.ts, dropping the package.json require and the module-load throw (a malformed/absent version can no longer crash any CLI command at import). The safety this PR delivers is the install method steered to (global / pnpm dlx), not a pinned gitnexus version, and the in-repo CJS mirror already degraded to `latest` once copied outside the package. Make the two resolve-analyze-cmd.cjs copies byte-identical and add a parity test that fails on drift. The separate, version-pinned NPX_REF that setup.ts writes into the MCP server registration is intentional and left unchanged. Co-authored-by: Cursor <cursoragent@cursor.com>
…n mode warnIfNpm11NpxRisk() ran at index.ts module load, so every CLI invocation (including the `gitnexus mcp` stdio hot path) paid which/where + npm --version spawns — against the lazy-startup/MCP-stdout discipline (#207, #1383). Move the call into analyzeCommand, after the ensureHeap() re-exec guard, so it fires once in the working process and only for `analyze`. Memoize the PATH-probe-derived invocation mode (the GITNEXUS_INVOCATION override stays uncached) so repeated callers don't re-probe, and add a test-only reset so the cache + once-only warning flag don't leak across the unit suite. Covers the mode!=='npx', npm<11, and npm-absent suppression branches. Co-authored-by: Cursor <cursoragent@cursor.com>
The winGitnexusWrapper branch only matched .cmd/.bat, so a global gitnexus installed by Volta or scoop (a .exe or an extensionless shim) was missed and the hint fell back to pnpm/npx. Accept .exe and treat any non-empty `where` hit as on-PATH (the emitted hint is `gitnexus analyze` regardless of which shim resolves it). Mirror the change into both resolve-analyze-cmd.cjs copies so the TS source and the byte-identical hook mirrors stay in sync. Add Windows-mocked test cases (.exe-only, extensionless, .cmd preference, CRLF stripping) and register resolve-invocation.test.ts in cross-platform-tests.ts so the windows-latest runner exercises the branch. Co-authored-by: Cursor <cursoragent@cursor.com>
…CLAUDE.md ai-context baked a machine-resolved command (formatAnalyzeCommand) into git-tracked AGENTS.md/CLAUDE.md, so the stale-index hint varied per machine and churned across branches (the #1706 class). Emit the fixed string `pnpm dlx gitnexus@latest analyze` instead: committed AI-context is the most authoritative instruction an agent reads, so it must name an install-free, crash-free method — never `npx`, the npm-11 path #1939 steers away from. formatAnalyzeCommand stays exported and unit-tested in resolve-invocation.ts (it still mirrors the two .cjs hook copies); ai-context just no longer calls it. Co-authored-by: Cursor <cursoragent@cursor.com>
installClaudeCodeHooks copied its four hook helpers in separate try/catch blocks that silently swallowed failures, while installAntigravityHooks recorded an error per failed copy. Extract one copyHookHelpers(srcDir, destDir, label, result) with a single canonical helper list (including resolve-analyze-cmd.cjs) and the antigravity loop's error-reporting policy, and use it from both paths so a missing helper surfaces as a setup error instead of a silent runtime crash. Assert both the Claude and Antigravity install paths co-locate resolve-analyze-cmd.cjs next to the adapter, and that a failed copy records an error rather than passing silently. Co-authored-by: Cursor <cursoragent@cursor.com>
The extracted HOOK_HELPERS/copyHookHelpers block landed between the installClaudeCodeHooks JSDoc and its function, leaving the doc reading as if it described the helper list. Move the block above the doc so it documents the function again. No behavior change. Co-authored-by: Cursor <cursoragent@cursor.com>
…osture Tier-2 review found two in-scope gaps in the #1945 follow-up: - The "mirrors resolve-invocation.ts / test enforces parity" comments overclaimed: the parity test only compared the two .cjs copies to each other, so the TS source and the CJS hook copies could silently drift (NPX_REF, the per-mode command, and the Windows shim regex were hand-edited in all three this PR). Add TS<->CJS value parity (NPX_REF + formatAnalyzeCommand for every forced mode) and a source-level shim-regex parity check, and make the mirror comments accurately describe what is enforced. - No test locked the R3/R4 startup posture, so re-adding warnIfNpm11NpxRisk() (or any resolve-invocation import) at index.ts module scope -- the #207/#1383 lazy-startup regression -- would pass CI. Add a guard asserting index.ts has no module-load invocation probe and the warning is wired into analyzeCommand. Co-authored-by: Cursor <cursoragent@cursor.com>
PR #1945 carried the gitnexus/pnpm/npx selection in three hand-synced places — the canonical hook helper, its byte-identical plugin copy, and a full TypeScript re-implementation in resolve-invocation.ts — kept in lockstep by per-mode-command and regex-extracted-by-regex parity tests. The TS formatAnalyzeCommand had no production caller (ai-context emits a fixed string), and the module memoized + exposed a test-only reset for a "repeated callers" case that has exactly one caller. Make hooks/claude/resolve-analyze-cmd.cjs the single source: extract the Windows-shim line-picking into a pure, exported pickPathMatch() and add an injectable probe to resolveInvocationMode() so the shipped logic is testable without spawning or global mocks. resolve-invocation.ts (118 -> 59 lines) now consumes that cjs via createRequire for resolveInvocationMode/NPX_REF and adds only the CLI-only npm-version probe and warning; the relative path resolves identically from src/cli/ (tsx, vitest) and dist/cli/ (shipped, hooks/ is a published sibling of dist/). Tests exercise the real shipped artifact, the NPX_REF/mode-command parity scaffolding is dropped (one implementation can't drift), and parity narrows to the two cjs copies staying byte-identical. No behavior change: hook stale-index hints and the analyze warning are byte-identical; the pre-existing setup.ts resolveGitnexusBin is untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
magyargergo
left a comment
There was a problem hiding this comment.
PR Tri-Review — #1945 fix(cli): steer npm 11 users away from npx install crash
Final verdict: production-ready with minor follow-ups. No blocking defects. Two P2 follow-ups (both squarely in the PR's own theme) plus minor test/doc nits. Branch hygiene: clean feature/fix branch. Merge state: CI green on all 3 OS — BLOCKED only on required-review approval.
Methods & engines (read first). Genuine three-method review: Codex (the one independent engine — live this run via the GitHub connector), the GitNexus swarm (risk-architect, security-boundary; the test/CI lane ended mid-investigation, its domain covered by the testing reviewer), and Compound-Engineering personas (correctness, adversarial, maintainability, testing). 2 of the 3 methods are Claude under different prompts, so Claude-only agreement is "consistent across personas," not independent confirmation — only Codex+Claude agreement is weighted strong.
What's solid (validated, not assumed):
- The refactor's riskiest move —
createRequire('../../hooks/claude/resolve-analyze-cmd.cjs')from the CLI (resolve-invocation.ts) — resolves in the published package, confirmed by Codex + 3 Claude lanes:package.jsonfiles:["dist","hooks"],bin:"dist/cli/index.js", and../../is identical fromsrc/cli/anddist/cli/. - No injection / trust-boundary issue:
execFileSyncuses fixed argv (no shell),GITNEXUS_INVOCATIONis allowlisted, the warning interpolates only a parsed int. - The two
resolve-analyze-cmd.cjscopies (gitnexus/hooks/claude/andgitnexus-claude-plugin/hooks/) are byte-identical (Codex: same git blob SHA; enforced by the parity test ingitnexus/test/unit/resolve-invocation.test.ts). - The prior review's two P0s are confirmed fixed: the antigravity-hook
MODULE_NOT_FOUND(helper now inHOOK_HELPERS) and theindex.tsmodule-load PATH probe (warning moved intoanalyzeCommand; posture-guard test added).
Inline findings (3):
- [P2] Generated guidance still funnels group repos into
npx.ai-context.ts:170(Cross-Repo Groups block) emitsnpx gitnexus group list/sync/impact, untouched by this PR — so a group-enabled repo's generated AGENTS.md/CLAUDE.md still steers npm-11 users into the exact arborist crash this PR fixes. (Codex — independent engine.) - [P2] Stale-index hook now spawns
which/whereunder a 10s budget. The PostToolUse hint was a pure string (0 spawns); it now callsformatAnalyzeCommand()→ 1–2 PATH probes (timeout:5000ms each) on top ofgit rev-parse(3s), under the hook'stimeout:10s. Worst case ≈ 3+5+5 = 13s > 10s → the nudge is killed mid-run. (risk + adversarial.) - [P3] Dead
NPX_REF/PKG_VERSION+ loose version regex in the e2e tests. Both unused; the cjs always emits@latest, sotoContain('npx gitnexus@latest analyze')is exact and stronger than/@\S+/. (maintainability + testing + risk — 4 lanes.)
Lower-priority (body only):
- [P2, pre-existing] Partial-install crash:
copyHookHelpers(setup.ts:334-363) records a copy failure but the caller still registers the hook → deferredMODULE_NOT_FOUNDon first fire. Corroborated by Codex + 3 Claude lanes; already listed as a Known Residual in the PR body — confirming it's real, and the new requiredresolve-analyze-cmd.cjswidens the blast radius by one file. (Pre-existing class; not introduced here.) - Design tradeoff: the fixed
pnpm dlx gitnexus@latest analyzein generated docs (ai-context.ts:133) strands users without pnpm (nonpxfallback shown). Deliberate per #1706, but consider a fallback hint. Relatedly, this repo's own committedCLAUDE.md:61/AGENTS.md:80still saynpx gitnexus analyze— regenerate to dogfood the fix. - Test gaps:
warnIfNpm11NpxRiskgitnexus-mode branch not exercised (test only setspnpm);getNpmMajorVersionedge inputs (empty / pre-release) untested;pickPathMatch(isWin:true, gitnexusWrapper:false)(Windows pnpm probe) untested; some e2e tests don't pinGITNEXUS_INVOCATION(host-dependent);copyHookHelperserror-count assertion hardcodes4. - Nits:
InvocationResolverTS interface omits theprobeparam;gitnexus/README.md:279pnpm dlx gitnexusmissing@latest;NPX_REFname covers all three modes, not just npx.
Refuted / not bugs: memoization removal is not a regression (only one caller, analyze.ts:624); the .ps1-only Windows shim edge is unrealistic (npm co-installs a .cmd); the createRequire fail-closed concern doesn't trigger in a correctly-published package.
Coverage: all 18 changed files reviewed; CLI/cjs/test source read in full, golden/fixture blobs skipped. CI green across ubuntu/macos/windows tests, packaged-install smoke, lint/format/typecheck.
Automated multi-tool digest — verify before acting. Two of three methods are the same engine (Claude); only Codex is independent.
The PostToolUse stale-index hint calls formatAnalyzeCommand(), which probes which/where; named PROBE_TIMEOUT_MS=2000 keeps git rev-parse (~3s) + up to two probes well under Claude Code's 10s hook timeout while preserving the machine-correct hint. Byte-identical in the plugin copy. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Cross-Repo Groups block in generated AGENTS.md/CLAUDE.md still emitted bare 'npx gitnexus group ...', funneling npm-11 users into the arborist crash; switch to fixed 'pnpm dlx gitnexus@latest group ...'. Export generateGitNexusContent and add a group-branch test asserting no 'npx gitnexus' literal survives. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
README troubleshooting uses gitnexus@latest; the repo's own committed CLAUDE.md/AGENTS.md stale-index hint now matches the generated output (pnpm dlx gitnexus@latest analyze) so the repo dogfoods the fix. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…mode (U4) Drop dead PKG_VERSION/NPX_REF version-pinned constants; the cjs always emits gitnexus@latest, so assert exact toContain(...) instead of the /@\\S+/ wildcard; pin GITNEXUS_INVOCATION in the --embeddings tests for host-independent determinism. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add coverage for the gitnexus-mode warn suppression, getNpmMajorVersion edge inputs (empty/pre-release/non-numeric), and the Windows non-wrapper pickPathMatch branch; widen the InvocationResolver interface to document the optional probe param. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
Mitigates the npm 11.x arborist
node.target is nullinstall crash (#1939) by steering every GitNexus surface — committed skills, generatedAGENTS.md/CLAUDE.md, and the editor stale-index hooks — through one CLI-neutral command instead of a hardcodednpx gitnexus.gitnexus analyzedrops a small runner at<repo>/.gitnexus/run.cjs(a copy of the canonicalhooks/claude/resolve-analyze-cmd.cjs). Docs referencenode .gitnexus/run.cjs <cmd>, which auto-selects a working runner at call time: a globalgitnexusbinary →pnpm dlx gitnexus@latest(npm 11 + pnpm) →npx gitnexus@latest. Committed docs therefore bake in no package-manager assumption and no per-machine content, and the resolver is cross-platform-correct on Windows.Fixes #1939.
Problem & approach
The crash happens inside npm/arborist during
npxinstall, before gitnexus runs, so runtime error handling cannot catch it — the only lever is steering installs toward working paths and documenting workarounds.An earlier revision of this PR hardcoded
pnpm --allow-build=… dlx gitnexus@latest <cmd>into committed docs/skills. That assumes pnpm is installed — a worse default for the npm majority just to dodge the npx crash. The final design defers the package-manager choice to call time via the project-local runner, so the committed instruction stays universal:~/.claude/helper —AGENTS.mdis the multi-CLI anchor (Cursor/Codex/Antigravity/…), so a Claude-specific path would be wrong for non-Claude readers. The runner lives next to the index, is gitignored, and is refreshed on every analyze.npx gitnexus analyze(the runner can't exist before the first analyze); the npm-11 escape hatch (npm i -g gitnexus, orpnpm … dlx) is documented there..cmd/.ps1/.exeshims through a shell on Windows (execFileSyncdoes no PATHEXT resolution and Node blocks.cmdwithout a shell — CVE-2024-27980), and print a diagnostic instead of a silentexit 1.What changed
resolve-analyze-cmd.cjs(canonical inhooks/claude/, byte-identical twin ingitnexus-claude-plugin/hooks/, parity-tested) gainsbuildRunnerArgv+ arequire.main === moduleexec tail.gitnexus analyzedrops it at.gitnexus/run.cjs; failure to copy is non-fatal (docs carry a bootstrap fallback).ai-context.tsemitsnode .gitnexus/run.cjs <cmd>(machine-independent, no version churn), kept under the#856CLAUDE.md token budget; Cross-Repo Group commands route through the runner too.gitnexus setupfails closed — it skips hook registration with an actionable error when a required helper (or adapter) is missing, rather than registering a hook thatMODULE_NOT_FOUNDs on every tool event.gitnexus/skills,.claude,gitnexus-claude-plugin,gitnexus-cursor-integration) route through the runner, guarded byskills-steering.test.ts.analyzecommand (after the heap re-exec guard), not at CLI module load, sogitnexus mcpand other commands pay no startup probe cost.Review history
This PR was hardened across several three-method tri-reviews (Codex + Compound-Engineering personas + GitNexus swarm). Findings from each round are addressed:
MODULE_NOT_FOUND(helper not staged); false-passing stdout-only tests.analyze, memoized.gitnexus@latest; the separate, version-pinned MCP-registration ref insetup.tsis intentional and unchanged (renamed toMCP_PINNED_REFto end the same-name collision).resolveOnPathrecognizes.exe/extensionless shims), hook-budget probe bounds, and repo-wide skill steering with a regression guard.Latest round (the Windows probe defect). The most recent review (Codex + adversarial, cross-engine) found that the
--versionprobes (probeVersionin the cjs,getNpmMajorVersionin the CLI) spawnednpm/pnpm --versionviaexecFileSyncwithout a shell, so on Windows the.cmdshims ENOENT'd, the probe reported a present tool as absent, and the stale-index hook recommended the exactnpxcrash command this PR exists to avoid (the runner's--allow-buildversion gate was defeated the same way). Not a regression (the pre-pivot hook was unconditionallynpx), but the headline npm-11 → pnpm steering was a no-op on the Windows hook path. Fixed:shell: process.platform === 'win32'on the version probes (mirroring the exec tail), so.cmdshims resolve on Windows.resolve-analyze-cmd.cjs(+ twin) brought under the shell-injection andwindowsHidesource-regression guards; the runner exec-tail's Windowsshellbranch now runs on thewindows-latestCI leg (was previously untested everywhere);--embeddings=N(equals form) now widens the pnpm allow-build set; a broken README troubleshooting anchor and a generated-docCannot find modulerecovery hint were fixed.Test plan
tsc --noEmitclean; prettier + typecheck pass (pre-commit) on every commit.runner-exec-tail.test.tsregistered inscripts/cross-platform-tests.ts(SPAWN_CLI) so the Windowsshellbranch runs onwindows-latest.windows-latestlegs are the real validator for the.cmd-shim resolution, which can't be exercised on a POSIX dev host).pnpm dlxguidance resolves their install crash.Known Residuals
Deliberately out of scope (tracked for follow-up), not regressions:
require.main === moduleexec tail forwardsprocess.argvthroughexecFileSyncwithshell: process.platform === 'win32', so on Windows cmd.exe would interpret& | ^in forwarded args. Safe under the PR's actual usage — generated docs/skills emit fixed subcommands; the group commands (group impact --target <symbol> --repo <path>,group sync <name>) carry argument slots, so the trust boundary is "forwarded args must not contain cmd.exe metacharacters." A deeper fix (explicit.cmdresolution) conflicts with the repo's mandatedshellidiom and has no clean in-repo primitive; the source-regression guard now locks the file soshell: truecan't be introduced.cliskill's non-analyzenpxsubcommands and the no-install-free-universal-command-on-npm-11 tradeoff remain documented as-is.Post-Deploy Monitoring & Validation
tests / windows-latestand thewindows-latestcross-platform-testsjob (runner-exec-tail+ the Windows probe path), the primary signal for the cross-platform fixes; plussetup-antigravity/hooks-e2e.gitnexus mcpstarts with no pre-protocol stderr; regeneratingAGENTS.md/CLAUDE.mdon an unchanged repo produces no diff (no machine/version churn); on npm ≥ 11 with pnpm present, the stale-index hint recommends thepnpm dlx(notnpx) form on Windows.MODULE_NOT_FOUND/Cannot find modulein hook logs → a required helper failed to copy (re-rungitnexus setup); stray stderr before MCP protocol output → a startup probe regressed; doc churn on regenerate → AI-context emitted machine-specific content again.npx gitnexusstill crashes with "node.target is null" on npm 11.x — clean cache doesn't help #1939. No data migration; no dashboards beyond CI.Made with Cursor; hardened via automated multi-engine tri-review and remediation.