gitnexus 1.6.10 → 1.6.11-rc.10

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.
Files changed (116) hide show
  1. package/README.md +43 -1
  2. package/dist/_shared/impact-risk.d.ts +37 -0
  3. package/dist/_shared/impact-risk.d.ts.map +1 -0
  4. package/dist/_shared/impact-risk.js +92 -0
  5. package/dist/_shared/impact-risk.js.map +1 -0
  6. package/dist/_shared/index.d.ts +2 -0
  7. package/dist/_shared/index.d.ts.map +1 -1
  8. package/dist/_shared/index.js +2 -0
  9. package/dist/_shared/index.js.map +1 -1
  10. package/dist/cli/ai-context.js +4 -4
  11. package/dist/cli/analyze-config.d.ts +2 -0
  12. package/dist/cli/analyze-config.js +16 -0
  13. package/dist/cli/analyze-options.d.ts +4 -0
  14. package/dist/cli/analyze.d.ts +17 -0
  15. package/dist/cli/analyze.js +43 -7
  16. package/dist/cli/eval-server.js +22 -5
  17. package/dist/cli/group.js +7 -1
  18. package/dist/cli/help-i18n.js +2 -0
  19. package/dist/cli/i18n/en.d.ts +11 -1
  20. package/dist/cli/i18n/en.js +11 -1
  21. package/dist/cli/i18n/resources.d.ts +21 -1
  22. package/dist/cli/i18n/zh-CN.d.ts +10 -0
  23. package/dist/cli/i18n/zh-CN.js +11 -1
  24. package/dist/cli/index.js +10 -3
  25. package/dist/cli/status.js +91 -6
  26. package/dist/cli/watch-queue.d.ts +41 -0
  27. package/dist/cli/watch-queue.js +184 -0
  28. package/dist/cli/watch.d.ts +20 -0
  29. package/dist/cli/watch.js +372 -0
  30. package/dist/cli/wiki.js +15 -2
  31. package/dist/config/ignore-service.d.ts +11 -0
  32. package/dist/config/ignore-service.js +41 -4
  33. package/dist/config/repo-control-file.d.ts +3 -0
  34. package/dist/config/repo-control-file.js +115 -0
  35. package/dist/core/group/config-parser.js +20 -2
  36. package/dist/core/group/cross-impact.d.ts +2 -1
  37. package/dist/core/group/cross-impact.js +33 -2
  38. package/dist/core/group/extractors/fs-utils.d.ts +2 -0
  39. package/dist/core/group/extractors/fs-utils.js +86 -0
  40. package/dist/core/group/extractors/graphql-extractor.d.ts +17 -0
  41. package/dist/core/group/extractors/graphql-extractor.js +652 -0
  42. package/dist/core/group/extractors/http-patterns/kotlin.js +522 -7
  43. package/dist/core/group/extractors/http-patterns/php.js +279 -11
  44. package/dist/core/group/extractors/manifest-extractor.d.ts +1 -1
  45. package/dist/core/group/extractors/manifest-extractor.js +1 -1
  46. package/dist/core/group/matching.js +8 -1
  47. package/dist/core/group/service.js +5 -1
  48. package/dist/core/group/storage.js +1 -0
  49. package/dist/core/group/sync.d.ts +3 -1
  50. package/dist/core/group/sync.js +43 -5
  51. package/dist/core/group/types.d.ts +19 -5
  52. package/dist/core/index-content-drift.d.ts +54 -0
  53. package/dist/core/index-content-drift.js +127 -0
  54. package/dist/core/index-freshness.d.ts +2 -2
  55. package/dist/core/index-freshness.js +13 -0
  56. package/dist/core/ingestion/filesystem-walker.d.ts +15 -5
  57. package/dist/core/ingestion/filesystem-walker.js +20 -3
  58. package/dist/core/ingestion/parsing-processor.d.ts +2 -0
  59. package/dist/core/ingestion/parsing-processor.js +5 -0
  60. package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +5 -0
  61. package/dist/core/ingestion/pipeline-phases/parse-impl.js +14 -0
  62. package/dist/core/ingestion/pipeline-phases/parse.d.ts +6 -0
  63. package/dist/core/ingestion/pipeline-phases/scan.js +25 -13
  64. package/dist/core/ingestion/pipeline.js +5 -1
  65. package/dist/core/ingestion/route-extractors/kotlin-const-resolver.d.ts +377 -0
  66. package/dist/core/ingestion/route-extractors/kotlin-const-resolver.js +1203 -0
  67. package/dist/core/ingestion/scope-extractor-bridge.js +8 -2
  68. package/dist/core/ingestion/scope-resolution/pipeline/phase.d.ts +2 -0
  69. package/dist/core/ingestion/scope-resolution/pipeline/phase.js +14 -2
  70. package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +2 -0
  71. package/dist/core/ingestion/scope-resolution/pipeline/run.js +11 -1
  72. package/dist/core/ingestion/scope-resolution/scope-extraction-failures.d.ts +14 -0
  73. package/dist/core/ingestion/scope-resolution/scope-extraction-failures.js +35 -0
  74. package/dist/core/ingestion/utils/symbol-labels.d.ts +2 -2
  75. package/dist/core/ingestion/utils/symbol-labels.js +2 -2
  76. package/dist/core/ingestion/workers/parse-worker.d.ts +6 -0
  77. package/dist/core/ingestion/workers/parse-worker.js +7 -1
  78. package/dist/core/ingestion/workers/result-merge.js +4 -1
  79. package/dist/core/run-analyze.d.ts +17 -0
  80. package/dist/core/run-analyze.js +117 -11
  81. package/dist/core/wiki/generator.js +8 -0
  82. package/dist/core/wiki/grok-client.d.ts +21 -0
  83. package/dist/core/wiki/grok-client.js +287 -0
  84. package/dist/core/wiki/llm-client.d.ts +1 -1
  85. package/dist/core/wiki/llm-client.js +5 -2
  86. package/dist/core/wiki/local-cli-client.d.ts +11 -0
  87. package/dist/core/wiki/local-cli-client.js +22 -9
  88. package/dist/mcp/local/local-backend.d.ts +26 -7
  89. package/dist/mcp/local/local-backend.js +219 -81
  90. package/dist/mcp/local/pdg-impact.d.ts +8 -4
  91. package/dist/mcp/local/pdg-impact.js +7 -2
  92. package/dist/mcp/repository-policy.d.ts +5 -1
  93. package/dist/mcp/repository-policy.js +48 -4
  94. package/dist/mcp/resources.js +2 -1
  95. package/dist/mcp/server.js +6 -5
  96. package/dist/mcp/tools.js +37 -23
  97. package/dist/storage/file-hash.d.ts +5 -0
  98. package/dist/storage/file-hash.js +16 -6
  99. package/dist/storage/git.d.ts +19 -8
  100. package/dist/storage/git.js +83 -24
  101. package/dist/storage/gitnexus-managed-paths.d.ts +36 -0
  102. package/dist/storage/gitnexus-managed-paths.js +46 -0
  103. package/dist/storage/parse-cache.js +19 -7
  104. package/dist/storage/repo-manager.d.ts +11 -1
  105. package/dist/storage/repo-manager.js +23 -2
  106. package/dist/storage/repo-meta.d.ts +29 -1
  107. package/dist/storage/repo-meta.js +1 -1
  108. package/dist/types/pipeline.d.ts +6 -0
  109. package/package.json +3 -1
  110. package/scripts/cross-platform-shard.ts +4 -2
  111. package/scripts/cross-platform-tests.ts +7 -1
  112. package/skills/gitnexus-cli.md +11 -3
  113. package/skills/gitnexus-impact-analysis.md +9 -0
  114. package/web/assets/{agent-Dr4l5EOp.js → agent-BWAXPjC5.js} +106 -104
  115. package/web/assets/{index-2zdvEdzg.js → index-DDRie6_8.js} +3 -3
  116. package/web/index.html +1 -1
