gitnexus 1.6.11-rc.3 → 1.6.11-rc.30

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 (211) hide show
  1. package/README.md +52 -23
  2. package/dist/_shared/graph/types.d.ts +6 -0
  3. package/dist/_shared/graph/types.d.ts.map +1 -1
  4. package/dist/_shared/impact-risk.d.ts +37 -0
  5. package/dist/_shared/impact-risk.d.ts.map +1 -0
  6. package/dist/_shared/impact-risk.js +92 -0
  7. package/dist/_shared/impact-risk.js.map +1 -0
  8. package/dist/_shared/index.d.ts +2 -0
  9. package/dist/_shared/index.d.ts.map +1 -1
  10. package/dist/_shared/index.js +2 -0
  11. package/dist/_shared/index.js.map +1 -1
  12. package/dist/cli/ai-context.d.ts +4 -0
  13. package/dist/cli/ai-context.js +92 -16
  14. package/dist/cli/analyze-config.d.ts +2 -0
  15. package/dist/cli/analyze-config.js +30 -0
  16. package/dist/cli/analyze-options.d.ts +9 -0
  17. package/dist/cli/analyze.d.ts +17 -0
  18. package/dist/cli/analyze.js +47 -7
  19. package/dist/cli/eval-server.js +22 -5
  20. package/dist/cli/group.js +7 -1
  21. package/dist/cli/help-i18n.js +2 -0
  22. package/dist/cli/i18n/en.d.ts +12 -2
  23. package/dist/cli/i18n/en.js +12 -2
  24. package/dist/cli/i18n/resources.d.ts +22 -2
  25. package/dist/cli/i18n/zh-CN.d.ts +10 -0
  26. package/dist/cli/i18n/zh-CN.js +12 -2
  27. package/dist/cli/index.js +13 -4
  28. package/dist/cli/setup.js +37 -10
  29. package/dist/cli/status.js +91 -6
  30. package/dist/cli/watch-queue.d.ts +41 -0
  31. package/dist/cli/watch-queue.js +184 -0
  32. package/dist/cli/watch.d.ts +20 -0
  33. package/dist/cli/watch.js +374 -0
  34. package/dist/config/ignore-service.d.ts +11 -0
  35. package/dist/config/ignore-service.js +41 -4
  36. package/dist/config/repo-control-file.d.ts +3 -0
  37. package/dist/config/repo-control-file.js +115 -0
  38. package/dist/core/analyzer-identity.js +21 -3
  39. package/dist/core/group/config-parser.js +8 -1
  40. package/dist/core/group/cross-impact.d.ts +5 -1
  41. package/dist/core/group/cross-impact.js +59 -6
  42. package/dist/core/group/extractors/http-patterns/java.js +18 -4
  43. package/dist/core/group/extractors/http-patterns/kotlin.js +2 -0
  44. package/dist/core/group/extractors/java-workspace-extractor.js +244 -31
  45. package/dist/core/group/normalization.d.ts +38 -1
  46. package/dist/core/group/normalization.js +59 -3
  47. package/dist/core/group/service.d.ts +11 -0
  48. package/dist/core/group/service.js +13 -1
  49. package/dist/core/group/sync.d.ts +24 -1
  50. package/dist/core/group/sync.js +46 -8
  51. package/dist/core/group/types.d.ts +25 -1
  52. package/dist/core/incremental/derived-writeback.d.ts +36 -0
  53. package/dist/core/incremental/derived-writeback.js +68 -0
  54. package/dist/core/incremental/spring-config-drift.d.ts +12 -0
  55. package/dist/core/incremental/spring-config-drift.js +46 -0
  56. package/dist/core/incremental/subgraph-extract.d.ts +6 -4
  57. package/dist/core/incremental/subgraph-extract.js +7 -5
  58. package/dist/core/index-content-drift.d.ts +54 -0
  59. package/dist/core/index-content-drift.js +127 -0
  60. package/dist/core/ingestion/filesystem-walker.d.ts +15 -5
  61. package/dist/core/ingestion/filesystem-walker.js +20 -3
  62. package/dist/core/ingestion/frameworks/spring/actuator-runtime.d.ts +26 -0
  63. package/dist/core/ingestion/frameworks/spring/actuator-runtime.js +843 -0
  64. package/dist/core/ingestion/frameworks/spring/argument-facts.d.ts +80 -0
  65. package/dist/core/ingestion/frameworks/spring/argument-facts.js +85 -0
  66. package/dist/core/ingestion/frameworks/spring/config-bindings.d.ts +1 -0
  67. package/dist/core/ingestion/frameworks/spring/config-bindings.js +2 -1
  68. package/dist/core/ingestion/frameworks/spring/dynamic-lookups.d.ts +22 -0
  69. package/dist/core/ingestion/frameworks/spring/dynamic-lookups.js +124 -0
  70. package/dist/core/ingestion/frameworks/spring/message-producers.d.ts +78 -0
  71. package/dist/core/ingestion/frameworks/spring/message-producers.js +90 -0
  72. package/dist/core/ingestion/frameworks/spring/non-http-handlers.d.ts +29 -0
  73. package/dist/core/ingestion/language-provider.d.ts +81 -1
  74. package/dist/core/ingestion/language-provider.js +22 -0
  75. package/dist/core/ingestion/languages/csharp/razor-view-components.d.ts +62 -0
  76. package/dist/core/ingestion/languages/csharp/razor-view-components.js +954 -0
  77. package/dist/core/ingestion/languages/csharp/resolution-config.d.ts +3 -0
  78. package/dist/core/ingestion/languages/csharp/resolution-config.js +6 -1
  79. package/dist/core/ingestion/languages/csharp/scope-resolver.js +8 -0
  80. package/dist/core/ingestion/languages/java/analysis-features.d.ts +1 -1
  81. package/dist/core/ingestion/languages/java/analysis-features.js +14 -6
  82. package/dist/core/ingestion/languages/java/capture-side-channel.d.ts +8 -0
  83. package/dist/core/ingestion/languages/java/capture-side-channel.js +34 -0
  84. package/dist/core/ingestion/languages/java/captures.js +22 -1
  85. package/dist/core/ingestion/languages/java/lombok-synthesizer.d.ts +42 -0
  86. package/dist/core/ingestion/languages/java/lombok-synthesizer.js +439 -0
  87. package/dist/core/ingestion/languages/java/scope-resolver.js +2 -0
  88. package/dist/core/ingestion/languages/java/spring-actuator.d.ts +2 -0
  89. package/dist/core/ingestion/languages/java/spring-actuator.js +62 -0
  90. package/dist/core/ingestion/languages/java/spring-di.d.ts +17 -1
  91. package/dist/core/ingestion/languages/java/spring-di.js +44 -2
  92. package/dist/core/ingestion/languages/java/spring-dynamic-lookup.d.ts +8 -0
  93. package/dist/core/ingestion/languages/java/spring-dynamic-lookup.js +62 -0
  94. package/dist/core/ingestion/languages/java/spring-message-producers.d.ts +20 -0
  95. package/dist/core/ingestion/languages/java/spring-message-producers.js +83 -0
  96. package/dist/core/ingestion/languages/java/spring-non-http-handlers.d.ts +11 -1
  97. package/dist/core/ingestion/languages/java/spring-non-http-handlers.js +13 -3
  98. package/dist/core/ingestion/languages/java.js +10 -7
  99. package/dist/core/ingestion/languages/jvm/accessor-synthesis.d.ts +99 -0
  100. package/dist/core/ingestion/languages/jvm/accessor-synthesis.js +173 -0
  101. package/dist/core/ingestion/languages/jvm/beanspec.d.ts +17 -0
  102. package/dist/core/ingestion/languages/jvm/beanspec.js +42 -0
  103. package/dist/core/ingestion/languages/kotlin/capture-side-channel.d.ts +15 -0
  104. package/dist/core/ingestion/languages/kotlin/capture-side-channel.js +50 -0
  105. package/dist/core/ingestion/languages/kotlin/captures.js +24 -1
  106. package/dist/core/ingestion/languages/kotlin/lombok-synthesizer.d.ts +26 -0
  107. package/dist/core/ingestion/languages/kotlin/lombok-synthesizer.js +417 -0
  108. package/dist/core/ingestion/languages/kotlin/scope-resolver.js +4 -0
  109. package/dist/core/ingestion/languages/kotlin/spring-actuator.d.ts +4 -0
  110. package/dist/core/ingestion/languages/kotlin/spring-actuator.js +172 -0
  111. package/dist/core/ingestion/languages/kotlin/spring-config-bindings.d.ts +18 -0
  112. package/dist/core/ingestion/languages/kotlin/spring-config-bindings.js +411 -0
  113. package/dist/core/ingestion/languages/kotlin/spring-di.d.ts +51 -1
  114. package/dist/core/ingestion/languages/kotlin/spring-di.js +86 -6
  115. package/dist/core/ingestion/languages/kotlin/spring-dynamic-lookup.d.ts +8 -0
  116. package/dist/core/ingestion/languages/kotlin/spring-dynamic-lookup.js +77 -0
  117. package/dist/core/ingestion/languages/kotlin/spring-message-producers.d.ts +17 -0
  118. package/dist/core/ingestion/languages/kotlin/spring-message-producers.js +119 -0
  119. package/dist/core/ingestion/languages/kotlin/spring-non-http-handlers.d.ts +16 -0
  120. package/dist/core/ingestion/languages/kotlin/spring-non-http-handlers.js +77 -2
  121. package/dist/core/ingestion/languages/kotlin.js +5 -0
  122. package/dist/core/ingestion/model/field-registry.d.ts +3 -3
  123. package/dist/core/ingestion/model/field-registry.js +11 -7
  124. package/dist/core/ingestion/model/method-registry.d.ts +3 -3
  125. package/dist/core/ingestion/model/method-registry.js +13 -8
  126. package/dist/core/ingestion/model/type-registry.js +8 -4
  127. package/dist/core/ingestion/pipeline-phases/di.js +47 -14
  128. package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +3 -1
  129. package/dist/core/ingestion/pipeline-phases/parse-impl.js +63 -87
  130. package/dist/core/ingestion/pipeline-phases/parse.d.ts +2 -0
  131. package/dist/core/ingestion/pipeline-phases/processes.d.ts +2 -1
  132. package/dist/core/ingestion/pipeline-phases/processes.js +39 -4
  133. package/dist/core/ingestion/pipeline-phases/runner.d.ts +4 -1
  134. package/dist/core/ingestion/pipeline-phases/runner.js +34 -14
  135. package/dist/core/ingestion/pipeline-phases/scan.js +106 -13
  136. package/dist/core/ingestion/pipeline-phases/spring-auto-configuration.d.ts +2 -0
  137. package/dist/core/ingestion/pipeline-phases/spring-auto-configuration.js +8 -0
  138. package/dist/core/ingestion/pipeline.d.ts +14 -0
  139. package/dist/core/ingestion/pipeline.js +44 -12
  140. package/dist/core/ingestion/route-extractors/constant-resolver.d.ts +16 -0
  141. package/dist/core/ingestion/route-extractors/constant-resolver.js +10 -0
  142. package/dist/core/ingestion/route-extractors/java-const-resolver.d.ts +27 -1
  143. package/dist/core/ingestion/route-extractors/java-const-resolver.js +161 -13
  144. package/dist/core/ingestion/route-extractors/kotlin-const-resolver.d.ts +7 -8
  145. package/dist/core/ingestion/route-extractors/kotlin-const-resolver.js +209 -23
  146. package/dist/core/ingestion/scope-extractor.js +1 -0
  147. package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +28 -0
  148. package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.d.ts +11 -1
  149. package/dist/core/ingestion/scope-resolution/passes/callable-value-flow.js +26 -6
  150. package/dist/core/ingestion/scope-resolution/pipeline/run.js +5 -2
  151. package/dist/core/ingestion/utils/ast-helpers.d.ts +16 -0
  152. package/dist/core/ingestion/utils/ast-helpers.js +18 -0
  153. package/dist/core/ingestion/workers/parse-worker.js +33 -3
  154. package/dist/core/lbug/csv-generator.js +26 -21
  155. package/dist/core/lbug/graph-emit-sink.d.ts +3 -2
  156. package/dist/core/lbug/graph-emit-sink.js +4 -2
  157. package/dist/core/lbug/lbug-adapter.d.ts +59 -0
  158. package/dist/core/lbug/lbug-adapter.js +155 -2
  159. package/dist/core/lbug/schema.d.ts +1 -1
  160. package/dist/core/lbug/schema.js +3 -0
  161. package/dist/core/run-analyze.d.ts +22 -0
  162. package/dist/core/run-analyze.js +313 -23
  163. package/dist/core/search/fts-indexes.d.ts +19 -1
  164. package/dist/core/search/fts-indexes.js +28 -1
  165. package/dist/mcp/local/local-backend.d.ts +24 -7
  166. package/dist/mcp/local/local-backend.js +236 -84
  167. package/dist/mcp/local/pdg-impact.d.ts +8 -4
  168. package/dist/mcp/local/pdg-impact.js +7 -2
  169. package/dist/mcp/repository-policy.d.ts +5 -1
  170. package/dist/mcp/repository-policy.js +48 -4
  171. package/dist/mcp/resources.js +3 -1
  172. package/dist/mcp/server.js +6 -5
  173. package/dist/mcp/tools.js +35 -23
  174. package/dist/server/analyze-launch.d.ts +1 -0
  175. package/dist/server/analyze-launch.js +1 -0
  176. package/dist/server/api.d.ts +4 -0
  177. package/dist/server/api.js +69 -68
  178. package/dist/server/grep-params.d.ts +18 -0
  179. package/dist/server/grep-params.js +83 -0
  180. package/dist/server/grep-scan.d.ts +23 -0
  181. package/dist/server/grep-scan.js +107 -0
  182. package/dist/server/grep-worker.d.ts +1 -0
  183. package/dist/server/grep-worker.js +12 -0
  184. package/dist/server/mcp-http.d.ts +8 -0
  185. package/dist/server/mcp-http.js +16 -1
  186. package/dist/storage/file-hash.d.ts +5 -0
  187. package/dist/storage/file-hash.js +16 -6
  188. package/dist/storage/fs-atomic.d.ts +24 -0
  189. package/dist/storage/fs-atomic.js +86 -2
  190. package/dist/storage/git.d.ts +19 -8
  191. package/dist/storage/git.js +83 -24
  192. package/dist/storage/gitnexus-managed-paths.d.ts +36 -0
  193. package/dist/storage/gitnexus-managed-paths.js +46 -0
  194. package/dist/storage/parse-cache.d.ts +22 -4
  195. package/dist/storage/parse-cache.js +126 -29
  196. package/dist/storage/parsedfile-store.d.ts +34 -60
  197. package/dist/storage/parsedfile-store.js +177 -171
  198. package/dist/storage/repo-manager.d.ts +9 -0
  199. package/dist/storage/repo-manager.js +23 -2
  200. package/dist/storage/repo-meta.d.ts +24 -0
  201. package/dist/storage/v8-sidecar.d.ts +48 -0
  202. package/dist/storage/v8-sidecar.js +347 -0
  203. package/dist/types/pipeline.d.ts +14 -0
  204. package/package.json +4 -2
  205. package/scripts/cross-platform-shard.ts +4 -2
  206. package/scripts/cross-platform-tests.ts +5 -1
  207. package/skills/gitnexus-cli.md +8 -1
  208. package/skills/gitnexus-impact-analysis.md +9 -0
  209. package/web/assets/{agent-Dr4l5EOp.js → agent-CFqT4hjR.js} +108 -104
  210. package/web/assets/{index-2zdvEdzg.js → index-BMIniRtX.js} +3 -3
  211. 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,15 +234,17 @@ 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)
