Commit graph

290 commits

Author SHA1 Message Date
dependabot[bot]
03dc0f1743
chore(deps): bump actions/setup-python from 7.0.0 to 7.1.0
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 7.0.0 to 7.1.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](5fda3b95a4...6d4fd22b20)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: 7.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-28 20:32:59 +00:00
Neutron
c2d9012b58
fix(lbug): guard read queries against runaway native memory (#3696) (#3749)
Some checks are pending
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Gitleaks / gitleaks (push) Waiting to run
Publish / Classify release event (push) Waiting to run
Publish / RC guard (marker + release-PR skip) (push) Blocked by required conditions
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-cli) (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-web) (push) Waiting to run
* fix(lbug): guard read queries against runaway native memory (#3696)

A single impact query was reported to allocate ~184 GB of native heap on a
66k-symbol index. That memory is outside the buffer pool and V8, so neither
bufferManagerSize nor --max-old-space-size bounds it, and the Node binding
cannot interrupt a running query.

- Add a process-wide memory guard around every pooled read query. While a
  query runs it samples RSS every 200 ms and, on macOS, the physical
  footprint for queries running over 1 s (RSS excludes compressed and
  swapped pages there). Past the budget it names the running queries on
  stderr and exits with code 70 instead of letting the host run out of
  memory. GITNEXUS_QUERY_MAX_RSS_MB sets the limit (0 disables); the
  default is max(8 GiB, 25% of RAM).
- Add GITNEXUS_QUERY_TRACE=1: one stderr line per query with duration,
  rows and memory, so a reporter can identify the query that blows up.
- Cap the impact BFS frontier query at 100k rows per depth level. A capped
  level stops the walk, marks the result partial, and cannot report a
  LOW/MEDIUM risk.

* fix(ci): initialize shards after fork approval

GitHub approval increments the attempt number without running any jobs. Allow initial timing snapshot creation on attempt 2 only when the first attempt required approval and had zero jobs. Keep real retries fail-closed on missing frozen input.

* fix(impact): qualify both capped risk scores

Apply the same conservative cap policy to risk and riskSharedAxes, retain proven high warnings, and strengthen frontier-limit regression assertions. Correct the memory-budget test description.

* fix: skip query phases after deadline

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
2026-10-28 14:08:17 +00:00
Gergő Magyar
13d06d41c4
feat(ci): rebalance test shards from recorded timings (#3748)
* feat(ci): rebalance test shards from recorded timings

* fix(ci): preserve artifact retries for shard timings

Find shard-plan generation by its stable step ID and clarify the native runner cohort count (#3748).

Note: pre-existing reference-oracle parser type failures in two test_oracle_assets cases remain outside this change.

* fix(ci): keep retry timing snapshots immutable

Require the existing snapshot on reruns so a failed download cannot refresh history and change shard assignments. Cover the workflow contract and document recovery when the artifact is unavailable.

* docs(ci): document shard timing profile selection

* fix(ci): balance cold shard estimates consistently

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
2026-10-28 11:58:29 +00:00
Gergő Magyar
bad2422aa1
feat: add the test scenario map and a Vitest 5 mutation runner (#3686)
* feat(ci): add advisory duplicate-test scan to the PR report

Adds `npm run test:dupes` (gitnexus/scripts/test-dupes.ts) and a
comment-only CI job that reports, for the lines a PR changes:

- same-test: same body and same setup as an existing test
- assertions-pinned: every assertion is a literal fn(...) -> matcher
  that another test already makes
- same-fixture-setup: a before* hook builds a fixture another describe
  already builds
- copied-helper: a top-level test helper identical to one elsewhere
- orphan-bench-gate: a bench script with --check that nothing runs

A case's identity includes its hooks, describe-level statements,
wrapper arguments, loop heads, each tables, referenced file-local
declarations and resolved imports, with fixture paths compared by
value. Extra context can only split a group, so identical bodies that
run against different fixtures, mocks or env are not reported.

The ci.yml job is continue-on-error and outside the CI Gate.
ci-report.yml renders its JSON into the sticky CI comment, keeping
only whitelisted kinds and strict path/line shapes because the
artifact comes from PR code. `// dupe-ok: <reason>` silences an
intentional repeat.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(mutation): record Vitest 5 and Stryker 10 probe findings

Go/no-go probe for the Stryker Vitest 5 runner: name-filter separator, per-spec task ids, static mutant activation, TypeScript plugin loading in child processes, setup-file meta and hook ordering.

* feat(mutation): prepare a mutable copy and a Vitest mutation config

Prepared copy blanks TypeScript as-assertions (Stryker's instrumenter skips every TSAsExpression) with equal-length spaces, checked by AST equality, and relocates gitnexus-shared/src inside the package so it can be mutated. The mutation Vitest config resolves gitnexus-shared to the relocated sources and takes its test list from a scope file.

* feat(mutation): add a Stryker test runner for Vitest 5

Stryker's vitest-runner 10.0.0 runs zero tests per mutant under Vitest 5 because Vitest 5 matches testNamePattern against ' > '-joined names. This runner selects tests by Vitest task id per file, keeps the configured fork pool, shares the dry-run manifest across Stryker worker processes, attributes hook-time hits to the suite's tests, and records a per-test outcome class in sidecar files. Adds exact devDependencies @stryker-mutator/core and @stryker-mutator/api 10.0.0.

* feat(mutation): add global mutant identities and a span-map check

A global mutant identity (original repo path, original content hash, span, mutator, replacement) makes mutants comparable across Stryker runs. The span-map check proves every mutant of a prepared copy sits on the same span and text in the original source, apart from blanked as-assertions.

* feat(mutation): add a scope driver for Stryker runs

run-scope turns a scope file into a prepared copy, a generated Stryker config (vitest5 or command runner), a Stryker run and normalised results: global mutant ids, runner test ids, sidecar outcome classes, consistency flags and the span-map check.

* fix(mutation): count assertion kills only for killed runs

A run classified timeout, inconclusive, invalid or infrastructure can still carry assertion rows (a test failing after a swallowed hit-limit error, or under a retry). Those kills are not trustworthy, so assertionKilledBy is now empty unless the run's status is killed. Found by the conformance suite.

* feat(mutation): add the runner conformance suite (gate 2)

A fixture project under test/fixtures/mutation-conformance pins 23 runner behaviours (static and collection-time mutants, beforeAll attribution, disableBail, it.each row ids, outcome classes for runtime, hook, collection, timeout, infrastructure, retry and zero-test runs, NoCoverage, environment isolation, runner reuse and manifest sharing) in two scheduling profiles. The path map and scope driver accept an explicit gitnexus/test/fixtures/mutation-* root for it.

* feat(mutation): classify pure-JS unit tests for mutation runs

Walks each unit test's import closure (static imports plus statically resolvable dynamic imports, require and createRequire) and rejects tests that reach native packages, worker threads or child processes, read source or fixture files a prepared copy would break, or contain unresolvable dynamic imports. 247 of 911 unit test files are pure JS.

* feat(mutation): add gate 1 execution-path fidelity and the envelope record

Gate 1 compares a normal Vitest 5 run of the pure-JS category with the runner's unmutated Stryker run: test identities with locations, outcomes, effective config against an allowed-difference list, resolved module paths (everything inside the active sandbox) and a runtime load check for native bindings, worker construction and child processes. It passes on 246 files / 4541 tests and writes test/fixtures/mutation-oracle/envelope.json. The runtime check found commander loading child_process, so the classifier now rejects tests importing commander.

* feat(mutation): add the oracle's command-runner run and classifier

The Vitest 5 cross-check oracle runs its own Stryker run with the command runner (cleanTempDir false). A wrapper runs the scope's tests per mutant with an oracle reporter and writes a per-mutant record, and the oracle classifies every mutant into the KTD17 outcome classes with its own classifier. Oracle code imports no runner code.

* feat(mutation): add the oracle single-test launcher and cost benchmark

launch-single runs one test with one mutant in a fresh process inside the oracle's kept sandbox, selected by file:line plus an anchored name pattern, with the mutant installed before any import, an oracle setup file that proves the installed id and buckets hits (load and collection, hook, per-test), a wall-clock limit and a process-group kill. A launch is valid only when exactly the intended test ran. The benchmark projects the three-scope oracle sample's cost on 4 vCPU. A boundary test keeps oracle code from importing runner code.

* feat(mutation): add the oracle freeze and gate 3 compare

freeze samples mutants per scope with a recorded seed, tops up strata, counts stratum populations from the oracle's own coverage probe, launches every sampled mutant against every scope test (resumable), and writes a manifest keyed by content hashes of the scope's import closure, Vitest configs and prepare tool. compare checks freshness, inventories (tests and global mutant ids) before outcomes, every mutant's class and sampled per-test outcomes, allowing only the four KTD13 normalisations.

* feat(mutation): add gate 4 positive controls and determinism

Nine planted controls, selected from the scopes' own Stryker mutants by global id (three in relocated gitnexus-shared as-const tables), must be killed by exactly their expected killers. Two scheduling profiles (concurrency 1 with unlimited runner reuse, concurrency 3 with one mutant per runner process) must give identical outcome classes and kill sets.

* ci(mutation): add an advisory mutation-runner validation workflow

Runs the runner conformance suite (gate 2) on pull requests that touch the mutation tooling, its fixtures, the gitnexus manifest, lockfile or Vitest config. workflow_dispatch also runs gate 1, the gate 3 oracle compare (or a per-scope re-freeze whose manifests are uploaded, never committed), gate 4 and the oracle cost benchmark. All jobs are advisory. Documents the tooling in TESTING.md and the residual deltas against upstream StrykerJS.

* test(mutation): freeze the gate 3 oracle manifests and record Phase 0 results

Frozen Vitest 5 cross-check oracle manifests for the three pure-JS scopes (seed u7-gate3-1): shared.ts, schema-constants.ts and middleware.ts. Gate 3 passes: all 1,606 mutant classes and all 20,455 sampled per-test outcomes agree with the runner, 0 differences. Adds the approved Test Scenario Map design (updated with Phase 0 findings and gate results) and the Phase 0 implementation plan.

* refactor(mutation): simplify the Phase 0 tooling

Shared CLI/fs helpers for the non-oracle tools, an oracle-local util for isObject and atomic writes, formatMutateEntry and formatDuration reused, a typed isUnusableClass, and hot-path fixes: per-sidecar index in the gate 3 compare, lazy suite-chain in the runner's dry-run hit attribution, one Classifier per freeze, memoised display paths and Vitest lookups. Behaviour unchanged: unit tests, gate 3 compare (byte-identical report) and the conformance suite (23/23) pass.

* fix(review): apply review findings

- Move the duplicate-test scanner out of the published scripts/ directory to gitnexus/tools/test-dupes/ so it no longer ships in the npm package.
- Scope the orphan bench gate to touched lines, like every other scanner finding.
- Let the conformance environment case reach Stryker through an explicit childEnv override, so it exercises the runner's own __STRYKER_ACTIVE_MUTANT__ deletion (a negative check now fails it).
- Do not raise the zero-tests flag when a timeout outside-test row explains the zero.
- Run Stryker in its own process group and signal the group on cancellation.
- Fingerprint conformance inputs and refuse stale artefacts in --compare-only.
- Path-gate the mutation workflow on gitnexus-shared/package.json and the setup action; anchor the PR-report path filter with \A...\z.

* chore(security): mark the runner's provide/inject key as a gitleaks false positive

gitleaks' generic-api-key rule matched PROTOCOL_KEY = 'gitnexusStrykerVitest5' (a Vitest provide/inject key name). Allow the line inline and ignore the fingerprint in the commit that introduced it.

* test(mutation): re-freeze the schema-constants oracle manifest

Merging main changed the scope's import closure (template-arguments.ts),
so gate 3 reported re-freeze required. Re-frozen with seed u7-gate3-2:
72 sampled mutants, 3024 valid observations, 0 invalid. Gate 3 now
passes on all three scopes (shared 1232, schema-constants 72,
middleware 302 mutants) with 0 differences.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(plans): add the Test Scenario Map Phase 1 plan

* chore(security): stop the gitleaks allowlist comment from quoting the key

The previous comment quoted the provide/inject key assignment and gitleaks
flagged the comment line itself (generic-api-key). Reword it and allowlist
that historical finding by fingerprint.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(mutation): select single tests in the vitest5 runner and keep per-test classes

Phase 1 U1 (KTD2, KTD9, KTD16):
- driver scope accepts optional testIds, passed as the vitest5.testIds
  runner option; the dry run collects, maps ids to task ids, runs only
  those tests and fails before any mutant run on unknown ids
- the dry-run sidecar (schema 2) carries the hook marker: per mutant,
  the tests a suite hook attributed it to
- results.json (schema 2) keeps every sidecar attempt's per-test rows
  (perTest), attemptsDisagree and hookAttributedTests
- gate 2 gains a selection scope and hook-marker cases (26 cases hold)

Gate 3 hashed inputs are untouched.

* refactor(test-dupes): export Layer 0's case extraction for the scenario map

Phase 1 U2 (KTD6): export extract, extractCases, buildFrame, closure,
staticValue, suppressed and dupeOkReason, plus a per-case record with
the describe path, title, context hash, body, each-table node and
enclosing loop head. Layer 0's --all scan output is byte-identical
before and after (1464 files, 114 findings).

* test(mutation): refresh the gate 1 envelope after the runner extensions

Gate 1 re-ran over the current pure-JS category after U1 and passed with
0 differences: 251 files, 4667 tests. The classifier now rejects
conformance-compare.test.ts (imports the child_process-spawning
conformance runner) and php-namespace-extraction.test.ts (now reaches
tree-sitter through main), and accepts the three oracle unit tests.

* feat(scenario-map): add the eligible-test inventory, identity join and anchors

Phase 1 U3 (R1, R2, R15; KTD3, KTD7):
- eligibility = gate 1 envelope intersect a fresh classifier run, with the
  delta; controls mode enrols a fixture's *.case.ts files
- static expansion of it.each/test.each/test.for tables and literal for-of
  loops into per-row instances; anything not statically evaluable is
  unresolved (fail closed)
- a pure join of static instances to runtime records through Phase 0
  test ids; any count or name mismatch makes the tests unsupported
- continuity anchors (no line; row and body fingerprints) and the one
  production-file predicate shared by every later stage
- test-dupes: additive exports (shapeOf, roleOf, eachTableOf, ASTs, an
  isTest option); Layer 0 output byte-identical

Over the repo: 4667 runtime tests, 4597 joined one-to-one, 70 unsupported
(5 tables built at runtime), 0 mismatches.

* test(scenario-map): add the controls fixture project with expected verdicts

Phase 1 U17: one pair per design §8 pure-JS adversarial case (Math.round,
parseInt radix, localeCompare, normalize, Date boundary, regex
alternatives, numeric boundary with a constants-only module, an
expected-only difference, a derived value reaching toFixed, an
enum-member-only difference), an order-dependent pair, an object-key row,
and positive controls (verbatim duplicate, repo arithmetic, Set table
reads). expected.json was written from the design's stated outcomes.
The fixture has its own Vitest project and tsconfig; no repo project
collects it.

* feat(scenario-map): extract per-instance checks and context

Phase 1 U5 (R5, KTD6):
- checks: the shape of each expect(...).matcher(...) with literals
  abstracted and selector literals in the subject kept exact; snapshots
  hashed from inline text or the .snap entry; a documented supported
  matcher list, anything else unsupported; per-row for it.each/test.for
- context: Layer 0's context hash plus body-level mocks/env writes and
  the test call's own modifiers and options
- checksContextKey for the second candidate source

Over the 251 eligible files: 4600 instances in 2.9 s, 183 with an
unsupported form, 37 with an unresolved selector.

* feat(scenario-map): add Layer 1 per-test V8 coverage and candidate retrieval

Phase 1 U4 (R3, R4; KTD4, KTD5):
- a Vitest setup file records per-test V8 block coverage in a prepared copy
  under the mutation config (gitnexus-shared runs from source), with design
  §5.2 attribution: module load discarded, a suite's beforeAll delta taken
  at its first beforeEach, concurrent tests flagged unattributable
- provenance per test: executed files, native-package entries and worker or
  child-process spawn call sites
- candidates: exact Jaccard >= 0.99 (size-ratio and prefix filters) plus
  identical checks-and-context buckets; connected components schedule
  Layer 3 only

Over the 251 eligible files: 4667 tests in 1:55 (82.8 s Vitest), 6281
candidate pairs in 611 groups, largest group 36 tests. Controls: 16/16
pairs are candidates, 0 cross-pair candidates. The directory is
path-coverage/ because coverage/ is ignored by git, prettier and eslint.

* feat(scenario-map): compute the per-instance input facet

Phase 1 U6 (R5, R9; KTD6), porting the input-facet spike without its
hard-coded inputs:
- rules 1-8: tree-sitter shapes of inline source, the COBOL profile,
  best-fit production tables (executed path, 2-hop import closure,
  property columns; never pooled), selector literals (reusing the checks
  predicate), object keys, source order, shared fixtures, fixture files
- numeric literals with 0/1/-1/negatives exact, and the +-1 rule against
  production numeric constants from executed files and the static import
  closure (folded initialisers included)
- discarded values per position with source locations for value flow
- the residual-difference guard: a body difference the facet misses makes
  the pair facet-unequal and both instances unresolved

Controls: all 16 pairs match expected.json. The spike's untouched
holdout-4 still scores 23/23 distinct. Eligible run: 4667 instances in
about 33 s, 245 unresolved.

* feat(scenario-map): run Layer 3 per candidate group and merge raw observations

Phase 1 U7 (R6, R7, R11; KTD7, KTD8, KTD14, KTD17):
- whole-file mutate scope per group from Layer 1 provenance and the
  static closure; executed-but-unmutated repo files mark tests excluded
- a run manifest of the prepared inputs that every shard verifies
- two plain Vitest 5 baselines (fresh instance per run) plus the Stryker
  dry run must agree; the generated config must carry perTest coverage,
  disableBail and static mutants before mutating
- raw observations from every sidecar attempt, keyed by group, run kind,
  lineage, attempt, test and mutant; class disagreement is inconclusive
  and a missing result is unknown, never a non-kill
- deterministic shard planning that never splits a group, with
  group-over-budget and start-only-if-it-fits rules

Controls: all 16 pairs ran as real groups; every kill set matches
expected.json.

* feat(scenario-map): add the full isolation pass for repeat-stage pairs

Phase 1 U8 (R7; KTD8, KTD9):
- select repeat-stage pairs (same coveredBy path, checks, context, facet
  without a residual difference, and the same non-empty kill set)
- per pair one together run and one alone run per test (shared across
  pairs), mutate restricted to the covered universe, a fresh runner
  process per mutant, all behind the same KTD8 baseline and config checks
  (runGroup's steps moved into runMutationRun)
- coverage and outcome class per test and mutant must agree across main,
  together and alone; a missing rerun result is unknown; hook-attributed
  mutants cap the pair at weak

Controls: order-dependent ends disagrees; verbatim-duplicate,
repo-arithmetic and set-non-member agree, matching expected.json.
Measured fresh-process cost: about 5.5 s per mutant.

* feat(scenario-map): add the row-deletion operator

Phase 1 U9 (R8, KTD10):
- find the one supported production table (object literal with plain
  keys, literal Set/Map) holding both differing values; spreads, computed
  keys, Object.assign, writes, getters, proxies, duplicate keys or an
  ambiguous table make the outcome inconclusive
- splice one key's text in a throwaway prepared copy, run the pair with a
  fresh Vitest instance per run after a control run that proves both pass
  and the edited file loaded
- symmetric / asymmetric (Row) / not applicable / inconclusive, with
  RowDeletion global mutant ids
- vitest-run: an opt-in load probe (probeFiles, loadedFiles)

Controls: all 16 pairs match expected.json (object-key-row and
set-membership asymmetric).

* feat(scenario-map): add the static value-flow check

Phase 1 U10 (R9, KTD11): for facet-equal pairs whose discarded values
differ, all sources must come back clean or the pair is vetoed to Review:
- Babel binds each differing value to its entry (call argument, fixture
  field, table key); an expected-only difference is unknown
- the TypeScript 7.0.2 unstable checker resolves entries and callees
  through aliases; a version mismatch degrades the whole run
- a walk stitched across functions over GitNexus PDG REACHING_DEF and
  CALL_SUMMARY edges (pdg_query flows are intra-procedural): opaque
  sinks (lib/@types/node_modules, any regex) veto, truncation, dynamic
  dispatch, a depth cap or a missing PDG layer are unknown or degraded;
  repo code is clean only inside the pair's mutated files
- row-deletion exports scanSupportedTables so table reads mean exactly
  the tables row deletion supports

Controls: 0 mismatches against expected.json. Whole-repo analyze --pdg:
6:49 wall, 8.4 GB peak RSS.

* feat(scenario-map): add the value-flow trace run

Phase 1 U11 (R9, KTD11): one traced Vitest 5 run over the tests of every
facet-equal candidate pair, with a setup file that wraps value-sensitive
built-ins (Math, string transforms and comparisons, RegExp, number
parsing and formatting, JSON, Intl, Date, sort, plus U10's opaque
callees) and records, per test and production call site, the receiver,
arguments and count. Storage and table reads stay unwrapped.
A shared site with a different receiver or argument, or asymmetric
sites or counts, vetoes the pair; a test whose outcome changes under
tracing makes it inconclusive.

Controls: all 13 pairs with a trace expectation match expected.json,
including receivers 24 and 25 reaching toFixed. Overhead on 40 eligible
files: 1.19x pooled, no outcome changes.

* feat(scenario-map): add the verdict engine

Phase 1 U12 (R10, R11, R15; KTD5, KTD8, KTD9, KTD12): a pure function
over merged observations and every stage's evidence. Design §2
precedence as an ordered rule list (Inconclusive, Out of scope, Weak,
Repeat strong, Repeat weak, Row, Review, Distinct), with the value-flow
and trace vetoes as a gate before any repeat category and the residual
difference ending in Review. One verdict per pair with its deciding rule
and every weak disqualifier; per-test Weak, Inconclusive and Subsumed;
per-file gaps recomputed from all observations with the §5.4 wording;
dupe-ok pairs kept with their evidence. Output is deterministic.

Controls: all 16 verdicts and rules match expected.json.

* feat(scenario-map): build the report, issue body and week-over-week diff

Phase 1 U13 (R12, R13; KTD13, KTD15):
- the JSON report: run provenance (the design §7 cache-key inputs),
  completeness and degraded flags, the eligibility delta, Layer 0
  findings, every verdict with its evidence, per-test properties, gaps,
  a seeded spot audit of 10 strong candidates, N of M evaluated and the
  precision-not-measured statement
- continuity: mutant fingerprints without revision or span, universe ids
  from the pair's common universe, evidence hashes per design §5.5
- a markdown rendering and the tracking-issue body (strong repeats, weak
  tests, gaps; truncated at 60,000 characters; a run-id marker so a
  stale run never overwrites a newer body)
- baseline comparison: new, changed, unchanged, resolved, with first-run
  and incompatible-baseline banners

* feat(scenario-map): add the CLI and the end-to-end controls run

Phase 1 U14 (R14, R16; KTD1, KTD14, KTD17): npm run test:scenario-map
with plan, shard, value-flow, merge, all and controls stages exchanging
JSON in a work directory, so CI jobs and a local run produce the same
report. Shards batch groups into one mutation run when their combined
estimate fits, and persist row-deletion and isolation results as they
finish. Exit codes are set explicitly.

controls: all 16 fixture pairs match expected.json (exit 0, 76 min).

* feat(scenario-map): fit the scheduled run into the CI budget

Phase 1 U14 follow-up (KTD14, KTD17), measured on a seeded slice of the
real category; no evidence rule is relaxed:
- value flow runs before the shards and re-plans them, so isolation is
  spent only on pairs that can still be strong (a value-flow veto or
  unknown ends Review, a trace inconclusive ends Inconclusive); a
  missing, stale or degraded value-flow result falls back to the
  provisional plan
- a shards stage prints the final shard count for the CI matrix
- --concurrency and --speed-factor feed the estimate; the main-run cost
  form is fixed + mutated bytes (measured; it does not grow with tests)
- a group whose isolation does not fit still runs its main run and row
  deletion; its pairs get isolation not-run (weak cap), and a shard
  isolates deferred pairs only when their measured universe fits
- groups that execute no production file are not run; their pairs are
  out of scope

Predicted CI run: 9 shards at concurrency 4, 1658-1829 min in total,
largest shard 196-253 min (budget 300), 0 groups over budget.
controls: 16/16 pairs match, 28 min.

* ci(scenario-map): add the weekly Test Scenario Map workflow and a PR controls job

Phase 1 U15 (R13, R14; KTD13, KTD14, KTD17):
- test-scenario-map.yml (weekly + dispatch, advisory): plan, value-flow,
  shards (sizes the matrix from the value-flow re-plan), a shard matrix
  (fail-fast off, max-parallel 10, 300-minute deadline), merge (always,
  against the newest scenario-map-baseline artifact) and upsert-issue
  (default branch only; the only job with issues: write; replaces the
  tracking issue's body only for a complete run that is not older than
  the body's run marker, comments on partial runs, never closes it)
- mutation-runner-validation.yml: a path-gated scenario-map-controls job
  that runs the controls fixture end to end on PRs touching the tooling

actionlint (with shellcheck), zizmor 1.24.1 and the concurrency check
pass. Neither workflow can run before the merge.

* docs(scenario-map): record Phase 1 in the design and the testing guide

Phase 1 U16: design corrections (the stitched PDG walk, the trace's
receivers and scope, row deletion and baselines on plain Vitest 5, the
isolation pass on testIds after value flow), the demote-only additions,
the refreshed gates, the measured Phase 1 costs and the CI topology
change; TESTING.md gains a Test Scenario Map section (stages, controls
fixture, supported matchers, wrapped built-ins, weekly workflow,
dupe-ok).

* fix(scenario-map): store observations compactly so large batches fit in memory

The first full run crashed a shard with "Invalid string length":
observations were materialised for every collected test x every mutant,
including a valid not-covered survival for each pair (1.6M objects for a
batch of 73 selected tests over 21,965 mutants; the batch file needed
about 700 MB of JSON).

- only a run's selected tests produce observations
- each run records its universe (selected tests, mutants with their
  status, reasons and hook marker); only rows, covered or static
  mutants without a row, and hook-named tests are stored explicitly; a
  not-covered survival is derived when read
- every consumer (pair comparison, isolation, verdict engine, report,
  batch split) reads through one index; group observation and isolation
  run files move to schema 2, and old files are rejected with a message
- merge lists an unreadable group result as incomplete instead of
  dropping it; repeat-stage decisions keep comparison summaries only

On the crashing batch: 141,308 explicit observations instead of 1.6M,
12.1 MB instead of an overflow, and a byte-identical verdict report.
controls: 16/16 pairs match.

* docs(scenario-map): record the Phase 1 measured slice; give the real-repo classify test headroom

- design §9: the full-category report comes from the first weekly
  workflow run; the local full run was stopped because it saturated the
  shared machine. Records the measured slice and the whole-category plan
  and value-flow figures.
- classify.test.ts: classify the real repo once in beforeAll with a
  120 s timeout; it takes about 30 s on a busy host and timed out at
  the default 30 s.

* fix(review): apply review findings and simplify the scenario-map tool

Review (ce-code-review, validated findings):
- trace: a baseline or traced run that is invalid, inconclusive, retried
  or has outside-test failures, unhandled errors, unwrapped entries or
  recorder errors makes every pair inconclusive (trace-run-invalid), never
  clean; the value-flow stage reports it and merge marks the run partial
- verdict: tests pin that a not-required static check for differing
  values reads as unknown, plus the worker-spawn, missing-provenance,
  unresolved-input and unknown-hook-marker weak caps
- workflow: the baseline comes only from this workflow's own scheduled or
  dispatched default-branch runs of this repository; an unreadable
  baseline shows the incompatible-baseline banner instead of failing merge
- controls: the oracle fails on an empty expected list, on any unlisted
  repeat verdict and on a case file without an expected pair
- value flow: the PDG analyze budget (25 min) sits below the 50-minute
  CI step; the TypeScript checker server is closed when opening fails
- --concurrency now also bounds every in-process Vitest run (maxWorkers),
  so local runs stay within the requested cores
- merge reads isolation runs tolerantly (an unreadable file makes the run
  partial); a duplicate test title is renamed; a stale TESTING.md heading
  reference is updated

Simplification (behavior-preserving; merge and plan outputs byte-identical
on fixed inputs): one util.ts for shared helpers, a run-level row-deletion
cache, one classify() per plan, memoised universe ids and single-pass
pair/subsumption/report loops.

* fix(test-dupes): keep beforeAll and beforeEach fixture builds apart

A same-fixture-setup key now includes the hook name. A beforeAll fixture is
built once per suite and a beforeEach one per test, so sharing one result
between them would drop per-test isolation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci(scenario-map): temporary label-gated pull_request run for PR #3686

schedule and workflow_dispatch only run from the default branch, so the
Test Scenario Map workflow cannot run before this PR merges. Adding the
run-ci label to the PR starts one full run. A pull_request run writes no
tracking issue and no baseline. Remove the trigger before merge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci(scenario-map): remove the temporary pull_request trigger

The one full run on PR #3686 finished (run 40183982111, complete, 9 of 9
shards). This reverts 5d06d731c.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(scenario-map): decide pairs past unknown mutants on a kill witness

A mutant both tests ran cleanly, killed by assertion by exactly one, proves
the kill sets differ whatever the unknown and runtime-class mutants hold.
kills-unknown and non-assertion-outcome now leave such a pair Inconclusive
no longer; it goes on to Row or Distinct. A pair's empty kill set only
decides Weak on a fully known run. Verdict engine 2.

Re-merged from the artifacts of run 40183982111: Inconclusive 4532 -> 1469;
every pair engine 1 decided keeps its verdict, rule and details, and the
repeat candidates are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(scenario-map): record a test file's import failure instead of a missing result

A static mutant that breaks a module at import makes its test files fail to
collect: the runner writes one file-level killed-outside-test:collection row
and no per-test rows, so every test of the file was a missing result. Those
were every missing-result observation of run 40183982111 (597 mutants, 675
same-file pairs left Inconclusive by them alone).

Extraction now records each test of a failed file with that class. When both
tests of a pair failed to import, neither ran, so the mutant cannot tell them
apart: comparePair counts it as a non-kill for both rather than another
class. Verdict engine 3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci(scenario-map): temporary label-gated pull_request run for PR #3686

schedule and workflow_dispatch only run from the default branch, so the
Test Scenario Map workflow cannot run before this PR merges. Adding the
run-ci label to the PR starts one full run. A pull_request run writes no
tracking issue and no baseline. Remove the trigger before merge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci(scenario-map): remove the temporary pull_request trigger again

The engine 3 run on PR #3686 finished (run 40208819019, complete, 9 of 9
shards). This reverts 0e76acc09.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(scenario-map): record the engine 3 run's results

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(scenario-map): scenario fingerprint verdicts (same path, input, expectation)

Two tests are duplicates when they run the same execution path on the same
input data and check the same expectation. The fingerprint engine decides
that from Layer 1 block sets, Layer 2 facets and discarded values, the
checks-and-context key and the trace run, with no mutation: duplicate,
possible-duplicate (anything unresolved, fail-closed), table-row (other
input values), different-checks, distinct.

On run 40208819019 the fully resolved triple names 26 pairs: the run's 13
strong repeats and 13 more mutation could not decide, none contradicted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(scenario-map): lead the report with the scenario fingerprint

The report (schema 2) carries every pair's fingerprint verdict with its
continuity key and the run's mutation scope. The markdown and the tracking
issue lead with duplicates and same-scenario-different-checks pairs; the
mutation sections (strong repeats, weak tests, gaps) render only when the
run gathered mutation evidence. The spot audit samples duplicates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(scenario-map): mutation scope (none, possible-duplicates, all)

plan and all take --mutation. The plan computes every pair's fingerprint
before the trace and packs only the scope's target: no group (none), every
group (all), or the groups with a possible duplicate, trimmed to the tests
of those pairs and the files they executed. Value flow re-plans a narrower
scope after the trace (a usable trace only narrows it) and builds the PDG
index for scope all only. Merge reports every pair's fingerprint and the
mutation verdicts of the pairs whose tests ran in a mutated group. A plan
with nothing to mutate has no shard; all skips the shard stage then.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(scenario-map): check fingerprint verdicts in the controls oracle

expected.json gives every control its fingerprint verdict and rule, written
from the fingerprint rules before any run: verbatim-duplicate is the one
duplicate, enum-member a possible duplicate (residual difference),
numeric-boundary distinct, the other 13 table rows. The controls stage
compares both verdicts per pair and fails on an unlisted fingerprint
duplicate. Local controls run: all 16 pairs match on both.

value-flow checks for dist/ only when it builds the PDG index (scope
all); controls, and all with scope all, still check before any stage.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci(scenario-map): fingerprint weekly, mutation on dispatch or label

The weekly run is the fingerprint only (mutation scope none: no build, no
shards). Workflow dispatch takes a mutation input (none, possible-duplicates,
all). Adding the scenario-map label to a pull request starts the deep run
over the possible duplicates; it writes no issue and no baseline, and every
run puts the issue-body view in the job summary. Pull request runs get their
own concurrency slot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(scenario-map): the scenario fingerprint as the primary verdict

The design defines a duplicate as the same execution path, input data and
expectation, records the maintainer decisions of 2026-10-25 (fingerprint
weekly, mutation on dispatch or label) and the local measurement: the
fingerprint-only run took 8.2 min over all 4,632 eligible tests and named
the 26 duplicates the evidence predicted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ci): place a single shard artifact in the scenario-map merge

download-artifact unpacks a pattern that matches one artifact into the
path itself, not into a directory named after it. With a one-shard plan
(the scenario-map label's possible-duplicates run) the placement step found
no shard directory, so merge reported the shard missing and every mutated
pair Inconclusive (run 40268120818). The step now uses the download path
when no artifact directory exists. A local re-merge of that run's artifacts
gives the complete result, recorded in the design doc.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(scenario-map): fingerprint every unit and integration test

The fingerprint needs no Stryker run, so its scope is no longer the
mutation runner's validated envelope. Eligibility now carries
fingerprintFiles (every *.test.ts under test/unit and test/integration)
next to the mutation-eligible files; a verdict input carries eligible
(mutation), fingerprintEligible and passed.

- Layer 1 and the trace run the base config's lbug-db files in a
  partition of their own with one worker (partitions.ts), the rest
  with --concurrency workers, and merge both runs.
- New fingerprint rule not-passing: a test that did not pass in
  Layer 1 makes its pairs Inconclusive.
- The mutation target keeps only pairs whose two tests are
  mutation-eligible.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(scenario-map): run Layer 1 in CI slices; load vendor and dist in integration runs

A sample of the integration tests showed two problems with fingerprinting
every unit and integration test:

- Half the sampled files failed to load: the prepare step (gate-3 hashed)
  leaves vendor/ and dist/ out of the prepared copy, and integration tests
  load leiden, the parse worker and the built CLI. Layer 1 and the trace now
  copy both from the checkout in normal mode, and every stage that runs tests
  (coverage, plan without --coverage, value-flow, all, controls) requires a
  built dist/.
- One plan job cannot hold Layer 1: 44 of 435 integration files ran past
  35 minutes. A new coverage stage (--index i --of n) runs one slice, split
  like the CI test shards (test/helpers/shard-balance.ts), and
  plan --coverage <dir> merges the slice files: one block table, indices
  remapped, files and tests in file order. A slice that did not report leaves
  its files unrecorded. The workflow runs 12 coverage slices before the plan.

The sequential partition now reads every fileParallelism: false project of
the base config (lbug-db and cli-e2e), not lbug-db alone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(scenario-map): order-dependent controls pair is Inconclusive on the fingerprint

The not-passing fingerprint rule (a test that did not pass in Layer 1 holds
its pairs Inconclusive) came after expected.json was written. Layer 1 runs
every test twice in a row (repeats 1, design §5.2); the order-dependent
fixture's shared counter makes each test's second attempt fail, and Vitest
reports a test failed when any repetition fails. So rule 2, not-passing,
decides the pair before input-values-differ. The expectation follows from
the rule and the fixture's code; the CI controls run that reported the
difference is run 40278026899.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* perf(scenario-map): skip Layer 1 for files no fingerprint finding can come from

Past the path rule, a pair is a duplicate, a possible duplicate or a table
row only when both checks-and-context keys are equal or one is unknown, and
the key is static (facet/checks.ts over the static inventory). Layer 1 now
runs only the files that hold a test whose key another test shares or that
has none, plus every file the static view cannot vouch for: a call whose
instance count is not static, a file snapshot read, a call at registration
level that is not the test API (a helper such as defineRenameFixtureTests or
describeGrammarPresence, or an it alias), or a parse failure. Mutation scope
all and the controls still run every file; the coverage jobs get the run's
--mutation so they slice the same files as the plan.

On the current checkout this skips 449 of 1,399 test files, about 24% of the
weighted Layer 1 cost. On the 250 unit files of the last full run, the static
keys reproduce all 3,313 runtime keys and select the same 172 files; runtime
collection (vitest list --no-static-parse) of the skipped files finds no test
the static inventory misses. Given up: different-checks pairs with a test of
a skipped file (0 on the last full unit run). The report says how many files
Layer 1 ran.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* perf(scenario-map): diff-scope the labelled pull request run

A labelled pull request asks whether its own tests duplicate anything, yet
the run fingerprinted the whole suite (12 coverage slices, hours of runner
time). plan --changed-since <ref> now scopes it to the diff:

- the changed test files are the fingerprint's files the diff since the
  merge base of ref and HEAD added or modified;
- Layer 1 runs the changed files the prefilter keeps plus every file with
  a test whose checks-and-context key a changed test shares;
- candidate pairs are kept only when they have a test of a changed file,
  before the groups form, so the mutation target, the trace and the report
  follow;
- a diff that changes no test file writes an empty work file and an empty,
  complete report.

The workflow skips the coverage matrix for pull requests and passes the
merge commit's first parent (fetch-depth 2); the plan job builds dist/ and
runs Layer 1 itself. The report names the changed files. Locally, over the
two test files of the previous commit, the run took 4 min 41 s end to end
(Layer 1 over 2 files 1.3 min, trace 1.1 min) on a loaded shared host.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* perf(scenario-map): size Layer 1 at 4 coverage slices, not 12

Twelve slices came from an estimate of three times the CI coverage time,
built on a local integration sample that other suites on the shared host
had slowed down. The test workflow runs the whole unit and integration
suite with coverage in three 7-8 minute shards (ci.yml run 30014110469),
and an instrumented Layer 1 run shows its overhead is small: an
integration file's work sits in beforeAll, which Layer 1 neither repeats
nor snapshots per test (resolvers/rust: 10.1 s of coverage snapshots
against about 190 s for the file). With each slice paying about five
minutes of setup, twelve slices spent more on setup than on tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(scenario-map): report the Layer 1 tests that got no fingerprint

Tests that Layer 1 saw but did not run dropped out of the candidates
without a word: skipped ones (skip, skipIf, todo; the GITNEXUS_BENCH
benchmark suites, which run only in the test workflow's benchmarks job)
and unfinished ones (pending, because their file's run ended first). The
report's eligibility section now counts both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(scenario-map): close gaps a code review found in the Layer 1 work

- The registration guard let a suite whose callback is not written
  inline (describe('x', defineCases)) through, so a file whose tests the
  inventory cannot see could be skipped. Such a suite now keeps its file.
- An empty coverage slice exited 2 and uploaded nothing; it now writes
  an empty slice file.
- --changed-since was accepted with the controls fixture, whose run must
  cover every file; that is now a usage error.
- The report counted the files of a coverage slice that did not report
  as run. It now says how many files wrote no Layer 1 record.
- A diff that only changes a snapshot file scoped nothing; a changed
  __snapshots__/<name>.snap now counts as a change of its test file.
- The diff-scope report claimed no other file can hold a changed test's
  duplicate. Files whose tests have no static key are not run, so it now
  says a possible duplicate there is not looked for.

Not changed: mutation shards never get integration tests, because
mutationTarget keeps only pairs of two mutation-eligible tests; a slice
that disagrees with the plan stops the merge on purpose (the slices
header now says so).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(scenario-map): cut setup cost and duplication in the Layer 1 work

A four-angle cleanup review (reuse, simplification, efficiency,
altitude) of the Layer 1 slices, prefilter and diff scope.

Fixed along the way: a shard's row-deletion batch ran every planned pair
of a complete group, including pairs whose tests the mutation target had
trimmed away (an integration test, or a pair outside the scope); it now
runs only pairs whose two tests the trimmed group holds (shardRowPlans).

Setup cost:
- Coverage jobs ran the Phase 0 classifier twice (about 33 s each) just
  to list the fingerprint's files; fingerprintScope lists them directly.
- The plan recomputed the prefilter (about 30 s) to rebuild the slice
  split. Slice files now carry Layer 1's file list, the mutation scope
  and the revision; the plan checks those against its own run.
- The prefilter re-parsed every test file. The unseen-registration check
  now lives in the static inventory (StaticInventory.incomplete), on the
  ASTs it holds and test-dupes' roleOf, which also catches
  test.describe with a named callback and it('x', namedFn).

Simplification: runCoverage writes the empty work file itself; reuse
partitionFiles, codeList, writeJson and path.matchesGlob (the hand-made
glob matcher read ** differently from Vitest); sameList moves to util;
copyBuildOutput owns the controls rule; slices are read before the work
directory is emptied, so --coverage no longer has to lie outside --work;
a dead sort is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(scenario-map): record the Layer 1 cleanup review in the fingerprint plan

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(scenario-map): full recall for diff-scoped pull request runs

A labelled pull request's run left out unchanged files whose tests have
no static checks-and-context key (helper-registered tests, dynamic it.each
counts, file snapshots, no assertion key), so a changed test's possible
duplicate in one was never looked for. Such a test can pair with any
changed test, so the diff scope now runs every one of those files too.

That floor is 230 of 1,407 test files, about 59% of the suite's weighted
Layer 1 cost with 59 sequential files: too much for the plan job alone.
A labelled pull request therefore runs the coverage slices as well:
coverage --changed-since records the changed files in each slice, and the
plan takes the diff scope from the slices (plan --changed-since stays for
a local all run). The plan job no longer builds dist/ or fetches history.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci(scenario-map): temporary owner-only test run on PR #3686

TEMPORARY, remove before merge. The scenario-map-test label starts the
whole-suite run (no diff scope) with mutation possible-duplicates, so
every stage (coverage slices, plan, value flow, mutation shards, merge)
can be tested on CI before the workflow reaches the default branch, where
workflow_dispatch would serve. It runs only when magyargergo adds the
label on PR #3686; the label on any other pull request, or by anyone
else, leaves every job skipped. The scenario-map label keeps its
diff-scoped run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: stabilize scenario-map test selection

* fix: exclude retry tests from scenario traces

* fix: keep captured loop inputs unresolved

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 16:46:58 +00:00
Gergő Magyar
9a0ef8fbbb
fix(eval): reuse reference settings for PR cost previews (#3738)
Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
2026-10-27 09:17:08 +00:00
Gergő Magyar
afea705e36
test(mcp): retain paired performance measurements (#3730)
Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
2026-10-27 07:32:26 +00:00
Gergő Magyar
c417ccfc81
perf(ingestion): reduce indexing overhead and declaration memory (#3726)
Some checks are pending
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Gitleaks / gitleaks (push) Waiting to run
Publish / Classify release event (push) Waiting to run
Publish / RC guard (marker + release-PR skip) (push) Blocked by required conditions
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-cli) (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-web) (push) Waiting to run
* refactor(ingestion): share callable declaration facts

Reuse pure parameter and signature facts between structure and scope
extraction, with tree-owned caches and read-only parameter contracts.
Preserve provider-specific wrappers and consumer projections.

Add characterization tests, real-worker parity checks, and reproducible
performance measurements. Keep the overall indexing effect explicit.

Refs #3723

* fix(bench): create result files exclusively

Address CodeQL review feedback on #3726. Use a private default directory and an exclusive file handle so existing files and symlinks cannot be overwritten.

* perf: speed analyzer identity guard probes

* perf(ingestion): reuse callable type and overload facts

* ci: retain callable time and memory benchmarks

* chore: use established CI performance measurements

* fix(bench): check callable baseline in CI

* perf(ingestion): guard callable scaling and reuse export checks

* fix(ci): budget for callable scaling matrix

* refactor(ingestion): simplify callable handling

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
2026-10-26 15:13:48 +00:00
rome-xi
34b873696b
fix(cli): recover pnpm and Bun invocation paths (#3721)
Some checks are pending
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Gitleaks / gitleaks (push) Waiting to run
Publish / Classify release event (push) Waiting to run
Publish / RC guard (marker + release-PR skip) (push) Blocked by required conditions
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-cli) (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-web) (push) Waiting to run
* fix(hooks): skip a pnpm shim that cannot run when picking the runner

Fixes #3717

* test(hooks): isolate runner liveness checks

Inject pnpm liveness and bunx presence in resolver unit tests so they do
not depend on installed package managers. Use fixture-only PATHs and
POSIX/Windows launchers to cover failed pnpm probes, banner output,
fallback execution, argument forwarding, and child exit codes.

* fix(cli): prepare native binary before identity

Restore skipped LadybugDB install copies before capturing analyzer
identity, while keeping native probes and analyzer imports after it.
Exercise real npm, pnpm and Bun tarball installs on Linux, macOS and
Windows so runner selection is backed by successful indexing.

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
2026-10-25 21:05:02 +00:00
Gergő Magyar
ee7eff97f7
fix(ci): rebalance native tests and stabilize flaky gates (#3719)
* fix(ci): stabilize timing gates and artifact uploads

* fix(ci): rebalance undercharged native test shards

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
2026-10-25 09:38:21 +00:00
Gergő Magyar
36227d93d1
perf: benchmark scope resolution and remove redundant allocation (#3711)
* fix(java): bound imported return-type propagation

* fix(java): preserve inherited return types

* perf: benchmark scope-resolution allocation in CI

Measure all supported languages with real parsing and resolution, and
require stable graphs and measured binding budgets in CI.

Keep transitive Java factory calls without re-copying dependency tables,
and build shared re-export closures only when a lookup needs them.

* test: cover scope benchmark CI dependency

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
2026-10-24 22:04:46 +01:00
Abhigyan Patwari
5726ad42f0
chore(deps): consolidate all open Dependabot updates (#3682)
* chore(deps): consolidate Dependabot updates

Keep all twelve dependency PRs in one verified update. Refresh the
workflow contract test for the new exact Claude action pin.

* test(eval): align setup-uv action pin

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
2026-10-23 10:49:45 +01:00
Gergő Magyar
d57f570dff
refactor(ingestion): colocate import resolution rules (#3670)
* refactor(ingestion): remove dormant import resolvers

Remove the unused LanguageProvider importResolver contract, factory and strategy chain. Keep active scope resolver helpers and their semantic tests.

Verified 5,309 corpus edges unchanged, 7,411 focused tests, typechecks, build and resolver benchmarks. Full local suite is still running; graph analysis remains partial on deleted and comment-only regions.

* refactor: colocate language import helpers

Keep import policy beside language resolvers and share only generic
indexes. Pass the existing ordered candidates explicitly so lookup
behavior and cache identities stay unchanged.

* fix: defer MCP imports and narrow Python paths

* fix(python): prefer packages in relative imports

* test(python): pin package-first import lookup

* test(python): use a valid parent-relative import

---------

Co-authored-by: Gergely Magyar <magyargergo@users.noreply.github.com>
Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
2026-10-22 03:49:35 +00:00
Abhigyan Patwari
04427e03c8
fix(ci): avoid RC tag collisions during npm processing (#3649)
Some checks failed
CodeQL / Analyze (python) (push) Waiting to run
Gitleaks / gitleaks (push) Waiting to run
Publish / Classify release event (push) Waiting to run
Publish / RC guard (marker + release-PR skip) (push) Blocked by required conditions
Publish / ci (push) Blocked by required conditions
Publish / Build & Push RC Docker images (push) Blocked by required conditions
Publish / Publish to npm (push) Blocked by required conditions
Scorecard / Scorecard analysis (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-cli) (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-web) (push) Waiting to run
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
Devcontainer Smoke / Config-transform unit tests (push) Has been cancelled
Devcontainer Smoke / Build devcontainer image (default) (push) Has been cancelled
Devcontainer Smoke / Build devcontainer image (ui) (push) Has been cancelled
Publish Development Images / publish (core) (push) Has been cancelled
Publish Development Images / publish (ui) (push) Has been cancelled
Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
2026-10-20 20:51:26 +01:00
Gergő Magyar
5d1bc3dcea
feat(eval): request PR cost comparisons by label (#3622)
* feat(eval): measure PR cost before merge

Reuse authenticated historical MCP measurements for one pinned PR preview. Keep the protected main evaluator and publish separate evidence that cannot authorize a release.

* fix(eval): gate PR cost runs on a label

Require a repository writer label event and retain the opt-in label
and exact PR head before dispatch and paid sessions. Keep the
request handler on trusted base code and execute evaluation on main.

* ci: document trusted cost label trigger

* fix(eval): restrict previews to maintainer labels

Remove manual PR preview inputs and authorize Maintain/Admin roles before calling the protected reusable evaluator. Compare workflow measurement settings with historical evidence instead of exempting the entire workflow.

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
2026-10-18 11:00:08 +01:00
Gergő Magyar
b961e695ca
fix(devcontainer): refresh Node and streamline development (#3610)
Some checks failed
Devcontainer Smoke / Config-transform unit tests (push) Has been cancelled
Devcontainer Smoke / Build devcontainer image (default) (push) Has been cancelled
Publish Development Images / publish (core) (push) Has been cancelled
Publish Development Images / publish (ui) (push) Has been cancelled
Devcontainer Smoke / Build devcontainer image (ui) (push) Has been cancelled
CodeQL / Analyze (python) (push) Waiting to run
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
Gitleaks / gitleaks (push) Waiting to run
Publish / ci (push) Blocked by required conditions
Publish / Classify release event (push) Waiting to run
Publish / RC guard (marker + release-PR skip) (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
Skill copy sync / shipped skills drift guard (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-cli) (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-web) (push) Waiting to run
2026-10-17 21:05:13 +00:00
Gergő Magyar
bd20dde825
fix(taint): report inline and factory handler flows (#3612)
* fix(taint): cover inline and returned handlers (U8)

Join expression-handler CFG summaries to distinct graph functions without changing existing anonymous-owner identities. Keep named function expressions private to their lexical scope.

Related: #3489

* fix(ci): encode inline handler taint paths (U8)

Use codec-safe generated display names while preserving positional function identity. Verify persisted hop continuity and remove the repaired inline-flow accuracy allowance.

* fix: keep anonymous names unbound (U8)

* test: pin inline callback captures (U8)

* ci: run inline taint guard (U8)

* test: align inline handler contracts (U8)

Pin callback-owned call edges while preserving nested callable IDs and module-level HOC attribution. Assert repaired inline flows and the retained captured-closure limitation.

* ci: run native inline proofs on all OSes (U8)

Register real-worker identity/CFG and persisted explain cases on the existing Windows/macOS matrix. Charge explicit scheduling estimates without changing watchdogs or runtime behavior.

* test(taint): reject all enclosing factory sources

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
2026-10-17 20:22:58 +00:00
Gergő Magyar
f43834e814
fix(indexing): converge coverage around directory symlinks (#3616)
* fix(indexing): converge coverage around directory symlinks (U5)

* style(bench): format symlink baseline (U4)

* ci: run directory symlink coverage benchmark

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
2026-10-17 19:37:45 +01:00
Gergő Magyar
9b04fbe627
fix(embeddings): budget generated inputs and isolate rejections (#3615)
* fix(embeddings): budget generated inputs and isolate rejections (U4)

* test(embeddings): require pending retry request

* fix(embeddings): preserve Unicode in context

* ci: run generated embedding input budget guard

* test(embeddings): run input isolation on native OSes

* fix: retain container identity after long prefixes

* test: distinguish generated input cases

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
2026-10-17 19:37:30 +01:00
Gergő Magyar
e6ae04ed84
fix(embeddings): reject corrupt identities before mutation (#3614)
* fix(embeddings): reject corrupt identities before mutation (U2)

* fix(embeddings): preserve exact Unicode keys (U2)

* fix(storage): validate identities before opening CSVs

* fix(embeddings): validate caches before mutation

* ci: gate native embedding identity benchmark

* test(embeddings): run identity proofs on native OSes

* docs: describe CSV identity validation pass

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
2026-10-17 18:45:28 +01:00
Gergő Magyar
c8629f1b6c
fix(storage): preserve published graph on rebuild failure (#3613)
* fix(storage): preserve published graph on rebuild failure (U1)

* test(storage): strengthen publication review coverage (U1)

* test(storage): align publication evidence (U1)

* fix(storage): retain completed recovery archives

* fix(storage): preserve quarantines before cache reads

* ci: run staged publication benchmark guard

* fix(ci): declare WAL replay probe determinism

Document that the bounded recovery read drains and discards its rows. Only WAL replay success is observed; row identity and query behavior are unchanged. The existing 21 query-determinism checks pass.

* test(storage): cover publication across platforms

* test(ci): exclude POSIX suite from Windows estimates

* test: allow native publication retry to finish

* test: verify Windows incremental recovery

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
2026-10-17 18:45:11 +01:00
Gergő Magyar
252a64573e
fix(eval): account for background completion turns (#3604)
Validate continuation evidence, sum per-turn tokens and turns, retain final cumulative cost, and include background wait in elapsed time. Add an offline pinned-CLI canary before paid evaluation and allow 60-minute sessions within the existing deadline and cleanup reserve.
2026-10-16 17:03:28 +00:00
Gergő Magyar
faf05f2eb7
fix(install): restore Linux ARM64 npm installation (#3601)
* fix(install): validate and package Linux ARM64 parser replacements

* fix(install): add rebuilt ARM64 grammar binaries

* fix(install): place ARM64 binaries in versioned bundle paths

* refactor(install): share ARM64 prebuild validation

* fix(review): keep grammar rebuild provenance accurate

* test: pin audited ARM64 repair provenance (#3601)
2026-10-16 15:28:35 +01:00
Gergő Magyar
fa70fd8343
chore(deps): consolidate ten Dependabot updates and fix compatibility (#3592)
* chore(deps): consolidate Dependabot GitHub Actions updates

* chore(deps): consolidate web updates and secure transitive dependencies

* fix(web): preserve diagram appearance with Mermaid 12

* test(ci): align workflow security tests with updated action pins

* fix(ci): split coverage across eight shards to avoid job timeout

CI run 38693066214 cancelled Ubuntu coverage shard 1 after 25 minutes while tests were still passing. The missing coverage blob then caused the execution audit and CI gate to fail.

Increase only the coverage shard count from four to eight. Keep the timeout, full suite, coverage thresholds, and execution audit intact.

Validation: all 1,247 test files form a complete, disjoint eight-shard partition using the configured Vitest sequencer; 117 targeted tests passed (2 existing skips); workflow generator, Prettier, concurrency validation, and diff checks passed.

* fix(ci): leave headroom for Windows test shards

Run 38697469283 exhausted the 20-minute Windows watchdog. Use ten platform shards while retaining eight coverage shards and all existing timeouts, coverage gates, and execution audits. The accompanying timing refresh and recorded-profile regression keep all 145 platform-sensitive test files covered exactly once.

* fix(ci): refresh underestimated Windows suite timings

Refresh eight materially underestimated timing weights using Windows runs 38697469283 and 38693066214. The old partition placed native suites ahead of cli-e2e with insufficient time left under the watchdog. Keep every suite and the partitioning algorithm unchanged.

* test(ci): replay the Windows timeout workload

Add a deterministic regression from recorded Windows CI timings, independent of the scheduling table. It failed before the fix with a 1,426-second shard and now protects three minutes of watchdog headroom.

Validation: 118 targeted tests passed (2 existing skips); typecheck, formatting, workflow generation, concurrency and diff checks passed. Independent review found no actionable issues. All 145 platform test files are selected exactly once; replaying the complete observed profile gives a 973-second maximum across ten shards. Hosted CI remains the final elapsed-time check.
2026-10-15 10:43:04 +01:00
Gergő Magyar
9572e71127
fix(npm): restore project-local consumer installs (#3568)
Some checks failed
Skill copy sync / shipped skills drift guard (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Gitleaks / gitleaks (push) Waiting to run
Publish / Classify release event (push) Waiting to run
Publish / RC guard (marker + release-PR skip) (push) Blocked by required conditions
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-cli) (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-web) (push) Waiting to run
* fix(npm): restore project-local consumer installs

* test(npm): cover fresh consumer installs on npm 10 and 11
2026-10-13 08:16:05 +01:00
Gergő Magyar
8fa8e64388
fix(rename): extend safe refactoring and flow coverage across languages (#3557) 2026-10-13 08:38:17 +03:00
Gergő Magyar
114ae0b411
fix(indexing): abort on exhausted or collapsed graph writes (#3540)
* docs(indexing): document native pool exhaustion recovery (U3)

Publish the reviewed recovery runbook and collapsed-write guardrails for #3526.

* docs(indexing): explain native buffer pool sizing (U3)

* fix(indexing): reject collapsed staged graph writes (U2)

* fix(indexing): abort native buffer exhaustion (U1)

* test(indexing): cover exhausted and collapsed graph writes

* ci(tests): split ubuntu coverage into 4 shards

Coverage shard 1/3 runs 20-25 minutes across branches and now hits the
25-minute job timeout (cancelled on this PR and on unrelated branches),
which skips coverage-merge and fails "every test executed" plus every
platform compatibility gate downstream. A fourth shard brings each slice
well under the cap. Shard job names are not required checks; the merge
job globs coverage-blob-*, so no other wiring changes.

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

* test(lbug): remove branching from buffer-exhaustion tests

Split the collapsed-staged-graph case into first-time and existing-index
tests sharing one helper, so every assertion runs unconditionally instead
of behind `if (hasExistingIndex)`. Parameterize the first-COPY exhaustion
case with its statement matcher (reusing isRelationshipCopy) rather than a
ternary on the phase name. Assertions are unchanged.

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

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 17:31:38 +01:00
Gergő Magyar
ecb444b4c8
chore(deps): consolidate ten Dependabot updates (#3554) 2026-10-10 16:16:16 +00:00
Gergő Magyar
22aeeebaf3
fix(eval): materialize release graphs before paid sessions (#3556)
Use the existing snapshot capture ceiling for buffered materialization so
valid graphs remain usable on filesystems without reflinks. Preflight both
release runtimes before paid sessions and exercise the real copy boundary
with a 513 MiB regression and the native release smoke.
2026-10-10 15:24:09 +00:00
Gergő Magyar
999cc9f913
fix(deps): upgrade native tree-sitter to 0.25.1 (#3531)
* fix(deps): upgrade native tree-sitter to 0.25.1

* fix(tree-sitter): preserve sync loading and update verified capture baselines

Route C# scope queries through the synchronous native grammar loader so the compiled analyze module remains require-compatible on Node 22.18. Refresh only the audited empty-Python-module and renamed-PHP-fixture captures, and pin the runtime assertion to 0.25.1.

Validated 479 targeted tests, all 16 scope-capture benchmark cases, Python capture/import guards, compiled C# worker parsing, build, typecheck and formatting. Performance budgets are unchanged.

* fix(tree-sitter): refresh upstream vendors and preserve parser semantics

* fix(ci): refresh prebuilds and support Windows ARM

Refresh macOS, Linux ARM, and Windows x64 grammar binaries from the successful native CI builds. Pin node-gyp 12.4.0 so the Windows ARM jobs recognize Visual Studio 2026.

Use local Git filtering for E2E to avoid PR-files API timeouts on generated parser diffs.

Validation: 143 focused tests, Actionlint, and all 16 scope-capture benchmark checks passed. Full npm test run started; native database suites still running.

* fix(ci): refresh Windows ARM grammar prebuilds

Import all seven Windows ARM grammar artifacts from successful native build run 37965761760. Artifact filenames and SHA-256 hashes verified; all 42 native build jobs passed.

Validation: 31 prebuild coverage tests passed.

* fix(bench): stabilize scope capture timing guard

Warm each input size seven times and use 21 median samples while retaining isolated timing blocks. Yield between languages so native finalizers release allocations outside the measured sections. Keep all fixture sizes, fingerprints, scaling formulas, and budgets unchanged.

Validation: all 16 language guards passed with a 2 GB heap limit (1.38 deep-chain ratio; 1518 MB peak RSS). Linear and quadratic controls passed their expected guard outcomes. Formatting and graph change analysis passed. Full npm test is running without failures so far.

* fix(parser): reduce TypeScript capture traversal cost

* fix(test): await parser worker readiness before teardown

* fix(parser): load C# synchronously in workers

* fix(grpc): resolve native proto detections against their own file

With the native proto grammar active, sibling .proto files that declare
the same short service name under different packages tied in the
directory-based resolveProtoConflict heuristic and both providers were
dropped. A proto-origin detection already knows its defining file, so
use that file's entry before falling back to the heuristic.

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

* ci(packaging): assert native grammars load from the installed tarball

The packaged-install smoke only ran `gitnexus --version`, so a grammar
that failed to load from the published package (bundled runtime, patched
peer manifests, vendored prebuilds, C# sync loader, Protobuf wrapper)
would ship silently; the dev-tree ABI smoke also accepts vendored
grammars that report unavailable. Parse a sample for every registered
grammar plus the native Protobuf plugin from the installed package, on
the main thread and in a worker thread.

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

* ci(tree-sitter): track compatibility workarounds instead of 0.25 readiness

The daily readiness report still targeted tree-sitter@0.25.0, so after the
upgrade it would keep reporting "Blocked" and never close its tracking issue.
Repurpose it to track what we carry for the bundled runtime: derive the target
from the package.json pin, list each pack-time peer patch from
prepare-tree-sitter-bundle.cjs with its drop condition (bump, wait for an
upstream release, transitive, or intentionally pinned), and reword the
buckets. The workflow adopts the issue opened under the old title.

Also update the grammar-update-monitor header and auto-PR text, which still
described the 0.21.1 runtime and a tree-sitter-c hold.

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

* test(dart): assert both nested labels target the loop; fix Zig call-shape doc

The nested-label CFG test only jumped to `outer` and checked reachability,
which still passes when a jump is retargeted to the inner loop (its exit
reaches the outer header). Jump to both labels and assert the exact
`continue` edges; dropping the inner label now fails the test.

Update the Zig callable-flow comment: call_expression now wraps actuals in a
required `arguments:` field.

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

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 13:07:59 +03:00
Gergő Magyar
4756e8a820
fix(release): gate publication on accuracy and paired evaluation (#3503)
* test(release): add fixed-answer native tool accuracy

* fix(release): gate stable artifacts on pinned paired evaluations

Apply review findings #1-4: gate Docker publication, grade in-flight retries, preserve repository context, and execute negative controls in CI.

* fix(eval): verify native context and resolve harness security findings

Inspect Claude's first startup reminder for ordinary repository guidance.
Bound launcher-option matching and escape Markdown backslashes and pipes.
Exclude only the parsed synthetic accuracy corpus from CodeQL; keep the
benchmark harness and evaluator under security analysis.

Validated focused Python and TypeScript regressions plus core typecheck.

* fix(eval): wake the EC2 runner and prove paired evaluator execution

Bootstrap the existing dedicated instance from a protected hosted job, bound
native runner pickup, and stop only instances started by this run. Keep paid
sessions inside the fixed stop window and add a runner-only dispatch.

Require a contained six-cell prepare/session/oracle/report canary in CI,
including a failed repair that remains in the measured denominator.

* fix(ci): reuse existing configuration and disambiguate accuracy cases

Remove the new AWS credential/settings path and release opt-in variable. Bound native runner pickup with the existing GitHub token and retain private EventBridge startup until its existing mechanism can be reused. Reuse current workflow environment names and evolution schedule controls.

Name malformed-observation cases explicitly so the execution audit distinguishes null from missing and actually tests invalid arrays.

* fix(review): isolate release builds and preserve benchmark evidence

* fix(release): gate RC publication on paired quality and manage EC2 lifecycle

* fix(ci): clarify release shell redirects and build script

* fix(eval): remove temporary patch sinks after capture

* fix(bench): retire tool-accuracy allowances repaired on main

Main at 50aa4be3b repaired three #3487 route checks (#3505) and all four
#3499 Python scope checks (#3502, #3504). The ratchet correctly failed the
merged head with stale allowances, so remove them and keep the fixed answers
as release protection: 18/31 pass, 13 recorded gaps remain.

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

* fix(release): gate RCs on accuracy only and keep paid runs for stable

Follow the cost split proposed in discussion #3493: fixed-answer tool
accuracy on every RC, paired agent runs before stable releases and on a
weekly schedule against the latest RC.

RC publication no longer prepares a bundle, calls release-evaluation.yml
and waits for a paid run of up to 21 hours on the shared EC2 lock. Every
release attaches this run's accuracy report; stable npm publication still
requires exact-commit paired evidence. release-evaluation.yml drops its
workflow_call path and the now-unused candidate bundle module.

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

* fix(release): address PR #3503 review feedback

- Page through recent release-evaluation runs instead of reading only
  the newest 50, so valid stable evidence cannot be pushed off page one.
- Bound each runner-pickup jobs request by the remaining deadline.
- Replace non-finite floats at any depth in failure receipts so the
  incomplete report still serializes with allow_nan=False.
- Clarify that the summary.cap case has 501 names over 1001 sites.

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

* fix(review): harden candidate build and close review gaps

- Mount the candidate checkout's .git read-only inside the build sandbox,
  so lifecycle scripts cannot plant git config (e.g. core.fsmonitor) that
  host git later runs in that checkout during actions/checkout cleanup.
  The real-Bubblewrap canary now also attempts that write.
- Type tool-accuracy observations instead of using explicit any.
- Cover the fail-closed branches reviewers found untested: unsafe or
  missing evidence artifacts, mismatched task pins, malformed repo/SHA,
  an instance that stops again during bootstrap, and unbalanced GitNexus
  guidance markers.

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

* docs(release): describe RC accuracy gate and stable evidence step

- CONTRIBUTING now states that RCs are gated by CI (including the
  fixed-answer tool-accuracy check) without a paid run, and that stable
  publication needs a passing Release evaluation for the exact commit
  within seven days.
- The oracle-control fixture passes tarfile's data filter only where it
  exists (3.11.4+), matching the declared Python 3.11 floor.

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

* refactor(bench): pin tool-accuracy fixture line anchors in one place

run.ts bucketed rename edits and explain findings by line literals that
expectations.ts duplicated. Export FIXTURE_ANCHORS (file, line, pinned text)
from expectations.ts, build the fixed answers and run.ts classifiers from it,
and fail loudly (runner and unit test) when a fixture line no longer holds
the pinned text. Expected answers and observations are unchanged.

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

* fix(bench): fail closed when ripgrep is missing from the tool-accuracy run

rename's text-search pass shells out to rg and only logs a degraded warning
when it is absent, so a runner without ripgrep scored a degraded rename
(homonym.ts:1 missing) and still passed. Check rg --version before indexing,
record it in accuracy.json source.externalTools, and install ripgrep in the
ci-tests tool-accuracy job and the docker release-gate (same if: condition).

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

* refactor(eval): split baseline guidance, share bwrap preamble, drop dead bare option, harden patch cleanup

- Move the baseline (no-GitNexus) guidance scrubbing out of proposer_sandbox.py
  into baseline_guidance.py, with its unit tests.
- Expose real_directory, runtime_mount_args and bwrap_base_args publicly so
  release_build no longer imports private helpers or re-assembles the shared
  bubblewrap preamble; the candidate build command is byte-identical.
- Remove the unused run_claude `bare` parameter and its --bare/--tools branches.
- capture_patch: a failed temporary-directory removal no longer discards the
  read patch or replaces an earlier error; it is attached as a note, or warned
  on stderr when there was no earlier error.

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

* fix(ec2-runner): keep stop observing through transient describe failures

- stop() treats a failed or timed-out describe-instances call as unknown
  state and keeps observing until the stop deadline; a persistent failure
  is still raised at the deadline with the last command error. Unusable
  states and identity mismatches still fail at once (new CommandError
  subclass separates command failures from semantic ones).
- Readiness CLI has one paid mode: --job-name NAME. --evolve is removed;
  skill evolution passes its job name, and tests tie the watchdog command
  to the paid job's actual name in both EC2 workflows.
- Jobs-API requests never get a timeout larger than the remaining pickup
  budget (previously rounded up to 1s past the deadline).
- Document that the shared concurrency group keeps only one pending run,
  so a queued release evaluation can be replaced and must be confirmed.

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

* docs(eval): record verified EC2 lifecycle configuration

The README still described the AWS settings as assumed and unverified.
The OIDC role, environment settings and runner_only lifecycle were
configured and verified live on 2026-10-09.

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

* fix(release-eval): grade both runtimes against one pinned task toolchain

Candidate and stable each staged task dependencies (node_modules,
gitnexus-shared/dist) from their own runtime checkout, so the same v1.6.12
task source was graded with different TypeScript, Vitest and LadybugDB
versions and a per-task solve delta also measured dependency drift.

- Check out and build the pinned task commit once (tasks-base) and point
  every task's repo at it for both runtimes; the runtime under test reaches
  sessions only through --gitnexus-root. prepare requires --task-repo at the
  single pinned task commit (new task-sha subcommand resolves it).
- Retain sandbox_dependency_content_digest per measured row and make
  release_gate fail when any task's cells, across candidate and stable, do not
  share one recorded dependency digest.
- Move the task-pin comparison into validate_report(task_pins=...) and use
  it from release_report check and release_gate.
- Cover the gate CLI with a missing and a corrupt candidate report.

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

* docs(ci): warn that a pending release evaluation can be replaced

GitHub keeps one pending run per concurrency group, so a newer queued
EC2 run cancels a pending release evaluation. Operators must confirm the
startup job ran before relying on the evidence.

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

* test(eval): prove hidden oracles against the grading toolchain

Release evaluation now grades every task with dependencies built at the
pinned task commit (TypeScript 5.9.3, Vitest 4.1.11), but the oracle
controls still ran against the current checkout's toolchain. The Ubuntu
containment job now builds the pinned task toolchain and points the
controls at it. All seven controls pass locally against that build.

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

* test(ci): pin the duplicated EC2 lifecycle jobs together

Both EC2 workflows carry their own copy of the live-verified start,
check, readiness and stop jobs. A reusable workflow would change that
verified job structure, so instead a test requires the copies to stay
identical apart from the job display name and the paid-job dependency.

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

* fix(release-eval): accept stable evidence only from main's current evaluator

Stable publish validated downloaded agent evidence against the release
commit's eval/ tree and never tied a report to the run that produced it.
Evidence from an older evaluator stayed acceptable for seven days after
graders changed, while task changes on main made every fresh evaluation
mismatch the tag. The first invalid artifact also hid older valid runs.

The composite action now extracts eval/ from main's head and runs the
validator there with locked base dependencies only (no dev extras or
project build). A report counts only when its harness_sha is the head_sha
of its trusted main run and the compare API shows no change under eval/,
the release-evaluation workflow or the pinned agent CLI between that
harness and the evaluator; a missing, diverged or 300-file comparison
fails closed. Runs are tried newest first, rejected runs are skipped
with a bounded reason list, every gh call has a timeout, and task pins
use validate_report's task_pins check.

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

* fix(eval): break the sandbox import cycle and resolve code-scanning alerts

- baseline_guidance is now pure text handling with its own GuidanceError;
  the baseline mount builder lives in proposer_sandbox again and converts
  that error to SandboxError, so imports run one way only.
- task_assets uses the public real_directory name; the unused private
  alias is gone.
- The oracle-control fixture always extracts with tarfile's data filter
  and skips on Pythons that lack it, instead of extracting unfiltered.

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

* fix(release-eval): run candidate lifecycle scripts offline; reject smuggled report fields

- build_candidate now downloads locked dependencies with --ignore-scripts,
  then runs every lifecycle script (dependency installs, prepare, build)
  in a fresh network namespace, so candidate code cannot reach host-local
  services. Verified locally that the current head and the pinned task
  commit build this way; the real-Bubblewrap canary now asserts only
  loopback is visible to a lifecycle script.
- validate_report requires the evidence document to equal its
  field-whitelisted rebuild, so per-run or top-level fields outside the
  published schema are rejected before the publisher copies the file.
- The sandbox test suite also covers a no-GitNexus sandbox refusing
  unbalanced guidance markers.

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

* docs(eval): describe the offline candidate lifecycle

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

* fix(release-eval): pin downloads to the npm registry; require dependency binding

Address review feedback on PR #3503:
- The candidate's online install phase now refuses lockfile entries that
  resolve outside https://registry.npmjs.org/ (other than in-checkout
  workspace links) and refuses shipped .npmrc files, so a candidate
  cannot steer npm at loopback, private or metadata endpoints.
- Every measured row must carry a 64-hex task-dependency digest, so a
  single report cannot be accepted with its grading toolchain unbound.
- Oversized JSON integers mark a measurement untrustworthy instead of
  crashing report generation.
- Baseline guidance stripping recognises headings with up to three
  leading spaces (CommonMark).
- Remove a stale comment about the old private helper name.

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

* fix(eval): parse CommonMark ATX headings; compare evidence by exact JSON

- Baseline guidance stripping now parses headings as CommonMark ATX
  headings (0-3 leading spaces, optional closing # run, tabs), so a
  GitNexus section heading like '## GitNexus rules ##' is removed too.
- Evidence validation compares the serialized rebuild with the report,
  so a retyped value (true for 1, 2.0 for 2) no longer passes.

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

* fix(eval): drop continuations of every CommonMark list item in baseline guidance

A removed GitNexus instruction left its indented continuation behind when
the item used '+' or an ordered marker (1. / 1)). The scrubber now
recognises every CommonMark list-item marker.

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

* fix(eval): isolate candidate MCP from agent task writes (#3503)

Run MCP in a nested Bubblewrap boundary with read-only task, graph,
registry and runtime mounts, private state and isolated processes/network.
Keep task writes on the agent's built-in tools and remove mutating MCP grants.

Add startup/tool mutation canaries and preserve explicit unsafe diagnostics.

Validation: focused pytest 138 passed, 16 skipped. Full locked evaluator
996 passed, 29 skipped; real containment canaries require Ubuntu CI.
Note: eight pre-existing comparator-reuse failures reproduce on the
unchanged head due to missing os.supports_dir_fd support. One process-control
timeout failed in the full run and passed alone and on the unchanged head.

* fix(eval): close baseline mount overlap and test symlink evidence (#3503)

Reject supplied no-MCP mounts that cover forbidden GitNexus paths, including ancestor mounts and lexical aliases. Keep ordinary dependency mounts available.

Exercise evidence symlink rejection with a real valid-report target and retain dangling-link coverage.

Validation: 1026 evaluator tests passed, 29 skipped; targeted mount tests 36 passed and evidence tests 34 passed. Removing the symlink guard in memory makes the repaired regression fail. Ruff and diff checks passed.

Note: eight pre-existing comparator-reuse failures remain in this environment because os.supports_dir_fd lacks the required os.lstat support.

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-10 08:26:08 +01:00
Gergő Magyar
e230914189
chore(deps): consolidate eight dependabot updates (#3525) 2026-10-08 08:19:42 +03:00
Gergő Magyar
dd096e690c
chore(deps): consolidate open dependabot updates (#3496) 2026-10-06 07:23:35 +00:00
Gergő Magyar
df49f90889
fix(ci): require every test to execute across the CI matrix (#3479) 2026-10-06 07:34:17 +03:00
Gergő Magyar
4758df1c6c
fix(ci): fail on TypeScript errors in tests (#3472) 2026-10-05 04:13:27 +00:00
Gergő Magyar
702eb9326a
chore(deps): consolidate pending dependency upgrades (#3441) 2026-10-01 19:16:12 +03:00
Joseph Yared
b92c14cdd0
feat: add Factory AI (Droid) integration (#2543)
Some checks are pending
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Gitleaks / gitleaks (push) Waiting to run
Publish / Classify release event (push) Waiting to run
Publish / RC guard (marker + release-PR skip) (push) Blocked by required conditions
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-cli) (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-web) (push) Waiting to run
* feat(setup): add Factory Droid (MCP + skills) to gitnexus setup

Register 'droid' in the editor-targets abstraction so `gitnexus setup -c droid`
writes the MCP server to ~/.factory/mcp.json and installs skills to
~/.factory/skills/ from the single canonical skills/ source (no per-editor
copies). uninstall.ts is target-driven, so removal is covered automatically.
Adds unit + round-trip coverage.

* feat(plugin): add gitnexus-factory-plugin for droid plugin install

* docs: add Factory Droid to editor support table and setup docs

* fix(factory-plugin): guard augment hook against fan-out and DB contention

Reuse the Claude adapter's acquireHookSlot and LadybugDB owner probe
(bundled byte-identical, kept in lockstep by a drift test) instead of
running an unguarded augment. Add direct tests for the hook and manifests.

* docs: align Factory row in editor support table

* fix(factory-plugin): honor GITNEXUS_HOOK_CLI_PATH so augment runs on Windows

* docs(hooks): point bundled guard copies at their drift tests

* docs(factory-plugin): note the Execute tokenizer's quoting limit

* docs(readme): clarify the Full tier and group the Factory row

* docs(hooks): trim drift note to a single line

* test(ci): run factory-plugin tests on the windows cross-platform lane

* refactor(hooks): drop the drift-note comments, the tests already enforce it

* fix(factory-plugin): pin CLI version and parse quoted shell patterns

- Pin mcp.json and the hook's npx fallback to gitnexus@<version> from
  the plugin manifest, registered with the release sync script so a
  mutable @latest can never execute on MCP connect or augment fallback
- Port the #2938 shell tokenizer (tokenizeShellWords + parseRgGrepPattern)
  so quoted, backslash-escaped, --regexp=, -eVALUE, and -- patterns survive
- Add the #2938 regression matrix and pin assertions to factory-plugin.test.ts

* docs: add Factory Droid to published npm README

* fix(factory-plugin): wire marketplace so droid installs the Factory plugin

Add .factory-plugin/marketplace.json sourcing ./gitnexus-factory-plugin.
Droid reads it before .claude-plugin/marketplace.json, so
`droid plugin install` now delivers the Factory plugin (Execute matcher,
pinned mcp.json) instead of the translated Claude plugin (Bash matcher,
gitnexus@latest). Register the surface in the version-sync script and
cover the wiring in the factory and sync test suites.

* fix(factory-plugin): use registry lookup for index resolution

Bundle registry-query.cjs so external indexes resolve (#3060); re-pin to 1.6.12.

* fix(factory-plugin): sync Execute parser with Cursor hook

Fixes echo-rg and -f false positives; tighten test env isolation.

* fix(factory-plugin): stop no-match augment from re-running via npx

A PATH `gitnexus` that finds no match exits 0 with empty stderr, which
fell through to a second `npx -y gitnexus@<pin> augment` with its own 8s
timeout (16s worst case vs the 10s hook budget). Fall through to npx only
when the PATH launcher is missing (ENOENT); any launched PATH binary,
including a timeout or non-zero exit, now ends the augment.

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

* fix(factory-plugin): filter augment stderr to the [GitNexus] block

runAugment returned raw child stderr, so npm/Node/LadybugDB warnings leaked
into additionalContext and noise-only stderr counted as success. Port the
Claude adapter's extractAugmentContext (verbatim, with isDebugEnabled) and
apply it on every launch tier before the success decision. Adds a drift test
against the Claude copy and PATH-tier noise/noise-only behavior tests.

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

* fix(factory-plugin): quote DROID_PLUGIN_ROOT in hook command

An unquoted plugin root containing spaces (e.g. a Windows user profile
path) split into multiple argv words, so the PostToolUse hook silently
never ran. Quote it like the Claude plugin does, and pin the exact
quoted command in the hooks.json wiring test.

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

* fix(release): stage Factory plugin manifests in the release commit

The rc release job stages only the original four manifest surfaces in the
detached release commit, so the v<version> tag tree carried the Factory
plugin.json, mcp.json and marketplace.json at the previous version while
--check (working tree) passed. Stage them too, and guard the git add block
against the synced surfaces in sync-plugin-manifests.test.ts.

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

* refactor(factory-plugin): simplify hook gates, spawn tiers and tests

- main(): resolve the repo only after the tool-name and pattern gates,
  matching the Claude/Cursor hook order (skips fs/git work on no-op calls).
- runAugment(): share one spawnAugment helper between the
  GITNEXUS_HOOK_CLI_PATH and npx tiers; PATH tier ENOENT logic unchanged.
- factory-plugin test: pre-filter comment lines instead of `continue`.
- sync-plugin-manifests test: hoist EXECUTABLE_MCP_FILES and derive
  TOTAL_SURFACES from its length.
- fnSource(): throw when the function or its closing brace is not found.

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

* fix(cli): list Factory Droid in localized setup help

`localizeCliHelp` overwrites the `setup` command description with the
`help.command.setup.description` i18n key, so the literal edited in
index.ts never reached `gitnexus setup --help`. Add Factory Droid to the
en and zh-CN keys.

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

* Address PR review feedback (#2543)

- factory hook: run every augment tier under the bundled Unix timeout
  guard (npx tier group-kills), keeping exactly-one-tier fall-through
- hook-db-lock-probe: trim GITNEXUS_HOOK_{LSOF,PS}_PATH once so a padded
  override is used, not silently replaced (all 3 copies)
- hook-lock: evict a stale slot via rename-to-tombstone + identity check,
  so a concurrently recreated fresh lock is never deleted (all 4 copies)
- registry-query: a set-but-invalid storage override resolves no repo
  instead of falling back to the registry storagePath (all 4 copies)
- publish.yml: stage the ten skill mcp.json manifests in the rc release
  commit; the staging test now requires every synced surface

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

* Address PR review feedback round 2 (#2543)

- hook-lock: replace rename-to-tombstone eviction with an O_EXCL per-slot
  `.evicting` marker plus an identity re-check before unlink, so a live
  lock is never moved, and a crashed evictor leaves only a self-expiring
  marker (all 4 copies)
- hook-db-lock-probe: clamp GITNEXUS_HOOK_PROC_CMDLINE_MAX to a named
  256 KiB ceiling and require an integer, so an oversized override can
  no longer fail the buffer allocation and miss a live owner (all 3 copies)
- registry-query: treat an empty GITNEXUS_STORAGE_PATH/ROOT as set but
  invalid, matching the CLI's `!== undefined` rule (all 4 copies); the
  factory test env now deletes those keys instead of blanking them

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

* Address PR review feedback round 3 (#2543)

- hook-db-lock-probe: a capped /proc cmdline read stops early only once
  both the GitNexus token and the mcp/serve mode are present (or at EOF,
  the ceiling, or the budget), so a mode word such as `--require mcp`
  before the GitNexus path no longer hides a live owner (all 3 copies)
- registry-query: correct the override comment; a filesystem root is
  invalid only for GITNEXUS_STORAGE_PATH, not GITNEXUS_STORAGE_ROOT
  (all 4 copies, comment only)

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

* Address PR review feedback round 4 (#2543)

- hook-db-lock-probe: an fd-directory read error other than ENOENT or
  ENOTDIR on an identified server candidate now fails closed ('timeout')
  instead of reporting not-owned (EMFILE/ENFILE/ENOMEM/EINTR)
- hook-db-lock-probe: resolve GITNEXUS_HOOK_TIMEOUT_PATH to an absolute
  path before validating and caching it, so callers that spawn with a
  request cwd can still execute the guard
- hook-db-lock-probe: document the chunked cmdline read's actual stop
  conditions (all 3 copies)

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

* Harden hook-lock eviction marker lifecycle (#2543)

Per the chosen option (B) for the stale-slot eviction race:
- `.evicting` markers carry a per-call owner token (pid + random hex)
- an evictor re-reads its token immediately before the slot identity
  check and unlink; a stalled evictor whose marker was broken backs off
- `finally` removes the marker only while it still holds our token
- an orphaned marker is broken only if, re-checked just before unlink,
  its bigint identity and token are unchanged from when judged stale
- doc comment states the two remaining two-syscall windows (slot
  lstat->unlink, marker token->unlink); POSIX has no conditional
  unlink, and the worst case is one extra concurrent augment

All four byte-identical hook-lock copies updated.

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

* Fix CodeQL file-system race in hook-lock orphan-marker check (#2543)

breakOrphanedMarker stat'd the marker by path and then read it by path,
which CodeQL flags (js/file-system-race): the file could be replaced
between the two calls. Take the stat and the token from one open
descriptor (readMarkerSnapshot, O_NOFOLLOW where available) for both the
"judged stale" snapshot and the pre-unlink re-check. All four hook-lock
copies updated.

The replaced-marker test injected its swap via a readFileSync(path) spy,
which no longer fires; it now swaps the marker just before its second
open, counting opens of the marker path only (a per-path counter fired
early on slot-0 and let a mutant pass).

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

* Unregister hook-lock exit listener on release (#2543)

Each acquireHookSlot registered `release` as a process 'exit' listener
that was never removed, so a long-lived process acquiring and releasing
slots repeatedly would accumulate listeners (MaxListenersExceededWarning)
and retain every closure. release() now removes itself. All four
hook-lock copies updated; a test asserts 12 acquire/release cycles leave
the 'exit' listener count unchanged.

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

---------

Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 19:12:40 +01:00
dependabot[bot]
1d79571de9
chore(deps): bump docker/setup-qemu-action from 4.3.0 to 4.4.0 (#3368)
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 4.3.0 to 4.4.0.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](1f40c72289...9901266195)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-version: 4.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>
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
2026-09-24 07:09:10 +01:00
dependabot[bot]
ce5831e342
chore(deps): bump docker/setup-buildx-action from 4.3.0 to 4.4.1 (#3367)
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 4.3.0 to 4.4.1.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](37fe631027...f87e5991a6)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-version: 4.4.1
  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-09-24 06:20:29 +01:00
Adam B.
7376347058
feat(ingestion): add tRPC procedure detection and MCP chain/route surfacing (#3339)
* feat(ingestion): tRPC pattern detection — procedures, curried calls, route extraction

Three changes to properly index tRPC router files:

1. HOC-in-pair patterns: detect procedures like
   'create: procedure.mutation(async ({ input }) => {...})'
   as named Function nodes (pair > call_expression > arguments > arrow_function)

2. Curried call detection: capture 'workflow(db)(input)' chained calls
   where call_expression.function is itself a call_expression

3. tRPC route extraction: new route-extractors/trpc.ts detects
   .query()/.mutation()/.subscription() procedures, maps to /trpc/* routes
   with prefix inference from router variable names

4. Function/Const dedup: structural check skips Const nodes when
   variable_declarator value is arrow_function/function_expression

5. Process-route linking: match by (filePath, methodName) instead of
   filePath only, preventing shared flows across procedures in same router

(cherry picked from commit eced15e60a39a181a48bff8c5bbe278d26aa53b8)

* fix(route-extractors): line-by-line scanner for chained tRPC procedures

Original regex only matched direct patterns (list: proc.query()) but not
chained patterns (create: proc.input(z.object({...})).mutation()). Only
41/256 routes were detected on Jurialis.

Rewrote extractTrpcRoutes() as a line-by-line scanner that:
- Detects procedure keys starting with *Procedure builders
- Tracks currentProcedure forward until terminal .query()/.mutation()
- Handles .input() chaining naturally
- Deduplicates via seen Set on procedurePath

Result: 245 routes from 30 routers (was 41), 256 total after re-index.
(cherry picked from commit 49edf953e93e6b67b77932e866fcbfb8d089b1f3)

* feat(mcp): expose tRPC chains via context/query tools

Eight fixes to make the tRPC route->procedure->workflow->sub-workflow chain
visible through the standard MCP tools (context, query) that AI agents use,
instead of requiring raw Cypher queries.

- A context: order incoming/outgoing CALLS test-last, raise LIMIT 30->100
- B query: batched ENTRY_POINT_OF lookup, surface route URL on processes
- C query: mark process_symbols entry point with is_entry_point=true
- D entry-point-scoring: skip UTILITY_PATTERNS (get*/set*) penalty for
  symbols in tRPC router files so framework boost (3.0x) is preserved
- E fts-schema: index Route nodes so /trpc/* URLs are keyword-searchable
- F tools: bump max_symbols default 10->25 to fit procedure->workflow chain
- G context: optional chain_depth (0-3) param walks CALLS edges in both
  directions and returns layered chain field
- H LadybugDB bug workaround: WHERE r.type IN [...] silently drops edges
  on relationship properties; replace with OR chains (7 occurrences in
  local-backend.ts, pdg-impact.ts, graph-queries.ts)

Validated on Jurialis: setProviderCap procedure now appears as caller of
setProviderCapWorkflow, /trpc/cabinet.setProviderCap Route is searchable,
chain_depth=3 returns the layered call graph.

(cherry picked from commit c24df0adce91e80f191a5c5d2e8b14e9da677366)

* feat(mcp): surface is_entry_point + routes in context, raise query limit

context() is the mandatory pre-edit tool (AGENTS.md). Until now an agent
had to issue a separate query() call just to learn whether its symbol is
a process entry point or which HTTP route it handles. These two fields
make context() self-sufficient for the bmad-dev flow.

- context: query STEP_IN_PROCESS now returns p.entryPointId; new
  ENTRY_POINT_OF lookup attributes routes only from processes where the
  symbol is the entry point (middle steps do not own the route) plus any
  direct Route->symbol handler edge (tRPC procedures outside any Process)
- context: new top-level is_entry_point (true only) and routes[] fields
  ({url, method?}), emitted only when non-empty to keep the diff additive
- query: raise default limit 5->10 so dense domains (tRPC action router
  with 20 chains, data-export with 9 flows) surface more of their flow
  set without an explicit param

(cherry picked from commit 004f5b0ba985fcef3dfac5e67a2f2f7262184215)

* docs(mcp): document chain_depth, routes, and entry-point flag; neutralize examples in comments

* fix(mcp): address code-review findings on tRPC entry points, queries, and dispatch

- entry-point scoring: optional-chain framework detection and normalize
  path separators before router-pattern matching (P1 crash on .js routers)
- tRPC extractor: emit controllerName as null (callers resolve via
  lookupClassByName; a router object stringified as name corrupted lookups)
- route dedup: key seenRoutes by method:url so GET/POST pairs survive
- legacy TS queries: drop curried-call patterns (arity-corrupting for
  overload resolution) and require non-array callee on pair member calls
- registry-primary TS query: mirror the non-array-callee predicate on the
  new pair member-expression patterns (fixes query compile error)
- group tool port: forward chain_depth into per-tool context args

* fix(mcp): nested tRPC router paths, controller-less route binding, query chain_depth

- trpc extractor: brace-depth nesting stack composes sibling router paths (bare router() import style included); merge-prefix dot normalization; strict publicProcedure allowlist gate; drop phantom router metadata

- call-processor: bind controller-less tRPC routes to same-file handlers via exact single-match symbol lookup; ambiguous or missing handlers skipped

- query/group query: optional chain_depth (0-3) enriches ranked processes with their context chain; fix _computeContextChain layer docstring

- tree-sitter TS/JS scope queries capture string-key function declarations; tRPC pattern scoring narrowed to server router files

- parse-cache schema bump to v103 for extractor and route-binding changes

- add trpc route extractor regression tests (9 cases incl. sibling nesting and merge prefix)

* Address PR review feedback (#3339)

Close remaining review threads: compact tRPC keys, comment-safe terminals,
quoted-key identifier HOC captures, group-query default alignment, and
LadybugDB label scalars on context chains.

* chore(autofix): apply prettier + eslint fixes via /autofix command

* test: pin PARSE_CACHE schema bump to 103 (PR #3339 review fixes)

* fix(ingestion): bind same-name tRPC handlers and surface HANDLES_ROUTE

Same-name procedures resolve by startLine, the extractor keeps nested paths
through multiline schemas, and context/query UNION HANDLES_ROUTE for leaf
procedures that never become Process entries.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3339)

Clamp group query bounds, drop HOC pair false positives, emit tRPC
terminal lines and hyphenated quoted keys, cap chain BFS concurrency,
and restrict the router utility exemption to accessor names.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3339)

Score JS/JSX tRPC routers like TypeScript, ignore inner db.query and
unrelated .merge calls, mask regex braces, and assert clamp tests invoke
the query mock.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(autofix): apply prettier + eslint fixes via /autofix command

* fix(ingestion,mcp): emit-side HOC callback guards + MCP schema prettier (PR #3339 round 2)

* Address PR review feedback (#3339)

Treat `/` after return-style keywords as a regex, drop the synthetic
appRouter path prefix, and bind the create mutation via an inline callback.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3339)

Qualify query() docs so is_entry_point is promised only when the entry
symbol is among the search hits.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3339)

Emit tRPC terminals only at procedure paren depth, drop the filename
prefix on bare appRouter = router(), mask regex after if (), and cap
groupQuery member fan-out.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3339)

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3339)

De-duplicate context-chain BFS nodes reached through multiple frontier
edges, and bind tRPC identifier callbacks (`.mutation(handler)`) to the
handler symbol instead of the procedure key.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3339)

Apply LIMIT 50 after DISTINCT neighbors in the context-chain BFS, and
treat the official lowercase `procedure` builder as a tRPC procedure key.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3339)

Keep the later duplicate tRPC object-literal key so route binding matches
the handler JavaScript actually ships.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3339)

Compose same-file identifier-mounted tRPC subrouters so admin: adminRouter
emits the live admin.list path instead of an unprefixed /trpc/list.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3339)

Memoize tRPC identifier-mount paths so a depth-N chain stays linear, and
gate it with the build-free measure.mjs / baselines.json harness.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3339)

Compose identifier mounts without phantom /trpc URLs, bind wrapped and
multiline handlers, fail-close missing bench budgets, and reject query
page bounds before search.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3339)

Reject advertised MCP query bounds in group mode and chain_depth
instead of clamping or accepting non-integers.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3339)

Reject invalid groupContext chain_depth and ignore non-callable
same-file tRPC handler candidates.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3339)

Memoize live tRPC mount paths so the depth-N chain bench stays linear,
and render invalid group/MCP bounds without throwing.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3339)

Keep t.merge('prefix.', namedRouter) procedures live by recording a
zero-hop mount so the unmounted-router drop does not hide them.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3339)

Recognize type-annotated `const adminRouter: AppRouter = t.router(`
bindings so identifier mounts still compose.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-21 09:44:42 +01:00
Twisted_Arrow
dcb2eb5cb4
fix(swift): resolve imports from Package.swift targets, not path segments (#3105)
Some checks are pending
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Gitleaks / gitleaks (push) Waiting to run
Publish / Classify release event (push) Waiting to run
Publish / RC guard (marker + release-PR skip) (push) Blocked by required conditions
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-cli) (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-web) (push) Waiting to run
* fix(swift): match repeated SPM target prefixes

* test(swift): cover repeated SPM target prefixes

* test(swift): cover valid prefix before later partial match

* docs(swift): clarify target grouping parity scope

* docs(swift): clarify target grouping parity scope

* docs(swift): clarify target grouping parity scope

* fix(swift): resolve imports from Package.swift targets, not path segments

Stop fabricating IMPORTS from import Foundation onto a same-named folder.
Declare modules from Package.swift when the manifest is usable; keep
Sources/* for grouping and fail-open folder resolve minus SDK names.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(swift): keep empty Package.swift declarations and nested .target() deps external

An inferred Sources/* folder is grouping-only. A dependency .target(name:) is not a module. Treat both as unresolved so import Foundation cannot bind to a decoy folder.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(swift): keep implicit IMPORTS intra-group and gate linear Package.swift resolve

@_exported must not paint sibling files as implicit imports. A dedicated
bench pins declaration-only resolve and (t_4n/t_n)/4 linearity.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3105)

Honor member-only @_exported imports, skip comments while scanning
Package.swift factories, fail-open mixed helper-built target lists, and
block CoreData/CoreGraphics decoy folders on the inferred path.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3105)

Match path: "." as the package root, skip block-commented Package.swift
factories, read import kind from the clause only, and skip capture tests
when the optional Swift grammar is missing.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ci): scan Swift import-kind without nested regex backtracking

CodeQL js/redos flagged the comment-skipping IMPORT_KIND_RE; a linear walk keeps the same kind tokens.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ci): linear Package.swift factory scan and gate Swift context

parseSwiftPackageManifest re-walked every prefix for comments (O(n²) in factory count). Resume the scan and cover nested factories in one pass. Wire Swift into the import-target context arm now that resolveImportTarget is 5-arg.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3105)

Tighten Package.swift and import-text scanners: skip comments/strings, reject escapes, treat ident + [ as incomplete, and drop the unused factory-comment wrapper.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ci): prettier the @_exported availability fixture

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3105)

Judge Package.swift completeness from Package(...)'s own targets: argument instead of raw-text regexes, nest block comments when reading an import kind, and strip leading ./ from declared target paths.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3105)

Collect Package.swift factories only from Package(targets: [...]), fail-open on computed array elements, and treat // after a label colon as a comment.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3105)

Ignore stray factories when Package() exists but omits targets:.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3105)

Require the Package-scan seen box so the always-true undefined guard goes away.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-19 15:50:31 +01:00
Gergő Magyar
56feb85c97
chore: compile first-party packages with TypeScript 7 (#3311)
Some checks are pending
CodeQL / Analyze (python) (push) Waiting to run
Publish / RC guard (marker + release-PR skip) (push) Blocked by required conditions
Trivy Image Scan / Trivy (gitnexus-web) (push) Waiting to run
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
Gitleaks / gitleaks (push) Waiting to run
Publish / Classify release event (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-cli) (push) Waiting to run
* fix(web): drop TypeScript 7-incompatible tsconfig paths

Remove baseUrl and the dead ../shared include so web project references typecheck under TypeScript 7.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(cli): parse TypeScript with a TypeScript 6 API package

Keep AST guards working after the named typescript package becomes 7, which no longer ships the Compiler API.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(lint): pin root TypeScript to the 6 API package

Give typescript-eslint a TypeScript 6 peer so syntax-only lint still installs after CLI and web move to TypeScript 7.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(deps): compile first-party packages with TypeScript 7.0.2

Unify CLI and web on the same native compiler line as gitnexus-shared so typecheck and emit no longer split 5.x versus 7.x.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs(ci): describe parent TypeScript 7 as the shared compiler

Stop saying web compiles shared with TypeScript 5 now that the parent lockfile is 7.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ci): compile shared from parent TypeScript on Vercel and skill-evolution

Stop isolated npm installs in gitnexus-shared so those paths do not pull a second TypeScript 7 optional-platform tree.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: record TypeScript 7 typecheck and Dependabot major-split policy

Keep contributor typecheck commands, and stop Dependabot from bumping shared onto a different TypeScript major than CLI and web.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lint): pin root TypeScript to 5.9 so npm ci satisfies eslint peers

typescript-eslint 8 peers typescript below 6.0.0, so the typescript6 alias made quality lint npm ci fail with ERESOLVE.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(cli): drop the TypeScript 6 Compiler API package

TypeScript 7.0 has no classic createProgram surface, so parse-only
guards now use Babel and Mode 4 uses the TypeScript 7 Checker.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: align contributor setup with parent TypeScript 7 compile

Stop telling clones to npm-install gitnexus-shared; CI and Vercel already emit that package from a parent lib/tsc.js shim.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(web): typecheck React JSX on TypeScript 7 with explicit DOM libs

TypeScript 7 no longer implies DOM or auto-includes @types, so the web app must declare React/JSX settings while Vite keeps plugin-react.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test: pin Vercel --include=dev and share parse-only string helpers

Production npm ci omits the web TypeScript unless --include=dev is on that install. Move staticStringValue next to the other Babel walk helpers so CLI help and contract tests share one source.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(autofix): apply prettier + eslint fixes via /autofix command

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-09-17 22:16:00 +01:00
dependabot[bot]
d2a43e33df
chore(deps): bump the codeql-action group with 3 updates (#3305)
Bumps the codeql-action group with 3 updates: [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/analyze](https://github.com/github/codeql-action) and [github/codeql-action/upload-sarif](https://github.com/github/codeql-action).


Updates `github/codeql-action/init` from 4.37.9 to 4.38.0
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](cdf488f595...b96794f015)

Updates `github/codeql-action/analyze` from 4.37.9 to 4.38.0
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](cdf488f595...b96794f015)

Updates `github/codeql-action/upload-sarif` from 4.37.9 to 4.38.0
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](cdf488f595...b96794f015)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.38.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: codeql-action
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.38.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: codeql-action
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.38.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: codeql-action
...

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-09-17 07:44:09 +01:00
Abhinav Pandey
0ede6ae501
fix(rust): respect Cargo target boundaries in name fallback (#3294)
* fix(rust): respect Cargo target boundaries in name fallback

* fix(rust): read Cargo sources through validated file descriptors

* fix(rust): require matching imports for crate-root guesses

* fix(rust): require Cargo root identity for cross-target imports

* fix(rust): enforce Cargo identity across fallback imports

* fix(rust): keep Cargo membership on typical derive/macros (#3294)

Abort only genuine unknown expansion, ignore Cargo artifact layouts instead of every `target` path segment, and require a covering import for unanswered crate-root name fallback so #3253 still holds on ordinary Rust sources.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(rust): gate Cargo target membership in CI (#3253)

Add a parse-dispatch-rounds-style bench so derive/macro abort, target-path globs, and superlinear membership walks fail in CI instead of staying graph-invisible.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(rust): verify Cargo macro and re-export evidence

* style(bench): format Cargo membership benchmark

* fix(rust): require imports for cross-file root guesses

---------

Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-16 11:36:07 +01:00
Gergő Magyar
ac9a4e9abd
fix(embeddings): keep ONNX off the install and analyze critical path (#3287)
Some checks are pending
Gitleaks / gitleaks (push) Waiting to run
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Publish / RC guard (marker + release-PR skip) (push) Blocked by required conditions
Publish / ci (push) Blocked by required conditions
Publish / Publish to npm (push) Blocked by required conditions
Trivy Image Scan / Trivy (gitnexus-cli) (push) Waiting to run
Publish / Classify release event (push) Waiting to run
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(embeddings): isolate local ONNX inference in a child_process sidecar

The analyze parent must not load onnxruntime-node. Fork a sidecar for
vectors only and reap it on worker exit; keep Ladybug writes in-process.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(embeddings): share the sidecar client across MCP, serve, and sync

Query hosts now use the core façade instead of a second in-process ONNX
embedder. Search skips an empty table, sync reaps beside closeLbug, and
ready means the stack is resolvable rather than a warm singleton.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(embeddings): refuse Intel Mac and unloadable prefix before npm heal

Analyze, sync, install, and the sidecar client now consult the platform
blocker before forking or downloading the optional stack. HTTP stays the
escape hatch; wasm is not treated as a rescue.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(embeddings): take the ONNX stack off default npm install

Pins live in gitnexusEmbeddingStack. embeddings install writes prefix
overrides before npm spawn. Leftover 1.6.12 package-first trees are residual.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(publish): drop grammar source from the published tarball

Every vendored grammar has 6/6 prebuilds, so files ships those plus
Leiden and FTS instead of parser.c. First ship stays above 80 MiB.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(embeddings): match MCP missing-stack warn to the R20 copy

Default install no longer calls the stack optional, so the once-per-backend
stderr assertion must look for the new lead line.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(review): bound sidecar death, cancel writes, and publish-file guards

Init-time native crashes no longer respawn a child on every query. Local
embedBatch honors AbortSignal after sidecar return, MCP query() surfaces
vector-lane degradation, disconnect always reaps, and the grammar prepack
guard checks files globs instead of on-disk prebuilds.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(embeddings): share runtime preflight and sidecar reap helpers

Analyze and embeddings-sync used the same blocker/prefix/install gate
with different error routing. One assessment keeps those paths aligned
without changing CLI vs thrown-error behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3287)

Keep a reaped sidecar from resetting its replacement, wait for dispose,
tighten the publish-files guard, and stop assuming a leftover ONNX tree in CI.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address remaining PR review feedback (#3287)

Clear the sidecar reap timeout, add init IPC slack, and isolate embeddings-sync tests from HTTP-mode env.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(embeddings): unstub globals after sidecar HTTP-mode tests

Keep a leaked fetch stub from failing assertions out of later tests in the same file.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(embeddings): pin sidecar success cases off darwin/x64

The runtime blocker reads the real process platform before the fork mock, so local-success tests must not inherit an Intel Mac host.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address remaining PR review feedback (#3287)

Keep vector degradation per query, treat leftover Intel-Mac stacks as not ready, and document that the CLI image no longer ships ONNX.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Simplify embedding sidecar shutdown and search hot paths

Drop redundant sidecar reaps and unused child helpers, and run FTS alongside semantic search.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address remaining PR review feedback (#3287)

Share HF attempt parsing with the sidecar init deadline, abort embed waits without killing the child, and restore last init options on recreate.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address remaining PR review feedback (#3287)

Treat sub-1 HF attempt env values as invalid, and drop leaked sidecar waiters when IPC send throws.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address remaining PR review feedback (#3287)

Keep sidecar init on a shared chain; each waiter can abort only its own wait.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(ci): declare embedding-table existence probe as unordered LIMIT

The empty-table skip in semanticSearch is existence-only; declare it so the #2787 determinism guard stops failing coverage shard 3/3.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-15 12:11:47 +01:00
Gergő Magyar
21a52af1d4
fix(lbug): ship FTS per-platform and recover in-place native aborts (#3274)
* fix(lbug): pin Ladybug core so Dependabot cannot ship a skewed FTS artifact

The extension version is a separate upstream constant. Ignore daily core bumps and fail the pairing gate when the committed manifest does not name the installed core.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): make doctor and CI FTS gates resolve the packaged artifact

Doctor and the REQUIRE_FTS file gates still treated an empty ~/.lbdb as
unavailable, which would turn three CI jobs red once analyze stops
installing into that tree.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): name native-abort and tuple-missing so analyze cannot mis-advise

The CLI summary's trailing else treated every unknown skip reason as a
missing extension. New crash and platform causes must get their own
remedies, not a network-install hint.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): delete the dead read-path FTS index create

ensureFTSIndex had no production callers and swallowed read-only
CREATE_FTS_INDEX failures, which hid the only signal that a reader
tried to write.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): vendor per-platform FTS artifacts so analyze needs no host install

Keyword search depended on a CDN fetch into ~/.lbdb. Shipping the five
published tuples inside the package makes air-gapped and ignore-scripts
installs load the same artifact the publish gate checksums.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): load the packaged FTS artifact before any network install

Analyze still required a CDN fetch into ~/.lbdb even when the package
already shipped the file. FTS now path-loads the vendored tuple first
and records source labels so a later truncated home copy cannot steal
the diagnosis.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): diagnose a core/extension version skew instead of a missing runtime

A structurally valid FTS artifact whose path version disagrees with the
packaged pin must name both versions, not prescribe VC++ or OpenSSL.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): stamp an FTS phase so repair stays usable after an in-place abort

A native CREATE_FTS_INDEX abort leaves no skip reason; the next run infers
it from the dirty flag, and --repair-fts must not treat that phase as a
half-written graph.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): park an in-place FTS crash WAL without wiping the graph

An FTS abort after a successful checkpoint must reopen the live index on
macOS, Windows, and Linux. Staging never parks the live WAL; readers keep
today's large-WAL refusal.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): refuse read-only opens of an FTS-poisoned WAL

MCP and serve cannot repair a leftover in-place abort. Fail before the
native open and name --repair-fts, on macOS, Windows, and Linux.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): name a vendor-neutral Windows OpenSSL prerequisite

OQ1 is unanswered here so GitNexus does not ship OpenSSL DLLs. Windows
FTS now asks for a system OpenSSL 3 runtime instead of Git Bash PATH.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(lbug): inject the FTS vendor root and redact it on HTTP and MCP

Path-loaded artifacts no longer vary with HOME. Tests pass an injected
vendor tree and assert search warnings never leak a filesystem path.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs(lbug): document load-only as the global FTS install default

Analyze still overrides to auto. Packaged per-platform artifacts load
before any network install on macOS, Windows, and Linux.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs(lbug): format the FTS install-policy README table

Prettier does not run on Markdown in pre-commit, so the U10 table wrap
needs its own formatting commit.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): skip FTS CREATE after a persisted native abort

A recovered analyze run was retrying CREATE_FTS_INDEX from skipReason
alone. Keep that skip until --repair-fts, fail closed on unsupported
tuples, and honor the checkpoint warrant for park/repair.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): honor checkpoint flushed warrant and align FTS tests with packaged vendor

A no-op CHECKPOINT must not satisfy the FTS park warrant, and CI still asserted HOME-only FTS isolation after analyze started path-LOADing the packaged artifact.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(lbug): accept a nonempty incremental write set in the #2790 recovery check

FTS-phase recovery can incremental-add files (changed=0, added=1). That is not the #2790 empty-diff wipe skip.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): compare FTS home versions to the core pin and tighten the publish filename gate

Ladybug's ~/.lbdb/extension directory is the runtime/core version; treating it as the artifact version false-diagnosed skew. The publish guard now rejects a path-escaping filename the same way the fetch script does.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(lbug): seed FTS e2e fixtures from the packaged vendor artifact

A machine with no ~/.lbdb copy should still run the vendor-survivorship cases; the seed no longer depends on HOME or a network install.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3274)

Keep in-place FTS abort evidence after persist so a second CREATE abort
cannot fail-open readers, and close the CLI, loader, embed, and e2e gaps
the review called out.

Note: full npm test hit Ladybug worker-pool startup failures under memory
pressure; tsc and 180 targeted unit tests passed.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3274)

Run the vendored-path symlink guard on the OS matrix, put e2e HOME
fixtures on Ladybug's real extension layout, pin the embed crash-WAL
gate before the writable open, and let analyze writers park through
missing-shadow recovery.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(lbug): keep --repair-fts CI green after vendored-first FTS

Never-installed warning fixtures must not inspect a packaged vendor binary, and a failed dirty restamp must not abort an otherwise successful --repair-fts run.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(cli): give the #1169 analyze e2e the same 90s Windows budget as its sibling

The first #1169 persist-meta case was still on a 60s spawn/it budget and was killed banner-only on windows-latest after the FTS warning fixture no longer failed the shard first.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(ci): reweight Windows shards after the FTS e2e grew

Vendored-first HOME fixtures pushed fts-extension-e2e to ~6 minutes on windows-latest, so the old 146s weight packed it with skills-e2e and blew the 20-minute watchdog.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-14 08:52:24 +01:00
Aakash Sharma
d1a3edd333
perf(mcp): avoid O(n) git spawns on tools/list with many repos (#3259)
* perf(mcp): avoid O(n) git spawns on tools/list with many repos

toolSchemaRepoRequirements called listAllowedRepos -> listRepos -> checkStalenessAsync for every registered repo. With ~200 repos, this spawned 200 parallel git rev-list processes on every tools/list discovery call, causing a ~30s delay.

Replaced with a lightweight countRepos() method that reads the registry file once without spawning git processes, preserving full staleness checks for list_repos.

* Address PR review feedback (#3259)

Count the validated registry in countRepos so tools/list cannot advertise a multi-repo schema for ENOENT ghosts, and update the unrestricted listTools mocks to that contract.

Note: pre-existing failure in update-notice.test.ts (missing dist/cli/mcp.js) not addressed by this PR.
Co-authored-by: Cursor <cursoragent@cursor.com>

* Add a 200-repo tools/list bench for the countRepos path (#3259)

Pin the #1363 comparison (listRepos git fan-out vs validated countRepos / listTools) in-tree so the latency claim can be re-run. Also drop the change-history comments on the unrestricted schema arm.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Gate the tools/list bench with baselines and CI --check (#3259)

Exact registry/schema floors plus ratio timing, no millisecond ceiling, so restoring listRepos() on tools/list fails CI.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Address PR review feedback (#3259)

Align unrestricted tools/list schema flags with the refreshed registry snapshot, and make the bench reject a non-positive BENCH_REPS and isolate fixtures by N.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(autofix): apply prettier + eslint fixes via /autofix command

* Address PR review feedback (#3259)

Isolate the tools/list bench from GITNEXUS_MCP_READ_ONLY and create the default fixture under mkdtempSync so CodeQL is not looking at a predictable /tmp path.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-09-11 13:18:28 +01:00
Parafee41
c9b391357e
fix(group): detect function-local Python imports (#3254)
* fix(group): detect function-local Python imports

* fix(group): parse Python imports structurally

* fix(group): use safe Python parser wrapper

* fix(group): isolate Python parse timeouts

* fix(group): skip recovered indented Python from-imports

Error-recovered trees can promote unclosed-docstring lookalikes into
real import_from_statement nodes. Drop those indented imports, bound
file reads, log parse timeouts, and add fingerprint floors for the
tree-sitter scan.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(autofix): apply prettier + eslint fixes via /autofix command

---------

Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-09-11 06:23:52 +00:00
Yahoo
0edf9ce0ff
fix(ruby): guard gem requires with dependency metadata (#3096)
* docs(plans): add ruby gem require boundary plan

* fix(ruby): guard gem requires with dependency metadata

* fix(ruby): scope gem sources by manifest

* test(ruby): model resolved lockfile specs

* fix(ruby): stop local gem suffix fallthrough

* docs: remove Ruby resolution plan

* test(ruby): gate gem resolution correctness and scaling

* test(ruby): align gem benchmark baseline with ratio gates

* Address PR review feedback (#3096)

- Strip a trailing .rb so local and external gem prefix matching follows Ruby's optional-suffix require.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-10 16:04:11 +01:00
dependabot[bot]
1909af4e04
chore(deps): bump softprops/action-gh-release from 3.0.2 to 3.0.3 (#3248)
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 3.0.2 to 3.0.3.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](3d0d9888cb...efb35369e0)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-version: 3.0.3
  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>
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
2026-09-10 07:18:56 +01:00
dependabot[bot]
d80230a564
chore(deps): bump docker/setup-qemu-action from 4.2.0 to 4.3.0 (#3249)
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 4.2.0 to 4.3.0.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](96fe6ef7f3...1f40c72289)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-version: 4.3.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-09-10 06:00:15 +01:00