package/README.md CHANGED
@@ -204,7 +204,7 @@ Your AI agent gets **17 tools** (15 per-repo + 2 group) automatically:
204
204
  | `group_list` | List configured repository groups |
205
205
  | `group_sync` | Rebuild a group's Contract Registry and cross-repo links |
206
206
 
207
- > With one indexed repo, the `repo` param is optional. With multiple, specify which: `query({search_query: "auth", repo: "my-app"})`. Per-repo tools also take an optional `branch` for indexes pinned with `gitnexus analyze --branch`; omitting it queries the workspace index, which follows your checked-out working tree. `explain` and `pdg_query` need an index built with `gitnexus analyze --pdg`.
207
+ > Read-only tools can omit `repo` when one repo is indexed, an MCP default is configured, or the GitNexus process cwd is inside a registered path without crossing into an unindexed nested Git checkout. Otherwise—and for mutating tools with multiple indexed repos and no MCP default—specify it explicitly: `query({search_query: "auth", repo: "my-app"})`. Per-repo tools also take an optional `branch` for indexes pinned with `gitnexus analyze --branch`; omitting it queries the workspace index, which follows your checked-out working tree. `explain` and `pdg_query` need an index built with `gitnexus analyze --pdg`.
208
208
 
209
209
  ## MCP Resources
210
210
 
@@ -234,6 +234,7 @@ Your AI agent gets **17 tools** (15 per-repo + 2 group) automatically:
234
234
  gitnexus setup # Configure MCP for detected editors (one-time; use -c to select)
235
235
  gitnexus uninstall # Preview removal of GitNexus MCP/skills/hooks (add --force to apply)
236
236
  gitnexus analyze [path] # Index a repository (or update stale index)
237
+ gitnexus analyze [path] --watch # Watch local files and serialize incremental refreshes
237
238
  gitnexus analyze --repair-fts # Fast path: rebuild/verify only FTS indexes on existing index data
238
239
  gitnexus analyze --force # Full rebuild: re-parse + graph rebuild + FTS rebuild
239
240
  gitnexus analyze --embeddings # Enable embedding generation (slower, better search)
@@ -256,6 +257,7 @@ gitnexus clean # Delete index for current repo
256
257
  gitnexus clean --all --force # Delete all indexes
257
258
  gitnexus wiki [path] # Generate LLM-powered docs from knowledge graph
258
259
  gitnexus wiki --model <model> # Wiki with custom LLM model (default: minimax/minimax-m2.5)
260
+ gitnexus wiki --provider grok # Local Grok Build CLI (uses `grok login`, no API key)
259
261
  gitnexus wiki --base-url http://llama-box.local:8080/v1 --allow-insecure-connection llama-box.local
260
262
  # Allow an exact LAN/self-hosted HTTP LLM host; env: GITNEXUS_ALLOW_INSECURE_CONNECTION
261
263
  gitnexus doctor # Show runtime platform capabilities and embedding configuration
@@ -281,6 +283,46 @@ gitnexus group status <name> # Check staleness of repos in a group
281
283
  gitnexus group impact <name> --target <symbol> --repo <groupPath> # Cross-repo blast radius