240
241
  gitnexus embeddings install # Fetch the optional local embedding stack on demand (--cuda, --force)
241
242
  gitnexus analyze --skills # Generate repo-specific skill files from detected communities
242
- gitnexus analyze --skip-agents-md # Preserve custom AGENTS.md/CLAUDE.md gitnexus section edits
243
+ gitnexus analyze --skip-agents-md # Preserve custom AGENTS.md/CLAUDE.md gitnexus section edits (does not skip standard skills; use --skip-skills; community --skills files are unaffected)
243
244
  gitnexus analyze --skip-skills # Skip installing standard .claude/skills/gitnexus-* skill files
244
245
  gitnexus analyze --skip-git # Index folders that are not Git repositories
245
246
  gitnexus analyze --workers <n> # Parse worker pool size (>=1; default: cores-1, capped at 16)
247
+ gitnexus analyze --spring-actuator ./actuator # Enrich with local Spring Boot Actuator JSON snapshots
246
248
  gitnexus analyze --verbose # Log skipped files when parsers are unavailable
247
249
  gitnexus analyze --max-file-size 1024 # Skip files larger than N KB (default: 512, cap: 32768)
248
250
  gitnexus analyze --worker-timeout 60 # Increase worker idle timeout for slow parses
@@ -282,6 +284,31 @@ gitnexus group status <name> # Check staleness of repos in a group
282
284
  gitnexus group impact <name> --target <symbol> --repo <groupPath> # Cross-repo blast radius
