@unerr-ai/unerr 0.1.0 → 0.1.1

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 (553) hide show
  1. package/dist/__tests__/architecture-guard.test.js +122 -0
  2. package/dist/__tests__/arg-validator.test.js +205 -0
  3. package/dist/__tests__/ast-extractor.test.js +203 -0
  4. package/dist/__tests__/auto-bootstrap.test.js +280 -0
  5. package/dist/__tests__/background-indexer.test.js +228 -0
  6. package/dist/__tests__/blast-radius-engine.test.js +200 -0
  7. package/dist/__tests__/bridge-isolation.test.js +37 -0
  8. package/dist/__tests__/budget-enforcer.test.js +53 -0
  9. package/dist/__tests__/cfg-test-detection-perf.test.js +82 -0
  10. package/dist/__tests__/change-narrative.test.js +190 -0
  11. package/dist/__tests__/check-commit.test.js +258 -0
  12. package/dist/__tests__/checksum.test.js +34 -0
  13. package/dist/__tests__/commit-watcher.test.js +154 -0
  14. package/dist/__tests__/community-detection.test.js +179 -0
  15. package/dist/__tests__/community-tools.test.js +299 -0
  16. package/dist/__tests__/components.test.js +449 -0
  17. package/dist/__tests__/compression-log.test.js +174 -0
  18. package/dist/__tests__/compression-quality-monitor.test.js +40 -0
  19. package/dist/__tests__/config-healer.test.js +165 -0
  20. package/dist/__tests__/context-ledger.test.js +58 -0
  21. package/dist/__tests__/convention-detector.test.js +99 -0
  22. package/dist/__tests__/convention-learner.test.js +86 -0
  23. package/dist/__tests__/correction-detector.test.js +330 -0
  24. package/dist/__tests__/daemon-autostart-install.test.js +283 -0
  25. package/dist/__tests__/daemon-bridge.test.js +222 -0
  26. package/dist/__tests__/daemon-dashboard.test.js +202 -0
  27. package/dist/__tests__/daemon-registry.test.js +240 -0
  28. package/dist/__tests__/daemon-supervisor.test.js +318 -0
  29. package/dist/__tests__/daemon-version-check.test.js +275 -0
  30. package/dist/__tests__/decision-point-detector.test.js +98 -0
  31. package/dist/__tests__/deep-link.test.js +143 -0
  32. package/dist/__tests__/disallowed-tools.test.js +115 -0
  33. package/dist/__tests__/drift-tracker.test.js +582 -0
  34. package/dist/__tests__/durability-scorer.test.js +152 -0
  35. package/dist/__tests__/efficiency-tracker.test.js +65 -0
  36. package/dist/__tests__/enrich.test.js +144 -0
  37. package/dist/__tests__/entity-rewind.test.js +248 -0
  38. package/dist/__tests__/ephemeral.test.js +111 -0
  39. package/dist/__tests__/exploration-cost.test.js +93 -0
  40. package/dist/__tests__/fact-generator.test.js +197 -0
  41. package/dist/__tests__/file-l0-graph.test.js +244 -0
  42. package/dist/__tests__/file-logger.test.js +82 -0
  43. package/dist/__tests__/file-outline.test.js +141 -0
  44. package/dist/__tests__/file-read-protocol.test.js +188 -0
  45. package/dist/__tests__/format-encoder.test.js +233 -0
  46. package/dist/__tests__/git-attribution.test.js +259 -0
  47. package/dist/__tests__/graph-temporal-joiner.test.js +219 -0
  48. package/dist/__tests__/health-grade-enhanced.test.js +138 -0
  49. package/dist/__tests__/health-map-data.test.js +173 -0
  50. package/dist/__tests__/helpers/mcp-harness.js +45 -0
  51. package/dist/__tests__/helpers/mcp-harness.test.js +68 -0
  52. package/dist/__tests__/hook-dedup.test.js +112 -0
  53. package/dist/__tests__/hook-runner.test.js +253 -0
  54. package/dist/__tests__/indexer-cfg.test.js +185 -0
  55. package/dist/__tests__/indexer-cross-file.test.js +172 -0
  56. package/dist/__tests__/indexer-extraction.test.js +245 -0
  57. package/dist/__tests__/indexer-incremental.test.js +232 -0
  58. package/dist/__tests__/indexer-language-expansion.test.js +165 -0
  59. package/dist/__tests__/init-push.test.js +131 -0
  60. package/dist/__tests__/instruction-writer.test.js +179 -0
  61. package/dist/__tests__/intelligence-integration.test.js +217 -0
  62. package/dist/__tests__/intent-correlator.test.js +175 -0
  63. package/dist/__tests__/intent-detector.test.js +235 -0
  64. package/dist/__tests__/intent-encoder.test.js +167 -0
  65. package/dist/__tests__/java-build-tool-detection.test.js +174 -0
  66. package/dist/__tests__/layer3-sprint-q.test.js +160 -0
  67. package/dist/__tests__/layer3-sprint-r.test.js +91 -0
  68. package/dist/__tests__/layer3-sprint-s.test.js +183 -0
  69. package/dist/__tests__/layer3-sprint-t.test.js +201 -0
  70. package/dist/__tests__/layer3-sprint-u.test.js +174 -0
  71. package/dist/__tests__/layer4-sprint-ba2.test.js +354 -0
  72. package/dist/__tests__/layer4-sprint-ba4.test.js +84 -0
  73. package/dist/__tests__/layer4-sprint-vs.test.js +105 -0
  74. package/dist/__tests__/ledger-chains.test.js +162 -0
  75. package/dist/__tests__/lifecycle-machine.test.js +226 -0
  76. package/dist/__tests__/local-chat-provider.test.js +170 -0
  77. package/dist/__tests__/local-convention-detector.test.js +308 -0
  78. package/dist/__tests__/local-embeddings.test.js +422 -0
  79. package/dist/__tests__/local-graph.test.js +540 -0
  80. package/dist/__tests__/local-indexer.test.js +228 -0
  81. package/dist/__tests__/local-intelligence-l3.test.js +332 -0
  82. package/dist/__tests__/local-llm.test.js +253 -0
  83. package/dist/__tests__/local-mode-offline.test.js +187 -0
  84. package/dist/__tests__/local-mode-stats.test.js +273 -0
  85. package/dist/__tests__/local-mode-tui.test.js +343 -0
  86. package/dist/__tests__/local-parse.test.js +199 -0
  87. package/dist/__tests__/log-tailer.test.js +208 -0
  88. package/dist/__tests__/loop-breaker.test.js +276 -0
  89. package/dist/__tests__/loop-miner.test.js +226 -0
  90. package/dist/__tests__/mcp-config.test.js +126 -0
  91. package/dist/__tests__/mcp-content-json.test.js +10 -0
  92. package/dist/__tests__/mcp-envelope.test.js +124 -0
  93. package/dist/__tests__/metrics-store.test.js +223 -0
  94. package/dist/__tests__/native-watcher.test.js +191 -0
  95. package/dist/__tests__/navigation-hooks-agent-aware.test.js +145 -0
  96. package/dist/__tests__/negative-knowledge.test.js +116 -0
  97. package/dist/__tests__/network-boundary.test.js +190 -0
  98. package/dist/__tests__/network-firewall.test.js +112 -0
  99. package/dist/__tests__/nudge-invariants.test.js +160 -0
  100. package/dist/__tests__/nudge-v2.test.js +225 -0
  101. package/dist/__tests__/offline-rewind.test.js +251 -0
  102. package/dist/__tests__/open-threads.test.js +89 -0
  103. package/dist/__tests__/output-compressor.test.js +93 -0
  104. package/dist/__tests__/pending-violations.test.js +112 -0
  105. package/dist/__tests__/persistence-effectiveness.test.js +143 -0
  106. package/dist/__tests__/provider-factory.test.js +42 -0
  107. package/dist/__tests__/providers.test.js +24 -0
  108. package/dist/__tests__/proxy.test.js +314 -0
  109. package/dist/__tests__/query-router.test.js +1018 -0
  110. package/dist/__tests__/reasoning-quality-route.test.js +138 -0
  111. package/dist/__tests__/redactor.test.js +120 -0
  112. package/dist/__tests__/resource-monitor.test.js +57 -0
  113. package/dist/__tests__/response-envelope.test.js +100 -0
  114. package/dist/__tests__/risk-classifier.test.js +101 -0
  115. package/dist/__tests__/risk-signal-scope.test.js +75 -0
  116. package/dist/__tests__/rule-evaluator.test.js +280 -0
  117. package/dist/__tests__/scip-decoder.test.js +49 -0
  118. package/dist/__tests__/scip-downloader.test.js +201 -0
  119. package/dist/__tests__/scip-merger.test.js +103 -0
  120. package/dist/__tests__/search-index.test.js +422 -0
  121. package/dist/__tests__/semantic-enrichment.test.js +360 -0
  122. package/dist/__tests__/session-brief-builder.test.js +187 -0
  123. package/dist/__tests__/session-context.test.js +221 -0
  124. package/dist/__tests__/session-continuity.test.js +144 -0
  125. package/dist/__tests__/session-dedup.test.js +74 -0
  126. package/dist/__tests__/session-event-wiring.test.js +206 -0
  127. package/dist/__tests__/session-events.test.js +149 -0
  128. package/dist/__tests__/session-legend.test.js +20 -0
  129. package/dist/__tests__/session-persistence.test.js +131 -0
  130. package/dist/__tests__/session-resume-block.test.js +107 -0
  131. package/dist/__tests__/session-resume.test.js +97 -0
  132. package/dist/__tests__/session-summary-writer.test.js +134 -0
  133. package/dist/__tests__/shadow-ledger.test.js +203 -0
  134. package/dist/__tests__/shell-classifier.test.js +151 -0
  135. package/dist/__tests__/shell-compression-floor.test.js +189 -0
  136. package/dist/__tests__/shell-compression-v2.test.js +339 -0
  137. package/dist/__tests__/shell-compressor.test.js +35 -0
  138. package/dist/__tests__/shell-hooks.test.js +128 -0
  139. package/dist/__tests__/shell-strategies.test.js +644 -0
  140. package/dist/__tests__/shell-tee.test.js +133 -0
  141. package/dist/__tests__/signal-dedup.test.js +158 -0
  142. package/dist/__tests__/signal-reinforcer.test.js +77 -0
  143. package/dist/__tests__/signal-scorer.test.js +251 -0
  144. package/dist/__tests__/signal-show-store.test.js +108 -0
  145. package/dist/__tests__/smart-truncate.test.js +215 -0
  146. package/dist/__tests__/snapshot-v2.test.js +113 -0
  147. package/dist/__tests__/sprint-l1-local-mode.test.js +130 -0
  148. package/dist/__tests__/sprint-l10-boot.test.js +220 -0
  149. package/dist/__tests__/sprint-l9-offline-commands.test.js +189 -0
  150. package/dist/__tests__/sprint-q-persistent-context.test.js +198 -0
  151. package/dist/__tests__/sprint-s1-wiring.test.js +215 -0
  152. package/dist/__tests__/sprint-s2-wiring.test.js +256 -0
  153. package/dist/__tests__/sprint-s3-wiring.test.js +195 -0
  154. package/dist/__tests__/sprint-s4-wiring.test.js +213 -0
  155. package/dist/__tests__/sprint-s6-hooks.test.js +222 -0
  156. package/dist/__tests__/sprint-s7-persistent.test.js +263 -0
  157. package/dist/__tests__/sprint-s8-value.test.js +167 -0
  158. package/dist/__tests__/sprint-s9-behavioral.test.js +179 -0
  159. package/dist/__tests__/sprint3-intelligence.test.js +297 -0
  160. package/dist/__tests__/sprint5-mcp-server.test.js +136 -0
  161. package/dist/__tests__/startup-display.test.js +302 -0
  162. package/dist/__tests__/startup-log-file.test.js +97 -0
  163. package/dist/__tests__/stash-manager.test.js +229 -0
  164. package/dist/__tests__/state-detector.test.js +92 -0
  165. package/dist/__tests__/status-dashboard.test.js +142 -0
  166. package/dist/__tests__/temporal-facts.test.js +292 -0
  167. package/dist/__tests__/temporal-routes.test.js +142 -0
  168. package/dist/__tests__/test-detector.test.js +174 -0
  169. package/dist/__tests__/theme.test.js +72 -0
  170. package/dist/__tests__/timeline-agents.test.js +122 -0
  171. package/dist/__tests__/timeline-bootstrap.test.js +176 -0
  172. package/dist/__tests__/timeline-filters.test.js +193 -0
  173. package/dist/__tests__/timeline-markers.test.js +151 -0
  174. package/dist/__tests__/timeline-routes.test.js +156 -0
  175. package/dist/__tests__/timeline-store.test.js +171 -0
  176. package/dist/__tests__/token-counter.test.js +86 -0
  177. package/dist/__tests__/token-estimator.test.js +96 -0
  178. package/dist/__tests__/token-flow-api.test.js +239 -0
  179. package/dist/__tests__/token-flow-instrumentation.test.js +437 -0
  180. package/dist/__tests__/token-flow-persistence.test.js +356 -0
  181. package/dist/__tests__/token-flow-routes.test.js +199 -0
  182. package/dist/__tests__/token-flow.test.js +695 -0
  183. package/dist/__tests__/tool-clusters.test.js +177 -0
  184. package/dist/__tests__/transport-mux.test.js +283 -0
  185. package/dist/__tests__/turn-segmenter.test.js +166 -0
  186. package/dist/__tests__/uninstall.test.js +141 -0
  187. package/dist/__tests__/warm-start-policy.test.js +271 -0
  188. package/dist/__tests__/wire-cap-nudge.test.js +77 -0
  189. package/dist/__tests__/worker-pool.test.js +101 -0
  190. package/dist/behaviors/agent-llm-bridge.js +166 -0
  191. package/dist/behaviors/architecture-guard.js +256 -0
  192. package/dist/behaviors/auto-doc.js +247 -0
  193. package/dist/behaviors/cascade-guard.js +289 -0
  194. package/dist/behaviors/change-narrative.js +270 -0
  195. package/dist/behaviors/convention-drift.js +290 -0
  196. package/dist/behaviors/framework.js +235 -0
  197. package/dist/behaviors/guard-formatter.js +44 -0
  198. package/dist/behaviors/incomplete-work.js +270 -0
  199. package/dist/behaviors/loop-breaker.js +300 -0
  200. package/dist/behaviors/session-continuity.js +208 -0
  201. package/dist/cli.js +992 -706
  202. package/dist/commands/branches.js +97 -0
  203. package/dist/commands/check-commit.js +225 -0
  204. package/dist/commands/compress-output.js +64 -0
  205. package/dist/commands/config-verify.js +243 -0
  206. package/dist/commands/daemon.js +905 -0
  207. package/dist/commands/dashboard.js +52 -0
  208. package/dist/commands/debug.js +200 -0
  209. package/dist/commands/enrich.js +184 -0
  210. package/dist/commands/exec.js +233 -0
  211. package/dist/commands/gain.js +156 -0
  212. package/dist/commands/hook.js +88 -0
  213. package/dist/commands/index.js +88 -0
  214. package/dist/commands/init.js +74 -0
  215. package/dist/commands/install.js +505 -0
  216. package/dist/commands/learn.js +116 -0
  217. package/dist/commands/manifest.js +193 -0
  218. package/dist/commands/rewind.js +103 -0
  219. package/dist/commands/serve.js +19 -0
  220. package/dist/commands/setup-wizard.js +414 -0
  221. package/dist/commands/skills.js +64 -0
  222. package/dist/commands/stats.js +20 -0
  223. package/dist/commands/status.js +654 -0
  224. package/dist/commands/timeline.js +139 -0
  225. package/dist/commands/uninstall.js +230 -0
  226. package/dist/components/App.js +109 -0
  227. package/dist/components/Banner.js +12 -0
  228. package/dist/components/ConfirmPrompt.js +25 -0
  229. package/dist/components/DriftSummary.js +23 -0
  230. package/dist/components/GradeBadge.js +15 -0
  231. package/dist/components/HealthCard.js +18 -0
  232. package/dist/components/InkSpinner.js +22 -0
  233. package/dist/components/InputBox.js +17 -0
  234. package/dist/components/KeyValue.js +13 -0
  235. package/dist/components/MessageList.js +14 -0
  236. package/dist/components/ProgressBar.js +26 -0
  237. package/dist/components/Section.js +16 -0
  238. package/dist/components/SessionSummaryCard.js +73 -0
  239. package/dist/components/StartupDisplay.js +24 -0
  240. package/dist/components/StatusDashboard.js +57 -0
  241. package/dist/components/StatusLine.js +8 -0
  242. package/dist/components/StepLine.js +22 -0
  243. package/dist/components/Theme.js +20 -0
  244. package/dist/components/ToolProgress.js +8 -0
  245. package/dist/components/ViolationList.js +21 -0
  246. package/dist/components/render.js +13 -0
  247. package/dist/config/agent-registry.js +237 -0
  248. package/dist/config/claude-settings-hooks.js +304 -0
  249. package/dist/config/hook-installer.js +65 -0
  250. package/dist/config/instruction-writer.js +388 -0
  251. package/dist/config/mcp-config-writer.js +266 -0
  252. package/dist/config/settings.js +174 -0
  253. package/dist/config/tool-detector.js +42 -0
  254. package/dist/config/value-surfacing.js +119 -0
  255. package/dist/core/context-assembly.js +108 -0
  256. package/dist/core/conversation.js +33 -0
  257. package/dist/core/local-chat-provider.js +475 -0
  258. package/dist/core/provider-factory.js +55 -0
  259. package/dist/core/providers.js +90 -0
  260. package/dist/core/query-engine.js +174 -0
  261. package/dist/daemon/api.js +312 -0
  262. package/dist/daemon/autostart.js +119 -0
  263. package/dist/daemon/bootstrap.js +39 -0
  264. package/dist/daemon/client.js +164 -0
  265. package/dist/daemon/detect-ci.js +81 -0
  266. package/dist/daemon/platform-linux.js +146 -0
  267. package/dist/daemon/platform-macos.js +134 -0
  268. package/dist/daemon/platform-windows.js +116 -0
  269. package/dist/daemon/process-manager.js +299 -0
  270. package/dist/daemon/protocol.js +23 -0
  271. package/dist/daemon/registry.js +270 -0
  272. package/dist/daemon/settings-schema.js +72 -0
  273. package/dist/daemon/system-health.js +134 -0
  274. package/dist/daemon/version-checker.js +262 -0
  275. package/dist/daemon/warm-start.js +223 -0
  276. package/dist/entrypoints/cli.js +1043 -0
  277. package/dist/entrypoints/daemon.js +380 -0
  278. package/dist/entrypoints/repl.js +147 -0
  279. package/dist/hooks/adapters/claude-code.js +90 -0
  280. package/dist/hooks/adapters/cline.js +100 -0
  281. package/dist/hooks/adapters/cursor.js +98 -0
  282. package/dist/hooks/hook-dedup.js +79 -0
  283. package/dist/hooks/hook-runner.js +113 -0
  284. package/dist/hooks/navigation-hooks.js +175 -0
  285. package/dist/hooks/prompt-hooks.js +63 -0
  286. package/dist/hooks/shell-hooks.js +47 -0
  287. package/dist/ignore.js +111 -0
  288. package/dist/intelligence/approach-suggester.js +61 -0
  289. package/dist/intelligence/ast-extractor.js +2615 -0
  290. package/dist/intelligence/ast-worker.js +34 -0
  291. package/dist/intelligence/background-indexer.js +121 -0
  292. package/dist/intelligence/blast-radius.js +200 -0
  293. package/dist/intelligence/community-detection.js +691 -0
  294. package/dist/intelligence/community-detector.js +184 -0
  295. package/dist/intelligence/computation-scheduler.js +75 -0
  296. package/dist/intelligence/confidence-propagation.js +47 -0
  297. package/dist/intelligence/convention-detector.js +242 -0
  298. package/dist/intelligence/convention-learner.js +205 -0
  299. package/dist/intelligence/convention-matcher.js +205 -0
  300. package/dist/intelligence/cozo-schema.js +376 -0
  301. package/dist/intelligence/decision-point-detector.js +90 -0
  302. package/dist/intelligence/deep-dive-tools.js +586 -0
  303. package/dist/intelligence/durability-scorer.js +84 -0
  304. package/dist/intelligence/exploration-cost.js +204 -0
  305. package/dist/intelligence/exploration-pattern-tracker.js +61 -0
  306. package/dist/intelligence/fact-generator.js +322 -0
  307. package/dist/intelligence/facts-schema.js +90 -0
  308. package/dist/intelligence/file-intelligence.js +59 -0
  309. package/dist/intelligence/graph-holder.js +220 -0
  310. package/dist/intelligence/graph-temporal-joiner.js +238 -0
  311. package/dist/intelligence/health-grade.js +423 -0
  312. package/dist/intelligence/health-grader.js +200 -0
  313. package/dist/intelligence/health-map-data.js +259 -0
  314. package/dist/intelligence/import-symbols.js +136 -0
  315. package/dist/intelligence/incremental-indexer.js +658 -0
  316. package/dist/intelligence/indexer/centrality.js +62 -0
  317. package/dist/intelligence/indexer/cfg-context.js +95 -0
  318. package/dist/intelligence/indexer/confidence.js +34 -0
  319. package/dist/intelligence/indexer/cross-file-resolver.js +104 -0
  320. package/dist/intelligence/indexer/edge-repair.js +89 -0
  321. package/dist/intelligence/indexer/entity-key.js +17 -0
  322. package/dist/intelligence/indexer/export-map.js +132 -0
  323. package/dist/intelligence/indexer/git-cochange.js +128 -0
  324. package/dist/intelligence/indexer/graph-patch.js +147 -0
  325. package/dist/intelligence/indexer/incremental.js +78 -0
  326. package/dist/intelligence/indexer/ingest.js +160 -0
  327. package/dist/intelligence/indexer/language-detect.js +226 -0
  328. package/dist/intelligence/indexer/metadata.js +63 -0
  329. package/dist/intelligence/indexer/mutation-tracker.js +79 -0
  330. package/dist/intelligence/indexer/orchestrator.js +155 -0
  331. package/dist/intelligence/indexer/plugin-interface.js +31 -0
  332. package/dist/intelligence/indexer/plugins/csharp.js +440 -0
  333. package/dist/intelligence/indexer/plugins/go.js +335 -0
  334. package/dist/intelligence/indexer/plugins/java.js +370 -0
  335. package/dist/intelligence/indexer/plugins/python.js +358 -0
  336. package/dist/intelligence/indexer/plugins/regex-fallback.js +82 -0
  337. package/dist/intelligence/indexer/plugins/ruby.js +290 -0
  338. package/dist/intelligence/indexer/plugins/rust.js +484 -0
  339. package/dist/intelligence/indexer/plugins/tier2-generic.js +310 -0
  340. package/dist/intelligence/indexer/plugins/typescript.js +456 -0
  341. package/dist/intelligence/indexer/resource-monitor.js +93 -0
  342. package/dist/intelligence/indexer/scip/decoder.js +253 -0
  343. package/dist/intelligence/indexer/scip/detector.js +232 -0
  344. package/dist/intelligence/indexer/scip/downloader.js +427 -0
  345. package/dist/intelligence/indexer/scip/fallback.js +34 -0
  346. package/dist/intelligence/indexer/scip/merger.js +109 -0
  347. package/dist/intelligence/indexer/scip/orchestrator.js +433 -0
  348. package/dist/intelligence/indexer/scip/runner.js +98 -0
  349. package/dist/intelligence/indexer/snapshot.js +66 -0
  350. package/dist/intelligence/indexer/test-detector.js +196 -0
  351. package/dist/intelligence/indexer/watch-integration.js +61 -0
  352. package/dist/intelligence/indexer/worker.js +85 -0
  353. package/dist/intelligence/local-convention-detector.js +437 -0
  354. package/dist/intelligence/local-embeddings.js +190 -0
  355. package/dist/intelligence/local-graph.js +1946 -0
  356. package/dist/intelligence/local-indexer.js +1575 -0
  357. package/dist/intelligence/local-llm.js +163 -0
  358. package/dist/intelligence/local-rule-generator.js +154 -0
  359. package/dist/intelligence/local-snapshot.js +213 -0
  360. package/dist/intelligence/negative-knowledge.js +103 -0
  361. package/dist/intelligence/persistent-db.js +85 -0
  362. package/dist/intelligence/query-router.js +2556 -0
  363. package/dist/intelligence/risk-classifier.js +116 -0
  364. package/dist/intelligence/rule-evaluator.js +380 -0
  365. package/dist/intelligence/rule-generator.js +49 -0
  366. package/dist/intelligence/search-index.js +173 -0
  367. package/dist/intelligence/semantic/docstring-extractor.js +67 -0
  368. package/dist/intelligence/semantic/embedding-store.js +52 -0
  369. package/dist/intelligence/semantic/enrichment-orchestrator.js +48 -0
  370. package/dist/intelligence/semantic/git-message-miner.js +114 -0
  371. package/dist/intelligence/semantic/identifier-tokenizer.js +51 -0
  372. package/dist/intelligence/semantic/node2vec-embeddings.js +71 -0
  373. package/dist/intelligence/semantic/node2vec-walks.js +103 -0
  374. package/dist/intelligence/semantic/path-domain-inference.js +112 -0
  375. package/dist/intelligence/semantic/similarity-engine.js +60 -0
  376. package/dist/intelligence/semantic/tfidf-vectors.js +88 -0
  377. package/dist/intelligence/session-brief-builder.js +159 -0
  378. package/dist/intelligence/session-context.js +221 -0
  379. package/dist/intelligence/session-health-monitor.js +211 -0
  380. package/dist/intelligence/session-narrative.js +197 -0
  381. package/dist/intelligence/session-pattern-analyzer.js +218 -0
  382. package/dist/intelligence/signal-scorer.js +390 -0
  383. package/dist/intelligence/signal-show-store.js +182 -0
  384. package/dist/intelligence/smart-truncate.js +158 -0
  385. package/dist/intelligence/subgraph-cache.js +88 -0
  386. package/dist/intelligence/temporal-facts.js +494 -0
  387. package/dist/intelligence/token-estimator.js +100 -0
  388. package/dist/intelligence/tool-injector.js +87 -0
  389. package/dist/intelligence/tree-sitter-loader.js +71 -0
  390. package/dist/intelligence/worker-pool.js +116 -0
  391. package/dist/proxy/arg-validator.js +79 -0
  392. package/dist/proxy/auto-bootstrap.js +167 -0
  393. package/dist/proxy/bridge.js +147 -0
  394. package/dist/proxy/budget-enforcer.js +70 -0
  395. package/dist/proxy/compression-quality-monitor.js +160 -0
  396. package/dist/proxy/compression-stats.js +51 -0
  397. package/dist/proxy/context-rot-detector.js +137 -0
  398. package/dist/proxy/drift-detector.js +139 -0
  399. package/dist/proxy/efficiency-tracker.js +79 -0
  400. package/dist/proxy/fact-ranking.js +154 -0
  401. package/dist/proxy/format-encoder.js +266 -0
  402. package/dist/proxy/http-transport.js +90 -0
  403. package/dist/proxy/lifecycle-actor.js +55 -0
  404. package/dist/proxy/lifecycle-machine.js +187 -0
  405. package/dist/proxy/log-tailer.js +265 -0
  406. package/dist/proxy/model-pricing.js +98 -0
  407. package/dist/proxy/network-firewall.js +141 -0
  408. package/dist/proxy/nudge-state.js +93 -0
  409. package/dist/proxy/output-compressor.js +185 -0
  410. package/dist/proxy/pid-lock.js +291 -0
  411. package/dist/proxy/proxy-context.js +11 -0
  412. package/dist/proxy/proxy.js +2633 -0
  413. package/dist/proxy/response-enrichment.js +32 -0
  414. package/dist/proxy/response-envelope.js +313 -0
  415. package/dist/proxy/session-dedup.js +82 -0
  416. package/dist/proxy/session-legend.js +30 -0
  417. package/dist/proxy/session-persistence.js +210 -0
  418. package/dist/proxy/session-resume.js +94 -0
  419. package/dist/proxy/session-stats.js +513 -0
  420. package/dist/proxy/shell-classifier.js +1346 -0
  421. package/dist/proxy/shell-compression-log.js +93 -0
  422. package/dist/proxy/shell-compressor.js +390 -0
  423. package/dist/proxy/shell-graph-boost.js +202 -0
  424. package/dist/proxy/shell-monitor-map.js +18 -0
  425. package/dist/proxy/shell-stats.js +54 -0
  426. package/dist/proxy/shell-strategies/cloud.js +215 -0
  427. package/dist/proxy/shell-strategies/diff.js +159 -0
  428. package/dist/proxy/shell-strategies/error-diagnostic.js +796 -0
  429. package/dist/proxy/shell-strategies/filter-dsl.js +358 -0
  430. package/dist/proxy/shell-strategies/git-status.js +177 -0
  431. package/dist/proxy/shell-strategies/key-value.js +193 -0
  432. package/dist/proxy/shell-strategies/log-text.js +154 -0
  433. package/dist/proxy/shell-strategies/omni.js +188 -0
  434. package/dist/proxy/shell-strategies/progress.js +55 -0
  435. package/dist/proxy/shell-strategies/redact.js +76 -0
  436. package/dist/proxy/shell-strategies/structured.js +241 -0
  437. package/dist/proxy/shell-strategies/tabular.js +243 -0
  438. package/dist/proxy/shell-strategies/test-results-types.js +13 -0
  439. package/dist/proxy/shell-strategies/test-results.js +784 -0
  440. package/dist/proxy/shell-strategies/tree-paths.js +144 -0
  441. package/dist/proxy/shell-strategies/yaml.js +182 -0
  442. package/dist/proxy/shell-tee.js +111 -0
  443. package/dist/proxy/signal-dedup.js +171 -0
  444. package/dist/proxy/startup-renderer.js +158 -0
  445. package/dist/proxy/task-token-display.js +38 -0
  446. package/dist/proxy/token-counter.js +61 -0
  447. package/dist/proxy/tool-clusters.js +273 -0
  448. package/dist/proxy/tool-definitions.js +525 -0
  449. package/dist/proxy/transport-mux.js +229 -0
  450. package/dist/proxy/wire-cap.js +268 -0
  451. package/dist/schemas/api/skills.js +19 -0
  452. package/dist/schemas/common/errors.js +7 -0
  453. package/dist/schemas/common/headers.js +5 -0
  454. package/dist/schemas/entities/edge.js +25 -0
  455. package/dist/schemas/entities/entity.js +22 -0
  456. package/dist/schemas/entities/rule.js +18 -0
  457. package/dist/schemas/index.js +14 -0
  458. package/dist/server/event-bus.js +59 -0
  459. package/dist/server/http.js +156 -0
  460. package/dist/server/middleware.js +70 -0
  461. package/dist/server/routes/drift.js +97 -0
  462. package/dist/server/routes/intelligence.js +1217 -0
  463. package/dist/server/routes/reasoning-quality.js +444 -0
  464. package/dist/server/routes/session.js +86 -0
  465. package/dist/server/routes/stream.js +120 -0
  466. package/dist/server/routes/system.js +73 -0
  467. package/dist/server/routes/temporal.js +170 -0
  468. package/dist/server/routes/timeline.js +232 -0
  469. package/dist/server/routes/token-flow.js +403 -0
  470. package/dist/skills/effectiveness-tracker.js +93 -0
  471. package/dist/skills/local-pack.js +380 -0
  472. package/dist/skills/resolver.js +495 -0
  473. package/dist/state-detector.js +83 -0
  474. package/dist/timeline/intent-detector.js +263 -0
  475. package/dist/timeline/loop-miner.js +140 -0
  476. package/dist/timeline/open-threads.js +49 -0
  477. package/dist/timeline/signal-reinforcer.js +62 -0
  478. package/dist/timeline/timeline-bootstrap.js +151 -0
  479. package/dist/timeline/timeline-store.js +618 -0
  480. package/dist/tools/coding/bash.js +49 -0
  481. package/dist/tools/coding/file-edit.js +72 -0
  482. package/dist/tools/coding/file-outline.js +227 -0
  483. package/dist/tools/coding/file-read-protocol.js +425 -0
  484. package/dist/tools/coding/file-read.js +35 -0
  485. package/dist/tools/coding/file-write.js +43 -0
  486. package/dist/tools/coding/glob-tool.js +109 -0
  487. package/dist/tools/coding/grep.js +162 -0
  488. package/dist/tools/coding/index.js +27 -0
  489. package/dist/tools/intelligence/index.js +269 -0
  490. package/dist/tools/intelligence/record-fact.js +48 -0
  491. package/dist/tools/intelligence/timeline-markers.js +130 -0
  492. package/dist/tools/registry.js +47 -0
  493. package/dist/tools/types.js +8 -0
  494. package/dist/tracking/auto-snapshot-triggers.js +246 -0
  495. package/dist/tracking/branch-context.js +115 -0
  496. package/dist/tracking/branch-snapshot.js +217 -0
  497. package/dist/tracking/causal-bridge.js +317 -0
  498. package/dist/tracking/circuit-breaker.js +147 -0
  499. package/dist/tracking/commit-watcher.js +114 -0
  500. package/dist/tracking/context-ledger.js +119 -0
  501. package/dist/tracking/correction-detector.js +324 -0
  502. package/dist/tracking/drift-tracker.js +874 -0
  503. package/dist/tracking/durability-tracker.js +94 -0
  504. package/dist/tracking/entity-rewind.js +200 -0
  505. package/dist/tracking/file-hash-state.js +114 -0
  506. package/dist/tracking/git-attribution.js +132 -0
  507. package/dist/tracking/git-trailers.js +171 -0
  508. package/dist/tracking/intelligence-counter.js +46 -0
  509. package/dist/tracking/intent-correlator.js +202 -0
  510. package/dist/tracking/intent-encoder.js +52 -0
  511. package/dist/tracking/intent-token-tracker.js +159 -0
  512. package/dist/tracking/ledger-archiver.js +94 -0
  513. package/dist/tracking/ledger-chains.js +245 -0
  514. package/dist/tracking/metrics-store.js +361 -0
  515. package/dist/tracking/native-watcher.js +131 -0
  516. package/dist/tracking/offline-rewind.js +295 -0
  517. package/dist/tracking/pending-violations.js +74 -0
  518. package/dist/tracking/persistence-effectiveness.js +167 -0
  519. package/dist/tracking/prompt-durability.js +202 -0
  520. package/dist/tracking/quality-signals.js +213 -0
  521. package/dist/tracking/redactor.js +73 -0
  522. package/dist/tracking/rewind-engine.js +161 -0
  523. package/dist/tracking/session-history.js +128 -0
  524. package/dist/tracking/session-receipt.js +88 -0
  525. package/dist/tracking/session-summary-writer.js +157 -0
  526. package/dist/tracking/shadow-ledger.js +321 -0
  527. package/dist/tracking/stash-manager.js +258 -0
  528. package/dist/tracking/timeline-fork.js +213 -0
  529. package/dist/tracking/timeline.js +69 -0
  530. package/dist/tracking/token-flow.js +276 -0
  531. package/dist/tracking/turn-segmenter.js +122 -0
  532. package/dist/tracking/weekly-accumulator.js +179 -0
  533. package/dist/tracking/working-snapshots.js +188 -0
  534. package/dist/tracking/workspace-manifest.js +176 -0
  535. package/dist/transport/http.js +102 -0
  536. package/dist/ui/assets/index-BsMTQdhX.js +10 -0
  537. package/dist/ui/index.html +1 -1
  538. package/dist/utils/counterfactual.js +65 -0
  539. package/dist/utils/deep-link.js +34 -0
  540. package/dist/utils/detect.js +193 -0
  541. package/dist/utils/exec.js +73 -0
  542. package/dist/utils/file-logger.js +87 -0
  543. package/dist/utils/format-error.js +29 -0
  544. package/dist/utils/git.js +181 -0
  545. package/dist/utils/log.js +57 -0
  546. package/dist/utils/logger.js +35 -0
  547. package/dist/utils/mcp-content-json.js +8 -0
  548. package/dist/utils/session-logger.js +154 -0
  549. package/dist/utils/startup-log.js +512 -0
  550. package/dist/utils/ui.js +56 -0
  551. package/package.json +5 -3
  552. package/scripts/postinstall.mjs +299 -0
  553. package/dist/ui/assets/index-B-0HTtUR.js +0 -10
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Multi-Factor Risk Classifier — computes entity risk from 4 factors:
3
+ * 1. Fan-in (centrality): how many callers depend on this entity
4
+ * 2. Bridge score: does this entity connect two communities?
5
+ * 3. Mutation score: does it write to shared state?
6
+ * 4. Guard score: is it protected by try/catch or similar?
7
+ *
8
+ * Output: "critical" | "high" | "medium" | "low" with numeric score (0-100).
9
+ *
10
+ * Note (Issue #5): The legacy enum used "normal" for the bottom rung; the
11
+ * health-map and other consumers use "low". We canonicalize on "low" here
12
+ * and provide `normalizeRiskLevel()` to translate stale "normal" values from
13
+ * existing graph data. Both names are accepted in `isRiskLevel()` to keep
14
+ * older snapshots working until they're re-indexed.
15
+ */
16
+ /** Translate a possibly-stale risk_level string to the canonical enum.
17
+ * Old snapshots used "normal" for the bottom rung; map it to "low". */
18
+ export function normalizeRiskLevel(value) {
19
+ if (value === "critical" || value === "high" || value === "medium") {
20
+ return value;
21
+ }
22
+ // "normal" (legacy) and any unknown / null fall through to "low".
23
+ return "low";
24
+ }
25
+ const WEIGHTS = {
26
+ fanIn: 0.4,
27
+ bridge: 0.25,
28
+ mutation: 0.2,
29
+ guard: 0.15,
30
+ };
31
+ const THRESHOLDS = {
32
+ critical: 35,
33
+ high: 22,
34
+ medium: 10,
35
+ };
36
+ /**
37
+ * Classify risk for a single entity.
38
+ */
39
+ export function classifyRisk(entityKey, fanIn, isBridge, hasMutations, isGuarded) {
40
+ const fanInScore = Math.min(100, fanIn * 2);
41
+ const bridgeScore = isBridge ? 80 : 0;
42
+ const mutationScore = hasMutations ? 60 : 0;
43
+ const guardScore = isGuarded ? -20 : 0;
44
+ const rawScore = WEIGHTS.fanIn * fanInScore +
45
+ WEIGHTS.bridge * bridgeScore +
46
+ WEIGHTS.mutation * mutationScore +
47
+ WEIGHTS.guard * Math.abs(guardScore);
48
+ const score = Math.max(0, Math.min(100, Math.round(rawScore + guardScore * WEIGHTS.guard)));
49
+ const level = score >= THRESHOLDS.critical
50
+ ? "critical"
51
+ : score >= THRESHOLDS.high
52
+ ? "high"
53
+ : score >= THRESHOLDS.medium
54
+ ? "medium"
55
+ : "low";
56
+ const reasons = [];
57
+ if (fanIn >= 50)
58
+ reasons.push(`${fanIn} callers (chokepoint)`);
59
+ else if (fanIn >= 20)
60
+ reasons.push(`${fanIn} callers (high traffic)`);
61
+ if (isBridge)
62
+ reasons.push("bridges 2+ communities");
63
+ if (hasMutations)
64
+ reasons.push("mutates shared state");
65
+ if (isGuarded)
66
+ reasons.push("protected by error handling");
67
+ return {
68
+ entityKey,
69
+ level,
70
+ score,
71
+ factors: {
72
+ fanIn: fanInScore,
73
+ bridgeScore,
74
+ mutationScore,
75
+ guardScore,
76
+ },
77
+ reasoning: reasons.length > 0
78
+ ? reasons.join("; ")
79
+ : "low risk (no significant factors)",
80
+ };
81
+ }
82
+ /**
83
+ * Detect bridge entities (entities that connect two communities).
84
+ */
85
+ export function detectBridges(entityKey, edges, communityAssignments) {
86
+ const myCommunity = communityAssignments.get(entityKey);
87
+ if (myCommunity === undefined)
88
+ return false;
89
+ const connectedCommunities = new Set();
90
+ for (const edge of edges) {
91
+ if (edge.from_key === entityKey) {
92
+ const targetCommunity = communityAssignments.get(edge.to_key);
93
+ if (targetCommunity !== undefined)
94
+ connectedCommunities.add(targetCommunity);
95
+ }
96
+ if (edge.to_key === entityKey) {
97
+ const sourceCommunity = communityAssignments.get(edge.from_key);
98
+ if (sourceCommunity !== undefined)
99
+ connectedCommunities.add(sourceCommunity);
100
+ }
101
+ }
102
+ connectedCommunities.delete(myCommunity);
103
+ return connectedCommunities.size >= 1;
104
+ }
105
+ /**
106
+ * Batch classify risk for all entities.
107
+ */
108
+ export function classifyAllRisks(entities, fanInMap, edges, communityAssignments, mutationEntities, guardedEntities) {
109
+ return entities.map((entity) => {
110
+ const fanIn = fanInMap.get(entity.key) ?? 0;
111
+ const isBridge = detectBridges(entity.key, edges, communityAssignments);
112
+ const hasMutations = mutationEntities.has(entity.key);
113
+ const isGuarded = guardedEntities.has(entity.key);
114
+ return classifyRisk(entity.key, fanIn, isBridge, hasMutations, isGuarded);
115
+ });
116
+ }
@@ -0,0 +1,380 @@
1
+ /**
2
+ * Phase 10b + Sprint 9: Local rule evaluator — tree-sitter structural + naming evaluation.
3
+ *
4
+ * Evaluates rules locally.
5
+ * - Structural rules: Uses tree-sitter to parse AST and match node types
6
+ * - Naming rules: Uses regex against entity names from CozoDB
7
+ * - Semgrep/LLM rules: Skipped (not yet supported locally)
8
+ *
9
+ * Sprint 9 additions:
10
+ * - 9.1: JIT Rule Filtering — score rules by relevance, cap at 30
11
+ * - 9.2: Auto-Remediation Passthrough — ast_grep_fix → autoFix in violations
12
+ * - 9.5: STAGED Rule Dry-Run — evaluate but separate into stagedRuleResults
13
+ * - 9.6: Rule Exception TTL — active exceptions downgrade to "suggest"
14
+ */
15
+ // Lazy-loaded tree-sitter instance
16
+ let parserCache = null;
17
+ const LANGUAGE_MAP = {
18
+ ".ts": "typescript",
19
+ ".tsx": "typescript",
20
+ ".js": "typescript",
21
+ ".jsx": "typescript",
22
+ ".py": "python",
23
+ ".go": "go",
24
+ };
25
+ /**
26
+ * Detect language from file extension.
27
+ */
28
+ function detectLanguage(filePath) {
29
+ const ext = filePath.slice(filePath.lastIndexOf("."));
30
+ return LANGUAGE_MAP[ext] ?? null;
31
+ }
32
+ /**
33
+ * Lazy-load tree-sitter parser for a language.
34
+ * Returns null if the language is not supported or tree-sitter is not available.
35
+ */
36
+ async function getParser(language) {
37
+ if (!parserCache) {
38
+ parserCache = new Map();
39
+ }
40
+ if (parserCache.has(language)) {
41
+ return parserCache.get(language);
42
+ }
43
+ try {
44
+ const TreeSitter = (await import("web-tree-sitter")).default;
45
+ await TreeSitter.init();
46
+ const parser = new TreeSitter();
47
+ // Try to load language grammar from node_modules
48
+ const langFile = `tree-sitter-${language}.wasm`;
49
+ try {
50
+ const { join } = await import("node:path");
51
+ const { existsSync } = await import("node:fs");
52
+ // Check multiple possible locations for WASM files
53
+ const possiblePaths = [
54
+ join(process.cwd(), "node_modules", `tree-sitter-${language}`, langFile),
55
+ join(process.cwd(), "node_modules", "web-tree-sitter", langFile),
56
+ ];
57
+ let wasmPath = null;
58
+ for (const p of possiblePaths) {
59
+ if (existsSync(p)) {
60
+ wasmPath = p;
61
+ break;
62
+ }
63
+ }
64
+ if (!wasmPath) {
65
+ // Grammar WASM not found — degrade gracefully
66
+ return null;
67
+ }
68
+ const lang = await TreeSitter.Language.load(wasmPath);
69
+ parser.setLanguage(lang);
70
+ parserCache.set(language, parser);
71
+ return parser;
72
+ }
73
+ catch {
74
+ return null;
75
+ }
76
+ }
77
+ catch {
78
+ // web-tree-sitter not available
79
+ return null;
80
+ }
81
+ }
82
+ /**
83
+ * Walk tree-sitter AST and collect nodes matching target types.
84
+ */
85
+ function collectNodesByType(node, targetTypes) {
86
+ const results = [];
87
+ function walk(n) {
88
+ if (targetTypes.includes(n.type)) {
89
+ results.push(n);
90
+ }
91
+ for (const child of n.children) {
92
+ walk(child);
93
+ }
94
+ }
95
+ walk(node);
96
+ return results;
97
+ }
98
+ /**
99
+ * Evaluate a structural rule using tree-sitter AST matching.
100
+ */
101
+ async function evaluateStructural(rule, filePath, content) {
102
+ const language = detectLanguage(filePath);
103
+ if (!language)
104
+ return [];
105
+ const parser = await getParser(language);
106
+ if (!parser)
107
+ return [];
108
+ const tree = parser.parse(content);
109
+ // Parse rule.query as comma-separated node types to match
110
+ const targetTypes = rule.query
111
+ .split(",")
112
+ .map((t) => t.trim())
113
+ .filter(Boolean);
114
+ if (targetTypes.length === 0)
115
+ return [];
116
+ const matches = collectNodesByType(tree.rootNode, targetTypes);
117
+ return matches.map((node) => ({
118
+ ruleKey: rule.key,
119
+ ruleName: rule.name,
120
+ severity: rule.severity,
121
+ message: rule.message ||
122
+ `Structural rule "${rule.name}" matched node type "${node.type}"`,
123
+ filePath,
124
+ line: node.startPosition.row + 1,
125
+ matchedCode: node.text.slice(0, 200),
126
+ }));
127
+ }
128
+ /**
129
+ * Evaluate a naming rule using regex against entity names in the file.
130
+ */
131
+ async function evaluateNaming(rule, filePath, localGraph) {
132
+ const entities = await localGraph.getEntitiesByFile(filePath);
133
+ if (entities.length === 0)
134
+ return [];
135
+ let regex;
136
+ try {
137
+ regex = new RegExp(rule.query);
138
+ }
139
+ catch {
140
+ return [];
141
+ }
142
+ const violations = [];
143
+ for (const entity of entities) {
144
+ if (regex.test(entity.name)) {
145
+ violations.push({
146
+ ruleKey: rule.key,
147
+ ruleName: rule.name,
148
+ severity: rule.severity,
149
+ message: rule.message ||
150
+ `Naming rule "${rule.name}" matched entity "${entity.name}"`,
151
+ filePath,
152
+ line: entity.start_line,
153
+ matchedCode: entity.name,
154
+ });
155
+ }
156
+ }
157
+ return violations;
158
+ }
159
+ /**
160
+ * Sprint 9.1: JIT Rule Filtering — score rules by relevance to target entity context.
161
+ *
162
+ * Scoring (Phase 6 §1.4b):
163
+ * +0.4 if rule.file_glob matches filePath
164
+ * +0.2 if rule.scope == "repo"
165
+ * +0.3 if entity kind ∈ rule.target_kinds
166
+ * +0.1 if rule.severity == "block" (always included)
167
+ *
168
+ * Returns rules with score > 0.3 OR severity == "block", capped at 30.
169
+ */
170
+ export async function getRelevantRules(allRules, filePath, entityKey, localGraph) {
171
+ const entityMeta = entityKey ? await localGraph.getEntity(entityKey) : null;
172
+ const scored = allRules.map((rule) => {
173
+ let score = 0.0;
174
+ // +0.4 for file_glob match
175
+ if (rule.file_glob && matchesGlob(filePath, rule.file_glob)) {
176
+ score += 0.4;
177
+ }
178
+ else if (!rule.file_glob) {
179
+ // No glob means rule applies to all files — partial credit
180
+ score += 0.2;
181
+ }
182
+ // +0.2 for repo scope
183
+ if (rule.scope === "repo") {
184
+ score += 0.2;
185
+ }
186
+ // +0.3 for entity kind match
187
+ if (entityMeta && rule.target_kinds) {
188
+ const targetKinds = rule.target_kinds.split(",").map((k) => k.trim());
189
+ if (targetKinds.includes(entityMeta.kind)) {
190
+ score += 0.3;
191
+ }
192
+ }
193
+ // +0.1 for block severity (ensures inclusion)
194
+ if (rule.severity === "block") {
195
+ score += 0.1;
196
+ }
197
+ return { ...rule, relevanceScore: score };
198
+ });
199
+ // Filter: score > 0.3 OR severity == "block"
200
+ const relevant = scored
201
+ .filter((r) => r.relevanceScore > 0.3 || r.severity === "block")
202
+ .sort((a, b) => b.relevanceScore - a.relevanceScore)
203
+ .slice(0, 30);
204
+ const maxScore = relevant.length > 0 ? relevant[0]?.relevanceScore : 0;
205
+ return { rules: relevant, totalRules: allRules.length, maxScore };
206
+ }
207
+ /**
208
+ * Simple glob matching for file paths.
209
+ */
210
+ function matchesGlob(filePath, glob) {
211
+ // Convert glob to regex: * → [^/]*, ** → .*, ? → .
212
+ const escaped = glob
213
+ .replace(/[.+^${}()|[\]\\]/g, "\\$&")
214
+ .replace(/\*\*/g, "<<<GLOBSTAR>>>")
215
+ .replace(/\*/g, "[^/]*")
216
+ .replace(/<<<GLOBSTAR>>>/g, ".*")
217
+ .replace(/\?/g, ".");
218
+ try {
219
+ return new RegExp(`^${escaped}$`).test(filePath);
220
+ }
221
+ catch {
222
+ return false;
223
+ }
224
+ }
225
+ /**
226
+ * Evaluate all applicable rules against a file.
227
+ *
228
+ * Sprint 9 enhancements:
229
+ * - 9.1: JIT filtering (when entityKey provided)
230
+ * - 9.2: Auto-remediation passthrough (ast_grep_fix → autoFix)
231
+ * - 9.5: STAGED rules evaluated but separated into the evaluator's internal `_meta.stagedRuleResults` return field (not the wire envelope)
232
+ * - 9.6: Rule exceptions downgrade enforcement to "suggest"
233
+ *
234
+ * Partitions rules by engine:
235
+ * - structural: tree-sitter AST matching
236
+ * - naming: regex match against entity names
237
+ * - semgrep/llm: skipped (not supported locally)
238
+ */
239
+ export async function evaluateRules(rules, filePath, content, localGraph, options) {
240
+ const violations = [];
241
+ const stagedResults = [];
242
+ let structuralCount = 0;
243
+ let namingCount = 0;
244
+ let skippedCount = 0;
245
+ let exceptionsApplied = 0;
246
+ // Sprint 9.1: JIT filtering
247
+ let jitMeta;
248
+ let activeRules;
249
+ if (options?.entityKey) {
250
+ const jit = await getRelevantRules(rules, filePath, options.entityKey, localGraph);
251
+ activeRules = jit.rules;
252
+ jitMeta = {
253
+ totalRules: jit.totalRules,
254
+ relevantRules: jit.rules.length,
255
+ maxScore: jit.maxScore,
256
+ };
257
+ }
258
+ else {
259
+ activeRules = rules;
260
+ }
261
+ // Sprint 9.5: Separate staged rules
262
+ const enforceableRules = [];
263
+ const stagedRules = [];
264
+ for (const rule of activeRules) {
265
+ if ((rule.status ?? "active") === "staged") {
266
+ stagedRules.push(rule);
267
+ }
268
+ else {
269
+ enforceableRules.push(rule);
270
+ }
271
+ }
272
+ // Build exception lookup: ruleKey → exception[]
273
+ const exceptionMap = new Map();
274
+ if (options?.exceptions) {
275
+ for (const ex of options.exceptions) {
276
+ const existing = exceptionMap.get(ex.rule_key) ?? [];
277
+ existing.push(ex);
278
+ exceptionMap.set(ex.rule_key, existing);
279
+ }
280
+ }
281
+ // Evaluate enforceable rules
282
+ for (const rule of enforceableRules) {
283
+ if (!rule.enabled) {
284
+ skippedCount++;
285
+ continue;
286
+ }
287
+ const ruleViolations = await evaluateSingleRule(rule, filePath, content, localGraph);
288
+ if (ruleViolations.engine === "skipped") {
289
+ skippedCount++;
290
+ continue;
291
+ }
292
+ if (ruleViolations.engine === "structural")
293
+ structuralCount++;
294
+ else if (ruleViolations.engine === "naming")
295
+ namingCount++;
296
+ // Sprint 9.6: Check exceptions for each violation
297
+ for (const v of ruleViolations.violations) {
298
+ const ruleExceptions = exceptionMap.get(rule.key);
299
+ if (ruleExceptions && ruleExceptions.length > 0) {
300
+ const activeEx = ruleExceptions[0];
301
+ v.severity = "suggest";
302
+ v.exception = {
303
+ key: activeEx.key,
304
+ reason: activeEx.reason,
305
+ expires_at: activeEx.expires_at,
306
+ granted_by: activeEx.granted_by,
307
+ };
308
+ exceptionsApplied++;
309
+ }
310
+ // Sprint 9.2: Auto-remediation passthrough
311
+ if (rule.ast_grep_fix) {
312
+ v.autoFix = {
313
+ rule: rule.key,
314
+ diff: rule.ast_grep_fix,
315
+ confidence: 0.95,
316
+ };
317
+ }
318
+ violations.push(v);
319
+ }
320
+ }
321
+ // Sprint 9.5: Evaluate staged rules (dry-run only)
322
+ for (const rule of stagedRules) {
323
+ if (!rule.enabled)
324
+ continue;
325
+ const ruleViolations = await evaluateSingleRule(rule, filePath, content, localGraph);
326
+ if (ruleViolations.engine === "skipped")
327
+ continue;
328
+ stagedResults.push({
329
+ ruleKey: rule.key,
330
+ ruleName: rule.name,
331
+ wouldViolate: ruleViolations.violations.length > 0,
332
+ violationCount: ruleViolations.violations.length,
333
+ message: ruleViolations.violations.length > 0
334
+ ? ruleViolations.violations[0]?.message
335
+ : `No violations for staged rule "${rule.name}"`,
336
+ });
337
+ }
338
+ // Sprint 9.6: Check for expiring exceptions (7 day window)
339
+ const SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;
340
+ const expiringExceptions = (await localGraph.getExpiringExceptions(SEVEN_DAYS_MS)).map((ex) => ({
341
+ ruleKey: ex.rule_key,
342
+ entityKey: ex.entity_key,
343
+ expires_at: ex.expires_at,
344
+ jira_ticket: ex.jira_ticket,
345
+ }));
346
+ return {
347
+ violations,
348
+ _meta: {
349
+ source: "local",
350
+ evaluatedRules: structuralCount + namingCount,
351
+ skippedRules: skippedCount,
352
+ engines: {
353
+ structural: structuralCount,
354
+ naming: namingCount,
355
+ skipped: skippedCount,
356
+ },
357
+ ...(jitMeta ? { jitFiltering: jitMeta } : {}),
358
+ ...(stagedResults.length > 0 ? { stagedRuleResults: stagedResults } : {}),
359
+ ...(exceptionsApplied > 0 ? { exceptionsApplied } : {}),
360
+ ...(expiringExceptions.length > 0 ? { expiringExceptions } : {}),
361
+ },
362
+ };
363
+ }
364
+ /**
365
+ * Evaluate a single rule and return violations + engine type.
366
+ */
367
+ async function evaluateSingleRule(rule, filePath, content, localGraph) {
368
+ switch (rule.engine) {
369
+ case "structural": {
370
+ const violations = await evaluateStructural(rule, filePath, content);
371
+ return { violations, engine: "structural" };
372
+ }
373
+ case "naming": {
374
+ const violations = await evaluateNaming(rule, filePath, localGraph);
375
+ return { violations, engine: "naming" };
376
+ }
377
+ default:
378
+ return { violations: [], engine: "skipped" };
379
+ }
380
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Auto-Rule Generation — promotes high-confidence corrections into enforced rules.
3
+ *
4
+ * U.6: When a correction has 3+ occurrences and confidence > 0.9,
5
+ * it graduates from "correction" to "rule" — proactively injected
6
+ * to prevent the same mistake in future sessions.
7
+ */
8
+ const PROMOTION_THRESHOLD_CONFIDENCE = 0.9;
9
+ const PROMOTION_THRESHOLD_OCCURRENCES = 3;
10
+ /**
11
+ * Evaluate corrections for rule promotion.
12
+ * Returns rules that should be auto-generated.
13
+ */
14
+ export function evaluateForPromotion(corrections) {
15
+ const rules = [];
16
+ for (const correction of corrections) {
17
+ if (correction.confidence >= PROMOTION_THRESHOLD_CONFIDENCE &&
18
+ correction.occurrences >= PROMOTION_THRESHOLD_OCCURRENCES) {
19
+ rules.push({
20
+ id: `auto-rule:${correction.entityKey}:${correction.pattern}`,
21
+ entityKey: correction.entityKey,
22
+ scope: extractScope(correction.entityKey),
23
+ severity: "warn",
24
+ message: correction.description,
25
+ source: "correction-auto",
26
+ confidence: correction.confidence,
27
+ occurrences: correction.occurrences,
28
+ createdAt: new Date().toISOString(),
29
+ });
30
+ }
31
+ }
32
+ return rules;
33
+ }
34
+ /**
35
+ * Check if a specific correction should be promoted.
36
+ */
37
+ export function shouldPromote(correction) {
38
+ return (correction.confidence >= PROMOTION_THRESHOLD_CONFIDENCE &&
39
+ correction.occurrences >= PROMOTION_THRESHOLD_OCCURRENCES);
40
+ }
41
+ function extractScope(entityKey) {
42
+ if (entityKey.includes("::"))
43
+ return entityKey.split("::")[0] ?? entityKey;
44
+ if (entityKey.includes("/")) {
45
+ const parts = entityKey.split("/");
46
+ return parts.slice(0, -1).join("/");
47
+ }
48
+ return entityKey;
49
+ }