282
284
  ```
283
285
 
286
+ `gitnexus analyze --watch` requires a Git repository. It performs an initial
287
+ analysis and then debounces scanner-admitted working-tree changes for 300 ms by
288
+ default into serialized incremental refreshes. Events arriving during a run
289
+ remain queued, and retryable failures retain the same batch with bounded
290
+ backoff. Invalid `.gitnexusrc` or ignore-file reloads pause ordinary refreshes
291
+ until the control file is fixed. Watch refreshes update only the graph: they
292
+ intentionally skip AGENTS.md / CLAUDE.md injection and standard skill
293
+ installation. Run a one-shot `gitnexus analyze` when those generated files need
294
+ updating. Stop watch mode with Ctrl+C.
295
+
296
+ Watch mode accepts `--debounce`, `--workers`, `--worker-timeout`,
297
+ `--max-file-size`, `--branch`, `--pdg`, `--name`, `--allow-duplicate-name`, and
298
+ `--verbose`. Explicit one-shot options such as `--force`, `--repair-fts`,
299
+ embedding flags, `--skills`, `--default-branch`, `--skip-agents-md`,
300
+ `--skip-skills`, `--no-stats`, `--self-commit`, `--index-only`, and `--skip-git`
301
+ are rejected. Unsupported defaults from `.gitnexusrc` are ignored with a warning.
302
+
303
+ POSIX requests clone-first copy-and-swap publication when the live index has no
304
+ orphan sidecars. Windows and sidecar fallback runs update in place: failures
305
+ known to occur before writes are retried, while a failure that may have mutated
306
+ the live index stops the watcher. Watch mode does not pull remotes. Running MCP
307
+ and `serve` processes periodically check for a newly published index and reopen
308
+ it without a restart. MCP checks are throttled to once every five seconds, so a
309
+ tool call before the next check can briefly use the previous index.
310
+
311
+ GraphQL contract matching is opt-in in the group's `group.yaml`:
312
+
313
+ ```yaml
314
+ detect:
315
+ graphql: true
316
+ ```
317
+
318
+ The initial exact-only slice matches methods and properties on top-level NestJS `@Resolver`
319
+ classes using imported `@Query`, `@Mutation`, and `@Subscription` decorators. Named
320
+ `.graphql`/`.gql` operations are anchored by generated `<OperationName>Document` declarations;
321
+ object, static `gql` template, and `TypedDocumentString` initializers must prove the operation name
322
+ and root fields. Dynamic decorator names, anonymous operations, and ambiguous or missing graph
323
+ anchors are deliberately omitted. Add common infrastructure fields such as `/health` to
324
+ `matching.exclude_links_paths` to keep those GraphQL contracts visible without cross-linking them.
325
+
284
326
  > **`gitnexus uninstall`** reverses `gitnexus setup` — it removes the GitNexus MCP entries, hooks, and skill directories it added to each detected editor. Skill directories are identified **by bundled gitnexus skill name** (e.g. `gitnexus-cli/`), so if you customized files inside an installed skill directory, back them up first. It is a dry-run preview by default and prints the exact paths it would remove; pass `--force` to apply. Per-repo indexes (`gitnexus clean --all`) and the global npm package (`npm uninstall -g gitnexus`) are left for you to remove.
285
327
 
286
328
  ## Remote Embeddings
@@ -0,0 +1,37 @@
1
+ export type ImpactRisk = 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL' | 'UNKNOWN';
2
+ export type ImpactRiskAxis = 'processes' | 'modules';
3
+ export type UnusedImpactRiskReason = 'file-nodes-have-no-process-or-community-membership' | 'enrichment-skipped' | 'enrichment-budget-exhausted' | 'enrichment-truncated' | 'enrichment-query-failed';
4
+ export interface UnusedImpactRiskAxis {
5
+ axis: ImpactRiskAxis;
6
+ reason: UnusedImpactRiskReason;
7
+ }
8
+ export interface ImpactRiskInput {
9
+ direction: 'upstream' | 'downstream';
10
+ directCount: number;
11
+ processCount: number;
12
+ moduleCount: number;
13
+ impactedCount: number;
14
+ unusedAxes?: readonly UnusedImpactRiskAxis[];
15
+ }
16
+ export interface ImpactRiskResult {
17
+ risk: ImpactRisk;
18
+ riskSharedAxes: ImpactRisk;
19
+ riskScale: {
20
+ comparableAcrossKinds: boolean;
21
+ unusedAxes: readonly UnusedImpactRiskAxis[];
22
+ };
23
+ }
24
+ /** Map walk outcomes to unused process/module axes so comparability matches what was sampled. */
25
+ export declare function unusedAxesForImpactWalk(input: {
26
+ isFileTarget: boolean;
27
+ skipEnrichment: boolean;
28
+ maxChunks: number;
29
+ processQueryFailed: boolean;
30
+ moduleQueryFailed: boolean;
31
+ /** When 0, a zero chunk budget is not an unused-axis event — there was nothing to enrich. */
32
+ impactedCount: number;
33
+ /** True when process/module queries ran on a strict subset of impacted symbols. */
34
+ enrichmentTruncated?: boolean;
35
+ }): UnusedImpactRiskAxis[];
36
+ export declare function scoreImpactRisk(input: ImpactRiskInput): ImpactRiskResult;
37
+ //# sourceMappingURL=impact-risk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"impact-risk.d.ts","sourceRoot":"","sources":["../src/impact-risk.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;AAE5E,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,SAAS,CAAC;AAErD,MAAM,MAAM,sBAAsB,GAC9B,oDAAoD,GACpD,oBAAoB,GACpB,6BAA6B,GAC7B,sBAAsB,GACtB,yBAAyB,CAAC;AAE9B,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,cAAc,CAAC;IACrB,MAAM,EAAE,sBAAsB,CAAC;CAChC;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,UAAU,GAAG,YAAY,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;CAC9C;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,UAAU,CAAC;IACjB,cAAc,EAAE,UAAU,CAAC;IAC3B,SAAS,EAAE;QACT,qBAAqB,EAAE,OAAO,CAAC;QAC/B,UAAU,EAAE,SAAS,oBAAoB,EAAE,CAAC;KAC7C,CAAC;CACH;AAwDD,iGAAiG;AACjG,wBAAgB,uBAAuB,CAAC,KAAK,EAAE;IAC7C,YAAY,EAAE,OAAO,CAAC;IACtB,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,6FAA6F;IAC7F,aAAa,EAAE,MAAM,CAAC;IACtB,mFAAmF;IACnF,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B,GAAG,oBAAoB,EAAE,CAqBzB;AAOD,wBAAgB,eAAe,CAAC,KAAK,EAAE,eAAe,GAAG,gBAAgB,CAuBxE"}
@@ -0,0 +1,92 @@
1
+ function score(input) {
2
+ const { direction, directCount, processCount, moduleCount, impactedCount } = input;
3
+ if (direction === 'upstream' && impactedCount === 0)
4
+ return 'UNKNOWN';
5
+ if (directCount >= 30 || processCount >= 5 || moduleCount >= 5 || impactedCount >= 200) {
6
+ return 'CRITICAL';
7
+ }
8
+ if (directCount >= 15 || processCount >= 3 || moduleCount >= 3 || impactedCount >= 100) {
9
+ return 'HIGH';
10
+ }
11
+ if (directCount >= 5 || impactedCount >= 30)
12
+ return 'MEDIUM';
13
+ return 'LOW';
14
+ }
15
+ const UNMEASURED_REASONS = new Set([
16
+ 'file-nodes-have-no-process-or-community-membership',
17
+ 'enrichment-skipped',
18
+ 'enrichment-budget-exhausted',
19
+ ]);
20
+ function unusedPair(reason) {
21
+ return [
22
+ { axis: 'processes', reason },
23
+ { axis: 'modules', reason },
24
+ ];
25
+ }
26
+ function countsWithUnmeasuredAxesZeroed(input) {
27
+ let processCount = input.processCount;
28
+ let moduleCount = input.moduleCount;
29
+ for (const unused of input.unusedAxes ?? []) {
30
+ if (!UNMEASURED_REASONS.has(unused.reason))
31
+ continue;
32
+ if (unused.axis === 'processes')
33
+ processCount = 0;
34
+ if (unused.axis === 'modules')
35
+ moduleCount = 0;
36
+ }
37
+ return {
38
+ direction: input.direction,
39
+ directCount: input.directCount,
40
+ processCount,
41
+ moduleCount,
42
+ impactedCount: input.impactedCount,
43
+ };
44
+ }
45
+ /** Map walk outcomes to unused process/module axes so comparability matches what was sampled. */
46
+ export function unusedAxesForImpactWalk(input) {
47
+ if (input.isFileTarget) {
48
+ return unusedPair('file-nodes-have-no-process-or-community-membership');
49
+ }
50
+ if (input.skipEnrichment) {
51
+ return unusedPair('enrichment-skipped');
52
+ }
53
+ if (input.maxChunks === 0 && input.impactedCount > 0) {
54
+ return unusedPair('enrichment-budget-exhausted');
55
+ }
56
+ const unused = [];
57
+ if (input.enrichmentTruncated) {
58
+ unused.push(...unusedPair('enrichment-truncated'));
59
+ }
60
+ if (input.processQueryFailed) {
61
+ unused.push({ axis: 'processes', reason: 'enrichment-query-failed' });
62
+ }
63
+ if (input.moduleQueryFailed) {
64
+ unused.push({ axis: 'modules', reason: 'enrichment-query-failed' });
65
+ }
66
+ return unused;
67
+ }
68
+ const INCOMPLETE_SAMPLE_REASONS = new Set([
69
+ 'enrichment-query-failed',
70
+ 'enrichment-truncated',
71
+ ]);
72
+ export function scoreImpactRisk(input) {
73
+ const unusedAxes = input.unusedAxes ?? [];
74
+ const observedRisk = score(countsWithUnmeasuredAxesZeroed(input));
75
+ const incompleteSample = unusedAxes.some((unused) => INCOMPLETE_SAMPLE_REASONS.has(unused.reason));
76
+ // Failed queries and truncated samples make observed process/module counts
77
+ // lower bounds. Preserve any HIGH/CRITICAL warning already proved by those
78
+ // counts, but never emit a confident LOW/MEDIUM edit gate from an incomplete
79
+ // enrichment pass.
80
+ const risk = incompleteSample && (observedRisk === 'LOW' || observedRisk === 'MEDIUM')
81
+ ? 'UNKNOWN'
82
+ : observedRisk;
83
+ return {
84
+ risk,
85
+ riskSharedAxes: score({ ...input, processCount: 0, moduleCount: 0 }),
86
+ riskScale: {
87
+ comparableAcrossKinds: unusedAxes.length === 0,
88
+ unusedAxes,
89
+ },
90
+ };
91
+ }
92
+ //# sourceMappingURL=impact-risk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"impact-risk.js","sourceRoot":"","sources":["../src/impact-risk.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,8 @@ export type { NodeTableName, RelType } from './lbug/schema-constants.js';
4
4
  export { SupportedLanguages } from './languages.js';
5
5
  export { getLanguageFromFilename, getSyntaxLanguageFromFilename, isBladeTemplateFilename, } from './language-detection.js';
6
6
  export type { MroStrategy } from './mro-strategy.js';
7
+ export { scoreImpactRisk, unusedAxesForImpactWalk } from './impact-risk.js';
8
+ export type { ImpactRisk, ImpactRiskAxis, ImpactRiskInput, ImpactRiskResult, UnusedImpactRiskAxis, UnusedImpactRiskReason, } from './impact-risk.js';
7
9
  export type { PipelinePhase, PipelineProgress } from './pipeline.js';
8
10
  export type { ParameterTypeClass, SymbolDefinition, TypeParameter, } from './scope-resolution/symbol-definition.js';
9
11
  export type { ScopeId, DefId, ScopeKind, Range, Capture, CaptureMatch, BindingRef, ImportEdge, TypeRef, Scope, ResolutionEvidence, Resolution, Reference, ReferenceIndex, LookupParams, RegistryContributor, ParsedImport, ParsedTypeBinding, WorkspaceIndex, Callsite, ScopeLookup, } from './scope-resolution/types.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,8 @@ export { NODE_TABLES, REL_TABLE_NAME, REL_TYPES, EMBEDDING_TABLE_NAME, } from '.
3
3
  // Language support
4
4
  export { SupportedLanguages } from './languages.js';
5
5
  export { getLanguageFromFilename, getSyntaxLanguageFromFilename, isBladeTemplateFilename, } from './language-detection.js';
6
+ // Impact risk scoring
7
+ export { scoreImpactRisk, unusedAxesForImpactWalk } from './impact-risk.js';
6
8
  // Evidence + tie-break constants (RFC Appendix A, Appendix B)
7
9
  export { EvidenceWeights, typeBindingWeightAtDepth } from './scope-resolution/evidence-weights.js';
8
10
  export { ORIGIN_PRIORITY } from './scope-resolution/origin-priority.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,mBAAmB;AACnB,OAAO,EACL,WAAW,EACX,cAAc,EACd,SAAS,EACT,oBAAoB,GACrB,MAAM,4BAA4B,CAAC;AAGpC,mBAAmB;AACnB,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EACL,uBAAuB,EACvB,6BAA6B,EAC7B,uBAAuB,GACxB,MAAM,yBAAyB,CAAC;AAqCjC,8DAA8D;AAC9D,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAC;AACnG,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AAGxE,yDAAyD;AACzD,OAAO,EACL,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,+CAA+C,CAAC;AAGvD,sEAAsE;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAEhE,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AAEjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,4CAA4C,CAAC;AAGrF,gEAAgE;AAChE,yEAAyE;AACzE,2DAA2D;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AA4BxE,oFAAoF;AACpF,OAAO,EAAE,wBAAwB,EAAE,MAAM,6CAA6C,CAAC;AAMvF,uEAAuE;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,0CAA0C,CAAC;AAUpE,sEAAsE;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iDAAiD,CAAC;AAErF,OAAO,EAAE,mBAAmB,EAAE,MAAM,kDAAkD,CAAC;AAKvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,iDAAiD,CAAC;AAKrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,iDAAiD,CAAC;AAErF,OAAO,EAAE,UAAU,EAAE,MAAM,8CAA8C,CAAC;AAE1E,OAAO,EAAE,eAAe,EAAE,MAAM,mDAAmD,CAAC;AAEpF,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AAEpG,OAAO,EACL,gCAAgC,EAChC,kBAAkB,GACnB,MAAM,6CAA6C,CAAC;AAErD,OAAO,EACL,WAAW,EACX,YAAY,EACZ,WAAW,EACX,WAAW,GACZ,MAAM,0CAA0C,CAAC;AAUlD,2EAA2E;AAC3E,OAAO,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAErF,OAAO,EACL,cAAc,EACd,cAAc,EACd,uBAAuB,GACxB,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAG1E,8EAA8E;AAC9E,wEAAwE;AACxE,wEAAwE;AACxE,8DAA8D;AAC9D,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEtE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAEjG,OAAO,EACL,cAAc,EACd,4BAA4B,EAC5B,kBAAkB,EAClB,eAAe,EACf,sBAAsB,GACvB,MAAM,mCAAmC,CAAC;AAG3C,mDAAmD;AACnD,OAAO,EACL,+BAA+B,EAC/B,6BAA6B,EAC7B,4BAA4B,EAC5B,sBAAsB,EACtB,gBAAgB,EAChB,wBAAwB,EACxB,cAAc,GACf,MAAM,sCAAsC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,mBAAmB;AACnB,OAAO,EACL,WAAW,EACX,cAAc,EACd,SAAS,EACT,oBAAoB,GACrB,MAAM,4BAA4B,CAAC;AAGpC,mBAAmB;AACnB,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EACL,uBAAuB,EACvB,6BAA6B,EAC7B,uBAAuB,GACxB,MAAM,yBAAyB,CAAC;AAGjC,sBAAsB;AACtB,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AA4C5E,8DAA8D;AAC9D,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAC;AACnG,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AAGxE,yDAAyD;AACzD,OAAO,EACL,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,+CAA+C,CAAC;AAGvD,sEAAsE;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAEhE,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AAEjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,4CAA4C,CAAC;AAGrF,gEAAgE;AAChE,yEAAyE;AACzE,2DAA2D;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AA4BxE,oFAAoF;AACpF,OAAO,EAAE,wBAAwB,EAAE,MAAM,6CAA6C,CAAC;AAMvF,uEAAuE;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,0CAA0C,CAAC;AAUpE,sEAAsE;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iDAAiD,CAAC;AAErF,OAAO,EAAE,mBAAmB,EAAE,MAAM,kDAAkD,CAAC;AAKvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,iDAAiD,CAAC;AAKrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,iDAAiD,CAAC;AAErF,OAAO,EAAE,UAAU,EAAE,MAAM,8CAA8C,CAAC;AAE1E,OAAO,EAAE,eAAe,EAAE,MAAM,mDAAmD,CAAC;AAEpF,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AAEpG,OAAO,EACL,gCAAgC,EAChC,kBAAkB,GACnB,MAAM,6CAA6C,CAAC;AAErD,OAAO,EACL,WAAW,EACX,YAAY,EACZ,WAAW,EACX,WAAW,GACZ,MAAM,0CAA0C,CAAC;AAUlD,2EAA2E;AAC3E,OAAO,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAErF,OAAO,EACL,cAAc,EACd,cAAc,EACd,uBAAuB,GACxB,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAG1E,8EAA8E;AAC9E,wEAAwE;AACxE,wEAAwE;AACxE,8DAA8D;AAC9D,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEtE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAEjG,OAAO,EACL,cAAc,EACd,4BAA4B,EAC5B,kBAAkB,EAClB,eAAe,EACf,sBAAsB,GACvB,MAAM,mCAAmC,CAAC;AAG3C,mDAAmD;AACnD,OAAO,EACL,+BAA+B,EAC/B,6BAA6B,EAC7B,4BAA4B,EAC5B,sBAAsB,EACtB,gBAAgB,EAChB,wBAAwB,EACxB,cAAc,GACf,MAAM,sCAAsC,CAAC"}
@@ -139,14 +139,14 @@ This project is indexed by GitNexus as **${projectName}**${noStats ? '' : ` (${s
139
139
 
140
140
  ## Always Do
141
141
 
142
- - **MUST run impact analysis before editing.** Use \`impact({target: "symbolName", direction: "upstream"})\` (MCP) or \`${runner} impact "symbolName" --direction upstream --repo .\` (CLI fallback); report callers, processes, and risk. Never substitute grep for graph analysis.${hasPdg
142
+ - **MUST run impact before editing.** Use \`impact({target: "symbolName", direction: "upstream"})\` or \`${runner} impact "symbolName" --direction upstream --repo .\`; report callers, processes, and risk. Never substitute grep for graph analysis.${hasPdg
143
143
  ? ` For unified PDG impact, add \`mode: "pdg"\` with optional \`line: <N>\` — it returns statement-level \`affectedStatements\` over CDG + REACHING_DEF and inter-procedural symbols in \`interproceduralByDepth\`/\`byDepth\`; no-layer/degraded PDG results are UNKNOWN-risk notes (\`--pdg\` layer). CLI equivalent: \`${runner} impact "symbolName" --direction upstream --mode pdg --line <N> --repo .\`.`
144
144
  : ''}
145
145
  - **MUST analyze graph changes before committing.** Use \`detect_changes({scope: "all"})\` (MCP) or \`${runner} detect-changes --scope all --repo .\` (CLI fallback). \`partial: true\` or \`truncated: true\` is not a clean check — a zero means unseen, not unaffected; re-run it. For regression review: \`detect_changes({scope: "compare", base_ref: ${JSON.stringify(markdownSafeBranch(defaultBranch))}})\` or \`${runner} detect-changes --scope compare --base-ref ${JSON.stringify(markdownSafeBranch(defaultBranch))} --repo .\`.
146
- - **MUST warn the user** if impact analysis returns HIGH or CRITICAL risk before proceeding with edits.
146
+ - MUST warn on HIGH/CRITICAL \`risk\` pre-edit; never use \`riskSharedAxes\` to waive a HIGH/CRITICAL \`risk\` warning. Compare File/symbol: MCP File omits axes; Graph-RAG expands File.
147
147
  - **MUST treat \`risk: UNKNOWN\` as unresolved, not as low.** An empty caller set is not evidence the symbol is unused — it can also mean the callers are not resolvable by the index (plain-object property access, dynamic dispatch, cross-language calls). \`impact\` pairs \`UNKNOWN\` with a \`riskNote\` saying so. Confirm with a text search before treating the symbol as safe to change or delete; do not proceed on the strength of a zero.
148
- - When exploring unfamiliar code, use \`query({search_query: "concept"})\` to find execution flows instead of grepping. It returns process-grouped results ranked by relevance.
149
- - When you need full context on a specific symbol — callers, callees, which execution flows it participates in — use \`context({name: "symbolName"})\`.
148
+ - Explore with \`query({search_query: "concept"})\` for process-grouped flows.
149
+ - Use \`context({name: "symbolName"})\` for callers, callees, and flows.
150
150
  - For security review, \`explain({target: "fileOrSymbol"})\` lists taint findings (source→sink flows; needs \`analyze --pdg\`).${hasPdg
151
151
  ? `\n- For control/data dependence, \`pdg_query({mode: "controls", target: "fileOrSymbol"})\` answers "under what condition does X run?" (CDG, incl. guard clauses) and \`pdg_query({mode: "flows", target, variable})\` traces "where does variable Y flow?" (REACHING_DEF). \`--pdg\` layer.`
152
152
  : ''}
