Commit graph

5 commits

Author SHA1 Message Date
samuel mbabhazi
9772bcd24f
feat(api_impact): list the callers of the requesting function as indirect consumers (#3720)
* feat(api_impact): list the callers of the requesting function as indirect consumers

The FETCHES edge is file-level, so api_impact saw only the file that sends
the request. The files that call its request function never mention the URL
and were missing from the report (#3644).

The edge's reason now names the callables whose spans contain the request
sites, one `|via:<id>` field each, under the containment rule the R3-6 sink
set already uses; that rule moves into EnclosingCallableIndex so both stay
one. Several sites of one file for one route now share the edge instead of
colliding on its id. api_impact follows the CALLS edges into those callables
one level up and reports the callers as `indirectConsumers`, apart from the
direct consumers and outside the risk level. Direct consumer files and the
handler file are left out. An index built before the attribution carries no
field. Expo navigation sites carry their real line so they attribute to the
component that contains them.

Closes #3644

* fix(api_impact): attribute a request site by its AST enclosing callable

A helper defined on the line of the request has the smaller span, so the
line-only lookup named it and the callers of the real requesting function
vanished from indirectConsumers. The parser now records the enclosing
callable of each fetch site and of each wrapper call (through the call's
position), and attribution prefers that identity; the span lookup remains
for sites found by text scan. The same preference applies to the R3-6 sink
set. A real analyze of the fixture followed by api_impact pins the helper
case and the wrapper case.

* test(bench): rebaseline receiver resolution for the indirect-consumers fixture

The api-impact-indirect-consumers fixture adds three receiver-unresolved
sites to the corpus: two `.then(...)` calls on the untyped return of
`fetch(...)` and of the local wrapper `apiFetch(...)`, and one
`req.query.path` read inside an inline Express handler with an untyped
`req`. Call drops 138 -> 140, reads 30 -> 31, all kinds 168 -> 171. No
shape-arm state and no existing site changed.

* fix(api_impact): preserve module-scope request attribution

Keep AST-confirmed module scope distinct from missing attribution for direct
fetches, HTTP clients, and wrapper calls. Prevent overlapping callable spans
from inventing indirect consumers or process sinks.

Preserve span fallback for callable forms the generic identity walk cannot
name. Add eight regression cases, including real analyze/api_impact coverage.
Rebaseline receiver-resolution counts for the two then calls and one property
read added by this PR's existing fixtures; shape expectations are unchanged.

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
2026-10-25 18:29:09 +00:00
Abhigyan Patwari
9df1e98350
fix(routes): scope inline Express handlers and report api_impact lower bound (#3643)
* fix(routes): scope inline Express handlers and report api_impact lower bound

Inline Express handlers are anonymous Function nodes named by position, but
the route facts only recorded a handler name for bare identifiers. Routes
with inline handlers therefore had no handlerSymbolId: every route in a file
got the union of its handlers' response keys and every flow starting there.

Record the positional name for inline handlers, read response keys from the
resolved handler when a file registers several routes, and let processes
link exactly by handlerSymbolId as they already do for named handlers.

Count, per route, the files that pass its URL to a callee not proven to be
a fetch wrapper (excluding proven consumers and the route's own file). The
count is stored as Route.unverifiedConsumers; api_impact reports
epistemic: 'lower-bound' with that count when it is non-zero. Older indexes
without the column fall back to the previous query.

Closes #3488

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

* refactor(routes): match unverified consumers once per URL

Memoize route matching per distinct fetch URL, skip the proven-consumer
scan when no unproven call matches a route, and build the Route query's
optional columns from a list instead of two booleans.

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

* fix(group): keep inline handlers attributed to their registrar

Inline Express handlers now carry their positional Function name in the
route facts so ingestion can resolve a handlerSymbolId. Group HTTP
contracts read the same facts, but that name is a graph identity rather
than a symbol name the contract lookup can match, so the provider lost its
enclosing-registrar attribution. Ignore the name for inline handlers there.

Rebaseline the two bench guards the branch moved:
- emit-persistence: route.csv gains the header-only unverifiedConsumers
  field; stripping it restores the prior fingerprint exactly.
- receiver-resolution: the new fixture's req.query.path read on an untyped
  inline-handler parameter adds one receiver-unresolved read (191 -> 192).

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

---------

Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
2026-10-20 17:44:08 +01:00
Copilot
962f22482b
feat(cli): Fingerprint indexed repos by remote URL to detect sibling-clone graph drift (#982)
Some checks are pending
CI / quality (push) Waiting to run
CI / tests (push) Waiting to run
CI / e2e (push) Waiting to run
CI / scope-parity (push) Waiting to run
CI / Save PR Metadata (push) Blocked by required conditions
CI / CI Gate (push) Blocked by required conditions
Release Candidate / Check if release candidate should run (push) Waiting to run
Release Candidate / ci (push) Blocked by required conditions
Release Candidate / Publish release candidate to npm (push) Blocked by required conditions
Release Candidate / Build & Push RC Docker images (push) Blocked by required conditions
* Initial plan

* feat: detect sibling-clone graph drift via remote URL fingerprint

Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/e5decb67-7fec-40e7-b2a1-b5e94a0d393f

Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>

* test: address review feedback — fake commit, same-commit case, regex docs

Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/e5decb67-7fec-40e7-b2a1-b5e94a0d393f

Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>

* fix(mcp): address review feedback — CI green, perf, dead branch, one-shot test

Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/cc2259f7-94e4-4243-aaa9-e03b7c632d32

* Merge branch 'main' into copilot/fix-single-path-indexing-issue

Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/5840b3dd-e879-4854-a067-d1622bec2634

Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>

* Merge branch 'main' into copilot/fix-single-path-indexing-issue

Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/9025262f-4dd4-4774-8f32-e14434100004

Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>

* style: prettier format run-analyze.ts after merge with main

Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/a7be18dd-102f-4a7b-ac56-53fbd414fe3b

Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>

* test: realpath both sides of cwdGitRoot assertion for Windows 8.3 short-name compat

Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/b2a1c6a3-e454-4b87-b0e4-69d7c0d9a51b

Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>

* fix(test): use path-agnostic assertion for cwdGitRoot on Windows (#1015)

git rev-parse --show-toplevel returns long path names on Windows
while os.tmpdir() returns 8.3 short names. fs.realpathSync does not
expand short names, so exact path comparison always fails on Windows
CI runners. Replace with behavioral assertions instead.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <copilot-swe-agent[bot]@users.noreply.github.com>
Co-authored-by: Gergő Magyar <gergomagyar@icloud.com>
Co-authored-by: evolution <wjc163@sina.cn>
2026-04-21 21:58:54 +01:00
Gergő Magyar
bf09eab95b
feat: configure prettier with pre-commit hook (#563)
* feat: configure prettier with pre-commit hook integration

Add prettier, lint-staged, and prettier-plugin-tailwindcss at the repo
root with husky pre-commit hook integration. Moves husky from
gitnexus/ to root package.json for reliable hook installation.

- Root package.json with prepare/format/format:check scripts
- .prettierrc with endOfLine:lf and tailwindStylesheet for TW v4
- .prettierignore excluding fixtures, vendor, generated, *.d.ts, *.md
- .gitattributes enforcing LF line endings for Windows consistency
- Pre-commit hook uses direct node_modules/.bin/ paths (no npx)

* style: apply prettier formatting to entire codebase

One-time bulk format. No logic changes.
Use .git-blame-ignore-revs to skip this commit in git blame.

* chore: add .git-blame-ignore-revs for prettier format commit

* perf: pre-commit hook runs only tests related to staged files

Use vitest --related to scope test execution to tests that import
the changed files, instead of running the full suite on every commit.

* perf: remove vitest from pre-commit hook, keep in CI only

Pre-commit now runs lint-staged + tsc only. Tests run in CI
(ci-tests.yml) where they belong — keeps commits fast.

* ci: add prettier format check to quality workflow

PRs will now fail if code isn't formatted with prettier.
2026-03-28 14:58:04 +00:00
marxo126
c437acf6bb
feat: deep flow detection — consumer access tracking, middleware chains, error shapes, api_impact tool (#482) 2026-03-23 22:13:48 +00:00