fix(graph): stop graph-on-stop hook crashing when tree-sitter is absent#319
fix(graph): stop graph-on-stop hook crashing when tree-sitter is absent#319efenocchi wants to merge 2 commits into
Conversation
The graph-on-stop Stop/SessionEnd hook statically imported the tree-sitter
extractor chain (runBuildCommand -> extract/index -> import Parser from
"tree-sitter"). esbuild hoisted the external tree-sitter import to the top of
the bundle, so Node resolved it at module load -- before main()'s try/catch --
and on an install without the optional native grammar (e.g. codex/cursor with
no embed-deps) the hook aborted with ERR_MODULE_NOT_FOUND and exit code 1.
Defer the build path behind the gate via a lazy dynamic import, and build
graph-on-stop as its own code-split bundle so the tree-sitter statics live in a
lazily loaded chunk instead of the entry. A missing grammar now degrades to a
logged skip + exit 0, honoring the hook's "never break the session" contract.
tree-sitter is an optionalDependency, so graceful degradation is by design.
- src/hooks/graph-on-stop.ts: lazy `await import("../commands/graph.js")`
behind the gate, inside the existing try/catch.
- esbuild.config.mjs: buildGraphOnStop() builds the hook with splitting so the
dynamic import stays a runtime chunk load; clears stale hashed chunks first;
removed graph-on-stop from the four shared harness build lists.
- tests: unit seam for the reject path + a bundle-level guard asserting the
shipped entry has no static tree-sitter import and loads it only via
graph-chunks/.
Verified end to end: the pre-fix bundle exits 1 with ERR_MODULE_NOT_FOUND when
tree-sitter is absent; the fixed bundle exits 0 (graceful) in the same setup
and still builds the graph normally when tree-sitter is present.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughGraph-on-stop is packaged separately for each harness with code-split graph chunks and deferred tree-sitter loading. The hook also lazily imports the graph command during build execution, while regression tests cover bundle structure and missing-dependency handling. ChangesGraph-on-stop isolation
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/shared/graph/graph-on-stop-bundle.test.ts`:
- Around line 28-37: Update the graph-on-stop bundle setup around HARNESSES and
built so every harness is required to have its expected graph-on-stop.js bundle;
remove the filtering that silently drops missing entries and assert the specific
expected bundle paths exist for all four harnesses. Keep the per-harness checks
operating on the complete HARNESSES set.
In `@tests/shared/graph/graph-on-stop-main.test.ts`:
- Around line 137-140: Update the logging assertion in the graph-on-stop test to
require the .graph-on-stop.log file and read it unconditionally, removing the
existsSync guard. Assert the specific expected “build threw” log message so
missing or incorrect logging fails the regression test.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 912f3c2a-dc66-4851-b8ba-c0215f9d4943
📒 Files selected for processing (4)
esbuild.config.mjssrc/hooks/graph-on-stop.tstests/shared/graph/graph-on-stop-bundle.test.tstests/shared/graph/graph-on-stop-main.test.ts
- bundle guard: require ALL four harness bundles (assert the exact harness set) instead of filtering to whichever exist, so a per-harness packaging regression can't pass unnoticed. - main test: assert the .graph-on-stop.log exists and contains the specific "build threw: Cannot find package 'tree-sitter'" message unconditionally, rather than skipping the check when the file is absent.
|
Closing: this branch was based on a stale main (v0.7.106, ~302 commits behind). The tree-sitter graph-on-stop crash still exists on current main and is being fixed in a fresh PR branched off up-to-date origin/main (with the openclaw ClawHub define adjustment that the stale base was missing). Superseded. |
Problem
The
graph-on-stopStop/SessionEnd hook crashed with exit code 1 on installs where the optionaltree-sitternative grammar is absent (e.g. codex / cursor with noembed-deps):Root cause: the hook's build path is a chain of static ESM imports —
runBuildCommand→extract/index→import Parser from "tree-sitter". esbuild hoisted the externaltree-sitterimport to the top of the bundle, so Node resolved it at module load — beforemain()'stry/catchruns.main().catch(() => process.exit(0))never fired, so the process exited 1 instead of degrading.tree-sitteris anoptionalDependency, so it is allowed to be absent.Fix
src/hooks/graph-on-stop.ts— defer the build path behind the gate via a lazyawait import("../commands/graph.js")inside the existingtry/catch. A missing extractor now degrades to a logged skip + exit 0.esbuild.config.mjs— a source-level lazy import alone isn't enough (esbuild inlines it and re-hoists the external), sograph-on-stopis now built in its ownsplitting: truebundle viabuildGraphOnStop(). The dynamic import stays a real runtime chunk load and thetree-sitterstatics live only ingraph-chunks/. Also clears stale hashed chunks before each build and removesgraph-on-stopfrom the four shared harness build lists (claude-code, codex, cursor, hermes).graph-on-stop-bundle.test.ts) asserting the shipped entry has no statictree-sitterimport and loads it only viagraph-chunks/. The guard fails ifsplittingis ever dropped — the exact regression.Verification
Reproduced before / after on the real bundle, same scenario (git repo, gate fires,
tree-sitterunresolvable):ERR_MODULE_NOT_FOUND: Cannot find package 'tree-sitter'build threw: Cannot find package 'tree-sitter', session unbrokencodex-hooks.test.ts→plugin.jsonarrays) is pre-existing and unrelated (a WIPplugin.jsonchange onmain), not touched here.Session Context
Session transcript
Summary by CodeRabbit