Commit graph

1322 commits

Author SHA1 Message Date
Gergo Magyar
2f74f75968 refactor(impact): move PDG bridge helpers + result composition to pdg-impact.ts
Behavior-preserving relocation of the pure PDG-result-shaping code from
local-backend.ts to pdg-impact.ts, where it is cohesive with the module's
projection/assembly role: the bridge-evidence types + helpers
(pdgBridgeEvidenceForImpact, betterBridgeEvidence, normalizePdgBridgeByDepth,
countPdgEvidence, dominantInterproceduralEvidence, projectStatementPreciseByDepth)
and composeUnifiedPdgImpactResult (method → exported function). LocalBackend keeps
the DB-access seams (calleesOfBlocks, _runImpactBFS) per the documented layering
("LocalBackend owns repo lifecycle; pdg-impact.ts owns traversal/projection") and
imports the moved helpers. No cycle (pdg-impact does not import local-backend).
local-backend.ts shrinks ~330 lines; tsc green, all impact/PDG suites pass, the
composed result is byte-identical (parseSourceSafe statementPrecision 0.667).

Addresses PR #2227 tri-review finding (maintainability) — the final remediation unit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 16:56:37 +00:00
Gergő Magyar
f4d4034994
Merge branch 'main' into feat/pdg-impact-mode 2026-06-18 17:44:55 +01:00
Gergo Magyar
ea757f8b5c test(impact): add a source-only (non-reconciled) ground-truth fixture
The accuracy corpus documents an annotation-circularity threat (KTD9): most
fixtures' intra_AIS was reconciled against the live traversal, so F1=1.0 proves
self-consistency, not independent correctness. Add one fixture
(intra-control-gate) whose intra_AIS is written PURELY from language semantics
and is deliberately NOT reconciled — each guarded arm is a single-statement block
so there is no coalescing to surprise the annotation. The traversal scores it
F1=1.0 (lines {11,13}, FPIS=FNIS=0), so it is a genuine independent confirmation —
the one corpus data point that breaks the circularity threat. Re-baseline the
annotation fingerprint and bump the corpus counts (intra 6→7, 13 measurable).