@@ -58,6 +58,8 @@ export declare function sanitizeDetectedBranch(value: string | null | undefined)
58
58
  * (the normal case). Throws {@link GitNexusRcError} on any problem.
59
59
  */
60
60
  export declare function loadAnalyzeConfig(repoRoot: string): Partial<AnalyzeOptions> | undefined;
61
+ /** Load `.gitnexusrc` through the strict bounded reader used by watch mode. */
62
+ export declare function loadAnalyzeConfigStrict(repoRoot: string): Promise<Partial<AnalyzeOptions> | undefined>;
61
63
  /**
62
64
  * Merge CLI options over `.gitnexusrc` defaults. CLI wins whenever it provides a
63
65
  * value — including an explicit `false` (so an explicit CLI off-switch beats a
@@ -29,6 +29,7 @@
29
29
  */
30
30
  import fs from 'node:fs';
31
31
  import path from 'node:path';
32
+ import { readRepoControlFile } from '../config/repo-control-file.js';
32
33
  export const GITNEXUS_RC_FILENAME = '.gitnexusrc';
33
34
  /** Final fallback when no branch is configured or detectable. */
34
35
  export const DEFAULT_BRANCH_FALLBACK = 'main';
@@ -328,6 +329,21 @@ export function loadAnalyzeConfig(repoRoot) {
328
329
  return undefined;
329
330
  throw new GitNexusRcError(`Could not read ${GITNEXUS_RC_FILENAME}: ${err.message}`);
330
331
  }