283
285
  ```
284
286
 
287
+ `gitnexus analyze --watch` requires a Git repository. It performs an initial
288
+ analysis and then debounces scanner-admitted working-tree changes for 300 ms by
289
+ default into serialized incremental refreshes. Events arriving during a run
290
+ remain queued, and retryable failures retain the same batch with bounded
291
+ backoff. Invalid `.gitnexusrc` or ignore-file reloads pause ordinary refreshes
292
+ until the control file is fixed. Watch refreshes update only the graph: they
293
+ intentionally skip AGENTS.md / CLAUDE.md injection and standard skill
294
+ installation. Run a one-shot `gitnexus analyze` when those generated files need
295
+ updating. Stop watch mode with Ctrl+C.
296
+
297
+ Watch mode accepts `--debounce`, `--workers`, `--worker-timeout`,
298
+ `--max-file-size`, `--branch`, `--pdg`, `--name`, `--allow-duplicate-name`, and
299
+ `--verbose`. Explicit one-shot options such as `--force`, `--repair-fts`,
300
+ embedding flags, `--skills`, `--default-branch`, `--skip-agents-md`,
301
+ `--skip-skills`, `--no-stats`, `--self-commit`, `--index-only`, and `--skip-git`
302
+ are rejected. Unsupported defaults from `.gitnexusrc` are ignored with a warning.
303
+
304
+ POSIX requests clone-first copy-and-swap publication when the live index has no
305
+ orphan sidecars. Windows and sidecar fallback runs update in place: failures
306
+ known to occur before writes are retried, while a failure that may have mutated
307
+ the live index stops the watcher. Watch mode does not pull remotes. Running MCP
308
+ and `serve` processes periodically check for a newly published index and reopen
309
+ it without a restart. MCP checks are throttled to once every five seconds, so a
310
+ tool call before the next check can briefly use the previous index.
311
+
285
312
  GraphQL contract matching is opt-in in the group's `group.yaml`:
286
313
 
287
314
  ```yaml
