@winspan/claude-forge 8.54.3 → 9.2.0

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 (879) hide show
  1. package/DEVELOPMENT.md +649 -33
  2. package/README.md +155 -17
  3. package/dist/catalogs/agents.json +72 -0
  4. package/dist/catalogs/skills.json +194 -0
  5. package/dist/claudemd/claudemd-generator.d.ts +45 -45
  6. package/dist/claudemd/claudemd-generator.d.ts.map +1 -1
  7. package/dist/claudemd/claudemd-generator.js +128 -449
  8. package/dist/claudemd/claudemd-generator.js.map +1 -1
  9. package/dist/claudemd/index.d.ts +14 -4
  10. package/dist/claudemd/index.d.ts.map +1 -1
  11. package/dist/claudemd/index.js +15 -4
  12. package/dist/claudemd/index.js.map +1 -1
  13. package/dist/claudemd/resume-manager.d.ts.map +1 -1
  14. package/dist/claudemd/resume-manager.js +37 -9
  15. package/dist/claudemd/resume-manager.js.map +1 -1
  16. package/dist/claudemd/templates/swarm-protocol.md +35 -186
  17. package/dist/claudemd/violations-manager.d.ts +40 -0
  18. package/dist/claudemd/violations-manager.d.ts.map +1 -0
  19. package/dist/claudemd/violations-manager.js +106 -0
  20. package/dist/claudemd/violations-manager.js.map +1 -0
  21. package/dist/cli/commands/admin.d.ts +15 -0
  22. package/dist/cli/commands/admin.d.ts.map +1 -0
  23. package/dist/cli/commands/admin.js +177 -0
  24. package/dist/cli/commands/admin.js.map +1 -0
  25. package/dist/cli/commands/agents.d.ts +18 -0
  26. package/dist/cli/commands/agents.d.ts.map +1 -0
  27. package/dist/cli/commands/agents.js +160 -0
  28. package/dist/cli/commands/agents.js.map +1 -0
  29. package/dist/cli/commands/bypass.d.ts +18 -0
  30. package/dist/cli/commands/bypass.d.ts.map +1 -0
  31. package/dist/cli/commands/bypass.js +87 -0
  32. package/dist/cli/commands/bypass.js.map +1 -0
  33. package/dist/cli/commands/claudemd.d.ts +60 -0
  34. package/dist/cli/commands/claudemd.d.ts.map +1 -1
  35. package/dist/cli/commands/claudemd.js +174 -37
  36. package/dist/cli/commands/claudemd.js.map +1 -1
  37. package/dist/cli/commands/config.d.ts.map +1 -1
  38. package/dist/cli/commands/config.js +94 -1
  39. package/dist/cli/commands/config.js.map +1 -1
  40. package/dist/cli/commands/daemon.d.ts +39 -0
  41. package/dist/cli/commands/daemon.d.ts.map +1 -1
  42. package/dist/cli/commands/daemon.js +167 -20
  43. package/dist/cli/commands/daemon.js.map +1 -1
  44. package/dist/cli/commands/decisions.d.ts +129 -0
  45. package/dist/cli/commands/decisions.d.ts.map +1 -0
  46. package/dist/cli/commands/decisions.js +669 -0
  47. package/dist/cli/commands/decisions.js.map +1 -0
  48. package/dist/cli/commands/doctor.d.ts +29 -0
  49. package/dist/cli/commands/doctor.d.ts.map +1 -0
  50. package/dist/cli/commands/doctor.js +124 -0
  51. package/dist/cli/commands/doctor.js.map +1 -0
  52. package/dist/cli/commands/entropy.d.ts +35 -0
  53. package/dist/cli/commands/entropy.d.ts.map +1 -0
  54. package/dist/cli/commands/entropy.js +121 -0
  55. package/dist/cli/commands/entropy.js.map +1 -0
  56. package/dist/cli/commands/executions.d.ts +1 -0
  57. package/dist/cli/commands/executions.d.ts.map +1 -1
  58. package/dist/cli/commands/executions.js +10 -1
  59. package/dist/cli/commands/executions.js.map +1 -1
  60. package/dist/cli/commands/fix.d.ts +31 -0
  61. package/dist/cli/commands/fix.d.ts.map +1 -0
  62. package/dist/cli/commands/fix.js +108 -0
  63. package/dist/cli/commands/fix.js.map +1 -0
  64. package/dist/cli/commands/governance.d.ts +21 -0
  65. package/dist/cli/commands/governance.d.ts.map +1 -0
  66. package/dist/cli/commands/governance.js +60 -0
  67. package/dist/cli/commands/governance.js.map +1 -0
  68. package/dist/cli/commands/init.d.ts +27 -0
  69. package/dist/cli/commands/init.d.ts.map +1 -1
  70. package/dist/cli/commands/init.js +158 -146
  71. package/dist/cli/commands/init.js.map +1 -1
  72. package/dist/cli/commands/insights-goal-check.d.ts +50 -0
  73. package/dist/cli/commands/insights-goal-check.d.ts.map +1 -0
  74. package/dist/cli/commands/insights-goal-check.js +318 -0
  75. package/dist/cli/commands/insights-goal-check.js.map +1 -0
  76. package/dist/cli/commands/insights.d.ts +15 -0
  77. package/dist/cli/commands/insights.d.ts.map +1 -0
  78. package/dist/cli/commands/insights.js +127 -0
  79. package/dist/cli/commands/insights.js.map +1 -0
  80. package/dist/cli/commands/knowledge.d.ts +66 -0
  81. package/dist/cli/commands/knowledge.d.ts.map +1 -0
  82. package/dist/cli/commands/knowledge.js +897 -0
  83. package/dist/cli/commands/knowledge.js.map +1 -0
  84. package/dist/cli/commands/mcp.d.ts +0 -12
  85. package/dist/cli/commands/mcp.d.ts.map +1 -1
  86. package/dist/cli/commands/mcp.js +11 -5
  87. package/dist/cli/commands/mcp.js.map +1 -1
  88. package/dist/cli/commands/menu.d.ts.map +1 -1
  89. package/dist/cli/commands/menu.js +10 -184
  90. package/dist/cli/commands/menu.js.map +1 -1
  91. package/dist/cli/commands/project.d.ts +98 -0
  92. package/dist/cli/commands/project.d.ts.map +1 -0
  93. package/dist/cli/commands/project.js +382 -0
  94. package/dist/cli/commands/project.js.map +1 -0
  95. package/dist/cli/commands/skills.d.ts.map +1 -1
  96. package/dist/cli/commands/skills.js +14 -128
  97. package/dist/cli/commands/skills.js.map +1 -1
  98. package/dist/cli/commands/spec.d.ts +40 -0
  99. package/dist/cli/commands/spec.d.ts.map +1 -0
  100. package/dist/cli/commands/spec.js +49 -0
  101. package/dist/cli/commands/spec.js.map +1 -0
  102. package/dist/cli/commands/stats.d.ts.map +1 -1
  103. package/dist/cli/commands/stats.js +3 -2
  104. package/dist/cli/commands/stats.js.map +1 -1
  105. package/dist/cli/commands/status.d.ts.map +1 -1
  106. package/dist/cli/commands/status.js +17 -2
  107. package/dist/cli/commands/status.js.map +1 -1
  108. package/dist/cli/commands/trace.d.ts.map +1 -1
  109. package/dist/cli/commands/trace.js +4 -9
  110. package/dist/cli/commands/trace.js.map +1 -1
  111. package/dist/cli/commands/violations.d.ts +14 -0
  112. package/dist/cli/commands/violations.d.ts.map +1 -0
  113. package/dist/cli/commands/violations.js +43 -0
  114. package/dist/cli/commands/violations.js.map +1 -0
  115. package/dist/cli/index.js +26 -0
  116. package/dist/cli/index.js.map +1 -1
  117. package/dist/cli/init/hook-manager.d.ts +1 -1
  118. package/dist/cli/init/hook-manager.d.ts.map +1 -1
  119. package/dist/cli/init/hook-manager.js +6 -0
  120. package/dist/cli/init/hook-manager.js.map +1 -1
  121. package/dist/cli/utils/resolve-session.d.ts +32 -0
  122. package/dist/cli/utils/resolve-session.d.ts.map +1 -0
  123. package/dist/cli/utils/resolve-session.js +39 -0
  124. package/dist/cli/utils/resolve-session.js.map +1 -0
  125. package/dist/core/config.d.ts +4 -1
  126. package/dist/core/config.d.ts.map +1 -1
  127. package/dist/core/config.js +11 -23
  128. package/dist/core/config.js.map +1 -1
  129. package/dist/core/constants.d.ts +14 -13
  130. package/dist/core/constants.d.ts.map +1 -1
  131. package/dist/core/constants.js +20 -13
  132. package/dist/core/constants.js.map +1 -1
  133. package/dist/core/diagnostics/checks.d.ts +151 -0
  134. package/dist/core/diagnostics/checks.d.ts.map +1 -0
  135. package/dist/core/diagnostics/checks.js +765 -0
  136. package/dist/core/diagnostics/checks.js.map +1 -0
  137. package/dist/core/diagnostics/daemon-status.d.ts +77 -0
  138. package/dist/core/diagnostics/daemon-status.d.ts.map +1 -0
  139. package/dist/core/diagnostics/daemon-status.js +113 -0
  140. package/dist/core/diagnostics/daemon-status.js.map +1 -0
  141. package/dist/core/diagnostics/entropy-checks.d.ts +82 -0
  142. package/dist/core/diagnostics/entropy-checks.d.ts.map +1 -0
  143. package/dist/core/diagnostics/entropy-checks.js +395 -0
  144. package/dist/core/diagnostics/entropy-checks.js.map +1 -0
  145. package/dist/core/diagnostics/fix-runner.d.ts +54 -0
  146. package/dist/core/diagnostics/fix-runner.d.ts.map +1 -0
  147. package/dist/core/diagnostics/fix-runner.js +90 -0
  148. package/dist/core/diagnostics/fix-runner.js.map +1 -0
  149. package/dist/core/diagnostics/knip-runner.d.ts +49 -0
  150. package/dist/core/diagnostics/knip-runner.d.ts.map +1 -0
  151. package/dist/core/diagnostics/knip-runner.js +100 -0
  152. package/dist/core/diagnostics/knip-runner.js.map +1 -0
  153. package/dist/core/diagnostics/markers.d.ts +96 -0
  154. package/dist/core/diagnostics/markers.d.ts.map +1 -0
  155. package/dist/core/diagnostics/markers.js +153 -0
  156. package/dist/core/diagnostics/markers.js.map +1 -0
  157. package/dist/core/governance/global-inject.d.ts +60 -0
  158. package/dist/core/governance/global-inject.d.ts.map +1 -0
  159. package/dist/core/governance/global-inject.js +129 -0
  160. package/dist/core/governance/global-inject.js.map +1 -0
  161. package/dist/core/queue/index.d.ts +16 -3
  162. package/dist/core/queue/index.d.ts.map +1 -1
  163. package/dist/core/queue/index.js +14 -3
  164. package/dist/core/queue/index.js.map +1 -1
  165. package/dist/core/storage/base.d.ts +158 -0
  166. package/dist/core/storage/base.d.ts.map +1 -1
  167. package/dist/core/storage/base.js +570 -0
  168. package/dist/core/storage/base.js.map +1 -1
  169. package/dist/core/storage/codec/tool-input-codec.d.ts +93 -0
  170. package/dist/core/storage/codec/tool-input-codec.d.ts.map +1 -0
  171. package/dist/core/storage/codec/tool-input-codec.js +159 -0
  172. package/dist/core/storage/codec/tool-input-codec.js.map +1 -0
  173. package/dist/core/storage/decisions.d.ts +362 -0
  174. package/dist/core/storage/decisions.d.ts.map +1 -0
  175. package/dist/core/storage/decisions.js +502 -0
  176. package/dist/core/storage/decisions.js.map +1 -0
  177. package/dist/core/storage/events.d.ts +112 -8
  178. package/dist/core/storage/events.d.ts.map +1 -1
  179. package/dist/core/storage/events.js +390 -39
  180. package/dist/core/storage/events.js.map +1 -1
  181. package/dist/core/storage/feedback.d.ts +131 -0
  182. package/dist/core/storage/feedback.d.ts.map +1 -0
  183. package/dist/core/storage/feedback.js +187 -0
  184. package/dist/core/storage/feedback.js.map +1 -0
  185. package/dist/core/storage/forge-config.d.ts +40 -0
  186. package/dist/core/storage/forge-config.d.ts.map +1 -0
  187. package/dist/core/storage/forge-config.js +65 -0
  188. package/dist/core/storage/forge-config.js.map +1 -0
  189. package/dist/core/storage/injections.d.ts +28 -0
  190. package/dist/core/storage/injections.d.ts.map +1 -1
  191. package/dist/core/storage/injections.js +62 -5
  192. package/dist/core/storage/injections.js.map +1 -1
  193. package/dist/core/storage/knowledge.d.ts +106 -0
  194. package/dist/core/storage/knowledge.d.ts.map +1 -0
  195. package/dist/core/storage/knowledge.js +202 -0
  196. package/dist/core/storage/knowledge.js.map +1 -0
  197. package/dist/core/storage/maintenance.d.ts +36 -9
  198. package/dist/core/storage/maintenance.d.ts.map +1 -1
  199. package/dist/core/storage/maintenance.js +56 -24
  200. package/dist/core/storage/maintenance.js.map +1 -1
  201. package/dist/core/storage/pipeline-rollup.d.ts +117 -0
  202. package/dist/core/storage/pipeline-rollup.d.ts.map +1 -0
  203. package/dist/core/storage/pipeline-rollup.js +471 -0
  204. package/dist/core/storage/pipeline-rollup.js.map +1 -0
  205. package/dist/core/storage/routing.d.ts +16 -3
  206. package/dist/core/storage/routing.d.ts.map +1 -1
  207. package/dist/core/storage/routing.js +39 -8
  208. package/dist/core/storage/routing.js.map +1 -1
  209. package/dist/core/storage/rows.d.ts +50 -7
  210. package/dist/core/storage/rows.d.ts.map +1 -1
  211. package/dist/core/storage/schema.sql +302 -23
  212. package/dist/core/storage/sessions.d.ts +136 -0
  213. package/dist/core/storage/sessions.d.ts.map +1 -1
  214. package/dist/core/storage/sessions.js +351 -15
  215. package/dist/core/storage/sessions.js.map +1 -1
  216. package/dist/core/storage/skills.d.ts +1 -0
  217. package/dist/core/storage/skills.d.ts.map +1 -1
  218. package/dist/core/storage/skills.js +21 -6
  219. package/dist/core/storage/skills.js.map +1 -1
  220. package/dist/core/storage/sqlite.d.ts +253 -20
  221. package/dist/core/storage/sqlite.d.ts.map +1 -1
  222. package/dist/core/storage/sqlite.js +425 -16
  223. package/dist/core/storage/sqlite.js.map +1 -1
  224. package/dist/core/storage/tasks.d.ts +474 -2
  225. package/dist/core/storage/tasks.d.ts.map +1 -1
  226. package/dist/core/storage/tasks.js +1213 -18
  227. package/dist/core/storage/tasks.js.map +1 -1
  228. package/dist/core/storage/tool-intercepts.d.ts +69 -0
  229. package/dist/core/storage/tool-intercepts.d.ts.map +1 -0
  230. package/dist/core/storage/tool-intercepts.js +116 -0
  231. package/dist/core/storage/tool-intercepts.js.map +1 -0
  232. package/dist/core/storage/workflow-recommendations.d.ts +124 -0
  233. package/dist/core/storage/workflow-recommendations.d.ts.map +1 -0
  234. package/dist/core/storage/workflow-recommendations.js +274 -0
  235. package/dist/core/storage/workflow-recommendations.js.map +1 -0
  236. package/dist/core/types.d.ts +112 -17
  237. package/dist/core/types.d.ts.map +1 -1
  238. package/dist/core/types.js +12 -0
  239. package/dist/core/types.js.map +1 -1
  240. package/dist/core/utils/backup.d.ts +81 -0
  241. package/dist/core/utils/backup.d.ts.map +1 -0
  242. package/dist/core/utils/backup.js +98 -0
  243. package/dist/core/utils/backup.js.map +1 -0
  244. package/dist/core/utils/binary-paths.d.ts +92 -0
  245. package/dist/core/utils/binary-paths.d.ts.map +1 -0
  246. package/dist/core/utils/binary-paths.js +166 -0
  247. package/dist/core/utils/binary-paths.js.map +1 -0
  248. package/dist/core/utils/bypass-token.d.ts +75 -0
  249. package/dist/core/utils/bypass-token.d.ts.map +1 -0
  250. package/dist/core/utils/bypass-token.js +133 -0
  251. package/dist/core/utils/bypass-token.js.map +1 -0
  252. package/dist/core/utils/cc-builtin-agents.d.ts +3 -0
  253. package/dist/core/utils/cc-builtin-agents.d.ts.map +1 -0
  254. package/dist/core/utils/cc-builtin-agents.js +29 -0
  255. package/dist/core/utils/cc-builtin-agents.js.map +1 -0
  256. package/dist/core/utils/claude-cli-spawn.d.ts +106 -0
  257. package/dist/core/utils/claude-cli-spawn.d.ts.map +1 -0
  258. package/dist/core/utils/claude-cli-spawn.js +219 -0
  259. package/dist/core/utils/claude-cli-spawn.js.map +1 -0
  260. package/dist/core/utils/forge-resume-block.d.ts.map +1 -1
  261. package/dist/core/utils/forge-resume-block.js +3 -2
  262. package/dist/core/utils/forge-resume-block.js.map +1 -1
  263. package/dist/core/utils/logger.d.ts +15 -3
  264. package/dist/core/utils/logger.d.ts.map +1 -1
  265. package/dist/core/utils/logger.js +20 -2
  266. package/dist/core/utils/logger.js.map +1 -1
  267. package/dist/core/utils/noise-prompt.d.ts +97 -0
  268. package/dist/core/utils/noise-prompt.d.ts.map +1 -0
  269. package/dist/core/utils/noise-prompt.js +127 -0
  270. package/dist/core/utils/noise-prompt.js.map +1 -0
  271. package/dist/core/utils/path.d.ts +0 -4
  272. package/dist/core/utils/path.d.ts.map +1 -1
  273. package/dist/core/utils/path.js +0 -7
  274. package/dist/core/utils/path.js.map +1 -1
  275. package/dist/core/utils/time.d.ts +41 -0
  276. package/dist/core/utils/time.d.ts.map +1 -1
  277. package/dist/core/utils/time.js +114 -0
  278. package/dist/core/utils/time.js.map +1 -1
  279. package/dist/daemon/agent-sync.d.ts +24 -0
  280. package/dist/daemon/agent-sync.d.ts.map +1 -0
  281. package/dist/daemon/agent-sync.js +114 -0
  282. package/dist/daemon/agent-sync.js.map +1 -0
  283. package/dist/daemon/config-store.d.ts +55 -0
  284. package/dist/daemon/config-store.d.ts.map +1 -0
  285. package/dist/daemon/config-store.js +137 -0
  286. package/dist/daemon/config-store.js.map +1 -0
  287. package/dist/daemon/event-parser.d.ts +22 -0
  288. package/dist/daemon/event-parser.d.ts.map +1 -1
  289. package/dist/daemon/event-parser.js +49 -3
  290. package/dist/daemon/event-parser.js.map +1 -1
  291. package/dist/daemon/handlers/history-exporter.d.ts.map +1 -1
  292. package/dist/daemon/handlers/history-exporter.js +9 -8
  293. package/dist/daemon/handlers/history-exporter.js.map +1 -1
  294. package/dist/daemon/handlers/post-tool-use.d.ts +58 -4
  295. package/dist/daemon/handlers/post-tool-use.d.ts.map +1 -1
  296. package/dist/daemon/handlers/post-tool-use.js +261 -8
  297. package/dist/daemon/handlers/post-tool-use.js.map +1 -1
  298. package/dist/daemon/handlers/pre-tool-use.d.ts +156 -0
  299. package/dist/daemon/handlers/pre-tool-use.d.ts.map +1 -0
  300. package/dist/daemon/handlers/pre-tool-use.js +585 -0
  301. package/dist/daemon/handlers/pre-tool-use.js.map +1 -0
  302. package/dist/daemon/handlers/stop.d.ts +35 -7
  303. package/dist/daemon/handlers/stop.d.ts.map +1 -1
  304. package/dist/daemon/handlers/stop.js +157 -8
  305. package/dist/daemon/handlers/stop.js.map +1 -1
  306. package/dist/daemon/handlers/user-prompt.d.ts +36 -14
  307. package/dist/daemon/handlers/user-prompt.d.ts.map +1 -1
  308. package/dist/daemon/handlers/user-prompt.js +135 -48
  309. package/dist/daemon/handlers/user-prompt.js.map +1 -1
  310. package/dist/daemon/hook-sync.d.ts.map +1 -1
  311. package/dist/daemon/hook-sync.js +2 -1
  312. package/dist/daemon/hook-sync.js.map +1 -1
  313. package/dist/daemon/index.d.ts.map +1 -1
  314. package/dist/daemon/index.js +471 -43
  315. package/dist/daemon/index.js.map +1 -1
  316. package/dist/daemon/lifecycle.d.ts +48 -1
  317. package/dist/daemon/lifecycle.d.ts.map +1 -1
  318. package/dist/daemon/lifecycle.js +98 -2
  319. package/dist/daemon/lifecycle.js.map +1 -1
  320. package/dist/daemon/router.d.ts +4 -1
  321. package/dist/daemon/router.d.ts.map +1 -1
  322. package/dist/daemon/router.js +4 -2
  323. package/dist/daemon/router.js.map +1 -1
  324. package/dist/daemon/rules/defaults.d.ts +20 -0
  325. package/dist/daemon/rules/defaults.d.ts.map +1 -0
  326. package/dist/daemon/rules/defaults.js +692 -0
  327. package/dist/daemon/rules/defaults.js.map +1 -0
  328. package/dist/daemon/rules/registry.d.ts +47 -0
  329. package/dist/daemon/rules/registry.d.ts.map +1 -0
  330. package/dist/daemon/rules/registry.js +84 -0
  331. package/dist/daemon/rules/registry.js.map +1 -0
  332. package/dist/daemon/rules/types.d.ts +170 -0
  333. package/dist/daemon/rules/types.d.ts.map +1 -0
  334. package/dist/daemon/rules/types.js +15 -0
  335. package/dist/daemon/rules/types.js.map +1 -0
  336. package/dist/daemon/rules/whitelist.d.ts +101 -0
  337. package/dist/daemon/rules/whitelist.d.ts.map +1 -0
  338. package/dist/daemon/rules/whitelist.js +210 -0
  339. package/dist/daemon/rules/whitelist.js.map +1 -0
  340. package/dist/daemon/rules/workflow-defaults.d.ts +52 -0
  341. package/dist/daemon/rules/workflow-defaults.d.ts.map +1 -0
  342. package/dist/daemon/rules/workflow-defaults.js +521 -0
  343. package/dist/daemon/rules/workflow-defaults.js.map +1 -0
  344. package/dist/daemon/server.d.ts +11 -1
  345. package/dist/daemon/server.d.ts.map +1 -1
  346. package/dist/daemon/server.js +7 -1
  347. package/dist/daemon/server.js.map +1 -1
  348. package/dist/daemon/services/context-injector.d.ts +34 -0
  349. package/dist/daemon/services/context-injector.d.ts.map +1 -0
  350. package/dist/daemon/services/context-injector.js +61 -0
  351. package/dist/daemon/services/context-injector.js.map +1 -0
  352. package/dist/daemon/services/decision-hint.d.ts +203 -0
  353. package/dist/daemon/services/decision-hint.d.ts.map +1 -0
  354. package/dist/daemon/services/decision-hint.js +487 -0
  355. package/dist/daemon/services/decision-hint.js.map +1 -0
  356. package/dist/daemon/services/event-ttl-sweep.d.ts +86 -0
  357. package/dist/daemon/services/event-ttl-sweep.d.ts.map +1 -0
  358. package/dist/daemon/services/event-ttl-sweep.js +123 -0
  359. package/dist/daemon/services/event-ttl-sweep.js.map +1 -0
  360. package/dist/daemon/services/experience-extractor.d.ts +67 -0
  361. package/dist/daemon/services/experience-extractor.d.ts.map +1 -0
  362. package/dist/daemon/services/experience-extractor.js +323 -0
  363. package/dist/daemon/services/experience-extractor.js.map +1 -0
  364. package/dist/daemon/services/feedback-aggregator.d.ts +179 -0
  365. package/dist/daemon/services/feedback-aggregator.d.ts.map +1 -0
  366. package/dist/daemon/services/feedback-aggregator.js +455 -0
  367. package/dist/daemon/services/feedback-aggregator.js.map +1 -0
  368. package/dist/daemon/services/heartbeat-writer.d.ts +55 -0
  369. package/dist/daemon/services/heartbeat-writer.d.ts.map +1 -0
  370. package/dist/daemon/services/heartbeat-writer.js +111 -0
  371. package/dist/daemon/services/heartbeat-writer.js.map +1 -0
  372. package/dist/daemon/services/idle-session-sweeper.d.ts +61 -0
  373. package/dist/daemon/services/idle-session-sweeper.d.ts.map +1 -0
  374. package/dist/daemon/services/idle-session-sweeper.js +94 -0
  375. package/dist/daemon/services/idle-session-sweeper.js.map +1 -0
  376. package/dist/daemon/services/idle-task-budget.d.ts +50 -0
  377. package/dist/daemon/services/idle-task-budget.d.ts.map +1 -0
  378. package/dist/daemon/services/idle-task-budget.js +72 -0
  379. package/dist/daemon/services/idle-task-budget.js.map +1 -0
  380. package/dist/daemon/services/intercept-revive.d.ts +60 -0
  381. package/dist/daemon/services/intercept-revive.d.ts.map +1 -0
  382. package/dist/daemon/services/intercept-revive.js +86 -0
  383. package/dist/daemon/services/intercept-revive.js.map +1 -0
  384. package/dist/daemon/services/intercept-rollback-guard.d.ts +105 -0
  385. package/dist/daemon/services/intercept-rollback-guard.d.ts.map +1 -0
  386. package/dist/daemon/services/intercept-rollback-guard.js +152 -0
  387. package/dist/daemon/services/intercept-rollback-guard.js.map +1 -0
  388. package/dist/daemon/services/intercept-timeout-sweeper.d.ts +58 -0
  389. package/dist/daemon/services/intercept-timeout-sweeper.d.ts.map +1 -0
  390. package/dist/daemon/services/intercept-timeout-sweeper.js +83 -0
  391. package/dist/daemon/services/intercept-timeout-sweeper.js.map +1 -0
  392. package/dist/daemon/services/kb-injector.d.ts +57 -0
  393. package/dist/daemon/services/kb-injector.d.ts.map +1 -0
  394. package/dist/daemon/services/kb-injector.js +140 -0
  395. package/dist/daemon/services/kb-injector.js.map +1 -0
  396. package/dist/daemon/services/outcome-classification-service.d.ts +49 -0
  397. package/dist/daemon/services/outcome-classification-service.d.ts.map +1 -0
  398. package/dist/daemon/services/outcome-classification-service.js +214 -0
  399. package/dist/daemon/services/outcome-classification-service.js.map +1 -0
  400. package/dist/daemon/services/outcome-classifier.d.ts +136 -0
  401. package/dist/daemon/services/outcome-classifier.d.ts.map +1 -0
  402. package/dist/daemon/services/outcome-classifier.js +178 -0
  403. package/dist/daemon/services/outcome-classifier.js.map +1 -0
  404. package/dist/daemon/services/outcome-nudge.d.ts +107 -0
  405. package/dist/daemon/services/outcome-nudge.d.ts.map +1 -0
  406. package/dist/daemon/services/outcome-nudge.js +242 -0
  407. package/dist/daemon/services/outcome-nudge.js.map +1 -0
  408. package/dist/daemon/services/spec-approval.d.ts +127 -0
  409. package/dist/daemon/services/spec-approval.d.ts.map +1 -0
  410. package/dist/daemon/services/spec-approval.js +216 -0
  411. package/dist/daemon/services/spec-approval.js.map +1 -0
  412. package/dist/daemon/services/spec-gate.d.ts +54 -0
  413. package/dist/daemon/services/spec-gate.d.ts.map +1 -0
  414. package/dist/daemon/services/spec-gate.js +113 -0
  415. package/dist/daemon/services/spec-gate.js.map +1 -0
  416. package/dist/daemon/services/task-boundary-classifier.d.ts +78 -0
  417. package/dist/daemon/services/task-boundary-classifier.d.ts.map +1 -0
  418. package/dist/daemon/services/task-boundary-classifier.js +202 -0
  419. package/dist/daemon/services/task-boundary-classifier.js.map +1 -0
  420. package/dist/daemon/services/task-segmenter.d.ts +219 -1
  421. package/dist/daemon/services/task-segmenter.d.ts.map +1 -1
  422. package/dist/daemon/services/task-segmenter.js +481 -17
  423. package/dist/daemon/services/task-segmenter.js.map +1 -1
  424. package/dist/daemon/services/violation-reporter.d.ts +130 -0
  425. package/dist/daemon/services/violation-reporter.d.ts.map +1 -0
  426. package/dist/daemon/services/violation-reporter.js +339 -0
  427. package/dist/daemon/services/violation-reporter.js.map +1 -0
  428. package/dist/daemon/skill-sync.d.ts +7 -2
  429. package/dist/daemon/skill-sync.d.ts.map +1 -1
  430. package/dist/daemon/skill-sync.js +114 -9
  431. package/dist/daemon/skill-sync.js.map +1 -1
  432. package/dist/daemon/templates/agents/claudemd-writer.md +101 -0
  433. package/dist/daemon/templates/agents/coder.md +105 -0
  434. package/dist/daemon/templates/agents/decision-maker.md +460 -0
  435. package/dist/daemon/templates/agents/doc-reviewer.md +115 -0
  436. package/dist/daemon/templates/agents/harness-debug-full.md +114 -0
  437. package/dist/daemon/templates/agents/harness-hotfix.md +99 -0
  438. package/dist/daemon/templates/agents/hybrid-feature-with-safety.md +104 -0
  439. package/dist/daemon/templates/agents/knowledge-builder.md +119 -0
  440. package/dist/daemon/templates/agents/patch-applier.md +144 -0
  441. package/dist/daemon/templates/agents/planner.md +165 -0
  442. package/dist/daemon/templates/agents/refactor-specialist.md +98 -0
  443. package/dist/daemon/templates/agents/skill-distiller.md +113 -0
  444. package/dist/daemon/templates/agents/task-boundary-classifier.md +64 -0
  445. package/dist/daemon/templates/agents/verify-agent.md +136 -0
  446. package/dist/daemon/utils/inject-block.d.ts +39 -0
  447. package/dist/daemon/utils/inject-block.d.ts.map +1 -0
  448. package/dist/daemon/utils/inject-block.js +25 -0
  449. package/dist/daemon/utils/inject-block.js.map +1 -0
  450. package/dist/hooks/hook-lib.sh +8 -0
  451. package/dist/hooks/notification.sh +19 -8
  452. package/dist/hooks/post-tool-use.sh +41 -23
  453. package/dist/hooks/pre-tool-use.sh +54 -23
  454. package/dist/hooks/session-start.sh +68 -0
  455. package/dist/hooks/stop.sh +24 -10
  456. package/dist/hooks/user-prompt-submit.sh +37 -21
  457. package/dist/knowledge/adapters/go-adapter.d.ts +65 -0
  458. package/dist/knowledge/adapters/go-adapter.d.ts.map +1 -0
  459. package/dist/knowledge/adapters/go-adapter.js +294 -0
  460. package/dist/knowledge/adapters/go-adapter.js.map +1 -0
  461. package/dist/knowledge/adapters/index.d.ts +41 -0
  462. package/dist/knowledge/adapters/index.d.ts.map +1 -0
  463. package/dist/knowledge/adapters/index.js +71 -0
  464. package/dist/knowledge/adapters/index.js.map +1 -0
  465. package/dist/knowledge/adapters/java-adapter.d.ts +66 -0
  466. package/dist/knowledge/adapters/java-adapter.d.ts.map +1 -0
  467. package/dist/knowledge/adapters/java-adapter.js +260 -0
  468. package/dist/knowledge/adapters/java-adapter.js.map +1 -0
  469. package/dist/knowledge/adapters/js-vue-adapter.d.ts +56 -0
  470. package/dist/knowledge/adapters/js-vue-adapter.d.ts.map +1 -0
  471. package/dist/knowledge/adapters/js-vue-adapter.js +203 -0
  472. package/dist/knowledge/adapters/js-vue-adapter.js.map +1 -0
  473. package/dist/knowledge/adapters/kotlin-adapter.d.ts +55 -0
  474. package/dist/knowledge/adapters/kotlin-adapter.d.ts.map +1 -0
  475. package/dist/knowledge/adapters/kotlin-adapter.js +209 -0
  476. package/dist/knowledge/adapters/kotlin-adapter.js.map +1 -0
  477. package/dist/knowledge/adapters/monorepo-adapter.d.ts +77 -0
  478. package/dist/knowledge/adapters/monorepo-adapter.d.ts.map +1 -0
  479. package/dist/knowledge/adapters/monorepo-adapter.js +170 -0
  480. package/dist/knowledge/adapters/monorepo-adapter.js.map +1 -0
  481. package/dist/knowledge/adapters/python-adapter.d.ts +89 -0
  482. package/dist/knowledge/adapters/python-adapter.d.ts.map +1 -0
  483. package/dist/knowledge/adapters/python-adapter.js +358 -0
  484. package/dist/knowledge/adapters/python-adapter.js.map +1 -0
  485. package/dist/knowledge/adapters/rust-adapter.d.ts +73 -0
  486. package/dist/knowledge/adapters/rust-adapter.d.ts.map +1 -0
  487. package/dist/knowledge/adapters/rust-adapter.js +329 -0
  488. package/dist/knowledge/adapters/rust-adapter.js.map +1 -0
  489. package/dist/knowledge/adapters/types.d.ts +99 -0
  490. package/dist/knowledge/adapters/types.d.ts.map +1 -0
  491. package/dist/knowledge/adapters/types.js +17 -0
  492. package/dist/knowledge/adapters/types.js.map +1 -0
  493. package/dist/knowledge/adapters/typescript-adapter.d.ts +57 -0
  494. package/dist/knowledge/adapters/typescript-adapter.d.ts.map +1 -0
  495. package/dist/knowledge/adapters/typescript-adapter.js +171 -0
  496. package/dist/knowledge/adapters/typescript-adapter.js.map +1 -0
  497. package/dist/knowledge/audit-applier.d.ts +70 -0
  498. package/dist/knowledge/audit-applier.d.ts.map +1 -0
  499. package/dist/knowledge/audit-applier.js +251 -0
  500. package/dist/knowledge/audit-applier.js.map +1 -0
  501. package/dist/knowledge/builder.d.ts +261 -0
  502. package/dist/knowledge/builder.d.ts.map +1 -0
  503. package/dist/knowledge/builder.js +937 -0
  504. package/dist/knowledge/builder.js.map +1 -0
  505. package/dist/knowledge/cli-provider.d.ts +151 -0
  506. package/dist/knowledge/cli-provider.d.ts.map +1 -0
  507. package/dist/knowledge/cli-provider.js +313 -0
  508. package/dist/knowledge/cli-provider.js.map +1 -0
  509. package/dist/knowledge/constants.d.ts +73 -0
  510. package/dist/knowledge/constants.d.ts.map +1 -0
  511. package/dist/knowledge/constants.js +93 -0
  512. package/dist/knowledge/constants.js.map +1 -0
  513. package/dist/knowledge/cross-module.d.ts +139 -0
  514. package/dist/knowledge/cross-module.d.ts.map +1 -0
  515. package/dist/knowledge/cross-module.js +370 -0
  516. package/dist/knowledge/cross-module.js.map +1 -0
  517. package/dist/knowledge/git-hooks.d.ts +67 -0
  518. package/dist/knowledge/git-hooks.d.ts.map +1 -0
  519. package/dist/knowledge/git-hooks.js +258 -0
  520. package/dist/knowledge/git-hooks.js.map +1 -0
  521. package/dist/knowledge/module-hash.d.ts +88 -0
  522. package/dist/knowledge/module-hash.d.ts.map +1 -0
  523. package/dist/knowledge/module-hash.js +162 -0
  524. package/dist/knowledge/module-hash.js.map +1 -0
  525. package/dist/knowledge/project-detector.d.ts +101 -0
  526. package/dist/knowledge/project-detector.d.ts.map +1 -0
  527. package/dist/knowledge/project-detector.js +223 -0
  528. package/dist/knowledge/project-detector.js.map +1 -0
  529. package/dist/knowledge/prompt.d.ts +228 -0
  530. package/dist/knowledge/prompt.d.ts.map +1 -0
  531. package/dist/knowledge/prompt.js +404 -0
  532. package/dist/knowledge/prompt.js.map +1 -0
  533. package/dist/knowledge/query.d.ts +105 -0
  534. package/dist/knowledge/query.d.ts.map +1 -0
  535. package/dist/knowledge/query.js +341 -0
  536. package/dist/knowledge/query.js.map +1 -0
  537. package/dist/knowledge/repo-map.d.ts +91 -0
  538. package/dist/knowledge/repo-map.d.ts.map +1 -0
  539. package/dist/knowledge/repo-map.js +408 -0
  540. package/dist/knowledge/repo-map.js.map +1 -0
  541. package/dist/knowledge/tools/index.d.ts +14 -0
  542. package/dist/knowledge/tools/index.d.ts.map +1 -0
  543. package/dist/knowledge/tools/index.js +11 -0
  544. package/dist/knowledge/tools/index.js.map +1 -0
  545. package/dist/knowledge/tools/knowledge-get-page.d.ts +46 -0
  546. package/dist/knowledge/tools/knowledge-get-page.d.ts.map +1 -0
  547. package/dist/knowledge/tools/knowledge-get-page.js +101 -0
  548. package/dist/knowledge/tools/knowledge-get-page.js.map +1 -0
  549. package/dist/knowledge/tools/knowledge-query.d.ts +77 -0
  550. package/dist/knowledge/tools/knowledge-query.d.ts.map +1 -0
  551. package/dist/knowledge/tools/knowledge-query.js +104 -0
  552. package/dist/knowledge/tools/knowledge-query.js.map +1 -0
  553. package/dist/knowledge/tools/repo-map-lookup.d.ts +45 -0
  554. package/dist/knowledge/tools/repo-map-lookup.d.ts.map +1 -0
  555. package/dist/knowledge/tools/repo-map-lookup.js +82 -0
  556. package/dist/knowledge/tools/repo-map-lookup.js.map +1 -0
  557. package/dist/knowledge/types.d.ts +269 -0
  558. package/dist/knowledge/types.d.ts.map +1 -0
  559. package/dist/knowledge/types.js +10 -0
  560. package/dist/knowledge/types.js.map +1 -0
  561. package/dist/knowledge/validator.d.ts +90 -0
  562. package/dist/knowledge/validator.d.ts.map +1 -0
  563. package/dist/knowledge/validator.js +288 -0
  564. package/dist/knowledge/validator.js.map +1 -0
  565. package/dist/mcp/server.d.ts.map +1 -1
  566. package/dist/mcp/server.js +222 -1
  567. package/dist/mcp/server.js.map +1 -1
  568. package/dist/skills/builtin-skills.d.ts +35 -0
  569. package/dist/skills/builtin-skills.d.ts.map +1 -0
  570. package/dist/skills/builtin-skills.js +68 -0
  571. package/dist/skills/builtin-skills.js.map +1 -0
  572. package/dist/skills/distill/attribution.d.ts +59 -0
  573. package/dist/skills/distill/attribution.d.ts.map +1 -0
  574. package/dist/skills/distill/attribution.js +101 -0
  575. package/dist/skills/distill/attribution.js.map +1 -0
  576. package/dist/skills/distill/claude-cli-resolver.d.ts +26 -0
  577. package/dist/skills/distill/claude-cli-resolver.d.ts.map +1 -0
  578. package/dist/skills/distill/claude-cli-resolver.js +115 -0
  579. package/dist/skills/distill/claude-cli-resolver.js.map +1 -0
  580. package/dist/skills/distill/distiller.d.ts +161 -0
  581. package/dist/skills/distill/distiller.d.ts.map +1 -0
  582. package/dist/skills/distill/distiller.js +461 -0
  583. package/dist/skills/distill/distiller.js.map +1 -0
  584. package/dist/skills/distill/index.d.ts +223 -0
  585. package/dist/skills/distill/index.d.ts.map +1 -0
  586. package/dist/skills/distill/index.js +466 -0
  587. package/dist/skills/distill/index.js.map +1 -0
  588. package/dist/skills/distill/project-anchor-guard.d.ts +116 -0
  589. package/dist/skills/distill/project-anchor-guard.d.ts.map +1 -0
  590. package/dist/skills/distill/project-anchor-guard.js +334 -0
  591. package/dist/skills/distill/project-anchor-guard.js.map +1 -0
  592. package/dist/skills/distill/topic-deduper.d.ts +77 -0
  593. package/dist/skills/distill/topic-deduper.d.ts.map +1 -0
  594. package/dist/skills/distill/topic-deduper.js +119 -0
  595. package/dist/skills/distill/topic-deduper.js.map +1 -0
  596. package/dist/skills/distill/upstream-fetcher.d.ts +71 -0
  597. package/dist/skills/distill/upstream-fetcher.d.ts.map +1 -0
  598. package/dist/skills/distill/upstream-fetcher.js +202 -0
  599. package/dist/skills/distill/upstream-fetcher.js.map +1 -0
  600. package/dist/skills/distilled/distilled-api-design.md +491 -0
  601. package/dist/skills/distilled/distilled-architecture-decision.md +173 -0
  602. package/dist/skills/distilled/distilled-creator.md +178 -0
  603. package/dist/skills/distilled/distilled-db-schema-design.md +245 -0
  604. package/dist/skills/distilled/distilled-defi-amm-security.md +293 -0
  605. package/dist/skills/distilled/distilled-executing-plans.md +113 -0
  606. package/dist/skills/distilled/distilled-harness-engineering.md +242 -0
  607. package/dist/skills/distilled/distilled-karpathy-guidelines.md +104 -0
  608. package/dist/skills/distilled/distilled-performance-optimization.md +175 -0
  609. package/dist/skills/distilled/distilled-spec-driven-design.md +193 -0
  610. package/dist/skills/distilled/distilled-systematic-debugging.md +306 -0
  611. package/dist/skills/distilled/distilled-verification-before-completion.md +203 -0
  612. package/dist/skills/keyword-score.d.ts +29 -0
  613. package/dist/skills/keyword-score.d.ts.map +1 -0
  614. package/dist/skills/keyword-score.js +54 -0
  615. package/dist/skills/keyword-score.js.map +1 -0
  616. package/dist/skills/registry.d.ts +64 -20
  617. package/dist/skills/registry.d.ts.map +1 -1
  618. package/dist/skills/registry.js +102 -105
  619. package/dist/skills/registry.js.map +1 -1
  620. package/dist/skills/tools/pipeline-suggest.js +14 -14
  621. package/dist/skills/tools/skill-invoke.d.ts +1 -1
  622. package/dist/skills/tools/skill-invoke.js +1 -1
  623. package/dist/web/routes/agent-content.d.ts +30 -0
  624. package/dist/web/routes/agent-content.d.ts.map +1 -0
  625. package/dist/web/routes/agent-content.js +139 -0
  626. package/dist/web/routes/agent-content.js.map +1 -0
  627. package/dist/web/routes/decisions.d.ts +15 -0
  628. package/dist/web/routes/decisions.d.ts.map +1 -0
  629. package/dist/web/routes/decisions.js +181 -0
  630. package/dist/web/routes/decisions.js.map +1 -0
  631. package/dist/web/routes/diagnostics.d.ts +61 -0
  632. package/dist/web/routes/diagnostics.d.ts.map +1 -0
  633. package/dist/web/routes/diagnostics.js +203 -0
  634. package/dist/web/routes/diagnostics.js.map +1 -0
  635. package/dist/web/routes/events.d.ts.map +1 -1
  636. package/dist/web/routes/events.js +24 -0
  637. package/dist/web/routes/events.js.map +1 -1
  638. package/dist/web/routes/health.d.ts +33 -0
  639. package/dist/web/routes/health.d.ts.map +1 -0
  640. package/dist/web/routes/health.js +37 -0
  641. package/dist/web/routes/health.js.map +1 -0
  642. package/dist/web/routes/insights.d.ts +0 -5
  643. package/dist/web/routes/insights.d.ts.map +1 -1
  644. package/dist/web/routes/insights.js +783 -2
  645. package/dist/web/routes/insights.js.map +1 -1
  646. package/dist/web/routes/knowledge.d.ts +16 -0
  647. package/dist/web/routes/knowledge.d.ts.map +1 -0
  648. package/dist/web/routes/knowledge.js +661 -0
  649. package/dist/web/routes/knowledge.js.map +1 -0
  650. package/dist/web/routes/patch.d.ts +60 -1
  651. package/dist/web/routes/patch.d.ts.map +1 -1
  652. package/dist/web/routes/patch.js +170 -64
  653. package/dist/web/routes/patch.js.map +1 -1
  654. package/dist/web/routes/pipeline.d.ts +37 -0
  655. package/dist/web/routes/pipeline.d.ts.map +1 -0
  656. package/dist/web/routes/pipeline.js +149 -0
  657. package/dist/web/routes/pipeline.js.map +1 -0
  658. package/dist/web/routes/rules.d.ts.map +1 -1
  659. package/dist/web/routes/rules.js +6 -1
  660. package/dist/web/routes/rules.js.map +1 -1
  661. package/dist/web/routes/sessions.d.ts.map +1 -1
  662. package/dist/web/routes/sessions.js +9 -1
  663. package/dist/web/routes/sessions.js.map +1 -1
  664. package/dist/web/routes/skill-content.d.ts +30 -0
  665. package/dist/web/routes/skill-content.d.ts.map +1 -0
  666. package/dist/web/routes/skill-content.js +117 -0
  667. package/dist/web/routes/skill-content.js.map +1 -0
  668. package/dist/web/routes/skills-distill.d.ts +29 -0
  669. package/dist/web/routes/skills-distill.d.ts.map +1 -0
  670. package/dist/web/routes/skills-distill.js +552 -0
  671. package/dist/web/routes/skills-distill.js.map +1 -0
  672. package/dist/web/routes/skills.js +7 -7
  673. package/dist/web/routes/skills.js.map +1 -1
  674. package/dist/web/routes/task-timeline.d.ts +102 -0
  675. package/dist/web/routes/task-timeline.d.ts.map +1 -0
  676. package/dist/web/routes/task-timeline.js +274 -0
  677. package/dist/web/routes/task-timeline.js.map +1 -0
  678. package/dist/web/routes/tasks.d.ts.map +1 -1
  679. package/dist/web/routes/tasks.js +355 -8
  680. package/dist/web/routes/tasks.js.map +1 -1
  681. package/dist/web/routes/trace.d.ts.map +1 -1
  682. package/dist/web/routes/trace.js +3 -2
  683. package/dist/web/routes/trace.js.map +1 -1
  684. package/dist/web/routes/types.d.ts +0 -4
  685. package/dist/web/routes/types.d.ts.map +1 -1
  686. package/dist/web/routes/types.js +1 -1
  687. package/dist/web/routes/types.js.map +1 -1
  688. package/dist/web/routes/violations.d.ts +14 -0
  689. package/dist/web/routes/violations.d.ts.map +1 -0
  690. package/dist/web/routes/violations.js +111 -0
  691. package/dist/web/routes/violations.js.map +1 -0
  692. package/dist/web/server.d.ts.map +1 -1
  693. package/dist/web/server.js +79 -19
  694. package/dist/web/server.js.map +1 -1
  695. package/dist/web/services/build-manager.d.ts +72 -0
  696. package/dist/web/services/build-manager.d.ts.map +1 -0
  697. package/dist/web/services/build-manager.js +189 -0
  698. package/dist/web/services/build-manager.js.map +1 -0
  699. package/dist/web/services/distill-manager.d.ts +125 -0
  700. package/dist/web/services/distill-manager.d.ts.map +1 -0
  701. package/dist/web/services/distill-manager.js +308 -0
  702. package/dist/web/services/distill-manager.js.map +1 -0
  703. package/dist/web/static/assets/AgentContentPage-DkeRNxok.js +2 -0
  704. package/dist/web/static/assets/AgentContentPage-DkeRNxok.js.map +1 -0
  705. package/dist/web/static/assets/AgentDelegationTable-ByBa0x1l.js +2 -0
  706. package/dist/web/static/assets/AgentDelegationTable-ByBa0x1l.js.map +1 -0
  707. package/dist/web/static/assets/ContextInsightsPage-oUk7_I8u.js +3 -0
  708. package/dist/web/static/assets/ContextInsightsPage-oUk7_I8u.js.map +1 -0
  709. package/dist/web/static/assets/DaemonHealthPage-DG2fyOP7.js +2 -0
  710. package/dist/web/static/assets/DaemonHealthPage-DG2fyOP7.js.map +1 -0
  711. package/dist/web/static/assets/DecisionsPage-CMAPEnKb.js +2 -0
  712. package/dist/web/static/assets/DecisionsPage-CMAPEnKb.js.map +1 -0
  713. package/dist/web/static/assets/DiagnosticsPage-DQd-Zm4r.js +2 -0
  714. package/dist/web/static/assets/DiagnosticsPage-DQd-Zm4r.js.map +1 -0
  715. package/dist/web/static/assets/DriftTab-DqpepOhI.js +2 -0
  716. package/dist/web/static/assets/DriftTab-DqpepOhI.js.map +1 -0
  717. package/dist/web/static/assets/HealthHomePage-CN6zNIie.js +3 -0
  718. package/dist/web/static/assets/HealthHomePage-CN6zNIie.js.map +1 -0
  719. package/dist/web/static/assets/KbHitRateTable-ByEIWujF.js +2 -0
  720. package/dist/web/static/assets/KbHitRateTable-ByEIWujF.js.map +1 -0
  721. package/dist/web/static/assets/MarkdownRenderer-DZmTl-8J.js +3 -0
  722. package/dist/web/static/assets/MarkdownRenderer-DZmTl-8J.js.map +1 -0
  723. package/dist/web/static/assets/NotFound-BQPh0vaF.js +2 -0
  724. package/dist/web/static/assets/NotFound-BQPh0vaF.js.map +1 -0
  725. package/dist/web/static/assets/ProjectSwitcher-D3lZMFd3.js +2 -0
  726. package/dist/web/static/assets/ProjectSwitcher-D3lZMFd3.js.map +1 -0
  727. package/dist/web/static/assets/SettingsPage-oLJBNzQj.js +2 -0
  728. package/dist/web/static/assets/SettingsPage-oLJBNzQj.js.map +1 -0
  729. package/dist/web/static/assets/SkillContentPage-DK5rgfgw.js +2 -0
  730. package/dist/web/static/assets/SkillContentPage-DK5rgfgw.js.map +1 -0
  731. package/dist/web/static/assets/SkillStatsTable-DYMzjEUV.js +2 -0
  732. package/dist/web/static/assets/SkillStatsTable-DYMzjEUV.js.map +1 -0
  733. package/dist/web/static/assets/SkillsDistillTab-C7qaG8q3.js +2 -0
  734. package/dist/web/static/assets/SkillsDistillTab-C7qaG8q3.js.map +1 -0
  735. package/dist/web/static/assets/TasksHubPage-03wsRRsJ.js +6 -0
  736. package/dist/web/static/assets/TasksHubPage-03wsRRsJ.js.map +1 -0
  737. package/dist/web/static/assets/ViolationsPage-DSiLr-9O.js +3 -0
  738. package/dist/web/static/assets/ViolationsPage-DSiLr-9O.js.map +1 -0
  739. package/dist/web/static/assets/arco-Bhi3a6Qp.js +14 -0
  740. package/dist/web/static/assets/arco-Bhi3a6Qp.js.map +1 -0
  741. package/dist/web/static/assets/arco-DFQA6dO_.css +1 -0
  742. package/dist/web/static/assets/charts-BuHQWDbQ.js +37 -0
  743. package/dist/web/static/assets/charts-BuHQWDbQ.js.map +1 -0
  744. package/dist/web/static/assets/date-fns-sbWH3_uq.js +2 -0
  745. package/dist/web/static/assets/date-fns-sbWH3_uq.js.map +1 -0
  746. package/dist/web/static/assets/index-7bl3kbcx.css +1 -0
  747. package/dist/web/static/assets/index-BIYnq1Dx.js +4 -0
  748. package/dist/web/static/assets/index-BIYnq1Dx.js.map +1 -0
  749. package/dist/web/static/assets/lucide-CnlPQoG8.js +72 -0
  750. package/dist/web/static/assets/lucide-CnlPQoG8.js.map +1 -0
  751. package/dist/web/static/assets/outcome-DUn1NjlC.js +2 -0
  752. package/dist/web/static/assets/outcome-DUn1NjlC.js.map +1 -0
  753. package/dist/web/static/assets/query-S6X1S7K9.js +2 -0
  754. package/dist/web/static/assets/{query-C99w429o.js.map → query-S6X1S7K9.js.map} +1 -1
  755. package/dist/web/static/assets/{react-router-r79dBVy4.js → react-router-JVUrkhdd.js} +3 -3
  756. package/dist/web/static/assets/{react-router-r79dBVy4.js.map → react-router-JVUrkhdd.js.map} +1 -1
  757. package/dist/web/static/assets/react-vendor-tkvCrao7.js +57 -0
  758. package/dist/web/static/assets/react-vendor-tkvCrao7.js.map +1 -0
  759. package/dist/web/static/assets/syntax-highlighter-BkZfCDsz.js +6 -0
  760. package/dist/web/static/assets/syntax-highlighter-BkZfCDsz.js.map +1 -0
  761. package/dist/web/static/assets/useTabsParam-k8qte_0C.js +2 -0
  762. package/dist/web/static/assets/useTabsParam-k8qte_0C.js.map +1 -0
  763. package/dist/web/static/assets/vendor-DWgdB1eY.js +65 -0
  764. package/dist/web/static/assets/vendor-DWgdB1eY.js.map +1 -0
  765. package/dist/web/static/index.html +12 -8
  766. package/package.json +14 -3
  767. package/dist/core/ai/provider.d.ts +0 -63
  768. package/dist/core/ai/provider.d.ts.map +0 -1
  769. package/dist/core/ai/provider.js +0 -241
  770. package/dist/core/ai/provider.js.map +0 -1
  771. package/dist/core/ai/types.d.ts +0 -43
  772. package/dist/core/ai/types.d.ts.map +0 -1
  773. package/dist/core/ai/types.js +0 -5
  774. package/dist/core/ai/types.js.map +0 -1
  775. package/dist/core/storage/token-usage.d.ts +0 -36
  776. package/dist/core/storage/token-usage.d.ts.map +0 -1
  777. package/dist/core/storage/token-usage.js +0 -59
  778. package/dist/core/storage/token-usage.js.map +0 -1
  779. package/dist/core/utils/token-tracker.d.ts +0 -39
  780. package/dist/core/utils/token-tracker.d.ts.map +0 -1
  781. package/dist/core/utils/token-tracker.js +0 -69
  782. package/dist/core/utils/token-tracker.js.map +0 -1
  783. package/dist/skills/index.d.ts +0 -3
  784. package/dist/skills/index.d.ts.map +0 -1
  785. package/dist/skills/index.js +0 -3
  786. package/dist/skills/index.js.map +0 -1
  787. package/dist/skills/matcher.d.ts +0 -26
  788. package/dist/skills/matcher.d.ts.map +0 -1
  789. package/dist/skills/matcher.js +0 -113
  790. package/dist/skills/matcher.js.map +0 -1
  791. package/dist/skills/official/code-simplifier.md +0 -52
  792. package/dist/skills/official/find-skills.md +0 -142
  793. package/dist/skills/official/official-api-design.md +0 -30
  794. package/dist/skills/official/official-architecture-decision.md +0 -41
  795. package/dist/skills/official/official-bmad.md +0 -118
  796. package/dist/skills/official/official-db-schema-design.md +0 -34
  797. package/dist/skills/official/official-debug.md +0 -25
  798. package/dist/skills/official/official-doc-driven.md +0 -31
  799. package/dist/skills/official/official-harness-engineering.md +0 -108
  800. package/dist/skills/official/official-performance-optimization.md +0 -30
  801. package/dist/skills/official/official-pr-review.md +0 -35
  802. package/dist/skills/official/official-release-checklist.md +0 -30
  803. package/dist/skills/official/official-security-hardening.md +0 -32
  804. package/dist/skills/official/official-spec-driven-design.md +0 -31
  805. package/dist/skills/official/planning-with-files.md +0 -241
  806. package/dist/skills/official/ui-ux-pro-max.md +0 -105
  807. package/dist/skills/official/webapp-testing.md +0 -96
  808. package/dist/skills/official-skills.d.ts +0 -26
  809. package/dist/skills/official-skills.d.ts.map +0 -1
  810. package/dist/skills/official-skills.js +0 -73
  811. package/dist/skills/official-skills.js.map +0 -1
  812. package/dist/skills/semantic-matcher.d.ts +0 -60
  813. package/dist/skills/semantic-matcher.d.ts.map +0 -1
  814. package/dist/skills/semantic-matcher.js +0 -192
  815. package/dist/skills/semantic-matcher.js.map +0 -1
  816. package/dist/skills/upgrade-engine.d.ts +0 -93
  817. package/dist/skills/upgrade-engine.d.ts.map +0 -1
  818. package/dist/skills/upgrade-engine.js +0 -447
  819. package/dist/skills/upgrade-engine.js.map +0 -1
  820. package/dist/skills/upgrade-prompt.d.ts +0 -20
  821. package/dist/skills/upgrade-prompt.d.ts.map +0 -1
  822. package/dist/skills/upgrade-prompt.js +0 -75
  823. package/dist/skills/upgrade-prompt.js.map +0 -1
  824. package/dist/web/routes/ai.d.ts +0 -10
  825. package/dist/web/routes/ai.d.ts.map +0 -1
  826. package/dist/web/routes/ai.js +0 -186
  827. package/dist/web/routes/ai.js.map +0 -1
  828. package/dist/web/routes/token-usage.d.ts +0 -7
  829. package/dist/web/routes/token-usage.d.ts.map +0 -1
  830. package/dist/web/routes/token-usage.js +0 -18
  831. package/dist/web/routes/token-usage.js.map +0 -1
  832. package/dist/web/ssrf-guard.d.ts +0 -35
  833. package/dist/web/ssrf-guard.d.ts.map +0 -1
  834. package/dist/web/ssrf-guard.js +0 -93
  835. package/dist/web/ssrf-guard.js.map +0 -1
  836. package/dist/web/static/assets/AIConfig-CdDWzJyO.js +0 -2
  837. package/dist/web/static/assets/AIConfig-CdDWzJyO.js.map +0 -1
  838. package/dist/web/static/assets/Dashboard-CoEmmIDt.js +0 -2
  839. package/dist/web/static/assets/Dashboard-CoEmmIDt.js.map +0 -1
  840. package/dist/web/static/assets/Drawer-DdRTzlLB.js +0 -2
  841. package/dist/web/static/assets/Drawer-DdRTzlLB.js.map +0 -1
  842. package/dist/web/static/assets/Events-DrIq1SUS.js +0 -2
  843. package/dist/web/static/assets/Events-DrIq1SUS.js.map +0 -1
  844. package/dist/web/static/assets/Reports-DFBM3MDK.js +0 -2
  845. package/dist/web/static/assets/Reports-DFBM3MDK.js.map +0 -1
  846. package/dist/web/static/assets/SearchInput-qCj_jAcf.js +0 -2
  847. package/dist/web/static/assets/SearchInput-qCj_jAcf.js.map +0 -1
  848. package/dist/web/static/assets/SessionDetail-CCzwdoT7.js +0 -2
  849. package/dist/web/static/assets/SessionDetail-CCzwdoT7.js.map +0 -1
  850. package/dist/web/static/assets/Sessions-FfLYkAw9.js +0 -2
  851. package/dist/web/static/assets/Sessions-FfLYkAw9.js.map +0 -1
  852. package/dist/web/static/assets/Skills-C8Gvs3Qa.js +0 -2
  853. package/dist/web/static/assets/Skills-C8Gvs3Qa.js.map +0 -1
  854. package/dist/web/static/assets/TaskDetail-BS8pYhaR.js +0 -2
  855. package/dist/web/static/assets/TaskDetail-BS8pYhaR.js.map +0 -1
  856. package/dist/web/static/assets/Tasks-CyuhizG8.js +0 -2
  857. package/dist/web/static/assets/Tasks-CyuhizG8.js.map +0 -1
  858. package/dist/web/static/assets/charts-CLrM0_uM.js +0 -37
  859. package/dist/web/static/assets/charts-CLrM0_uM.js.map +0 -1
  860. package/dist/web/static/assets/date-fns-CZ_bHujz.js +0 -2
  861. package/dist/web/static/assets/date-fns-CZ_bHujz.js.map +0 -1
  862. package/dist/web/static/assets/export-L_VBD2p1.js +0 -4
  863. package/dist/web/static/assets/export-L_VBD2p1.js.map +0 -1
  864. package/dist/web/static/assets/index-CBX47X8l.js +0 -3
  865. package/dist/web/static/assets/index-CBX47X8l.js.map +0 -1
  866. package/dist/web/static/assets/index-DjIoMdoR.css +0 -1
  867. package/dist/web/static/assets/lucide-Bs_edTLa.js +0 -232
  868. package/dist/web/static/assets/lucide-Bs_edTLa.js.map +0 -1
  869. package/dist/web/static/assets/query-C99w429o.js +0 -2
  870. package/dist/web/static/assets/react-vendor-CSp-GLFF.js +0 -49
  871. package/dist/web/static/assets/react-vendor-CSp-GLFF.js.map +0 -1
  872. package/dist/web/static/assets/syntax-highlighter-44FakypI.js +0 -9
  873. package/dist/web/static/assets/syntax-highlighter-44FakypI.js.map +0 -1
  874. package/dist/web/static/assets/task-title-BhOcemuR.js +0 -2
  875. package/dist/web/static/assets/task-title-BhOcemuR.js.map +0 -1
  876. package/dist/web/static/assets/time-Bxuk0M-C.js +0 -2
  877. package/dist/web/static/assets/time-Bxuk0M-C.js.map +0 -1
  878. package/dist/web/static/assets/vendor-CMMjVdZs.js +0 -64
  879. package/dist/web/static/assets/vendor-CMMjVdZs.js.map +0 -1