332
+ return parseAnalyzeConfig(raw);
333
+ }
334
+ /** Load `.gitnexusrc` through the strict bounded reader used by watch mode. */
335
+ export async function loadAnalyzeConfigStrict(repoRoot) {
336
+ let raw;
337
+ try {
338
+ raw = await readRepoControlFile(repoRoot, GITNEXUS_RC_FILENAME);
339
+ }
340
+ catch (err) {
341
+ throw new GitNexusRcError(`Could not read ${GITNEXUS_RC_FILENAME}: ${err.message}`);
342
+ }
343
+ return raw === null ? undefined : parseAnalyzeConfig(raw);
344
+ }
345
+ function parseAnalyzeConfig(rawInput) {
346
+ let raw = rawInput;
331
347
  // Strip a leading UTF-8 BOM: Node's 'utf-8' decode keeps it, and JSON.parse
332
348
  // then fails with a confusing "Unexpected token" on an otherwise-valid file
333
349
  // (#1996 tri-review). Only one leading BOM is stripped; in-string control
@@ -15,6 +15,10 @@
15
15
  * import cycle. `analyze.ts` re-exports the type for existing importers.
16
16
  */
17
17
  export interface AnalyzeOptions {
18
+ /** Keep this repository current with serialized incremental refreshes. */
19
+ watch?: boolean;
20
+ /** Watch quiet period in milliseconds. */
21
+ debounce?: string;
18
22
  force?: boolean;
19
23
  repairFts?: boolean;
20
24
  /**
@@ -25,6 +25,22 @@ export declare function computeHeapCapMb(totalBytes: number, constrainedBytes: n
25
25
  * later-flag-wins semantics when NODE_OPTIONS repeats a flag.
26
26
  */
27
27
  export declare function parseMaxOldSpaceMb(nodeOptions: string): number | null;
28
+ /** Re-exec the process with the RAM-aware auto heap cap + larger semi-space/stack
29
+ * if we're currently below that.
30
+ *
31
+ * Heap-source precedence (#2649):
32
+ * - an explicit per-invocation `--max-old-space-size` (execArgv) always wins;
33
+ * - `GITNEXUS_MEMORY=off` declines the memory autopilot entirely;
34
+ * - an ambient NODE_OPTIONS heap >= the auto cap is honored as-is;
35
+ * - an ambient NODE_OPTIONS heap BELOW the auto cap is treated as an
36
+ * inherited environment default (devcontainers/CI export one for other
37
+ * tooling), not a deliberate per-run choice: warn and respawn with the
38
+ * auto cap. Pre-#2649 this returned early and large repos then OOM'd on
39
+ * whatever heap the environment happened to specify. */
40
+ export declare function forwardedSignalExitCode(signal: NodeJS.Signals, cleanTermination: boolean): number;
41
+ export declare function ensureHeap(options?: {
42
+ cleanForwardedTermination?: boolean;
43
+ }): Promise<boolean>;
28
44
  /**
29
45
  * CLI `analyze` flag shape. Defined in `./analyze-options.js` so
30
46
  * `analyze-config.ts` can reference it without importing this module back —
@@ -50,3 +66,4 @@ export declare const shouldGenerateCommunitySkillFiles: (options: Pick<AnalyzeOp
50
66
  export declare const analyzeCommand: (inputPath?: string, options?: AnalyzeOptions, runnerIdentityAtBootstrap?: AnalyzerRunnerIdentity) => Promise<void>;
51
67
  /** Commander entrypoint used only by the capture-before-import lazy bootstrap. */
52
68
  export declare const analyzeCommandWithRunnerIdentity: (runnerIdentityAtBootstrap: AnalyzerRunnerIdentity, inputPath?: string, options?: AnalyzeOptions) => Promise<void>;
69
+ export declare function analyzeOrWatchCommandWithRunnerIdentity(runnerIdentityAtBootstrap: AnalyzerRunnerIdentity, inputPath?: string, options?: AnalyzeOptions): Promise<void>;
@@ -282,17 +282,29 @@ const runRespawnedAnalyze = (args, env) => new Promise((resolve) => {
282
282
  let stdout = '';
283
283
  let stderr = '';
284
284
  let settled = false;
285
- const finish = (exit) => {
286
- if (settled)
287
- return;
288
- settled = true;
289
- resolve(exit);
290
- };
285
+ let forwardedSignal;
291
286
  const child = spawn(process.execPath, [...args], {
292
287
  stdio: ['inherit', 'pipe', 'pipe'],
293
288
  windowsHide: true,
294
289
  env,
295
290
  });
291
+ const forwardSignal = (signal) => {
292
+ forwardedSignal ??= signal;
293
+ if (child.exitCode === null && child.signalCode === null)
294
+ child.kill(signal);
295
+ };
296
+ const forwardSigint = () => forwardSignal('SIGINT');
297
+ const forwardSigterm = () => forwardSignal('SIGTERM');
298
+ const finish = (exit) => {
299
+ if (settled)
300
+ return;
301
+ settled = true;
302
+ process.removeListener('SIGINT', forwardSigint);
303
+ process.removeListener('SIGTERM', forwardSigterm);
304
+ resolve({ ...exit, forwardedSignal });
305
+ };
306
+ process.once('SIGINT', forwardSigint);
307
+ process.once('SIGTERM', forwardSigterm);
296
308
  child.stdout?.on('data', (chunk) => {
297
309
  stdout = appendOutputTail(stdout, chunk);
298
310
  realStdoutWrite(chunk);
@@ -412,7 +424,16 @@ export function parseMaxOldSpaceMb(nodeOptions) {
412
424
  * tooling), not a deliberate per-run choice: warn and respawn with the
413
425
  * auto cap. Pre-#2649 this returned early and large repos then OOM'd on
414
426
  * whatever heap the environment happened to specify. */
415
- async function ensureHeap() {
427
+ export function forwardedSignalExitCode(signal, cleanTermination) {
428
+ if (cleanTermination)
429
+ return 0;
430
+ if (signal === 'SIGINT')
431
+ return 130;
432
+ if (signal === 'SIGTERM')
433
+ return 143;
434
+ return 1;
435
+ }
436
+ export async function ensureHeap(options = {}) {
416
437
  // Explicit opt-out disables auto-sizing ENTIRELY — both the ambient-pin
417
438
  // override and the default v8-limit respawn — and is honored SILENTLY:
418
439
  // the operator already made the call, and stderr-sensitive consumers
@@ -456,6 +477,10 @@ async function ensureHeap() {
456
477
  if (shouldBridgeRespawnProgressTty())
457
478
  childEnv[RESPAWN_PROGRESS_ENV] = '1';
458
479
  const childExit = await runRespawnedAnalyze(childArgs, childEnv);
480
+ if (childExit.forwardedSignal !== undefined) {
481
+ process.exitCode = forwardedSignalExitCode(childExit.forwardedSignal, options.cleanForwardedTermination === true);
482
+ return true;
483
+ }
459
484
  if (childExit.status !== 0 || childExit.signal) {
460
485
  if (childProcessLikelyOom(childExit)) {
461
486
  cliError(` Analysis likely ran out of memory (heap cap auto-sized to ${RESPAWN_HEAP_MB}MB ≈ 0.75x RAM).\n` +
@@ -573,6 +598,14 @@ export const analyzeCommand = async (inputPath, options, runnerIdentityAtBootstr
573
598
  };
574
599
  /** Commander entrypoint used only by the capture-before-import lazy bootstrap. */
575
600
  export const analyzeCommandWithRunnerIdentity = async (runnerIdentityAtBootstrap, inputPath, options) => analyzeCommand(inputPath, options, runnerIdentityAtBootstrap);
601
+ export async function analyzeOrWatchCommandWithRunnerIdentity(runnerIdentityAtBootstrap, inputPath, options = {}) {
602
+ if (options.watch) {
603
+ const { watchCommandWithRunnerIdentity } = await import('./watch.js');
604
+ await watchCommandWithRunnerIdentity(runnerIdentityAtBootstrap, inputPath, options);
605
+ return;
606
+ }
607
+ await analyzeCommandWithRunnerIdentity(runnerIdentityAtBootstrap, inputPath, options);
608
+ }
576
609
  const analyzeCommandImpl = async (inputPath, cliOptions, runnerIdentityAtBootstrap) => {
577
610
  console.log('\n GitNexus Analyzer\n');
578
611
  // ── Resolve the target repo root ──────────────────────────────────
@@ -1140,6 +1173,9 @@ const analyzeCommandImpl = async (inputPath, cliOptions, runnerIdentityAtBootstr
1140
1173
  console.error = origError;
1141
1174
  bar.stop();
1142
1175
  console.log(' Already up to date\n');
1176
+ if (runOptions.registryName) {
1177
+ console.log(` Registry name: ${result.repoName}\n`);
1178
+ }
1143
1179
  if (baseRefRefreshed.length > 0) {
1144
1180
  console.log(` Updated base_ref to "${resolvedDefaultBranch}" in ${baseRefRefreshed.join(', ')}\n`);
1145
1181
  }
@@ -240,6 +240,17 @@ function formatTruncationSuffix(result) {
240
240
  : '';
241
241
  return label ? ` (by ${label})` : '';
242
242
  }
243
+ function pushCallgraphRiskLines(lines, result) {
244
+ if (result.risk) {
245
+ lines.push(`Risk: ${result.risk}`);
246
+ }
247
+ if (result.riskNote) {
248
+ lines.push(String(result.riskNote));
249
+ }
250
+ if (result.riskScale?.comparableAcrossKinds === false && result.riskSharedAxes) {
251
+ lines.push(`Shared-axes risk: ${result.riskSharedAxes} (process/module axes are unavailable — compare File vs symbol only; do not use this to waive a HIGH/CRITICAL risk warning)`);
252
+ }
253
+ }
243
254
  export function formatImpactResult(result) {
244
255
  if (result.error) {
245
256
  const suggestion = result.suggestion ? `\nSuggestion: ${result.suggestion}` : '';
@@ -467,15 +478,20 @@ export function formatImpactResult(result) {
467
478
  // #1858 — "isolated" is a confident claim. If an interface / indirection
468
479
  // boundary is on the path, the true count is a lower bound, not zero;
469
480
  // callers binding via DI / dynamic dispatch were not traced. Say so instead.
481
+ const lines = [];
470
482
  if (result.epistemic === 'lower-bound') {
471
- const lines = [
472
- `${target?.name || '?'}: no direct ${direction} dependencies traced, but this is a LOWER BOUND — unresolved indirection on the path (actual impact may be higher):`,
473
- ];
483
+ lines.push(`${target?.name || '?'}: no direct ${direction} dependencies traced, but this is a LOWER BOUND — unresolved indirection on the path (actual impact may be higher):`);
474
484
  for (const b of result.boundaries || [])
475
485
  lines.push(` • ${b}`);
476
- return lines.join('\n');
477
486
  }
478
- return `${target?.name || '?'}: No ${direction} dependencies found. This symbol appears isolated.`;
487
+ else if (direction === 'upstream') {
488
+ lines.push(`${target?.name || '?'}: No ${direction} callers resolved. This is not evidence the symbol is unused or isolated.`);
489
+ }
490
+ else {
491
+ lines.push(`${target?.name || '?'}: No ${direction} dependencies found.`);
492
+ }
493
+ pushCallgraphRiskLines(lines, result);
494
+ return lines.join('\n');
479
495
  }
480
496
  const lines = [];
481
497
  const dirLabel = direction === 'upstream' ? 'depends on this (will break if changed)' : 'this depends on';
@@ -490,6 +506,7 @@ export function formatImpactResult(result) {
490
506
  for (const b of result.boundaries || [])
491
507
  lines.push(` • ${b}`);
492
508
  }
509
+ pushCallgraphRiskLines(lines, result);
493
510
  lines.push('');
494
511
  const depthLabels = {
495
512
  1: 'WILL BREAK (direct)',
package/dist/cli/group.js CHANGED
@@ -172,8 +172,9 @@ export function registerGroupCommands(program) {
172
172
  .action(async (name, opts) => {
173
173
  const { getGroupDir, getDefaultGitnexusDir } = await import('../core/group/storage.js');
174
174
  const { loadGroupConfig } = await import('../core/group/config-parser.js');
175
- const { syncGroup } = await import('../core/group/sync.js');
175
+ const { syncGroup, formatGroupSyncAmbiguousError } = await import('../core/group/sync.js');
176
176
  const { GroupSyncLockError } = await import('../core/group/group-lock.js');
177
+ const { RegistryAmbiguousTargetError } = await import('../storage/repo-manager.js');
177
178
  const groupDir = getGroupDir(getDefaultGitnexusDir(), name);
178
179
  const config = await loadGroupConfig(groupDir);
179
180
  console.log(`Syncing group "${name}" (${Object.keys(config.repos).length} repos)...\n`);
@@ -186,6 +187,11 @@ export function registerGroupCommands(program) {
186
187
  });
187
188
  }
188
189
  catch (err) {
190
+ if (err instanceof RegistryAmbiguousTargetError) {
191
+ logger.error(`⚠️ Did not sync group "${name}": ${formatGroupSyncAmbiguousError(err)}`);
192
+ process.exitCode = 1;
193
+ return;
194
+ }
189
195
  // A sync that could not take the group's lock did NOT run and wrote
190
196
  // nothing (R9 fails closed). That is an operator-actionable outcome, not
191
197
  // a crash, so report it as a failed command rather than letting it
@@ -68,6 +68,8 @@ const OPTION_DESCRIPTION_KEYS = {
68
68
  'analyze|--embedding-batch-size <n>': 'help.option.analyze.embeddingBatchSize',
69
69
  'analyze|--embedding-sub-batch-size <n>': 'help.option.analyze.embeddingSubBatchSize',
70
70
  'analyze|--embedding-device <device>': 'help.option.analyze.embeddingDevice',
71
+ 'analyze|--watch': 'help.option.analyze.watch',
72
+ 'analyze|--debounce <ms>': 'help.option.analyze.debounce',
71
73
  'index|-f, --force': 'help.option.index.force',
72
74
  'index|--allow-non-git': 'help.option.index.allowNonGit',
73
75
  'mcp|--http': 'help.option.mcp.http',
@@ -32,6 +32,14 @@ export declare const en: {
32
32
  readonly 'status.detached': "(detached HEAD)";
33
33
  readonly 'status.workspaceIndexLabel': "Workspace index: last analyzed on '{{primary}}' (re-run gitnexus analyze to follow the current branch)";
34
34
  readonly 'status.status': "Status";
35
+ readonly 'status.indexContentCurrent': "Index content: matches all {{count}} covered file(s)";
36
+ readonly 'status.indexContentDrifted': "Index content: {{changed}} changed, {{added}} added, {{deleted}} deleted";
37
+ readonly 'status.indexContentMore': " ...and {{count}} more {{label}}";
38
+ readonly 'status.indexContentUnmeasurable': "Index content: not comparable ({{reason}}); fell back to the working-tree check";
39
+ readonly 'status.indexContentScanFailed': "Index content: coverage scan failed; treating the index as stale";
40
+ readonly 'status.driftChanged': "changed";
41
+ readonly 'status.driftAdded': "added";
42
+ readonly 'status.driftDeleted': "deleted";
35
43
  readonly 'status.upToDate': "✅ up-to-date";
36
44
  readonly 'status.stale': "⚠️ stale (re-run gitnexus analyze)";
37
45
  readonly 'clean.deleteAll': "This will delete GitNexus indexes for {{count}} repo(s):";
@@ -171,6 +179,8 @@ export declare const en: {
171
179
  readonly 'help.option.analyze.embeddingBatchSize': "Number of nodes per embedding batch";
172
180
  readonly 'help.option.analyze.embeddingSubBatchSize': "Number of chunks per embedding model call";
173
181
  readonly 'help.option.analyze.embeddingDevice': "Embedding device: auto, cpu, dml, cuda, or wasm";
182
+ readonly 'help.option.analyze.watch': "Keep the index current with serialized incremental refreshes";
183
+ readonly 'help.option.analyze.debounce': "Watch quiet period before refreshing (milliseconds)";
174
184
  readonly 'help.option.index.force': "Register even if index metadata is missing (stats will be empty)";
175
185
  readonly 'help.option.index.allowNonGit': "Allow registering folders that are not Git repositories";
176
186
  readonly 'help.option.port': "Port number";
@@ -184,7 +194,7 @@ export declare const en: {
184
194
  readonly 'help.option.clean.branch': "Delete only the named branch index (not the workspace index)";
185
195
  readonly 'help.option.clean.lbugSidecars': "Clean parked LadybugDB recovery sidecars (missing-shadow WAL quarantines and dirty-recovery parks)";
186
196
  readonly 'help.option.wiki.force': "Force full regeneration even if up to date";
187
- readonly 'help.option.wiki.provider': "LLM provider: minimax, openai, openrouter, azure, custom, cursor, claude, codex, or opencode (default: minimax)";
197
+ readonly 'help.option.wiki.provider': "LLM provider: minimax, openai, openrouter, azure, custom, cursor, claude, codex, opencode, or grok (default: minimax)";
188
198
  readonly 'help.option.wiki.model': "LLM model or deployment name (default: MiniMax-M3)";
189
199
  readonly 'help.option.wiki.baseUrl': "LLM API base URL. Azure v1: https://{resource}.openai.azure.com/openai/v1";
190
200
  readonly 'help.option.wiki.apiKey': "LLM API key or Azure api-key (saved to ~/.gitnexus/config.json)";
@@ -32,6 +32,14 @@ export const en = {
32
32
  'status.detached': '(detached HEAD)',
33
33
  'status.workspaceIndexLabel': "Workspace index: last analyzed on '{{primary}}' (re-run gitnexus analyze to follow the current branch)",
34
34
  'status.status': 'Status',
35
+ 'status.indexContentCurrent': 'Index content: matches all {{count}} covered file(s)',
36
+ 'status.indexContentDrifted': 'Index content: {{changed}} changed, {{added}} added, {{deleted}} deleted',
37
+ 'status.indexContentMore': ' ...and {{count}} more {{label}}',
38
+ 'status.indexContentUnmeasurable': 'Index content: not comparable ({{reason}}); fell back to the working-tree check',
39
+ 'status.indexContentScanFailed': 'Index content: coverage scan failed; treating the index as stale',
40
+ 'status.driftChanged': 'changed',
41
+ 'status.driftAdded': 'added',
42
+ 'status.driftDeleted': 'deleted',
35
43
  'status.upToDate': '✅ up-to-date',
36
44
  'status.stale': '⚠️ stale (re-run gitnexus analyze)',
37
45
  'clean.deleteAll': 'This will delete GitNexus indexes for {{count}} repo(s):',
@@ -173,6 +181,8 @@ export const en = {
173
181
  'help.option.analyze.embeddingBatchSize': 'Number of nodes per embedding batch',
174
182
  'help.option.analyze.embeddingSubBatchSize': 'Number of chunks per embedding model call',
175
183
  'help.option.analyze.embeddingDevice': 'Embedding device: auto, cpu, dml, cuda, or wasm',
184
+ 'help.option.analyze.watch': 'Keep the index current with serialized incremental refreshes',
185
+ 'help.option.analyze.debounce': 'Watch quiet period before refreshing (milliseconds)',
176
186
  'help.option.index.force': 'Register even if index metadata is missing (stats will be empty)',
177
187
  'help.option.index.allowNonGit': 'Allow registering folders that are not Git repositories',
178
188
  'help.option.port': 'Port number',
@@ -186,7 +196,7 @@ export const en = {
186
196
  'help.option.clean.branch': 'Delete only the named branch index (not the workspace index)',
187
197
  'help.option.clean.lbugSidecars': 'Clean parked LadybugDB recovery sidecars (missing-shadow WAL quarantines and dirty-recovery parks)',
188
198
  'help.option.wiki.force': 'Force full regeneration even if up to date',
189
- 'help.option.wiki.provider': 'LLM provider: minimax, openai, openrouter, azure, custom, cursor, claude, codex, or opencode (default: minimax)',
199
+ 'help.option.wiki.provider': 'LLM provider: minimax, openai, openrouter, azure, custom, cursor, claude, codex, opencode, or grok (default: minimax)',
190
200
  'help.option.wiki.model': 'LLM model or deployment name (default: MiniMax-M3)',
191
201
  'help.option.wiki.baseUrl': 'LLM API base URL. Azure v1: https://{resource}.openai.azure.com/openai/v1',
192
202
  'help.option.wiki.apiKey': 'LLM API key or Azure api-key (saved to ~/.gitnexus/config.json)',