gitnexus 1.6.8-rc.2 → 1.6.8-rc.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -0
- package/dist/_shared/scope-resolution/parsed-file.d.ts +21 -0
- package/dist/_shared/scope-resolution/parsed-file.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/symbol-definition.d.ts +4 -0
- package/dist/_shared/scope-resolution/symbol-definition.d.ts.map +1 -1
- package/dist/cli/ai-context.js +1 -0
- package/dist/cli/analyze-config.js +40 -0
- package/dist/cli/analyze.d.ts +22 -0
- package/dist/cli/analyze.js +36 -6
- package/dist/cli/clean.d.ts +1 -0
- package/dist/cli/clean.js +43 -1
- package/dist/cli/eval-server.js +43 -0
- package/dist/cli/help-i18n.js +11 -0
- package/dist/cli/i18n/en.d.ts +13 -0
- package/dist/cli/i18n/en.js +13 -0
- package/dist/cli/i18n/resources.d.ts +26 -0
- package/dist/cli/i18n/zh-CN.d.ts +13 -0
- package/dist/cli/i18n/zh-CN.js +13 -0
- package/dist/cli/index.js +19 -0
- package/dist/cli/list.js +12 -0
- package/dist/cli/optional-grammars.d.ts +6 -8
- package/dist/cli/optional-grammars.js +8 -11
- package/dist/cli/skill-gen.js +1 -0
- package/dist/cli/status.js +26 -5
- package/dist/cli/tool.d.ts +12 -1
- package/dist/cli/tool.js +41 -1
- package/dist/core/embeddings/embedder.js +4 -0
- package/dist/core/embeddings/embedding-pipeline.js +27 -16
- package/dist/core/embeddings/onnxruntime-common-resolver.d.ts +6 -0
- package/dist/core/embeddings/onnxruntime-common-resolver.js +130 -0
- package/dist/core/graph/import-cycles.d.ts +10 -0
- package/dist/core/graph/import-cycles.js +103 -0
- package/dist/core/group/extractors/grpc-patterns/proto.js +10 -6
- package/dist/core/group/extractors/http-patterns/java.js +3 -50
- package/dist/core/group/extractors/http-patterns/kotlin.js +7 -7
- package/dist/core/group/extractors/include-extractor.js +7 -7
- package/dist/core/ingestion/cfg/cfg-builder.d.ts +64 -0
- package/dist/core/ingestion/cfg/cfg-builder.js +129 -0
- package/dist/core/ingestion/cfg/collect.d.ts +30 -0
- package/dist/core/ingestion/cfg/collect.js +34 -0
- package/dist/core/ingestion/cfg/control-flow-context.d.ts +97 -0
- package/dist/core/ingestion/cfg/control-flow-context.js +113 -0
- package/dist/core/ingestion/cfg/emit.d.ts +144 -0
- package/dist/core/ingestion/cfg/emit.js +315 -0
- package/dist/core/ingestion/cfg/reaching-defs.d.ts +90 -0
- package/dist/core/ingestion/cfg/reaching-defs.js +364 -0
- package/dist/core/ingestion/cfg/traversal-result.d.ts +20 -0
- package/dist/core/ingestion/cfg/traversal-result.js +2 -0
- package/dist/core/ingestion/cfg/types.d.ts +231 -0
- package/dist/core/ingestion/cfg/types.js +13 -0
- package/dist/core/ingestion/cfg/visitors/typescript-harvest.d.ts +144 -0
- package/dist/core/ingestion/cfg/visitors/typescript-harvest.js +1032 -0
- package/dist/core/ingestion/cfg/visitors/typescript.d.ts +66 -0
- package/dist/core/ingestion/cfg/visitors/typescript.js +584 -0
- package/dist/core/ingestion/language-provider.d.ts +36 -2
- package/dist/core/ingestion/languages/c-cpp.js +11 -4
- package/dist/core/ingestion/languages/cpp/arity-metadata.js +6 -2
- package/dist/core/ingestion/languages/cpp/captures.js +24 -1
- package/dist/core/ingestion/languages/cpp/query.js +23 -0
- package/dist/core/ingestion/languages/java.js +3 -0
- package/dist/core/ingestion/languages/kotlin/query.js +3 -2
- package/dist/core/ingestion/languages/kotlin.js +5 -1
- package/dist/core/ingestion/languages/typescript.js +5 -0
- package/dist/core/ingestion/method-extractors/configs/c-cpp.js +6 -13
- package/dist/core/ingestion/method-extractors/generic.js +1 -0
- package/dist/core/ingestion/method-types.d.ts +2 -0
- package/dist/core/ingestion/model/symbol-table.d.ts +1 -0
- package/dist/core/ingestion/model/symbol-table.js +1 -0
- package/dist/core/ingestion/parsing-processor.js +22 -0
- package/dist/core/ingestion/pipeline-phases/parse-impl.js +18 -1
- package/dist/core/ingestion/pipeline-phases/routes.js +64 -14
- package/dist/core/ingestion/pipeline.d.ts +57 -0
- package/dist/core/ingestion/route-extractors/spring-shared.d.ts +50 -0
- package/dist/core/ingestion/route-extractors/spring-shared.js +80 -0
- package/dist/core/ingestion/route-extractors/spring.d.ts +35 -0
- package/dist/core/ingestion/route-extractors/spring.js +136 -0
- package/dist/core/ingestion/scope-extractor.js +3 -0
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +12 -0
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +145 -24
- package/dist/core/ingestion/scope-resolution/pipeline/phase.js +6 -0
- package/dist/core/ingestion/scope-resolution/pipeline/reconcile-ownership.js +43 -3
- package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +21 -0
- package/dist/core/ingestion/scope-resolution/pipeline/run.js +207 -0
- package/dist/core/ingestion/scope-resolution/resolution-outcome.d.ts +1 -1
- package/dist/core/ingestion/taint/emit.d.ts +124 -0
- package/dist/core/ingestion/taint/emit.js +204 -0
- package/dist/core/ingestion/taint/match.d.ts +153 -0
- package/dist/core/ingestion/taint/match.js +278 -0
- package/dist/core/ingestion/taint/path-codec.d.ts +134 -0
- package/dist/core/ingestion/taint/path-codec.js +190 -0
- package/dist/core/ingestion/taint/propagate.d.ts +216 -0
- package/dist/core/ingestion/taint/propagate.js +664 -0
- package/dist/core/ingestion/taint/site-safety.d.ts +29 -0
- package/dist/core/ingestion/taint/site-safety.js +98 -0
- package/dist/core/ingestion/taint/source-sink-config.d.ts +94 -23
- package/dist/core/ingestion/taint/source-sink-config.js +11 -11
- package/dist/core/ingestion/taint/source-sink-registry.d.ts +6 -4
- package/dist/core/ingestion/taint/source-sink-registry.js +6 -4
- package/dist/core/ingestion/taint/typescript-model.d.ts +38 -0
- package/dist/core/ingestion/taint/typescript-model.js +102 -0
- package/dist/core/ingestion/utils/method-props.js +1 -0
- package/dist/core/ingestion/workers/clone-safety.d.ts +109 -0
- package/dist/core/ingestion/workers/clone-safety.js +465 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +11 -0
- package/dist/core/ingestion/workers/parse-worker.js +70 -53
- package/dist/core/ingestion/workers/post-result.d.ts +22 -0
- package/dist/core/ingestion/workers/post-result.js +87 -0
- package/dist/core/ingestion/workers/result-merge.d.ts +20 -0
- package/dist/core/ingestion/workers/result-merge.js +43 -0
- package/dist/core/ingestion/workers/worker-pool.d.ts +15 -0
- package/dist/core/ingestion/workers/worker-pool.js +33 -16
- package/dist/core/lbug/lbug-adapter.d.ts +19 -0
- package/dist/core/lbug/lbug-adapter.js +56 -1
- package/dist/core/run-analyze.d.ts +87 -0
- package/dist/core/run-analyze.js +280 -25
- package/dist/core/tree-sitter/parser-loader.js +5 -4
- package/dist/core/tree-sitter/vendored-grammars.d.ts +39 -0
- package/dist/core/tree-sitter/vendored-grammars.js +57 -0
- package/dist/mcp/core/embedder.js +4 -0
- package/dist/mcp/local/local-backend.d.ts +86 -2
- package/dist/mcp/local/local-backend.js +657 -27
- package/dist/mcp/resources.js +1 -0
- package/dist/mcp/tools.d.ts +9 -0
- package/dist/mcp/tools.js +109 -0
- package/dist/server/analyze-launch.d.ts +29 -0
- package/dist/server/analyze-launch.js +137 -0
- package/dist/server/analyze-upload.d.ts +33 -0
- package/dist/server/analyze-upload.js +123 -0
- package/dist/server/analyze-worker-ipc.d.ts +58 -0
- package/dist/server/analyze-worker-ipc.js +16 -0
- package/dist/server/analyze-worker.d.ts +17 -1
- package/dist/server/analyze-worker.js +7 -1
- package/dist/server/api.js +46 -140
- package/dist/server/git-clone.d.ts +1 -0
- package/dist/server/git-clone.js +1 -1
- package/dist/server/middleware.d.ts +11 -0
- package/dist/server/middleware.js +27 -0
- package/dist/server/upload-ingest.d.ts +56 -0
- package/dist/server/upload-ingest.js +276 -0
- package/dist/server/upload-paths.d.ts +31 -0
- package/dist/server/upload-paths.js +51 -0
- package/dist/server/upload-sweep.d.ts +20 -0
- package/dist/server/upload-sweep.js +57 -0
- package/dist/storage/branch-index.d.ts +52 -0
- package/dist/storage/branch-index.js +65 -0
- package/dist/storage/git.d.ts +11 -0
- package/dist/storage/git.js +28 -0
- package/dist/storage/parse-cache.d.ts +22 -1
- package/dist/storage/parse-cache.js +32 -10
- package/dist/storage/repo-manager.d.ts +122 -10
- package/dist/storage/repo-manager.js +162 -21
- package/hooks/antigravity/gitnexus-antigravity-hook.cjs +42 -8
- package/hooks/claude/gitnexus-hook.cjs +36 -8
- package/hooks/claude/hook-db-lock-probe.cjs +123 -2
- package/package.json +4 -2
- package/scripts/assert-publish-grammar-coverage.cjs +31 -0
- package/scripts/build-tree-sitter-grammars.cjs +16 -10
- package/skills/gitnexus-guide.md +11 -0
- package/vendor/tree-sitter-c/package.json +1 -1
- package/vendor/tree-sitter-dart/package.json +1 -1
- package/vendor/tree-sitter-kotlin/package.json +1 -1
- package/vendor/tree-sitter-proto/package.json +1 -1
- package/vendor/tree-sitter-swift/package.json +1 -1
- package/web/assets/{agent-CKPMqImC.js → agent-ay4LD70X.js} +1 -1
- package/web/assets/{architectureDiagram-UL44E2DR-D1EXI0zA.js → architectureDiagram-UL44E2DR-Dc-viYhd.js} +1 -1
- package/web/assets/{chunk-LCXTWHL2-Dfmux4m1.js → chunk-LCXTWHL2-4rpojOyj.js} +1 -1
- package/web/assets/{chunk-RG4AUYOV-CAkzcoRj.js → chunk-RG4AUYOV-BnOy944n.js} +1 -1
- package/web/assets/{classDiagram-KGZ6W3CR-Bv93af_b.js → classDiagram-KGZ6W3CR-Bsgpy98Q.js} +1 -1
- package/web/assets/{classDiagram-v2-72OJOZXJ-CLfEqHUa.js → classDiagram-v2-72OJOZXJ-D5atDGjc.js} +1 -1
- package/web/assets/{diagram-3NCE3AQN-BqAtKUpW.js → diagram-3NCE3AQN-Cz1OEMVi.js} +1 -1
- package/web/assets/{diagram-GF46GFSD-CaBG6n6o.js → diagram-GF46GFSD-CWYwzfP8.js} +1 -1
- package/web/assets/{diagram-QXG6HAR7-CZ-O3rcV.js → diagram-QXG6HAR7-DtBObr8L.js} +1 -1
- package/web/assets/{diagram-WEQXMOUZ-P4lSL4GH.js → diagram-WEQXMOUZ-BUV44Ov_.js} +1 -1
- package/web/assets/{erDiagram-L5TCEMPS-QN2eEP1e.js → erDiagram-L5TCEMPS-Ds9s-sRF.js} +1 -1
- package/web/assets/{flowDiagram-H6V6AXG4-CXbXImlN.js → flowDiagram-H6V6AXG4-CupStHQb.js} +1 -1
- package/web/assets/index-COMMmbxW.css +2 -0
- package/web/assets/{index-CG6q8eTs.js → index-Do8AE5yF.js} +85 -85
- package/web/assets/{infoDiagram-3YFTVSEB-DmLICZx1.js → infoDiagram-3YFTVSEB-DPTXSbgu.js} +1 -1
- package/web/assets/{ishikawaDiagram-BNXS4ZKH-6LKOvBfp.js → ishikawaDiagram-BNXS4ZKH-CeK-Qhet.js} +1 -1
- package/web/assets/{kanban-definition-75IXJCU3-DgDi9oJT.js → kanban-definition-75IXJCU3-D4tx6QQ-.js} +1 -1
- package/web/assets/{mindmap-definition-2TDM6QVE-CwR5sBB-.js → mindmap-definition-2TDM6QVE-Bcto_kGa.js} +1 -1
- package/web/assets/{pieDiagram-CU6KROY3-By8g6f6B.js → pieDiagram-CU6KROY3-DPIeBTG6.js} +1 -1
- package/web/assets/{requirementDiagram-JXO7QTGE-7oDcJ1_J.js → requirementDiagram-JXO7QTGE-DDGXjVKO.js} +1 -1
- package/web/assets/{sequenceDiagram-VS2MUI6T-FySeKCUy.js → sequenceDiagram-VS2MUI6T-BzDqpcVW.js} +1 -1
- package/web/assets/{stateDiagram-7D4R322I-CB2nABwH.js → stateDiagram-7D4R322I-Bx__als3.js} +1 -1
- package/web/assets/{stateDiagram-v2-36443NZ5-COBGd2RL.js → stateDiagram-v2-36443NZ5-QqOh2yO-.js} +1 -1
- package/web/assets/{timeline-definition-O6YCAMPW-Ds2CnVZK.js → timeline-definition-O6YCAMPW-C1eogTOG.js} +1 -1
- package/web/assets/{vennDiagram-MWXL3ELB-DUIEwXWp.js → vennDiagram-MWXL3ELB-D20F4rSW.js} +1 -1
- package/web/assets/{wardleyDiagram-CUQ6CDDI-DEiFPQih.js → wardleyDiagram-CUQ6CDDI-BeBHg7ST.js} +1 -1
- package/web/assets/{xychartDiagram-N2JHSOCM-BUbayhST.js → xychartDiagram-N2JHSOCM-CdOWeoNI.js} +1 -1
- package/web/index.html +2 -2
- package/scripts/materialize-vendor-grammars.cjs +0 -97
- package/web/assets/index-BKWA-m7o.css +0 -2
package/README.md
CHANGED
|
@@ -436,6 +436,26 @@ After scope resolution, analyze prunes inert block-local value symbols (a functi
|
|
|
436
436
|
|
|
437
437
|
Programmatic callers can pass `keepLocalValueSymbols: true` in `PipelineOptions` instead of setting the env var.
|
|
438
438
|
|
|
439
|
+
### Hook augmentation/notifications are silently skipped
|
|
440
|
+
|
|
441
|
+
The Claude Code / Antigravity hooks intentionally stay **silent** on normal skip
|
|
442
|
+
paths so strict hook runners (e.g. Codex `PreToolUse`) never see unexpected
|
|
443
|
+
output. A search may not be augmented — or a stale-index reminder may not appear
|
|
444
|
+
on stderr — when the GitNexus MCP server owns the repo DB, when the DB-lock probe
|
|
445
|
+
times out and fails closed, or when the index is already current.
|
|
446
|
+
|
|
447
|
+
To see why a hook skipped, set `GITNEXUS_DEBUG=1` and re-run the action — the hook
|
|
448
|
+
writes the reason (e.g. `[GitNexus] augment skipped: MCP server owns DB`) and the
|
|
449
|
+
stale-index hint to its stderr:
|
|
450
|
+
|
|
451
|
+
```bash
|
|
452
|
+
GITNEXUS_DEBUG=1 <your command> # surfaces hook skip/diagnostic reasons on stderr
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
Only `GITNEXUS_DEBUG=1` and `GITNEXUS_DEBUG=true` enable diagnostics; every other
|
|
456
|
+
value (including `0` and `false`) is treated as off. Diagnostics go to stderr
|
|
457
|
+
only — the hook's structured stdout (the JSON the agent consumes) is unaffected.
|
|
458
|
+
|
|
439
459
|
## Privacy
|
|
440
460
|
|
|
441
461
|
- All processing happens locally on your machine
|
|
@@ -96,5 +96,26 @@ export interface ParsedFile {
|
|
|
96
96
|
* side effects — the contract default) leave this undefined.
|
|
97
97
|
*/
|
|
98
98
|
readonly captureSideChannel?: unknown;
|
|
99
|
+
/**
|
|
100
|
+
* Per-function control-flow graphs for this file (#2081 M1, PDG/taint
|
|
101
|
+
* substrate). A DISTINCT field from {@link captureSideChannel} — different
|
|
102
|
+
* producer, consumer, and lifecycle: the worker builds it from the
|
|
103
|
+
* tree-sitter AST via `LanguageProvider.cfgVisitor` (only on a `--pdg` run),
|
|
104
|
+
* and scope-resolution emits BasicBlock nodes + CFG edges from it while the
|
|
105
|
+
* disk-backed ParsedFile store is still live (it is NOT a capture-time
|
|
106
|
+
* marker the resolver restores into module maps). Kept separate so a future
|
|
107
|
+
* change to either channel's shape invalidates independently.
|
|
108
|
+
*
|
|
109
|
+
* Shared / ingestion code treats this as opaque (`unknown`) per AGENTS.md.
|
|
110
|
+
* Concretely it is a `readonly FunctionCfg[]` (see
|
|
111
|
+
* `core/ingestion/cfg/types.ts`) — plain JSON-serializable data (no AST
|
|
112
|
+
* refs, no class instances) so it round-trips through the parse cache and
|
|
113
|
+
* the `parsedfile-store` (whose interning reviver keys on `nodeId`, which
|
|
114
|
+
* these blocks/edges deliberately lack).
|
|
115
|
+
*
|
|
116
|
+
* Optional: `undefined` on non-`--pdg` runs and for languages with no
|
|
117
|
+
* `cfgVisitor` — the default for every run today.
|
|
118
|
+
*/
|
|
119
|
+
readonly cfgSideChannel?: unknown;
|
|
99
120
|
}
|
|
100
121
|
//# sourceMappingURL=parsed-file.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parsed-file.d.ts","sourceRoot":"","sources":["../../src/scope-resolution/parsed-file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oDAAoD;IACpD,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IAClC,QAAQ,CAAC,aAAa,EAAE,SAAS,YAAY,EAAE,CAAC;IAChD;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAChD,QAAQ,CAAC,cAAc,EAAE,SAAS,aAAa,EAAE,CAAC;IAClD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"parsed-file.d.ts","sourceRoot":"","sources":["../../src/scope-resolution/parsed-file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oDAAoD;IACpD,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IAClC,QAAQ,CAAC,aAAa,EAAE,SAAS,YAAY,EAAE,CAAC;IAChD;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAChD,QAAQ,CAAC,cAAc,EAAE,SAAS,aAAa,EAAE,CAAC;IAClD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAEtC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;CACnC"}
|
|
@@ -54,6 +54,10 @@ export interface SymbolDefinition {
|
|
|
54
54
|
* Currently used by C++ overload ranking to exclude explicit constructors
|
|
55
55
|
* from implicit user-defined conversion candidates. */
|
|
56
56
|
isExplicit?: boolean;
|
|
57
|
+
/** True when the callable is declared unavailable (for example C++ `= delete`).
|
|
58
|
+
* Unavailable callables still participate in overload selection, but a
|
|
59
|
+
* selected unavailable target must suppress edge emission. */
|
|
60
|
+
isDeleted?: boolean;
|
|
57
61
|
/** Links Method/Constructor/Property to owning Class/Struct/Trait nodeId */
|
|
58
62
|
ownerId?: string;
|
|
59
63
|
/** #1982/#1993: bridge-held enclosing-namespace path (e.g. `NS1`, `Outer.Inner`)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"symbol-definition.d.ts","sourceRoot":"","sources":["../../src/scope-resolution/symbol-definition.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,WAAW,kBAAkB;IACjC,wFAAwF;IACxF,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,gBAAgB,GAAG,SAAS,CAAC;IACjE,4CAA4C;IAC5C,WAAW,EAAE,OAAO,GAAG,YAAY,GAAG,YAAY,GAAG,SAAS,GAAG,SAAS,CAAC;IAC3E,4EAA4E;IAC5E,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,SAAS,CAAC;IAChB;;+FAE2F;IAC3F,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;iHAC6G;IAC7G,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC;uFACmF;IACnF,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B;4FACwF;IACxF,oBAAoB,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAC5C,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gGAAgG;IAChG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gGAAgG;IAChG,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B;;;;;yEAKqE;IACrE,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;4DAEwD;IACxD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;iEAO6D;IAC7D,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B"}
|
|
1
|
+
{"version":3,"file":"symbol-definition.d.ts","sourceRoot":"","sources":["../../src/scope-resolution/symbol-definition.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,WAAW,kBAAkB;IACjC,wFAAwF;IACxF,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,gBAAgB,GAAG,SAAS,CAAC;IACjE,4CAA4C;IAC5C,WAAW,EAAE,OAAO,GAAG,YAAY,GAAG,YAAY,GAAG,SAAS,GAAG,SAAS,CAAC;IAC3E,4EAA4E;IAC5E,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,SAAS,CAAC;IAChB;;+FAE2F;IAC3F,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;iHAC6G;IAC7G,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC;uFACmF;IACnF,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B;4FACwF;IACxF,oBAAoB,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAC5C,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gGAAgG;IAChG,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gGAAgG;IAChG,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B;;;;;yEAKqE;IACrE,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;4DAEwD;IACxD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;mEAE+D;IAC/D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;iEAO6D;IAC7D,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B"}
|
package/dist/cli/ai-context.js
CHANGED
|
@@ -136,6 +136,7 @@ This project is indexed by GitNexus as **${projectName}**${noStats ? '' : ` (${s
|
|
|
136
136
|
- **MUST warn the user** if impact analysis returns HIGH or CRITICAL risk before proceeding with edits.
|
|
137
137
|
- When exploring unfamiliar code, use \`query({query: "concept"})\` to find execution flows instead of grepping. It returns process-grouped results ranked by relevance.
|
|
138
138
|
- When you need full context on a specific symbol — callers, callees, which execution flows it participates in — use \`context({name: "symbolName"})\`.
|
|
139
|
+
- For security review, \`explain({target: "fileOrSymbol"})\` lists taint findings (source→sink flows; needs \`analyze --pdg\`).
|
|
139
140
|
|
|
140
141
|
## Never Do
|
|
141
142
|
|
|
@@ -63,6 +63,7 @@ const KEY_SPECS = {
|
|
|
63
63
|
skipContextFiles: { target: 'skipAgentsMd', kind: 'boolean' },
|
|
64
64
|
skipAiContext: { target: 'skipAgentsMd', kind: 'boolean' },
|
|
65
65
|
skipSkills: { target: 'skipSkills', kind: 'boolean' },
|
|
66
|
+
pdg: { target: 'pdg', kind: 'boolean' },
|
|
66
67
|
indexOnly: { target: 'indexOnly', kind: 'boolean' },
|
|
67
68
|
stats: { target: 'stats', kind: 'boolean' },
|
|
68
69
|
noStats: { target: 'stats', kind: 'boolean-negate' },
|
|
@@ -78,6 +79,12 @@ const KEY_SPECS = {
|
|
|
78
79
|
embeddingBatchSize: { target: 'embeddingBatchSize', kind: 'numeric-string' },
|
|
79
80
|
embeddingSubBatchSize: { target: 'embeddingSubBatchSize', kind: 'numeric-string' },
|
|
80
81
|
embeddingDevice: { target: 'embeddingDevice', kind: 'string' },
|
|
82
|
+
// #1589/#1852 residual — extra fetch-wrapper function names to treat as HTTP
|
|
83
|
+
// consumers. The auto-detector only flags functions that call the bare global
|
|
84
|
+
// `fetch()`; a wrapper built on axios / a custom client, or named outside the
|
|
85
|
+
// built-in convention set, is otherwise invisible to route_map consumers.
|
|
86
|
+
// Listing it here adds it to the cross-file consumer scan.
|
|
87
|
+
fetchWrappers: { target: 'fetchWrappers', kind: 'string-array' },
|
|
81
88
|
};
|
|
82
89
|
/** Top-level container key for the nested form; not itself an `AnalyzeOptions` field. */
|
|
83
90
|
const NESTED_KEY = 'analyze';
|
|
@@ -195,6 +202,39 @@ const normalizeValue = (kind, value, key) => {
|
|
|
195
202
|
}
|
|
196
203
|
return trimmed;
|
|
197
204
|
}
|
|
205
|
+
case 'string-array': {
|
|
206
|
+
// Generic shared validator — `source` already names the config key, so
|
|
207
|
+
// messages here stay key-agnostic (no fetch-wrapper coupling in the
|
|
208
|
+
// shared normalizer; #1589/#1852 review F7).
|
|
209
|
+
if (!Array.isArray(value)) {
|
|
210
|
+
throw new GitNexusRcError(`${source} must be an array of strings.`);
|
|
211
|
+
}
|
|
212
|
+
const names = [];
|
|
213
|
+
for (const item of value) {
|
|
214
|
+
if (typeof item !== 'string') {
|
|
215
|
+
throw new GitNexusRcError(`${source} entries must all be strings.`);
|
|
216
|
+
}
|
|
217
|
+
const trimmed = item.trim();
|
|
218
|
+
if (!trimmed) {
|
|
219
|
+
throw new GitNexusRcError(`${source} entries must not be empty.`);
|
|
220
|
+
}
|
|
221
|
+
assertNoHiddenChars(trimmed, source);
|
|
222
|
+
// Values may be interpolated into a RegExp downstream. Restrict to
|
|
223
|
+
// identifier / member-access shapes so a config value can never smuggle
|
|
224
|
+
// regex metacharacters into a consumer.
|
|
225
|
+
if (!/^[A-Za-z_$][A-Za-z0-9_$.]*$/.test(trimmed)) {
|
|
226
|
+
throw new GitNexusRcError(`${source} entry "${trimmed}" must be an identifier or member name ` +
|
|
227
|
+
`(letters, digits, _, $, . — e.g. "client.get").`);
|
|
228
|
+
}
|
|
229
|
+
names.push(trimmed);
|
|
230
|
+
}
|
|
231
|
+
if (names.length === 0) {
|
|
232
|
+
throw new GitNexusRcError(`${source} must list at least one string.`);
|
|
233
|
+
}
|
|
234
|
+
// De-duplicate and cap to a sane bound so a pathological config cannot
|
|
235
|
+
// blow up the consumer scan's alternation.
|
|
236
|
+
return Array.from(new Set(names)).slice(0, 100);
|
|
237
|
+
}
|
|
198
238
|
case 'numeric-string': {
|
|
199
239
|
// Mirror Commander's contract: these options reach the existing CLI
|
|
200
240
|
// validation as strings. Accept a JSON number or a string; normalize to a
|
package/dist/cli/analyze.d.ts
CHANGED
|
@@ -37,6 +37,12 @@ export interface AnalyzeOptions {
|
|
|
37
37
|
verbose?: boolean;
|
|
38
38
|
/** Skip AGENTS.md and CLAUDE.md gitnexus block updates. */
|
|
39
39
|
skipAgentsMd?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Build the control-flow-graph / PDG substrate (#2081 M1). Opt-in; off by
|
|
42
|
+
* default. Threaded to both the worker (CFG build) and scope-resolution
|
|
43
|
+
* (BasicBlock/CFG emit).
|
|
44
|
+
*/
|
|
45
|
+
pdg?: boolean;
|
|
40
46
|
/**
|
|
41
47
|
* Stats inclusion in AGENTS.md and CLAUDE.md.
|
|
42
48
|
*
|
|
@@ -58,6 +64,14 @@ export interface AnalyzeOptions {
|
|
|
58
64
|
* before being threaded into the generated AGENTS.md / CLAUDE.md content.
|
|
59
65
|
*/
|
|
60
66
|
defaultBranch?: string;
|
|
67
|
+
/**
|
|
68
|
+
* Index-branch selector (#2106). From `--branch`. Distinct from
|
|
69
|
+
* `defaultBranch` (cosmetic base_ref): this routes the index to a per-branch
|
|
70
|
+
* slot. NOT sourced from `.gitnexusrc` — the `.gitnexusrc` `branch` key is an
|
|
71
|
+
* alias for `defaultBranch` and must not change index placement. Defaults to
|
|
72
|
+
* the checked-out branch inside `runFullAnalysis` when omitted.
|
|
73
|
+
*/
|
|
74
|
+
branch?: string;
|
|
61
75
|
/** Pure index mode: skip all file injection (AGENTS.md, CLAUDE.md, skills). */
|
|
62
76
|
indexOnly?: boolean;
|
|
63
77
|
/** Index the folder even when no .git directory is present. */
|
|
@@ -93,6 +107,14 @@ export interface AnalyzeOptions {
|
|
|
93
107
|
embeddingBatchSize?: string;
|
|
94
108
|
embeddingSubBatchSize?: string;
|
|
95
109
|
embeddingDevice?: string;
|
|
110
|
+
/**
|
|
111
|
+
* Extra fetch-wrapper function names to treat as HTTP consumers (#1589/#1852
|
|
112
|
+
* residual). Supplied via `.gitnexusrc` `fetchWrappers: [...]`. Threaded into
|
|
113
|
+
* the routes phase, where the cross-file consumer scan unions them with the
|
|
114
|
+
* auto-detected `fetch()` wrappers so a custom/axios-based wrapper named
|
|
115
|
+
* outside the built-in convention still produces `route_map` consumers.
|
|
116
|
+
*/
|
|
117
|
+
fetchWrappers?: string[];
|
|
96
118
|
}
|
|
97
119
|
/**
|
|
98
120
|
* Whether the post-index skill step should run.
|
package/dist/cli/analyze.js
CHANGED
|
@@ -551,6 +551,21 @@ const analyzeCommandImpl = async (inputPath, cliOptions) => {
|
|
|
551
551
|
return;
|
|
552
552
|
}
|
|
553
553
|
}
|
|
554
|
+
// Validate the index-branch selector (#2106) the same way, so a malformed
|
|
555
|
+
// `--branch` exits before any expensive analysis starts. Capture the TRIMMED
|
|
556
|
+
// return so a whitespace-padded value (e.g. " feature" from shell completion)
|
|
557
|
+
// normalizes before the checked-out-branch mismatch guard and slug — otherwise
|
|
558
|
+
// it would false-reject on-branch or create a ghost index when detached.
|
|
559
|
+
if (cliOptions?.branch !== undefined) {
|
|
560
|
+
try {
|
|
561
|
+
cliOptions.branch = validateBranchName(cliOptions.branch, '--branch');
|
|
562
|
+
}
|
|
563
|
+
catch (err) {
|
|
564
|
+
cliError(` ${err instanceof Error ? err.message : String(err)}\n`);
|
|
565
|
+
process.exitCode = 1;
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
554
569
|
// ── Load .gitnexusrc and merge: CLI flags override config (#243) ───
|
|
555
570
|
// Parse/validate before the progress bar so a malformed config produces an
|
|
556
571
|
// actionable error and exits before any expensive analysis starts.
|
|
@@ -826,9 +841,15 @@ const analyzeCommandImpl = async (inputPath, cliOptions) => {
|
|
|
826
841
|
skipGit: options.skipGit,
|
|
827
842
|
skipAgentsMd,
|
|
828
843
|
skipSkills,
|
|
844
|
+
// CFG/PDG substrate opt-in (#2081 M1) — threaded to both sinks downstream.
|
|
845
|
+
pdg: options.pdg === true,
|
|
829
846
|
// Resolved default branch (CLI > .gitnexusrc > auto-detect > "main")
|
|
830
847
|
// threaded into the generated regression-compare example (#243).
|
|
831
848
|
defaultBranch: resolvedDefaultBranch,
|
|
849
|
+
// Index-branch selector (#2106). Read straight from the CLI flag (not
|
|
850
|
+
// the .gitnexusrc-merged options) so the cosmetic defaultBranch config
|
|
851
|
+
// can never change index placement. Undefined → auto-detect in pipeline.
|
|
852
|
+
branch: cliOptions?.branch,
|
|
832
853
|
// commander.js `.option('--no-stats', …)` registers the flag as
|
|
833
854
|
// `options.stats` (boolean, default true; `false` when the user
|
|
834
855
|
// passed --no-stats). Reading `options.noStats` here returns
|
|
@@ -845,6 +866,9 @@ const analyzeCommandImpl = async (inputPath, cliOptions) => {
|
|
|
845
866
|
// GITNEXUS_WORKER_POOL_SIZE env mutation. `undefined` defers to the
|
|
846
867
|
// env / auto-formula fallback inside the pipeline.
|
|
847
868
|
workerPoolSize,
|
|
869
|
+
// Extra fetch-wrapper names from `.gitnexusrc` (#1589/#1852 residual);
|
|
870
|
+
// forwarded to the routes phase consumer scan.
|
|
871
|
+
fetchWrappers: options.fetchWrappers,
|
|
848
872
|
}, {
|
|
849
873
|
onProgress: (_phase, percent, message) => {
|
|
850
874
|
updateBar(percent, message);
|
|
@@ -863,13 +887,19 @@ const analyzeCommandImpl = async (inputPath, cliOptions) => {
|
|
|
863
887
|
// preserving the rest of the block (incl. --skills community rows). No-op
|
|
864
888
|
// when the value already matches, so a routine up-to-date run is silent
|
|
865
889
|
// (#1996 tri-review P2).
|
|
890
|
+
// Only refresh the repo-root AGENTS.md/CLAUDE.md base_ref for the
|
|
891
|
+
// PRIMARY/flat index (#2106 R2). A non-primary branch's up-to-date
|
|
892
|
+
// analyze must not churn the committed AGENTS.md — this mirrors the
|
|
893
|
+
// in-pipeline `if (!placement.branch)` gate around generateAIContextFiles.
|
|
866
894
|
let baseRefRefreshed = [];
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
895
|
+
if (result.isPrimaryBranch !== false) {
|
|
896
|
+
try {
|
|
897
|
+
const { refreshBaseRefLine } = await import('./ai-context.js');
|
|
898
|
+
baseRefRefreshed = (await refreshBaseRefLine(repoPath, resolvedDefaultBranch, { skipAgentsMd })).files;
|
|
899
|
+
}
|
|
900
|
+
catch {
|
|
901
|
+
/* best-effort — never fail the fast path over a context refresh */
|
|
902
|
+
}
|
|
873
903
|
}
|
|
874
904
|
clearInterval(elapsedTimer);
|
|
875
905
|
process.removeListener('SIGINT', sigintHandler);
|
package/dist/cli/clean.d.ts
CHANGED
package/dist/cli/clean.js
CHANGED
|
@@ -7,10 +7,52 @@
|
|
|
7
7
|
import fs from 'fs/promises';
|
|
8
8
|
import path from 'path';
|
|
9
9
|
import { logger } from '../core/logger.js';
|
|
10
|
-
import { findRepo, unregisterRepo, listRegisteredRepos, assertSafeStoragePath, UnsafeStoragePathError, } from '../storage/repo-manager.js';
|
|
10
|
+
import { findRepo, unregisterRepo, listRegisteredRepos, assertSafeStoragePath, getStoragePaths, removeBranchIndex, UnsafeStoragePathError, } from '../storage/repo-manager.js';
|
|
11
11
|
import { cleanQuarantinedMissingShadowWals, inspectLbugSidecars, listQuarantinedMissingShadowWals, } from '../core/lbug/sidecar-recovery.js';
|
|
12
12
|
import { t } from './i18n/index.js';
|
|
13
13
|
export const cleanCommand = async (options) => {
|
|
14
|
+
// --branch <name>: remove a single non-primary branch's index (#2106 R7).
|
|
15
|
+
// Resolve against the RECORDED branches[] summary (never by slugging the
|
|
16
|
+
// user's raw input, which can disagree with the index-time-sanitized label).
|
|
17
|
+
if (options?.branch) {
|
|
18
|
+
const cwd = process.cwd();
|
|
19
|
+
const repo = await findRepo(cwd);
|
|
20
|
+
if (!repo) {
|
|
21
|
+
console.log(t('clean.notFoundHere'));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const entries = await listRegisteredRepos();
|
|
25
|
+
const entry = entries.find((e) => path.resolve(e.path) === path.resolve(repo.repoPath));
|
|
26
|
+
const summary = entry?.branches?.find((b) => b.branch === options.branch);
|
|
27
|
+
if (!summary) {
|
|
28
|
+
console.log(t('clean.branchNotIndexed', { branch: options.branch }));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const { storagePath, lbugPath } = getStoragePaths(repo.repoPath, summary.branch);
|
|
32
|
+
const branchDir = path.dirname(lbugPath);
|
|
33
|
+
// Safety guard: the target MUST live under <repo>/.gitnexus/branches/.
|
|
34
|
+
// assertSafeStoragePath only validates the flat `<repo>/.gitnexus`, so this
|
|
35
|
+
// is a dedicated branches-sub-dir check before any destructive fs.rm.
|
|
36
|
+
const branchesRoot = path.join(storagePath, 'branches') + path.sep;
|
|
37
|
+
if (!branchDir.startsWith(branchesRoot)) {
|
|
38
|
+
logger.error(`Refusing to clean branch index outside .gitnexus/branches: ${branchDir}`);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (!options.force) {
|
|
42
|
+
console.log(t('clean.deleteBranch', { branch: summary.branch, path: branchDir }));
|
|
43
|
+
console.log(`\n${t('common.runForceConfirm')}`);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
await fs.rm(branchDir, { recursive: true, force: true });
|
|
48
|
+
await removeBranchIndex(repo.repoPath, summary.branch);
|
|
49
|
+
console.log(t('clean.deletedBranch', { branch: summary.branch }));
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
logger.error({ err }, 'Failed to delete branch index:');
|
|
53
|
+
}
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
14
56
|
if (options?.lbugSidecars) {
|
|
15
57
|
const cwd = process.cwd();
|
|
16
58
|
const repo = await findRepo(cwd);
|
package/dist/cli/eval-server.js
CHANGED
|
@@ -155,7 +155,43 @@ export function formatImpactResult(result) {
|
|
|
155
155
|
const direction = result.direction;
|
|
156
156
|
const byDepth = result.byDepth || {};
|
|
157
157
|
const total = result.impactedCount || 0;
|
|
158
|
+
// #2129 — an ambiguous bare name must not print the "isolated / safe to
|
|
159
|
+
// refactor" headline. Surface the per-candidate blast radius + the maximum,
|
|
160
|
+
// mirroring formatContextResult, so the real impact under whichever symbol the
|
|
161
|
+
// caller meant is visible on the text surface, not just in the JSON.
|
|
162
|
+
if (result.status === 'ambiguous') {
|
|
163
|
+
// #2129 review F11 — report the FULL match count (`totalCandidates`), not the
|
|
164
|
+
// truncated `candidates[]` length; note when the candidate list is capped.
|
|
165
|
+
const shown = result.candidates?.length ?? 0;
|
|
166
|
+
const total = result.totalCandidates ?? shown;
|
|
167
|
+
const countPhrase = total > shown ? `${total} symbols (showing ${shown})` : `${total} symbols`;
|
|
168
|
+
const lines = [
|
|
169
|
+
`${target?.name || '?'}: AMBIGUOUS — ${countPhrase} share this name. ` +
|
|
170
|
+
`Max blast radius ${result.maxImpactedCount ?? 0} (${result.maxRisk ?? 'UNKNOWN'} risk). ` +
|
|
171
|
+
`Disambiguate with --uid for one authoritative result:`,
|
|
172
|
+
];
|
|
173
|
+
for (const c of result.candidates || []) {
|
|
174
|
+
lines.push(` ${c.kind} ${c.name} → ${c.filePath}:${c.line || '?'} ` +
|
|
175
|
+
`[${c.impactedCount ?? 0} ${direction}, risk ${c.risk ?? 'UNKNOWN'}] (uid: ${c.uid})`);
|
|
176
|
+
}
|
|
177
|
+
// #2129 review F1 — a failed per-candidate probe makes the max a lower bound.
|
|
178
|
+
if (result.partialProbe) {
|
|
179
|
+
lines.push(' ⚠️ One or more candidate probes failed — max blast radius / risk are lower bounds.');
|
|
180
|
+
}
|
|
181
|
+
return lines.join('\n');
|
|
182
|
+
}
|
|
158
183
|
if (total === 0) {
|
|
184
|
+
// #1858 — "isolated" is a confident claim. If an interface / indirection
|
|
185
|
+
// boundary is on the path, the true count is a lower bound, not zero;
|
|
186
|
+
// callers binding via DI / dynamic dispatch were not traced. Say so instead.
|
|
187
|
+
if (result.epistemic === 'lower-bound') {
|
|
188
|
+
const lines = [
|
|
189
|
+
`${target?.name || '?'}: no direct ${direction} dependencies traced, but this is a LOWER BOUND — unresolved indirection on the path (actual impact may be higher):`,
|
|
190
|
+
];
|
|
191
|
+
for (const b of result.boundaries || [])
|
|
192
|
+
lines.push(` • ${b}`);
|
|
193
|
+
return lines.join('\n');
|
|
194
|
+
}
|
|
159
195
|
return `${target?.name || '?'}: No ${direction} dependencies found. This symbol appears isolated.`;
|
|
160
196
|
}
|
|
161
197
|
const lines = [];
|
|
@@ -164,6 +200,13 @@ export function formatImpactResult(result) {
|
|
|
164
200
|
if (result.partial) {
|
|
165
201
|
lines.push('⚠️ Partial results — graph traversal was interrupted. Deeper impacts may exist.');
|
|
166
202
|
}
|
|
203
|
+
// #1858 — an interface / indirection boundary on the path makes this a lower
|
|
204
|
+
// bound; surface it so the count is not read as exhaustive.
|
|
205
|
+
if (result.epistemic === 'lower-bound') {
|
|
206
|
+
lines.push('⚠️ Lower bound — unresolved indirection on the path (callers binding via DI / dynamic dispatch are not traced; actual impact may be higher):');
|
|
207
|
+
for (const b of result.boundaries || [])
|
|
208
|
+
lines.push(` • ${b}`);
|
|
209
|
+
}
|
|
167
210
|
lines.push('');
|
|
168
211
|
const depthLabels = {
|
|
169
212
|
1: 'WILL BREAK (direct)',
|
package/dist/cli/help-i18n.js
CHANGED
|
@@ -27,6 +27,7 @@ const COMMAND_DESCRIPTION_KEYS = {
|
|
|
27
27
|
impact: 'help.command.impact.description',
|
|
28
28
|
cypher: 'help.command.cypher.description',
|
|
29
29
|
'detect-changes': 'help.command.detectChanges.description',
|
|
30
|
+
check: 'help.command.check.description',
|
|
30
31
|
'eval-server': 'help.command.evalServer.description',
|
|
31
32
|
group: 'help.command.group.description',
|
|
32
33
|
'group create': 'help.command.group.create.description',
|
|
@@ -69,6 +70,7 @@ const OPTION_DESCRIPTION_KEYS = {
|
|
|
69
70
|
'uninstall|-f, --force': 'help.option.uninstall.force',
|
|
70
71
|
'clean|-f, --force': 'help.option.force.confirmation',
|
|
71
72
|
'clean|--all': 'help.option.clean.all',
|
|
73
|
+
'clean|--branch <name>': 'help.option.clean.branch',
|
|
72
74
|
'clean|--lbug-sidecars': 'help.option.clean.lbugSidecars',
|
|
73
75
|
'remove|-f, --force': 'help.option.force.confirmation',
|
|
74
76
|
'wiki|-f, --force': 'help.option.wiki.force',
|
|
@@ -89,16 +91,19 @@ const OPTION_DESCRIPTION_KEYS = {
|
|
|
89
91
|
'publish|--id <owner/repo>': 'help.option.publish.id',
|
|
90
92
|
'publish|--skip-git': 'help.option.skipGit',
|
|
91
93
|
'query|-r, --repo <name>': 'help.option.repo.targetOmitOne',
|
|
94
|
+
'query|--branch <name>': 'help.option.branch',
|
|
92
95
|
'query|-c, --context <text>': 'help.option.query.context',
|
|
93
96
|
'query|-g, --goal <text>': 'help.option.query.goal',
|
|
94
97
|
'query|-l, --limit <n>': 'help.option.query.limit',
|
|
95
98
|
'query|--content': 'help.option.content',
|
|
96
99
|
'context|-r, --repo <name>': 'help.option.repo.target',
|
|
100
|
+
'context|--branch <name>': 'help.option.branch',
|
|
97
101
|
'context|-u, --uid <uid>': 'help.option.context.uid',
|
|
98
102
|
'context|-f, --file <path>': 'help.option.context.file',
|
|
99
103
|
'context|--content': 'help.option.content',
|
|
100
104
|
'impact|-d, --direction <dir>': 'help.option.impact.direction',
|
|
101
105
|
'impact|-r, --repo <name>': 'help.option.repo.target',
|
|
106
|
+
'impact|--branch <name>': 'help.option.branch',
|
|
102
107
|
'impact|-u, --uid <uid>': 'help.option.context.uid',
|
|
103
108
|
'impact|-f, --file <path>': 'help.option.context.file',
|
|
104
109
|
'impact|--kind <kind>': 'help.option.impact.kind',
|
|
@@ -108,9 +113,15 @@ const OPTION_DESCRIPTION_KEYS = {
|
|
|
108
113
|
'impact|--offset <n>': 'help.option.impact.offset',
|
|
109
114
|
'impact|--summary-only': 'help.option.impact.summaryOnly',
|
|
110
115
|
'cypher|-r, --repo <name>': 'help.option.repo.target',
|
|
116
|
+
'cypher|--branch <name>': 'help.option.branch',
|
|
111
117
|
'detect-changes|-s, --scope <scope>': 'help.option.detectChanges.scope',
|
|
112
118
|
'detect-changes|-b, --base-ref <ref>': 'help.option.detectChanges.baseRef',
|
|
113
119
|
'detect-changes|-r, --repo <name>': 'help.option.repo.target',
|
|
120
|
+
'detect-changes|--branch <name>': 'help.option.branch',
|
|
121
|
+
'check|--cycles': 'help.option.check.cycles',
|
|
122
|
+
'check|--json': 'help.option.json',
|
|
123
|
+
'check|-r, --repo <name>': 'help.option.repo.target',
|
|
124
|
+
'check|--branch <name>': 'help.option.branch',
|
|
114
125
|
'eval-server|-p, --port <port>': 'help.option.port',
|
|
115
126
|
'eval-server|--host <host>': 'help.option.evalServer.host',
|
|
116
127
|
'eval-server|--idle-timeout <seconds>': 'help.option.evalServer.idleTimeout',
|
package/dist/cli/i18n/en.d.ts
CHANGED
|
@@ -10,6 +10,9 @@ export declare const en: {
|
|
|
10
10
|
readonly 'list.title': "Indexed Repositories ({{count}})";
|
|
11
11
|
readonly 'list.indexed': "Indexed";
|
|
12
12
|
readonly 'list.commit': "Commit";
|
|
13
|
+
readonly 'list.branch': "Branch";
|
|
14
|
+
readonly 'list.branchIndexes': "Branch indexes";
|
|
15
|
+
readonly 'list.branchLine': "{{branch}} ({{commit}}, {{indexed}})";
|
|
13
16
|
readonly 'list.stats': "Stats";
|
|
14
17
|
readonly 'list.statsValue': "{{files}} files, {{symbols}} symbols, {{edges}} edges";
|
|
15
18
|
readonly 'list.clusters': "Clusters";
|
|
@@ -23,6 +26,9 @@ export declare const en: {
|
|
|
23
26
|
readonly 'status.indexed': "Indexed";
|
|
24
27
|
readonly 'status.indexedCommit': "Indexed commit";
|
|
25
28
|
readonly 'status.currentCommit': "Current commit";
|
|
29
|
+
readonly 'status.branch': "Branch";
|
|
30
|
+
readonly 'status.detached': "(detached HEAD)";
|
|
31
|
+
readonly 'status.branchNotIndexed': "⚠️ current branch not indexed (primary index is for '{{primary}}'; run gitnexus analyze)";
|
|
26
32
|
readonly 'status.status': "Status";
|
|
27
33
|
readonly 'status.upToDate': "✅ up-to-date";
|
|
28
34
|
readonly 'status.stale': "⚠️ stale (re-run gitnexus analyze)";
|
|
@@ -30,6 +36,9 @@ export declare const en: {
|
|
|
30
36
|
readonly 'clean.deletedRepo': "Deleted: {{name}} ({{storagePath}})";
|
|
31
37
|
readonly 'clean.notFoundHere': "No indexed repository found in this directory.";
|
|
32
38
|
readonly 'clean.deleteCurrent': "This will delete the GitNexus index for: {{repoName}}";
|
|
39
|
+
readonly 'clean.branchNotIndexed': "No indexed branch named \"{{branch}}\" for this repository.";
|
|
40
|
+
readonly 'clean.deleteBranch': "This will delete the branch index \"{{branch}}\" at: {{path}}";
|
|
41
|
+
readonly 'clean.deletedBranch': "Deleted branch index: {{branch}}";
|
|
33
42
|
readonly 'clean.lbugSidecars.state': "LadybugDB sidecar state: {{state}}";
|
|
34
43
|
readonly 'clean.lbugSidecars.none': "No quarantined LadybugDB missing-shadow WAL sidecars found.";
|
|
35
44
|
readonly 'clean.lbugSidecars.preview': "This will delete {{count}} quarantined LadybugDB missing-shadow WAL sidecar(s):";
|
|
@@ -117,6 +126,7 @@ export declare const en: {
|
|
|
117
126
|
readonly 'help.command.impact.description': "Blast radius analysis: what breaks if you change a symbol";
|
|
118
127
|
readonly 'help.command.cypher.description': "Execute raw Cypher query against the knowledge graph";
|
|
119
128
|
readonly 'help.command.detectChanges.description': "Map git diff hunks to indexed symbols and affected execution flows";
|
|
129
|
+
readonly 'help.command.check.description': "Run structural checks against the indexed graph";
|
|
120
130
|
readonly 'help.command.evalServer.description': "Start lightweight HTTP server for fast tool calls during evaluation";
|
|
121
131
|
readonly 'help.command.group.description': "Manage repository groups for cross-index impact analysis";
|
|
122
132
|
readonly 'help.command.group.create.description': "Create a new group with template group.yaml";
|
|
@@ -156,6 +166,7 @@ export declare const en: {
|
|
|
156
166
|
readonly 'help.option.force.confirmation': "Skip confirmation prompt";
|
|
157
167
|
readonly 'help.option.uninstall.force': "Apply the changes (default is a dry-run preview)";
|
|
158
168
|
readonly 'help.option.clean.all': "Clean all indexed repos";
|
|
169
|
+
readonly 'help.option.clean.branch': "Delete only the named branch index (not the primary)";
|
|
159
170
|
readonly 'help.option.clean.lbugSidecars': "Clean quarantined LadybugDB missing-shadow WAL sidecars";
|
|
160
171
|
readonly 'help.option.wiki.force': "Force full regeneration even if up to date";
|
|
161
172
|
readonly 'help.option.wiki.provider': "LLM provider: openai, openrouter, azure, custom, cursor, claude, codex, or opencode (default: openai)";
|
|
@@ -178,6 +189,7 @@ export declare const en: {
|
|
|
178
189
|
readonly 'help.option.query.limit': "Max processes to return (default: 5)";
|
|
179
190
|
readonly 'help.option.content': "Include full symbol source code";
|
|
180
191
|
readonly 'help.option.repo.target': "Target repository";
|
|
192
|
+
readonly 'help.option.branch': "Scope to a specific branch index (multi-branch repos)";
|
|
181
193
|
readonly 'help.option.context.uid': "Direct symbol UID (zero-ambiguity lookup)";
|
|
182
194
|
readonly 'help.option.context.file': "File path to disambiguate common names";
|
|
183
195
|
readonly 'help.option.impact.kind': "Kind filter to disambiguate common names (e.g. Function, Class, Method)";
|
|
@@ -189,6 +201,7 @@ export declare const en: {
|
|
|
189
201
|
readonly 'help.option.impact.summaryOnly': "Return counts and risk only, omit symbol list";
|
|
190
202
|
readonly 'help.option.detectChanges.scope': "What to analyze: unstaged, staged, all, or compare";
|
|
191
203
|
readonly 'help.option.detectChanges.baseRef': "Branch/commit for compare scope (e.g. main)";
|
|
204
|
+
readonly 'help.option.check.cycles': "Detect circular imports and fail when any are found";
|
|
192
205
|
readonly 'help.option.evalServer.host': "Bind address (default: 127.0.0.1, use 0.0.0.0 to expose to all interfaces)";
|
|
193
206
|
readonly 'help.option.evalServer.idleTimeout': "Auto-shutdown after N seconds idle (0 = disabled)";
|
|
194
207
|
readonly 'help.option.group.create.force': "Overwrite existing group";
|
package/dist/cli/i18n/en.js
CHANGED
|
@@ -10,6 +10,9 @@ export const en = {
|
|
|
10
10
|
'list.title': 'Indexed Repositories ({{count}})',
|
|
11
11
|
'list.indexed': 'Indexed',
|
|
12
12
|
'list.commit': 'Commit',
|
|
13
|
+
'list.branch': 'Branch',
|
|
14
|
+
'list.branchIndexes': 'Branch indexes',
|
|
15
|
+
'list.branchLine': '{{branch}} ({{commit}}, {{indexed}})',
|
|
13
16
|
'list.stats': 'Stats',
|
|
14
17
|
'list.statsValue': '{{files}} files, {{symbols}} symbols, {{edges}} edges',
|
|
15
18
|
'list.clusters': 'Clusters',
|
|
@@ -23,6 +26,9 @@ export const en = {
|
|
|
23
26
|
'status.indexed': 'Indexed',
|
|
24
27
|
'status.indexedCommit': 'Indexed commit',
|
|
25
28
|
'status.currentCommit': 'Current commit',
|
|
29
|
+
'status.branch': 'Branch',
|
|
30
|
+
'status.detached': '(detached HEAD)',
|
|
31
|
+
'status.branchNotIndexed': "⚠️ current branch not indexed (primary index is for '{{primary}}'; run gitnexus analyze)",
|
|
26
32
|
'status.status': 'Status',
|
|
27
33
|
'status.upToDate': '✅ up-to-date',
|
|
28
34
|
'status.stale': '⚠️ stale (re-run gitnexus analyze)',
|
|
@@ -30,6 +36,9 @@ export const en = {
|
|
|
30
36
|
'clean.deletedRepo': 'Deleted: {{name}} ({{storagePath}})',
|
|
31
37
|
'clean.notFoundHere': 'No indexed repository found in this directory.',
|
|
32
38
|
'clean.deleteCurrent': 'This will delete the GitNexus index for: {{repoName}}',
|
|
39
|
+
'clean.branchNotIndexed': 'No indexed branch named "{{branch}}" for this repository.',
|
|
40
|
+
'clean.deleteBranch': 'This will delete the branch index "{{branch}}" at: {{path}}',
|
|
41
|
+
'clean.deletedBranch': 'Deleted branch index: {{branch}}',
|
|
33
42
|
'clean.lbugSidecars.state': 'LadybugDB sidecar state: {{state}}',
|
|
34
43
|
'clean.lbugSidecars.none': 'No quarantined LadybugDB missing-shadow WAL sidecars found.',
|
|
35
44
|
'clean.lbugSidecars.preview': 'This will delete {{count}} quarantined LadybugDB missing-shadow WAL sidecar(s):',
|
|
@@ -117,6 +126,7 @@ export const en = {
|
|
|
117
126
|
'help.command.impact.description': 'Blast radius analysis: what breaks if you change a symbol',
|
|
118
127
|
'help.command.cypher.description': 'Execute raw Cypher query against the knowledge graph',
|
|
119
128
|
'help.command.detectChanges.description': 'Map git diff hunks to indexed symbols and affected execution flows',
|
|
129
|
+
'help.command.check.description': 'Run structural checks against the indexed graph',
|
|
120
130
|
'help.command.evalServer.description': 'Start lightweight HTTP server for fast tool calls during evaluation',
|
|
121
131
|
'help.command.group.description': 'Manage repository groups for cross-index impact analysis',
|
|
122
132
|
'help.command.group.create.description': 'Create a new group with template group.yaml',
|
|
@@ -156,6 +166,7 @@ export const en = {
|
|
|
156
166
|
'help.option.force.confirmation': 'Skip confirmation prompt',
|
|
157
167
|
'help.option.uninstall.force': 'Apply the changes (default is a dry-run preview)',
|
|
158
168
|
'help.option.clean.all': 'Clean all indexed repos',
|
|
169
|
+
'help.option.clean.branch': 'Delete only the named branch index (not the primary)',
|
|
159
170
|
'help.option.clean.lbugSidecars': 'Clean quarantined LadybugDB missing-shadow WAL sidecars',
|
|
160
171
|
'help.option.wiki.force': 'Force full regeneration even if up to date',
|
|
161
172
|
'help.option.wiki.provider': 'LLM provider: openai, openrouter, azure, custom, cursor, claude, codex, or opencode (default: openai)',
|
|
@@ -178,6 +189,7 @@ export const en = {
|
|
|
178
189
|
'help.option.query.limit': 'Max processes to return (default: 5)',
|
|
179
190
|
'help.option.content': 'Include full symbol source code',
|
|
180
191
|
'help.option.repo.target': 'Target repository',
|
|
192
|
+
'help.option.branch': 'Scope to a specific branch index (multi-branch repos)',
|
|
181
193
|
'help.option.context.uid': 'Direct symbol UID (zero-ambiguity lookup)',
|
|
182
194
|
'help.option.context.file': 'File path to disambiguate common names',
|
|
183
195
|
'help.option.impact.kind': 'Kind filter to disambiguate common names (e.g. Function, Class, Method)',
|
|
@@ -189,6 +201,7 @@ export const en = {
|
|
|
189
201
|
'help.option.impact.summaryOnly': 'Return counts and risk only, omit symbol list',
|
|
190
202
|
'help.option.detectChanges.scope': 'What to analyze: unstaged, staged, all, or compare',
|
|
191
203
|
'help.option.detectChanges.baseRef': 'Branch/commit for compare scope (e.g. main)',
|
|
204
|
+
'help.option.check.cycles': 'Detect circular imports and fail when any are found',
|
|
192
205
|
'help.option.evalServer.host': 'Bind address (default: 127.0.0.1, use 0.0.0.0 to expose to all interfaces)',
|
|
193
206
|
'help.option.evalServer.idleTimeout': 'Auto-shutdown after N seconds idle (0 = disabled)',
|
|
194
207
|
'help.option.group.create.force': 'Overwrite existing group',
|