@@ -297,6 +324,8 @@ and root fields. Dynamic decorator names, anonymous operations, and ambiguous or
297
324
  anchors are deliberately omitted. Add common infrastructure fields such as `/health` to
298
325
  `matching.exclude_links_paths` to keep those GraphQL contracts visible without cross-linking them.
299
326
 
327
+ `--spring-actuator` is explicitly opt-in. The path may be a JSON bundle keyed by `mappings`, `beans`, `conditions`, `configprops`, and/or `env`, or a directory containing endpoint-named JSON files. Runtime mappings and beans confirm matching static nodes; conditions and configuration property keys enrich existing evidence, with conservative runtime-only nodes added when no match exists. The configured input is excluded from source scanning; only normalized repository-relative exclusions are retained for future scans, never absolute paths. Env/configprops values, origins, condition messages, and source names are never persisted or printed. Enabled runs always rebuild because runtime snapshots are external to git freshness; omitting the option later rebuilds once to remove runtime evidence. Project config can set the same path with `springActuator` in `.gitnexusrc`.
328
+
300
329
  > **`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.
301
330
 
302
331
  ## Remote Embeddings
@@ -405,7 +434,7 @@ Installed automatically by both `gitnexus analyze` (per-repo) and `gitnexus setu
405
434
  LadybugDB native binary ships as a prebuild against that floor, so on an older host it cannot
406
435
  load and reinstalling does not help — see