Addresses PR #2227 tri-review finding (testing).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 16:42:12 +00:00
glier
16e6ad6da8
fix(server): resolve clone/upload/mapping roots from GITNEXUS_HOME (#2229)
Some checks are pending
CodeQL / Analyze (python) (push) Waiting to run
Gitleaks / gitleaks (push) Waiting to run
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
Publish / Classify release event (push) Waiting to run
Publish / RC guard (marker + release-PR skip) (push) Blocked by required conditions
Trivy Image Scan / Trivy (gitnexus-cli) (push) Waiting to run
Publish / ci (push) Blocked by required conditions
Publish / Publish to npm (push) Blocked by required conditions
Publish / Build & Push RC Docker images (push) Blocked by required conditions
Scorecard / Scorecard analysis (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-web) (push) Waiting to run
* fix(server): resolve clone/upload/mapping roots from GITNEXUS_HOME

CLONE_ROOT (git-clone.ts), UPLOAD_ROOT (upload-paths.ts), and the
server-mapping file (embeddings/server-mapping.ts) computed their root
from os.homedir() directly, ignoring GITNEXUS_HOME. The Docker image
sets GITNEXUS_HOME=/data/gitnexus (the persistent volume that also holds
the registry and indexes), so cloned/uploaded repos and their .gitnexus
indexes instead landed in the container's ephemeral ~/.gitnexus and were
lost on container recreation, while registry.json (which honors
GITNEXUS_HOME) kept pointing at the now-dead path. That also defeated
incremental re-analysis: a recreated container re-clones from scratch and
full-rebuilds instead of git pull + incremental update.

Source all three from the existing getGlobalDir() helper — the same
GITNEXUS_HOME-aware primitive the registry and groups already use.
Behavior is unchanged when GITNEXUS_HOME is unset (CLI / local installs):
it falls back to ~/.gitnexus exactly as before. No signatures change and
no UPLOAD_ROOT consumers are touched.

Adds test/unit/gitnexus-home-roots.test.ts covering both the
GITNEXUS_HOME-set and unset paths for all three roots.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(server): make clone-root assertions GITNEXUS_HOME-aware; cover server-mapping fallback

Addresses PR review (#2229):

- git-clone.test.ts hardcoded path.join(os.homedir(), '.gitnexus', 'repos')
  for the clone root, so the "direct child of the clone root" and containment
  assertions failed when GITNEXUS_HOME was set in the ambient env (e.g. a CI
  runner). CLONE_ROOT now derives from getGlobalDir(); mirror that derivation
  via EXPECTED_CLONE_ROOT (GITNEXUS_HOME || ~/.gitnexus), computed at module
  load — the same point CLONE_ROOT is frozen — so the two always agree.

- The GITNEXUS_HOME-unset fallback test covered clone + upload roots but not
  server-mapping (one of the three changed modules). Add a fallback case for
  readServerMapping. It redirects HOME/USERPROFILE to a tmp dir (os.homedir()
  honors them) so it exercises the real ~/.gitnexus fallback without writing
  into the developer's actual ~/.gitnexus/server-mapping.json.

Both files pass with and without GITNEXUS_HOME set.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(server): use mkdtemp for GITNEXUS_HOME path-root test temp dirs

CodeQL js/insecure-temporary-file flagged the two writes that used a fixed
os.tmpdir() name (gitnexus-home-roots-test, gitnexus-fallback-home): a
co-located process could pre-create or symlink the predictable path before
the test write lands. Switch both to fs.mkdtemp(), which atomically creates a
uniquely-named directory — the canonical sanitizer this repo already uses
(see core/group/storage.ts). Behavior is unchanged; tests still pass with and
without GITNEXUS_HOME set.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(embeddings): resolve server-mapping path for parity with clone/upload roots

MAPPING_FILE now wraps path.resolve() like CLONE_ROOT (git-clone.ts) and
UPLOAD_ROOT (upload-paths.ts), so a relative GITNEXUS_HOME yields an absolute
path. No-op for the supported absolute-GITNEXUS_HOME config (Docker) and for
readServerMapping's only caller (run-analyze.ts).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(server): derive EXPECTED_CLONE_ROOT from getGlobalDir() to avoid drift

The test mirror now imports getGlobalDir() and computes the expected clone root
the same way production CLONE_ROOT does, instead of re-deriving the
GITNEXUS_HOME || ~/.gitnexus fallback by hand. Byte-identical today; future-proof
if getGlobalDir() grows a branch. (os import retained — still used by os.tmpdir().)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(server): rename shadowed savedHome in server-mapping fallback test

The inner savedHome (saves process.env.HOME) shadowed the describe-scope
savedHome (saves process.env.GITNEXUS_HOME). Renamed the inner one to
savedProcessHome at its declaration and both restore sites in the finally
block. Pure rename, no behavior change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(server): scope customHome temp dir to the GITNEXUS_HOME-set cases

beforeEach created a customHome temp dir for all five tests, but the two
fallback cases never use it (one manages its own fakeHome, the other needs
none). Moved the mkdtemp/rm into a nested describe('with GITNEXUS_HOME set')
wrapping the three set-cases; the shared outer afterEach still restores
GITNEXUS_HOME and resets modules for all five.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
2026-06-18 17:39:44 +01:00
Gergo Magyar
b3ef08b149 docs(impact): correct axis-3 figures after the seed-line fix
Re-measured the statement-precise reach on the live index after the seed-line
proven fix (and the related closure-pin / order-independence fixes). The
corrected downstream numbers: the statement-precise subset is strictly tighter
than callgraph on 52/90 with-slice functions (median proven 1 vs callgraph 2,
median statement-precision 0.67); localization median 0.26 (down) / 0.21 (up).
Upstream stays all-proven (callgraph-equal) by design. Full inter-procedural
reach remains identical to callgraph (240/240). The earlier figures (43/90,
0.30/0.22) predated the seed-block union, which moved seed-only-call functions
from a false all-proven into correct statement-precise discrimination.

Addresses PR #2227 tri-review headline follow-up (re-measure + doc correction).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 16:31:07 +00:00
Gergo Magyar
9463281153 test(impact): gate the statement-precise projection end-to-end
The new statement-precise inter-procedural reach (statementPreciseByDepth /
statementPrecision) shipped with no accuracy gate. Add a real-DB integration test
of an FN-shaped function: the seeded line calls `foo` (and `foo` is called
nowhere else), a dependent line calls `bar`, an unreachable block calls `baz`.
It asserts foo (the seed-line callee — the regression target) and bar are proven,
baz is excluded, and the full reach still lists all three (recall preserved). The
test fails if the seed-block union (U2) regresses.

Chosen over a measure.mjs scored axis: the harness scores full reach against the
whole-symbol inter_AIS, but the statement-precise subset is per-seeded-line, so a
shared-axis gate would be apples-to-oranges; a purpose-built fixture gates it
cleanly.

Addresses PR #2227 tri-review finding (P2 — projection ships ungated).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 16:27:05 +00:00
Gergo Magyar
64049b0c99 fix(impact): signal the per-statement site cap on BasicBlock.callees
When a statement's call sites are truncated at DEFAULT_PDG_MAX_SITES_PER_STATEMENT
the recorded callee list is incomplete, so over-cap callees were silently absent
from BasicBlock.callees — making the impact bridge label a reachable-but-dropped
callee `unproven-bridge` with no signal. calleesOfBlock now emits a reserved
sentinel ('*', not a valid identifier leaf) for a capped block, and the bridge
treats a slice containing it as callee-unknown → keeps reach callgraph-equal
(proven) rather than under-proving. No fixture/real block hits the cap, so the
emit byte-identity fingerprint is unchanged (gate stays green; no re-index).

Addresses PR #2227 tri-review finding (P3, adversarial).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 16:21:30 +00:00
Gergo Magyar
2a511ebd88 test(impact): integration cover line-seeded slice over callee-less blocks
A real-DB downstream line seed reaches a dependent block via the CDG edge, so
calleesOfBlocks runs over real seed+reachable blocks whose `callees` carry no
data (created without the property — the no-calls / pre-v2 reality). Assert the
call completes without surfacing a query failure, the slice resolves, and the
statement-precise inter-procedural precision is null (empty reach) rather than a
partial value. The column-absent variant is unit-covered (forced-throw test);
the harness builds the full schema so it cannot create a column-less table.

Addresses PR #2227 tri-review finding (testing).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 16:15:04 +00:00
Gergo Magyar
2bb1b0ac6a test(impact): cover calleesOfBlocks error-swallow graceful fallback
When the slice-callees query (RETURN b.callees) fails, calleesOfBlocks logs and
returns an empty set, so the bridge is not built and inter-procedural reach falls
back to callgraph-equal — no error surfaces and no partial proven/unproven label
is produced. Add a dispatch test that throws on the callees query (via
vi.mocked, strictly typed) and asserts no bridge is passed to the BFS and no
error surfaces.

Addresses PR #2227 tri-review finding (P1-testing).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 16:12:13 +00:00
Gergo Magyar
a03f977c25 refactor(impact): single-source the statement-precise fields under pdgInterprocedural
statementPreciseByDepth / *Counts / *ImpactedCount / statementPrecision were
emitted both at the top level of the impact result and nested under
pdgInterprocedural, doubling the contract surface and risking incoherence if one
were mutated. Keep them only under pdgInterprocedural (the scoped namespace),
drop the top-level duplicates from PdgImpactBaseResult and the composer, and
point the blast-radius reader at the single nested path (no fallback chain).

Addresses PR #2227 tri-review finding (maintainability).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 16:09:09 +00:00
Gergo Magyar
7955a534e2 refactor(impact): narrow PdgImpactResult instead of as any for slice fields
The dispatch read reachableBlocks/seedBlocks and the composer read pdgEvidence
via `(pdgResult as any)`. Replace both with a discriminated-union narrow: the
slice fields live only on the success/empty results, so narrowing with the same
`'error' in / 'pdgLayer' in` guard the composer already uses yields the typed
string[] / PdgImpactEvidenceSummary without a cast. No `as any` remain on
pdgResult; behaviour is unchanged.

Addresses PR #2227 tri-review finding (maintainability) and the strict-typing
requirement.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 16:06:28 +00:00
Gergo Magyar
909a4401d6 fix(impact): pin owning function in the statement seed anchor
The statement seed query matches blocks by startLine within the symbol's span
(a forgiving window), so a closure body block that starts on the SAME source
line as the seeded statement — but is owned by a different (nested) function —
leaked into the seed and contaminated the intra slice with the closure's
dependence. Filter the seed blocks to those whose owning fnLine === sym.startLine
+ 1 (block ids encode the 1-based function start line). Defensive: the filter
only applies when it leaves >=1 seed, so a symbol kind whose fnLine convention
differs never loses a real seed.

Addresses PR #2227 tri-review finding (P3, adversarial).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 16:03:55 +00:00
Gergo Magyar
3618ee62cf fix(impact): order-independent depth>1 bridge evidence
A symbol reachable from multiple parents in the inter-procedural BFS got its
proven/unproven bridge label from whichever parent the DB returned first
(first-writer-wins), so a diamond-reachable depth≥2 symbol could flip label
run-to-run. Compute evidence for every edge, keep the strongest across all
parents (callgraph-bridge wins, via betterBridgeEvidence), and stamp the
finalized label onto the impacted items after the depth loop. The label is now
deterministic; reach is unaffected.

Addresses PR #2227 tri-review finding (P3, correctness + adversarial).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 15:54:51 +00:00
Gergo Magyar
3ed88b330f fix(impact): prove callees invoked on the seeded line (statement-precise)
The statement-precise projection dropped a callee invoked directly on the
changed line when that callee was not also called from a downstream-dependent
block: sliceCalleeNames was built only from reachableBlocks, which excludes the
seed block by the seed-minus-reachable convention. Such a callee — the most
directly impacted of all — was labeled unproven-bridge and dropped from
statementPreciseByDepth, deflating statementPrecision.

runImpactPDG now surfaces its seedBlocks (threaded through assemblePdgImpactResult
and both empty/no-reachability early returns), and the dispatch unions
calleesOfBlocks(seedBlocks ∪ reachableBlocks). A callee on the changed line is
now proven. Recall was already preserved (full interproceduralByDepth unchanged);
this fixes the precision label.

Verified: parseSourceSafe@231 statementPrecision 0.500 → 0.667 (the seed-line
callee is now proven). New dispatch regression test covers the empty-reachable /
non-empty-seed case.

Addresses PR #2227 tri-review headline (P2, Codex + correctness + adversarial).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 15:50:19 +00:00
Gergo Magyar
7a303cffc3 refactor(impact): drop dead relationReason column from impact BFS query
The bridge rewrite replaced the old `rel[7]` call-site-line parse with
`rel.name`, leaving `r.reason AS relationReason` selected in both _runImpactBFS
queries but never read — dead payload fetched on every BFS depth step. Remove it.

Addresses PR #2227 tri-review finding (P3, Codex + maintainability).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 15:44:20 +00:00
Gergo Magyar
f4087c8d1f test(impact): re-baseline emit-persistence fingerprints for BasicBlock.callees
The new `BasicBlock.callees` column changes the BasicBlock node CSV header (and
thus the byte-identity fingerprint over all emitted CSV lines), tripping the
emit-persistence --check gate that the CI benchmarks job runs. This is the gate
working as designed — a legitimate, reviewed emit change.

Regenerate both committed baselines (whole-graph + streaming PdgEmitSink) per the
documented procedure. The streaming gate still confirms byte_identical_nodes/edges
and resident_basic_blocks === 0, so the schema change preserves the streaming
invariants.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 14:59:44 +00:00
Gergo Magyar
af35c9a955 feat(impact): statement-precise inter-procedural reach (pdg)
Make PDG impact mode's cross-function reach a real precision win instead of a
flat tie with callgraph. The proven/unproven-bridge labeling was degenerate:
it tried to read a call-site line off the CALLS edge, but edges carry only
{type, confidence, reason} (no line), so downstream was always "unproven" and
upstream always defaulted "proven" — neither a real signal.

Fix: persist what the CFG already harvests but dropped. `BasicBlock.callees`
(new STRING column) now carries the space-joined leaf callee names invoked in
each block, extracted in `emitFileCfgs` from the per-statement `sites`. The
impact bridge then marks a first-hop callee "proven" (callgraph-bridge) iff its
name appears in the callees of a block in the changed line's dependence slice,
else "unproven-bridge" — a sound, statement-precise discriminator.

`mode:'pdg'` gains an additive `statementPreciseByDepth` (+ counts,
`statementPreciseImpactedCount`, `statementPrecision`): the proven subset of the
inter-procedural reach. The full `interproceduralByDepth` is unchanged and still
preserves callgraph reach, so nothing is lost — the precise view sits alongside.

Measured on the live GitNexus index (240 functions): full reach stays identical
to callgraph (still no false "finds more"), and the statement-precise subset is
strictly tighter than callgraph on 43/90 with-slice functions (median proven 1
vs callgraph 2 symbols). Ground-truth `measure.mjs --check` stays green (native
PDG/callgraph F1 unchanged). Latency is ~1.2-1.6x (the extra slice-callees
lookup) — precision, not speed, as scoped.

INCREMENTAL_SCHEMA_VERSION → 2 (the new column forces a full re-analyze of
pre-v2 indexes; absent column degrades gracefully to the prior behavior).
`blast-radius.mjs` + its unit test gain the statement-precise axis; README's
four-axis verdict updated. Removes the dead `parseRelationSiteLine`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 12:12:54 +00:00
Gergo Magyar
fc1a94f035 feat(impact): real-code blast-radius proof for pdg localization
Add bench/impact-pdg/blast-radius.mjs: a real-code sampler that quantifies
HOW MUCH PDG narrows the impact set versus the pre-PDG (callgraph-only)
answer. Per real function it compares the line-seeded PDG statement slice to
the whole function body (block units), checks the PDG inter-procedural symbol
set against callgraph, and times both engines.

Measured on the live GitNexus index (240 functions, both directions): the PDG
slice is a median 0.30 (downstream) / 0.22 (upstream) of the function body and
localizes below whole-body on 240/240 functions, while its inter-procedural
symbol set is identical to callgraph on 240/240 (0 divergence) and it runs
~1.2-1.6x slower. Combined with the AIS-backed measure.mjs gate (intra/mixed
PDG F1=1.0, FPIS=FNIS=0), this is the proof that PDG's narrower slice is a
correct over-approximation cut, not a dropped-truth risk.

README gains a four-axis verdict that tests each "better" claim and reports it
honestly: tighter/fewer-false-alarms CONFIRMED, catches-callgraph-misses
CONFIRMED (new statement axis), finds-more-callers REFUTED (tie by design),
faster REFUTED. Adds a deterministic helper unit test (no analyze/DB).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 11:06:11 +00:00
Gergo Magyar
b85c801433 feat(impact): real-code perf/quality probe for pdg impact mode
Add bench/impact-pdg/real-code.mjs: a latency + quality-proxy probe that
runs both impact engines against an already-indexed real repo (default
GitNexus) and checks that unified mode:'pdg' preserves the callgraph
inter-procedural symbol set, what it costs, and how honest its PDG
evidence/degraded signals are. Unlike measure.mjs (the AIS-backed fixture
accuracy gate), a real repo has no curated ground truth, so this reports
quality proxies, not accuracy.

Each default case is anchored on a CFG block-start line so every case
exercises a real intra-procedural slice; a mid-block anchor degrades to
pdg-no-block-at-line, which the harness still detects and counts.

Measured on the live GitNexus index (PDG layer via analyze --pdg, ~171k
BasicBlocks): unified pdg reproduces callgraph symbol reach exactly
(recall = precision = 1.0 on all cases), ~1.2-1.4x latency overhead, and
downstream statement-anchored seeds correctly label out-of-slice reach
unproven-bridge (an expected proven-vs-reachable signal, not a regression).

Adds a deterministic helper unit test (pure metric math, no analyze/DB) and
README docs covering the probe, its gates, and a representative run.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 10:44:30 +00:00
Gergo Magyar
d9d702dc4d feat(impact): label pdg bridge evidence 2026-06-18 10:14:04 +00:00
Gergo Magyar
a9fd55a91b feat(impact): unify pdg symbol reach 2026-06-18 08:52:08 +00:00
Gergő Magyar
0271da39e3
Merge branch 'main' into feat/pdg-impact-mode 2026-06-18 08:36:04 +01:00
Gergo Magyar
4c84ec57c9 feat(impact): add unified accuracy axes 2026-06-18 07:31:26 +00:00
dependabot[bot]
868a83d7f9
chore(deps)(deps): bump dompurify (#2245)
Bumps the npm_and_yarn group with 1 update in the /gitnexus-web directory: [dompurify](https://github.com/cure53/DOMPurify).


Updates `dompurify` from 3.4.8 to 3.4.11
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.4.8...3.4.11)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-version: 3.4.11
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
2026-06-18 07:35:44 +01:00
Gergo Magyar
84612056cc fix(impact): harden PDG review findings 2026-06-18 06:18:26 +00:00
dependabot[bot]
4691e47bb5
chore(deps)(deps): bump mnemonist from 0.39.8 to 0.40.4 in /gitnexus-web (#2237)
Bumps [mnemonist](https://github.com/yomguithereal/mnemonist) from 0.39.8 to 0.40.4.
- [Release notes](https://github.com/yomguithereal/mnemonist/releases)
- [Changelog](https://github.com/Yomguithereal/mnemonist/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yomguithereal/mnemonist/compare/0.39.8...0.40.4)

---
updated-dependencies:
- dependency-name: mnemonist
  dependency-version: 0.40.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
2026-06-18 07:16:23 +01:00
Gergő Magyar
50586aa058
Merge branch 'main' into feat/pdg-impact-mode 2026-06-18 06:45:02 +01:00
dependabot[bot]
ecfedb3ef3
chore(deps)(deps): bump lucide-react in /gitnexus-web (#2238)
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 1.16.0 to 1.17.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/1.17.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-version: 1.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
2026-06-18 06:42:31 +01:00
dependabot[bot]
e5baffcd2c
chore(deps)(deps): bump @langchain/langgraph in /gitnexus-web (#2235)
Bumps [@langchain/langgraph](https://github.com/langchain-ai/langgraphjs/tree/HEAD/libs/langgraph-core) from 1.3.2 to 1.4.1.
- [Release notes](https://github.com/langchain-ai/langgraphjs/releases)
- [Changelog](https://github.com/langchain-ai/langgraphjs/blob/main/libs/langgraph-core/CHANGELOG.md)
- [Commits](https://github.com/langchain-ai/langgraphjs/commits/@langchain/langgraph@1.4.1/libs/langgraph-core)

---
updated-dependencies:
- dependency-name: "@langchain/langgraph"
  dependency-version: 1.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-18 06:41:39 +01:00
Gergo Magyar
99ae83103c fix(impact): harden PDG impact mode 2026-06-18 05:21:15 +00:00
Gergő Magyar
2ed8b83139
Merge branch 'main' into feat/pdg-impact-mode 2026-06-18 06:13:32 +01:00
dependabot[bot]
aee73aadaa
chore(deps): bump aiohttp in /eval in the uv group across 1 directory (#2224)
---
updated-dependencies:
- dependency-name: aiohttp
  dependency-version: 3.14.1
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-18 06:00:01 +01:00
Gergő Magyar
246ff5d7be
Merge branch 'main' into feat/pdg-impact-mode 2026-06-18 05:59:30 +01:00
dependabot[bot]
c899814393
chore(deps)(deps): bump react-dom from 19.2.6 to 19.2.7 in /gitnexus-web (#2240)
Bumps [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom) from 19.2.6 to 19.2.7.
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/react/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v19.2.7/packages/react-dom)

---
updated-dependencies:
- dependency-name: react-dom
  dependency-version: 19.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-18 05:59:01 +01:00
dependabot[bot]
9898acc5ba
chore(deps)(deps): bump @langchain/ollama in /gitnexus-web (#2236)
Bumps [@langchain/ollama](https://github.com/langchain-ai/langchainjs) from 1.2.6 to 1.2.7.
- [Release notes](https://github.com/langchain-ai/langchainjs/releases)
- [Commits](https://github.com/langchain-ai/langchainjs/compare/@langchain/ollama@1.2.6...langchain@1.2.7)

---
updated-dependencies:
- dependency-name: "@langchain/ollama"
  dependency-version: 1.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-18 05:57:57 +01:00
dependabot[bot]
542f54f616
chore(deps): bump gitleaks/gitleaks-action from 2.3.9 to 3.0.0 (#2241)
Bumps [gitleaks/gitleaks-action](https://github.com/gitleaks/gitleaks-action) from 2.3.9 to 3.0.0.
- [Release notes](https://github.com/gitleaks/gitleaks-action/releases)
- [Commits](ff98106e4c...e0c47f4f8b)

---
updated-dependencies:
- dependency-name: gitleaks/gitleaks-action
  dependency-version: 3.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-18 05:57:39 +01:00
dependabot[bot]
21315f02c9
chore(deps): bump github/codeql-action from 4.36.0 to 4.36.2 (#2242)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.36.0 to 4.36.2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](7211b7c807...8aad20d150)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.36.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-18 05:57:15 +01:00
dependabot[bot]
4d9318e2ee
chore(deps)(deps): bump hono from 4.12.23 to 4.12.26 in /gitnexus (#2244)
Bumps [hono](https://github.com/honojs/hono) from 4.12.23 to 4.12.26.
- [Release notes](https://github.com/honojs/hono/releases)
- [Commits](https://github.com/honojs/hono/compare/v4.12.23...v4.12.26)

---
updated-dependencies:
- dependency-name: hono
  dependency-version: 4.12.26
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-18 05:56:59 +01:00
Parafee41
e33f908775
ci: keep tree-sitter readiness summary counts current (#2196) 2026-06-18 05:14:44 +01:00
Parafee41
78e5ff3b9b
fix(wiki): keep graph DB pinned during generation (#2232) 2026-06-17 21:52:31 +01:00
Gergő Magyar
6c828ac6a4
Merge branch 'main' into feat/pdg-impact-mode 2026-06-17 07:43:01 +01:00
azizur100389
72876ab69a
fix(cpp): rank homogeneous braced-init overloads (#2214)
Some checks failed
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Gitleaks / gitleaks (push) Has been cancelled
Publish / Classify release event (push) Has been cancelled
Scorecard / Scorecard analysis (push) Has been cancelled
Trivy Image Scan / Trivy (gitnexus-cli) (push) Has been cancelled
Trivy Image Scan / Trivy (gitnexus-web) (push) Has been cancelled
Publish / RC guard (marker + release-PR skip) (push) Has been cancelled
Publish / ci (push) Has been cancelled
Publish / Publish to npm (push) Has been cancelled
Publish / Build & Push RC Docker images (push) Has been cancelled
2026-06-16 18:29:28 +01:00
Gergo Magyar
cb21e4737a test(impact-pdg): statement-line scoring — real measurement, real verdict
Rework the harness to seed PDG on criterion.line and score at LINE
granularity vs intra_AIS (callgraph stays symbol vs inter_AIS). The
measurement is now real and non-empty:

  intra  pdg  line/intra  P=R=F1=1.000  (6 fixtures, FPIS=FNIS=0)
  mixed  pdg  line/intra  P=R=F1=1.000  (3)
  inter  cg   symbol/inter P=R=F1=1.000 (3)
  mixed  cg   symbol/inter P=R=F1=1.000 (3)

Verdict: PDG mode is exact at intra-procedural STATEMENT granularity
(which statements depend on a change); callgraph is exact at inter-
procedural SYMBOL granularity (what calls/uses a symbol). Different
questions, neither dominates, they compose. The old 'PDG empty /
callgraph wins' verdict was a whole-symbol-seed artifact.

Adds criterion.line to each fixture (source-semantics first). 6 fixtures'
intra_AIS reconciled to block granularity (CFG coalesces consecutive
stmts into one block; combined CDG+RD slice reaches more) — documented
per-rationale + as the #1 validity threat (annotation circularity).
inter/pdg P=0 is honest: a dispatcher's intra routing-returns aren't the
cross-function impact. --check exit 0; 105 tests green.
2026-06-16 10:51:45 +00:00
Gergo Magyar
e12abbd56f feat(impact): statement-anchored PDG slice (line param) — the useful mode
The whole-symbol pdg seed was structurally empty: seeding a function's
entire blocks and excluding seeds leaves nothing (intra-procedural reach
stays inside the function). Add a 'line' statement anchor: impact({mode:
'pdg', line:N}) seeds the dependence BFS on the BasicBlock at 1-based
source line N within the symbol and returns the dependent STATEMENTS
(affectedStatements: {line,filePath,text}[], affectedStatementCount,
criterionLine). Verified: impact --mode pdg total --line 8 on the
accumulator returns lines [10,12] = the ground-truth slice.

- blockAnchorForStatement (a.startLine = line, no +1 — block lines are
  1-based and match source; bounded to the symbol span).
- pdgStatementsForBlocks resolves reachable blocks to source statements.
- line validated: PDG-only, positive integer; rejected on callgraph.
- Whole-symbol pdg keeps an honest empty note steering to line:<N>.
- tools.ts schema + CLI --line + eval-server statement render.

Refs: redesign after the harness/maintainer caught that symbol-level
pdg impact is empty in v1.
2026-06-16 10:51:45 +00:00
Gergő Magyar
fe87408e06
Merge branch 'main' into feat/pdg-impact-mode 2026-06-16 11:09:31 +01:00
Gergő Magyar
b895a20415
perf(lbug): overlap node COPY with relationship emit (#2203) (#2226)
* test(lbug): lock PARALLEL=false as a tested correctness invariant (#2203)

The parallel CSV reader (Kuzu-derived, default PARALLEL=true) cannot parse
quoted fields with embedded newlines (kuzudb/kuzu#5778); our content/text
columns hold source code, so PARALLEL=false is mandatory for correctness.
Add a live-DB multiline-quoted round-trip that fails if it is ever flipped,
plus a static guard on the generated COPY queries. Export COPY_CSV_OPTS /
getCopyQuery for the static assertion; document the invariant at the source.

* feat(lbug): expose node/rel phase boundary via onNodePhaseComplete hook (#2203)

streamAllCSVsToDisk now fires an optional onNodePhaseComplete(nodeFiles)
callback right after node CSVs are flushed and before the relationship pass
writes any rel_*.csv — the boundary the COPY-overlap leg needs. The node-file
manifest construction is hoisted above the rel pass and reused in the return,
so output is byte-for-byte identical when no callback is supplied (verified by
the emit bench fingerprint and the splitRelCsvByLabelPair differential oracle).
The callback is not awaited, so the rel pass runs concurrently with the
caller's node COPY.

* perf(lbug): overlap node COPY with relationship emit (#2203)

The deferred parallelism leg of #2203. LadybugDB is single-writer and its
parallel CSV reader is unsafe for our multiline content (kuzudb/kuzu#5778), so
the only safe parallelism is pipeline-overlap: node COPY (uses conn, never the
rel files) runs concurrently with the relationship emit pass (writes rel_*.csv,
never conn). Node COPY now starts at streamAllCSVsToDisk's onNodePhaseComplete
boundary while the rel pass keeps writing; the relationship COPY still waits for
node COPY (FK precondition), so DB load order and content are unchanged.

- Extract copyNodeCSVs; start it in the hook (overlap) or after emit (serial).
- GITNEXUS_SERIAL_LBUG_LOAD=1 forces the legacy strictly-sequential path
  (operator escape hatch + differential-test oracle).
- Settle the in-flight node-COPY promise on emit failure (no unhandled
  rejection); rethrow node-COPY errors at the FK barrier.
- Preserve the PDG manifest merge + collision guards (node merge at the hook,
  rel merge before rel COPY) and all retry/fallback/cleanup behavior.
- PROF_LBUG_LOAD gains mode=overlap|serial; copy-nodes becomes the residual
  node-COPY time after emit (trends to 0 as overlap hides it).

* test(lbug): differential gate — overlap load === serial load (#2203)

Loads one fixture (multiple node tables, multiple edge pairs, multiline File
content + BasicBlock text) into two fresh DBs — once via the default node-COPY
‖ rel-emit overlap, once via GITNEXUS_SERIAL_LBUG_LOAD=1 — and asserts the two
databases are content-equivalent: identical per-table node counts, per-type
edge counts, byte-for-byte multiline content/text, and identical
insertedRels/skippedRels/warnings. This is the issue's byte-identical-content
acceptance gate for the parallelism leg.

* fix(review): apply autofix feedback

- csv-generator: onNodePhaseComplete doc-contract now matches reality (a sync
  throw is allowed and is how loadGraphToLbug surfaces the manifest collision
  guard) — drops the inaccurate 'must not throw synchronously' line.
- lbug-adapter: copyNodeCSVs totalSteps is the node-table count (drop the +1
  rel-step holdover; the rel COPY has its own progress line).
- lbug-adapter: on emit+node-COPY double-failure, log the swallowed node-COPY
  error before rethrowing the emit error (diagnosability).
- lbug-load-prof test: assert mode=overlap on the default path.

* fix(test): use mkdtemp for secure temp dirs (CodeQL js/insecure-temporary-file)

CodeQL flagged lbug-load-overlap.test.ts writing a file into a predictable
os.tmpdir() path. Create the base temp dir with fs.mkdtemp (atomic, random
suffix) in both new live-DB tests, and switch to the gitnexus-lbug- prefix that
TEST_FIXTURE_PREFIXES recognizes so the Windows stale-sidecar sweep covers
these fixtures.

* fix(lbug): check PDG manifest rel-pair collision before node COPY (#2203)

Found by Codex in tri-review. The manifest rel-pair collision guard ran after
the FK barrier (after node COPY committed), so on that should-never-happen
error branch the overlap path left orphan node rows AND the
GITNEXUS_SERIAL_LBUG_LOAD escape hatch diverged from the legacy 'validate
manifest before any COPY' behavior. Move the rel merge + collision check ahead
of beginNodeCopy/the barrier: the serial path now detects a collision before
committing any node rows (legacy parity restored — the escape hatch is a
faithful oracle again), and the overlap path detects it as early as csvResult
is available. The node-collision guard already ran before node COPY (in the
hook).

* test(lbug): cover rel-emit failure with node COPY in flight (#2203)

Resolves a P1 review gap on PR #2226: the overlap's catch(emitErr) branch
(settle the in-flight node-COPY promise, then rethrow the emit error) was
untested. Fault-injects via a vi.mock of streamAllCSVsToDisk that fires
onNodePhaseComplete (starting a real node COPY on a live DB) then throws,
asserting loadGraphToLbug rejects with the emit error and no unhandled
rejection leaks. Also covers the both-fail case (node COPY error is logged,
emit error still wins). Listener removed in finally; macrotask queue flushed
before the assertion so it can't pass vacuously.

* test(lbug): cover node-COPY hard-failure rethrow at the FK barrier (#2203)

Resolves the second P1 review gap on PR #2226. Mocks emit to fire
onNodePhaseComplete with a nodeFiles entry pointing at a missing CSV (a
bind-time COPY error that IGNORE_ERRORS does not suppress) and otherwise
succeed, so copyNodeCSVs throws, the error is captured in nodeCopyError, and
loadGraphToLbug rethrows it at the FK barrier — asserted via rejects /COPY
failed for File/.

* test(lbug): cover PDG manifest rel-pair collision in overlap + serial (#2203)

Resolves the P2 gap behind the Codex tri-review finding: the manifest rel-pair
collision guard (moved ahead of node COPY in ad195582) had no test. A leaky
graph with a structural BasicBlock->BasicBlock edge (routed by id-prefix, no
BasicBlock nodes — isolating the rel-pair clash from the node-CSV one) plus a
PdgEmitSink manifest declaring the same pair makes loadGraphToLbug reject with
the rel-pair collision error, asserted on both the overlap (default) and serial
(GITNEXUS_SERIAL_LBUG_LOAD=1) paths.

* perf(lbug): yield the event loop periodically during relationship emit (#2203)

Resolves a P2 review finding on PR #2226: the relationship-emit loop ran long
synchronous stretches between write-stream drain awaits, which could starve the
overlapped node-COPY callbacks on fast I/O and erode the node-COPY-||-rel-emit
overlap. Yield via setImmediate every REL_YIELD_EVERY (5000) edges so the node
COPY and drains get scheduling time. Scheduling-only — emit bench fingerprint
unchanged (byte-identical), csv-pipeline determinism + overlap differential
green.

* refactor(lbug): extract shared copyCsvWithRetry helper (#2203)

Resolves a P2 maintainability finding on PR #2226: the COPY + IGNORE_ERRORS
retry block was duplicated in copyNodeCSVs and the inline relationship-COPY
loop. Extract copyCsvWithRetry(conn, query, onError); the callback receives the
RAW retry error so each site keeps its own message shape + slice length (node
throws, slices 200; relationship warns + records the failed pair, slices 80).
Behavior-preserving — guarded by the live-DB round-trips plus the new
node-COPY-failure and overlap error-path tests.

* docs(lbug): document loadGraphToLbug non-transactionality (#2203)

Resolves the advisory review finding on PR #2226: loadGraphToLbug runs
independent COPYs with no surrounding transaction, so a mid-load failure leaves
a partial DB and recovery is a --force re-analyze. Make that contract explicit
on the function so callers don't assume atomicity.
2026-06-16 10:57:26 +01:00
Gergo Magyar
bcbc055845 fix(review): apply autofix feedback
Code-review fixes for the PDG impact mode:
- P1: _runImpactPDG re-resolved its seed by bare name, dropping the
  file_path/target_uid/kind disambiguation the dispatch already applied
  (wrong-symbol blast radius for ambiguous names). Anchor the seed from
  the resolved sym via new blockAnchorForResolvedSymbol (no re-resolve);
  resolveBlockAnchor untouched. +test (same-name funcs, file_path/uid).
- Degraded/no-body/no-dependence returns now share emptyPdgParityFields
  (KTD8 shape parity for programmatic consumers).
- Drop dead offset/summaryOnly params; delete stale stub JSDoc.
- pdgLayerStatus unknown-probe wrapped in try/catch + uses its result.
- projectBlocksToSymbols no longer swallows DB errors as no-match.
- Seed-query truncation now sets truncated/truncatedBy:'limit'.
- Harness: try/finally cleans the work temp dir on callTool throw.
- Tests: pin REACHING_DEF exclusion, CDG controller-P precision guard,
  Windows drive-colon path projection.
2026-06-16 09:37:35 +00:00
Gergo Magyar
620e9e008a style(impact-pdg): prettier formatting + drop unused import
Root prettier --write across the feature's changed files (whitespace
only; ground-truth.json values and the data-based annotation fingerprint
unchanged — --check still PASS). Remove an unused loadMeta import flagged
by eslint (unused-imports/no-unused-imports).
2026-06-16 09:11:03 +00:00
Gergo Magyar
306f0ee071 feat(impact-pdg): accuracy measurement harness (U7)
measure.mjs drives both impact modes over the U6 corpus via a mock-free
real-analyze substrate (temp GITNEXUS_HOME + child-process analyze
--pdg + LocalBackend), validates fixtures in Step 0 (>=1 PDG edge + R4
same-line guard), and computes per-mode/per-scope precision/recall/F1 +
Jaccard + true/noise set-diffs (Arnold-Bohner CIS/AIS). Two-gate --check
(one-sided F1 band + annotation fingerprint, median-of-K for substrate
noise). Pure scorer in metrics.mjs; 18 synthetic-set metric-math unit
tests stay out of the flaky pipeline lane.

Key measured finding (the deliverable verdict): at SYMBOL granularity
PDG mode's intra blast radius is empty (intra-procedural dependence
collapses onto the criterion's own symbol), so callgraph wins for
symbol-level impact; PDG v1's value is block-level dependence detail.
Promotion gated on a deferred Function->BasicBlock CONTAINS_BLOCK edge.

Refs U7
2026-06-16 09:08:10 +00:00
Gergo Magyar
6e6c300d48 test(impact-pdg): curated ground-truth fixture corpus (U6)
13-case corpus (12 measurable: intra=6/inter=3/mixed=3, + 1 excluded
no-body) under bench/impact-pdg/fixtures. Each case: tiny TS source +
ground-truth.json {criterion, intra_AIS, inter_AIS, locus, provenance,
analyzerVersion, rationale}. Annotated from SOURCE SEMANTICS only
(KTD9 annotation-circularity guard — U7 reconciles vs the traversal).
Symbol/line granularity, not block-id. Schema+smoke test asserts each
measurable criterion emits its declared PDG edges (catches accidental
zero-edge/no-body criteria).

Refs U6
2026-06-16 08:41:19 +00:00