From 450702e10c8cc818caf2faa6498df0868d8bcbe3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C5=91=20Magyar?= Date: Wed, 4 Nov 2026 10:15:24 +0000 Subject: [PATCH] perf: reduce lookup allocations and stream identity checks (#3805) Reduce lexical lookup allocations and stream persisted node identities during incremental verification. Preserve lookup snapshots, connection ownership, cursor cleanup, and both fail-closed publication checks. Include fresh and persistent benchmark coverage, differential comparisons, and memory scaling reproduction. Validation: 4,019 local tests, 72,000 differential comparisons, build and typechecks, and all 12 required CI checks passed. --- .github/workflows/ci-tests.yml | 87 + .../src/scope-resolution/name-claims.ts | 101 +- gitnexus/bench/analyze-phase-breakdown.md | 190 +- .../incremental-write-integrity/README.md | 43 + .../incremental-write-integrity/measure.cjs | 19 +- .../incremental-write-integrity/memory.mjs | 143 + .../lexical-lookup/baseline-20261103.json | 1277 ++++ .../bench/lexical-lookup/differential.mjs | 109 + gitnexus/bench/lexical-lookup/measure.mjs | 306 + .../bench/lexical-lookup/measurements.json | 735 ++ .../lexical-lookup/optimization-20261103.json | 6310 +++++++++++++++++ .../core/incremental/write-reconciliation.ts | 39 +- .../scope-resolution/scope/walkers.ts | 36 +- gitnexus/src/core/lbug/lbug-adapter.ts | 52 + gitnexus/src/core/run-analyze.ts | 5 +- .../lbug-conn-serialization.test.ts | 110 +- .../unit/identity-reader-contract.test.ts | 16 + ...ncremental-write-benchmark-verdict.test.ts | 7 +- .../unit/incremental-write-integrity.test.ts | 4 +- .../unit/lexical-benchmark-preflight.test.ts | 204 + .../unit/run-analyze-fts-crash-marker.test.ts | 11 +- .../lexical-name-claims.test.ts | 35 + .../test/unit/write-reconciliation.test.ts | 4 +- 23 files changed, 9744 insertions(+), 99 deletions(-) create mode 100644 gitnexus/bench/incremental-write-integrity/memory.mjs create mode 100644 gitnexus/bench/lexical-lookup/baseline-20261103.json create mode 100644 gitnexus/bench/lexical-lookup/differential.mjs create mode 100644 gitnexus/bench/lexical-lookup/measure.mjs create mode 100644 gitnexus/bench/lexical-lookup/measurements.json create mode 100644 gitnexus/bench/lexical-lookup/optimization-20261103.json create mode 100644 gitnexus/test/unit/identity-reader-contract.test.ts create mode 100644 gitnexus/test/unit/lexical-benchmark-preflight.test.ts diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index a75e207bf..642b42d91 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -7,6 +7,93 @@ permissions: contents: read jobs: + lexical-lookup-benchmark: + name: lexical lookup / separate and repeated processes + runs-on: ubuntu-latest + timeout-minutes: 45 + permissions: + contents: read + env: + GITNEXUS_LEXICAL_BENCH_WORKERS: '2' + GITNEXUS_LEXICAL_BENCH_HEAP_MIB: '4096' + GITNEXUS_LEXICAL_BENCH_SCREEN: '0' + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 2 + persist-credentials: false + - name: Pin comparison revision + id: baseline + shell: bash + env: + PR_BASE_SHA: ${{ github.event.pull_request.base.sha }} + run: | + if [[ -n "$PR_BASE_SHA" ]]; then + comparison_sha="$PR_BASE_SHA" + else + comparison_sha="$(git rev-parse --verify HEAD^1)" + fi + printf 'sha=%s\n' "$comparison_sha" >> "$GITHUB_OUTPUT" + - uses: ./.github/actions/setup-gitnexus + with: + build: 'true' + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: ${{ steps.baseline.outputs.sha }} + path: baseline + persist-credentials: false + - name: Build baseline runtime and install search extensions + working-directory: baseline/gitnexus + run: | + npm ci + npm run build + npx tsx scripts/ensure-fts.ts + - name: Install candidate search extensions + working-directory: gitnexus + run: npx tsx scripts/ensure-fts.ts + - name: Prepare identical source corpora + shell: bash + env: + BASE_SHA: ${{ steps.baseline.outputs.sha }} + run: | + mkdir "$RUNNER_TEMP/lexical-lookup" + for variant in baseline candidate; do + corpus="$RUNNER_TEMP/lexical-lookup/corpus-$variant" + git clone --quiet --no-checkout --no-hardlinks "$GITHUB_WORKSPACE/baseline" "$corpus" + git -C "$corpus" sparse-checkout set gitnexus/src/core/ingestion gitnexus-shared/src/scope-resolution + git -C "$corpus" checkout --quiet --detach "$BASE_SHA" + done + - name: Compare lexical lookup semantics + run: node gitnexus/bench/lexical-lookup/differential.mjs "$GITHUB_WORKSPACE/baseline" "$GITHUB_WORKSPACE" | tee "$RUNNER_TEMP/lexical-lookup/differential.log" + shell: bash + - name: Measure separate processes + shell: bash + run: >- + node gitnexus/bench/lexical-lookup/measure.mjs + "$GITHUB_WORKSPACE/baseline" "$GITHUB_WORKSPACE" + "$RUNNER_TEMP/lexical-lookup/corpus-baseline" "$RUNNER_TEMP/lexical-lookup/corpus-candidate" + "$RUNNER_TEMP/lexical-lookup/fresh" fresh + 2>&1 | tee "$RUNNER_TEMP/lexical-lookup/fresh.log" + - name: Measure repeated processes + if: ${{ !cancelled() }} + shell: bash + run: >- + node gitnexus/bench/lexical-lookup/measure.mjs + "$GITHUB_WORKSPACE/baseline" "$GITHUB_WORKSPACE" + "$RUNNER_TEMP/lexical-lookup/corpus-baseline" "$RUNNER_TEMP/lexical-lookup/corpus-candidate" + "$RUNNER_TEMP/lexical-lookup/persistent" persistent + 2>&1 | tee "$RUNNER_TEMP/lexical-lookup/persistent.log" + - name: Retain lexical lookup measurements + if: always() + uses: ./.github/actions/upload-test-artifact + with: + name: lexical-lookup-performance + path: | + ${{ runner.temp }}/lexical-lookup/fresh/results.json + ${{ runner.temp }}/lexical-lookup/persistent/results.json + ${{ runner.temp }}/lexical-lookup/*.log + retention-days: 30 + mcp-query-benchmark: name: MCP query performance runs-on: ubuntu-latest diff --git a/gitnexus-shared/src/scope-resolution/name-claims.ts b/gitnexus-shared/src/scope-resolution/name-claims.ts index 05c009fce..d69a1fe0a 100644 --- a/gitnexus-shared/src/scope-resolution/name-claims.ts +++ b/gitnexus-shared/src/scope-resolution/name-claims.ts @@ -29,11 +29,15 @@ export interface NameClaimSources { readonly bindingsAt?: (scope: Scope, name: string) => readonly BindingRef[]; readonly importsAt?: (scope: Scope) => readonly ImportEdge[]; } +const NO_BINDINGS: readonly BindingRef[] = Object.freeze([]); +const NO_CLAIMS: readonly NameClaim[] = Object.freeze([]); +const NO_IMPORTS: readonly ImportEdge[] = Object.freeze([]); +const NO_SELECTION: ScopeClaimSelection = Object.freeze({ status: 'absent', claims: NO_CLAIMS }); const ABSENT: NameClaimResult = Object.freeze({ status: 'absent', - bindings: [], - imports: [], - claims: [], + bindings: NO_BINDINGS, + imports: NO_IMPORTS, + claims: NO_CLAIMS, }); // Published scope arrays are readonly. Cache by the array, not the scope ID: // finalization and cache hydration can replace a scope's import/claim snapshot. @@ -42,8 +46,6 @@ const importsByName = new WeakMap< readonly ImportEdge[], ReadonlyMap >(); -const NO_CLAIMS: readonly NameClaim[] = Object.freeze([]); -const NO_IMPORTS: readonly ImportEdge[] = Object.freeze([]); export function nameClaimsFor(scope: Scope, name: string): readonly NameClaim[] { const claims = scope.nameClaims; @@ -93,11 +95,13 @@ export function selectClaimsAtScope( name: string, options: NameLookupOptions = {}, ): ScopeClaimSelection { + const candidates = nameClaimsFor(scope, name); + if (candidates.length === 0) return NO_SELECTION; const purpose = options.purpose ?? 'value'; - const claims = nameClaimsFor(scope, name).filter( + const claims = candidates.filter( (c) => c.purpose === undefined || c.purpose === 'both' || c.purpose === purpose, ); - if (claims.length === 0) return { status: 'absent', claims }; + if (claims.length === 0) return NO_SELECTION; const active = claims.filter( (c) => c.availableFrom === undefined || @@ -192,6 +196,9 @@ export function lookupLexicalName( ): NameClaimResult { let id: ScopeId | null = startScope; let position = options.position; + // Position is cleared when crossing deferred/redirected ownership. Reuse + // the caller's readonly options until that happens, then copy only once. + let selectionOptions = options; let forcedClaims: readonly NameClaim[] | undefined; let carriedConstructor: TypeRef | undefined; const visited = new Set(); @@ -209,9 +216,10 @@ export function lookupLexicalName( id = scope.lookupPolicy?.parentScope ?? scope.parent; continue; } + if (selectionOptions.position !== position) selectionOptions = { ...options, position }; const selected: ScopeClaimSelection = forcedClaims === undefined - ? selectClaimsAtScope(scope, name, { ...options, position }) + ? selectClaimsAtScope(scope, name, selectionOptions) : { status: 'selected', claims: forcedClaims }; forcedClaims = undefined; const redirected = selected.claims.find((c) => c.redirect !== undefined); @@ -245,38 +253,47 @@ export function lookupLexicalName( return { ...ABSENT, status: 'blocked', scope, claims: selected.claims }; const nameClaims = nameClaimsFor(scope, name); const hasClaimsForName = nameClaims.length > 0; - const allBindings = sources.bindingsAt?.(scope, name) ?? scope.bindings.get(name) ?? []; + const allBindings = + sources.bindingsAt?.(scope, name) ?? scope.bindings.get(name) ?? NO_BINDINGS; const allImports = importsFor(sources.importsAt?.(scope) ?? scope.imports ?? NO_IMPORTS, name); - let bindings = allBindings.filter( - (b) => - b.availableFrom === undefined || - position === undefined || - compare(b.availableFrom, position) <= 0, - ); + let bindings = + allBindings.length === 0 + ? NO_BINDINGS + : allBindings.filter( + (b) => + b.availableFrom === undefined || + position === undefined || + compare(b.availableFrom, position) <= 0, + ); let imports = allImports; if (selected.status === 'selected') { - bindings = bindings.filter((b) => - selected.claims.some((c) => - c.kind === 'import' - ? b.via !== undefined && matchesClaim(b.via.atRange, c) - : c.kind === 'binding' && - (b.origin === 'local' || b.declarationRange !== undefined) && - matchesBindingClaim(b.declarationRange, c), - ), - ); - imports = allImports.filter((e) => - selected.claims.some((c) => c.kind === 'import' && matchesClaim(e.atRange, c)), - ); + if (bindings.length > 0) + bindings = bindings.filter((b) => + selected.claims.some((c) => + c.kind === 'import' + ? b.via !== undefined && matchesClaim(b.via.atRange, c) + : c.kind === 'binding' && + (b.origin === 'local' || b.declarationRange !== undefined) && + matchesBindingClaim(b.declarationRange, c), + ), + ); + imports = + allImports.length === 0 + ? NO_IMPORTS + : allImports.filter((e) => + selected.claims.some((c) => c.kind === 'import' && matchesClaim(e.atRange, c)), + ); } else if (hasClaimsForName) { // A declaration in another namespace, or a not-yet-visible declaration, // must not sneak back through the unfiltered legacy binding channels. - bindings = bindings.filter( - (b) => - b.availableFrom !== undefined && - b.declarationRange !== undefined && - !nameClaims.some((c) => rangesOverlap(c.range, b.declarationRange!)), - ); - imports = []; + if (bindings.length > 0) + bindings = bindings.filter( + (b) => + b.availableFrom !== undefined && + b.declarationRange !== undefined && + !nameClaims.some((c) => rangesOverlap(c.range, b.declarationRange!)), + ); + imports = NO_IMPORTS; } const ownType = scope.typeBindings.get(name); const typeFactOwnsName = @@ -328,9 +345,12 @@ export function lookupLexicalName( (typeBinding === undefined || isInferredFact(typeBinding.source)) ) typeBinding = carriedConstructor; - const usable = bindings.filter( - (b) => (options.purpose ?? 'value') !== 'value' || b.via?.typeOnly !== true, - ); + const usable = + bindings.length === 0 + ? NO_BINDINGS + : bindings.filter( + (b) => (options.purpose ?? 'value') !== 'value' || b.via?.typeOnly !== true, + ); return { status: usable.length > 0 || @@ -358,6 +378,9 @@ export function lookupLexicalName( } // A write to an undeclared name declares nothing, but it still carries the // value's type to reads inside the writing scope. - const carried = carriedConstructor === undefined ? {} : { typeBinding: carriedConstructor }; - return id === null ? { ...ABSENT, ...carried } : { ...ABSENT, ...carried, status: 'blocked' }; + if (carriedConstructor === undefined) + return id === null ? ABSENT : { ...ABSENT, status: 'blocked' }; + return id === null + ? { ...ABSENT, typeBinding: carriedConstructor } + : { ...ABSENT, typeBinding: carriedConstructor, status: 'blocked' }; } diff --git a/gitnexus/bench/analyze-phase-breakdown.md b/gitnexus/bench/analyze-phase-breakdown.md index a3bbc5cd3..631b33687 100644 --- a/gitnexus/bench/analyze-phase-breakdown.md +++ b/gitnexus/bench/analyze-phase-breakdown.md @@ -1,7 +1,6 @@ # Analyze phase breakdown — where the time actually goes -Updated 2026-11-01 with scope-emission measurements after #3796 merged, plus -production-hardening measurements on LadybugDB **0.22.0** for unchanged dirty checkouts. +Updated 2026-11-02 with the lexical-lookup allocation experiment below. Records what the `analyze` pipeline costs per phase and the results of optimization experiments. The September measurements remain below as historical @@ -14,6 +13,193 @@ dispatch path is `bench/parse-dispatch-rounds/`. --- +## Lexical-lookup allocation experiment — 2026-11-02 + +**Decision: keep experimental; the performance requirement for both workflows +has not passed.** Fresh-process edits improved in all three pairs (8.95% lower +median), but the first repeated-process pair took 12.68% longer and triggered +the harness's early rejection gate. Its host load rose sharply. That does not +prove a patch-induced regression, and it also does not establish a warm-process +speedup. Do not promote this as a production optimization on this evidence. + +The patch reduces temporary allocation in `lookupNameClaim`, +`selectClaimsAtScope` and `lookupLexicalName`: reuse frozen empty results, skip +filters over empty inputs, avoid concatenating empty binding channels, and copy +lookup options only when the effective position changes. Nonempty binding +results retain snapshot semantics. Provider hooks, declaration ownership, +shadowing, redirects and position checks still run. No semantic-result cache, +new invalidation mechanism or native dependency is introduced. + +### Separate-process edit measurements + +| Measurement | Baseline | Candidate | Less elapsed time | +| --- | ---: | ---: | ---: | +| Edit 1: `save` → `load` | 122.065s | 111.135s | 8.95% | +| Edit 2: `load` → `save` | 114.006s | 101.730s | 10.77% | +| Edit 3: `save` → `load` | 131.285s | 111.303s | 15.22% | +| Median edit | 122.065s | 111.135s | 8.95% | +| All three edits | 367.356s | 324.168s | 11.76% | +| Median scope-resolution phase | 68.197s | 62.344s | 8.58% | +| Highest process peak RSS across edits | 4.29 GiB | 4.25 GiB | — | + +All three scope-resolution phases improve, but not all wall-time differences +belong to that phase. For example, the first pair's process-detection interval +falls from 5.889s to 1.475s, and the third pair's post-`done` work falls from +16.551s to 7.974s. The patch does not directly change either stage. Treat the +observed end-to-end reductions as a small shared-host screen, not a universal +speedup or a precise attribution of saved time. One-minute host load ranges +from 7.79 to 11.43 at the start of these measured edits. + +### Repeated-process screen + +| Measurement | Baseline | Candidate | Less elapsed time | +| --- | ---: | ---: | ---: | +| First edit: `save` → `load` | 109.483s | 123.364s | −12.68% | +| Scope-resolution phase | 67.013s | 65.739s | 1.90% | +| Ladybug write intervals | 8.814s | 12.902s | — | +| FTS phase | 10.600s | 14.766s | — | +| Work after `done` progress | 8.947s | 14.858s | — | +| Process peak RSS, including setup | 5.49 GiB | 5.62 GiB | — | + +These intervals come from progress callbacks; they include all work between +adjacent callbacks rather than instrumenting native operations individually. +Baseline one-minute load fell **6.35 → 3.81**; candidate load rose +**3.81 → 12.23**. Scope resolution improved slightly while several other +stages slowed. Only this first pair was run, as specified by the screening +gate; there is no three-pair warm-process median. Both graphs and persisted +call targets matched. Persistent mode retains one process per variant and +models repeated analysis, not watch-event scheduling or debounce latency. + +Separate excluded cold setup runs took 218.219s/187.148s in fresh mode and +158.148s/153.951s in persistent mode (baseline/candidate). Each lifecycle uses +independent index directories. Setup order is fixed and host load changes, +so these are not controlled cold-index speedup claims. The +[measurement receipt](lexical-lookup/measurements.json) includes every sample, +phase duration, peak memory, graph hash, load average and runtime checksum. + +### Method and correctness boundaries + +Baseline runtime and both disposable corpus checkouts are pinned to +`347cc99b4a237f9a71c0084167bcbcbd9d06e610`; the candidate runtime adds only the +lookup patch. Each corpus has 3,384 indexed files / 3,120 parseable files, +including the same control file. Node **v22.23.3**, LadybugDB **0.22.0**, +Linux x64, Intel i9-12900K (24 logical CPUs), 16 parse workers, 8 GiB V8 heap. +Samples run serially; paired order is baseline/candidate, candidate/baseline, +baseline/candidate after excluded initialization runs. Runtime builds stay +fixed throughout each comparison, with no tests or other benchmarks launched +by this experiment concurrently. The machine is shared with other workloads. + +The [harness](lexical-lookup/measure.mjs) times `runFullAnalysis`, including +incremental persistence and FTS. Process startup, graph hashing and subsequent +persisted-target verification are outside the timer. CPU profiling and heap +probes are off; the existing scope phase logger remains on for both variants. +Each measured edit changes one file, reparses 22 files, hits the parser cache +for 3,098 files, uses incremental writes and has no rebuild reasons. FTS must +remain available. This is a real edit benchmark, not an up-to-date fast return. + +Every pair compares canonical hashes of **114,413 source/semantic nodes and +318,798 relationships**. Derived Folder/Community/Process nodes and +CONTAINS/MEMBER_OF/STEP_IN_PROCESS edges are excluded. Hashes cover the graph +returned after persistence; cleared source content is not independently +verified by these hashes. A separate LadybugDB query after each sample verifies +that the control CALLS edge follows `save`/`load`. Matching graphs preserve the +baseline's limits; they do not establish complete resolution of the corpus. + +Targeted tests cover mutation after a missing lookup, result snapshots, reused +frozen options and deferred activation. The initial validation passed 137 tests +across lexical ownership, TypeScript type ownership, block shadowing and +TypeScript/Python/C++ native rename suites. A seeded differential screen also +matched the original implementation in 72,000 generated lexical lookups. +The broader scope-resolution suite then passed **3,467 tests / 175 files** +(overlaps the initial targeted tests). The parameterized differential harness +also passed when rerun against the same two builds. +Build, test typecheck and ESLint passed (existing non-null assertion warnings +remain). These were the checks completed alongside the benchmark; PR validation is recorded separately. + +To reproduce, build the baseline and candidate runtimes first, prepare two +clean disposable corpus checkouts at the same commit, then run from +`gitnexus/` (the runtime arguments name repository roots): + +```sh +node bench/lexical-lookup/differential.mjs BASE_RUNTIME CANDIDATE_RUNTIME +node bench/lexical-lookup/measure.mjs BASE_RUNTIME CANDIDATE_RUNTIME BASE_CORPUS CANDIDATE_CORPUS OUTPUT_FRESH fresh +node bench/lexical-lookup/measure.mjs BASE_RUNTIME CANDIDATE_RUNTIME BASE_CORPUS CANDIDATE_CORPUS OUTPUT_PERSISTENT persistent +``` + +By default, the timing harness stops after the first edit pair if the candidate +is not faster. To establish a baseline, set `GITNEXUS_LEXICAL_BENCH_SCREEN=0` +to collect all three pairs regardless of their timings. Repeat each lifecycle +in independent sessions, setting `GITNEXUS_LEXICAL_BENCH_BASE_FIRST=0` in +alternating sessions to reverse seed and edit ordering. Both settings accept +only `0` or `1` and are recorded in `results.json`. Report every sample and +the variation between sessions; a screening result alone is not a baseline. + +The harness waits for native workers to exit normally and removes only its +control source file. Keep builds fixed and do not run tests concurrently. +The receipt's harness checksums identify the versions used for measurement. +The checked-in scripts were subsequently formatted, and cleanup now attempts +both worker shutdowns and removes the control files even if a worker fails. +These changes are outside the timed analysis interval. + +### CI execution + +`.github/workflows/ci-tests.yml` runs the differential check and both process +lifecycles in a dedicated job. It builds the candidate and the pull request's +event baseline SHA, falling back to a verified first parent when the event has +no baseline. It uses two clean sparse corpus checkouts at that baseline. +The CI corpus contains the ingestion and shared +scope-resolution source trees, plus Git's cone-mode parent files. It is smaller +than the full-repository corpus measured above; its timings are a separate series. + +CI sets `GITNEXUS_LEXICAL_BENCH_WORKERS=2` and +`GITNEXUS_LEXICAL_BENCH_HEAP_MIB=4096`; the local defaults remain 16 workers and +8192 MiB. Each lifecycle requires a new output directory and retains its raw +results and logs in the `lexical-lookup-performance` artifact. Graph and persisted +call mismatches fail the job. CI sets `GITNEXUS_LEXICAL_BENCH_SCREEN=0` so all +three paired edits and their correctness checks run regardless of timing noise. + +### Repeated baseline, 2026-11-03 (CI corpus) + +The [baseline receipt](lexical-lookup/baseline-20261103.json) records three +independent sessions per lifecycle, each with three paired edits. Every pair +was retained, including slower candidates. Runtime order was reversed in the +middle session. The corpus is the sparse CI source tree at +`4916e0d5e1f4d6d70d41c1f39cd244bca2c7b390`; baseline and candidate runtimes are +`4916e0d5e1f4d6d70d41c1f39cd244bca2c7b390` and +`6b487a529e14d59e51a9df9a44524e98705a6b71`. Both use Node 22.23.3, +LadybugDB 0.22.0, two workers and a 4 GiB heap on the same shared host. + +These are medians of the three session medians; cold seeds are excluded: + +| Lifecycle | Baseline | PR candidate | Change | +| --- | ---: | ---: | ---: | +| Separate processes | 28.494s | 27.552s | 3.31% less time | +| Repeated processes | 30.276s | 29.814s | 1.53% less time | + +The candidate's session medians have coefficients of variation of **5.02%** +and **17.01%**, respectively. These small aggregate gains are inconclusive on +this host. The receipt also retains every paired percentage change, graph hash, +persisted call target and host-load reading. All 18 edit pairs matched 23,641 +source/semantic nodes and 64,292 relationships, and the seeded differential +check passed 72,000 comparisons per session. Selection and reporting share the +same corpus; no holdout was used. This does not establish a full-repository or +watch-mode speedup. + +During measurement, the PR advanced to +`6aeeace8e96603fb062dcc709e834042d5a6df74` by merging a Kotlin grammar update. +The lookup implementations and lockfile are unchanged, but the newer native +grammar and revision were not measured in that baseline. This receipt remains +pinned to the earlier builds. + +The subsequent [optimization review in PR #3805](https://github.com/abhigyanpatwari/GitNexus/pull/3805) +and [experiment receipt](lexical-lookup/optimization-20261103.json) compare two +additional candidates against unchanged `6aeeace8` controls. Neither met the +required repeatable 5% warm-process improvement with at most 3% fresh-process +regression. Neither additional lexical candidate was retained. The harness +makes complete, opposite-order baseline collection reproducible. + +--- + ## Current measurements — 2026-10-31 ### Environment and timing boundaries diff --git a/gitnexus/bench/incremental-write-integrity/README.md b/gitnexus/bench/incremental-write-integrity/README.md index a75861500..71b33a7d5 100644 --- a/gitnexus/bench/incremental-write-integrity/README.md +++ b/gitnexus/bench/incremental-write-integrity/README.md @@ -84,3 +84,46 @@ An in-place verification failure keeps a non-FTS dirty phase: an FTS-only repair cannot clear the marker and recertify the inconsistent graph. The same protection applies when FTS returns but analyzer finalization fails before the final identity scan: recovery still rebuilds the graph. + +## Memory scaling + +`memory.mjs` measures the compiled production reader in a fresh process, without +forcing GC between reads. It records full identity verification, elapsed time, +sampled heap/RSS, the process RSS high-water mark, and initial/final retained heap. +The native pool is 512 MiB for measurements and 1 GiB for fixture creation. + +Build the runtime with `npm run build`. Save this configuration outside the repo: + +```json +{ + "runtime": "/absolute/path/to/GitNexus", + "storage": "/tmp/gnx-identity-memory", + "output": "/tmp/gnx-identity-memory/seed.json", + "count": 1048576, + "width": 0, + "mode": "seed", + "reader": "stream", + "iterations": 40 +} +``` + +Run from `gitnexus/`: + +```sh +node --expose-gc --max-old-space-size=4096 bench/incremental-write-integrity/memory.mjs /tmp/config.json +``` + +Then change `mode` to `measure` and choose a new output file. Run each measurement +in a new process and use one process per database at a time. To compare the +original array-based implementation, set `runtime` to its separately built +checkout and `reader` to `baseline`; keep the same fixture and memory limits. + +Vary `count` with separate fixtures to measure node scaling. `width` adds that +many ASCII bytes to each of ID, name and path, so it measures identity size +independently of node count. Repeat each point and hold the largest size out of +the fitted curve. A finite RSS fit is evidence over that range, not a guarantee +about every native allocator or the rest of the indexing pipeline. + +The streaming verifier retains expected-node maps and one decoded row rather +than a full table of JavaScript rows. The expected maps grow linearly with graph +size; the native query result and the original graph still consume memory. diff --git a/gitnexus/bench/incremental-write-integrity/measure.cjs b/gitnexus/bench/incremental-write-integrity/measure.cjs index 8db1d2d5b..ee8f7910d 100644 --- a/gitnexus/bench/incremental-write-integrity/measure.cjs +++ b/gitnexus/bench/incremental-write-integrity/measure.cjs @@ -66,9 +66,9 @@ const source = (file) => import(pathToFileURL(join(ROOT, file)).href); await adapter.tryFlushWAL(); const samples = []; let calls = 0; - const query = async (sql) => { + const query = async (sql, onRow) => { calls++; - return adapter.executeQuery(sql); + await adapter.forEachQueryRow(sql, onRow); }; for (let run = 0; run < 9; run++) { calls = 0; @@ -80,17 +80,18 @@ const source = (file) => import(pathToFileURL(join(ROOT, file)).href); if (run >= 2) samples.push(elapsed); } const first = graph.iterNodes().next().value; - const alteredQuery = async (sql) => { - const rows = await adapter.executeQuery(sql); - if (sql.includes('(n:`Function`)')) rows.find((r) => r.id === first.id).startLine++; - return rows; + const alteredQuery = async (sql, onRow) => { + await adapter.forEachQueryRow(sql, (row) => { + if (sql.includes('(n:`Function`)') && row.id === first.id) row.startLine++; + onRow(row); + }); }; await assert.rejects( reconcileGraphNodeIdentities(graph, alteredQuery, 'negative-control'), /startLine/, ); await assert.rejects( - reconcileGraphNodeIdentities(graph, async () => [], 'negative-control'), + reconcileGraphNodeIdentities(graph, async () => {}, 'negative-control'), /missing ID/, ); @@ -124,12 +125,12 @@ const source = (file) => import(pathToFileURL(join(ROOT, file)).href); rows.length !== size.nodes || mismatched > 0 || actual.size !== wanted.size; if (rejected) { await assert.rejects( - reconcileGraphNodeIdentities(graph, adapter.executeQuery, phase), + reconcileGraphNodeIdentities(graph, adapter.forEachQueryRow, phase), /Graph identity reconciliation/, ); } else { assert.equal( - (await reconcileGraphNodeIdentities(graph, adapter.executeQuery, phase)).nodes, + (await reconcileGraphNodeIdentities(graph, adapter.forEachQueryRow, phase)).nodes, size.nodes, ); } diff --git a/gitnexus/bench/incremental-write-integrity/memory.mjs b/gitnexus/bench/incremental-write-integrity/memory.mjs new file mode 100644 index 000000000..569b8bd23 --- /dev/null +++ b/gitnexus/bench/incremental-write-integrity/memory.mjs @@ -0,0 +1,143 @@ +// Build the runtime, then: node --expose-gc --max-old-space-size=4096 memory.mjs CONFIG.json +// Config: { runtime, storage, output, count, width, mode: "seed"|"measure", +// reader: "baseline"|"stream", iterations }. Each measurement is a fresh process. +// No forced GC between reads. Initial/final GC measure retained graph memory only. +import fs from 'node:fs'; +import path from 'node:path'; +import assert from 'node:assert/strict'; +import { createHash } from 'node:crypto'; +import { pathToFileURL } from 'node:url'; + +const config = JSON.parse(fs.readFileSync(process.argv[2], 'utf8')); +const { runtime, storage, output, count, width = 0, mode, reader, iterations } = config; +assert(Number.isSafeInteger(count) && count >= 0); +assert(Number.isSafeInteger(width) && width >= 0); +assert(Number.isSafeInteger(iterations) && iterations > 0); +assert(['seed', 'measure'].includes(mode)); +assert(['baseline', 'stream'].includes(reader)); +assert(global.gc, 'Run with --expose-gc'); +const bufferPoolBytes = (mode === 'seed' ? 1024 : 512) * 1048576; +process.env.GITNEXUS_LBUG_BUFFER_POOL_SIZE = String(bufferPoolBytes); +process.env.GITNEXUS_SHARED_STORE = 'off'; +process.env.GITNEXUS_HOME = path.join(path.dirname(output), 'home'); +const source = (file) => import(pathToFileURL(path.join(runtime, 'gitnexus/dist', file)).href); +const { createKnowledgeGraph } = await source('core/graph/graph.js'); +const { reconcileGraphNodeIdentities } = await source('core/incremental/write-reconciliation.js'); +const adapter = await source('core/lbug/lbug-adapter.js'); +const graph = createKnowledgeGraph(); +const padding = 'x'.repeat(width); +const fingerprint = createHash('sha256'); +let identityBytes = 0; +for (let i = 0; i < count; i++) { + const index = String(i).padStart(7, '0'); + const id = `Function:node${index}${padding}`; + const name = `fn${index}${padding}`; + const filePath = `src/file${index}.ts${padding}`; + const startLine = (i % 32) * 4; + const endLine = startLine + 2; + identityBytes += Buffer.byteLength(id) + Buffer.byteLength(name) + Buffer.byteLength(filePath); + fingerprint.update(JSON.stringify([id, name, filePath, startLine, endLine]) + '\n'); + graph.addNode({ id, label: 'Function', properties: { name, filePath, startLine, endLine } }); +} +const result = { + config, + node: process.version, + driver: JSON.parse( + fs.readFileSync(path.join(runtime, 'gitnexus/node_modules/@ladybugdb/core/package.json')), + ).version, + bufferPoolBytes, + identityBytes, + identityFingerprint: fingerprint.digest('hex'), + iterations: [], + completed: false, +}; +let peakRss = 0, + peakHeap = 0, + currentPeakRss = 0, + currentPeakHeap = 0; +function sample() { + const memory = process.memoryUsage(); + peakRss = Math.max(peakRss, memory.rss); + peakHeap = Math.max(peakHeap, memory.heapUsed); + currentPeakRss = Math.max(currentPeakRss, memory.rss); + currentPeakHeap = Math.max(currentPeakHeap, memory.heapUsed); + return memory; +} +function save() { + result.peakRssBytes = Math.max(peakRss, process.resourceUsage().maxRSS * 1024); + result.sampledPeakHeapBytes = peakHeap; + fs.writeFileSync(output, JSON.stringify(result, null, 2) + '\n'); +} +let timer; +try { + await adapter.initLbug(path.join(storage, 'lbug'), { skipFts: true }); + if (mode === 'seed') { + await adapter.loadGraphToLbug(graph, storage, storage, undefined, undefined, undefined, 'none'); + await adapter.tryFlushWAL(); + } else { + global.gc(); + result.initial = sample(); + timer = setInterval(sample, 20); + timer.unref(); + for (let i = 0; i < iterations; i++) { + currentPeakRss = 0; + currentPeakHeap = 0; + const before = sample(); + let queries = 0; + const readRows = + reader === 'baseline' + ? async (query) => { + queries++; + sample(); + const rows = await adapter.executeQuery(query); + sample(); + return rows; + } + : async (query, visit) => { + queries++; + sample(); + await adapter.forEachQueryRow(query, visit); + sample(); + }; + const start = performance.now(); + const receipt = await reconcileGraphNodeIdentities(graph, readRows, 'memory-scaling'); + const ms = performance.now() - start; + assert.equal(receipt.nodes, count); + assert.equal(queries, receipt.tables); + const after = sample(); + result.iterations.push({ + i, + ms, + queries, + verifiedNodes: receipt.nodes, + before, + after, + peakRssBytes: currentPeakRss, + sampledPeakHeapBytes: currentPeakHeap, + maxRssKiB: process.resourceUsage().maxRSS, + }); + save(); + } + clearInterval(timer); + global.gc(); + result.finalAfterGc = sample(); + } + result.completed = true; +} catch (error) { + result.error = String(error); + process.exitCode = 1; +} finally { + clearInterval(timer); + await adapter.closeLbug(); + save(); +} +console.log( + JSON.stringify({ + count, + width, + reader, + completed: result.completed, + iterations: result.iterations.length, + peakRssMiB: result.peakRssBytes / 1048576, + }), +); diff --git a/gitnexus/bench/lexical-lookup/baseline-20261103.json b/gitnexus/bench/lexical-lookup/baseline-20261103.json new file mode 100644 index 000000000..7e4cd3695 --- /dev/null +++ b/gitnexus/bench/lexical-lookup/baseline-20261103.json @@ -0,0 +1,1277 @@ +{ + "date": "2026-11-03T08:23:10.793Z", + "purpose": "Reproducible PR 3805 baseline before further optimization", + "provenance": { + "date": "2026-11-03T07:48:04.400Z", + "before": { + "head": "4916e0d5e1f4d6d70d41c1f39cd244bca2c7b390", + "ladybug": "0.22.0", + "lock": "b5e208e91da7ac7270e0985f8d19097f51fa5c6d4480b6e07473a8d3ea306ff8", + "nameClaims": "157fd1ff2870468d335f97fff41d0b002f4cad749db64634aa48469053d7cea3", + "walkers": "15dba69d6ec871e43f4d0d1aadbad93e1645c13a9ad2e664e9f9bd679f73e55c" + }, + "after": { + "head": "6b487a529e14d59e51a9df9a44524e98705a6b71", + "ladybug": "0.22.0", + "lock": "b5e208e91da7ac7270e0985f8d19097f51fa5c6d4480b6e07473a8d3ea306ff8", + "nameClaims": "6f998066bcb3f17d69f2dbae7dba1a1d5af865bc8798d4b137aaed9387a81284", + "walkers": "9400ed640a22343f6cc54e3515944af664022ac7f4a8c4306da0cc95df37f9e1" + }, + "node": "v22.23.3", + "cpu": "12th Gen Intel(R) Core(TM) i9-12900K", + "cpuCount": 24, + "memory": 33516720128, + "os": "6.6.114.1-microsoft-standard-WSL2", + "workers": 2, + "heapMiB": 4096, + "corpusCommit": "4916e0d5e1f4d6d70d41c1f39cd244bca2c7b390", + "corpusSparsePaths": ["gitnexus/src/core/ingestion", "gitnexus-shared/src/scope-resolution"], + "harness": "02826b93d5826bcf3074ddd2853882350d4a0a8114f64609d60b7bf8aff88bdc", + "evaluator": "d83c9ec58ce04b647e282b20e49b59fe84c7448848450e8e5bdfca68fff7823f", + "repeats": 3, + "pairsPerRepeat": 3, + "earlyStopping": false, + "order": ["base-first", "candidate-first", "base-first"], + "noOpProbe": "rejected; both control files removed", + "selectionAndReportingShareCorpus": true, + "worktreeCount": 254, + "worktreeBudgetWarning": "Existing count exceeds ce-optimize suggested budget 12; no other worktrees changed. Experiments serial.", + "remoteHeadObservedAtEnd": "6aeeace8e96603fb062dcc709e834042d5a6df74", + "remoteBaseObservedAtEnd": "24d3de239daaa45f163473ea3f195d37a8397b78", + "remoteDrift": "PR merged Kotlin grammar update during measurement. Lookup implementations and lockfile unchanged; newer native grammar and head have not been benchmarked. All measurements remain pinned to recorded before/after commits." + }, + "measurements": { + "fresh": { + "before_session_medians_ms": { + "samples": [27167.331744, 28493.790027000003, 30487.120746999997], + "median": 28493.790027000003, + "min": 27167.331744, + "max": 30487.120746999997, + "standard_deviation": 1364.3825612209573, + "cv_percent": 4.751284023940061 + }, + "after_session_medians_ms": { + "samples": [25073.12691, 28214.86869, 27551.789628000002], + "median": 27551.789628000002, + "min": 25073.12691, + "max": 28214.86869, + "standard_deviation": 1352.1170283120848, + "cv_percent": 5.017765786358472 + }, + "change_percent": -3.305984911475046, + "paired_change_percent": { + "samples": [ + -33.927324510337066, -7.708540734636237, 1.7210219559163908, -0.9788846507807647, + -6.172499108184015, 35.12771016582481, -5.880796687043244, -13.386655756223742, + -0.8958687711658531 + ], + "median": -5.880796687043244, + "min": -33.927324510337066, + "max": 35.12771016582481, + "standard_deviation": 16.952700990592877 + }, + "samples": [ + { + "session": 1, + "pair": 1, + "before": { + "ms": 41835.567646, + "scope_ms": 16664.676064, + "maxRssKiB": 1975176, + "loadBefore": [23.29, 14.18, 7.75], + "loadAfter": [20.05, 14.57, 8.16], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "after": { + "ms": 27641.87885, + "scope_ms": 9817.220289, + "maxRssKiB": 1974016, + "loadBefore": [20.05, 14.57, 8.16], + "loadAfter": [16.14, 14.15, 8.23], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "change_percent": -33.927324510337066 + }, + { + "session": 1, + "pair": 2, + "before": { + "ms": 27167.331744, + "scope_ms": 12672.416329, + "maxRssKiB": 1988984, + "loadBefore": [13.77, 13.75, 8.25], + "loadAfter": [13.07, 13.58, 8.37], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "save" + } + ] + }, + "after": { + "ms": 25073.12691, + "scope_ms": 9655.368435, + "maxRssKiB": 1949060, + "loadBefore": [16.14, 14.15, 8.23], + "loadAfter": [13.77, 13.75, 8.25], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "save" + } + ] + }, + "change_percent": -7.708540734636237 + }, + { + "session": 1, + "pair": 3, + "before": { + "ms": 24176.948735, + "scope_ms": 10316.814948, + "maxRssKiB": 1992156, + "loadBefore": [13.07, 13.58, 8.37], + "loadAfter": [10.47, 12.94, 8.3], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "after": { + "ms": 24593.039331, + "scope_ms": 9934.868561, + "maxRssKiB": 1973040, + "loadBefore": [10.47, 12.94, 8.3], + "loadAfter": [9.77, 12.57, 8.3], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "change_percent": 1.7210219559163908 + }, + { + "session": 2, + "pair": 1, + "before": { + "ms": 28493.790027000003, + "scope_ms": 10862.499722, + "maxRssKiB": 1763120, + "loadBefore": [10.75, 10.37, 9.14], + "loadAfter": [11, 10.48, 9.21], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "after": { + "ms": 28214.86869, + "scope_ms": 10576.886433, + "maxRssKiB": 1966932, + "loadBefore": [11.31, 10.43, 9.11], + "loadAfter": [10.75, 10.37, 9.14], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "change_percent": -0.9788846507807647 + }, + { + "session": 2, + "pair": 2, + "before": { + "ms": 28463.054967, + "scope_ms": 10746.571084, + "maxRssKiB": 1967760, + "loadBefore": [11, 10.48, 9.21], + "loadAfter": [10.63, 10.46, 9.25], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "save" + } + ] + }, + "after": { + "ms": 26706.173153, + "scope_ms": 9386.829097, + "maxRssKiB": 1760300, + "loadBefore": [10.63, 10.46, 9.25], + "loadAfter": [13.02, 10.98, 9.46], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "save" + } + ] + }, + "change_percent": -6.172499108184015 + }, + { + "session": 2, + "pair": 3, + "before": { + "ms": 29975.521841, + "scope_ms": 11109.654848000002, + "maxRssKiB": 1994928, + "loadBefore": [18.77, 12.78, 10.13], + "loadAfter": [15.65, 12.6, 10.16], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "after": { + "ms": 40505.236273999995, + "scope_ms": 17595.557853000002, + "maxRssKiB": 1956592, + "loadBefore": [13.02, 10.98, 9.46], + "loadAfter": [18.77, 12.78, 10.13], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "change_percent": 35.12771016582481 + }, + { + "session": 3, + "pair": 1, + "before": { + "ms": 29273.29244, + "scope_ms": 11244.51295, + "maxRssKiB": 1991304, + "loadBefore": [10.07, 11.4, 10.05], + "loadAfter": [12.12, 11.75, 10.21], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "after": { + "ms": 27551.789628000002, + "scope_ms": 10222.888305, + "maxRssKiB": 1953404, + "loadBefore": [12.43, 11.82, 10.24], + "loadAfter": [11.26, 11.58, 10.2], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "change_percent": -5.880796687043244 + }, + { + "session": 3, + "pair": 2, + "before": { + "ms": 30587.541568, + "scope_ms": 11982.26958, + "maxRssKiB": 1973032, + "loadBefore": [11.19, 11.53, 10.22], + "loadAfter": [12.67, 11.87, 10.38], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "save" + } + ] + }, + "after": { + "ms": 26492.892674, + "scope_ms": 9234.379915, + "maxRssKiB": 1758284, + "loadBefore": [11.26, 11.58, 10.2], + "loadAfter": [11.19, 11.53, 10.22], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "save" + } + ] + }, + "change_percent": -13.386655756223742 + }, + { + "session": 3, + "pair": 3, + "before": { + "ms": 30487.120746999997, + "scope_ms": 11982.057261, + "maxRssKiB": 1758652, + "loadBefore": [12.67, 11.87, 10.38], + "loadAfter": [10.55, 11.43, 10.29], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "after": { + "ms": 30213.996153, + "scope_ms": 10663.045373, + "maxRssKiB": 1910132, + "loadBefore": [10.55, 11.43, 10.29], + "loadAfter": [13.09, 11.93, 10.49], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "change_percent": -0.8958687711658531 + } + ] + }, + "persistent": { + "before_session_medians_ms": { + "samples": [24619.465085000003, 30276.214410000015, 35277.003012], + "median": 30276.214410000015, + "min": 24619.465085000003, + "max": 35277.003012, + "standard_deviation": 4353.667856381744, + "cv_percent": 14.484434981881922 + }, + "after_session_medians_ms": { + "samples": [22883.167759999997, 29814.153575999997, 35026.18395899999], + "median": 29814.153575999997, + "min": 22883.167759999997, + "max": 35026.18395899999, + "standard_deviation": 4973.894824247497, + "cv_percent": 17.009904497732137 + }, + "change_percent": -1.5261512808133704, + "paired_change_percent": { + "samples": [ + -9.159571429407476, -7.763463257227798, -4.053410478963137, -21.4258822645351, + -1.374828412704443, -2.0887840531941593, 3.716134035588081, -17.56829308134683, + -0.71099875722066 + ], + "median": -4.053410478963137, + "min": -21.4258822645351, + "max": 3.716134035588081, + "standard_deviation": 7.768448880307043 + }, + "samples": [ + { + "session": 1, + "pair": 1, + "before": { + "ms": 25190.51056899999, + "scope_ms": 10669.653483000002, + "maxRssKiB": 2600492, + "loadBefore": [8.96, 11.48, 8.41], + "loadAfter": [8.76, 11.23, 8.41], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "after": { + "ms": 22883.167759999997, + "scope_ms": 9326.451480999996, + "maxRssKiB": 2733820, + "loadBefore": [8.76, 11.23, 8.41], + "loadAfter": [8.55, 10.98, 8.4], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "change_percent": -9.159571429407476 + }, + { + "session": 1, + "pair": 2, + "before": { + "ms": 24619.465085000003, + "scope_ms": 10660.948642999982, + "maxRssKiB": 2834936, + "loadBefore": [7.81, 10.62, 8.35], + "loadAfter": [7.53, 10.32, 8.31], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "save" + } + ] + }, + "after": { + "ms": 22708.141959, + "scope_ms": 8981.871341000005, + "maxRssKiB": 2894124, + "loadBefore": [8.55, 10.98, 8.4], + "loadAfter": [7.81, 10.62, 8.35], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "save" + } + ] + }, + "change_percent": -7.763463257227798 + }, + { + "session": 1, + "pair": 3, + "before": { + "ms": 24531.59210400001, + "scope_ms": 10001.811278000008, + "maxRssKiB": 2873708, + "loadBefore": [7.53, 10.32, 8.31], + "loadAfter": [7.41, 10.06, 8.28], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "after": { + "ms": 23537.22597899998, + "scope_ms": 9256.044935999991, + "maxRssKiB": 2986960, + "loadBefore": [7.41, 10.06, 8.28], + "loadAfter": [6.98, 9.75, 8.22], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "change_percent": -4.053410478963137 + }, + { + "session": 2, + "pair": 1, + "before": { + "ms": 37943.98770900001, + "scope_ms": 11086.613411999992, + "maxRssKiB": 2673196, + "loadBefore": [10.62, 9.82, 8.46], + "loadAfter": [10.39, 9.86, 8.53], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "after": { + "ms": 29814.153575999997, + "scope_ms": 9854.81807400001, + "maxRssKiB": 2552236, + "loadBefore": [9.7, 9.6, 8.34], + "loadAfter": [10.62, 9.82, 8.46], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "change_percent": -21.4258822645351 + }, + { + "session": 2, + "pair": 2, + "before": { + "ms": 30276.214410000015, + "scope_ms": 12005.400338000007, + "maxRssKiB": 2816756, + "loadBefore": [10.39, 9.86, 8.53], + "loadAfter": [11.7, 10.25, 8.7], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "save" + } + ] + }, + "after": { + "ms": 29859.968412000017, + "scope_ms": 10533.230467999994, + "maxRssKiB": 2813324, + "loadBefore": [11.7, 10.25, 8.7], + "loadAfter": [11.18, 10.26, 8.75], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "save" + } + ] + }, + "change_percent": -1.374828412704443 + }, + { + "session": 2, + "pair": 3, + "before": { + "ms": 29899.892047, + "scope_ms": 11824.771922000014, + "maxRssKiB": 2868456, + "loadBefore": [11.23, 10.36, 8.84], + "loadAfter": [9.84, 10.11, 8.81], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "after": { + "ms": 29275.347869999998, + "scope_ms": 10707.014708000002, + "maxRssKiB": 3146864, + "loadBefore": [11.18, 10.26, 8.75], + "loadAfter": [11.23, 10.36, 8.84], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "change_percent": -2.0887840531941593 + }, + { + "session": 3, + "pair": 1, + "before": { + "ms": 29568.35863500001, + "scope_ms": 10798.847978000005, + "maxRssKiB": 2454324, + "loadBefore": [14.88, 12.7, 10.95], + "loadAfter": [14.79, 12.84, 11.05], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "after": { + "ms": 30667.158473999996, + "scope_ms": 10579.910604999997, + "maxRssKiB": 2449224, + "loadBefore": [14.79, 12.84, 11.05], + "loadAfter": [14.48, 12.95, 11.15], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "change_percent": 3.716134035588081 + }, + { + "session": 3, + "pair": 2, + "before": { + "ms": 48961.37195100004, + "scope_ms": 17583.823956999986, + "maxRssKiB": 2750280, + "loadBefore": [21.17, 14.9, 11.89], + "loadAfter": [26.54, 17.48, 12.94], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "save" + } + ] + }, + "after": { + "ms": 40359.69463000001, + "scope_ms": 11766.693460999988, + "maxRssKiB": 2645752, + "loadBefore": [14.48, 12.95, 11.15], + "loadAfter": [21.17, 14.9, 11.89], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "save" + } + ] + }, + "change_percent": -17.56829308134683 + }, + { + "session": 3, + "pair": 3, + "before": { + "ms": 35277.003012, + "scope_ms": 13586.94374399999, + "maxRssKiB": 3042924, + "loadBefore": [26.54, 17.48, 12.94], + "loadAfter": [22.52, 17.48, 13.1], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "after": { + "ms": 35026.18395899999, + "scope_ms": 13313.036121999961, + "maxRssKiB": 2658640, + "loadBefore": [22.52, 17.48, 13.1], + "loadAfter": [20.43, 17.57, 13.3], + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + "change_percent": -0.71099875722066 + } + ] + } + }, + "validation": { + "targeted_tests": 59, + "source_typecheck": "passed", + "test_typecheck": "passed", + "build": "passed", + "eslint": "passed", + "formatting": "passed", + "differential_comparisons_per_session": 72000, + "semantic_graphs_equal": true, + "persisted_call_targets_follow_edits": true, + "noop_rejected": true + }, + "limitations": [ + "Shared machine; host load recorded for every sample.", + "Sparse CI corpus; these times do not replace the original full-repository numbers.", + "Three sessions per mode; three correlated edits within each session.", + "No holdout: selection and reporting use the same sample.", + "Timing includes analysis, graph persistence and FTS; excludes process startup and subsequent graph verification.", + "Semantic equality excludes derived Community, Process and Folder nodes, corresponding derived relationships, and cleared source content.", + "Repeated API analysis does not measure watch scheduling.", + "maxRSS is a process lifetime high-water mark, including prior samples in persistent mode.", + "PR head advanced during measurement; all results apply only to the recorded runtime and corpus pins." + ], + "aggregation": "Median of three session medians; each session contains three alternating edit pairs. The paired-change distribution is separately recorded.", + "decision": "Inconclusive for small gains: repeated-process candidate session CV is 17.01%, above the proposed 5% noise threshold. No additional runtime optimization made or accepted.", + "reproduction": { + "screen": "GITNEXUS_LEXICAL_BENCH_SCREEN=0", + "order": "GITNEXUS_LEXICAL_BENCH_BASE_FIRST=1,0,1 across sessions", + "lifecycleOrder": ["fresh,persistent", "persistent,fresh", "fresh,persistent"], + "workers": 2, + "heapMiB": 4096, + "corpus": "4916e0d5e1f4d6d70d41c1f39cd244bca2c7b390", + "snapshotNote": "Measured runner copied the PR harness, removed its early screen, and added ordering control. The tracked harness now exposes equivalent optional controls and records their values." + } +} diff --git a/gitnexus/bench/lexical-lookup/differential.mjs b/gitnexus/bench/lexical-lookup/differential.mjs new file mode 100644 index 000000000..35012799f --- /dev/null +++ b/gitnexus/bench/lexical-lookup/differential.mjs @@ -0,0 +1,109 @@ +import assert from 'node:assert/strict'; +import path from 'node:path'; +import { pathToFileURL } from 'node:url'; +const [baseline, candidate] = process.argv.slice(2); +assert(baseline && candidate, 'Expected BASE_RUNTIME CANDIDATE_RUNTIME'); +const moduleAt = (root) => + pathToFileURL(path.resolve(root, 'gitnexus/dist/_shared/scope-resolution/name-claims.js')).href; +const { lookupLexicalName: before } = await import(moduleAt(baseline)); +const { lookupLexicalName: after } = await import(moduleAt(candidate)); +let seed = 48161; +const random = (n) => { + seed = (Math.imul(seed, 1664525) + 1013904223) >>> 0; + return seed % n; +}; +const pos = (n) => ({ startLine: n, startCol: 0 }); +const range = (n) => ({ ...pos(n), endLine: n, endCol: 20 }); +const names = ['a', 'b', 'missing']; +let comparisons = 0; +for (let trial = 0; trial < 3000; trial++) { + const scopes = new Map(); + for (let i = 0; i < 5; i++) { + const claims = []; + const bindings = new Map(); + const types = new Map(); + const imports = []; + for (const name of names.slice(0, 2)) { + if (random(3) === 0) + claims.push({ + name, + kind: ['binding', 'import', 'blocked'][random(3)], + range: range(2 + random(8)), + purpose: ['value', 'type', 'both', undefined][random(4)], + availableFrom: random(2) ? pos(2 + random(8)) : undefined, + inactive: ['outer', 'blocked', 'module'][random(3)], + redirect: random(8) === 0 ? 'module' : undefined, + hoisted: random(2) === 0, + merge: random(3) === 0, + }); + if (random(2)) + bindings.set(name, [ + { + def: { nodeId: `${i}:${name}`, type: 'Function', filePath: 'a.ts' }, + origin: random(2) ? 'local' : 'import', + availableFrom: random(2) ? pos(5) : undefined, + declarationRange: range(5), + }, + ]); + if (random(3) === 0) + imports.push({ + kind: 'namespace', + localName: name, + targetFile: random(2) ? 'b.ts' : null, + targetExportedName: '', + atRange: range(4), + linkStatus: random(2) ? 'resolved' : 'unresolved', + }); + if (random(3) === 0) + types.set(name, { + rawName: 'Value', + source: [ + 'annotation', + 'constructor-inferred', + 'assignment-inferred', + 'receiver-propagated', + ][random(4)], + declaredAtScope: String(i), + bindingRange: random(2) ? range(5) : undefined, + }); + } + scopes.set(String(i), { + id: String(i), + parent: i === 0 ? null : String(i - 1), + kind: i === 0 ? 'Module' : ['Function', 'Block', 'Class', 'Object'][random(4)], + filePath: 'a.ts', + range: range(i), + bindings, + imports, + ownedDefs: [], + typeBindings: types, + nameClaims: claims, + lexicalNames: random(3) === 0 ? new Set(['a']) : undefined, + ownsReceivers: random(3) === 0 ? new Set(['b']) : undefined, + lookupPolicy: { + nameClaimsComplete: random(2) === 0, + deferParentActivation: random(2) === 0, + skipFromChildren: random(4) === 0, + }, + }); + } + if (trial % 20 === 0) scopes.get('0').parent = '4'; + const sources = { scopes: { getScope: (id) => scopes.get(id) } }; + for (const name of names) + for (const purpose of ['value', 'type']) + for (const position of [undefined, pos(1), pos(6), pos(12)]) { + const options = Object.freeze({ + purpose, + position, + skipEnclosingClasses: trial % 2 === 0, + preservePosition: trial % 3 === 0, + }); + assert.deepEqual( + after('4', name, sources, options), + before('4', name, sources, options), + `Trial ${trial}, ${name}, ${purpose}, line ${position?.startLine}`, + ); + comparisons++; + } +} +console.log({ comparisons, status: 'passed' }); diff --git a/gitnexus/bench/lexical-lookup/measure.mjs b/gitnexus/bench/lexical-lookup/measure.mjs new file mode 100644 index 000000000..dd8fe7f69 --- /dev/null +++ b/gitnexus/bench/lexical-lookup/measure.mjs @@ -0,0 +1,306 @@ +// Build both runtimes, then run with Node: +// measure.mjs BASE_RUNTIME CANDIDATE_RUNTIME BASE_CORPUS CANDIDATE_CORPUS OUTPUT [fresh|persistent] +// Corpus checkouts must be clean/disposable and at the same commit. OUTPUT must not exist. +import assert from 'node:assert/strict'; +import fs from 'node:fs'; +import path from 'node:path'; +import os from 'node:os'; +import { createHash } from 'node:crypto'; +import { execFileSync, fork } from 'node:child_process'; +import { fileURLToPath } from 'node:url'; +const args = process.argv.slice(2); +assert( + args.length >= 5 && args.slice(0, 5).every((value) => value !== ''), + 'Expected BASE_RUNTIME CANDIDATE_RUNTIME BASE_CORPUS CANDIDATE_CORPUS OUTPUT [fresh|persistent]', +); +const [baselineRuntime, candidateRuntime, baseline, candidate, output] = args + .slice(0, 5) + .map((value) => path.resolve(value)); +const lifecycle = args[5] ?? 'fresh'; +const workers = Number(process.env.GITNEXUS_LEXICAL_BENCH_WORKERS ?? 16); +const heapMiB = Number(process.env.GITNEXUS_LEXICAL_BENCH_HEAP_MIB ?? 8192); +const screenSetting = process.env.GITNEXUS_LEXICAL_BENCH_SCREEN ?? '1'; +const baseFirstSetting = process.env.GITNEXUS_LEXICAL_BENCH_BASE_FIRST ?? '1'; +assert(Number.isSafeInteger(workers) && workers > 0, 'Workers must be a positive integer'); +assert(Number.isSafeInteger(heapMiB) && heapMiB > 0, 'Heap MiB must be a positive integer'); +assert(['0', '1'].includes(screenSetting), 'Screen must be 0 or 1'); +assert(['0', '1'].includes(baseFirstSetting), 'Base first must be 0 or 1'); +const screen = screenSetting === '1'; +const baseFirst = baseFirstSetting === '1'; +assert( + ['fresh', 'persistent'].includes(lifecycle), + `Lifecycle must be fresh or persistent; received ${JSON.stringify(lifecycle)}`, +); +assert.notEqual(baseline, candidate, 'BASE_CORPUS and CANDIDATE_CORPUS must differ'); +const isWorker = process.env.GITNEXUS_LEXICAL_BENCH_WORKER === '1'; +let runFullAnalysis, initLbug, executeQuery, closeLbug; +if (!isWorker) assert(!fs.existsSync(output), 'Output already exists'); +const control = 'gitnexus/src/semantic-bench-control.ts'; +const source = + 'export class SemanticBenchStore { save(): void {} load(): void {} }\nexport function semanticBenchUse(s: SemanticBenchStore) { s.save(); }\n'; +const head = (repo) => + execFileSync('git', ['rev-parse', 'HEAD'], { cwd: repo, encoding: 'utf8' }).trim(); +assert.equal(head(baseline), head(candidate)); +for (const repo of isWorker ? [] : [baseline, candidate]) { + assert.equal( + execFileSync('git', ['status', '--porcelain'], { cwd: repo, encoding: 'utf8' }), + '', + 'Checkout must be clean', + ); + assert(!fs.existsSync(path.join(repo, control))); +} +fs.mkdirSync(output, { recursive: true }); +process.env.GITNEXUS_HOME = path.join(output, 'home'); +process.env.GITNEXUS_STORAGE_ROOT = path.join(output, 'indexes'); +delete process.env.GITNEXUS_STORAGE_PATH; +process.env.GITNEXUS_SHARED_STORE = 'off'; +process.env.PROF_SCOPE_RESOLUTION = '1'; +const records = []; +if (isWorker) { + const runtime = process.env.GITNEXUS_BENCH_RUNTIME; + ({ runFullAnalysis } = await import(path.join(runtime, 'gitnexus/dist/core/run-analyze.js'))); + ({ initLbug, executeQuery, closeLbug } = await import( + path.join(runtime, 'gitnexus/dist/core/lbug/lbug-adapter.js') + )); + const { configureLoggerSink } = await import(path.join(runtime, 'gitnexus/dist/core/logger.js')); + configureLoggerSink({ + destination: { + write(line) { + try { + records.push(JSON.parse(line)); + } catch { + /* non-JSON diagnostic */ + } + process.stderr.write(line); + }, + }, + }); +} +const results = []; +const canonical = (value) => + Array.isArray(value) + ? value.map(canonical) + : value && typeof value === 'object' + ? Object.fromEntries( + Object.keys(value) + .sort() + .map((key) => [key, canonical(value[key])]), + ) + : value; +const digest = (rows) => { + const hash = createHash('sha256'); + for (const row of rows.sort()) hash.update(row).update('\n'); + return { count: rows.length, sha256: hash.digest('hex') }; +}; + +async function sample(repo, isCandidate, name) { + process.env.GITNEXUS_EXPERIMENTAL_SEMANTIC_CACHE = '0'; + global.gc?.(); + records.length = 0; + const logs = []; + const progress = []; + const loadBefore = os.loadavg(); + const started = performance.now(); + const result = await runFullAnalysis( + repo, + { + skipAgentsMd: true, + skipSkills: true, + workerPoolSize: workers, + verbose: true, + }, + { + onProgress(phase, percent, message) { + if (progress.at(-1)?.phase !== phase) + progress.push({ ms: performance.now() - started, phase, percent, message }); + }, + onLog(message) { + logs.push(message); + }, + }, + ); + const ms = performance.now() - started; + assert(!result.alreadyUpToDate, 'A no-op is not an edit benchmark'); + assert(!result.graphWriteCollapsed); + assert(!result.ftsSkipped, 'This benchmark includes FTS'); + const graph = result.pipelineResult.graph; + const nodes = [], + edges = []; + for (const node of graph.iterNodes()) { + // Derived clustering is stochastic; compare all source/semantic properties. + if (['Community', 'Process', 'Folder'].includes(node.label)) continue; + nodes.push(JSON.stringify(canonical(node))); + } + let controlCalls = 0; + for (const edge of graph.iterRelationships()) { + if (['MEMBER_OF', 'STEP_IN_PROCESS', 'CONTAINS'].includes(edge.type)) continue; + edges.push(JSON.stringify(canonical(edge))); + if (edge.type === 'CALLS' && edge.sourceId.includes('semanticBenchUse')) controlCalls++; + } + assert(controlCalls > 0, 'The changed call must resolve'); + const expectedTarget = fs.readFileSync(path.join(repo, control), 'utf8').includes('s.load()') + ? 'load' + : 'save'; + let persistedTargets; + try { + await initLbug(path.join(result.storagePath, 'lbug'), { skipFts: true }); + persistedTargets = await executeQuery( + "MATCH (a:Function)-[r:CodeRelation]->(b:Method) WHERE a.name = 'semanticBenchUse' AND r.type = 'CALLS' RETURN b.name AS target", + ); + assert.deepEqual( + persistedTargets.map((row) => row.target), + [expectedTarget], + 'Persisted call must follow the edit', + ); + } finally { + await closeLbug(); + } + const report = { + name, + variant: isCandidate ? 'candidate' : 'baseline', + ms, + loadBefore, + loadAfter: os.loadavg(), + maxRssKiB: process.resourceUsage().maxRSS, + stats: result.stats, + incremental: result.incrementalStats, + rebuildReasons: result.rebuildReasons, + reparsedFiles: result.pipelineResult.reparsedFileCount, + cachedFiles: result.pipelineResult.parseCacheHitFileCount, + graph: { nodes: digest(nodes), edges: digest(edges) }, + logs, + progress, + persistedTargets, + records: [...records], + }; + console.log( + 'LEXICAL_BENCH ' + + JSON.stringify({ name, ms, incremental: report.incremental, graph: report.graph }), + ); + return report; +} + +// Separate runtimes isolate implementation and JIT state. Fresh mode exits +// after every sample; persistent mode retains a process across real edits. +function worker(repo, isCandidate) { + let child, pending, exited; + const start = () => { + child = fork(fileURLToPath(import.meta.url), process.argv.slice(2), { + execArgv: [`--max-old-space-size=${heapMiB}`, '--expose-gc'], + env: { + ...process.env, + GITNEXUS_LEXICAL_BENCH_WORKER: '1', + GITNEXUS_BENCH_RUNTIME: isCandidate ? candidateRuntime : baselineRuntime, + }, + stdio: ['ignore', 'inherit', 'inherit', 'ipc'], + }); + exited = new Promise((resolve) => child.once('exit', resolve)); + child.on('message', (message) => { + const current = pending; + pending = undefined; + if (message.error) current?.reject(new Error(message.error)); + else current?.resolve(message.report); + }); + child.on('error', (error) => pending?.reject(error)); + child.on('exit', (code) => pending?.reject(new Error(`Benchmark worker exited: ${code}`))); + }; + const close = async () => { + if (!child) return; + if (child.connected) child.disconnect(); + const code = await exited; + child = undefined; + assert.equal(code, 0, 'Worker must exit normally after analysis'); + }; + return { + async run(name) { + assert(!pending, 'Samples must run serially'); + if (!child) start(); + const report = await new Promise((resolve, reject) => { + pending = { resolve, reject }; + child.send({ repo, reuse: isCandidate, name }); + }); + results.push(report); + fs.writeFileSync( + path.join(output, 'results.json'), + JSON.stringify( + { + head: head(repo), + node: process.version, + lifecycle, + workers, + heapMiB, + screen, + baseFirst, + baselineRuntime, + candidateRuntime, + results, + }, + null, + 2, + ), + ); + if (lifecycle === 'fresh') await close(); + return report; + }, + close, + }; +} + +if (isWorker) { + process.on('message', async ({ repo, reuse: isCandidate, name }) => { + try { + process.send({ report: await sample(repo, isCandidate, name) }); + } catch (error) { + process.send({ error: error.stack ?? String(error) }); + } + }); +} else { + const beforeWorker = worker(baseline, false); + const afterWorker = worker(candidate, true); + try { + for (const repo of [baseline, candidate]) { + fs.mkdirSync(path.dirname(path.join(repo, control)), { recursive: true }); + fs.writeFileSync(path.join(repo, control), source); + } + let beforeSeed, afterSeed; + if (baseFirst) { + beforeSeed = await beforeWorker.run('baseline-seed'); + afterSeed = await afterWorker.run('candidate-seed'); + } else { + afterSeed = await afterWorker.run('candidate-seed'); + beforeSeed = await beforeWorker.run('baseline-seed'); + } + assert.deepEqual(afterSeed.graph, beforeSeed.graph, 'Seed semantic graphs differ'); + for (let pair = 1; pair <= 3; pair++) { + const text = pair % 2 ? source.replace('s.save()', 's.load()') : source; + for (const repo of [baseline, candidate]) fs.writeFileSync(path.join(repo, control), text); + // Alternate ordering to reduce warm-up/load bias. Both indexes see a real edit. + let before, after; + if (Boolean(pair % 2) === baseFirst) { + before = await beforeWorker.run(`baseline-${pair}`); + after = await afterWorker.run(`candidate-${pair}`); + } else { + after = await afterWorker.run(`candidate-${pair}`); + before = await beforeWorker.run(`baseline-${pair}`); + } + assert.deepEqual( + after.graph, + before.graph, + 'Semantic graph differs from a full semantic pass', + ); + for (const entry of [before, after]) { + assert.equal(entry.incremental?.writeMode, 'incremental'); + assert.equal(entry.incremental?.changedFiles, 1); + assert.deepEqual(entry.rebuildReasons, []); + } + if (screen && pair === 1 && after.ms >= before.ms) { + console.log('SCREEN REJECTED: no end-to-end improvement; stopping after one pair.'); + break; + } + } + } finally { + const closed = await Promise.allSettled([beforeWorker.close(), afterWorker.close()]); + for (const repo of [baseline, candidate]) fs.rmSync(path.join(repo, control), { force: true }); + for (const result of closed) if (result.status === 'rejected') throw result.reason; + } +} diff --git a/gitnexus/bench/lexical-lookup/measurements.json b/gitnexus/bench/lexical-lookup/measurements.json new file mode 100644 index 000000000..832ed444d --- /dev/null +++ b/gitnexus/bench/lexical-lookup/measurements.json @@ -0,0 +1,735 @@ +{ + "date": "2026-11-02", + "baseCommit": "347cc99b4a237f9a71c0084167bcbcbd9d06e610", + "node": "v22.23.3", + "ladybug": "0.22.0", + "hardware": { + "cpu": "12th Gen Intel(R) Core(TM) i9-12900K", + "logicalCpus": 24, + "platform": "linux", + "arch": "x64" + }, + "settings": { + "workers": 16, + "heapMiB": 8192, + "sharedHost": true, + "scopePhaseLogging": true, + "cpuProfile": false, + "independentColdSeeds": true + }, + "measurement": { + "timed": "runFullAnalysis including graph persistence and FTS", + "excluded": ["process startup", "graph hashing", "post-analysis persisted target query"], + "editOrder": [ + "baseline-1", + "candidate-1", + "candidate-2", + "baseline-2", + "baseline-3", + "candidate-3" + ], + "graphExclusions": [ + "Folder", + "Community", + "Process", + "CONTAINS", + "MEMBER_OF", + "STEP_IN_PROCESS" + ], + "limitations": [ + "three fresh-process pairs and one repeated-process pair on a shared host", + "graph hashes are post-persistence; source content may have been cleared", + "persistent process exercises repeated analysis, not watch event scheduling", + "baseline resolution limits also apply to candidate", + "process maxRSS includes earlier samples in persistent mode" + ] + }, + "pin": { + "patchSha256": "a61b37f5ab42a95a62ae96510a5e285cb9b835a3f983ce4a96ecd0413504ea43", + "runtimes": { + "baseline": { + "gitnexus/dist/_shared/scope-resolution/name-claims.js": "157fd1ff2870468d335f97fff41d0b002f4cad749db64634aa48469053d7cea3", + "gitnexus/dist/core/ingestion/scope-resolution/scope/walkers.js": "15dba69d6ec871e43f4d0d1aadbad93e1645c13a9ad2e664e9f9bd679f73e55c" + }, + "candidate": { + "gitnexus/dist/_shared/scope-resolution/name-claims.js": "6f998066bcb3f17d69f2dbae7dba1a1d5af865bc8798d4b137aaed9387a81284", + "gitnexus/dist/core/ingestion/scope-resolution/scope/walkers.js": "9400ed640a22343f6cc54e3515944af664022ac7f4a8c4306da0cc95df37f9e1" + } + } + }, + "harnessSha256": "dbd428561cd614b8f0fb2dda48ad5445e214bea02a9c39f201cc2488bd7a81c8", + "harnessProvenance": "Checksums identify the scripts used for measurement, before repository formatting, preflight/cleanup fixes and configurable CI worker/heap limits. Local resource defaults are unchanged.", + "differential": { + "seed": 48161, + "comparisons": 72000, + "status": "passed", + "harnessSha256": "8a34834c153531daa9f6000e178fc87458e48d3507c8c6e20e2738f739413e88" + }, + "runs": { + "fresh": { + "rawResultSha256": "3da8095b17ecbb5099164220152f8c9582268868db6a7d23b2565d987f2a7d6d", + "samples": [ + { + "name": "baseline-seed", + "variant": "baseline", + "ms": 218218.857255, + "loadBefore": [19.08, 16.18, 14.03], + "loadAfter": [13.58, 16.53, 14.82], + "maxRssKiB": 5929416, + "rebuildReasons": [], + "reparsedFiles": 3120, + "cachedFiles": 0, + "phaseMs": { + "extracting": 307.5897699999996, + "structure": 59.0564260000001, + "parsing": 77980.037363, + "scopeResolution": 80390.527192, + "enriching": 36.09870200001751, + "communities": 2342.1585379999888, + "processes": 659.8627029999916, + "complete": 0.06783200000063516, + "lbug": 17391.16107600002, + "fts": 29286.008015999978, + "done": 6083.309720000019, + "beforeFirstProgress": 3682.979917 + }, + "scopeLogs": [ + "[scope-resolution prof] extract=21ms finalize=71ms propagate=78ms rangeBind=0.0ms resolve=175ms emit=1547ms total=1891ms (110 files)", + "[scope-resolution prof] extract=2649ms finalize=1451ms propagate=1426ms rangeBind=0.0ms resolve=7468ms emit=41291ms total=54285ms (2893 files)", + "[scope-resolution prof] extract=270ms finalize=65ms propagate=61ms rangeBind=0.0ms resolve=444ms emit=1835ms total=2675ms (113 files)" + ], + "graph": { + "nodes": { + "count": 114413, + "sha256": "d2e2ee693005fee4770a654b1391f5348d7b03316d57bf0e7bceb4cf6787f9ad" + }, + "edges": { + "count": 318798, + "sha256": "595afccf9f3fa2725727f3439cb5fd7b1aadd18ae6aca4eaa478ef00b793fe21" + } + }, + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "candidate-seed", + "variant": "candidate", + "ms": 187147.92687899998, + "loadBefore": [13.13, 16.39, 14.78], + "loadAfter": [11.64, 15.07, 14.65], + "maxRssKiB": 5912680, + "rebuildReasons": [], + "reparsedFiles": 3120, + "cachedFiles": 0, + "phaseMs": { + "extracting": 248.5604829999993, + "structure": 55.20889800000077, + "parsing": 62435.270292, + "scopeResolution": 61285.705398999984, + "enriching": 31.93969999998808, + "communities": 2074.6883160000143, + "processes": 544.6516690000135, + "complete": 0.05536599998595193, + "lbug": 16684.85912899999, + "fts": 29567.160881000018, + "done": 5673.711943999981, + "beforeFirstProgress": 8546.114802 + }, + "scopeLogs": [ + "[scope-resolution prof] extract=18ms finalize=60ms propagate=52ms rangeBind=0.0ms resolve=118ms emit=1176ms total=1425ms (110 files)", + "[scope-resolution prof] extract=2048ms finalize=1153ms propagate=1045ms rangeBind=0.0ms resolve=5119ms emit=31736ms total=41101ms (2893 files)", + "[scope-resolution prof] extract=201ms finalize=62ms propagate=64ms rangeBind=0.0ms resolve=282ms emit=1469ms total=2078ms (113 files)" + ], + "graph": { + "nodes": { + "count": 114413, + "sha256": "d2e2ee693005fee4770a654b1391f5348d7b03316d57bf0e7bceb4cf6787f9ad" + }, + "edges": { + "count": 318798, + "sha256": "595afccf9f3fa2725727f3439cb5fd7b1aadd18ae6aca4eaa478ef00b793fe21" + } + }, + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "baseline-1", + "variant": "baseline", + "ms": 122065.065072, + "loadBefore": [11.43, 14.97, 14.62], + "loadAfter": [8.47, 12.61, 13.79], + "maxRssKiB": 4474272, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 22, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 22, + "cachedFiles": 3098, + "phaseMs": { + "extracting": 221.9082469999994, + "structure": 52.67533299999923, + "parsing": 8765.232970000001, + "scopeResolution": 65945.25450899999, + "enriching": 121.54619799999637, + "complete": 0.25131200000760145, + "lbug": 10923.801725000012, + "communities": 2019.391571, + "processes": 5888.645534999989, + "fts": 13240.190296, + "done": 8270.738006, + "beforeFirstProgress": 6615.429370000001 + }, + "scopeLogs": [ + "[scope-resolution prof] extract=19ms finalize=60ms propagate=58ms rangeBind=0.0ms resolve=148ms emit=1294ms total=1578ms (110 files)", + "[scope-resolution prof] extract=2031ms finalize=1178ms propagate=1108ms rangeBind=0.0ms resolve=6717ms emit=35251ms total=46284ms (2893 files)", + "[scope-resolution prof] extract=232ms finalize=61ms propagate=59ms rangeBind=0.0ms resolve=379ms emit=1552ms total=2283ms (113 files)" + ], + "graph": { + "nodes": { + "count": 114413, + "sha256": "d2e2ee693005fee4770a654b1391f5348d7b03316d57bf0e7bceb4cf6787f9ad" + }, + "edges": { + "count": 318798, + "sha256": "4ece58529c66b824a32ee5b1c3f642193279f98e39d95eea53bf2f5ec1700ae8" + } + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + { + "name": "candidate-1", + "variant": "candidate", + "ms": 111134.852017, + "loadBefore": [8.47, 12.61, 13.79], + "loadAfter": [7.79, 11.1, 13.1], + "maxRssKiB": 4406608, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 22, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 22, + "cachedFiles": 3098, + "phaseMs": { + "extracting": 228.39688900000056, + "structure": 58.946551, + "parsing": 7914.542683, + "scopeResolution": 62759.170073999994, + "enriching": 126.18967100000009, + "complete": 0.17001499999605585, + "lbug": 9233.545855000018, + "communities": 1969.2113839999947, + "processes": 1475.3109669999976, + "fts": 12857.877876999992, + "done": 8347.120962, + "beforeFirstProgress": 6164.369089 + }, + "scopeLogs": [ + "[scope-resolution prof] extract=15ms finalize=57ms propagate=51ms rangeBind=0.0ms resolve=115ms emit=1221ms total=1459ms (110 files)", + "[scope-resolution prof] extract=2192ms finalize=1268ms propagate=1122ms rangeBind=0.0ms resolve=5371ms emit=33985ms total=43937ms (2893 files)", + "[scope-resolution prof] extract=176ms finalize=75ms propagate=55ms rangeBind=0.0ms resolve=253ms emit=1333ms total=1892ms (113 files)" + ], + "graph": { + "nodes": { + "count": 114413, + "sha256": "d2e2ee693005fee4770a654b1391f5348d7b03316d57bf0e7bceb4cf6787f9ad" + }, + "edges": { + "count": 318798, + "sha256": "4ece58529c66b824a32ee5b1c3f642193279f98e39d95eea53bf2f5ec1700ae8" + } + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + { + "name": "candidate-2", + "variant": "candidate", + "ms": 101730.29475, + "loadBefore": [7.79, 11.1, 13.1], + "loadAfter": [8.7, 10.56, 12.7], + "maxRssKiB": 4447528, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 22, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 22, + "cachedFiles": 3098, + "phaseMs": { + "extracting": 227.87885000000006, + "structure": 50.07236400000011, + "parsing": 6870.926647, + "scopeResolution": 58457.57910199999, + "enriching": 123.74990100000286, + "complete": 0.12248400000680704, + "lbug": 9597.999660000001, + "communities": 1855.2971499999985, + "processes": 1319.511560999992, + "fts": 12526.206298000005, + "done": 8028.759919000004, + "beforeFirstProgress": 2672.190814 + }, + "scopeLogs": [ + "[scope-resolution prof] extract=14ms finalize=61ms propagate=47ms rangeBind=0.0ms resolve=103ms emit=1077ms total=1302ms (110 files)", + "[scope-resolution prof] extract=1860ms finalize=1052ms propagate=1064ms rangeBind=0.0ms resolve=4989ms emit=31810ms total=40774ms (2893 files)", + "[scope-resolution prof] extract=189ms finalize=62ms propagate=52ms rangeBind=0.0ms resolve=258ms emit=1383ms total=1943ms (113 files)" + ], + "graph": { + "nodes": { + "count": 114413, + "sha256": "d2e2ee693005fee4770a654b1391f5348d7b03316d57bf0e7bceb4cf6787f9ad" + }, + "edges": { + "count": 318798, + "sha256": "595afccf9f3fa2725727f3439cb5fd7b1aadd18ae6aca4eaa478ef00b793fe21" + } + }, + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "baseline-2", + "variant": "baseline", + "ms": 114005.953714, + "loadBefore": [8.7, 10.56, 12.7], + "loadAfter": [9.5, 10.18, 12.3], + "maxRssKiB": 4501784, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 22, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 22, + "cachedFiles": 3098, + "phaseMs": { + "extracting": 220.18439399999988, + "structure": 56.05602999999974, + "parsing": 6693.682359, + "scopeResolution": 68196.749623, + "enriching": 136.36504800000694, + "complete": 0.24019299999054056, + "lbug": 10199.119456000015, + "communities": 1921.6023549999954, + "processes": 1269.8549959999946, + "fts": 12961.042190000007, + "done": 8423.348173999999, + "beforeFirstProgress": 3927.708896 + }, + "scopeLogs": [ + "[scope-resolution prof] extract=15ms finalize=63ms propagate=59ms rangeBind=0.0ms resolve=129ms emit=1239ms total=1506ms (110 files)", + "[scope-resolution prof] extract=2317ms finalize=1312ms propagate=1295ms rangeBind=0.0ms resolve=7098ms emit=36604ms total=48627ms (2893 files)", + "[scope-resolution prof] extract=225ms finalize=58ms propagate=59ms rangeBind=0.0ms resolve=366ms emit=1623ms total=2331ms (113 files)" + ], + "graph": { + "nodes": { + "count": 114413, + "sha256": "d2e2ee693005fee4770a654b1391f5348d7b03316d57bf0e7bceb4cf6787f9ad" + }, + "edges": { + "count": 318798, + "sha256": "595afccf9f3fa2725727f3439cb5fd7b1aadd18ae6aca4eaa478ef00b793fe21" + } + }, + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "baseline-3", + "variant": "baseline", + "ms": 131285.117027, + "loadBefore": [9.94, 10.26, 12.32], + "loadAfter": [11.35, 10.88, 12.28], + "maxRssKiB": 4423784, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 22, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 22, + "cachedFiles": 3098, + "phaseMs": { + "extracting": 246.84667200000013, + "structure": 55.95557000000008, + "parsing": 7195.49225, + "scopeResolution": 72694.88498100001, + "enriching": 136.15589299998828, + "complete": 0.1802390000084415, + "lbug": 13022.899677999987, + "communities": 2414.3188599999994, + "processes": 1639.1324740000127, + "fts": 14523.853445, + "done": 16550.80450099999, + "beforeFirstProgress": 2804.592464 + }, + "scopeLogs": [ + "[scope-resolution prof] extract=17ms finalize=67ms propagate=66ms rangeBind=0.0ms resolve=138ms emit=1370ms total=1658ms (110 files)", + "[scope-resolution prof] extract=2113ms finalize=1144ms propagate=1129ms rangeBind=0.0ms resolve=7406ms emit=40471ms total=52262ms (2893 files)", + "[scope-resolution prof] extract=255ms finalize=74ms propagate=68ms rangeBind=0.0ms resolve=393ms emit=1821ms total=2611ms (113 files)" + ], + "graph": { + "nodes": { + "count": 114413, + "sha256": "d2e2ee693005fee4770a654b1391f5348d7b03316d57bf0e7bceb4cf6787f9ad" + }, + "edges": { + "count": 318798, + "sha256": "4ece58529c66b824a32ee5b1c3f642193279f98e39d95eea53bf2f5ec1700ae8" + } + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + { + "name": "candidate-3", + "variant": "candidate", + "ms": 111303.319634, + "loadBefore": [11, 10.82, 12.25], + "loadAfter": [8.98, 10.27, 11.9], + "maxRssKiB": 4458828, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 22, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 22, + "cachedFiles": 3098, + "phaseMs": { + "extracting": 224.80108500000006, + "structure": 54.754461999999876, + "parsing": 9906.336681, + "scopeResolution": 62344.37333, + "enriching": 117.25856000000203, + "complete": 0.1237049999908777, + "lbug": 9196.625813000006, + "communities": 2015.0293479999964, + "processes": 3180.0593300000037, + "fts": 12870.898965, + "done": 7974.200893999994, + "beforeFirstProgress": 3418.8574609999996 + }, + "scopeLogs": [ + "[scope-resolution prof] extract=22ms finalize=74ms propagate=61ms rangeBind=0.0ms resolve=115ms emit=1269ms total=1540ms (110 files)", + "[scope-resolution prof] extract=2053ms finalize=1125ms propagate=1129ms rangeBind=0.0ms resolve=5562ms emit=32778ms total=42647ms (2893 files)", + "[scope-resolution prof] extract=215ms finalize=61ms propagate=54ms rangeBind=0.0ms resolve=267ms emit=1445ms total=2041ms (113 files)" + ], + "graph": { + "nodes": { + "count": 114413, + "sha256": "d2e2ee693005fee4770a654b1391f5348d7b03316d57bf0e7bceb4cf6787f9ad" + }, + "edges": { + "count": 318798, + "sha256": "4ece58529c66b824a32ee5b1c3f642193279f98e39d95eea53bf2f5ec1700ae8" + } + }, + "persistedTargets": [ + { + "target": "load" + } + ] + } + ], + "summary": { + "baseline": { + "editCount": 3, + "medianMs": 122065.065072, + "sumMs": 367356.13581300003, + "medianScopeMs": 68196.749623, + "maxRssKiB": 4501784 + }, + "candidate": { + "editCount": 3, + "medianMs": 111134.852017, + "sumMs": 324168.466401, + "medianScopeMs": 62344.37333, + "maxRssKiB": 4458828 + }, + "medianReductionPercent": 8.954415457488041, + "aggregateReductionPercent": 11.756349003514243, + "scopeMedianReductionPercent": 8.581605905490585 + } + }, + "persistent": { + "rawResultSha256": "b09e4f487c1933281a4f875620b5ac5a23794e56246d6c317dd6d3196762293e", + "samples": [ + { + "name": "baseline-seed", + "variant": "baseline", + "ms": 158147.924033, + "loadBefore": [3.28, 6.72, 10.14], + "loadAfter": [5.3, 7.19, 9.87], + "maxRssKiB": 5757604, + "rebuildReasons": [], + "reparsedFiles": 3120, + "cachedFiles": 0, + "phaseMs": { + "extracting": 205.49587699999938, + "structure": 49.78513100000055, + "parsing": 58223.494267999995, + "scopeResolution": 62109.850408000006, + "enriching": 31.760779000003822, + "communities": 1872.6300760000013, + "processes": 506.77787499999977, + "complete": 0.04477599999518134, + "lbug": 10664.06607499998, + "fts": 18818.957672999997, + "done": 2247.716622000007, + "beforeFirstProgress": 3417.344473 + }, + "scopeLogs": [ + "[scope-resolution prof] extract=16ms finalize=59ms propagate=66ms rangeBind=0.0ms resolve=132ms emit=1181ms total=1454ms (110 files)", + "[scope-resolution prof] extract=1988ms finalize=1096ms propagate=1099ms rangeBind=0.0ms resolve=6393ms emit=33758ms total=44335ms (2893 files)", + "[scope-resolution prof] extract=168ms finalize=64ms propagate=50ms rangeBind=0.0ms resolve=322ms emit=1375ms total=1978ms (113 files)" + ], + "graph": { + "nodes": { + "count": 114413, + "sha256": "d2e2ee693005fee4770a654b1391f5348d7b03316d57bf0e7bceb4cf6787f9ad" + }, + "edges": { + "count": 318798, + "sha256": "595afccf9f3fa2725727f3439cb5fd7b1aadd18ae6aca4eaa478ef00b793fe21" + } + }, + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "candidate-seed", + "variant": "candidate", + "ms": 153951.283825, + "loadBefore": [5.3, 7.19, 9.87], + "loadAfter": [6.35, 7.83, 9.77], + "maxRssKiB": 5734340, + "rebuildReasons": [], + "reparsedFiles": 3120, + "cachedFiles": 0, + "phaseMs": { + "extracting": 226.53108299999963, + "structure": 46.397985999999946, + "parsing": 58254.662231, + "scopeResolution": 61421.754931999996, + "enriching": 35.70321300000069, + "communities": 1928.893007000006, + "processes": 529.0402800000011, + "complete": 0.05887399999483023, + "lbug": 10686.215123000002, + "fts": 16689.450012999994, + "done": 2236.283251999994, + "beforeFirstProgress": 1896.2938310000002 + }, + "scopeLogs": [ + "[scope-resolution prof] extract=16ms finalize=54ms propagate=49ms rangeBind=0.0ms resolve=108ms emit=1134ms total=1361ms (110 files)", + "[scope-resolution prof] extract=2107ms finalize=1253ms propagate=1084ms rangeBind=0.0ms resolve=5107ms emit=32228ms total=41779ms (2893 files)", + "[scope-resolution prof] extract=172ms finalize=65ms propagate=52ms rangeBind=0.0ms resolve=270ms emit=1373ms total=1932ms (113 files)" + ], + "graph": { + "nodes": { + "count": 114413, + "sha256": "d2e2ee693005fee4770a654b1391f5348d7b03316d57bf0e7bceb4cf6787f9ad" + }, + "edges": { + "count": 318798, + "sha256": "595afccf9f3fa2725727f3439cb5fd7b1aadd18ae6aca4eaa478ef00b793fe21" + } + }, + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "baseline-1", + "variant": "baseline", + "ms": 109482.844232, + "loadBefore": [6.35, 7.83, 9.77], + "loadAfter": [3.81, 6.46, 9.05], + "maxRssKiB": 5757604, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 22, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 22, + "cachedFiles": 3098, + "phaseMs": { + "extracting": 211.5071590000298, + "structure": 41.07579499995336, + "parsing": 7984.799295000033, + "scopeResolution": 67012.942599, + "enriching": 124.94524899998214, + "complete": 0.18859700002940372, + "lbug": 8813.617234999954, + "communities": 1921.8943519999739, + "processes": 1619.4587620000239, + "fts": 10599.878043000004, + "done": 8947.475924000028, + "beforeFirstProgress": 2205.0612219999894 + }, + "scopeLogs": [ + "[scope-resolution prof] extract=12ms finalize=49ms propagate=55ms rangeBind=0.0ms resolve=133ms emit=1216ms total=1467ms (110 files)", + "[scope-resolution prof] extract=2000ms finalize=1107ms propagate=1133ms rangeBind=0.0ms resolve=7186ms emit=37166ms total=48593ms (2893 files)", + "[scope-resolution prof] extract=164ms finalize=57ms propagate=58ms rangeBind=0.0ms resolve=346ms emit=1455ms total=2081ms (113 files)" + ], + "graph": { + "nodes": { + "count": 114413, + "sha256": "d2e2ee693005fee4770a654b1391f5348d7b03316d57bf0e7bceb4cf6787f9ad" + }, + "edges": { + "count": 318798, + "sha256": "4ece58529c66b824a32ee5b1c3f642193279f98e39d95eea53bf2f5ec1700ae8" + } + }, + "persistedTargets": [ + { + "target": "load" + } + ] + }, + { + "name": "candidate-1", + "variant": "candidate", + "ms": 123364.35062099999, + "loadBefore": [3.81, 6.46, 9.05], + "loadAfter": [12.23, 8.31, 9.37], + "maxRssKiB": 5896624, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 22, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 22, + "cachedFiles": 3098, + "phaseMs": { + "extracting": 221.45905800000764, + "structure": 46.565340999979526, + "parsing": 7283.348788000003, + "scopeResolution": 65739.48159400001, + "enriching": 129.2759209999931, + "complete": 0.21377500001108274, + "lbug": 12901.81731199997, + "communities": 2457.193612000032, + "processes": 2556.050026999961, + "fts": 14765.58123000001, + "done": 14857.72775999998, + "beforeFirstProgress": 2405.636203000031 + }, + "scopeLogs": [ + "[scope-resolution prof] extract=11ms finalize=47ms propagate=51ms rangeBind=0.0ms resolve=107ms emit=1124ms total=1340ms (110 files)", + "[scope-resolution prof] extract=2046ms finalize=1134ms propagate=1135ms rangeBind=0.0ms resolve=5161ms emit=34994ms total=44470ms (2893 files)", + "[scope-resolution prof] extract=407ms finalize=69ms propagate=71ms rangeBind=0.0ms resolve=369ms emit=2216ms total=3132ms (113 files)" + ], + "graph": { + "nodes": { + "count": 114413, + "sha256": "d2e2ee693005fee4770a654b1391f5348d7b03316d57bf0e7bceb4cf6787f9ad" + }, + "edges": { + "count": 318798, + "sha256": "4ece58529c66b824a32ee5b1c3f642193279f98e39d95eea53bf2f5ec1700ae8" + } + }, + "persistedTargets": [ + { + "target": "load" + } + ] + } + ], + "summary": { + "baseline": { + "editCount": 1, + "medianMs": 109482.844232, + "sumMs": 109482.844232, + "medianScopeMs": 67012.942599, + "maxRssKiB": 5757604 + }, + "candidate": { + "editCount": 1, + "medianMs": 123364.35062099999, + "sumMs": 123364.35062099999, + "medianScopeMs": 65739.48159400001, + "maxRssKiB": 5896624 + }, + "medianReductionPercent": -12.679161275335815, + "aggregateReductionPercent": -12.679161275335815, + "scopeMedianReductionPercent": 1.9003209762333162 + } + } + }, + "decision": "Experimental: fresh-process screen positive; persistent screen stopped after first non-improving pair; benefit for both workflows unproven", + "validation": { + "runtimePinsVerifiedAfterRuns": true, + "focusedTests": { + "files": 6, + "tests": 137, + "status": "passed" + }, + "scopeTests": { + "files": 175, + "tests": 3467, + "status": "passed", + "overlapWithFocused": true + }, + "differentialComparisons": 72000, + "parameterizedDifferentialRerun": "passed", + "build": "passed for both runtimes", + "testTypecheck": "passed", + "eslint": "passed; existing warnings", + "fullSuite": "not run" + } +} diff --git a/gitnexus/bench/lexical-lookup/optimization-20261103.json b/gitnexus/bench/lexical-lookup/optimization-20261103.json new file mode 100644 index 000000000..158a6102e --- /dev/null +++ b/gitnexus/bench/lexical-lookup/optimization-20261103.json @@ -0,0 +1,6310 @@ +{ + "date": "2026-11-03T09:41:53.604Z", + "pr": "https://github.com/abhigyanpatwari/GitNexus/pull/3805", + "referenceHead": "6aeeace8e96603fb062dcc709e834042d5a6df74", + "corpusHead": "4916e0d5e1f4d6d70d41c1f39cd244bca2c7b390", + "environment": { + "node": "v22.23.3", + "ladybug": "0.22.0", + "cpu": "12th Gen Intel(R) Core(TM) i9-12900K", + "workers": 2, + "heapMiB": 4096, + "sharedHost": true + }, + "protocol": { + "pairsPerLifecyclePerSession": 3, + "coldSeedsExcluded": true, + "noEarlyPairScreen": true, + "oppositeSessionOrder": true, + "requiredWarmImprovementPercent": 5, + "maxFreshRegressionPercent": 3, + "confirmationSessionsRequiredForKeep": 3, + "holdout": false + }, + "historicalBaseline": "baseline-20261103.json", + "runtimeChangesKept": 0, + "profiles": { + "cpu": { + "totalProfileMs": 29707.414000000248, + "modules": [ + { + "name": "walkers", + "ms": 3086.69, + "percent": 10.39 + }, + { + "name": "name-claims", + "ms": 2345.48, + "percent": 7.9 + } + ], + "self": [ + { + "name": "(idle) :0", + "ms": 10261.18, + "percent": 34.54 + }, + { + "name": "(garbage collector) :0", + "ms": 2528.01, + "percent": 8.51 + }, + { + "name": "spawn :0", + "ms": 1234.65, + "percent": 4.16 + }, + { + "name": "deserialize node:v8:433", + "ms": 1173.64, + "percent": 3.95 + }, + { + "name": "lookupLexicalName dist/_shared/scope-resolution/name-claims.js:133", + "ms": 941.19, + "percent": 3.17 + }, + { + "name": "NodeQueryResult :0", + "ms": 840.55, + "percent": 2.83 + }, + { + "name": "walk dist/storage/v8-sidecar.js:44", + "ms": 699.42, + "percent": 2.35 + }, + { + "name": "(program) :0", + "ms": 661.35, + "percent": 2.23 + }, + { + "name": "internString dist/storage/v8-sidecar.js:28", + "ms": 443.93, + "percent": 1.49 + }, + { + "name": "bindingsAt dist/core/ingestion/scope-resolution/scope/walkers.js:37", + "ms": 431.27, + "percent": 1.45 + }, + { + "name": "runScopeResolution dist/core/ingestion/scope-resolution/pipeline/run.js:414", + "ms": 331.81, + "percent": 1.12 + }, + { + "name": "emitReceiverBoundCalls dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js:437", + "ms": 328.57, + "percent": 1.11 + }, + { + "name": "nameClaimsFor dist/_shared/scope-resolution/name-claims.js:15", + "ms": 292.55, + "percent": 0.98 + }, + { + "name": "getScope dist/_shared/scope-resolution/scope-tree.js:116", + "ms": 275.44, + "percent": 0.93 + }, + { + "name": "selectClaimsAtScope dist/_shared/scope-resolution/name-claims.js:60", + "ms": 270.44, + "percent": 0.91 + }, + { + "name": "resolveDefGraphId dist/core/ingestion/scope-resolution/graph-bridge/ids.js:208", + "ms": 261.89, + "percent": 0.88 + }, + { + "name": "update :0", + "ms": 230.57, + "percent": 0.78 + }, + { + "name": "buildGraphNodeLookup dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js:112", + "ms": 224.25, + "percent": 0.75 + }, + { + "name": "post node:inspector:118", + "ms": 182.18, + "percent": 0.61 + }, + { + "name": "resolveDefGraphIdUncached dist/core/ingestion/scope-resolution/graph-bridge/ids.js:227", + "ms": 180.8, + "percent": 0.61 + }, + { + "name": "get dist/_shared/scope-resolution/def-index.js:43", + "ms": 168.63, + "percent": 0.57 + }, + { + "name": "resolveCompoundReceiverClass dist/core/ingestion/scope-resolution/passes/compound-receiver.js:723", + "ms": 157.91, + "percent": 0.53 + }, + { + "name": "addToBucket dist/core/graph/graph.js:28", + "ms": 152.6, + "percent": 0.51 + }, + { + "name": "lookupNameClaim dist/core/ingestion/scope-resolution/scope/walkers.js:33", + "ms": 146.33, + "percent": 0.49 + }, + { + "name": "findClassBindingInScope dist/core/ingestion/scope-resolution/scope/walkers.js:786", + "ms": 133.03, + "percent": 0.45 + }, + { + "name": "addRelationship dist/core/graph/graph.js:82", + "ms": 129.71, + "percent": 0.44 + }, + { + "name": "lookupCore dist/_shared/scope-resolution/registries/lookup-core.js:79", + "ms": 122.27, + "percent": 0.41 + }, + { + "name": "producerTypeRef dist/core/ingestion/scope-resolution/passes/imported-return-types.js:47", + "ms": 115.67, + "percent": 0.39 + }, + { + "name": "emitCallableValueFlow dist/core/ingestion/scope-resolution/passes/callable-value-flow.js:122", + "ms": 114.23, + "percent": 0.38 + }, + { + "name": "evaluate dist/core/ingestion/route-extractors/framework-route-resolver.js:138", + "ms": 99.89, + "percent": 0.34 + }, + { + "name": "(anonymous) dist/core/ingestion/scope-resolution/passes/callable-value-flow.js:490", + "ms": 92.74, + "percent": 0.31 + }, + { + "name": "importsAt dist/core/ingestion/scope-resolution/scope/walkers.js:36", + "ms": 89.48, + "percent": 0.3 + }, + { + "name": "isResolveDefGraphIdMemoEnabled dist/core/ingestion/scope-resolution/graph-bridge/ids.js:26", + "ms": 86.13, + "percent": 0.29 + }, + { + "name": "resolveReferenceSites dist/core/ingestion/resolve-references.js:184", + "ms": 84.76, + "percent": 0.29 + }, + { + "name": "isTestFilePath dist/core/ingestion/utils/test-file-path.js:72", + "ms": 82.03, + "percent": 0.28 + }, + { + "name": "resolveAmbiguousInheritanceBaseViaImports dist/core/ingestion/scope-resolution/scope/walkers.js:1501", + "ms": 79.89, + "percent": 0.27 + }, + { + "name": "(anonymous) dist/core/ingestion/utils/test-file-path.js:78", + "ms": 78.64, + "percent": 0.26 + }, + { + "name": "collectDeferredIndirectCollection dist/core/ingestion/scope-resolution/passes/callable-value-flow.js:35", + "ms": 78.57, + "percent": 0.26 + }, + { + "name": "writeRel dist/core/graph/graph.js:44", + "ms": 78.35, + "percent": 0.26 + }, + { + "name": "emitReturnShapeMemberAccesses dist/core/ingestion/scope-resolution/passes/return-shape-members.js:285", + "ms": 77.32, + "percent": 0.26 + }, + { + "name": "resolveCallerGraphId dist/core/ingestion/scope-resolution/graph-bridge/ids.js:467", + "ms": 75.89, + "percent": 0.26 + }, + { + "name": "emitReferencesViaLookup dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js:49", + "ms": 75.15, + "percent": 0.25 + }, + { + "name": "resolveFrameworkRouteFacts dist/core/ingestion/route-extractors/framework-route-resolver.js:21", + "ms": 70.34, + "percent": 0.24 + }, + { + "name": "emitUniqueNamePropertyAccesses dist/core/ingestion/scope-resolution/passes/unique-name-properties.js:266", + "ms": 69.79, + "percent": 0.23 + }, + { + "name": "get dist/_shared/scope-resolution/qualified-name-index.js:67", + "ms": 69.58, + "percent": 0.23 + }, + { + "name": "typeParameterNamesInScope dist/core/ingestion/scope-resolution/scope/walkers.js:654", + "ms": 69.55, + "percent": 0.23 + }, + { + "name": "canonicalBindingKey dist/core/ingestion/scope-resolution/passes/callable-value-flow.js:1007", + "ms": 69.42, + "percent": 0.23 + }, + { + "name": "watch dist/core/ingestion/scope-resolution/passes/callable-value-flow.js:195", + "ms": 68.44, + "percent": 0.23 + }, + { + "name": "emitFreeCallFallback dist/core/ingestion/scope-resolution/passes/free-call-fallback.js:25", + "ms": 68.42, + "percent": 0.23 + }, + { + "name": "buildQualifiedNameIndex dist/_shared/scope-resolution/qualified-name-index.js:33", + "ms": 67.55, + "percent": 0.23 + } + ], + "inclusive": [ + { + "name": "lookupNameClaim dist/core/ingestion/scope-resolution/scope/walkers.js:33", + "ms": 2378.97, + "percent": 8.01 + }, + { + "name": "lookupLexicalName dist/_shared/scope-resolution/name-claims.js:133", + "ms": 2324.77, + "percent": 7.83 + }, + { + "name": "findClassBindingInScope dist/core/ingestion/scope-resolution/scope/walkers.js:786", + "ms": 836.82, + "percent": 2.82 + }, + { + "name": "lookupMatchingNameClaim dist/core/ingestion/scope-resolution/scope/walkers.js:69", + "ms": 699.83, + "percent": 2.36 + }, + { + "name": "selectClaimsAtScope dist/_shared/scope-resolution/name-claims.js:60", + "ms": 524.86, + "percent": 1.77 + }, + { + "name": "resolveClassBindingForName dist/core/ingestion/scope-resolution/scope/walkers.js:1132", + "ms": 497.29, + "percent": 1.67 + }, + { + "name": "bindingsAt dist/core/ingestion/scope-resolution/scope/walkers.js:37", + "ms": 459.73, + "percent": 1.55 + }, + { + "name": "findReceiverTypeBinding dist/core/ingestion/scope-resolution/scope/walkers.js:476", + "ms": 394.65, + "percent": 1.33 + }, + { + "name": "nameClaimsFor dist/_shared/scope-resolution/name-claims.js:15", + "ms": 292.55, + "percent": 0.98 + }, + { + "name": "resolveInheritanceBaseInScope dist/core/ingestion/scope-resolution/scope/walkers.js:1325", + "ms": 227.39, + "percent": 0.77 + }, + { + "name": "findValueBindingInScope dist/core/ingestion/scope-resolution/scope/walkers.js:1672", + "ms": 128.77, + "percent": 0.43 + }, + { + "name": "walkScopeChain dist/core/ingestion/scope-resolution/scope/walkers.js:1700", + "ms": 123.15, + "percent": 0.41 + }, + { + "name": "resolveAmbiguousInheritanceBaseViaImports dist/core/ingestion/scope-resolution/scope/walkers.js:1501", + "ms": 121.13, + "percent": 0.41 + }, + { + "name": "findAllBindingsInScope dist/core/ingestion/scope-resolution/scope/walkers.js:1773", + "ms": 116.03, + "percent": 0.39 + }, + { + "name": "findAllCallableBindingsInScope dist/core/ingestion/scope-resolution/scope/walkers.js:1785", + "ms": 107.28, + "percent": 0.36 + }, + { + "name": "findCallableBindingInScope dist/core/ingestion/scope-resolution/scope/walkers.js:1715", + "ms": 91.78, + "percent": 0.31 + }, + { + "name": "importsAt dist/core/ingestion/scope-resolution/scope/walkers.js:36", + "ms": 89.48, + "percent": 0.3 + }, + { + "name": "bindsTypeParameter dist/core/ingestion/scope-resolution/scope/walkers.js:725", + "ms": 80.38, + "percent": 0.27 + }, + { + "name": "typeParameterNamesInScope dist/core/ingestion/scope-resolution/scope/walkers.js:654", + "ms": 75.04, + "percent": 0.25 + }, + { + "name": "importsFor dist/_shared/scope-resolution/name-claims.js:34", + "ms": 46.25, + "percent": 0.16 + }, + { + "name": "(anonymous) dist/_shared/scope-resolution/name-claims.js:202", + "ms": 42.06, + "percent": 0.14 + }, + { + "name": "isReceiverOwnedButUnbound dist/core/ingestion/scope-resolution/scope/walkers.js:307", + "ms": 31.86, + "percent": 0.11 + }, + { + "name": "collectNamespaceFqnBindings dist/core/ingestion/scope-resolution/scope/walkers.js:152", + "ms": 30.72, + "percent": 0.1 + }, + { + "name": "findExportedDefByName dist/core/ingestion/scope-resolution/scope/walkers.js:2018", + "ms": 28.93, + "percent": 0.1 + }, + { + "name": "(anonymous) dist/_shared/scope-resolution/name-claims.js:196", + "ms": 25.16, + "percent": 0.08 + }, + { + "name": "findAllCallableBindingCandidatesInScope dist/core/ingestion/scope-resolution/scope/walkers.js:1744", + "ms": 23.11, + "percent": 0.08 + }, + { + "name": "rangesOverlap dist/_shared/scope-resolution/name-claims.js:55", + "ms": 15.28, + "percent": 0.05 + }, + { + "name": "populateClassOwnedMembers dist/core/ingestion/scope-resolution/scope/walkers.js:1802", + "ms": 13.73, + "percent": 0.05 + }, + { + "name": "(anonymous) dist/_shared/scope-resolution/name-claims.js:161", + "ms": 9.84, + "percent": 0.03 + }, + { + "name": "resolveErasedBaseName dist/core/ingestion/scope-resolution/scope/walkers.js:1258", + "ms": 8.87, + "percent": 0.03 + } + ] + }, + "allocations": { + "totalBytes": 8465103160, + "allocations": [ + { + "name": "selectClaimsAtScope _shared/scope-resolution/name-claims.js:60", + "mb": 1641.46, + "pct": 20.33 + }, + { + "name": "lookupLexicalName _shared/scope-resolution/name-claims.js:133", + "mb": 895.52, + "pct": 11.09 + }, + { + "name": "deserialize node:v8:433", + "mb": 549.86, + "pct": 6.81 + }, + { + "name": "next :0", + "mb": 479.41, + "pct": 5.94 + }, + { + "name": "Set :0", + "mb": 432.93, + "pct": 5.36 + }, + { + "name": "filter :0", + "mb": 382.72, + "pct": 4.74 + }, + { + "name": "add :0", + "mb": 246.34, + "pct": 3.05 + }, + { + "name": "bindingsAt core/ingestion/scope-resolution/scope/walkers.js:37", + "mb": 178.64, + "pct": 2.21 + }, + { + "name": "set :0", + "mb": 150.26, + "pct": 1.86 + }, + { + "name": "keys :0", + "mb": 137.48, + "pct": 1.7 + }, + { + "name": "findClassBindingInScope core/ingestion/scope-resolution/scope/walkers.js:786", + "mb": 130.06, + "pct": 1.61 + }, + { + "name": "Map :0", + "mb": 129.14, + "pct": 1.6 + }, + { + "name": "split :0", + "mb": 122.14, + "pct": 1.51 + }, + { + "name": "resolveDefGraphId core/ingestion/scope-resolution/graph-bridge/ids.js:208", + "mb": 119.06, + "pct": 1.47 + }, + { + "name": "emitReceiverBoundCalls core/ingestion/scope-resolution/passes/receiver-bound-calls.js:437", + "mb": 98.6, + "pct": 1.22 + }, + { + "name": "canonicalBindingKey core/ingestion/scope-resolution/passes/callable-value-flow.js:1007", + "mb": 74.67, + "pct": 0.92 + }, + { + "name": "resolveCompoundReceiverClass core/ingestion/scope-resolution/passes/compound-receiver.js:723", + "mb": 69.27, + "pct": 0.86 + }, + { + "name": "buildGraphNodeLookup core/ingestion/scope-resolution/graph-bridge/node-lookup.js:112", + "mb": 62.95, + "pct": 0.78 + }, + { + "name": "walkLexicalChain _shared/scope-resolution/registries/lookup-core.js:153", + "mb": 62.95, + "pct": 0.78 + }, + { + "name": "lookupForSite core/ingestion/resolve-references.js:263", + "mb": 60.61, + "pct": 0.75 + }, + { + "name": "isTestFile core/ingestion/entry-point-scoring.js:150", + "mb": 60.44, + "pct": 0.75 + }, + { + "name": " core/ingestion/scope-resolution/scope/canonicalize-bindings.js:73", + "mb": 59.72, + "pct": 0.74 + }, + { + "name": "emitUniqueNamePropertyAccesses core/ingestion/scope-resolution/passes/unique-name-properties.js:266", + "mb": 58.1, + "pct": 0.72 + }, + { + "name": "lookupName _shared/scope-resolution/registries/lookup-core.js:275", + "mb": 52.24, + "pct": 0.65 + }, + { + "name": "findReceiverTypeBinding core/ingestion/scope-resolution/scope/walkers.js:476", + "mb": 51.27, + "pct": 0.64 + }, + { + "name": "slice node:buffer:640", + "mb": 49.94, + "pct": 0.62 + }, + { + "name": "resolveDefGraphIdUncached core/ingestion/scope-resolution/graph-bridge/ids.js:227", + "mb": 45.32, + "pct": 0.56 + }, + { + "name": "values :0", + "mb": 43.99, + "pct": 0.54 + }, + { + "name": "reconcileGraphNodeIdentities core/incremental/write-reconciliation.js:28", + "mb": 38.94, + "pct": 0.48 + }, + { + "name": " core/ingestion/scope-resolution/passes/callable-value-flow.js:490", + "mb": 37.79, + "pct": 0.47 + }, + { + "name": "producerTypeRef core/ingestion/scope-resolution/passes/imported-return-types.js:47", + "mb": 37.45, + "pct": 0.46 + }, + { + "name": "emitReferencesViaLookup core/ingestion/scope-resolution/graph-bridge/references-to-edges.js:49", + "mb": 35.2, + "pct": 0.44 + }, + { + "name": "add core/ingestion/model/symbol-table.js:114", + "mb": 34.82, + "pct": 0.43 + }, + { + "name": "lookupNameClaim core/ingestion/scope-resolution/scope/walkers.js:33", + "mb": 31.6, + "pct": 0.39 + }, + { + "name": "emitFreeCallFallback core/ingestion/scope-resolution/passes/free-call-fallback.js:25", + "mb": 31.58, + "pct": 0.39 + } + ] + }, + "limitations": "Diagnostic profiling only. CPU profile overlapped indexing; allocation estimates include collected objects and are not live heap or RSS. Neither profile is acceptance evidence." + }, + "experiments": [ + { + "iteration": 1, + "hypothesis": "claim-selection", + "opportunity": { + "workload": "CI-sized corpus, repeated cached edit on PR 6aeeace8", + "baseline": "Latest PR CPU profile; original CP-1 retained as historical timing only", + "evidence": "Lexical lookup 2325ms inclusive (7.83% of 29.7s profile); selector 525ms inclusive; nameClaimsFor 293ms self; empty redirect .find 103 position ticks. GC 2528ms, unattributed.", + "expected_benefit": "Approximately 0.3-1.5 seconds per ~30-second edit (1-5%) before unknown GC savings; upper bound for all lexical work is 7.8%. Needs paired measurement to establish whether gain exceeds 5%.", + "confidence": "low: profile under concurrent indexing; allocation attribution unknown", + "cost_and_risk": "Small two-function shared change plus private selection helper, no persistent state/dependencies; preserve purpose, activation, redirect, tie/merge and result snapshot behavior." + }, + "status": "reverted", + "referenceHead": "6aeeace8e96603fb062dcc709e834042d5a6df74", + "candidatePatchSha256": "eb6f48facdfcc8a9de1db4e2fbef4113c50efc2d34a6b7238b335423877f01bf", + "validation": { + "scope_tests": 3472, + "scope_test_files": 175, + "differential_comparisons": 72000 + }, + "decision": { + "decision": "revert", + "eligible": false, + "next_measurement": "none", + "target_reached": false, + "improved_objectives": [], + "violated_objectives": ["fresh_ms"], + "comparisons": { + "persistent_ms": { + "verdict": "inconclusive", + "delta": 1041.8203429999703, + "relative": 0.030391537478421788, + "violated": false + }, + "fresh_ms": { + "verdict": "regressed", + "delta": -2434.774620000004, + "relative": -0.08170780705354379, + "violated": true + } + }, + "primary_delta": 1041.8203429999703, + "rank_score": 0.030391537478421788, + "regressions": [], + "holdout": null, + "reason": "violated fresh_ms" + }, + "samples": [ + { + "semantic_equal": 1, + "differential_passed": 1, + "complete_pairs": 1, + "max_rss_kib": 2931372, + "repeat": 1, + "system": { + "node": "v22.23.3", + "cpus": 24, + "platform": "linux", + "arch": "x64" + }, + "fresh_ms": 32233.330080000003, + "fresh_scope_ms": 12646.549523999998, + "fresh_comparison": { + "baseline": { + "times_ms": [29798.55546, 28789.834352, 33206.992737], + "median_ms": 29798.55546, + "scope_ms": [13502.115716999997, 11920.100382999999, 13488.059776999999], + "max_rss_kib": 1969616 + }, + "candidate": { + "times_ms": [32233.330080000003, 29073.301581, 32654.394981999998], + "median_ms": 32233.330080000003, + "scope_ms": [13265.282714000003, 12354.629384999998, 12646.549523999998], + "max_rss_kib": 1955424 + } + }, + "persistent_ms": 33238.12826900001, + "persistent_scope_ms": 13260.555336999998, + "persistent_comparison": { + "baseline": { + "times_ms": [34279.94861199998, 34714.92345200002, 31603.453433999966], + "median_ms": 34279.94861199998, + "scope_ms": [15210.634866999986, 15037.95161899997, 13539.875867000024], + "max_rss_kib": 3162760 + }, + "candidate": { + "times_ms": [33238.12826900001, 33457.24028900001, 29203.065649000026], + "median_ms": 33238.12826900001, + "scope_ms": [13260.555336999998, 13725.79320299998, 12491.834156999976], + "max_rss_kib": 2931372 + } + }, + "raw": { + "fresh": [ + { + "name": "baseline-seed", + "variant": "baseline", + "ms": 65628.81534100001, + "loadBefore": [13.14, 14.32, 15.55], + "loadAfter": [13.23, 13.95, 15.32], + "maxRssKiB": 2192112, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "rebuildReasons": [], + "reparsedFiles": 836, + "cachedFiles": 0, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 3509.1538520000004, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 3579.3203139999996, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 3598.940984, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 32627.376761, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 44637.622053, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 44653.837629, + "phase": "communities", + "percent": 59, + "message": "Detecting code communities..." + }, + { + "ms": 45182.207511, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 45443.799321, + "phase": "complete", + "percent": 60, + "message": "Graph complete! 774 communities, 670 processes detected." + }, + { + "ms": 45443.869192, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 51500.074421000005, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 64195.039917, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "candidate-seed", + "variant": "candidate", + "ms": 73408.79573700001, + "loadBefore": [13.23, 13.95, 15.32], + "loadAfter": [17.53, 15.27, 15.68], + "maxRssKiB": 2317780, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "rebuildReasons": [], + "reparsedFiles": 836, + "cachedFiles": 0, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 3192.9671700000004, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 3265.7137780000003, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 3287.089837, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 37402.244269, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 51784.405312, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 51800.077424, + "phase": "communities", + "percent": 59, + "message": "Detecting code communities..." + }, + { + "ms": 52375.783751, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 52637.806257000004, + "phase": "complete", + "percent": 60, + "message": "Graph complete! 774 communities, 670 processes detected." + }, + { + "ms": 52637.976532, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 58945.235985, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 71983.379193, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "baseline-1", + "variant": "baseline", + "ms": 29798.55546, + "loadBefore": [17.53, 15.27, 15.68], + "loadAfter": [15.62, 15.06, 15.6], + "maxRssKiB": 1952292, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 1307.396139, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1375.471078, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1396.773312, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 4732.430829000001, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 18234.546545999998, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 18269.480457999998, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 18269.726961999997, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 18275.663291999997, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 18726.397171999997, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 19452.342126, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 23089.487564, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 27270.690484, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + }, + { + "name": "candidate-1", + "variant": "candidate", + "ms": 32233.330080000003, + "loadBefore": [15.62, 15.06, 15.6], + "loadAfter": [17.76, 15.61, 15.76], + "maxRssKiB": 1955424, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 1353.107634, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1433.799143, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1459.6389239999999, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 4531.17086, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 17796.453574000003, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 17832.848195000002, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 17833.100145, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 17840.730773000003, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 18414.079031, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 19329.179971, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 23882.121373, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 28481.164800000002, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + }, + { + "name": "candidate-2", + "variant": "candidate", + "ms": 29073.301581, + "loadBefore": [17.76, 15.61, 15.76], + "loadAfter": [16.05, 15.47, 15.72], + "maxRssKiB": 1935172, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 1566.346216, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1647.37927, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1664.6144719999998, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 4761.188839, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 17115.818224, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 17153.126366, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 17153.387748, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 17160.219237, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 17679.286717, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 18546.868091, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 21788.657167, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 26540.791412, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "baseline-2", + "variant": "baseline", + "ms": 28789.834352, + "loadBefore": [16.05, 15.47, 15.72], + "loadAfter": [15.52, 15.42, 15.69], + "maxRssKiB": 1969616, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 1424.0875190000002, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1519.842048, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1551.179146, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 4441.278408, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 16361.378791, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 16393.441255, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 16393.683635, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 16400.528732, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 16839.500861, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 17539.253046, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 20659.270477000002, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 25095.993566, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "baseline-3", + "variant": "baseline", + "ms": 33206.992737, + "loadBefore": [15.52, 15.42, 15.69], + "loadAfter": [16.54, 15.72, 15.78], + "maxRssKiB": 1763948, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 1289.5618060000002, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1356.6231940000002, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1379.929517, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 4281.199216, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 17769.258993, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 17804.348083999997, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 17804.516848, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 17809.319993, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 18316.711639, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 19280.050091999998, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 24112.424112, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 29308.480545, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + }, + { + "name": "candidate-3", + "variant": "candidate", + "ms": 32654.394981999998, + "loadBefore": [16.54, 15.72, 15.78], + "loadAfter": [16.99, 15.92, 15.85], + "maxRssKiB": 1906708, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 1620.1922610000001, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1730.8859780000003, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1758.8178900000003, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 5084.842194, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 17731.391718, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 17768.006184, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 17768.143322, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 17773.041569, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 18279.833841, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 19161.782231, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 24088.587528, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 29050.081305, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + } + ], + "persistent": [ + { + "name": "baseline-seed", + "variant": "baseline", + "ms": 70194.849581, + "loadBefore": [16.99, 15.92, 15.85], + "loadAfter": [17.39, 16.17, 15.94], + "maxRssKiB": 2203640, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "rebuildReasons": [], + "reparsedFiles": 836, + "cachedFiles": 0, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 1180.136332, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1249.710824, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1270.765594, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 32841.673386999995, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 46273.821281, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 46287.12928, + "phase": "communities", + "percent": 59, + "message": "Detecting code communities..." + }, + { + "ms": 46802.184917, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 47068.678953999995, + "phase": "complete", + "percent": 60, + "message": "Graph complete! 774 communities, 670 processes detected." + }, + { + "ms": 47068.784408, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 52987.828612, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 68825.21900699999, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "candidate-seed", + "variant": "candidate", + "ms": 74193.441515, + "loadBefore": [17.39, 16.17, 15.94], + "loadAfter": [17.82, 16.65, 16.13], + "maxRssKiB": 2131004, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "rebuildReasons": [], + "reparsedFiles": 836, + "cachedFiles": 0, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 1517.6874469999998, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1584.5084809999998, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1611.2322100000001, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 38830.016204, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 52618.3247, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 52636.26474, + "phase": "communities", + "percent": 59, + "message": "Detecting code communities..." + }, + { + "ms": 53190.034921, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 53417.115387, + "phase": "complete", + "percent": 60, + "message": "Graph complete! 774 communities, 670 processes detected." + }, + { + "ms": 53417.188744, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 59186.847963, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 72588.648662, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "baseline-1", + "variant": "baseline", + "ms": 34279.94861199998, + "loadBefore": [17.82, 16.65, 16.13], + "loadAfter": [16.36, 16.42, 16.07], + "maxRssKiB": 2640372, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 1156.5955659999745, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1214.678126999992, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1231.8949969999958, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 4217.634909999993, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 19428.26977699998, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 19466.267020999978, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 19466.563547999976, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 19473.73401799999, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 20019.234776999976, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 21438.9081, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 25732.54163999998, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 30663.623489999998, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + }, + { + "name": "candidate-1", + "variant": "candidate", + "ms": 33238.12826900001, + "loadBefore": [16.36, 16.42, 16.07], + "loadAfter": [14.72, 16.02, 15.95], + "maxRssKiB": 2504712, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 1119.4276220000029, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1187.9822260000074, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1202.0007909999986, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 4809.233737000002, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 18069.789074, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 18106.712098000004, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 18106.915330000003, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 18113.035044000004, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 18704.264834, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 19803.105459, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 24677.01905999999, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 29848.289040000003, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + }, + { + "name": "candidate-2", + "variant": "candidate", + "ms": 33457.24028900001, + "loadBefore": [14.72, 16.02, 15.95], + "loadAfter": [16.2, 16.29, 16.04], + "maxRssKiB": 2673820, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 1240.4017910000111, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1310.6163890000025, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1325.4716509999998, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 4476.474022000009, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 18202.26722499999, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 18229.752542000002, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 18229.850693000015, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 18234.903496999992, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 18797.514016, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 19579.819669999997, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 24354.49141799999, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 29298.609326000005, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "baseline-2", + "variant": "baseline", + "ms": 34714.92345200002, + "loadBefore": [16.2, 16.29, 16.04], + "loadAfter": [16.88, 16.46, 16.11], + "maxRssKiB": 2878748, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 1375.4053530000092, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1451.9092860000092, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1465.7184239999915, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 4701.057270000019, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 19739.00888899999, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 19765.682927999995, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 19765.786620999977, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 19771.408366999996, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 20200.72553200001, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 20938.532238000014, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 25808.977079999982, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 30556.89061599999, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "baseline-3", + "variant": "baseline", + "ms": 31603.453433999966, + "loadBefore": [16.88, 16.46, 16.11], + "loadAfter": [16.72, 16.55, 16.16], + "maxRssKiB": 3162760, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 1333.0421599999536, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1436.0369469999569, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1459.6783270000014, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 4553.997158999962, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 18093.873025999987, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 18127.464217, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 18127.59359299997, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 18132.105923999974, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 18637.19939699996, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 19348.14475799998, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 23392.614838999987, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 27840.12971000001, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + }, + { + "name": "candidate-3", + "variant": "candidate", + "ms": 29203.065649000026, + "loadBefore": [16.72, 16.55, 16.16], + "loadAfter": [15.48, 16.25, 16.07], + "maxRssKiB": 2931372, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 1202.2229870000156, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1265.3199820000154, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1283.3012980000058, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 4238.928321000014, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 16730.76247799999, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 16762.143253000017, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 16762.26086400004, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 16768.954153, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 17309.75822400002, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 18027.32870500002, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 21519.62142499999, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 25921.905318000034, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + } + ] + } + } + ] + }, + { + "iteration": 2, + "hypothesis": "selection-allocations", + "opportunity": { + "workload": "Latest PR 6aeeace8 on pinned sparse ingestion corpus, warm edit", + "baseline": "Unchanged latest-PR CPU and allocation profiles", + "evidence": "Claim selection self allocations 1641 MiB (20.33% of estimated 8073 MiB); selector CPU inclusive 525ms (1.77%). Whole-profile GC 2528ms (8.51%). Allocation profiling overhead is diagnostic only.", + "expected_benefit": "Approximately 0.5-1.5 seconds (~2-5%) from removing purpose/active/ordered temporary arrays and callbacks; GC contribution not linear, so >5% remains uncertain. The cheap allocation measurement now supports testing.", + "confidence": "medium on allocation reduction, low on total elapsed improvement under shared-host noise", + "cost_and_risk": "One selector rewrite using repeated scans and one output array; no persistent state, dependencies or changed language behavior. Must preserve inactive order, hoisting, merge/tie ambiguity and fresh result snapshots." + }, + "status": "inconclusive", + "referenceHead": "6aeeace8e96603fb062dcc709e834042d5a6df74", + "candidatePatchSha256": "3016157298475c3d247531d91fc33d8d9d4c486d4832694cdc2634869ed8a988", + "validation": { + "scope_tests": 3471, + "scope_test_files": 175, + "differential_comparisons": 72000, + "selector_comparisons": 50000, + "build": "passed" + }, + "decision": { + "decision": "inconclusive", + "eligible": false, + "next_measurement": "none", + "target_reached": false, + "improved_objectives": [], + "violated_objectives": [], + "comparisons": { + "persistent_ms": { + "verdict": "inconclusive", + "delta": 34.92118149997259, + "relative": 0.00148435831051221, + "violated": false + }, + "fresh_ms": { + "verdict": "inconclusive", + "delta": 406.3638205000025, + "relative": 0.01542353908830917, + "violated": false + } + }, + "primary_delta": 34.92118149997259, + "rank_score": 0.00148435831051221, + "regressions": [], + "holdout": null, + "reason": "delta inside the comparison threshold" + }, + "samples": [ + { + "semantic_equal": 1, + "differential_passed": 1, + "complete_pairs": 1, + "max_rss_kib": 3030232, + "repeat": 1, + "system": { + "node": "v22.23.3", + "cpus": 24, + "platform": "linux", + "arch": "x64" + }, + "fresh_ms": 29402.440592, + "fresh_scope_ms": 11047.315225999999, + "fresh_comparison": { + "baseline": { + "times_ms": [32929.472970999996, 28391.96733, 29325.383512], + "median_ms": 29325.383512, + "scope_ms": [12570.913379000001, 12260.064309, 13394.642316999998], + "max_rss_kib": 1967816 + }, + "candidate": { + "times_ms": [29402.440592, 29689.824257, 27332.084170000002], + "median_ms": 29402.440592, + "scope_ms": [12620.986895999999, 11047.315225999999, 10430.096191999999], + "max_rss_kib": 1933152 + } + }, + "persistent_ms": 24548.97740200002, + "persistent_scope_ms": 9447.967802, + "persistent_comparison": { + "baseline": { + "times_ms": [36910.615672000014, 24383.306538999983, 24439.099341999972], + "median_ms": 24439.099341999972, + "scope_ms": [13848.231398000004, 9480.015752999985, 10156.866689999995], + "max_rss_kib": 3102380 + }, + "candidate": { + "times_ms": [29701.778214000005, 24548.97740200002, 24027.054672], + "median_ms": 24548.97740200002, + "scope_ms": [11481.431329000014, 9374.105639999994, 9447.967802], + "max_rss_kib": 3030232 + } + }, + "raw": { + "fresh": [ + { + "name": "baseline-seed", + "variant": "baseline", + "ms": 75000.377352, + "loadBefore": [16.93, 17.06, 17.01], + "loadAfter": [17.37, 17.14, 17.04], + "maxRssKiB": 2184284, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "rebuildReasons": [], + "reparsedFiles": 836, + "cachedFiles": 0, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 2354.2229429999998, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 2425.355908, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 2451.938087, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 33569.347507, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 49348.097466, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 49365.532666, + "phase": "communities", + "percent": 59, + "message": "Detecting code communities..." + }, + { + "ms": 49954.453013, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 50274.61027, + "phase": "complete", + "percent": 60, + "message": "Graph complete! 774 communities, 670 processes detected." + }, + { + "ms": 50274.692016999994, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 56896.854139999996, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 72993.943329, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "candidate-seed", + "variant": "candidate", + "ms": 78817.062681, + "loadBefore": [17.37, 17.14, 17.04], + "loadAfter": [13.2, 16.19, 16.73], + "maxRssKiB": 2150704, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "rebuildReasons": [], + "reparsedFiles": 836, + "cachedFiles": 0, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 12227.146322999999, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 12310.141704, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 12334.028272, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 43481.809095000004, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 55744.331254000004, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 55759.774403, + "phase": "communities", + "percent": 59, + "message": "Detecting code communities..." + }, + { + "ms": 56565.601307000004, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 56915.294079, + "phase": "complete", + "percent": 60, + "message": "Graph complete! 774 communities, 670 processes detected." + }, + { + "ms": 56915.397685, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 64075.797201, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 77631.862996, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "baseline-1", + "variant": "baseline", + "ms": 32929.472970999996, + "loadBefore": [13.2, 16.19, 16.73], + "loadAfter": [12.04, 15.54, 16.49], + "maxRssKiB": 1967816, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 2940.877802, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 3015.5050850000002, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 3039.961336, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 5967.468548, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 18538.381927000002, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 18568.356409, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 18568.536311, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 18573.476977000002, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 19016.826529, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 20331.439603000003, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 24440.147301, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 29501.878341, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + }, + { + "name": "candidate-1", + "variant": "candidate", + "ms": 29402.440592, + "loadBefore": [12.04, 15.54, 16.49], + "loadAfter": [12.6, 15.35, 16.4], + "maxRssKiB": 1933152, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 1293.351483, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1352.318091, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1372.9884220000001, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 4224.342591, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 16845.329487, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 16876.22064, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 16876.445304, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 16881.447308, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 17304.20634, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 18302.737301999998, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 22386.860496999998, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 26907.999703999998, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + }, + { + "name": "candidate-2", + "variant": "candidate", + "ms": 29689.824257, + "loadBefore": [12.31, 15.25, 16.36], + "loadAfter": [13.52, 15.21, 16.31], + "maxRssKiB": 1888204, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 1178.3365529999999, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1231.956017, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1248.1919209999999, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 3688.24982, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 14735.565046, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 14764.058309, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 14764.226099, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 14770.341751, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 15210.029077, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 16061.168812000002, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 20705.638602, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 26038.694594, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "baseline-2", + "variant": "baseline", + "ms": 28391.96733, + "loadBefore": [13.52, 15.21, 16.31], + "loadAfter": [12.98, 14.97, 16.19], + "maxRssKiB": 1943212, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 1263.2697509999998, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1333.4543520000002, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1351.575182, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 4385.317901, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 16645.38221, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 16675.880995, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 16676.040140999998, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 16680.122559, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 17057.54722, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 17753.581422, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 21418.990049, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 25860.848944999998, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "baseline-3", + "variant": "baseline", + "ms": 29325.383512, + "loadBefore": [12.98, 14.97, 16.19], + "loadAfter": [13.8, 15.01, 16.17], + "maxRssKiB": 1736652, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 1224.982187, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1294.495246, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1309.921877, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 3999.740062, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 17394.382379, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 17435.896643, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 17436.133622999998, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 17443.745162, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 18037.14116, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 19025.646714, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 22461.109779, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 26895.027491, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + }, + { + "name": "candidate-3", + "variant": "candidate", + "ms": 27332.084170000002, + "loadBefore": [13.8, 15.01, 16.17], + "loadAfter": [12.12, 14.49, 15.96], + "maxRssKiB": 1901612, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 1333.813814, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1405.439817, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1432.5911230000002, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 4003.24818, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 14433.344372, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 14458.204125, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 14458.347944000001, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 14462.346666, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 14836.096425, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 15517.822601, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 18807.444828, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 23365.351607, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + } + ], + "persistent": [ + { + "name": "baseline-seed", + "variant": "baseline", + "ms": 69743.692275, + "loadBefore": [12.12, 14.49, 15.96], + "loadAfter": [11.7, 13.85, 15.63], + "maxRssKiB": 2203936, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "rebuildReasons": [], + "reparsedFiles": 836, + "cachedFiles": 0, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 1225.851554, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1286.501025, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1306.560612, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 29185.137528, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 42820.418982, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 42831.549671, + "phase": "communities", + "percent": 59, + "message": "Detecting code communities..." + }, + { + "ms": 43192.5967, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 43380.173825000005, + "phase": "complete", + "percent": 60, + "message": "Graph complete! 774 communities, 670 processes detected." + }, + { + "ms": 43380.261192000005, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 49165.192408, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 68349.47804199999, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "candidate-seed", + "variant": "candidate", + "ms": 76257.737363, + "loadBefore": [11.7, 13.85, 15.63], + "loadAfter": [20.89, 16.4, 16.38], + "maxRssKiB": 2126356, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "rebuildReasons": [], + "reparsedFiles": 836, + "cachedFiles": 0, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 1152.231588, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1221.7744859999998, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1239.180433, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 30943.861144000002, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 42112.777291, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 42125.082233, + "phase": "communities", + "percent": 59, + "message": "Detecting code communities..." + }, + { + "ms": 42526.333127, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 42711.401289, + "phase": "complete", + "percent": 60, + "message": "Graph complete! 774 communities, 670 processes detected." + }, + { + "ms": 42711.460265, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 51565.277569, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 74337.574302, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "baseline-1", + "variant": "baseline", + "ms": 36910.615672000014, + "loadBefore": [20.89, 16.4, 16.38], + "loadAfter": [15.96, 15.71, 16.15], + "maxRssKiB": 2756384, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 1103.0908160000108, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1174.1361160000088, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1186.4570150000218, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 4973.535463000007, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 18821.76686100001, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 18850.627978000004, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 18850.795671, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 18854.994866000023, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 19258.78237100001, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 21831.902724000014, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 27674.681942000025, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 34577.978138000006, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + }, + { + "name": "candidate-1", + "variant": "candidate", + "ms": 29701.778214000005, + "loadBefore": [15.96, 15.71, 16.15], + "loadAfter": [14.45, 15.4, 16.03], + "maxRssKiB": 2735004, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 833.2799180000002, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 889.5255980000074, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 900.4124350000056, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 3862.369777, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 15343.801106000014, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 15375.120921000009, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 15375.362940000006, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 15380.42412299999, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 15836.518681000001, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 16727.177922999996, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 21528.170132999992, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 27174.89620100001, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + }, + { + "name": "candidate-2", + "variant": "candidate", + "ms": 24548.97740200002, + "loadBefore": [14.45, 15.4, 16.03], + "loadAfter": [12.35, 14.86, 15.84], + "maxRssKiB": 2982020, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 976.8606819999986, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1031.4570430000022, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1043.0648690000235, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 3480.009846000001, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 12854.115485999995, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 12879.125859000022, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 12879.23213400002, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 12882.971313999995, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 13251.498028000002, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 13904.783657000022, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 17516.993491, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 22170.895289000007, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "baseline-2", + "variant": "baseline", + "ms": 24383.306538999983, + "loadBefore": [12.35, 14.86, 15.84], + "loadAfter": [9.52, 13.98, 15.52], + "maxRssKiB": 3056284, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 926.3708229999756, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 975.770617000002, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 987.933269000001, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 3170.2159479999973, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 12650.231700999982, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 12670.539085999975, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 12670.627256999986, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 12673.795809000003, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 13020.241874999978, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 13598.984085999982, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 16632.51996799998, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 21655.599963999965, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "baseline-3", + "variant": "baseline", + "ms": 24439.099341999972, + "loadBefore": [9.08, 13.82, 15.46], + "loadAfter": [7.07, 12.96, 15.13], + "maxRssKiB": 3102380, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 964.5339619999868, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1013.9079769999953, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1025.7152110000025, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 3273.743192999973, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 13430.609882999968, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 13453.238440999994, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 13453.354417999974, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 13457.377673999988, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 13803.65630099998, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 14365.11494999996, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 17411.443904999993, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 22082.590387000004, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + }, + { + "name": "candidate-3", + "variant": "candidate", + "ms": 24027.054672, + "loadBefore": [7.07, 12.96, 15.13], + "loadAfter": [7.64, 12.63, 14.96], + "maxRssKiB": 3030232, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 996.1977469999983, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1053.830030000012, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1067.9800730000134, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 3299.4026190000004, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 12747.370421, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 12767.73889400001, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 12767.844688000012, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 12771.036244999996, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 13119.161932999996, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 13687.854183999996, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 17017.43691400002, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 21465.138980999996, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + } + ] + } + }, + { + "semantic_equal": 1, + "differential_passed": 1, + "complete_pairs": 1, + "max_rss_kib": 2600784, + "repeat": 2, + "system": { + "node": "v22.23.3", + "cpus": 24, + "platform": "linux", + "arch": "x64" + }, + "persistent_ms": 22433.406443000014, + "persistent_scope_ms": 9353.181201, + "persistent_comparison": { + "baseline": { + "times_ms": [22613.126866000006, 21584.991368999996, 23607.338552], + "median_ms": 22613.126866000006, + "scope_ms": [9746.149032000001, 8917.897706999996, 9699.304400000023], + "max_rss_kib": 2970204 + }, + "candidate": { + "times_ms": [23346.203471, 22433.406443000014, 21442.27035799998], + "median_ms": 22433.406443000014, + "scope_ms": [9438.950406999997, 9353.181201, 9021.226263999997], + "max_rss_kib": 2600784 + } + }, + "fresh_ms": 22478.810519, + "fresh_scope_ms": 9431.54927, + "fresh_comparison": { + "baseline": { + "times_ms": [25186.114075, 23368.595240000002, 22067.853994999998], + "median_ms": 23368.595240000002, + "scope_ms": [10944.262560000001, 9759.121893, 9359.433594], + "max_rss_kib": 1987644 + }, + "candidate": { + "times_ms": [23272.661176999998, 22478.810519, 22157.014896], + "median_ms": 22478.810519, + "scope_ms": [9467.538907, 9431.54927, 9250.186839999998], + "max_rss_kib": 1937040 + } + }, + "raw": { + "fresh": [ + { + "name": "candidate-seed", + "variant": "candidate", + "ms": 47629.787157, + "loadBefore": [8.63, 9.13, 12.71], + "loadAfter": [6.52, 8.48, 12.3], + "maxRssKiB": 2076420, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "rebuildReasons": [], + "reparsedFiles": 836, + "cachedFiles": 0, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 1066.349751, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1119.653176, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1135.790511, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 23759.141515000003, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 32765.514582, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 32776.514698, + "phase": "communities", + "percent": 59, + "message": "Detecting code communities..." + }, + { + "ms": 33158.674114, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 33333.409725, + "phase": "complete", + "percent": 60, + "message": "Graph complete! 774 communities, 670 processes detected." + }, + { + "ms": 33333.464108, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 37549.933168999996, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 46657.53139, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "baseline-seed", + "variant": "baseline", + "ms": 50677.431454, + "loadBefore": [6.52, 8.48, 12.3], + "loadAfter": [8.17, 8.6, 12.14], + "maxRssKiB": 2209388, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "rebuildReasons": [], + "reparsedFiles": 836, + "cachedFiles": 0, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 1042.487527, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1096.531763, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1112.067042, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 25091.564247, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 34646.744003, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 34658.107303, + "phase": "communities", + "percent": 59, + "message": "Detecting code communities..." + }, + { + "ms": 35026.97397, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 35211.201402, + "phase": "complete", + "percent": 60, + "message": "Graph complete! 774 communities, 670 processes detected." + }, + { + "ms": 35211.258513, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 40096.974943, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 49730.421491, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "candidate-1", + "variant": "candidate", + "ms": 23272.661176999998, + "loadBefore": [8.17, 8.6, 12.14], + "loadAfter": [15.06, 10.46, 12.67], + "maxRssKiB": 1721740, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 1112.96591, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1165.144292, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1181.550871, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 3894.734922, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 13362.273829, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 13389.909851, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 13390.023096, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 13393.936084, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 13757.078784000001, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 14388.498645000001, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 17150.042255, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 20784.807515999997, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + }, + { + "name": "baseline-1", + "variant": "baseline", + "ms": 25186.114075, + "loadBefore": [15.06, 10.46, 12.67], + "loadAfter": [14.22, 10.6, 12.66], + "maxRssKiB": 1987644, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 1167.274475, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1223.354865, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1238.849633, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 3801.6168810000004, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 14745.879441000001, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 14778.183681, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 14778.337927, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 14783.362248000001, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 15185.097383, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 15854.04657, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 18922.247163, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 22752.784586, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + }, + { + "name": "baseline-2", + "variant": "baseline", + "ms": 23368.595240000002, + "loadBefore": [14.22, 10.6, 12.66], + "loadAfter": [11.23, 10.19, 12.47], + "maxRssKiB": 1972564, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 1076.544593, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1135.221758, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1151.3591979999999, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 3553.818396, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 13312.940289, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 13338.056107, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 13338.201619000001, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 13342.574101, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 13718.365848000001, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 14343.446896000001, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 17252.380679, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 20916.265042, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "candidate-2", + "variant": "candidate", + "ms": 22478.810519, + "loadBefore": [11.23, 10.19, 12.47], + "loadAfter": [8.83, 9.7, 12.25], + "maxRssKiB": 1723496, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 1094.077166, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1146.375669, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1162.7304430000002, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 3421.148992, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 12852.698262, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 12880.22503, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 12880.364232999998, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 12884.708437, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 13260.436348, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 13905.202425, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 16694.577882999998, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 20502.741928, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "candidate-3", + "variant": "candidate", + "ms": 22157.014896, + "loadBefore": [8.83, 9.7, 12.25], + "loadAfter": [7.31, 9.29, 12.04], + "maxRssKiB": 1937040, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 1080.726855, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1134.0602920000001, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1150.731878, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 3358.010361, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 12608.197200999999, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 12634.366904, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 12634.510241, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 12638.410708, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 13004.176118, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 13646.670573, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 16574.239953, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 20148.125541, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + }, + { + "name": "baseline-3", + "variant": "baseline", + "ms": 22067.853994999998, + "loadBefore": [7.31, 9.29, 12.04], + "loadAfter": [6.6, 9.01, 11.89], + "maxRssKiB": 1941568, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 1080.170665, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1133.3820970000002, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1148.7439020000002, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 3335.153602, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 12694.587196, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 12721.574637, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 12721.738691, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 12725.987867, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 13081.090837, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 13669.934157, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 16505.79384, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 20110.383681, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + } + ], + "persistent": [ + { + "name": "candidate-seed", + "variant": "candidate", + "ms": 49430.043894999995, + "loadBefore": [7.26, 11.43, 14.39], + "loadAfter": [6.23, 10.49, 13.91], + "maxRssKiB": 2151124, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "rebuildReasons": [], + "reparsedFiles": 836, + "cachedFiles": 0, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 1436.924462, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1488.41811, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1504.878897, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 24403.099295, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 33679.686107, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 33690.838653, + "phase": "communities", + "percent": 59, + "message": "Detecting code communities..." + }, + { + "ms": 34040.432569, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 34213.443919, + "phase": "complete", + "percent": 60, + "message": "Graph complete! 774 communities, 670 processes detected." + }, + { + "ms": 34213.490217, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 38708.534258, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 48432.419935, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "baseline-seed", + "variant": "baseline", + "ms": 51372.255803, + "loadBefore": [6.23, 10.49, 13.91], + "loadAfter": [6.5, 9.97, 13.55], + "maxRssKiB": 2356284, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "rebuildReasons": [], + "reparsedFiles": 836, + "cachedFiles": 0, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 1021.071966, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1073.231636, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1089.844967, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 24573.295407999998, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 34068.890471, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 34078.847935, + "phase": "communities", + "percent": 59, + "message": "Detecting code communities..." + }, + { + "ms": 34456.595084, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 34636.604738, + "phase": "complete", + "percent": 60, + "message": "Graph complete! 774 communities, 670 processes detected." + }, + { + "ms": 34636.655071, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 39502.827838, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 50426.114345, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "candidate-1", + "variant": "candidate", + "ms": 23346.203471, + "loadBefore": [6.5, 9.97, 13.55], + "loadAfter": [6.58, 9.7, 13.37], + "maxRssKiB": 2383484, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 783.5985890000011, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 837.5159200000053, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 849.0497790000081, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 3169.825155000013, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 12608.77556200001, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 12630.51436300001, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 12630.678169000006, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 12634.408156000005, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 12997.314514000012, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 13550.833403000011, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 16561.345008000004, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 20487.39213800001, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + }, + { + "name": "baseline-1", + "variant": "baseline", + "ms": 22613.126866000006, + "loadBefore": [6.58, 9.7, 13.37], + "loadAfter": [6.11, 9.35, 13.15], + "maxRssKiB": 2482600, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 834.8115439999965, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 889.9484809999994, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 901.0175049999962, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 3174.080818000002, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 12920.229850000003, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 12941.497331000006, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 12941.654149000009, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 12945.699964, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 13297.827529000002, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 13809.531657, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 16589.281711999996, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 20401.894417000003, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + }, + { + "name": "baseline-2", + "variant": "baseline", + "ms": 21584.991368999996, + "loadBefore": [6.11, 9.35, 13.15], + "loadAfter": [5.83, 9.08, 12.98], + "maxRssKiB": 2669284, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 756.8523209999985, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 804.2194630000013, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 819.2052169999952, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 2974.2487129999936, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 11892.14641999999, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 11914.056576999996, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 11914.165756999995, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 11917.829488000003, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 12277.481012999997, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 12745.858911999996, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 15751.27971599999, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 19299.293047, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "candidate-2", + "variant": "candidate", + "ms": 22433.406443000014, + "loadBefore": [5.83, 9.08, 12.98], + "loadAfter": [5.58, 8.76, 12.77], + "maxRssKiB": 2419912, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "370ac0472dc57f08cd23d8151c2e9da4db5d4f7070446d66f20db9162ba1ceca" + } + }, + "progress": [ + { + "ms": 821.897649999999, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 872.4490320000041, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 884.1823380000133, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 3210.363032000023, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 12563.544233000022, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 12586.506557000015, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 12586.59673000002, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 12589.545421000017, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 12935.707815000002, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 13426.105544999999, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 16561.695632000017, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 20128.457175000018, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "save" + } + ] + }, + { + "name": "candidate-3", + "variant": "candidate", + "ms": 21442.27035799998, + "loadBefore": [5.58, 8.76, 12.77], + "loadAfter": [6.66, 8.8, 12.7], + "maxRssKiB": 2600784, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 810.1562580000027, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 860.9136279999802, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 871.0058799999824, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 3032.3640869999945, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 12053.590350999992, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 12075.165229000006, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 12075.279507, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 12079.105695999984, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 12449.867710999999, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 12924.626484999986, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 15594.527864000003, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 19254.68305599998, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + }, + { + "name": "baseline-3", + "variant": "baseline", + "ms": 23607.338552, + "loadBefore": [6.66, 8.8, 12.7], + "loadAfter": [8.63, 9.13, 12.71], + "maxRssKiB": 2970204, + "stats": { + "files": 862, + "nodes": 25092, + "edges": 76047, + "communities": 774, + "processes": 670, + "embeddings": 0 + }, + "incremental": { + "changedFiles": 1, + "reparsedFiles": 8, + "affectedDependents": 0, + "deletedFiles": 0, + "writeMode": "incremental" + }, + "rebuildReasons": [], + "reparsedFiles": 8, + "cachedFiles": 828, + "graph": { + "nodes": { + "count": 23641, + "sha256": "6c5bce88c7e16be3cf13f9242a8f4b8db4c9b39a087b11bc62a661311c20451e" + }, + "edges": { + "count": 64292, + "sha256": "ca918e3bc320a00a46e52edda70010320ed1ba7ddb951a02dbe51adbb47c5e27" + } + }, + "progress": [ + { + "ms": 1366.363784999994, + "phase": "extracting", + "percent": 0, + "message": "Scanning repository..." + }, + { + "ms": 1462.2462379999924, + "phase": "structure", + "percent": 9, + "message": "Analyzing project structure..." + }, + { + "ms": 1484.048907999997, + "phase": "parsing", + "percent": 12, + "message": "Parsing 836 files in 131 chunks..." + }, + { + "ms": 4039.572480999981, + "phase": "scopeResolution", + "percent": 54, + "message": "Resolving types" + }, + { + "ms": 13738.876881000004, + "phase": "enriching", + "percent": 59, + "message": "Computing method resolution order..." + }, + { + "ms": 13758.202458999993, + "phase": "complete", + "percent": 60, + "message": "Graph complete! (graph phases skipped)" + }, + { + "ms": 13758.304463999986, + "phase": "lbug", + "percent": 60, + "message": "Loading into LadybugDB..." + }, + { + "ms": 13761.598081999982, + "phase": "communities", + "percent": 58, + "message": "Detecting code communities and flows..." + }, + { + "ms": 14092.365290999995, + "phase": "processes", + "percent": 59, + "message": "Detecting execution flows..." + }, + { + "ms": 14621.086907999997, + "phase": "lbug", + "percent": 62, + "message": "Removing rows for changed files (0/2)..." + }, + { + "ms": 17686.805055999983, + "phase": "fts", + "percent": 85, + "message": "Creating search indexes..." + }, + { + "ms": 21360.17223299999, + "phase": "done", + "percent": 98, + "message": "Saving metadata..." + } + ], + "persistedTargets": [ + { + "target": "load" + } + ] + } + ] + } + } + ] + } + ], + "stoppingReason": "No remaining supported hypothesis that can establish the required >5% gain within the remaining approved confirmation budget.", + "phase3Seconds": 2769, + "confirmation": "No candidate earned a keep; final runtime is unchanged at the reference HEAD. No final before/after speedup or holdout claim.", + "cost": { + "judge": "not applicable", + "wholeRunMonetaryCost": "unavailable; no reliable monetary telemetry", + "subagents": 0 + }, + "finalValidation": { + "targeted_tests": 59, + "source_typecheck": "passed at latest PR head", + "test_typecheck": "passed at latest PR head", + "build": "passed", + "eslint": "passed", + "formatting": "passed", + "differential_comparisons_per_session": 72000, + "semantic_graphs_equal": true, + "persisted_call_targets_follow_edits": true, + "noop_rejected": true, + "full_suite": { + "command": "npm test -- --maxWorkers=4", + "exit_code": 1, + "files_passed": 1449, + "files_failed": 2, + "files_skipped": 14, + "tests_passed": 31567, + "tests_failed": 4, + "tests_skipped": 103, + "duration_seconds": 5585.34, + "failures": [ + "test/integration/setup-skills.test.ts:120", + "test/integration/setup-skills.test.ts:137", + "test/unit/setup.test.ts:1062", + "test/unit/setup.test.ts:1088" + ], + "status": "failed: four unchanged Codex setup tests affected by inherited CODEX_HOME; both files pass when unset in child process" + }, + "detect_changes": { + "changed_count": 18, + "affected_count": 0, + "changed_files": 6, + "risk_level": "low", + "partial": false, + "truncated": false + }, + "staged_diff_check": "passed", + "setup_recheck": { + "command": "env -u CODEX_HOME npx vitest run test/integration/setup-skills.test.ts test/unit/setup.test.ts --maxWorkers=2", + "exit_code": 0, + "files_passed": 2, + "tests_passed": 62, + "duration_seconds": 2.49, + "setup_source_and_tests_unchanged": true, + "inherited_codex_home_present": true, + "full_suite_repeated": false + } + }, + "remoteVerified": { + "timestamp": "2026-11-03T10:36:13.986Z", + "head": "6aeeace8e96603fb062dcc709e834042d5a6df74", + "base": "24d3de239daaa45f163473ea3f195d37a8397b78", + "unchanged": true + } +} diff --git a/gitnexus/src/core/incremental/write-reconciliation.ts b/gitnexus/src/core/incremental/write-reconciliation.ts index bbd717e0f..b7e9fe731 100644 --- a/gitnexus/src/core/incremental/write-reconciliation.ts +++ b/gitnexus/src/core/incremental/write-reconciliation.ts @@ -34,14 +34,15 @@ const storedIdentityField = (node: GraphNode, field: string): unknown => { * retained rows. A write-set-only probe misses corruption of an unchanged row. * Scan one label at a time, without path/range predicates: a corrupt field must * not be able to hide its own row. No multi-label scans (#3139), N+1 ID lookups, - * source-content copies, or whole-graph row materialization. + * source-content copies, or JS row-array materialization. The reader calls the + * synchronous visitor for each row and releases its cursor before resolving. * * This certifies node identity, not relationships or native storage internals. * Call after COPY/checkpoint and after FTS/embedding/checkpoint, before metadata. */ export async function reconcileGraphNodeIdentities( graph: KnowledgeGraph, - query: (cypher: string) => Promise, + readRows: (cypher: string, onRow: (row: IdentityRow) => undefined) => Promise, phase: string, ): Promise<{ nodes: number; tables: number }> { const expected = new Map>(); @@ -71,10 +72,25 @@ export async function reconcileGraphNodeIdentities( { cause }, ); }; - let rows: IdentityRow[]; try { - rows = await query( + await readRows( `MATCH (n:\`${table}\`) RETURN ${fields.map((f) => `n.${f} AS ${f}`).join(', ')}`, + (row) => { + const node = remaining.get(row.id); + if (!node) throw new Error(`unexpected or duplicate ID ${JSON.stringify(row.id)}`); + for (const field of identityFields) { + const wanted = storedIdentityField(node, field); + const actual = + field === 'name' || field === 'filePath' ? (row[field] ?? '') : row[field]; + if (actual !== wanted) { + throw new Error( + `${row.id}.${field}: expected ${JSON.stringify(wanted)}, read ${JSON.stringify(actual)}`, + ); + } + } + remaining.delete(row.id); + nodes++; + }, ); } catch (error) { fail( @@ -82,21 +98,6 @@ export async function reconcileGraphNodeIdentities( error, ); } - for (const row of rows) { - const node = remaining.get(row.id); - if (!node) fail(`unexpected or duplicate ID ${JSON.stringify(row.id)}`); - for (const field of identityFields) { - const wanted = storedIdentityField(node, field); - const actual = field === 'name' || field === 'filePath' ? (row[field] ?? '') : row[field]; - if (actual !== wanted) { - fail( - `${row.id}.${field}: expected ${JSON.stringify(wanted)}, read ${JSON.stringify(actual)}`, - ); - } - } - remaining.delete(row.id); - nodes++; - } if (remaining.size) { fail( `${remaining.size} missing ID(s), including ${JSON.stringify(remaining.keys().next().value)}`, diff --git a/gitnexus/src/core/ingestion/scope-resolution/scope/walkers.ts b/gitnexus/src/core/ingestion/scope-resolution/scope/walkers.ts index 51f9e91fe..95141ce3c 100644 --- a/gitnexus/src/core/ingestion/scope-resolution/scope/walkers.ts +++ b/gitnexus/src/core/ingestion/scope-resolution/scope/walkers.ts @@ -99,6 +99,7 @@ export function lookupNameClaim( local, scopes.bindings.get(scope.id)?.get(spelling) ?? EMPTY_BINDINGS, ) ?? EMPTY_BINDINGS; + if (additional.length === 0 && augmented.length === 0) return local; return [ ...local, ...compatibleClassBindings(additional, options.classCandidateFilter), @@ -108,24 +109,23 @@ export function lookupNameClaim( ), ]; } - return [ - ...local, - ...compatibleClassBindings( - scopes.bindings.get(scope.id)?.get(spelling) ?? EMPTY_BINDINGS, - options.classCandidateFilter, - ), - ...augmented, - ...(collectNamespaceFqnBindings( - scope.id, - spelling, - scopes, - options.classCandidateFilter, - ) ?? []), - ...compatibleClassBindings( - scopes.workspaceFqnBindings?.get(spelling) ?? EMPTY_BINDINGS, - options.classCandidateFilter, - ), - ]; + const indexed = compatibleClassBindings( + scopes.bindings.get(scope.id)?.get(spelling) ?? EMPTY_BINDINGS, + options.classCandidateFilter, + ); + const namespace = + collectNamespaceFqnBindings(scope.id, spelling, scopes, options.classCandidateFilter) ?? + EMPTY_BINDINGS; + const workspace = compatibleClassBindings( + scopes.workspaceFqnBindings?.get(spelling) ?? EMPTY_BINDINGS, + options.classCandidateFilter, + ); + if ( + local.length + indexed.length + augmented.length + namespace.length + workspace.length === + 0 + ) + return EMPTY_BINDINGS; + return [...local, ...indexed, ...augmented, ...namespace, ...workspace]; }, }, options, diff --git a/gitnexus/src/core/lbug/lbug-adapter.ts b/gitnexus/src/core/lbug/lbug-adapter.ts index 407db8630..4aea794b1 100644 --- a/gitnexus/src/core/lbug/lbug-adapter.ts +++ b/gitnexus/src/core/lbug/lbug-adapter.ts @@ -3,6 +3,7 @@ import { createReadStream, createWriteStream, existsSync, constants as fsConstan import { createInterface } from 'readline'; import { once } from 'events'; import { finished } from 'stream/promises'; +import { setImmediate as yieldQueryRows } from 'node:timers/promises'; import path from 'path'; import lbug from '@ladybugdb/core'; import { closeQueryResults } from './query-result-utils.js'; @@ -1956,6 +1957,57 @@ export const executeQuery = async (cypher: string): Promise => { return await executePrepared(cypher, {}); }; +/** + * Visit a single trusted, parameter-free query without retaining a JS row array. + * The visitor must be synchronous and must not issue another connection query. + * Keep the connection locked through yields and cursor close so a checkpoint + * cannot interleave with reading. Use direct execution: repeated prepared reads + * exhausted the native pool in the normal-GC identity scaling probe. + */ +export const forEachQueryRow = async ( + cypher: string, + onRow: (row: any) => undefined, +): Promise => { + warnIfQueryTextUnbounded(cypher, 'forEachQueryRow', (message) => logger.warn(message)); + const c = conn; + if (!c) throw new Error('LadybugDB not initialized. Call initLbug first.'); + + await withConnLock(async () => { + const queryResult = await c.query(cypher); + const results = Array.isArray(queryResult) ? queryResult : [queryResult]; + let failed = false; + let failure: unknown; + try { + if (results.length !== 1 || !results[0]) { + throw new Error('forEachQueryRow requires exactly one query result'); + } + const result = results[0]; + let rows = 0; + while (result.hasNext()) { + const row = result.getNextSync(); + if (row === null) throw new Error('Query cursor ended before its advertised next row'); + onRow(row); + if (++rows % 1024 === 0) await yieldQueryRows(); + } + } catch (error) { + failed = true; + failure = error; + } finally { + for (const result of results) { + try { + result?.close(); + } catch (error) { + if (!failed) { + failed = true; + failure = error; + } + } + } + } + if (failed) throw failure; + }); +}; + export const streamQuery = async ( cypher: string, onRow: (row: any) => void | Promise, diff --git a/gitnexus/src/core/run-analyze.ts b/gitnexus/src/core/run-analyze.ts index 3e0f99ed9..bf2b2e7c2 100644 --- a/gitnexus/src/core/run-analyze.ts +++ b/gitnexus/src/core/run-analyze.ts @@ -73,6 +73,7 @@ import { loadGraphToLbug, getLbugStats, executeQuery, + forEachQueryRow, executeWithReusedStatement, closeLbug, closeLbugBeforeExit, @@ -4419,7 +4420,7 @@ async function runFullAnalysisInner( await markIncrementalGraphVerification(); await reconcileGraphNodeIdentities( pipelineResult.graph, - executeQuery, + forEachQueryRow, 'post-COPY/checkpoint', ); } @@ -5573,7 +5574,7 @@ async function runFullAnalysisInner( } await reconcileGraphNodeIdentities( pipelineResult.graph, - executeQuery, + forEachQueryRow, 'pre-publish/checkpoint', ); } diff --git a/gitnexus/test/integration/lbug-conn-serialization.test.ts b/gitnexus/test/integration/lbug-conn-serialization.test.ts index 57a1ec32e..e6c24700e 100644 --- a/gitnexus/test/integration/lbug-conn-serialization.test.ts +++ b/gitnexus/test/integration/lbug-conn-serialization.test.ts @@ -11,7 +11,8 @@ * use an empty (initialized) DB — they prove the lock is taken regardless of * whether any rows match. */ -import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; +import lbug from '@ladybugdb/core'; import { withTestLbugDB } from '../helpers/test-indexed-db.js'; import { NODE_TABLES } from '../../src/core/lbug/schema.js'; @@ -40,6 +41,113 @@ import { closeQueryResults } from '../../src/core/lbug/query-result-utils.js'; const closeSpy = vi.mocked(closeQueryResults); withTestLbugDB('conn-serialization', () => { + describe('incremental identity cursor lifetime', () => { + afterEach(() => vi.restoreAllMocks()); + + it('reads real rows without getAll and releases the cursor after a visitor failure', async () => { + const adapter = await import('../../src/core/lbug/lbug-adapter.js'); + const getAll = vi.spyOn(lbug.QueryResult.prototype, 'getAll'); + const close = vi.spyOn(lbug.QueryResult.prototype, 'close'); + const seen: number[] = []; + await adapter.forEachQueryRow('UNWIND [1, 2, 3] AS n RETURN n', (row) => { + seen.push(row.n); + }); + expect(seen).toEqual([1, 2, 3]); + expect(getAll).not.toHaveBeenCalled(); + expect(close).toHaveBeenCalledTimes(1); + const error = new Error('bad identity'); + await expect( + adapter.forEachQueryRow('RETURN 1 AS n', () => { + throw error; + }), + ).rejects.toBe(error); + expect(close).toHaveBeenCalledTimes(2); + await expect(adapter.executeQuery('RETURN 2 AS n')).resolves.toEqual([{ n: 2 }]); + }); + + it('yields while retaining the lock through the last row and cursor close', async () => { + const adapter = await import('../../src/core/lbug/lbug-adapter.js'); + let read = 0; + let visited = 0; + let yieldedAt = 0; + const close = vi.fn(); + const cursor = { + hasNext: () => read < 2050, + getNextSync: () => { + expect(visited).toBe(read); + return { n: ++read }; + }, + close, + }; + const query = vi.spyOn(lbug.Connection.prototype, 'query').mockImplementation(async (sql) => { + expect(sql).toBe('scan'); + return cursor as any; + }); + let checkpoint: Promise | undefined; + // Schedule outside the reader's lock context, like the WAL driver timer. + setImmediate(() => { + yieldedAt = visited; + checkpoint = adapter.executeQuery('CHECKPOINT'); + }); + const prepare = vi.spyOn(lbug.Connection.prototype, 'prepare'); + prepare.mockImplementation(async () => { + expect(visited).toBe(2050); + expect(close).toHaveBeenCalledTimes(1); + return { isSuccess: () => true } as any; + }); + vi.spyOn(lbug.Connection.prototype, 'execute').mockResolvedValue({ + getAll: async () => [], + close: () => {}, + } as any); + await adapter.forEachQueryRow('scan', () => { + visited++; + }); + await checkpoint; + expect(yieldedAt).toBeGreaterThan(0); + expect(yieldedAt).toBeLessThan(2050); + expect(query).toHaveBeenCalledTimes(1); + expect(prepare).toHaveBeenCalledTimes(1); + }); + + it.each(['none', 'multiple'] as const)( + 'rejects %s result cursors and closes all returned cursors', + async (kind) => { + const { forEachQueryRow } = await import('../../src/core/lbug/lbug-adapter.js'); + const close = vi.fn(); + const cursors = kind === 'none' ? [] : [{ close }, { close }]; + vi.spyOn(lbug.Connection.prototype, 'query').mockResolvedValue(cursors as any); + const visit = vi.fn(); + await expect(forEachQueryRow('scan', visit)).rejects.toThrow('exactly one query result'); + expect(visit).not.toHaveBeenCalled(); + expect(close).toHaveBeenCalledTimes(cursors.length); + }, + ); + + it.each(['read', 'null', 'close', 'read-and-close'] as const)( + 'fails closed on %s failure', + async (stage) => { + const { forEachQueryRow } = await import('../../src/core/lbug/lbug-adapter.js'); + const readError = new Error('native read failure'); + const closeError = new Error('native close failure'); + const close = vi.fn(() => { + if (stage.includes('close')) throw closeError; + }); + vi.spyOn(lbug.Connection.prototype, 'query').mockResolvedValue({ + hasNext: () => stage !== 'close', + getNextSync: () => { + if (stage === 'null') return null; + throw readError; + }, + close, + } as any); + const outcome = forEachQueryRow('scan', vi.fn()); + if (stage === 'null') await expect(outcome).rejects.toThrow('advertised next row'); + else await expect(outcome).rejects.toBe(stage === 'close' ? closeError : readError); + expect(close).toHaveBeenCalledTimes(1); + }, + ); + }); + describe('singleton-conn helpers acquire withConnLock (P1 #2264)', () => { beforeEach(() => { // Setup (clear/seed/flush) already exercised the lock; reset so each diff --git a/gitnexus/test/unit/identity-reader-contract.test.ts b/gitnexus/test/unit/identity-reader-contract.test.ts new file mode 100644 index 000000000..c7e020ff3 --- /dev/null +++ b/gitnexus/test/unit/identity-reader-contract.test.ts @@ -0,0 +1,16 @@ +import { describe, expectTypeOf, it } from 'vitest'; +import type { forEachQueryRow } from '../../src/core/lbug/lbug-adapter.js'; +import type { reconcileGraphNodeIdentities } from '../../src/core/incremental/write-reconciliation.js'; + +type CursorVisitor = Parameters[1]; +type IdentityReader = Parameters[1]; +type IdentityVisitor = Parameters[1]; + +describe('identity reader synchronous visitor contract', () => { + it('accepts synchronous visitors and rejects async visitors at both boundaries', () => { + expectTypeOf<() => undefined>().toExtend(); + expectTypeOf<() => undefined>().toExtend(); + expectTypeOf<() => Promise>().not.toExtend(); + expectTypeOf<() => Promise>().not.toExtend(); + }); +}); diff --git a/gitnexus/test/unit/incremental-write-benchmark-verdict.test.ts b/gitnexus/test/unit/incremental-write-benchmark-verdict.test.ts index e1c3b0c35..377b36215 100644 --- a/gitnexus/test/unit/incremental-write-benchmark-verdict.test.ts +++ b/gitnexus/test/unit/incremental-write-benchmark-verdict.test.ts @@ -52,7 +52,12 @@ it.each([ nativePhases, size: { nodes: 1 }, reconcileGraphNodeIdentities, - adapter: { executeQuery: async (query: string) => (query.includes('Function') ? rows : []) }, + adapter: { + executeQuery: async (query: string) => (query.includes('Function') ? rows : []), + forEachQueryRow: async (query: string, onRow: (row: (typeof rows)[number]) => void) => { + if (query.includes('Function')) rows.forEach(onRow); + }, + }, }) as (phase: string) => Promise; await audit('controlled-scan'); expect(nativePhases).toEqual([expect.objectContaining({ verdict, rows: rows.length })]); diff --git a/gitnexus/test/unit/incremental-write-integrity.test.ts b/gitnexus/test/unit/incremental-write-integrity.test.ts index 00d3941c8..c8aee91f5 100644 --- a/gitnexus/test/unit/incremental-write-integrity.test.ts +++ b/gitnexus/test/unit/incremental-write-integrity.test.ts @@ -138,7 +138,7 @@ describe('incremental graph identity before publication', () => { ); await adapter.tryFlushWAL(); await expect( - reconcileGraphNodeIdentities(graph, adapter.executeQuery, 'native CSV parity'), + reconcileGraphNodeIdentities(graph, adapter.forEachQueryRow, 'native CSV parity'), ).resolves.toMatchObject({ nodes: 5 }); } finally { await adapter.closeLbug(); @@ -264,7 +264,7 @@ describe('incremental graph identity before publication', () => { await expect( reconcileGraphNodeIdentities( recovered.pipelineResult.graph, - adapter.executeQuery, + adapter.forEachQueryRow, 'recovered/reopened', ), ).resolves.toMatchObject({ nodes: expect.any(Number) }); diff --git a/gitnexus/test/unit/lexical-benchmark-preflight.test.ts b/gitnexus/test/unit/lexical-benchmark-preflight.test.ts new file mode 100644 index 000000000..9f0f3deba --- /dev/null +++ b/gitnexus/test/unit/lexical-benchmark-preflight.test.ts @@ -0,0 +1,204 @@ +import { execFileSync, spawnSync } from 'node:child_process'; +import fs from 'node:fs'; +import os from 'node:os'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { afterEach, describe, expect, it } from 'vitest'; + +const harness = fileURLToPath(new URL('../../bench/lexical-lookup/measure.mjs', import.meta.url)); +const scratch: string[] = []; +afterEach(() => { + for (const root of scratch.splice(0)) fs.rmSync(root, { recursive: true, force: true }); +}); + +describe('lexical benchmark preflight', () => { + it.each(['missing', 'empty-runtime', 'empty-output', 'lifecycle'])( + 'rejects %s arguments with a diagnostic before filesystem work', + (kind) => { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'lexical-args-')); + scratch.push(root); + const args = [ + root, + root, + path.join(root, 'before'), + path.join(root, 'after'), + path.join(root, 'output'), + ]; + if (kind === 'missing') args.pop(); + if (kind === 'empty-runtime') args[0] = ''; + if (kind === 'empty-output') args[4] = ''; + if (kind === 'lifecycle') args.push('warm'); + const result = spawnSync(process.execPath, [harness, ...args], { encoding: 'utf8' }); + expect(result.status).toBe(1); + expect(result.stderr).toContain( + kind === 'lifecycle' + ? 'Lifecycle must be fresh or persistent; received "warm"' + : 'Expected BASE_RUNTIME CANDIDATE_RUNTIME BASE_CORPUS CANDIDATE_CORPUS OUTPUT', + ); + expect(fs.readdirSync(root)).toEqual([]); + }, + ); + + it.each([ + ['GITNEXUS_LEXICAL_BENCH_SCREEN', 'Screen must be 0 or 1'], + ['GITNEXUS_LEXICAL_BENCH_BASE_FIRST', 'Base first must be 0 or 1'], + ])('rejects invalid %s before touching corpora', (setting, message) => { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'lexical-option-')); + scratch.push(root); + const output = path.join(root, 'output'); + const result = spawnSync(process.execPath, [harness, root, root, root, root, output], { + encoding: 'utf8', + env: { ...process.env, [setting]: 'false' }, + }); + expect(result.status).toBe(1); + expect(result.stderr).toContain(message); + expect(fs.existsSync(output)).toBe(false); + }); + + it.each(['empty', 'indexes', 'results.json'])( + 'rejects existing %s output before touching corpora', + (contents) => { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'lexical-preflight-')); + scratch.push(root); + const output = path.join(root, 'output'); + fs.mkdirSync(output); + if (contents === 'indexes') fs.mkdirSync(path.join(output, 'indexes')); + if (contents === 'results.json') + fs.writeFileSync(path.join(output, 'results.json'), 'prior result'); + const before = path.join(root, 'before'); + const after = path.join(root, 'after'); + const result = spawnSync(process.execPath, [harness, root, root, before, after, output], { + encoding: 'utf8', + env: { + ...process.env, + GITNEXUS_LEXICAL_BENCH_WORKER: '0', + GITNEXUS_LEXICAL_BENCH_WORKERS: '2', + GITNEXUS_LEXICAL_BENCH_HEAP_MIB: '4096', + }, + }); + expect(result.status).toBe(1); + expect(result.stderr).toContain('Output already exists'); + expect(fs.existsSync(before)).toBe(false); + expect(fs.existsSync(after)).toBe(false); + expect(fs.readdirSync(output)).toEqual(contents === 'empty' ? [] : [contents]); + if (contents === 'results.json') + expect(fs.readFileSync(path.join(output, contents), 'utf8')).toBe('prior result'); + }, + ); +}); + +describe('lexical benchmark sample collection', () => { + it.each(['fresh', 'persistent'])( + 'collects a complete reversed-order baseline with a slower candidate (%s)', + (lifecycle) => { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'lexical-samples-')); + scratch.push(root); + const corpora = ['before', 'after'].map((name) => { + const repo = path.join(root, name); + fs.mkdirSync(repo); + execFileSync('git', ['init', '--quiet'], { cwd: repo }); + execFileSync( + 'git', + [ + '-c', + 'user.name=Benchmark Test', + '-c', + 'user.email=test@example.test', + '-c', + 'commit.gpgsign=false', + 'commit', + '--quiet', + '--allow-empty', + '-m', + 'fixture', + ], + { + cwd: repo, + env: { + ...process.env, + GIT_AUTHOR_DATE: '2020-01-01T00:00:00Z', + GIT_COMMITTER_DATE: '2020-01-01T00:00:00Z', + }, + }, + ); + return repo; + }); + const runtimes = [1, 100].map((duration) => { + const runtime = path.join(root, `runtime-${duration}`); + const core = path.join(runtime, 'gitnexus/dist/core'); + fs.mkdirSync(path.join(core, 'lbug'), { recursive: true }); + fs.writeFileSync(path.join(runtime, 'package.json'), '{"type":"module"}'); + // A deterministic clock isolates collection/order behavior from machine load. + fs.writeFileSync( + path.join(core, 'run-analyze.js'), + ` + import fs from 'node:fs'; + import path from 'node:path'; + let clock = 0; + Object.defineProperty(globalThis, 'performance', {value: {now: () => clock}}); + export async function runFullAnalysis(repo) { + clock += ${duration}; + const target = fs.readFileSync(path.join(repo, 'gitnexus/src/semantic-bench-control.ts'), 'utf8').includes('s.load()') ? 'load' : 'save'; + return { + storagePath: repo, stats: {}, rebuildReasons: [], + incrementalStats: {writeMode: 'incremental', changedFiles: 1}, + pipelineResult: {graph: { + *iterNodes() { yield {id: 'semanticBenchUse', label: 'Function'}; }, + *iterRelationships() { yield {sourceId: 'semanticBenchUse', targetId: target, type: 'CALLS'}; } + }} + }; + } + `, + ); + fs.writeFileSync(path.join(core, 'logger.js'), 'export function configureLoggerSink() {}'); + fs.writeFileSync( + path.join(core, 'lbug/lbug-adapter.js'), + ` + import fs from 'node:fs'; + import path from 'node:path'; + let repo; + export async function initLbug(db) { repo = path.dirname(db); } + export async function executeQuery() { + return [{target: fs.readFileSync(path.join(repo, 'gitnexus/src/semantic-bench-control.ts'), 'utf8').includes('s.load()') ? 'load' : 'save'}]; + } + export async function closeLbug() {} + `, + ); + return runtime; + }); + for (const screen of ['0', '1']) { + const output = path.join(root, `output-${screen}`); + const result = spawnSync( + process.execPath, + [harness, ...runtimes, ...corpora, output, lifecycle], + { + encoding: 'utf8', + env: { + ...process.env, + GITNEXUS_LEXICAL_BENCH_WORKER: '0', + GITNEXUS_LEXICAL_BENCH_WORKERS: '2', + GITNEXUS_LEXICAL_BENCH_HEAP_MIB: '256', + GITNEXUS_LEXICAL_BENCH_SCREEN: screen, + GITNEXUS_LEXICAL_BENCH_BASE_FIRST: '0', + }, + }, + ); + expect(result.status, result.stderr).toBe(0); + const report = JSON.parse(fs.readFileSync(path.join(output, 'results.json'), 'utf8')); + expect(report.screen).toBe(screen === '1'); + expect(report.baseFirst).toBe(false); + expect(report.results.map((sample: { name: string }) => sample.name)).toEqual([ + 'candidate-seed', + 'baseline-seed', + 'candidate-1', + 'baseline-1', + ...(screen === '0' ? ['baseline-2', 'candidate-2', 'candidate-3', 'baseline-3'] : []), + ]); + for (const repo of corpora) + expect(fs.existsSync(path.join(repo, 'gitnexus/src/semantic-bench-control.ts'))).toBe( + false, + ); + } + }, + ); +}); diff --git a/gitnexus/test/unit/run-analyze-fts-crash-marker.test.ts b/gitnexus/test/unit/run-analyze-fts-crash-marker.test.ts index 352f987d9..4c0056aa6 100644 --- a/gitnexus/test/unit/run-analyze-fts-crash-marker.test.ts +++ b/gitnexus/test/unit/run-analyze-fts-crash-marker.test.ts @@ -120,13 +120,14 @@ const mockLbugAdapter = async () => { initLbug: vi.fn(async () => undefined), loadGraphToLbug: vi.fn(async () => undefined), getLbugStats: vi.fn(async () => ({ nodes: 1, edges: 0, communities: 0, processes: 0 })), + executeQuery: vi.fn(async () => []), // The policy fixture has one stored File row. Publication now reconciles // that identity instead of trusting the synthetic node count alone. - executeQuery: vi.fn(async (query: string) => - query.startsWith('MATCH (n:`File`) RETURN n.id AS id') - ? [{ id: 'file:src/a.ts', name: REL_FILE, filePath: REL_FILE }] - : [], - ), + forEachQueryRow: vi.fn(async (query, onRow) => { + if (query.startsWith('MATCH (n:`File`) RETURN n.id AS id')) { + onRow({ id: 'file:src/a.ts', name: REL_FILE, filePath: REL_FILE }); + } + }), executeWithReusedStatement: vi.fn(async () => []), closeLbug: vi.fn(async () => undefined), wipeLbugDbFiles: vi.fn(async () => undefined), diff --git a/gitnexus/test/unit/scope-resolution/lexical-name-claims.test.ts b/gitnexus/test/unit/scope-resolution/lexical-name-claims.test.ts index 45ae37cfd..cf002c027 100644 --- a/gitnexus/test/unit/scope-resolution/lexical-name-claims.test.ts +++ b/gitnexus/test/unit/scope-resolution/lexical-name-claims.test.ts @@ -14,6 +14,7 @@ import { findClassBindingInScope, findReceiverTypeBinding, isNamespaceNameShadowed, + lookupNameClaim, } from '../../../src/core/ingestion/scope-resolution/scope/walkers.js'; import { findCallableBindingsAndAdlBlocker } from '../../../src/core/ingestion/languages/cpp/callable-bindings.js'; import { followChainPostFinalize } from '../../../src/core/ingestion/scope-resolution/passes/imported-return-types.js'; @@ -60,6 +61,40 @@ function indexes( } describe('lexical name ownership', () => { + it.each(['Function', 'Class'] as const)( + 'keeps %s lookup snapshots after source bindings change', + (kind) => { + const bindings = new Map(); + const inner = scope('fn', 'module', { bindings, kind }); + const outer = scope('module', null); + const state = { ...indexes(inner, outer), bindings: new Map([[inner.id, bindings]]) }; + const missing = lookupNameClaim(inner.id, 'helper', state); + expect(missing.status).toBe('absent'); + const local: BindingRef[] = [binding]; + bindings.set('helper', local); + const found = lookupNameClaim(inner.id, 'helper', state); + expect(found.bindings).toEqual([binding]); + local.push({ def: { ...target, nodeId: 'second:helper' }, origin: 'local' }); + expect(found.bindings).toEqual([binding]); + expect(missing.bindings).toEqual([]); + expect(lookupNameClaim(inner.id, 'helper', state).bindings).toHaveLength(2); + }, + ); + + it('clears deferred activation without mutating reused caller options', () => { + const late: BindingRef = { ...binding, availableFrom: { startLine: 8, startCol: 0 } }; + const outer = scope('module', null, { bindings: new Map([['helper', [late]]]) }); + const inner = scope('fn', outer.id, { lookupPolicy: { deferParentActivation: true } }); + const options = Object.freeze({ position: Object.freeze({ startLine: 1, startCol: 0 }) }); + const state = indexes(inner, outer); + expect(lookupNameClaim(inner.id, 'helper', state, options).bindings).toEqual([late]); + expect(lookupNameClaim(outer.id, 'helper', state, options).status).toBe('absent'); + expect( + lookupNameClaim(inner.id, 'helper', state, { ...options, preservePosition: true }).status, + ).toBe('absent'); + expect(options.position).toEqual({ startLine: 1, startCol: 0 }); + }); + it('keeps touching half-open import ranges separate', () => { const earlier = { startLine: 1, startCol: 0, endLine: 1, endCol: 10 }; const later = { startLine: 1, startCol: 10, endLine: 1, endCol: 20 }; diff --git a/gitnexus/test/unit/write-reconciliation.test.ts b/gitnexus/test/unit/write-reconciliation.test.ts index d4d4a86ea..f2efba614 100644 --- a/gitnexus/test/unit/write-reconciliation.test.ts +++ b/gitnexus/test/unit/write-reconciliation.test.ts @@ -41,7 +41,9 @@ const rows = () => [ }, ]; const queryFor = (functions: ReturnType) => - vi.fn(async (query: string) => (query.includes('(n:`Function`)') ? functions : [])); + vi.fn(async (query: string, onRow: (row: ReturnType[number]) => void) => { + if (query.includes('(n:`Function`)')) functions.forEach(onRow); + }); describe('incremental identity reconciliation', () => { it('certifies every identity using one unfiltered query per label', async () => {