407
436
  [Linux: `GLIBC_2.34' not found`](#linux-glibc_234-not-found).
408
- - **Windows, for full-text search:** the Microsoft Visual C++ 2015-2022 Redistributable (x64) *and*
437
+ - **Windows, for full-text search:** the Microsoft Visual C++ 2015-2022 Redistributable (x64) _and_
409
438
  OpenSSL 3 (`libssl-3-x64.dll`, `libcrypto-3-x64.dll`) resolvable on `PATH` — see
410
439
  [Windows: full-text search unavailable](#windows-full-text-search-unavailable).
411
440
 
@@ -682,17 +711,17 @@ For repositories with very large source files, `GITNEXUS_WORKER_SUB_BATCH_MAX_BY
682
711
 
683
712
  Four env vars expose the pool's resilience layers (respawn budget, cumulative-timeout cap, circuit breaker, startup handshake). Defaults are tuned for typical repos; bump them when an analyze legitimately needs more retries, or lower them to fail-fast on a known-bad shape.
684
713
 
685
- | Variable | Default | Effect |
686
- | ----------------------------------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
687
- | `GITNEXUS_WORKER_MAX_RESPAWNS_PER_SLOT` | `3` | Max replacement spawns per slot before the slot is dropped from the active rotation. |
688
- | `GITNEXUS_WORKER_MAX_CUMULATIVE_TIMEOUT_MS` | `5 × subBatchTimeoutMs` | Total retry wall-time budget per job before quarantining. Bounds exponentially-growing retry waits. |
689
- | `GITNEXUS_WORKER_CONSECUTIVE_FAILURE_THRESHOLD` | `max(3, poolSize)` | Per-slot consecutive deaths before the pool's circuit breaker trips. After tripping, dispatches require a fresh pool. |
690
- | `GITNEXUS_WORKER_SHUTDOWN_DRAIN_MS` | `30000` | Max wait at pool shutdown for a retired worker still inside native code — terminated at its next JS-safe point instead of mid-native-call, which would abort the process (`Napi::Error`, #2432). |
691
- | `GITNEXUS_WORKER_READY_TIMEOUT_MS` | `5000` | Startup budget for a parse worker to load its grammar bindings and report `{type:'ready'}`. Slots that miss it are treated as startup crashes. Raise it on a slow or heavily loaded host where a full pool cold-starting concurrently needs more than 5s. |
692
- | `GITNEXUS_MEMORY` | `off` | unset (autopilot on) | `off` declines GitNexus's memory autopilot: analyze will neither re-run itself with a RAM-aware heap cap nor abort the parse before V8 enters its ineffective-mark-compact death spiral. Use it when you want to drive memory manually; to simply pin a heap size, pass Node's own `--max-old-space-size`, which is already honoured as your decision. |
693
- | `GITNEXUS_WORKER_HEAP_MB` | `clamp(512, RAM/2/poolSize, 4096)` | Per-worker V8 old-generation heap cap (#2649). Bounds pool RSS on large repos; a worker exceeding it dies with a real heap error handled by quarantine/respawn. |
694
- | `GITNEXUS_SERVER_ANALYZE_HEAP_MB` | `min(8192, auto cap)` | Heap for the web/MCP server's forked analyze worker (#2649). Defaults to the historical 8192 MB bounded by the machine/container's RAM-aware auto cap; set an absolute MB value to override. |
695
- | `GITNEXUS_CPP_CAPTURE_BUDGET_MS` | `20000` | Per-file wall-clock budget for C++ capture extraction; on breach the file keeps partial captures with a warning (#2432). `0` expires immediately. |
714
+ | Variable | Default | Effect |
715
+ | ----------------------------------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
716
+ | `GITNEXUS_WORKER_MAX_RESPAWNS_PER_SLOT` | `3` | Max replacement spawns per slot before the slot is dropped from the active rotation. |
717
+ | `GITNEXUS_WORKER_MAX_CUMULATIVE_TIMEOUT_MS` | `5 × subBatchTimeoutMs` | Total retry wall-time budget per job before quarantining. Bounds exponentially-growing retry waits. |
718
+ | `GITNEXUS_WORKER_CONSECUTIVE_FAILURE_THRESHOLD` | `max(3, poolSize)` | Per-slot consecutive deaths before the pool's circuit breaker trips. After tripping, dispatches require a fresh pool. |
719
+ | `GITNEXUS_WORKER_SHUTDOWN_DRAIN_MS` | `30000` | Max wait at pool shutdown for a retired worker still inside native code — terminated at its next JS-safe point instead of mid-native-call, which would abort the process (`Napi::Error`, #2432). |
720
+ | `GITNEXUS_WORKER_READY_TIMEOUT_MS` | `5000` | Startup budget for a parse worker to load its grammar bindings and report `{type:'ready'}`. Slots that miss it are treated as startup crashes. Raise it on a slow or heavily loaded host where a full pool cold-starting concurrently needs more than 5s. |
721
+ | `GITNEXUS_MEMORY` | `off` | unset (autopilot on) | `off` declines GitNexus's memory autopilot: analyze will neither re-run itself with a RAM-aware heap cap nor abort the parse before V8 enters its ineffective-mark-compact death spiral. Use it when you want to drive memory manually; to simply pin a heap size, pass Node's own `--max-old-space-size`, which is already honoured as your decision. |
722
+ | `GITNEXUS_WORKER_HEAP_MB` | `clamp(512, RAM/2/poolSize, 4096)` | Per-worker V8 old-generation heap cap (#2649). Bounds pool RSS on large repos; a worker exceeding it dies with a real heap error handled by quarantine/respawn. |
723
+ | `GITNEXUS_SERVER_ANALYZE_HEAP_MB` | `min(8192, auto cap)` | Heap for the web/MCP server's forked analyze worker (#2649). Defaults to the historical 8192 MB bounded by the machine/container's RAM-aware auto cap; set an absolute MB value to override. |
724
+ | `GITNEXUS_CPP_CAPTURE_BUDGET_MS` | `20000` | Per-file wall-clock budget for C++ capture extraction; on breach the file keeps partial captures with a warning (#2432). `0` expires immediately. |
696
725
 
697
726
  ### Graph cleanup tuning
698
727
 
@@ -706,8 +735,8 @@ Programmatic callers can pass `keepLocalValueSymbols: true` in `PipelineOptions`
706
735
 
707
736
  ### Scope-resolution property-key dispatch cap
708
737
 
709
- During scope resolution GitNexus synthesizes CALLS edges through *property-key
710
- dispatch* — call sites like `hooks.emitScopeCaptures()` where a property key is
738
+ During scope resolution GitNexus synthesizes CALLS edges through _property-key
739
+ dispatch_ — call sites like `hooks.emitScopeCaptures()` where a property key is
711
740
  registered by multiple definitions across the codebase. To keep this fan-in
712
741
  bounded, each property key is capped at **32 registrations**: a key registered
713
742
  by more than 32 distinct functions is skipped entirely (no CALLS are synthesized
@@ -715,8 +744,8 @@ through it), and the dropped key names are surfaced in the analyze log for
715
744
  operator visibility. The cap is calibrated at 2× this repo's own provider table
716
745
  (16 legitimate registrations, one per language provider).
717
746
 
718
- | Variable | Default | Effect |
719
- | --------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
747
+ | Variable | Default | Effect |
748
+ | --------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
720
749
  | `GITNEXUS_MAX_PROPERTY_DISPATCH_FANOUT` | `32` | Per-property-key registration cap in the property-dispatch scope-resolution pass. Set to a positive integer to raise it for repositories whose provider/hook tables exceed the default and lose CALLS coverage on a legitimate key; non-integer or `< 1` values fall back to `32`. Lowering it tightens the overflow budget. |
721
750
 
722
751
  ```bash
@@ -729,11 +758,11 @@ npx gitnexus analyze --force
729
758
 
730
759
  ### Scope-resolution dispatch-target cap
731
760
 
732
- During scope resolution GitNexus resolves calls that flow through *callable
733
- values* — function/method references bound to variables, passed as arguments,
761
+ During scope resolution GitNexus resolves calls that flow through _callable
762
+ values_ — function/method references bound to variables, passed as arguments,
734
763
  or stored in maps/tables. To keep that inclusion-based resolution finite, each
735
764
  callable site is capped at **32 dispatch targets**. When a site gathers more
736
- candidates than the cap it is treated as **overflowed** and *all* of its call
765
+ candidates than the cap it is treated as **overflowed** and _all_ of its call
737
766
  edges are dropped — a cliff, not a tail, so a repository with a legitimately
738
767
  wide dispatch table (a single callable site resolving to 33+ targets) loses
739
768
  that site's whole call chain. In that case `analyze` logs
@@ -743,8 +772,8 @@ candidate count, and the cap (32).
743
772
 
744
773
  Raise the cap for such repositories:
745
774
 
746
- | Variable | Default | Effect |
747
- | ------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
775
+ | Variable | Default | Effect |
776
+ | ------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
748
777
  | `GITNEXUS_MAX_CALLABLE_VALUE_TARGETS` | `32` | Per-callable-site dispatch-target cap in the callable-value-flow scope-resolution pass. Set to a positive integer to raise it for repositories whose wide dispatch tables overflow the default and lose a whole call chain; non-integer or `< 1` values fall back to `32`. Lowering it tightens the overflow budget. |
749
778
 
750
779
  ```bash
@@ -48,6 +48,12 @@ export type NodeProperties = {
48
48
  responseKeys?: string[];
49
49
  errorKeys?: string[];
50
50
  middleware?: string[];
51
+ /** Route runtime evidence is authoritative only when this is exactly true. */
52
+ runtimeConfirmed?: boolean;
53
+ /** Provenance of runtime evidence; presence alone does not imply confirmation. */
54
+ runtimeSource?: string;
55
+ /** Runtime result such as runtime-confirmed or handler-conflict. */
56
+ runtimeStatus?: string;
51
57
  text?: string;
52
58
  /** BasicBlock: space-joined leaf callee names invoked in the block — the
53
59
  * statement-precise inter-procedural reach substrate for impact mode. */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/graph/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/graph/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,MAAM,SAAS,GACjB,SAAS,GACT,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,MAAM,GACN,OAAO,GACP,UAAU,GACV,QAAQ,GACR,UAAU,GACV,WAAW,GACX,MAAM,GACN,WAAW,GACX,QAAQ,GACR,MAAM,GACN,aAAa,GACb,WAAW,GACX,SAAS,GAET,QAAQ,GACR,OAAO,GACP,SAAS,GACT,OAAO,GACP,WAAW,GACX,OAAO,GACP,MAAM,GACN,WAAW,GACX,OAAO,GACP,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,UAAU,GACV,YAAY,GACZ,aAAa,GACb,UAAU,GACV,SAAS,GACT,OAAO,GACP,MAAM,GAGN,YAAY,CAAC;AAEjB,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,kBAAkB,GAAG,MAAM,CAAC;IACvC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;IAEjC,WAAW,CAAC,EAAE,iBAAiB,GAAG,iBAAiB,CAAC;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;4EACwE;IACxE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAEvB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,kFAAkF;IAClF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oEAAoE;IACpE,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;8EAC0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GACxB,UAAU,GACV,OAAO,GACP,UAAU,GACV,kBAAkB,GAClB,mBAAmB,GACnB,SAAS,GACT,MAAM,GACN,SAAS,GACT,WAAW,GACX,YAAY,GACZ,SAAS,GACT,YAAY,GACZ,cAAc,GACd,UAAU,GACV,WAAW,GACX,iBAAiB,GACjB,eAAe,GACf,SAAS,GACT,cAAc,GACd,gBAAgB,GAChB,OAAO,GACP,SAAS;AACX;;;;;;;;;;;0EAW0E;GACxE,SAAS;AACX;;;;;qBAKqB;GACnB,gBAAgB;AAClB;;;;+BAI+B;GAC7B,UAAU;AACZ;;;;6EAI6E;GAC3E,YAAY;AACd;;;;;;qEAMqE;GACnE,qBAAqB;AACvB;;;;;;gEAMgE;GAC9D,aAAa;AAOf,6EAA6E;GAC3E,KAAK;AACP;;;;qCAIqC;GACnC,cAAc;AAChB,qDAAqD;GACnD,SAAS;AACX,6CAA6C;GAC3C,WAAW;AACb;8EAC8E;GAC5E,YAAY;AACd;;;;qEAIqE;GACnE,KAAK;AACP;;;;;;0EAM0E;GACxE,eAAe;AACjB;;;;;;;;;;;oCAWoC;GAClC,cAAc,CAAC;AAEnB,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,EAAE,cAAc,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,gBAAgB,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,EAAE,SAAS;QAClB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;KACxB,EAAE,CAAC;CACL"}
@@ -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"}
@@ -30,6 +30,8 @@ export interface AIContextOptions {
30
30
  * "no PDG layer" note, so advertising it on a non-`--pdg` index is noise.
31
31
  */
32
32
  hasPdg?: boolean;
33
+ /** Whether this index includes opt-in Spring Actuator runtime evidence. */
34
+ hasSpringActuator?: boolean;
33
35
  }
34
36
  /**
35
37
  * Strip backticks from a branch name before it is embedded in a Markdown
@@ -62,6 +64,8 @@ export interface GitNexusContentOptions {
62
64
  * line below — false (default) omits it, so a non-pdg index doesn't advertise
63
65
  * a tool that only returns a "no PDG layer" note. */
64
66
  hasPdg?: boolean;
67
+ /** Whether Route nodes may carry Spring Actuator runtime evidence. */
68
+ hasSpringActuator?: boolean;
65
69
  }
66
70
  export declare function generateGitNexusContent(projectName: string, stats: RepoStats, opts?: GitNexusContentOptions): string;
67
71
  /**
@@ -9,6 +9,7 @@ import fs from 'fs/promises';
9
9
  import path from 'path';
10
10
  import { fileURLToPath } from 'url';
11
11
  import { STANDARD_SKILL_CATALOG } from './standard-skills.js';
12
+ import { isEnoent } from './editor-targets.js';
12
13
  import { logger } from '../core/logger.js';
13
14
  // ESM equivalent of __dirname
14
15
  const __filename = fileURLToPath(import.meta.url);
@@ -79,7 +80,7 @@ export function markdownSafeBranch(branch) {
79
80
  return branch.replace(/`/g, '');
80
81
  }