@@ -1,9 +1,114 @@
1
1
  import { AntiPatternDetector, } from '../analytics/anti-pattern-detector.js';
2
+ import { getUserPrompt, getSubagentType } from '../../core/event-fields.js';
3
+ import { FeedbackAggregator } from '../../daemon/services/feedback-aggregator.js';
4
+ import { logger } from '../../core/utils/logger.js';
5
+ /** Phase 8 feature flag — must match config-store.ts DEFAULT_FLAGS. */
6
+ const FEEDBACK_LOOP_FLAG = 'feedback_loop.enabled';
7
+ /** Whitelisted `apply_action.type` values — anything outside this set is rejected. */
8
+ const APPLY_ACTION_WHITELIST = new Set([
9
+ // Rule actions
10
+ 'disable_rule',
11
+ 'tighten_threshold',
12
+ 'loosen_threshold',
13
+ // Skill actions
14
+ 'update_keywords',
15
+ 'disable_skill',
16
+ 'enable_skill',
17
+ // KB actions
18
+ 'regenerate_module',
19
+ 'archive_page',
20
+ 'lower_priority',
21
+ ]);
2
22
  /**
3
- * /api/insights 工作流反模式检测 API
23
+ * Build the forge_config key for a given action. All apply_action writes go
24
+ * through this helper so callers can't smuggle path traversal or arbitrary
25
+ * keys into the KV table.
26
+ */
27
+ function buildConfigKey(actionType, targetKind, targetName) {
28
+ // Reject non-alphanumeric chars in target name to keep the key clean. KB
29
+ // page names contain '/', so we allow '/', '-', '_', '.' too. Explicitly
30
+ // disallow '..' anywhere in the target (path traversal guard).
31
+ if (!targetName || !/^[A-Za-z0-9_./-]+$/.test(targetName))
32
+ return null;
33
+ if (targetName.includes('..'))
34
+ return null;
35
+ if (targetName.startsWith('/') || targetName.startsWith('-'))
36
+ return null;
37
+ // Rule actions go under rule.<rule_id>.<setting>
38
+ if (actionType === 'disable_rule') {
39
+ return `rule.${targetName}.enabled`;
40
+ }
41
+ if (actionType === 'tighten_threshold' || actionType === 'loosen_threshold') {
42
+ return `rule.${targetName}.threshold_mode`;
43
+ }
44
+ // Skill actions go under skill.<skill_id>.<setting>
45
+ if (actionType === 'disable_skill') {
46
+ return `skill.${targetName}.enabled`;
47
+ }
48
+ if (actionType === 'enable_skill') {
49
+ return `skill.${targetName}.enabled`;
50
+ }
51
+ if (actionType === 'update_keywords') {
52
+ return `skill.${targetName}.keywords_pending`;
53
+ }
54
+ // KB actions go under kb.<page_name>.<setting>
55
+ if (actionType === 'archive_page') {
56
+ return `kb.${targetName}.archived`;
57
+ }
58
+ if (actionType === 'lower_priority') {
59
+ return `kb.${targetName}.priority`;
60
+ }
61
+ if (actionType === 'regenerate_module') {
62
+ return `kb.${targetName}.regenerate_pending`;
63
+ }
64
+ void targetKind;
65
+ return null;
66
+ }
67
+ /**
68
+ * /api/insights — 工作流反模式检测 API + 单会话全链路时间线 + Phase 8 tuning
4
69
  *
5
- * 扫描事件流,识别可操作的反模式(编辑循环 / 工具失败 / 无 commit / 事件爆量)。
70
+ * - GET /api/insights : 扫事件流,识别反模式
71
+ * - GET /api/insights/timeline : 单 session 的 prompt → injection → tool intercept →
72
+ * tool event → skill → routing → outcome 时间线
73
+ * - GET /api/insights/agent-board : routa 风格 Kanban (lanes: prompted / recommended /
74
+ * spawned / done) 聚合 workflow_recommendations 行
75
+ * - GET /api/insights/tuning : Phase 8 feedback aggregator report (flag-gated)
76
+ * - POST /api/insights/tuning/apply: whitelisted tuning action → forge_config row
77
+ */
78
+ /**
79
+ * Parse the GROUP_CONCAT(metadata_json, '||') blob produced by
80
+ * queryAgentBoardSessions. Each chunk is a JSON array of `{name, score, refs}`
81
+ * objects (MVP1 KB injection shape). De-dup names, preserve insertion order,
82
+ * cap at 5 to keep cards compact. Result is `{name, cited}` so the UI can
83
+ * render "modules/daemon.md (cited 3)" style chips.
6
84
  */
