feat(kernel): R3 — TS/JS equivalence gate passed, kernel default-on

Gate evidence (docs/design/rust-kernel-migration-plan.md §4b):

- Graph parity, byte-identical (stronger than the §5 ≤0.5% bar): full
  codegraph-init dump-diffs kernel-vs-wasm on express (13,712 rows),
  excalidraw (89,898), and vscode (2,378,238 rows) — identical bytes.
  Python control repo (flask) identical + timing unchanged. The parity
  harness is now ORDER-sensitive (emission order drives rowids, which
  drive resolution order) and dumps come from the new
  scripts/dump-graph.mjs (natural keys, no rowids/timestamps).

- The one real find, caught by the vscode tier: tree-sitter error
  RECOVERY is encoding-dependent — byte-identical grammar sources and
  the same core (0.25.10) recover erroring files differently under
  UTF-8 (native) vs UTF-16 (web-tree-sitter) parsing; proven by
  reproducing the wasm tree with a native UTF-16 parse. Policy: the
  kernel defers any file whose tree has_error() to the wasm extractor
  (silent 'defer:' signal, per file) — parity by construction on
  erroring files (incidence 0-0.42% across the gate repos), and the
  harness fails if deferrals exceed 10% so a broken kernel can't hide
  behind the fallback.

- Retrieval invariants: canonical excalidraw flow (mutateElement →
  renderStaticScene) connects end-to-end on the kernel-indexed graph;
  synthesized-edge families present. Agent A/B is vacuous under
  byte-identical DBs (same justification as #1320-#1322).

- Perf: vscode init 105.4s → 82.1s (1.28×) on an 11-core Mac;
  excalidraw on a 2-CPU/6GB Linux container (the CI-runner envelope)
  6.2-7.1s → 4.3-4.8s (~1.5×). Linux arm64 in-container build: all 22
  kernel tests green under CODEGRAPH_KERNEL_EXPECT=1. Windows VM leg
  deferred (VM stopped; prlctl start needs Parallels Pro) — benign: a
  missing .node falls back to wasm, and the release matrix builds and
  gates the win32 prebuilds.

- Full suite: 2,465 tests pass WITH default-on routing, so the entire
  extraction corpus now exercises the kernel for TS/JS wherever a
  .node is staged.

DEFAULT_ROUTED = {typescript, tsx, javascript, jsx}. Override:
CODEGRAPH_KERNEL_LANGS (replaces the set) / CODEGRAPH_KERNEL=0 (kill).
Changelog entry added under [Unreleased].

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Colby McHenry
2026-07-16 22:50:02 -05:00
co-authored by Claude Fable 5
parent 9ad5cd7ba2
commit c8cca9a601
9 changed files with 202 additions and 20 deletions
+20 -7
View File
@@ -7,9 +7,11 @@
* everything else stays on the wasm path forever if need be. Rollback per
* language = removing it from DEFAULT_ROUTED (or CODEGRAPH_KERNEL=0 for all).
*
* R1 status: NO language is default-routed yet. Development/testing opt-in:
* CODEGRAPH_KERNEL_LANGS=typescript,tsx (or "all" for every kernel-capable
* language). R3 flips TS/JS into DEFAULT_ROUTED once the gate passes.
* Routing status: TypeScript/TSX/JavaScript/JSX are default-routed (R3 gate
* passed 2026-07-16 — full-index dumps byte-identical on express/excalidraw/
* vscode, control repo unchanged; see the migration plan §4a). Override with
* CODEGRAPH_KERNEL_LANGS=<langs|all> (replaces the default set), or
* CODEGRAPH_KERNEL=0 (kill switch, everything → wasm).
*/
import type { ExtractionResult, Language } from '../../types';
@@ -22,8 +24,16 @@ export { decodeExtractBuffers } from './decode';
/**
* Languages routed to the kernel by default (gate-passed only — see the
* per-language tracker in docs/design/rust-kernel-migration-plan.md §4).
* Per-file safety valve regardless of routing: a file whose parse tree
* contains ERRORS defers to the wasm extractor (error recovery differs
* between UTF-8 and UTF-16 parsing — wasm's recovery is canonical).
*/
const DEFAULT_ROUTED: ReadonlySet<Language> = new Set<Language>([]);
const DEFAULT_ROUTED: ReadonlySet<Language> = new Set<Language>([
'typescript',
'tsx',
'javascript',
'jsx',
]);
/**
* Per-language TS post-pass over the decoded result — the escape hatch for
@@ -82,12 +92,15 @@ export function tryKernelExtract(
result.durationMs = Date.now() - t0;
return result;
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
// `defer:` is the kernel's expected-routing signal (files with parse
// errors take the wasm path — its error RECOVERY is the canonical one;
// recovery differs between UTF-8 and UTF-16 parsing). Silent by design.
if (message.includes('defer:')) return null;
if (!warned.has(language)) {
warned.add(language);
process.stderr.write(
`[codegraph-kernel] ${language} extraction failed (${
err instanceof Error ? err.message : String(err)
}) — falling back to the wasm path\n`
`[codegraph-kernel] ${language} extraction failed (${message}) — falling back to the wasm path\n`
);
}
return null;