81
82
  export function generateGitNexusContent(projectName, stats, opts = {}) {
82
- const { generatedSkills, groupNames, noStats, skipSkills, runnerPath = '.gitnexus/run.cjs', defaultBranch = 'main', hasPdg = false, } = opts;
83
+ const { generatedSkills, groupNames, noStats, skipSkills, runnerPath = '.gitnexus/run.cjs', defaultBranch = 'main', hasPdg = false, hasSpringActuator = false, } = opts;
83
84
  const generatedRows = generatedSkills && generatedSkills.length > 0
84
85
  ? generatedSkills
85
86
  .map((s) =>
@@ -139,14 +140,15 @@ This project is indexed by GitNexus as **${projectName}**${noStats ? '' : ` (${s
139
140
 
140
141
  ## Always Do
141
142
 
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
143
+ - **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
144
  ? ` 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
145
  : ''}
145
146
  - **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.
147
+ - 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
148
  - **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"})\`.
149
+ - **MUST use \`query({search_query: "concept"})\` for concepts/flows, \`context({name: "symbolName"})\` for a named symbol, or \`impact\` for blast radius, on read-only callers, dependencies, imports, or execution flow.** Graph first; text search only for empty/\`UNKNOWN\`/literals.${hasSpringActuator
150
+ ? '\n- Spring Actuator runtime evidence is enabled. A Route is authoritative only when `runtimeConfirmed === true`; `runtimeSource` is provenance and may also describe conflicts. Snapshot values are never persisted.'
151
+ : ''}
150
152
  - For security review, \`explain({target: "fileOrSymbol"})\` lists taint findings (source→sink flows; needs \`analyze --pdg\`).${hasPdg
151
153
  ? `\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
154
  : ''}
@@ -320,6 +322,55 @@ export async function shouldMirrorSkillsToAgents(repoPath) {
320
322
  return false;
321
323
  }
322
324
  }