85
+ function extractKbCitedPages(concat) {
86
+ if (!concat)
87
+ return [];
88
+ const counts = new Map();
89
+ for (const chunk of concat.split('||')) {
90
+ if (!chunk)
91
+ continue;
92
+ try {
93
+ const arr = JSON.parse(chunk);
94
+ if (!Array.isArray(arr))
95
+ continue;
96
+ for (const hit of arr) {
97
+ const name = typeof hit?.name === 'string' ? hit.name : null;
98
+ if (!name)
99
+ continue;
100
+ counts.set(name, (counts.get(name) ?? 0) + 1);
101
+ }
102
+ }
103
+ catch {
104
+ // ignore malformed chunks
105
+ }
106
+ }
107
+ return Array.from(counts.entries())
108
+ .sort((a, b) => b[1] - a[1])
109
+ .slice(0, 5)
110
+ .map(([name, cited]) => ({ name, cited }));
111
+ }
7
112
  export function registerInsightsRoutes(app, ctx) {
8
113
  const { storage } = ctx;
9
114
  app.get('/api/insights', (req, res) => {
@@ -30,5 +135,681 @@ export function registerInsightsRoutes(app, ctx) {
30
135
  patterns: patterns,
31
136
  });
32
137
  });
138
+ // ── perf P0.4 (2026-05-25): lightweight badge endpoint ────────────────
139
+ //
140
+ // Layout.tsx polls a notification badge every 60s; the existing
141
+ // /api/insights endpoint runs full AntiPatternDetector (~420ms / call) and
142
+ // returns a fat patterns[] payload. The Layout only reads
143
+ // `summary.critical + summary.warn > 0`, so we offer a tiny endpoint that:
144
+ // 1. Caches by (days) for 30s in process memory.
145
+ // 2. Returns only the counts the badge actually needs.
146
+ //
147
+ // The cache is intentionally module-local (single daemon, single worker) —
148
+ // no need for shared cache infra. 30s ≪ user perception of "new alert".
149
+ const badgeCache = new Map();
150
+ const BADGE_TTL_MS = 30_000;
151
+ app.get('/api/insights/badge', (req, res) => {
152
+ const raw = req.query.days;
153
+ const days = parseInt(typeof raw === 'string' ? raw : '7', 10);
154
+ if (Number.isNaN(days) || days < 1 || days > 90) {
155
+ res.status(400).json({ error: 'days must be between 1 and 90' });
156
+ return;
157
+ }
158
+ const now = Date.now();
159
+ const hit = badgeCache.get(days);
160
+ if (hit && now - hit.ts < BADGE_TTL_MS) {
161
+ res.json({ ...hit.data, cached: true });
162
+ return;
163
+ }
164
+ try {
165
+ const detector = new AntiPatternDetector(storage);
166
+ const patterns = detector.detectAll(days);
167
+ let critical = 0;
168
+ let warn = 0;
169
+ let info = 0;
170
+ for (const p of patterns) {
171
+ if (p.severity === 'critical')
172
+ critical += 1;
173
+ else if (p.severity === 'warn')
174
+ warn += 1;
175
+ else
176
+ info += 1;
177
+ }
178
+ // v6 Batch 1: 3 daemon-observer counters. Each is a single COUNT(*) so
179
+ // the badge endpoint stays cheap (and is still 30s-cached). If any one
180
+ // throws we surface 0 rather than fail the whole badge — the chip group
181
+ // is informational.
182
+ const sinceIso = new Date(now - days * 86400_000).toISOString();
183
+ let denied_7d = 0;
184
+ let hinted_7d = 0;
185
+ let trivial_passed_7d = 0;
186
+ try {
187
+ denied_7d = storage.queryInterceptDecisionCounts(sinceIso).denied;
188
+ }
189
+ catch (e) {
190
+ logger.warn(`[Insights] badge denied_7d failed: ${e}`);
191
+ }
192
+ try {
193
+ hinted_7d = storage.countDecisionsSince(sinceIso);
194
+ }
195
+ catch (e) {
196
+ logger.warn(`[Insights] badge hinted_7d failed: ${e}`);
197
+ }
198
+ try {
199
+ trivial_passed_7d = storage.countTrivialTasksSince(sinceIso);
200
+ }
201
+ catch (e) {
202
+ logger.warn(`[Insights] badge trivial_passed_7d failed: ${e}`);
203
+ }
204
+ const data = {
205
+ hasUnread: critical + warn > 0,
206
+ criticalCount: critical,
207
+ warnCount: warn,
208
+ infoCount: info,
209
+ total: patterns.length,
210
+ windowDays: days,
211
+ cached: false,
212
+ generatedAt: new Date(now).toISOString(),
213
+ denied_7d,
214
+ hinted_7d,
215
+ trivial_passed_7d,
216
+ };
217
+ badgeCache.set(days, { ts: now, data });
218
+ res.json(data);
219
+ }
220
+ catch (err) {
221
+ logger.warn(`[Insights] badge query failed: ${err}`);
222
+ res.status(500).json({ error: 'BADGE_FAILED', message: String(err) });
223
+ }
224
+ });
225
+ /**
226
+ * GET /api/insights/timeline?session_id=<id>[&limit=N]
227
+ *
228
+ * 一条 session 的全链路:prompt → injection → tool intercept → tool event →
229
+ * skill → routing → outcome。每条流默认取最近 500 行(per-stream cap),
230
+ * 真正分页留给 Phase 8。
231
+ *
232
+ * 不预聚合 — 前端组件自行 merge & sort by ts。
233
+ */
234
+ app.get('/api/insights/timeline', (req, res) => {
235
+ const sessionIdRaw = typeof req.query.session_id === 'string' ? req.query.session_id.trim() : '';
236
+ if (!sessionIdRaw) {
237
+ res.status(400).json({ error: 'session_id required' });
238
+ return;
239
+ }
240
+ // Phase 3: per-stream cap (default 500). Hard ceiling 2000 to keep response
241
+ // memory bounded; cursor-style pagination is Phase 8 work.
242
+ const requestedLimit = parseInt(typeof req.query.limit === 'string' ? req.query.limit : '500', 10);
243
+ const limit = Math.min(Math.max(Number.isFinite(requestedLimit) ? requestedLimit : 500, 1), 2000);
244
+ // Accept short prefixes (>=8 chars) the same way SessionDetail does.
245
+ const session = storage.getSessionWithMetrics(sessionIdRaw);
246
+ if (!session) {
247
+ res.status(404).json({ error: 'session not found' });
248
+ return;
249
+ }
250
+ const fullId = session.session_id;
251
+ // audit F5: switch to queryEventsTimeline (drops tool_output / ai_response
252
+ // from SELECT). PostToolUse rows on tool-heavy sessions can carry MB of
253
+ // tool_output that the timeline UI never reads — pulling them through
254
+ // JSON.parse + serialising back over the wire was the dominant cost.
255
+ const promptEvents = storage.queryEventsTimeline({
256
+ session_id: fullId,
257
+ hook_type: 'UserPromptSubmit',
258
+ limit,
259
+ });
260
+ const postToolEvents = storage.queryEventsTimeline({
261
+ session_id: fullId,
262
+ hook_type: 'PostToolUse',
263
+ limit,
264
+ });
265
+ const injections = storage.queryInjections({ session_id: fullId, limit });
266
+ const toolIntercepts = storage.queryToolIntercepts({ session_id: fullId, limit });
267
+ const skillInvocations = storage.querySkillInvocations({ session_id: fullId, limit });
268
+ const routingEvents = storage.queryRoutingEvents({ session_id: fullId, limit });
269
+ // ── Shape the response: each stream is its own array; let the UI merge ──
270
+ const prompts = promptEvents.map(e => ({
271
+ event_id: e.event_id ?? null,
272
+ timestamp: e.timestamp,
273
+ prompt: (getUserPrompt(e) ?? '').slice(0, 1000),
274
+ }));
275
+ const injectionRows = injections.map(inj => ({
276
+ id: inj.id ?? null,
277
+ event_id: inj.event_id ?? null,
278
+ timestamp: inj.timestamp,
279
+ source_handler: inj.source_handler,
280
+ injection_type: inj.injection_type,
281
+ content_preview: inj.content.slice(0, 400),
282
+ content_length: inj.content.length,
283
+ metadata_json: inj.metadata_json ?? null,
284
+ }));
285
+ const interceptRows = toolIntercepts.map(t => ({
286
+ id: t.id,
287
+ event_id: t.event_id,
288
+ timestamp: t.timestamp,
289
+ tool_name: t.tool_name,
290
+ tool_input_summary: t.tool_input_summary,
291
+ rule_id: t.rule_id,
292
+ decision: t.decision,
293
+ hint: t.hint,
294
+ outcome: t.outcome,
295
+ }));
296
+ // Tool events: surface PostToolUse with a small summary. Agent spawns are
297
+ // worth highlighting (subagent_type) so the UI can colour them differently.
298
+ const toolEventRows = postToolEvents
299
+ .filter(e => !!e.tool_name)
300
+ .map(e => {
301
+ const subagent = getSubagentType(e);
302
+ // Keep tool_input small for transport. Anything > 300 char gets a
303
+ // {truncated:true} marker so the UI knows the preview is partial.
304
+ let summary = null;
305
+ try {
306
+ const json = JSON.stringify(e.tool_input ?? {});
307
+ summary = json.length > 300 ? { truncated: true, preview: json.slice(0, 300) } : e.tool_input ?? null;
308
+ }
309
+ catch {
310
+ summary = null;
311
+ }
312
+ return {
313
+ event_id: e.event_id ?? null,
314
+ timestamp: e.timestamp,
315
+ tool_name: e.tool_name,
316
+ subagent_type: subagent ?? null,
317
+ tool_input_summary: summary,
318
+ };
319
+ });
320
+ const skillRows = skillInvocations.map(s => ({
321
+ id: s.id,
322
+ // skill_invocations.timestamp is unix ms — convert to ISO for the UI to
323
+ // sort alongside the string-based timestamps from other streams.
324
+ timestamp: new Date(s.timestamp).toISOString(),
325
+ skill_id: s.skill_id,
326
+ invocation_type: s.invocation_type,
327
+ workflow: s.workflow,
328
+ phase: s.phase,
329
+ success: s.success === 1,
330
+ reason: s.reason,
331
+ }));
332
+ const routingRows = routingEvents.map(r => ({
333
+ id: r.id,
334
+ timestamp: new Date(r.ts).toISOString(),
335
+ routed_to_type: r.routed_to_type ?? null,
336
+ routed_to_name: r.routed_to_name ?? null,
337
+ obeyed: r.obeyed,
338
+ refusal_reason: r.refusal_reason ?? null,
339
+ first_tool_name: r.first_tool_name ?? null,
340
+ }));
341
+ res.json({
342
+ session: {
343
+ session_id: session.session_id,
344
+ project_path: session.project_path,
345
+ first_prompt: session.first_prompt,
346
+ start_time: session.start_time,
347
+ end_time: session.end_time,
348
+ event_count: session.event_count,
349
+ outcome: session.outcome,
350
+ outcome_reason: session.outcome_reason,
351
+ intercept_count: session.intercept_count,
352
+ kb_inject_count: session.kb_inject_count,
353
+ skill_match_count: session.skill_match_count,
354
+ },
355
+ prompts,
356
+ injections: injectionRows,
357
+ tool_intercepts: interceptRows,
358
+ tool_events: toolEventRows,
359
+ skills: skillRows,
360
+ routing: routingRows,
361
+ meta: {
362
+ limit,
363
+ capped: {
364
+ prompts: prompts.length === limit,
365
+ injections: injectionRows.length === limit,
366
+ tool_intercepts: interceptRows.length === limit,
367
+ tool_events: toolEventRows.length === limit,
368
+ skills: skillRows.length === limit,
369
+ routing: routingRows.length === limit,
370
+ },
371
+ },
372
+ });
373
+ });
374
+ // ── Task-centric Kanban: GET /api/insights/agent-board (v3, 2026-05-22) ───
375
+ //
376
+ // v1 (workflow_recommendation lifecycle) — too abstract.
377
+ // v2 (session-centric) — sessions are execution traces, not work items;
378
+ // synthetic / test sessions cluttered the board.
379
+ // v3 (task-centric) — each card = one `tasks` row (TaskSegmenter auto-
380
+ // splits sessions on user prompts). This is the real
381
+ // "what was the user trying to do" unit of work.
382
+ //
383
+ // Lanes (priority by status + event_count):
384
+ // - status='completed' → 完成 (border colour by outcome)
385
+ // - status='abandoned' → 中断
386
+ // - status='active' AND event_count < 3 → 待处理 (just kicked off, no动作)
387
+ // - status='active' AND event_count >= 3 → 进行中
388
+ //
389
+ // Noise filter (server-side via SQL): drop title=='<task-notification>%',
390
+ // length<8, pure 应答 ('yes','ok','好',...), and single-word slash commands.
391
+ app.get('/api/insights/agent-board', (req, res) => {
392
+ const windowRaw = typeof req.query.window === 'string' ? parseInt(req.query.window, 10) : 7;
393
+ const windowDays = Number.isFinite(windowRaw) ? Math.min(Math.max(windowRaw, 1), 90) : 7;
394
+ const projectRaw = typeof req.query.project === 'string' ? req.query.project.trim() : '';
395
+ const projectPath = projectRaw && /^[A-Za-z0-9_./\\:-]+$/.test(projectRaw) ? projectRaw : '';
396
+ // Default lowered 120 → 40 (2026-05-25) — user feedback: "Task Lane 那么卡"。
397
+ // Each card runs 5 sub-queries server-side and ~7 chip renders client-side,
398
+ // so 120 cards × 7 chips × 4 lanes ~ 3.4k DOM nodes on first paint. 40
399
+ // covers ≥1 day of typical activity with a 7-day window; UI shows "已展示
400
+ // 前 30 / 共 N 张" so users still see the total. Hard cap stays 300.
401
+ const limitRaw = typeof req.query.limit === 'string' ? parseInt(req.query.limit, 10) : 40;
402
+ const limit = Number.isFinite(limitRaw) ? Math.min(Math.max(limitRaw, 1), 300) : 40;
403
+ // 2026-05-26: server-side pagination for the list view. The lanes payload
404
+ // is still capped at `limit` per request, but `offset` lets the frontend
405
+ // page through the unbounded set. Kanban view always passes offset=0 (or
406
+ // omits it) so its semantics stay unchanged. List view paginator drives
407
+ // offset = (page - 1) * pageSize.
408
+ const offsetRaw = typeof req.query.offset === 'string' ? parseInt(req.query.offset, 10) : 0;
409
+ const offset = Number.isFinite(offsetRaw) ? Math.max(offsetRaw, 0) : 0;
410
+ // Task-tracking overhaul (2026-05-27 spec §3.2 / §5.E): audit param to
411
+ // surface is_noise=1 rows. Q2 (user-approved): NO UI toggle ships in
412
+ // this overhaul — the param is for SQL audit / curl. Defaults false so
413
+ // the production dashboard stays clean.
414
+ const includeNoise = req.query.include_noise === '1' || req.query.include_noise === 'true';
415
+ // spec b1480935 (2026-06-01 Option A): ?include_kinds=user,agent-callback,...
416
+ // — granular per-kind opt-in for the TasksHubPage "含系统任务" chip. Falls
417
+ // back to includeNoise (legacy ?include_noise=1 maps to all 4 kinds) and
418
+ // finally defaults to user-only. Whitelist enforced so an attacker can't
419
+ // pass a SQL fragment.
420
+ const KIND_WHITELIST = [
421
+ 'user', 'agent-callback', 'image', 'system',
422
+ ];
423
+ const includeKindsRaw = typeof req.query.include_kinds === 'string'
424
+ ? req.query.include_kinds
425
+ : '';
426
+ let includeKinds;
427
+ if (includeKindsRaw) {
428
+ const parsed = includeKindsRaw.split(',')
429
+ .map(s => s.trim())
430
+ .filter((s) => KIND_WHITELIST.includes(s));
431
+ if (parsed.length > 0)
432
+ includeKinds = parsed;
433
+ }
434
+ // ── decision b509fd91 (2026-06-08): ?rows=prompt mode ────────────────
435
+ //
436
+ // P1 方案 B (zero schema): "一行 = 一条 user prompt + 按 task 分组". The
437
+ // default (no ?rows= or ?rows=task) keeps the legacy task-lane shape so
438
+ // kanban / other callers are unaffected (backward compatible). When
439
+ // ?rows=prompt, we return逐条 prompt 行 + a group-metadata map keyed by
440
+ // task_id. Reuses the SAME window / project / limit / offset / kind parsing
441
+ // above so query semantics stay aligned with the task-row path.
442
+ const rowsMode = req.query.rows === 'prompt' ? 'prompt' : 'task';
443
+ if (rowsMode === 'prompt') {
444
+ let promptRows;
445
+ let totalPromptRows = 0;
446
+ try {
447
+ promptRows = storage.queryAgentBoardPromptRows({
448
+ windowDays,
449
+ projectPath: projectPath || undefined,
450
+ limit,
451
+ offset,
452
+ includeNoise,
453
+ includeKinds,
454
+ });
455
+ totalPromptRows = storage.countAgentBoardPromptRows({
456
+ windowDays,
457
+ projectPath: projectPath || undefined,
458
+ includeNoise,
459
+ includeKinds,
460
+ });
461
+ }
462
+ catch (err) {
463
+ logger.warn(`[Insights] agent-board (rows=prompt) query failed: ${err}`);
464
+ res.status(500).json({ error: 'AGENT_BOARD_QUERY_FAILED', message: String(err) });
465
+ return;
466
+ }
467
+ function classifyGroupLane(status, eventCount) {
468
+ if (status === 'completed')
469
+ return 'completed';
470
+ if (status === 'abandoned')
471
+ return 'abandoned';
472
+ if (eventCount < 3)
473
+ return 'pending';
474
+ return 'active';
475
+ }
476
+ const outRows = [];
477
+ const groups = {};
478
+ for (const r of promptRows) {
479
+ outRows.push({
480
+ event_id: r.event_id,
481
+ prompt_text: r.prompt_text.slice(0, 300),
482
+ prompt_ts: r.prompt_ts,
483
+ session_id: r.session_id,
484
+ project_path: r.project_path,
485
+ group_id: r.group_id,
486
+ });
487
+ const existing = groups[r.group_id];
488
+ if (existing) {
489
+ existing.prompt_count += 1;
490
+ }
491
+ else {
492
+ groups[r.group_id] = {
493
+ title: (r.group_title ?? '').slice(0, 200),
494
+ status: r.group_status,
495
+ outcome: r.group_outcome,
496
+ lane: classifyGroupLane(r.group_status, r.group_event_count),
497
+ task_kind: r.group_task_kind,
498
+ start_time: r.group_start_time,
499
+ end_time: r.group_end_time,
500
+ duration_sec: r.group_duration_sec,
501
+ prompt_count: 1,
502
+ };
503
+ }
504
+ }
505
+ // KPI counts deduped by group (OQ3): a task with N prompts must not
506
+ // inflate "总任务数". by_outcome / by_lane count distinct groups.
507
+ const byOutcome = {};
508
+ const byLane = {
509
+ pending: 0, active: 0, abandoned: 0, completed: 0,
510
+ };
511
+ for (const g of Object.values(groups)) {
512
+ byLane[g.lane] += 1;
513
+ if (g.outcome)
514
+ byOutcome[g.outcome] = (byOutcome[g.outcome] ?? 0) + 1;
515
+ }
516
+ res.json({
517
+ generated_at: new Date().toISOString(),
518
+ window_days: windowDays,
519
+ project: projectPath || null,
520
+ mode: 'prompt',
521
+ // total_in_window = total PROMPT rows in window (paginator denominator).
522
+ total_in_window: totalPromptRows,
523
+ limit,
524
+ offset,
525
+ rows: outRows,
526
+ groups,
527
+ summary: {
528
+ // group-deduped counts so KPIs keep "总任务数" semantics stable.
529
+ total_groups: Object.keys(groups).length,
530
+ total_rows: outRows.length,
531
+ by_lane: byLane,
532
+ by_outcome: byOutcome,
533
+ },
534
+ });
535
+ return;
536
+ }
537
+ let rows;
538
+ let totalInWindow = 0;
539
+ try {
540
+ rows = storage.queryAgentBoardTasks({
541
+ windowDays,
542
+ projectPath: projectPath || undefined,
543
+ limit,
544
+ offset,
545
+ includeNoise,
546
+ includeKinds,
547
+ });
548
+ // Unbounded count for the "总任务数 (7d)" KPI. Same WHERE filter as the
549
+ // lane query so the number is consistent with "what could appear in
550
+ // the board if you removed the perf cap". Added 2026-05-26 — fixes
551
+ // KPI stuck at 40 (=limit) regardless of true task volume.
552
+ // 2026-05-27: includeNoise param propagated so audit callers
553
+ // (?include_noise=1) see a count matching the lane rows.
554
+ // 2026-06-01 (spec b1480935): includeKinds added.
555
+ totalInWindow = storage.countAgentBoardTasks({
556
+ windowDays,
557
+ projectPath: projectPath || undefined,
558
+ includeNoise,
559
+ includeKinds,
560
+ });
561
+ }
562
+ catch (err) {
563
+ logger.warn(`[Insights] agent-board (v3) query failed: ${err}`);
564
+ res.status(500).json({ error: 'AGENT_BOARD_QUERY_FAILED', message: String(err) });
565
+ return;
566
+ }
567
+ function parseJsonArray(s) {
568
+ if (!s)
569
+ return [];
570
+ try {
571
+ const v = JSON.parse(s);
572
+ return Array.isArray(v) ? v : [];
573
+ }
574
+ catch {
575
+ return [];
576
+ }
577
+ }
578
+ function classifyLane(status, eventCount) {
579
+ if (status === 'completed')
580
+ return 'completed';
581
+ if (status === 'abandoned')
582
+ return 'abandoned';
583
+ if (eventCount < 3)
584
+ return 'pending';
585
+ return 'active';
586
+ }
587
+ const cards = rows.map(r => ({
588
+ task_id: r.id,
589
+ session_id: r.session_id,
590
+ project_path: r.project_path ?? null,
591
+ title: (r.title ?? '').slice(0, 200),
592
+ start_time: r.start_time,
593
+ end_time: r.end_time,
594
+ status: r.status,
595
+ duration_sec: r.duration_sec ?? null,
596
+ event_count: r.event_count ?? 0,
597
+ outcome: r.outcome,
598
+ outcome_reason: r.outcome_reason,
599
+ top_tools: parseJsonArray(r.top_tools_json),
600
+ spawned_agents: parseJsonArray(r.spawned_json),
601
+ kb_pages: extractKbCitedPages(r.kb_meta_concat),
602
+ files_changed: r.files_changed ?? 0,
603
+ last_file: r.last_file ?? null,
604
+ intercepts: {
605
+ deny: r.deny_count ?? 0,
606
+ warn: r.warn_count ?? 0,
607
+ },
608
+ commit_count: r.commit_count ?? 0,
609
+ reverted_commits: r.reverted_commits ?? 0,
610
+ user_violation_count: r.user_violation_count ?? 0,
611
+ task_kind: r.task_kind ?? 'user',
612
+ }));
613
+ const lanes = {
614
+ pending: [],
615
+ active: [],
616
+ abandoned: [],
617
+ completed: [],
618
+ };
619
+ const byOutcome = {};
620
+ for (const c of cards) {
621
+ const lane = classifyLane(c.status, c.event_count);
622
+ lanes[lane].push(c);
623
+ if (c.outcome)
624
+ byOutcome[c.outcome] = (byOutcome[c.outcome] ?? 0) + 1;
625
+ }
626
+ res.json({
627
+ generated_at: new Date().toISOString(),
628
+ window_days: windowDays,
629
+ project: projectPath || null,
630
+ // Unbounded count for KPI "总任务数 (7d)". summary.total only reflects
631
+ // returned cards (capped at limit). Frontend should prefer this field.
632
+ total_in_window: totalInWindow,
633
+ // Echo pagination params so the client can compute total pages without
634
+ // re-parsing its own URL state. limit/offset added 2026-05-26.
635
+ limit,
636
+ offset,
637
+ lanes,
638
+ summary: {
639
+ total: cards.length,
640
+ by_lane: {
641
+ pending: lanes.pending.length,
642
+ active: lanes.active.length,
643
+ abandoned: lanes.abandoned.length,
644
+ completed: lanes.completed.length,
645
+ },
646
+ by_outcome: byOutcome,
647
+ },
648
+ });
649
+ });
650
+ // ── /api/insights/commit-activity — daily commit + task activity (2026-05-26)
651
+ //
652
+ // Returns unbounded daily buckets straight off `tasks` table (DATE(start_time)
653
+ // GROUP BY). Drives HealthHomePage 30d Commit calendar without the lane LIMIT
654
+ // undercount that the agent-board path suffered for high-volume days.
655
+ //
656
+ // Response shape:
657
+ // { generated_at, days, project,
658
+ // daily: [{ date: 'YYYY-MM-DD', total, succeeded, failed, commits }, ...],
659
+ // total_tasks, total_commits }
660
+ //
661
+ // Implemented for the 30d calendar but the `?days=N` knob accepts [1,365] for
662
+ // future use. No `limit` — the data is small (<= 365 rows of 5 ints each).
663
+ app.get('/api/insights/commit-activity', (req, res) => {
664
+ const daysRaw = typeof req.query.days === 'string' ? parseInt(req.query.days, 10) : 30;
665
+ const days = Number.isFinite(daysRaw) ? Math.min(Math.max(daysRaw, 1), 365) : 30;
666
+ const projectRaw = typeof req.query.project === 'string' ? req.query.project.trim() : '';
667
+ const projectPath = projectRaw && /^[A-Za-z0-9_./\\:-]+$/.test(projectRaw) ? projectRaw : '';
668
+ let daily;
669
+ try {
670
+ daily = storage.queryCommitActivityDaily({
671
+ days,
672
+ projectPath: projectPath || undefined,
673
+ });
674
+ }
675
+ catch (err) {
676
+ logger.warn(`[Insights] commit-activity query failed: ${err}`);
677
+ res.status(500).json({ error: 'COMMIT_ACTIVITY_QUERY_FAILED', message: String(err) });
678
+ return;
679
+ }
680
+ const totalTasks = daily.reduce((s, d) => s + d.total, 0);
681
+ const totalCommits = daily.reduce((s, d) => s + d.commits, 0);
682
+ res.json({
683
+ generated_at: new Date().toISOString(),
684
+ days,
685
+ project: projectPath || null,
686
+ daily,
687
+ total_tasks: totalTasks,
688
+ total_commits: totalCommits,
689
+ });
690
+ });
691
+ // ── Phase 8: GET /api/insights/tuning ─────────────────────────────────
692
+ //
693
+ // Returns {generated_at, window_days, suggestions[], summary{...}}. Flag
694
+ // `feedback_loop.enabled` gates access — 410 Gone when off so the front-end
695
+ // can show the "enable me" hint without erroring out the SPA fetch.
696
+ app.get('/api/insights/tuning', (req, res) => {
697
+ const enabled = storage.readConfig(FEEDBACK_LOOP_FLAG) === 'true';
698
+ if (!enabled) {
699
+ // F17: include `reason` + `enable_cmd` so the SPA can render a copy-able
700
+ // hint instead of a bare error code. `error` kept as FEATURE_DISABLED for
701
+ // backward-compat with InsightsTuning.tsx's discriminator.
702
+ res.status(410).json({
703
+ error: 'FEATURE_DISABLED',
704
+ reason: 'flag_off',
705
+ flag: FEEDBACK_LOOP_FLAG,
706
+ enable_cmd: `cf config set ${FEEDBACK_LOOP_FLAG} true && cf daemon restart`,
707
+ message: 'Enable with `cf config set feedback_loop.enabled true` and restart the daemon.',
708
+ });
709
+ return;
710
+ }
711
+ const windowRaw = typeof req.query.window === 'string' ? parseInt(req.query.window, 10) : 7;
712
+ const windowDays = windowRaw === 30 ? 30 : 7;
713
+ try {
714
+ const aggregator = new FeedbackAggregator(storage);
715
+ const report = aggregator.generateReport({ windowDays });
716
+ res.json(report);
717
+ }
718
+ catch (err) {
719
+ logger.warn(`[Insights] tuning report failed: ${err}`);
720
+ res.status(500).json({ error: 'TUNING_REPORT_FAILED', message: String(err) });
721
+ }
722
+ });
723
+ // ── Phase 8: POST /api/insights/tuning/apply ─────────────────────────
724
+ //
725
+ // Whitelisted action types only. Each action becomes a single forge_config
726
+ // row write — NEVER a CLAUDE.md / skill .md / KB .md mutation. The CLI /
727
+ // future hook layer reads these keys back to actually act on them.
728
+ //
729
+ // Body shape:
730
+ // {
731
+ // kind: 'rule_tuning' | 'skill_tuning' | 'kb_tuning',
732
+ // target: '<rule_id|skill_id|page_name>',
733
+ // action_type: '<one of APPLY_ACTION_WHITELIST>',
734
+ // payload?: {...} // currently ignored by writer
735
+ // }
736
+ app.post('/api/insights/tuning/apply', (req, res) => {
737
+ const enabled = storage.readConfig(FEEDBACK_LOOP_FLAG) === 'true';
738
+ if (!enabled) {
739
+ // F17: mirror the structure used by GET /tuning so the mutation onError
740
+ // handler can surface a copy-able enable command.
741
+ res.status(410).json({
742
+ error: 'FEATURE_DISABLED',
743
+ reason: 'flag_off',
744
+ flag: FEEDBACK_LOOP_FLAG,
745
+ enable_cmd: `cf config set ${FEEDBACK_LOOP_FLAG} true && cf daemon restart`,
746
+ message: 'Tuning apply requires the feedback loop flag to be ON.',
747
+ });
748
+ return;
749
+ }
750
+ const body = (req.body ?? {});
751
+ const kind = typeof body.kind === 'string' ? body.kind : '';
752
+ const target = typeof body.target === 'string' ? body.target.trim() : '';
753
+ const actionType = typeof body.action_type === 'string' ? body.action_type : '';
754
+ if (!kind || !target || !actionType) {
755
+ res.status(400).json({ error: 'kind, target and action_type are required' });
756
+ return;
757
+ }
758
+ if (!APPLY_ACTION_WHITELIST.has(actionType)) {
759
+ res.status(400).json({
760
+ error: 'INVALID_ACTION',
761
+ message: `action_type '${actionType}' is not whitelisted`,
762
+ allowed: Array.from(APPLY_ACTION_WHITELIST),
763
+ });
764
+ return;
765
+ }
766
+ const key = buildConfigKey(actionType, kind, target);
767
+ if (!key) {
768
+ res.status(400).json({
769
+ error: 'INVALID_TARGET',
770
+ message: 'target name failed validation (must match [A-Za-z0-9_./-]+)',
771
+ });
772
+ return;
773
+ }
774
+ // Choose the value to persist based on action semantics. We keep this
775
+ // hard-coded (no body-driven values) so a malicious caller can't write
776
+ // anything but the canonical disable/enable/queue markers.
777
+ let value;
778
+ if (actionType === 'disable_rule' || actionType === 'disable_skill' || actionType === 'archive_page') {
779
+ value = 'false';
780
+ }
781
+ else if (actionType === 'enable_skill') {
782
+ value = 'true';
783
+ }
784
+ else if (actionType === 'tighten_threshold') {
785
+ value = 'tight';
786
+ }
787
+ else if (actionType === 'loosen_threshold') {
788
+ value = 'loose';
789
+ }
790
+ else if (actionType === 'lower_priority') {
791
+ value = 'low';
792
+ }
793
+ else if (actionType === 'regenerate_module' || actionType === 'update_keywords') {
794
+ // These are deferred: writing the marker key here just queues the work
795
+ // for a later `cf knowledge build --module=<name>` invocation.
796
+ value = new Date().toISOString();
797
+ }
798
+ else {
799
+ // Unreachable thanks to the whitelist check above, but TypeScript wants
800
+ // a definite assignment.
801
+ res.status(500).json({ error: 'UNHANDLED_ACTION' });
802
+ return;
803
+ }
804
+ try {
805
+ storage.writeConfig(key, value);
806
+ logger.info(`[Insights] Applied tuning: ${actionType} on ${target} → ${key}=${value}`);
807
+ res.json({ ok: true, applied: { key, value, action_type: actionType, target, kind } });
808
+ }
809
+ catch (err) {
810
+ logger.warn(`[Insights] tuning apply failed: ${err}`);
811
+ res.status(500).json({ error: 'APPLY_FAILED', message: String(err) });
812
+ }
813
+ });
33
814
  }
34
815
  //# sourceMappingURL=insights.js.map