Repository navigation
fix(build): fall back to WASM grammars when native tree-sitter is unavailable (#119) - #214
Frankie-Xu wants to merge 1 commit into
Conversation
🌱 graft blast radius2 areas changed → 6 areas can be affected. 20 dependent symbols, depth 2. flowchart TB
A0(("Review Process<br/>8 symbols"))
A1(("Workspace Federation<br/>5 symbols"))
A2(("Tool Invocation<br/>3 symbols"))
A3(("Graph Management<br/>2 symbols"))
A4(("build-viewer.mjs<br/>1 symbol"))
AX(("1 smaller area<br/>1 symbol"))
classDef reached fill:#D9EDF3,stroke:#3AA7C9,stroke-width:1.5px,color:#0E313C;
class A0,A1,A2,A3,A4 reached;
classDef tail fill:#EEF2F3,stroke:#9AA4A9,stroke-width:1px,color:#3A4247;
class AX tail;
Who knows this code — 6 people across 8 areas
Ownership is git history over each area's own files, weighted towards recent work (120-day half-life). Merge commits and bots are dropped, and you are dropped from your own PR. A name with no All 20 dependent symbols, grouped by areaReview Process — 8 symbols in 6 files
Workspace Federation — 5 symbols in 3 files
Tool Invocation — 3 symbols in 1 file
Graph Management — 2 symbols in 1 file
build-viewer.mjs — 1 symbol in 1 file
Sync Execution — 1 symbol in 1 file
Test signal per changed area — 1 ✓ · 1 –Reached = a node under a test path has a resolved edge into the changed symbol. It undercounts anything called indirectly — through a CLI, a spawned process or a dynamic import — so read a low ratio as “look here”, never as a coverage gate.
37 test suites also reference this code48 symbols, kept out of the diagram and the table so they cannot crowd out the areas a reviewer has to look at.
Open the interactive graph → — click an area to see the code that changed, and the line that reaches it. |
|
Rebased onto current main. Kept |
597e2ae to
de29268
Compare
…vailable (trailhq#119) linux/arm64 has no tree-sitter@0.21.1 prebuild, so require() crashed every CLI command. Catch the native load, extract depth languages via the existing WASM path, and warn about reduced binding fidelity. Darwin/linux-x64 native behavior is unchanged. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Rebased onto current main. CI is green — please review when you can. |
… depth language (trailhq#337 trailhq#217 trailhq#214 trailhq#325) Four PRs were rewriting the same code path in extract.ts — one function now does what they each asked for: - Lazy loading (trailhq#217): a grammar (and the core tree-sitter binding itself) is required at most once, the first time entryFor()/depthExtensions() is asked about that language, not for all nine at module-import time. `graft mcp` never asks before the client's `initialize` reply, so a client can no longer see that handshake stall behind nine native loads. - Per-language isolation (trailhq#337, unchanged): a grammar that will not load costs its own language, not the CLI. - WASM fallback for every depth language, not just Kotlin/Java (trailhq#214): the breadth tier already had a "FALLBACK row" mechanism (a GENERIC_LANGS row reachable only when the matching depth grammar failed); tree-sitter-wasm ships a .wasm for all nine depth languages already, so the remaining seven now have one too. None has a queries/<name>.scm, so on the rare machine that actually reaches one it degrades to the node-kind walker (symbols only) instead of leaving the language unindexed. - optionalDependencies (trailhq#325's core ask): the eight native grammar packages moved out of dependencies, so a platform lacking a prebuild for one no longer fails `npm install` for the other eight (core tree-sitter stays required — a missing core is a bigger question than one language, left for a follow-up). New test: `graft mcp` answers `initialize` with tree-sitter-typescript broken and never touches grammar loading at all (no warning on stderr) — the concrete claim trailhq#217 exists for. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Thanks for this! We tested it against a mixed TS/Python/Kotlin repo. With a single grammar broken it falls back to WASM with no warning at all: Python silently dropped from 11 to 9 edges. After the grammar is restored, the extract cache keeps replaying the fallback parse, so |
Summary
graft init/graft buildno longer crash on linux/arm64 whentree-sitter@0.21.1has no native prebuild.require("tree-sitter")fails, depth languages (TypeScript/JavaScript, Python, Go, Java, Kotlin, PHP, R) extract through the existing WASM breadth path.native parser unavailable — falling back to WASM (reduced binding fidelity).graft checkand the statusline do not treat that as an error.Closes #119.
Root cause
Failure is at
require("tree-sitter")on CLI load, notnpm installand notscripts/postinstall.mjs(that script is a one-line nudge and never throws).tree-sitter@0.21.1ships prebuilds for darwin-arm64/x64, linux-x64, and win32-x64 only — no linux-arm64. With install scripts blocked, install succeeds and every command then dies withNo native build was found for platform=linux arch=arm64.Bumping to
tree-sitter@0.25(#40) would pick up linux-arm64 prebuilds, but that PR is still OPEN, CONFLICTING, last Ubuntu CI failed, and Alpine/musl / “no compiler” would still lose. Mixing0.25with today’stree-sitter-typescript@0.23.2is not a small bump.Fidelity (not papered over)
WASM fallback has no
bindings/ receiver-type resolution. Call edges come fromtags.scmwhen the query compiles (symbols only if it does not). Depth extensions stay owned bylanguageOf;genericLangOfstill does not claim.ts/.py/.go/etc., so darwin/linux-x64 native extraction is unchanged.Tests
test/native-fallback.test.ts: mock native throw → empty grammars;{ wasm: true }still emits function nodes withorigin: "generic"; default path on darwin staysorigin: "ast"andwarnings: [];graft checkstays OK.npm teston darwin: 919 pass. The 2 failures (PageRanktiming,viz --tabsmissing a local graph) are unrelated flakes/environment.Docker evidence (linux/arm64, Node 22)
tree-sitter@0.21.1 --ignore-scriptsthenrequire("tree-sitter"):Prebuilds in the tarball:
darwin-arm64,darwin-x64,linux-x64,win32-x64— nolinux-arm64.After this change,
graft buildof a tinyhello.ts(hello()→world()):Nodes are
origin: generic(hello.ts,hello.ts#hello,hello.ts#world).Made with Cursor