@unerr-ai/unerr 0.1.0 → 0.1.2

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 +996 -710
  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 +312 -0
  553. package/dist/ui/assets/index-B-0HTtUR.js +0 -10
@@ -0,0 +1,97 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import { gitQuery } from "../utils/exec.js";
4
+ export async function listLocalBranches(cwd) {
5
+ const raw = await gitQuery([
6
+ "branch",
7
+ "-a",
8
+ "--format=%(HEAD)|%(refname:short)|%(upstream:track)|%(committerdate:relative)",
9
+ ], cwd);
10
+ if (!raw)
11
+ return [];
12
+ const driftCounts = loadBranchDriftCounts(cwd);
13
+ const branches = [];
14
+ for (const line of raw.split("\n")) {
15
+ const trimmed = line.trim();
16
+ if (!trimmed)
17
+ continue;
18
+ const parts = trimmed.split("|");
19
+ const isCurrent = parts[0] === "*";
20
+ const name = parts[1] ?? "";
21
+ const tracking = parts[2] ?? "";
22
+ const lastCommit = parts[3] ?? "";
23
+ if (!name)
24
+ continue;
25
+ branches.push({
26
+ name,
27
+ isCurrent,
28
+ lastCommit,
29
+ tracking,
30
+ driftEntityCount: driftCounts.get(name) ?? 0,
31
+ });
32
+ }
33
+ return branches;
34
+ }
35
+ function loadBranchDriftCounts(cwd) {
36
+ const counts = new Map();
37
+ const branchDir = path.join(cwd, ".unerr", "state", "branch-overlays");
38
+ if (!fs.existsSync(branchDir))
39
+ return counts;
40
+ try {
41
+ const entries = fs.readdirSync(branchDir, { withFileTypes: true });
42
+ for (const entry of entries) {
43
+ if (!entry.isDirectory())
44
+ continue;
45
+ const overlayPath = path.join(branchDir, entry.name, "overlay_snapshot.json");
46
+ if (!fs.existsSync(overlayPath))
47
+ continue;
48
+ try {
49
+ const raw = fs.readFileSync(overlayPath, "utf-8");
50
+ const snapshot = JSON.parse(raw);
51
+ if (snapshot.branch && snapshot.entities) {
52
+ counts.set(snapshot.branch, snapshot.entities.length);
53
+ }
54
+ }
55
+ catch {
56
+ // Skip corrupt snapshots
57
+ }
58
+ }
59
+ }
60
+ catch {
61
+ // Non-blocking
62
+ }
63
+ return counts;
64
+ }
65
+ export function registerBranchesCommand(program) {
66
+ program
67
+ .command("branches")
68
+ .description("Show branches for this repository")
69
+ .action(async () => {
70
+ try {
71
+ const cwd = process.cwd();
72
+ const branches = await listLocalBranches(cwd);
73
+ if (branches.length === 0) {
74
+ process.stderr.write("[unerr] No branches found.\n");
75
+ return;
76
+ }
77
+ let withDrift = 0;
78
+ process.stderr.write("\n");
79
+ for (const branch of branches) {
80
+ const marker = branch.isCurrent ? "* " : " ";
81
+ const trackingSuffix = branch.tracking ? ` ${branch.tracking}` : "";
82
+ let driftSuffix = "";
83
+ if (branch.driftEntityCount > 0) {
84
+ driftSuffix = ` (${branch.driftEntityCount} drift entities)`;
85
+ withDrift++;
86
+ }
87
+ process.stderr.write(`${marker}${branch.name.padEnd(30)} ${branch.lastCommit}${trackingSuffix}${driftSuffix}\n`);
88
+ }
89
+ process.stderr.write(`\n ${branches.length} branches · ${withDrift} with drift overlays\n\n`);
90
+ }
91
+ catch (error) {
92
+ const message = error instanceof Error ? error.message : String(error);
93
+ console.error(`Error: ${message}`);
94
+ process.exit(1);
95
+ }
96
+ });
97
+ }
@@ -0,0 +1,225 @@
1
+ /**
2
+ * unerr check-commit — Pre-commit convention validation.
3
+ *
4
+ * Called by the pre-commit git hook to check staged changes
5
+ * against project conventions. Non-blocking by default.
6
+ *
7
+ * Sprint 4 (Task 4.2): Full convention checking implementation.
8
+ *
9
+ * Flow:
10
+ * 1. Load CozoDB graph from local snapshot
11
+ * 2. Get staged files from git
12
+ * 3. Evaluate rules against each staged file
13
+ * 4. Display violations with formatted output
14
+ * 5. Exit 1 if blocking mode and violations found
15
+ *
16
+ * Exit codes:
17
+ * 0 — All checks pass (or no checks available)
18
+ * 1 — Violations found (only when blocking mode is enabled)
19
+ */
20
+ import { existsSync, readFileSync } from "node:fs";
21
+ import { extname, join } from "node:path";
22
+ import { gunzipSync } from "node:zlib";
23
+ import pc from "picocolors";
24
+ import { getStagedFiles } from "../utils/git.js";
25
+ import { logInfo } from "../utils/log.js";
26
+ import { detail, fail, info, section, success, warn } from "../utils/ui.js";
27
+ /** File extensions we can evaluate rules against. */
28
+ const SUPPORTED_EXTENSIONS = new Set([
29
+ ".ts",
30
+ ".tsx",
31
+ ".js",
32
+ ".jsx",
33
+ ".py",
34
+ ".go",
35
+ ]);
36
+ export function registerCheckCommitCommand(program) {
37
+ program
38
+ .command("check-commit")
39
+ .description("Check staged changes against project conventions (pre-commit hook)")
40
+ .option("--blocking", "Exit with code 1 on violations (default: non-blocking)")
41
+ .option("--verbose", "Show detailed output including passing files")
42
+ .action(async (opts) => {
43
+ const cwd = process.cwd();
44
+ // ── Blocking mode detection ──────────────────────────────────
45
+ let blockingMode = opts.blocking ?? false;
46
+ const settingsPath = join(cwd, ".unerr", "settings.json");
47
+ if (!blockingMode && existsSync(settingsPath)) {
48
+ try {
49
+ const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
50
+ blockingMode = settings.hooks?.precommit?.blocking ?? false;
51
+ }
52
+ catch {
53
+ /* ignore malformed settings */
54
+ }
55
+ }
56
+ logInfo("check-commit invoked", { blocking: blockingMode });
57
+ // ── Config gating ────────────────────────────────────────────
58
+ const configPath = join(cwd, ".unerr", "config.json");
59
+ if (!existsSync(configPath)) {
60
+ logInfo("check-commit: no .unerr/config.json, skipping");
61
+ return;
62
+ }
63
+ let repoId;
64
+ try {
65
+ const config = JSON.parse(readFileSync(configPath, "utf-8"));
66
+ if (!config.repoId) {
67
+ logInfo("check-commit: no repoId in config, skipping");
68
+ return;
69
+ }
70
+ repoId = config.repoId;
71
+ }
72
+ catch {
73
+ logInfo("check-commit: invalid config.json, skipping");
74
+ return;
75
+ }
76
+ // ── Get staged files ─────────────────────────────────────────
77
+ const stagedFiles = await getStagedFiles(cwd);
78
+ if (stagedFiles.length === 0) {
79
+ logInfo("check-commit: no staged files");
80
+ return;
81
+ }
82
+ // Filter to supported file types
83
+ const checkableFiles = stagedFiles.filter((f) => SUPPORTED_EXTENSIONS.has(extname(f)));
84
+ if (checkableFiles.length === 0) {
85
+ if (opts.verbose) {
86
+ section("unerr pre-commit check");
87
+ detail(`${stagedFiles.length} staged file${stagedFiles.length !== 1 ? "s" : ""} — none with supported extensions`);
88
+ }
89
+ return;
90
+ }
91
+ // ── Load graph ───────────────────────────────────────────────
92
+ const snapshotsDir = join(cwd, ".unerr", "snapshots");
93
+ const manifestsDir = join(cwd, ".unerr", "manifests");
94
+ const localGraph = await loadGraphForCheckCommit(repoId, snapshotsDir, manifestsDir);
95
+ if (!localGraph) {
96
+ if (opts.verbose) {
97
+ section("unerr pre-commit check");
98
+ detail("No local graph available — skipping convention checks");
99
+ }
100
+ logInfo("check-commit: no graph available, skipping");
101
+ return;
102
+ }
103
+ // Check if any rules exist
104
+ if (!(await localGraph.hasRules())) {
105
+ if (opts.verbose) {
106
+ section("unerr pre-commit check");
107
+ detail("No rules defined — skipping convention checks");
108
+ }
109
+ logInfo("check-commit: no rules in graph, skipping");
110
+ return;
111
+ }
112
+ // ── Evaluate rules per file ──────────────────────────────────
113
+ const { evaluateRules } = await import("../intelligence/rule-evaluator.js");
114
+ const allFileViolations = [];
115
+ let totalRulesEvaluated = 0;
116
+ let filesChecked = 0;
117
+ for (const filePath of checkableFiles) {
118
+ const absPath = join(cwd, filePath);
119
+ if (!existsSync(absPath))
120
+ continue;
121
+ let content;
122
+ try {
123
+ content = readFileSync(absPath, "utf-8");
124
+ }
125
+ catch {
126
+ continue; // Skip unreadable files
127
+ }
128
+ const rules = await localGraph.getRules(filePath);
129
+ if (rules.length === 0)
130
+ continue;
131
+ filesChecked++;
132
+ totalRulesEvaluated += rules.length;
133
+ try {
134
+ const result = await evaluateRules(rules, filePath, content, localGraph);
135
+ if (result.violations.length > 0) {
136
+ allFileViolations.push({
137
+ filePath,
138
+ violations: result.violations,
139
+ });
140
+ }
141
+ }
142
+ catch (err) {
143
+ logInfo(`check-commit: rule evaluation failed for ${filePath}`, err);
144
+ }
145
+ }
146
+ const totalViolations = allFileViolations.reduce((sum, fv) => sum + fv.violations.length, 0);
147
+ // ── Display results ──────────────────────────────────────────
148
+ section("unerr pre-commit check");
149
+ if (totalViolations === 0) {
150
+ success(`${filesChecked} file${filesChecked !== 1 ? "s" : ""} checked, ${totalRulesEvaluated} rules evaluated — all clear`);
151
+ process.exitCode = 0;
152
+ return;
153
+ }
154
+ // Display violations grouped by file
155
+ for (const fv of allFileViolations) {
156
+ fail(`${fv.filePath}`);
157
+ for (const v of fv.violations) {
158
+ const location = v.line ? `:${v.line}` : "";
159
+ const severityColor = v.severity === "error"
160
+ ? pc.red
161
+ : v.severity === "warning"
162
+ ? pc.yellow
163
+ : pc.dim;
164
+ info(`${severityColor(`[${v.severity}]`)} ${v.message}${location ? pc.dim(` (line ${v.line})`) : ""}`);
165
+ if (v.matchedCode && opts.verbose) {
166
+ detail(` → ${v.matchedCode.slice(0, 80)}`);
167
+ }
168
+ }
169
+ }
170
+ // Summary line
171
+ const errorCount = allFileViolations.reduce((sum, fv) => sum + fv.violations.filter((v) => v.severity === "error").length, 0);
172
+ const warningCount = totalViolations - errorCount;
173
+ const errorSuffix = errorCount > 0
174
+ ? ` (${errorCount} error${errorCount !== 1 ? "s" : ""})`
175
+ : "";
176
+ const warnSuffix = warningCount > 0
177
+ ? ` (${warningCount} warning${warningCount !== 1 ? "s" : ""})`
178
+ : "";
179
+ warn(`${totalViolations} violation${totalViolations !== 1 ? "s" : ""} found${errorSuffix}${warnSuffix}`);
180
+ if (blockingMode) {
181
+ fail("Commit blocked — fix violations or use --no-verify to bypass");
182
+ process.exitCode = 1;
183
+ }
184
+ else {
185
+ detail("Non-blocking mode — commit will proceed");
186
+ detail("Enable blocking: set hooks.precommit.blocking=true in .unerr/settings.json");
187
+ process.exitCode = 0;
188
+ }
189
+ });
190
+ }
191
+ // ── Graph Loading ────────────────────────────────────────────────────
192
+ /**
193
+ * Load CozoDB graph for standalone check-commit (proxy may not be running).
194
+ * Returns null if no snapshot available.
195
+ */
196
+ async function loadGraphForCheckCommit(repoId, snapshotsDir, manifestsDir) {
197
+ // Check manifest exists
198
+ const manifestPath = join(manifestsDir, `${repoId}.json`);
199
+ if (!existsSync(manifestPath))
200
+ return null;
201
+ // Find snapshot file
202
+ let snapshotPath = join(snapshotsDir, `${repoId}.msgpack.gz`);
203
+ if (!existsSync(snapshotPath)) {
204
+ snapshotPath = join(snapshotsDir, `${repoId}.msgpack`);
205
+ }
206
+ if (!existsSync(snapshotPath))
207
+ return null;
208
+ try {
209
+ // Dynamic imports to keep cold start fast when no check needed
210
+ const { default: CozoDbConstructor } = await import("cozo-node");
211
+ const { CozoGraphStore } = await import("../intelligence/local-graph.js");
212
+ const { unpack } = await import("msgpackr");
213
+ const db = new CozoDbConstructor();
214
+ const localGraph = await CozoGraphStore.create(db);
215
+ const raw = readFileSync(snapshotPath);
216
+ const buffer = snapshotPath.endsWith(".gz") ? gunzipSync(raw) : raw;
217
+ const envelope = unpack(buffer);
218
+ await localGraph.loadSnapshot(envelope);
219
+ return localGraph;
220
+ }
221
+ catch (err) {
222
+ logInfo("check-commit: failed to load graph", err);
223
+ return null;
224
+ }
225
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * `unerr compress-output` — stdin→stdout compression for CLI hooks.
3
+ *
4
+ * S6.4: Reads text from stdin, compresses with the output compressor,
5
+ * writes compressed output to stdout. When graph is available, passes
6
+ * entity risk map for graph-aware prioritization.
7
+ *
8
+ * Usage (in hooks): echo "$OUTPUT" | unerr compress-output
9
+ */
10
+ import { existsSync, readFileSync } from "node:fs";
11
+ import { join } from "node:path";
12
+ import { compressOutput, } from "../proxy/output-compressor.js";
13
+ /**
14
+ * Load entity risk map from the local graph state if available.
15
+ * Returns empty map if graph is not initialized.
16
+ */
17
+ function loadEntityRiskMap(cwd) {
18
+ const riskMap = new Map();
19
+ try {
20
+ const unerrDir = join(cwd, ".unerr");
21
+ const configPath = join(unerrDir, "config.json");
22
+ if (!existsSync(configPath))
23
+ return riskMap;
24
+ const config = JSON.parse(readFileSync(configPath, "utf-8"));
25
+ if (!config.repoId)
26
+ return riskMap;
27
+ const riskCachePath = join(unerrDir, "state", "entity_risk_cache.json");
28
+ if (!existsSync(riskCachePath))
29
+ return riskMap;
30
+ const data = JSON.parse(readFileSync(riskCachePath, "utf-8"));
31
+ for (const [key, info] of Object.entries(data)) {
32
+ riskMap.set(key, info);
33
+ }
34
+ }
35
+ catch {
36
+ // Risk map loading is best-effort — compression works without it
37
+ }
38
+ return riskMap;
39
+ }
40
+ export function registerCompressOutputCommand(program) {
41
+ program
42
+ .command("compress-output")
43
+ .description("Compress text from stdin using graph-aware compression (for hooks)")
44
+ .option("--budget <tokens>", "Token budget", "2000")
45
+ .option("--no-graph", "Skip loading graph risk map")
46
+ .action(async (opts) => {
47
+ const budget = Number.parseInt(opts.budget, 10) || 2000;
48
+ let input = "";
49
+ for await (const chunk of process.stdin) {
50
+ input += chunk;
51
+ }
52
+ if (input.length === 0) {
53
+ process.exit(0);
54
+ return;
55
+ }
56
+ // S6.4: Load entity risk map from graph when available
57
+ const entityRiskMap = opts.graph !== false ? loadEntityRiskMap(process.cwd()) : undefined;
58
+ const result = compressOutput(input, {
59
+ tokenBudget: budget,
60
+ entityRiskMap: entityRiskMap && entityRiskMap.size > 0 ? entityRiskMap : undefined,
61
+ });
62
+ process.stdout.write(result.output);
63
+ });
64
+ }
@@ -0,0 +1,243 @@
1
+ /**
2
+ * unerr config verify — P5.6-ADV-04: Self-healing MCP configuration.
3
+ * Checks and repairs MCP config for supported IDEs (VS Code, Cursor, etc.)
4
+ */
5
+ import * as fs from "node:fs";
6
+ import * as os from "node:os";
7
+ import * as path from "node:path";
8
+ const IDE_CONFIG_PATHS = {
9
+ vscode: path.join(os.homedir(), ".vscode", "settings.json"),
10
+ cursor: path.join(os.homedir(), ".cursor", "mcp.json"),
11
+ windsurf: path.join(os.homedir(), ".windsurf", "mcp.json"),
12
+ "claude-code": path.join(os.homedir(), ".claude", "claude_desktop_config.json"),
13
+ };
14
+ function loadConfig() {
15
+ const configPath = path.join(process.cwd(), ".unerr", "config.json");
16
+ if (!fs.existsSync(configPath))
17
+ return null;
18
+ return JSON.parse(fs.readFileSync(configPath, "utf-8"));
19
+ }
20
+ export function checkIdeConfig(ideName, configPath) {
21
+ const issues = [];
22
+ if (!fs.existsSync(configPath)) {
23
+ return {
24
+ found: false,
25
+ configured: false,
26
+ issues: [`${ideName} config not found at ${configPath}`],
27
+ needsMigration: false,
28
+ };
29
+ }
30
+ try {
31
+ const raw = fs.readFileSync(configPath, "utf-8");
32
+ const config = JSON.parse(raw);
33
+ if (!config.mcpServers) {
34
+ issues.push(`${ideName}: No mcpServers section found`);
35
+ return { found: true, configured: false, issues, needsMigration: false };
36
+ }
37
+ const unerrServer = config.mcpServers.unerr;
38
+ if (!unerrServer) {
39
+ issues.push(`${ideName}: No unerr MCP server configured`);
40
+ return { found: true, configured: false, issues, needsMigration: false };
41
+ }
42
+ // Check if still pointing to remote URL (needs migration to local proxy)
43
+ if (unerrServer.url && !unerrServer.command) {
44
+ issues.push(`${ideName}: unerr MCP config points to remote URL — should use local proxy`);
45
+ return { found: true, configured: true, issues, needsMigration: true };
46
+ }
47
+ // Check if using local proxy correctly (direct binary or npx)
48
+ if (unerrServer.command === "unerr" &&
49
+ unerrServer.args?.includes("--mcp")) {
50
+ return { found: true, configured: true, issues, needsMigration: false };
51
+ }
52
+ // Legacy: npx @unerr/unerr format (needs migration to direct binary)
53
+ if (unerrServer.command === "npx" &&
54
+ (unerrServer.args?.includes("@unerr/unerr") ||
55
+ unerrServer.args?.includes("@unerr/unerr-mcp"))) {
56
+ issues.push(`${ideName}: using npx with unpublished package — should use direct 'unerr' binary`);
57
+ return { found: true, configured: true, issues, needsMigration: true };
58
+ }
59
+ issues.push(`${ideName}: unerr MCP config has unexpected format`);
60
+ return { found: true, configured: true, issues, needsMigration: true };
61
+ }
62
+ catch {
63
+ issues.push(`${ideName}: Failed to parse config at ${configPath}`);
64
+ return { found: true, configured: false, issues, needsMigration: false };
65
+ }
66
+ }
67
+ export function repairIdeConfig(ideName, configPath, mode = "proxy") {
68
+ try {
69
+ const dir = path.dirname(configPath);
70
+ if (!fs.existsSync(dir)) {
71
+ fs.mkdirSync(dir, { recursive: true });
72
+ }
73
+ let config = {};
74
+ if (fs.existsSync(configPath)) {
75
+ const raw = fs.readFileSync(configPath, "utf-8");
76
+ config = JSON.parse(raw);
77
+ }
78
+ if (!config.mcpServers)
79
+ config.mcpServers = {};
80
+ if (mode === "standalone") {
81
+ // Sprint 5.4: Standalone read-only MCP server
82
+ const graphPath = resolveGraphPath();
83
+ config.mcpServers.unerr = {
84
+ command: "unerr",
85
+ args: ["--mcp"],
86
+ env: graphPath ? { UNERR_GRAPH_PATH: graphPath } : {},
87
+ };
88
+ }
89
+ else {
90
+ // Local proxy — direct binary
91
+ config.mcpServers.unerr = {
92
+ command: "unerr",
93
+ args: ["--mcp"],
94
+ };
95
+ }
96
+ fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`);
97
+ return true;
98
+ }
99
+ catch {
100
+ return false;
101
+ }
102
+ }
103
+ /**
104
+ * Sprint 5.4: Resolve the graph snapshot path.
105
+ * Looks in the repo's .unerr/snapshots/ directory.
106
+ */
107
+ function resolveGraphPath() {
108
+ const snapshotsDir = path.join(process.cwd(), ".unerr", "snapshots");
109
+ if (!fs.existsSync(snapshotsDir))
110
+ return null;
111
+ const files = fs
112
+ .readdirSync(snapshotsDir)
113
+ .filter((f) => f.endsWith(".msgpack.gz") || f.endsWith(".msgpack"))
114
+ .map((f) => ({
115
+ name: f,
116
+ path: path.join(snapshotsDir, f),
117
+ mtime: fs.statSync(path.join(snapshotsDir, f)).mtimeMs,
118
+ }))
119
+ .sort((a, b) => b.mtime - a.mtime);
120
+ return files[0]?.path ?? null;
121
+ }
122
+ export function registerConfigVerifyCommand(program) {
123
+ const configCmd = program
124
+ .command("config")
125
+ .description("Manage unerr configuration");
126
+ configCmd
127
+ .command("verify")
128
+ .description("Check and optionally repair MCP configuration for IDEs")
129
+ .option("--silent", "Only output errors")
130
+ .option("--repair", "Automatically repair misconfigured IDEs")
131
+ .option("--ide <ide>", "Check specific IDE (vscode, cursor, windsurf, claude-code)")
132
+ .option("--mode <mode>", "Server mode: proxy (full) or standalone (read-only)", "proxy")
133
+ .action(async (opts) => {
134
+ const idesToCheck = opts.ide
135
+ ? { [opts.ide]: IDE_CONFIG_PATHS[opts.ide] ?? "" }
136
+ : IDE_CONFIG_PATHS;
137
+ let allGood = true;
138
+ for (const [ideName, configPath] of Object.entries(idesToCheck)) {
139
+ if (!configPath) {
140
+ if (!opts.silent)
141
+ console.log(` Unknown IDE: ${ideName}`);
142
+ continue;
143
+ }
144
+ const result = checkIdeConfig(ideName, configPath);
145
+ if (result.configured && result.issues.length === 0) {
146
+ if (!opts.silent)
147
+ console.log(` ✓ ${ideName}: configured correctly`);
148
+ }
149
+ else {
150
+ allGood = false;
151
+ for (const issue of result.issues) {
152
+ console.log(` ✗ ${issue}`);
153
+ }
154
+ if (opts.repair) {
155
+ const serverMode = (opts.mode === "standalone" ? "standalone" : "proxy");
156
+ const repaired = repairIdeConfig(ideName, configPath, serverMode);
157
+ if (repaired) {
158
+ console.log(` ✓ ${ideName}: repaired`);
159
+ }
160
+ else {
161
+ console.log(` ✗ ${ideName}: repair failed`);
162
+ }
163
+ }
164
+ }
165
+ }
166
+ if (!allGood && !opts.repair) {
167
+ console.log("\n Run with --repair to fix issues automatically.");
168
+ }
169
+ if (allGood && !opts.silent) {
170
+ console.log("\n All IDE configurations look good!");
171
+ }
172
+ });
173
+ // Show MCP config for manual copy-paste
174
+ configCmd
175
+ .command("show")
176
+ .description("Show MCP config snippet for an agent (for manual setup)")
177
+ .argument("[agent]", "Agent name (e.g. cursor, claude-code, kiro) or 'all'")
178
+ .action(async (agent) => {
179
+ const { generateConfigSnippet, getConfigInfo } = await import("../config/mcp-config-writer.js");
180
+ const { AGENT_REGISTRY } = await import("../config/agent-registry.js");
181
+ const { ideDisplayName } = await import("../utils/detect.js");
182
+ if (!agent || agent === "all") {
183
+ console.log("\n Supported agents and their MCP config paths:\n");
184
+ for (const a of AGENT_REGISTRY) {
185
+ console.log(` ${a.name.padEnd(22)} ${a.projectConfigPath}`);
186
+ }
187
+ console.log("\n Usage: unerr install <agent>\n Example: unerr install kiro\n");
188
+ return;
189
+ }
190
+ const agentDef = AGENT_REGISTRY.find((a) => a.id === agent || a.name.toLowerCase() === agent.toLowerCase());
191
+ if (!agentDef) {
192
+ console.error(` Unknown agent: ${agent}\n Available: ${AGENT_REGISTRY.map((a) => a.id).join(", ")}`);
193
+ process.exit(1);
194
+ }
195
+ const info = getConfigInfo(agentDef.id);
196
+ const snippet = generateConfigSnippet(agentDef.id);
197
+ console.log(`\n ${agentDef.name} — ${agentDef.description}`);
198
+ console.log(` Config path: ${info?.path}\n`);
199
+ console.log(" Add this to your config:\n");
200
+ console.log(snippet
201
+ .split("\n")
202
+ .map((l) => ` ${l}`)
203
+ .join("\n"));
204
+ console.log("");
205
+ });
206
+ // Git hooks sub-command
207
+ configCmd
208
+ .command("install-hooks")
209
+ .description("Install git hooks for automatic MCP config verification")
210
+ .action(async () => {
211
+ const gitDir = path.join(process.cwd(), ".git");
212
+ if (!fs.existsSync(gitDir)) {
213
+ console.error("Not a git repository");
214
+ process.exit(1);
215
+ }
216
+ const hooksDir = path.join(gitDir, "hooks");
217
+ if (!fs.existsSync(hooksDir)) {
218
+ fs.mkdirSync(hooksDir, { recursive: true });
219
+ }
220
+ const hookScript = `#!/bin/sh
221
+ # unerr auto-verify MCP config
222
+ if command -v unerr &> /dev/null; then
223
+ unerr config verify --silent 2>/dev/null || true
224
+ fi
225
+ `;
226
+ for (const hookName of ["post-checkout", "post-merge"]) {
227
+ const hookPath = path.join(hooksDir, hookName);
228
+ if (fs.existsSync(hookPath)) {
229
+ const existing = fs.readFileSync(hookPath, "utf-8");
230
+ if (existing.includes("unerr config verify")) {
231
+ console.log(` ✓ ${hookName}: already installed`);
232
+ continue;
233
+ }
234
+ fs.appendFileSync(hookPath, `\n${hookScript}`);
235
+ }
236
+ else {
237
+ fs.writeFileSync(hookPath, hookScript);
238
+ fs.chmodSync(hookPath, "755");
239
+ }
240
+ console.log(` ✓ ${hookName}: installed`);
241
+ }
242
+ });
243
+ }