mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-03 02:21:44 +00:00
* feat(zig): static-gating analysis module + fixture (ported from feat/zig-static-gated-edges-v2) Squashes c6fe922c, 2f3c8e9e, fab088f4, 9b58af74, aef2ae83, 86b892ef, d5657861, f3780b3a: file-local comptime bool constants, cross-file flag resolution via the @import alias map, re-aliased const chains, == / != against known bools, else / else-if branch awareness. The module is self-contained; the hooks that call it land in the next commit. * feat(zig): stamp static-gated call sites through the scope pipeline Wires the ported gating module into the scope-resolution pipeline that now emits every Zig CALLS edge (PR #1432), replacing the parse-worker / call-processor hooks of the original branch, which targeted the legacy DAG path the merged provider no longer uses. Data flow, one new fact carried end to end: emitZigScopeCaptures stamps `@reference.static-gated` on a call capture whose anchor lies in a statically dead range (body of `if (CONST_FALSE)`, else of `if (CONST_TRUE)`), via the module's new `collectZigStaticGatedRanges` (line/col ranges, because a Capture keeps no node) scope-extractor marker -> `ReferenceSite.staticGated` buildReference -> `Reference.staticGated` references-to-edges, -> `GraphRelationship.staticGated` on the free-call-fallback, emitted CALLS edge (both emit paths, plus edges.ts (tryEmitEdge*) the generic bridge) local-backend impact -> `staticGated` on impact frontier edges Same marker idiom as Go's `@reference.callee-position` / `embedded-pointer`: zero-range, present or absent, so every ungated site's capture set is byte-identical and no other language changes. SCHEMA_BUMP 92 -> 93: parse-time captures changed. Cross-file constants (`if (cfg.FOO)` with `cfg = @import("cfg.zig")`) are NOT stamped yet: the module resolves them through `lookupBoolsForPath`, but the capture emitter runs per file in the parse worker with only `{ path, content }`, so it cannot see the sibling source. The two positive cross-file cases in zig-static-gating.test.ts are `it.skip` with that reason; the negative ones pass unchanged. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015ciQ3MTjpQXkCoNntZR9zG * feat(graph): add staticGated edge property Adds an optional `staticGated?: boolean` field to `GraphRelationship` that flags edges originating in code branches known at index time to be unreachable in production — e.g. `if (CONST_FALSE)` blocks where the condition reduces to a comptime-known `false`. Schema + persistence wiring: - `gitnexus-shared/src/graph/types.ts` — additive optional field on `GraphRelationship`; absent edges read identically to live ones. - `gitnexus/src/core/lbug/schema.ts` — `staticGated BOOLEAN` column on the `CodeRelation` REL table. - `gitnexus/src/core/lbug/csv-generator.ts` — appends a `staticGated` column (0/1) to the `relations.csv` written for bulk COPY ingest. - `gitnexus/src/core/lbug/lbug-adapter.ts` — fallback per-row `MATCH ... CREATE` insert reads the optional column and threads it into the relationship properties. No language has populated this field yet — the Zig hookup lands in the next commit. Existing DBs need a re-index for the new column to appear; existing readers are unchanged because the field is optional and absent on every other language's edges. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> (cherry picked from commit c8cd5efe27a77a5d1b3f05e3f4e89069b5c6b19e) * fix(zig): gate bare literal branches; AND the flag over deduplicated free-call sites PR #3161 review, two findings: 1. `stampZigStaticGating` returned early when the file declared no boolean constants, but `collectZigStaticGatedRanges` also folds bare literals, so `if (false) { foo(); }` in a constant-free file went unstamped. The early return is gone; the range walk runs for every file. 2. `emitFreeCallFallback` deduplicates CALLS edges per (caller, callee) and wrote `staticGated` from whichever site it met first, so a callee reached from one live site and one dead site was gated or not by traversal order. Emission is now deferred to the end of each file's sites and the flag is the AND over every site that collapsed into the edge: one live site keeps the edge live. The other emit path keys its dedup on the site range and was not affected; `collapseByCallerTarget` in the generic bridge would have the same shape but no language that sets the marker opts into it. Fixture + tests: `gated_bare_literal`, `live_and_gated_same_callee` (live site first) and `gated_then_live_same_callee` (dead site first) in zig-static-gating.test.ts. All 70 resolver suites (3,603 tests) pass with the shared emitter change. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015ciQ3MTjpQXkCoNntZR9zG * test(zig): move the SCHEMA_BUMP pin to 93; rebaseline emit fingerprints for the staticGated column Three CI failures on |
||
|---|---|---|
| .. | ||
| baselines-streaming.json | ||
| baselines.json | ||
| measure-streaming.mjs | ||
| measure.mjs | ||
| README.md | ||
Emit-persistence bench (#2203)
Build-free throughput + byte-identity guard for the CSV-generation half of
the graph-DB persistence pipeline (streamAllCSVsToDisk), which dominates
large-repo analyze wall time alongside parsing (issue #2203).
# from gitnexus/
node --import tsx bench/emit-persistence/measure.mjs # print one JSON line
node --import tsx bench/emit-persistence/measure.mjs --check # gate vs baselines.json
What it measures
A synthetic KnowledgeGraph (files + functions + classes + 4 edge types across
the File→Function, File→Class, Function→Function label pairs) at two
scales:
elapsed_ms_small/elapsed_ms_large— median wall-clock overREPSruns ofstreamAllCSVsToDisk.scaling_ratio—(t_large/t_small)/(LARGE/SMALL); ~1.0 is linear. The--checkgate fails if it exceedsscaling_budget(catches an O(n²) re-regression in the emit/routing path).fingerprint— order-independent sha256 over every emitted CSV line (node CSVs + per-FROM→TO-label-pair rel CSVs). This is the byte-identity gate: the U2 (direct per-pair routing) and U3 (per-row microtask elimination) optimisations must not change graph content, and any future change that does fails--check. Byte-identity holds for all quote-free ids; for an id containing a"the router intentionally diverges from — and is more correct than — the legacy regex oracle (seesrc/core/lbug/rel-pair-routing.ts).
What it does NOT measure
- The LadybugDB
COPYhalf. Bulk loading needs a live writable DB connection, so it can't run build-free. Its per-stage timing lives in the runtimePROF_LBUG_LOAD=1breakdown ([lbug-load prof] csv-emit=… copy-nodes=… copy-rels=… fallback=… total=…) and is exercised end-to-end by the integration round-trip tests (test/integration/basicblock-roundtrip.test.ts,lbug-core-adapter.test.ts). - Content extraction. Bench nodes have no backing source files, so the
contentcolumn is empty — emit cost here reflects the CSV machinery (routing, escaping, buffering, disk writes), not file reads. - At-scale absolute numbers. The real postgres / kernel-
fs/wall (issue #2203's table) is a maintainer-run measurement; this synthetic bench is the reproducible regression guard, not a substitute for those runs.
Deferred follow-up
Parallelising the COPY loop (PARALLEL=false is load-bearing; LadybugDB is
single-writer) is out of scope for #2203 pending empirical validation of
concurrent-COPY support — the PROF_LBUG_LOAD breakdown is the prerequisite
that shows whether COPY is the dominant cost worth that risk.
Regenerating the baseline
node --import tsx bench/emit-persistence/measure.mjs # copy fingerprint + ratio into baselines.json