325
+ const SKILL_PRESERVE_HINT = 'delete the file to refresh from the bundled template, or pass --skip-skills to skip skill install';
326
+ async function readUtf8IfPresent(filePath) {
327
+ try {
328
+ return await fs.readFile(filePath, 'utf-8');
329
+ }
330
+ catch (err) {
331
+ if (isEnoent(err))
332
+ return null;
333
+ throw err;
334
+ }
335
+ }
336
+ function skillBytesDiverge(existing, bundled) {
337
+ return existing !== null && existing !== bundled;
338
+ }
339
+ /** Write bundled skill bytes unless an existing file already differs. */
340
+ async function writeSkillUnlessDivergent(filePath, content) {
341
+ const existing = await readUtf8IfPresent(filePath);
342
+ if (skillBytesDiverge(existing, content)) {
343
+ logger.warn(`Preserved customized skill ${filePath}; ${SKILL_PRESERVE_HINT}.`);
344
+ return true;
345
+ }
346
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
347
+ await fs.writeFile(filePath, content, 'utf-8');
348
+ return false;
349
+ }
350
+ async function inspectLegacySkillDir(legacyDir) {
351
+ let entries;
352
+ try {
353
+ entries = await fs.readdir(legacyDir);
354
+ }
355
+ catch (err) {
356
+ if (isEnoent(err))
357
+ return null;
358
+ throw err;
359
+ }
360
+ const nestedExisting = entries.includes('SKILL.md')
361
+ ? await fs.readFile(path.join(legacyDir, 'SKILL.md'), 'utf-8')
362
+ : null;
363
+ return {
364
+ nestedExisting,
365
+ hasSiblings: entries.some((entry) => entry !== 'SKILL.md'),
366
+ };
367
+ }
368
+ function formatSkillInstallLine(prefix, total, preserved, allWrittenSuffix, partialSuffix) {
369
+ if (preserved > 0) {
370
+ return `${prefix} (${total - preserved} written, ${preserved} ${partialSuffix})`;
371
+ }
372
+ return `${prefix} (${total} ${allWrittenSuffix})`;
373
+ }
323
374
  /**
324
375
  * Install GitNexus skills as direct children of .claude/skills/
325
376
  * Works natively with Claude Code, Cursor, and GitHub Copilot.
@@ -329,13 +380,14 @@ async function installSkills(repoPath) {
329
380
  const skillsDir = path.join(repoPath, '.claude', 'skills');
330
381
  const legacySkillsDir = path.join(skillsDir, 'gitnexus');
331
382
  const installedSkills = [];
383
+ let claudePreserved = 0;
384
+ let agentsPreserved = 0;
385
+ let legacyPreserved = 0;
332
386
  const agentsMirror = await shouldMirrorSkillsToAgents(repoPath);
333
387
  for (const skill of STANDARD_SKILL_CATALOG.filter((entry) => entry.distributions.project && entry.distributions.npm)) {
334
388
  const skillDir = path.join(skillsDir, skill.name);
335
389
  const skillPath = path.join(skillDir, 'SKILL.md');
336
390
  try {
337
- // Create skill directory
338
- await fs.mkdir(skillDir, { recursive: true });
339
391
  // Try to read from package skills directory
340
392
  const packageSkillPath = path.join(__dirname, '..', '..', 'skills', `${skill.name}.md`);
341
393
  let skillContent;
@@ -356,13 +408,14 @@ ${skill.fallbackDescription}
356
408
  Use GitNexus tools to accomplish this task.
357
409
  `;
358
410
  }
359
- await fs.writeFile(skillPath, skillContent, 'utf-8');
411
+ if (await writeSkillUnlessDivergent(skillPath, skillContent))
412
+ claudePreserved += 1;
360
413
  // Mirror to .agents/skills/ for agents that read repo-local skills
361
414
  if (agentsMirror) {
362
415
  try {
363
- const agentsSkillDir = path.join(repoPath, '.agents', 'skills', skill.name);
364
- await fs.mkdir(agentsSkillDir, { recursive: true });
365
- await fs.writeFile(path.join(agentsSkillDir, 'SKILL.md'), skillContent, 'utf-8');
416
+ const agentsSkillPath = path.join(repoPath, '.agents', 'skills', skill.name, 'SKILL.md');
417
+ if (await writeSkillUnlessDivergent(agentsSkillPath, skillContent))
418
+ agentsPreserved += 1;
366
419
  }
367
420
  catch (err) {
368
421
  logger.warn({ err }, `Warning: Could not mirror skill ${skill.name} to .agents/skills:`);
@@ -373,7 +426,20 @@ Use GitNexus tools to accomplish this task.
373
426
  // deep. Remove only the child owned by this installer; unknown siblings
374
427
  // under the legacy grouping directory may be user-authored and survive.
375
428
  try {
376
- await fs.rm(path.join(legacySkillsDir, skill.name), { recursive: true, force: true });
429
+ const legacyDir = path.join(legacySkillsDir, skill.name);
430
+ const nestedSkill = path.join(legacyDir, 'SKILL.md');
431
+ const leftover = await inspectLegacySkillDir(legacyDir);
432
+ if (leftover !== null && skillBytesDiverge(leftover.nestedExisting, skillContent)) {
433
+ logger.warn(`Preserved customized skill ${nestedSkill}; ${SKILL_PRESERVE_HINT}.`);
434
+ legacyPreserved += 1;
435
+ }
436
+ else if (leftover?.hasSiblings) {
437
+ logger.warn(`Preserved legacy skill directory ${legacyDir} because it contains operator-owned files.`);
438
+ legacyPreserved += 1;
439
+ }
440
+ else if (leftover !== null) {
441
+ await fs.rm(legacyDir, { recursive: true, force: true });
442
+ }
377
443
  }
378
444
  catch (err) {
379
445
  logger.warn({ err }, `Warning: Could not remove legacy skill ${skill.name}:`);
@@ -384,7 +450,13 @@ Use GitNexus tools to accomplish this task.
384
450
  logger.warn({ err }, `Warning: Could not install skill ${skill.name}:`);
385
451
  }
386
452
  }
387
- return { skills: installedSkills, agentsMirror };
453
+ return {
454
+ skills: installedSkills,
455
+ agentsMirror,
456
+ claudePreserved,
457
+ agentsPreserved,
458
+ legacyPreserved,
459
+ };
388
460
  }
389
461
  /**
390
462
  * Generate AI context files after indexing
@@ -414,6 +486,7 @@ export async function generateAIContextFiles(repoPath, storagePath, projectName,
414
486
  runnerPath,
415
487
  defaultBranch: options?.defaultBranch ?? 'main',
416
488
  hasPdg: options?.hasPdg ?? false,
489
+ hasSpringActuator: options?.hasSpringActuator ?? false,
417
490
  });
418
491
  const createdFiles = [];
419
492
  if (!options?.skipAgentsMd) {
@@ -432,11 +505,14 @@ export async function generateAIContextFiles(repoPath, storagePath, projectName,
432
505
  }
433
506
  // Install standard skills directly under .claude/skills/ (unless --skip-skills)
434
507
  if (!options?.skipSkills) {
435
- const { skills: installedSkills, agentsMirror } = await installSkills(repoPath);
508
+ const { skills: installedSkills, agentsMirror, claudePreserved, agentsPreserved, legacyPreserved, } = await installSkills(repoPath);
436
509
  if (installedSkills.length > 0) {
437
- createdFiles.push(`.claude/skills/gitnexus-*/ (${installedSkills.length} skills)`);
510
+ createdFiles.push(formatSkillInstallLine('.claude/skills/gitnexus-*/', installedSkills.length, claudePreserved, 'skills', 'preserved'));
438
511
  if (agentsMirror) {
439
- createdFiles.push(`.agents/skills/gitnexus-*/ (${installedSkills.length} skills mirrored for .agents)`);
512
+ createdFiles.push(formatSkillInstallLine('.agents/skills/gitnexus-*/', installedSkills.length, agentsPreserved, 'skills mirrored for .agents', 'preserved for .agents'));
513
+ }
514
+ if (legacyPreserved > 0) {
515
+ createdFiles.push(`.claude/skills/gitnexus/<name>/ (legacy directories preserved: ${legacyPreserved})`);
440
516
  }
441
517
  }
442
518
  }
@@ -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