@winspan/claude-forge 9.2.0 → 9.12.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 (591) hide show
  1. package/DEVELOPMENT.md +80 -19
  2. package/README.md +13 -6
  3. package/dist/catalogs/agents.json +19 -24
  4. package/dist/catalogs/skills.json +139 -27
  5. package/dist/claudemd/templates/swarm-protocol.md +1 -1
  6. package/dist/cli/commands/agent.d.ts +169 -0
  7. package/dist/cli/commands/agent.d.ts.map +1 -0
  8. package/dist/cli/commands/agent.js +690 -0
  9. package/dist/cli/commands/agent.js.map +1 -0
  10. package/dist/cli/commands/codegraph.d.ts +17 -0
  11. package/dist/cli/commands/codegraph.d.ts.map +1 -0
  12. package/dist/cli/commands/codegraph.js +263 -0
  13. package/dist/cli/commands/codegraph.js.map +1 -0
  14. package/dist/cli/commands/decisions.d.ts.map +1 -1
  15. package/dist/cli/commands/decisions.js +46 -9
  16. package/dist/cli/commands/decisions.js.map +1 -1
  17. package/dist/cli/commands/executions.d.ts.map +1 -1
  18. package/dist/cli/commands/executions.js +2 -1
  19. package/dist/cli/commands/executions.js.map +1 -1
  20. package/dist/cli/commands/insights-goal-check.d.ts +5 -1
  21. package/dist/cli/commands/insights-goal-check.d.ts.map +1 -1
  22. package/dist/cli/commands/insights-goal-check.js +15 -15
  23. package/dist/cli/commands/insights-goal-check.js.map +1 -1
  24. package/dist/cli/commands/knowledge.d.ts +51 -0
  25. package/dist/cli/commands/knowledge.d.ts.map +1 -1
  26. package/dist/cli/commands/knowledge.js +202 -29
  27. package/dist/cli/commands/knowledge.js.map +1 -1
  28. package/dist/cli/commands/loop.d.ts +95 -0
  29. package/dist/cli/commands/loop.d.ts.map +1 -0
  30. package/dist/cli/commands/loop.js +408 -0
  31. package/dist/cli/commands/loop.js.map +1 -0
  32. package/dist/cli/commands/maintenance.d.ts +33 -0
  33. package/dist/cli/commands/maintenance.d.ts.map +1 -0
  34. package/dist/cli/commands/maintenance.js +75 -0
  35. package/dist/cli/commands/maintenance.js.map +1 -0
  36. package/dist/cli/commands/mcp.d.ts +23 -0
  37. package/dist/cli/commands/mcp.d.ts.map +1 -1
  38. package/dist/cli/commands/mcp.js +82 -0
  39. package/dist/cli/commands/mcp.js.map +1 -1
  40. package/dist/cli/commands/skills.d.ts +131 -0
  41. package/dist/cli/commands/skills.d.ts.map +1 -1
  42. package/dist/cli/commands/skills.js +409 -9
  43. package/dist/cli/commands/skills.js.map +1 -1
  44. package/dist/cli/commands/stats.d.ts.map +1 -1
  45. package/dist/cli/commands/stats.js +9 -2
  46. package/dist/cli/commands/stats.js.map +1 -1
  47. package/dist/cli/index.js +8 -0
  48. package/dist/cli/index.js.map +1 -1
  49. package/dist/core/constants.d.ts +37 -0
  50. package/dist/core/constants.d.ts.map +1 -1
  51. package/dist/core/constants.js +43 -0
  52. package/dist/core/constants.js.map +1 -1
  53. package/dist/core/diagnostics/checks.d.ts.map +1 -1
  54. package/dist/core/diagnostics/checks.js +2 -1
  55. package/dist/core/diagnostics/checks.js.map +1 -1
  56. package/dist/core/diagnostics/daemon-status.d.ts +1 -1
  57. package/dist/core/diagnostics/daemon-status.d.ts.map +1 -1
  58. package/dist/core/diagnostics/daemon-status.js +1 -1
  59. package/dist/core/diagnostics/daemon-status.js.map +1 -1
  60. package/dist/core/diagnostics/entropy-checks.d.ts +3 -2
  61. package/dist/core/diagnostics/entropy-checks.d.ts.map +1 -1
  62. package/dist/core/diagnostics/entropy-checks.js +10 -5
  63. package/dist/core/diagnostics/entropy-checks.js.map +1 -1
  64. package/dist/core/diagnostics/heartbeat-reader.d.ts +28 -0
  65. package/dist/core/diagnostics/heartbeat-reader.d.ts.map +1 -0
  66. package/dist/core/diagnostics/heartbeat-reader.js +50 -0
  67. package/dist/core/diagnostics/heartbeat-reader.js.map +1 -0
  68. package/dist/core/event-fields.d.ts +27 -0
  69. package/dist/core/event-fields.d.ts.map +1 -1
  70. package/dist/core/event-fields.js +43 -0
  71. package/dist/core/event-fields.js.map +1 -1
  72. package/dist/core/governance/global-inject.d.ts +34 -4
  73. package/dist/core/governance/global-inject.d.ts.map +1 -1
  74. package/dist/core/governance/global-inject.js +80 -25
  75. package/dist/core/governance/global-inject.js.map +1 -1
  76. package/dist/core/insights/agent-anchor-guard.d.ts +77 -0
  77. package/dist/core/insights/agent-anchor-guard.d.ts.map +1 -0
  78. package/dist/core/insights/agent-anchor-guard.js +119 -0
  79. package/dist/core/insights/agent-anchor-guard.js.map +1 -0
  80. package/dist/core/insights/agent-distill-context.d.ts +55 -0
  81. package/dist/core/insights/agent-distill-context.d.ts.map +1 -0
  82. package/dist/core/insights/agent-distill-context.js +146 -0
  83. package/dist/core/insights/agent-distill-context.js.map +1 -0
  84. package/dist/core/insights/agent-distill-spawn.d.ts +56 -0
  85. package/dist/core/insights/agent-distill-spawn.d.ts.map +1 -0
  86. package/dist/core/insights/agent-distill-spawn.js +179 -0
  87. package/dist/core/insights/agent-distill-spawn.js.map +1 -0
  88. package/dist/core/insights/agent-drift.d.ts +66 -0
  89. package/dist/core/insights/agent-drift.d.ts.map +1 -0
  90. package/dist/core/insights/agent-drift.js +109 -0
  91. package/dist/core/insights/agent-drift.js.map +1 -0
  92. package/dist/core/insights/agent-evolution-sources.d.ts +21 -0
  93. package/dist/core/insights/agent-evolution-sources.d.ts.map +1 -0
  94. package/dist/core/insights/agent-evolution-sources.js +36 -0
  95. package/dist/core/insights/agent-evolution-sources.js.map +1 -0
  96. package/dist/core/insights/agent-health.d.ts +142 -0
  97. package/dist/core/insights/agent-health.d.ts.map +1 -0
  98. package/dist/core/insights/agent-health.js +296 -0
  99. package/dist/core/insights/agent-health.js.map +1 -0
  100. package/dist/core/insights/agent-patch-apply.d.ts +45 -0
  101. package/dist/core/insights/agent-patch-apply.d.ts.map +1 -0
  102. package/dist/core/insights/agent-patch-apply.js +165 -0
  103. package/dist/core/insights/agent-patch-apply.js.map +1 -0
  104. package/dist/core/insights/agent-suggest.d.ts +128 -0
  105. package/dist/core/insights/agent-suggest.d.ts.map +1 -0
  106. package/dist/core/insights/agent-suggest.js +284 -0
  107. package/dist/core/insights/agent-suggest.js.map +1 -0
  108. package/dist/core/insights/coverage-tiers.d.ts +46 -0
  109. package/dist/core/insights/coverage-tiers.d.ts.map +1 -0
  110. package/dist/core/insights/coverage-tiers.js +95 -0
  111. package/dist/core/insights/coverage-tiers.js.map +1 -0
  112. package/dist/{daemon/services → core/insights}/experience-extractor.d.ts +0 -7
  113. package/dist/core/insights/experience-extractor.d.ts.map +1 -0
  114. package/dist/{daemon/services → core/insights}/experience-extractor.js +5 -9
  115. package/dist/core/insights/experience-extractor.js.map +1 -0
  116. package/dist/{daemon/services → core/insights}/violation-reporter.d.ts +20 -1
  117. package/dist/core/insights/violation-reporter.d.ts.map +1 -0
  118. package/dist/{daemon/services → core/insights}/violation-reporter.js +56 -4
  119. package/dist/core/insights/violation-reporter.js.map +1 -0
  120. package/dist/core/loop/loop-engine.d.ts +140 -0
  121. package/dist/core/loop/loop-engine.d.ts.map +1 -0
  122. package/dist/core/loop/loop-engine.js +266 -0
  123. package/dist/core/loop/loop-engine.js.map +1 -0
  124. package/dist/core/queue/index.d.ts.map +1 -1
  125. package/dist/core/queue/index.js +2 -1
  126. package/dist/core/queue/index.js.map +1 -1
  127. package/dist/core/storage/base.d.ts +159 -0
  128. package/dist/core/storage/base.d.ts.map +1 -1
  129. package/dist/core/storage/base.js +523 -0
  130. package/dist/core/storage/base.js.map +1 -1
  131. package/dist/core/storage/codegraph-types.d.ts +79 -0
  132. package/dist/core/storage/codegraph-types.d.ts.map +1 -0
  133. package/dist/core/storage/codegraph-types.js +14 -0
  134. package/dist/core/storage/codegraph-types.js.map +1 -0
  135. package/dist/core/storage/codegraph.d.ts +186 -0
  136. package/dist/core/storage/codegraph.d.ts.map +1 -0
  137. package/dist/core/storage/codegraph.js +452 -0
  138. package/dist/core/storage/codegraph.js.map +1 -0
  139. package/dist/core/storage/decisions.d.ts +30 -5
  140. package/dist/core/storage/decisions.d.ts.map +1 -1
  141. package/dist/core/storage/decisions.js +45 -13
  142. package/dist/core/storage/decisions.js.map +1 -1
  143. package/dist/core/storage/events.d.ts +127 -0
  144. package/dist/core/storage/events.d.ts.map +1 -1
  145. package/dist/core/storage/events.js +318 -3
  146. package/dist/core/storage/events.js.map +1 -1
  147. package/dist/core/storage/feedback.d.ts +3 -23
  148. package/dist/core/storage/feedback.d.ts.map +1 -1
  149. package/dist/core/storage/feedback.js +37 -38
  150. package/dist/core/storage/feedback.js.map +1 -1
  151. package/dist/core/storage/injections.d.ts +40 -0
  152. package/dist/core/storage/injections.d.ts.map +1 -1
  153. package/dist/core/storage/injections.js +69 -0
  154. package/dist/core/storage/injections.js.map +1 -1
  155. package/dist/core/storage/knowledge.d.ts +226 -0
  156. package/dist/core/storage/knowledge.d.ts.map +1 -1
  157. package/dist/core/storage/knowledge.js +391 -4
  158. package/dist/core/storage/knowledge.js.map +1 -1
  159. package/dist/core/storage/pipeline-rollup.d.ts +1 -7
  160. package/dist/core/storage/pipeline-rollup.d.ts.map +1 -1
  161. package/dist/core/storage/pipeline-rollup.js +18 -57
  162. package/dist/core/storage/pipeline-rollup.js.map +1 -1
  163. package/dist/core/storage/routing.d.ts +34 -0
  164. package/dist/core/storage/routing.d.ts.map +1 -1
  165. package/dist/core/storage/routing.js +92 -2
  166. package/dist/core/storage/routing.js.map +1 -1
  167. package/dist/core/storage/rows.d.ts +5 -25
  168. package/dist/core/storage/rows.d.ts.map +1 -1
  169. package/dist/core/storage/schema.sql +92 -27
  170. package/dist/core/storage/sessions.d.ts.map +1 -1
  171. package/dist/core/storage/sessions.js +2 -1
  172. package/dist/core/storage/sessions.js.map +1 -1
  173. package/dist/core/storage/skills.d.ts +159 -0
  174. package/dist/core/storage/skills.d.ts.map +1 -1
  175. package/dist/core/storage/skills.js +350 -4
  176. package/dist/core/storage/skills.js.map +1 -1
  177. package/dist/core/storage/sqlite.d.ts +81 -25
  178. package/dist/core/storage/sqlite.d.ts.map +1 -1
  179. package/dist/core/storage/sqlite.js +143 -45
  180. package/dist/core/storage/sqlite.js.map +1 -1
  181. package/dist/core/storage/tasks.d.ts +270 -0
  182. package/dist/core/storage/tasks.d.ts.map +1 -1
  183. package/dist/core/storage/tasks.js +495 -16
  184. package/dist/core/storage/tasks.js.map +1 -1
  185. package/dist/core/storage/tool-intercepts.d.ts +1 -1
  186. package/dist/core/storage/tool-intercepts.js +1 -1
  187. package/dist/core/types.d.ts +26 -3
  188. package/dist/core/types.d.ts.map +1 -1
  189. package/dist/core/types.js +1 -3
  190. package/dist/core/types.js.map +1 -1
  191. package/dist/core/utils/binary-paths.d.ts +32 -0
  192. package/dist/core/utils/binary-paths.d.ts.map +1 -1
  193. package/dist/core/utils/binary-paths.js +52 -0
  194. package/dist/core/utils/binary-paths.js.map +1 -1
  195. package/dist/core/utils/claude-cli-resolver.d.ts.map +1 -0
  196. package/dist/{skills/distill → core/utils}/claude-cli-resolver.js +1 -1
  197. package/dist/core/utils/claude-cli-resolver.js.map +1 -0
  198. package/dist/core/utils/claude-cli-spawn.d.ts +1 -1
  199. package/dist/core/utils/claude-cli-spawn.js +2 -2
  200. package/dist/core/utils/claude-cli-spawn.js.map +1 -1
  201. package/dist/core/utils/noise-prompt.d.ts +1 -1
  202. package/dist/core/utils/noise-prompt.js +1 -1
  203. package/dist/core/utils/time.d.ts +26 -0
  204. package/dist/core/utils/time.d.ts.map +1 -1
  205. package/dist/core/utils/time.js +33 -0
  206. package/dist/core/utils/time.js.map +1 -1
  207. package/dist/daemon/config-store.d.ts.map +1 -1
  208. package/dist/daemon/config-store.js +14 -5
  209. package/dist/daemon/config-store.js.map +1 -1
  210. package/dist/daemon/event-parser.d.ts.map +1 -1
  211. package/dist/daemon/event-parser.js +5 -0
  212. package/dist/daemon/event-parser.js.map +1 -1
  213. package/dist/daemon/handlers/post-tool-use.d.ts +24 -16
  214. package/dist/daemon/handlers/post-tool-use.d.ts.map +1 -1
  215. package/dist/daemon/handlers/post-tool-use.js +76 -116
  216. package/dist/daemon/handlers/post-tool-use.js.map +1 -1
  217. package/dist/daemon/handlers/pre-tool-use.d.ts +35 -10
  218. package/dist/daemon/handlers/pre-tool-use.d.ts.map +1 -1
  219. package/dist/daemon/handlers/pre-tool-use.js +71 -38
  220. package/dist/daemon/handlers/pre-tool-use.js.map +1 -1
  221. package/dist/daemon/handlers/stop.d.ts +20 -0
  222. package/dist/daemon/handlers/stop.d.ts.map +1 -1
  223. package/dist/daemon/handlers/stop.js +96 -8
  224. package/dist/daemon/handlers/stop.js.map +1 -1
  225. package/dist/daemon/handlers/user-prompt.d.ts +16 -1
  226. package/dist/daemon/handlers/user-prompt.d.ts.map +1 -1
  227. package/dist/daemon/handlers/user-prompt.js +97 -56
  228. package/dist/daemon/handlers/user-prompt.js.map +1 -1
  229. package/dist/daemon/handlers/violation-content-backfill.d.ts +76 -0
  230. package/dist/daemon/handlers/violation-content-backfill.d.ts.map +1 -0
  231. package/dist/daemon/handlers/violation-content-backfill.js +167 -0
  232. package/dist/daemon/handlers/violation-content-backfill.js.map +1 -0
  233. package/dist/daemon/index.d.ts +19 -0
  234. package/dist/daemon/index.d.ts.map +1 -1
  235. package/dist/daemon/index.js +125 -200
  236. package/dist/daemon/index.js.map +1 -1
  237. package/dist/daemon/rules/defaults.d.ts.map +1 -1
  238. package/dist/daemon/rules/defaults.js +151 -64
  239. package/dist/daemon/rules/defaults.js.map +1 -1
  240. package/dist/daemon/rules/types.d.ts +28 -22
  241. package/dist/daemon/rules/types.d.ts.map +1 -1
  242. package/dist/daemon/rules/workflow-defaults.js +9 -9
  243. package/dist/daemon/rules/workflow-defaults.js.map +1 -1
  244. package/dist/daemon/services/codegraph-sync.d.ts +94 -0
  245. package/dist/daemon/services/codegraph-sync.d.ts.map +1 -0
  246. package/dist/daemon/services/codegraph-sync.js +159 -0
  247. package/dist/daemon/services/codegraph-sync.js.map +1 -0
  248. package/dist/daemon/services/decision-hint.d.ts +47 -10
  249. package/dist/daemon/services/decision-hint.d.ts.map +1 -1
  250. package/dist/daemon/services/decision-hint.js +99 -24
  251. package/dist/daemon/services/decision-hint.js.map +1 -1
  252. package/dist/daemon/services/event-ttl-sweep.d.ts.map +1 -1
  253. package/dist/daemon/services/event-ttl-sweep.js +3 -2
  254. package/dist/daemon/services/event-ttl-sweep.js.map +1 -1
  255. package/dist/daemon/services/feedback-aggregator.d.ts +14 -26
  256. package/dist/daemon/services/feedback-aggregator.d.ts.map +1 -1
  257. package/dist/daemon/services/feedback-aggregator.js +23 -63
  258. package/dist/daemon/services/feedback-aggregator.js.map +1 -1
  259. package/dist/daemon/services/heartbeat-writer.d.ts +6 -15
  260. package/dist/daemon/services/heartbeat-writer.d.ts.map +1 -1
  261. package/dist/daemon/services/heartbeat-writer.js +7 -36
  262. package/dist/daemon/services/heartbeat-writer.js.map +1 -1
  263. package/dist/daemon/services/kb-injector.d.ts +1 -1
  264. package/dist/daemon/services/kb-injector.d.ts.map +1 -1
  265. package/dist/daemon/services/kb-injector.js +10 -2
  266. package/dist/daemon/services/kb-injector.js.map +1 -1
  267. package/dist/daemon/services/kb-rebuild-scheduler.d.ts +95 -0
  268. package/dist/daemon/services/kb-rebuild-scheduler.d.ts.map +1 -0
  269. package/dist/daemon/services/kb-rebuild-scheduler.js +149 -0
  270. package/dist/daemon/services/kb-rebuild-scheduler.js.map +1 -0
  271. package/dist/daemon/services/loop-hint.d.ts +139 -0
  272. package/dist/daemon/services/loop-hint.d.ts.map +1 -0
  273. package/dist/daemon/services/loop-hint.js +272 -0
  274. package/dist/daemon/services/loop-hint.js.map +1 -0
  275. package/dist/daemon/services/outcome-classification-service.js +1 -1
  276. package/dist/daemon/services/outcome-classification-service.js.map +1 -1
  277. package/dist/daemon/services/task-segmenter.d.ts +11 -0
  278. package/dist/daemon/services/task-segmenter.d.ts.map +1 -1
  279. package/dist/daemon/services/task-segmenter.js +48 -2
  280. package/dist/daemon/services/task-segmenter.js.map +1 -1
  281. package/dist/daemon/startup/maintenance-schedulers.d.ts +68 -0
  282. package/dist/daemon/startup/maintenance-schedulers.d.ts.map +1 -0
  283. package/dist/daemon/startup/maintenance-schedulers.js +294 -0
  284. package/dist/daemon/startup/maintenance-schedulers.js.map +1 -0
  285. package/dist/daemon/templates/agents/agent-retro-distiller.md +106 -0
  286. package/dist/daemon/templates/agents/claudemd-writer.md +1 -0
  287. package/dist/daemon/templates/agents/coder.md +165 -8
  288. package/dist/daemon/templates/agents/decision-maker.md +107 -21
  289. package/dist/daemon/templates/agents/doc-reviewer.md +4 -1
  290. package/dist/daemon/templates/agents/harness-debug-full.md +85 -3
  291. package/dist/daemon/templates/agents/knowledge-builder.md +1 -0
  292. package/dist/daemon/templates/agents/patch-applier.md +1 -0
  293. package/dist/daemon/templates/agents/planner.md +55 -3
  294. package/dist/daemon/templates/agents/safety-net-implementer.md +278 -0
  295. package/dist/daemon/templates/agents/skill-distiller.md +1 -0
  296. package/dist/daemon/templates/agents/task-boundary-classifier.md +1 -0
  297. package/dist/daemon/templates/agents/verify-agent.md +128 -5
  298. package/dist/hooks/stop.sh +7 -1
  299. package/dist/knowledge/builder.js +36 -7
  300. package/dist/knowledge/builder.js.map +1 -1
  301. package/dist/knowledge/constants.d.ts +10 -5
  302. package/dist/knowledge/constants.d.ts.map +1 -1
  303. package/dist/knowledge/constants.js +10 -5
  304. package/dist/knowledge/constants.js.map +1 -1
  305. package/dist/knowledge/graph/edge-extractor.d.ts +45 -0
  306. package/dist/knowledge/graph/edge-extractor.d.ts.map +1 -0
  307. package/dist/knowledge/graph/edge-extractor.js +242 -0
  308. package/dist/knowledge/graph/edge-extractor.js.map +1 -0
  309. package/dist/knowledge/graph/impact.d.ts +73 -0
  310. package/dist/knowledge/graph/impact.d.ts.map +1 -0
  311. package/dist/knowledge/graph/impact.js +94 -0
  312. package/dist/knowledge/graph/impact.js.map +1 -0
  313. package/dist/knowledge/graph/types.d.ts +22 -0
  314. package/dist/knowledge/graph/types.d.ts.map +1 -0
  315. package/dist/knowledge/graph/types.js +13 -0
  316. package/dist/knowledge/graph/types.js.map +1 -0
  317. package/dist/knowledge/prompt.d.ts +9 -0
  318. package/dist/knowledge/prompt.d.ts.map +1 -1
  319. package/dist/knowledge/prompt.js +17 -5
  320. package/dist/knowledge/prompt.js.map +1 -1
  321. package/dist/knowledge/query.d.ts +13 -0
  322. package/dist/knowledge/query.d.ts.map +1 -1
  323. package/dist/knowledge/query.js +107 -10
  324. package/dist/knowledge/query.js.map +1 -1
  325. package/dist/knowledge/repo-map.d.ts +11 -5
  326. package/dist/knowledge/repo-map.d.ts.map +1 -1
  327. package/dist/knowledge/repo-map.js +42 -3
  328. package/dist/knowledge/repo-map.js.map +1 -1
  329. package/dist/knowledge/validator.d.ts.map +1 -1
  330. package/dist/knowledge/validator.js +69 -2
  331. package/dist/knowledge/validator.js.map +1 -1
  332. package/dist/mcp/server.d.ts +64 -8
  333. package/dist/mcp/server.d.ts.map +1 -1
  334. package/dist/mcp/server.js +233 -18
  335. package/dist/mcp/server.js.map +1 -1
  336. package/dist/skills/distill/distiller.js +1 -1
  337. package/dist/skills/distill/distiller.js.map +1 -1
  338. package/dist/skills/distilled/distilled-api-design.md +4 -0
  339. package/dist/skills/distilled/distilled-brainstorming.md +79 -0
  340. package/dist/skills/distilled/distilled-brand-guidelines.md +86 -0
  341. package/dist/skills/distilled/distilled-canvas-design.md +128 -0
  342. package/dist/skills/distilled/distilled-claude-api.md +185 -0
  343. package/dist/skills/distilled/distilled-creator.md +5 -2
  344. package/dist/skills/distilled/distilled-dispatching-parallel-agents.md +136 -0
  345. package/dist/skills/distilled/distilled-doc-coauthoring.md +144 -0
  346. package/dist/skills/distilled/distilled-docx.md +231 -0
  347. package/dist/skills/distilled/distilled-executing-plans.md +85 -50
  348. package/dist/skills/distilled/distilled-finishing-a-development-branch.md +213 -0
  349. package/dist/skills/distilled/distilled-frontend-design.md +118 -0
  350. package/dist/skills/distilled/distilled-harness-engineering.md +1 -1
  351. package/dist/skills/distilled/distilled-receiving-code-review.md +185 -0
  352. package/dist/skills/distilled/distilled-subagent-driven-development.md +124 -0
  353. package/dist/skills/distilled/distilled-systematic-debugging.md +108 -260
  354. package/dist/skills/distilled/distilled-test-driven-development.md +432 -0
  355. package/dist/skills/distilled/distilled-using-superpowers.md +134 -0
  356. package/dist/skills/distilled/distilled-verification-before-completion.md +88 -78
  357. package/dist/skills/distilled/distilled-writing-skills.md +175 -0
  358. package/dist/skills/registry.d.ts +10 -50
  359. package/dist/skills/registry.d.ts.map +1 -1
  360. package/dist/skills/registry.js +7 -118
  361. package/dist/skills/registry.js.map +1 -1
  362. package/dist/skills/tools/pipeline-suggest.js +2 -2
  363. package/dist/skills/tools/pipeline-suggest.js.map +1 -1
  364. package/dist/skills/tools/skill-invoke.d.ts +2 -1
  365. package/dist/skills/tools/skill-invoke.d.ts.map +1 -1
  366. package/dist/skills/tools/skill-invoke.js +3 -1
  367. package/dist/skills/tools/skill-invoke.js.map +1 -1
  368. package/dist/web/analytics/anti-pattern-detector.d.ts.map +1 -1
  369. package/dist/web/analytics/anti-pattern-detector.js +6 -1
  370. package/dist/web/analytics/anti-pattern-detector.js.map +1 -1
  371. package/dist/web/analytics/drift-detector.d.ts +6 -0
  372. package/dist/web/analytics/drift-detector.d.ts.map +1 -1
  373. package/dist/web/analytics/drift-detector.js +15 -8
  374. package/dist/web/analytics/drift-detector.js.map +1 -1
  375. package/dist/web/analytics/weekly-report.d.ts +13 -0
  376. package/dist/web/analytics/weekly-report.d.ts.map +1 -1
  377. package/dist/web/analytics/weekly-report.js +17 -3
  378. package/dist/web/analytics/weekly-report.js.map +1 -1
  379. package/dist/web/routes/_helpers.d.ts +31 -0
  380. package/dist/web/routes/_helpers.d.ts.map +1 -1
  381. package/dist/web/routes/_helpers.js +33 -0
  382. package/dist/web/routes/_helpers.js.map +1 -1
  383. package/dist/web/routes/agent-distill.d.ts +49 -0
  384. package/dist/web/routes/agent-distill.d.ts.map +1 -0
  385. package/dist/web/routes/agent-distill.js +526 -0
  386. package/dist/web/routes/agent-distill.js.map +1 -0
  387. package/dist/web/routes/config.d.ts +56 -0
  388. package/dist/web/routes/config.d.ts.map +1 -0
  389. package/dist/web/routes/config.js +243 -0
  390. package/dist/web/routes/config.js.map +1 -0
  391. package/dist/web/routes/decisions.js +1 -1
  392. package/dist/web/routes/decisions.js.map +1 -1
  393. package/dist/web/routes/error-handler.d.ts +0 -4
  394. package/dist/web/routes/error-handler.d.ts.map +1 -1
  395. package/dist/web/routes/error-handler.js +0 -8
  396. package/dist/web/routes/error-handler.js.map +1 -1
  397. package/dist/web/routes/events.d.ts.map +1 -1
  398. package/dist/web/routes/events.js +2 -1
  399. package/dist/web/routes/events.js.map +1 -1
  400. package/dist/web/routes/insights.d.ts.map +1 -1
  401. package/dist/web/routes/insights.js +0 -0
  402. package/dist/web/routes/insights.js.map +1 -1
  403. package/dist/web/routes/knowledge.d.ts +43 -2
  404. package/dist/web/routes/knowledge.d.ts.map +1 -1
  405. package/dist/web/routes/knowledge.js +117 -6
  406. package/dist/web/routes/knowledge.js.map +1 -1
  407. package/dist/web/routes/pipeline.d.ts +0 -9
  408. package/dist/web/routes/pipeline.d.ts.map +1 -1
  409. package/dist/web/routes/pipeline.js +0 -4
  410. package/dist/web/routes/pipeline.js.map +1 -1
  411. package/dist/web/routes/rules.d.ts.map +1 -1
  412. package/dist/web/routes/rules.js +20 -6
  413. package/dist/web/routes/rules.js.map +1 -1
  414. package/dist/web/routes/sessions.d.ts.map +1 -1
  415. package/dist/web/routes/sessions.js +8 -7
  416. package/dist/web/routes/sessions.js.map +1 -1
  417. package/dist/web/routes/skill-stats.d.ts.map +1 -1
  418. package/dist/web/routes/skill-stats.js +153 -16
  419. package/dist/web/routes/skill-stats.js.map +1 -1
  420. package/dist/web/routes/skills-distill.js +1 -1
  421. package/dist/web/routes/skills-distill.js.map +1 -1
  422. package/dist/web/routes/stats.d.ts.map +1 -1
  423. package/dist/web/routes/stats.js +2 -1
  424. package/dist/web/routes/stats.js.map +1 -1
  425. package/dist/web/routes/task-timeline.d.ts +95 -19
  426. package/dist/web/routes/task-timeline.d.ts.map +1 -1
  427. package/dist/web/routes/task-timeline.js +344 -88
  428. package/dist/web/routes/task-timeline.js.map +1 -1
  429. package/dist/web/routes/tasks.d.ts.map +1 -1
  430. package/dist/web/routes/tasks.js +52 -30
  431. package/dist/web/routes/tasks.js.map +1 -1
  432. package/dist/web/routes/violations.d.ts +1 -1
  433. package/dist/web/routes/violations.d.ts.map +1 -1
  434. package/dist/web/routes/violations.js +3 -2
  435. package/dist/web/routes/violations.js.map +1 -1
  436. package/dist/web/server.d.ts.map +1 -1
  437. package/dist/web/server.js +20 -0
  438. package/dist/web/server.js.map +1 -1
  439. package/dist/web/services/agent-distill-manager.d.ts +122 -0
  440. package/dist/web/services/agent-distill-manager.d.ts.map +1 -0
  441. package/dist/web/services/agent-distill-manager.js +397 -0
  442. package/dist/web/services/agent-distill-manager.js.map +1 -0
  443. package/dist/web/services/distill-manager.d.ts +47 -0
  444. package/dist/web/services/distill-manager.d.ts.map +1 -1
  445. package/dist/web/services/distill-manager.js +103 -0
  446. package/dist/web/services/distill-manager.js.map +1 -1
  447. package/dist/web/static/assets/AgentDetailPage-DlUeA1sX.js +2 -0
  448. package/dist/web/static/assets/AgentDetailPage-DlUeA1sX.js.map +1 -0
  449. package/dist/web/static/assets/AgentDistillRunPage-Cybo4bii.js +3 -0
  450. package/dist/web/static/assets/AgentDistillRunPage-Cybo4bii.js.map +1 -0
  451. package/dist/web/static/assets/AgentsPage-Qd9FExLG.js +2 -0
  452. package/dist/web/static/assets/AgentsPage-Qd9FExLG.js.map +1 -0
  453. package/dist/web/static/assets/DaemonHealthPage-DTSVqtrI.js +2 -0
  454. package/dist/web/static/assets/DaemonHealthPage-DTSVqtrI.js.map +1 -0
  455. package/dist/web/static/assets/DecisionDetailPage-b4BA8dhc.js +2 -0
  456. package/dist/web/static/assets/DecisionDetailPage-b4BA8dhc.js.map +1 -0
  457. package/dist/web/static/assets/DecisionsPage-a3NRo_T7.js +2 -0
  458. package/dist/web/static/assets/DecisionsPage-a3NRo_T7.js.map +1 -0
  459. package/dist/web/static/assets/DiagnosticsPage-DIVdiIQG.js +2 -0
  460. package/dist/web/static/assets/DiagnosticsPage-DIVdiIQG.js.map +1 -0
  461. package/dist/web/static/assets/DistillDetailPage-U6a3l2iP.js +4 -0
  462. package/dist/web/static/assets/DistillDetailPage-U6a3l2iP.js.map +1 -0
  463. package/dist/web/static/assets/DistillPage-O7BHtRN8.js +2 -0
  464. package/dist/web/static/assets/DistillPage-O7BHtRN8.js.map +1 -0
  465. package/dist/web/static/assets/DistillRunPage-D1JuRWWr.js +2 -0
  466. package/dist/web/static/assets/DistillRunPage-D1JuRWWr.js.map +1 -0
  467. package/dist/web/static/assets/GlobalScopeHint-Q3wTJx3F.js +2 -0
  468. package/dist/web/static/assets/GlobalScopeHint-Q3wTJx3F.js.map +1 -0
  469. package/dist/web/static/assets/IssueDetailPage-BDfrtk2C.js +2 -0
  470. package/dist/web/static/assets/IssueDetailPage-BDfrtk2C.js.map +1 -0
  471. package/dist/web/static/assets/IssuesPage-SKmhlCrw.js +2 -0
  472. package/dist/web/static/assets/IssuesPage-SKmhlCrw.js.map +1 -0
  473. package/dist/web/static/assets/KbDetailPage-Yna86Na8.js +2 -0
  474. package/dist/web/static/assets/KbDetailPage-Yna86Na8.js.map +1 -0
  475. package/dist/web/static/assets/KbHitsPage-Cljl7H9p.js +2 -0
  476. package/dist/web/static/assets/KbHitsPage-Cljl7H9p.js.map +1 -0
  477. package/dist/web/static/assets/{MarkdownRenderer-DZmTl-8J.js → MarkdownRenderer-DlDQNihj.js} +2 -2
  478. package/dist/web/static/assets/{MarkdownRenderer-DZmTl-8J.js.map → MarkdownRenderer-DlDQNihj.js.map} +1 -1
  479. package/dist/web/static/assets/NotFound-LMzbP51V.js +2 -0
  480. package/dist/web/static/assets/{NotFound-BQPh0vaF.js.map → NotFound-LMzbP51V.js.map} +1 -1
  481. package/dist/web/static/assets/SettingsPage-DzoK4PKg.js +2 -0
  482. package/dist/web/static/assets/SettingsPage-DzoK4PKg.js.map +1 -0
  483. package/dist/web/static/assets/SkillDetailPage-BuBJJ_NX.js +2 -0
  484. package/dist/web/static/assets/SkillDetailPage-BuBJJ_NX.js.map +1 -0
  485. package/dist/web/static/assets/SkillsPage-aojkJpBc.js +2 -0
  486. package/dist/web/static/assets/SkillsPage-aojkJpBc.js.map +1 -0
  487. package/dist/web/static/assets/TaskDetailPage-1ckxnGhw.js +4 -0
  488. package/dist/web/static/assets/TaskDetailPage-1ckxnGhw.js.map +1 -0
  489. package/dist/web/static/assets/TasksHubPage-C2PLh3eg.js +6 -0
  490. package/dist/web/static/assets/TasksHubPage-C2PLh3eg.js.map +1 -0
  491. package/dist/web/static/assets/WorkplacePage-DHrp5VxS.js +2 -0
  492. package/dist/web/static/assets/WorkplacePage-DHrp5VxS.js.map +1 -0
  493. package/dist/web/static/assets/arco-DV6xCLhr.js +14 -0
  494. package/dist/web/static/assets/arco-DV6xCLhr.js.map +1 -0
  495. package/dist/web/static/assets/charts-BSV4cyC4.js +37 -0
  496. package/dist/web/static/assets/charts-BSV4cyC4.js.map +1 -0
  497. package/dist/web/static/assets/{index-7bl3kbcx.css → index-B_v_MKlb.css} +1 -1
  498. package/dist/web/static/assets/index-DileOOE4.js +4 -0
  499. package/dist/web/static/assets/index-DileOOE4.js.map +1 -0
  500. package/dist/web/static/assets/markdown-CA7ePUts.js +30 -0
  501. package/dist/web/static/assets/markdown-CA7ePUts.js.map +1 -0
  502. package/dist/web/static/assets/{outcome-DUn1NjlC.js → outcome-BKGy9azt.js} +2 -2
  503. package/dist/web/static/assets/{outcome-DUn1NjlC.js.map → outcome-BKGy9azt.js.map} +1 -1
  504. package/dist/web/static/assets/{query-S6X1S7K9.js → query-CgCOpYWf.js} +2 -2
  505. package/dist/web/static/assets/{query-S6X1S7K9.js.map → query-CgCOpYWf.js.map} +1 -1
  506. package/dist/web/static/assets/{react-router-JVUrkhdd.js → react-router-Cxmg8RuL.js} +3 -3
  507. package/dist/web/static/assets/{react-router-JVUrkhdd.js.map → react-router-Cxmg8RuL.js.map} +1 -1
  508. package/dist/web/static/assets/{syntax-highlighter-BkZfCDsz.js → syntax-highlighter-BDYycNja.js} +3 -3
  509. package/dist/web/static/assets/{syntax-highlighter-BkZfCDsz.js.map → syntax-highlighter-BDYycNja.js.map} +1 -1
  510. package/dist/web/static/assets/task-title-BhOcemuR.js +2 -0
  511. package/dist/web/static/assets/task-title-BhOcemuR.js.map +1 -0
  512. package/dist/web/static/assets/useAgentStats-B-uTgqBd.js +2 -0
  513. package/dist/web/static/assets/useAgentStats-B-uTgqBd.js.map +1 -0
  514. package/dist/web/static/assets/useDecisions-D-G2Ft5T.js +2 -0
  515. package/dist/web/static/assets/useDecisions-D-G2Ft5T.js.map +1 -0
  516. package/dist/web/static/assets/useDistill-21dZkXlT.js +3 -0
  517. package/dist/web/static/assets/useDistill-21dZkXlT.js.map +1 -0
  518. package/dist/web/static/assets/useEffectiveProject-DQiyX54y.js +2 -0
  519. package/dist/web/static/assets/useEffectiveProject-DQiyX54y.js.map +1 -0
  520. package/dist/web/static/assets/useIssuesFeed-CFiyQkAL.js +2 -0
  521. package/dist/web/static/assets/useIssuesFeed-CFiyQkAL.js.map +1 -0
  522. package/dist/web/static/assets/useKbHits-xKXWgqh9.js +2 -0
  523. package/dist/web/static/assets/useKbHits-xKXWgqh9.js.map +1 -0
  524. package/dist/web/static/assets/useSkillStats-B5hbIwdf.js +2 -0
  525. package/dist/web/static/assets/useSkillStats-B5hbIwdf.js.map +1 -0
  526. package/dist/web/static/assets/vendor-DS-q4Eyc.js +36 -0
  527. package/dist/web/static/assets/vendor-DS-q4Eyc.js.map +1 -0
  528. package/dist/web/static/index.html +6 -6
  529. package/package.json +5 -3
  530. package/dist/core/storage/workflow-recommendations.d.ts +0 -124
  531. package/dist/core/storage/workflow-recommendations.d.ts.map +0 -1
  532. package/dist/core/storage/workflow-recommendations.js +0 -274
  533. package/dist/core/storage/workflow-recommendations.js.map +0 -1
  534. package/dist/daemon/services/experience-extractor.d.ts.map +0 -1
  535. package/dist/daemon/services/experience-extractor.js.map +0 -1
  536. package/dist/daemon/services/violation-reporter.d.ts.map +0 -1
  537. package/dist/daemon/services/violation-reporter.js.map +0 -1
  538. package/dist/daemon/templates/agents/harness-hotfix.md +0 -99
  539. package/dist/daemon/templates/agents/hybrid-feature-with-safety.md +0 -104
  540. package/dist/daemon/templates/agents/refactor-specialist.md +0 -98
  541. package/dist/skills/distill/claude-cli-resolver.d.ts.map +0 -1
  542. package/dist/skills/distill/claude-cli-resolver.js.map +0 -1
  543. package/dist/skills/distilled/distilled-defi-amm-security.md +0 -293
  544. package/dist/skills/keyword-score.d.ts +0 -29
  545. package/dist/skills/keyword-score.d.ts.map +0 -1
  546. package/dist/skills/keyword-score.js +0 -54
  547. package/dist/skills/keyword-score.js.map +0 -1
  548. package/dist/web/static/assets/AgentContentPage-DkeRNxok.js +0 -2
  549. package/dist/web/static/assets/AgentContentPage-DkeRNxok.js.map +0 -1
  550. package/dist/web/static/assets/AgentDelegationTable-ByBa0x1l.js +0 -2
  551. package/dist/web/static/assets/AgentDelegationTable-ByBa0x1l.js.map +0 -1
  552. package/dist/web/static/assets/ContextInsightsPage-oUk7_I8u.js +0 -3
  553. package/dist/web/static/assets/ContextInsightsPage-oUk7_I8u.js.map +0 -1
  554. package/dist/web/static/assets/DaemonHealthPage-DG2fyOP7.js +0 -2
  555. package/dist/web/static/assets/DaemonHealthPage-DG2fyOP7.js.map +0 -1
  556. package/dist/web/static/assets/DecisionsPage-CMAPEnKb.js +0 -2
  557. package/dist/web/static/assets/DecisionsPage-CMAPEnKb.js.map +0 -1
  558. package/dist/web/static/assets/DiagnosticsPage-DQd-Zm4r.js +0 -2
  559. package/dist/web/static/assets/DiagnosticsPage-DQd-Zm4r.js.map +0 -1
  560. package/dist/web/static/assets/DriftTab-DqpepOhI.js +0 -2
  561. package/dist/web/static/assets/DriftTab-DqpepOhI.js.map +0 -1
  562. package/dist/web/static/assets/HealthHomePage-CN6zNIie.js +0 -3
  563. package/dist/web/static/assets/HealthHomePage-CN6zNIie.js.map +0 -1
  564. package/dist/web/static/assets/KbHitRateTable-ByEIWujF.js +0 -2
  565. package/dist/web/static/assets/KbHitRateTable-ByEIWujF.js.map +0 -1
  566. package/dist/web/static/assets/NotFound-BQPh0vaF.js +0 -2
  567. package/dist/web/static/assets/ProjectSwitcher-D3lZMFd3.js +0 -2
  568. package/dist/web/static/assets/ProjectSwitcher-D3lZMFd3.js.map +0 -1
  569. package/dist/web/static/assets/SettingsPage-oLJBNzQj.js +0 -2
  570. package/dist/web/static/assets/SettingsPage-oLJBNzQj.js.map +0 -1
  571. package/dist/web/static/assets/SkillContentPage-DK5rgfgw.js +0 -2
  572. package/dist/web/static/assets/SkillContentPage-DK5rgfgw.js.map +0 -1
  573. package/dist/web/static/assets/SkillStatsTable-DYMzjEUV.js +0 -2
  574. package/dist/web/static/assets/SkillStatsTable-DYMzjEUV.js.map +0 -1
  575. package/dist/web/static/assets/SkillsDistillTab-C7qaG8q3.js +0 -2
  576. package/dist/web/static/assets/SkillsDistillTab-C7qaG8q3.js.map +0 -1
  577. package/dist/web/static/assets/TasksHubPage-03wsRRsJ.js +0 -6
  578. package/dist/web/static/assets/TasksHubPage-03wsRRsJ.js.map +0 -1
  579. package/dist/web/static/assets/ViolationsPage-DSiLr-9O.js +0 -3
  580. package/dist/web/static/assets/ViolationsPage-DSiLr-9O.js.map +0 -1
  581. package/dist/web/static/assets/arco-Bhi3a6Qp.js +0 -14
  582. package/dist/web/static/assets/arco-Bhi3a6Qp.js.map +0 -1
  583. package/dist/web/static/assets/charts-BuHQWDbQ.js +0 -37
  584. package/dist/web/static/assets/charts-BuHQWDbQ.js.map +0 -1
  585. package/dist/web/static/assets/index-BIYnq1Dx.js +0 -4
  586. package/dist/web/static/assets/index-BIYnq1Dx.js.map +0 -1
  587. package/dist/web/static/assets/useTabsParam-k8qte_0C.js +0 -2
  588. package/dist/web/static/assets/useTabsParam-k8qte_0C.js.map +0 -1
  589. package/dist/web/static/assets/vendor-DWgdB1eY.js +0 -65
  590. package/dist/web/static/assets/vendor-DWgdB1eY.js.map +0 -1
  591. /package/dist/{skills/distill → core/utils}/claude-cli-resolver.d.ts +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"file":"AgentDelegationTable-ByBa0x1l.js","sources":["../../src/components/context/AgentContentDrawer.tsx","../../src/components/context/AgentDelegationTable.tsx"],"sourcesContent":["/**\n * AgentContentDrawer — right-side Arco Drawer that shows an agent's full\n * markdown (frontmatter + body) when a row in AgentDelegationTable is clicked.\n *\n * Mirrors SkillContentDrawer but reads .claude/agents/<name>.md via\n * /api/agents/:name/content.\n *\n * Empty case: virtual subagents (`general-purpose`, etc.) have no .md file —\n * the endpoint returns exists:false; UI renders a friendly Empty rather than\n * disabling the row click (spec Q6 = default Empty).\n */\nimport { useQuery } from '@tanstack/react-query'\nimport Drawer from '@arco-design/web-react/es/Drawer'\nimport Descriptions from '@arco-design/web-react/es/Descriptions'\nimport Empty from '@arco-design/web-react/es/Empty'\nimport Skeleton from '@arco-design/web-react/es/Skeleton'\nimport Typography from '@arco-design/web-react/es/Typography'\nimport { IconLaunch } from '@arco-design/web-react/icon'\nimport MarkdownRenderer from '../MarkdownRenderer'\n\nexport interface AgentRowStats {\n agent: string\n count: number\n rate: string\n source?: 'project' | 'builtin'\n}\n\ninterface AgentContentResponse {\n name: string\n source?: 'project' | 'builtin'\n exists: boolean\n path: string | null\n bytes: number\n body: string\n frontmatter: Record<string, unknown>\n tools: string | null\n model: string | null\n message?: string\n}\n\ninterface Props {\n open: boolean\n agentName: string | null\n stats?: AgentRowStats | null\n onClose: () => void\n}\n\nconst WHITELIST: ReadonlyArray<string> = [\n 'name',\n 'description',\n 'tools',\n 'model',\n 'version',\n 'spawn_agent',\n 'tags',\n]\n\nfunction renderFmValue(v: unknown): string {\n if (v == null) return '-'\n if (Array.isArray(v)) return v.join(', ')\n if (typeof v === 'string') return v\n if (typeof v === 'number' || typeof v === 'boolean') return String(v)\n try {\n return JSON.stringify(v)\n } catch {\n return String(v)\n }\n}\n\nexport default function AgentContentDrawer({ open, agentName, stats, onClose }: Props) {\n const { data, isLoading, isError, error } = useQuery<AgentContentResponse>({\n queryKey: ['agent-content', agentName],\n enabled: !!agentName && open,\n queryFn: async () => {\n const r = await fetch(`/api/agents/${encodeURIComponent(agentName!)}/content`)\n if (!r.ok) throw new Error(`HTTP ${r.status}`)\n return r.json()\n },\n staleTime: 5 * 60_000,\n })\n\n const title = (\n <div style={{ display: 'flex', alignItems: 'center', gap: 12, flexWrap: 'wrap' }}>\n <span style={{ fontFamily: 'monospace', fontSize: 13 }}>{agentName ?? '-'}</span>\n {agentName && (\n <a\n href={`/context/agent/${encodeURIComponent(agentName)}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{ marginLeft: 'auto', fontSize: 12, display: 'inline-flex', alignItems: 'center', gap: 4 }}\n >\n <IconLaunch /> Open in full page\n </a>\n )}\n </div>\n )\n\n return (\n <Drawer\n visible={open}\n onCancel={onClose}\n onOk={onClose}\n title={title}\n width={760}\n footer={null}\n unmountOnExit\n >\n {stats && (\n <Descriptions\n colon=\" :\"\n size=\"small\"\n column={3}\n data={[\n { label: 'delegations (7d)', value: stats.count },\n { label: 'rate', value: stats.rate },\n { label: 'subagent_type', value: stats.agent },\n ]}\n style={{ marginBottom: 12 }}\n />\n )}\n\n {isLoading && <Skeleton animation text={{ rows: 6 }} />}\n {isError && (\n <Empty description={<Typography.Text type=\"error\">加载失败: {String(error)}</Typography.Text>} />\n )}\n\n {data && !data.exists && data.source === 'builtin' && (\n <Empty\n description={\n <span>\n <code style={{ fontFamily: 'monospace' }}>{agentName}</code> 是 Claude Code 内置的虚拟 subagent_type,无项目级 markdown 文件。\n <br />\n {data.message ?? 'Claude Code built-in agent; no project-level details available'}\n </span>\n }\n />\n )}\n\n {data && !data.exists && data.source !== 'builtin' && (\n <Empty\n description={\n <span>\n 未找到 <code style={{ fontFamily: 'monospace' }}>.claude/agents/{agentName}.md</code>。\n <br />\n 若这是新建 agent,请在 TUI 重启(Cmd+R)后再触发。\n </span>\n }\n />\n )}\n\n {data && data.exists && (\n <>\n <Descriptions\n colon=\" :\"\n size=\"mini\"\n column={2}\n title={<Typography.Text style={{ fontSize: 13 }}>Frontmatter</Typography.Text>}\n data={WHITELIST.map((key) => ({\n label: key,\n value: renderFmValue(data.frontmatter[key]),\n }))}\n style={{ marginBottom: 16 }}\n />\n <Typography.Text style={{ fontSize: 13, fontWeight: 600 }}>Body</Typography.Text>\n <div\n style={{\n marginTop: 8,\n maxHeight: 'calc(100vh - 360px)',\n overflow: 'auto',\n border: '1px solid var(--color-border-2)',\n borderRadius: 4,\n padding: 12,\n }}\n >\n <MarkdownRenderer content={data.body} />\n </div>\n </>\n )}\n </Drawer>\n )\n}\n","/**\n * AgentDelegationTable — Tab 3 of /context (🤖 Agent 委托).\n *\n * 数据: GET /api/rules/hit-rate?days=7 — 复用同一个 endpoint, 取 agents[].\n * 0 改后端.\n *\n * 列: agent (subagent_type) | delegations_7d | rate (vs 全部 prompt) | 状态 chip.\n */\nimport { useMemo, useState } from 'react'\nimport { useQuery } from '@tanstack/react-query'\nimport Table from '@arco-design/web-react/es/Table'\nimport Tag from '@arco-design/web-react/es/Tag'\nimport Empty from '@arco-design/web-react/es/Empty'\nimport Skeleton from '@arco-design/web-react/es/Skeleton'\nimport Typography from '@arco-design/web-react/es/Typography'\nimport AgentContentDrawer, { type AgentRowStats } from './AgentContentDrawer'\n\ninterface AgentRow {\n agent: string\n count: number\n rate: string\n source?: 'project' | 'builtin'\n}\ninterface HitRateResponse {\n summary: { totalPrompts: number; agentDelegations: number; agentRate: string }\n agents: AgentRow[]\n}\n\nexport default function AgentDelegationTable() {\n const [openAgent, setOpenAgent] = useState<AgentRowStats | null>(null)\n const { data, isLoading, isError, error } = useQuery<HitRateResponse>({\n queryKey: ['ctx-agent-hit-rate'],\n queryFn: async () => {\n const r = await fetch('/api/rules/hit-rate?days=7')\n if (!r.ok) throw new Error(`HTTP ${r.status}`)\n return r.json()\n },\n staleTime: 60_000,\n })\n\n const rows = useMemo(() => {\n if (!data) return []\n return data.agents.map((a) => ({ ...a })).sort((a, b) => b.count - a.count)\n }, [data])\n\n if (isError) return <Empty description={<Typography.Text type=\"error\">加载失败: {String(error)}</Typography.Text>} />\n if (isLoading || !data) return <Skeleton animation text={{ rows: 8 }} />\n\n const columns = [\n {\n title: 'agent (subagent_type)',\n dataIndex: 'agent',\n render: (id: string, record: AgentRow) => (\n <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>\n <span style={{ fontFamily: 'monospace', fontSize: 12 }}>{id}</span>\n {record.source === 'builtin' && (\n <Tag color=\"gray\" size=\"small\">built-in</Tag>\n )}\n </span>\n ),\n },\n {\n title: 'delegations (7d)',\n dataIndex: 'count',\n width: 160,\n sorter: (a: { count: number }, b: { count: number }) => a.count - b.count,\n render: (n: number) => <span style={{ fontFamily: 'monospace', fontWeight: 600 }}>{n}</span>,\n },\n {\n title: 'rate (vs 全部 prompt)',\n dataIndex: 'rate',\n width: 160,\n render: (s: string) => <Typography.Text style={{ fontSize: 12 }}>{s}</Typography.Text>,\n },\n {\n title: '热度',\n dataIndex: 'count',\n key: 'tier',\n width: 100,\n render: (n: number) => (\n n >= 50 ? <Tag color=\"green\" size=\"small\">heavy</Tag> :\n n >= 5 ? <Tag color=\"arcoblue\" size=\"small\">used</Tag> :\n <Tag color=\"orange\" size=\"small\">rare</Tag>\n ),\n },\n ]\n\n return (\n <div>\n <div style={{ marginBottom: 12 }}>\n <Typography.Text style={{ fontSize: 13, color: 'var(--color-text-3)' }}>\n 近 7d · 总 delegation {data.summary.agentDelegations} / {data.summary.totalPrompts} prompts ·\n agent rate {data.summary.agentRate} · 共 {rows.length} 个 agent\n </Typography.Text>\n </div>\n <Table\n rowKey=\"agent\"\n data={rows}\n columns={columns}\n pagination={{ pageSize: 20, showTotal: true }}\n size=\"small\"\n border={{ wrapper: true, cell: true }}\n onRow={(record) => ({\n onClick: () => setOpenAgent(record as AgentRowStats),\n style: { cursor: 'pointer' },\n })}\n noDataElement={<Empty description=\"无 agent 委托记录\" />}\n />\n <AgentContentDrawer\n open={openAgent !== null}\n agentName={openAgent?.agent ?? null}\n stats={openAgent}\n onClose={() => setOpenAgent(null)}\n />\n </div>\n )\n}\n"],"names":["WHITELIST","renderFmValue","v","AgentContentDrawer","open","agentName","stats","onClose","data","isLoading","isError","error","useQuery","r","title","jsxs","jsx","IconLaunch","Drawer","Descriptions","Skeleton","Empty","Typography","Fragment","key","MarkdownRenderer","AgentDelegationTable","openAgent","setOpenAgent","useState","rows","useMemo","a","b","columns","id","record","Tag","n","s","Table"],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/KbHitRateTable-ByEIWujF.js","assets/react-vendor-tkvCrao7.js","assets/query-S6X1S7K9.js","assets/react-router-JVUrkhdd.js","assets/vendor-DWgdB1eY.js","assets/arco-Bhi3a6Qp.js","assets/arco-DFQA6dO_.css","assets/MarkdownRenderer-DZmTl-8J.js","assets/syntax-highlighter-BkZfCDsz.js","assets/ProjectSwitcher-D3lZMFd3.js","assets/SkillStatsTable-DYMzjEUV.js","assets/AgentDelegationTable-ByBa0x1l.js","assets/SkillsDistillTab-C7qaG8q3.js","assets/auth-Bnf8ZcqN.js","assets/charts-BuHQWDbQ.js"])))=>i.map(i=>d[i]);
2
- import{_ as l}from"./index-BIYnq1Dx.js";import{j as e,r as s}from"./react-vendor-tkvCrao7.js";import{u as n,T as r,c as o,p,aa as j,W as b,ab as h}from"./arco-Bhi3a6Qp.js";import{P as m}from"./ProjectSwitcher-D3lZMFd3.js";import{u as g}from"./useTabsParam-k8qte_0C.js";import"./react-router-JVUrkhdd.js";import"./vendor-DWgdB1eY.js";import"./query-S6X1S7K9.js";import"./lucide-CnlPQoG8.js";const _=s.lazy(()=>l(()=>import("./KbHitRateTable-ByEIWujF.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9]))),u=s.lazy(()=>l(()=>import("./SkillStatsTable-DYMzjEUV.js"),__vite__mapDeps([10,1,2,5,4,6,7,8]))),y=s.lazy(()=>l(()=>import("./AgentDelegationTable-ByBa0x1l.js"),__vite__mapDeps([11,1,2,5,4,6,7,8]))),f=s.lazy(()=>l(()=>import("./SkillsDistillTab-C7qaG8q3.js"),__vite__mapDeps([12,1,2,5,4,6,13,14]))),t=o.TabPane,T=["kb","skills","agents","distill"];function a(){return e.jsx("div",{style:{padding:24,color:"var(--color-text-3)",fontSize:13},children:"加载中…"})}function R(){const{tab:i,setTab:d}=g(T,"kb"),c=x=>d(x);return e.jsxs("div",{"data-testid":"context-insights","data-tab":i,style:{padding:16,display:"flex",flexDirection:"column",gap:12},children:[e.jsx(n,{bordered:!1,bodyStyle:{padding:"12px 16px"},style:{background:"var(--color-bg-1)"},children:e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,flexWrap:"wrap"},children:[e.jsx(r.Title,{heading:5,style:{margin:0},children:"AI 在拿什么"}),e.jsx(r.Text,{type:"secondary",style:{fontSize:12},children:"Claude 写代码时调用了哪些 KB / Skill / Agent · 近 7d"}),e.jsx("div",{style:{marginLeft:"auto"},children:e.jsx(m,{})})]})}),e.jsx(n,{bordered:!0,bodyStyle:{padding:12},children:e.jsxs(o,{activeTab:i,onChange:c,type:"line",children:[e.jsx(t,{title:e.jsxs("span",{children:[e.jsx(p,{})," 📚 KB 命中"]}),children:e.jsx(s.Suspense,{fallback:e.jsx(a,{}),children:e.jsx(_,{})})},"kb"),e.jsx(t,{title:e.jsxs("span",{children:[e.jsx(j,{})," 🔧 Skill 调用"]}),children:e.jsx(s.Suspense,{fallback:e.jsx(a,{}),children:e.jsx(u,{})})},"skills"),e.jsx(t,{title:e.jsxs("span",{children:[e.jsx(b,{})," 🤖 Agent 委托"]}),children:e.jsx(s.Suspense,{fallback:e.jsx(a,{}),children:e.jsx(y,{})})},"agents"),e.jsx(t,{title:e.jsxs("span",{children:[e.jsx(h,{})," 🧪 蒸馏"]}),children:e.jsx(s.Suspense,{fallback:e.jsx(a,{}),children:e.jsx(f,{})})},"distill")]})})]})}export{R as default};
3
- //# sourceMappingURL=ContextInsightsPage-oUk7_I8u.js.map
@@ -1 +0,0 @@
1
- {"version":3,"mappings":";sYAqBA,MAAMA,EAAiBC,OAAK,IAAAC,EAAA,IAAM,OAAO,8BAAsC,yCAAC,EAC1EC,EAAkBF,OAAK,IAAAC,EAAA,IAAM,OAAO,+BAAuC,sCAAC,EAC5EE,EAAuBH,OAAK,IAAAC,EAAA,IAAM,OAAO,oCAA4C,sCAAC,EACtFG,EAAmBJ,OAAK,IAAAC,EAAA,IAAM,OAAO,gCAAwC,wCAAC,EAE9EI,EAAUC,EAAK,QAGfC,EAA2B,CAAC,KAAM,SAAU,SAAU,SAAS,EAErE,SAASC,GAAe,CACtB,OACEC,MAAC,OAAI,MAAO,CAAE,QAAS,GAAI,MAAO,sBAAuB,SAAU,IAAM,gBAEzE,CAEJ,CAEA,SAAwBC,GAAsB,CAC5C,KAAM,CAAE,IAAAC,EAAK,OAAAC,CAAA,EAAWC,EAAqBN,EAAO,IAAI,EAClDO,EAAgBC,GAAgBH,EAAOG,CAAa,EAE1D,cACG,OAAI,cAAY,mBAAmB,WAAUJ,EAAK,MAAO,CAAE,QAAS,GAAI,QAAS,OAAQ,cAAe,SAAU,IAAK,IAEtH,UAAAF,MAACO,EAAA,CAAK,SAAU,GAAO,UAAW,CAAE,QAAS,aAAe,MAAO,CAAE,WAAY,qBAC/E,SAAAC,OAAC,OAAI,MAAO,CAAE,QAAS,OAAQ,WAAY,SAAU,IAAK,GAAI,SAAU,QACtE,UAAAR,MAACS,EAAW,MAAX,CAAiB,QAAS,EAAG,MAAO,CAAE,OAAQ,GAAK,mBAAO,EAC3DT,MAACS,EAAW,KAAX,CAAgB,KAAK,YAAY,MAAO,CAAE,SAAU,IAAM,sDAE3D,EACAT,MAAC,OAAI,MAAO,CAAE,WAAY,QACxB,SAAAA,MAACU,EAAA,EAAgB,EACnB,GACF,EACF,QAGCH,EAAA,CAAK,SAAQ,GAAC,UAAW,CAAE,QAAS,IACnC,SAAAC,OAACX,GAAK,UAAWK,EAAK,SAAUG,EAAc,KAAK,OACjD,UAAAL,MAACJ,EAAA,CAEC,aAAQ,QAAK,UAAAI,MAACW,EAAA,EAAS,EAAE,aAAS,EAElC,SAAAX,MAACY,YAAS,SAAUZ,MAACD,IAAa,EAChC,SAAAC,MAACV,IAAe,EAClB,GALI,MAONU,MAACJ,EAAA,CAEC,aAAQ,QAAK,UAAAI,MAACa,EAAA,EAAS,EAAE,gBAAY,EAErC,SAAAb,MAACY,YAAS,SAAUZ,MAACD,IAAa,EAChC,SAAAC,MAACP,IAAgB,EACnB,GALI,UAONO,MAACJ,EAAA,CAEC,aAAQ,QAAK,UAAAI,MAACc,EAAA,EAAU,EAAE,gBAAY,EAEtC,SAAAd,MAACY,YAAS,SAAUZ,MAACD,IAAa,EAChC,SAAAC,MAACN,IAAqB,EACxB,GALI,UAONM,MAACJ,EAAA,CAEC,aAAQ,QAAK,UAAAI,MAACe,EAAA,EAAe,EAAE,UAAM,EAErC,SAAAf,MAACY,YAAS,SAAUZ,MAACD,IAAa,EAChC,SAAAC,MAACL,IAAiB,EACpB,GALI,UAMN,EACF,EACF,GACF,CAEJ","names":["KbHitRateTable","lazy","__vitePreload","SkillStatsTable","AgentDelegationTable","SkillsDistillTab","TabPane","Tabs","KNOWN","PaneFallback","jsx","ContextInsightsPage","tab","setTab","useTabsParam","handleChange","key","Card","jsxs","Typography","ProjectSwitcher","IconBook","Suspense","IconTool","IconRobot","IconExperiment"],"ignoreList":[],"sources":["../../src/pages/ContextInsightsPage.tsx"],"sourcesContent":["/**\n * /context — AI 在拿什么 (v4 IA).\n *\n * Step 3 实施: 3 tabs — 📚 KB 命中 / 🔧 Skill 调用 / 🤖 Agent 委托.\n * Active tab 由 ?tab=kb|skills|agents 驱动 (default kb).\n *\n * 数据 100% 复用现有 API (无后端改动):\n * - KB tab: /api/knowledge/list + /api/insights/agent-board (per-page 聚合)\n * - Skill tab: /api/rules/hit-rate (skills[] + neverTriggered[])\n * - Agent tab: /api/rules/hit-rate (agents[])\n *\n * 覆盖场景: D (KB 命中率) / F (Skill 是否被调用) — spec §3.3 §6 Step 3.\n */\nimport { lazy, Suspense } from 'react'\nimport Card from '@arco-design/web-react/es/Card'\nimport Tabs from '@arco-design/web-react/es/Tabs'\nimport Typography from '@arco-design/web-react/es/Typography'\nimport { IconBook, IconTool, IconRobot, IconExperiment } from '@arco-design/web-react/icon'\nimport { ProjectSwitcher } from '../components/ProjectSwitcher'\nimport { useTabsParam } from '../hooks/useTabsParam'\n\nconst KbHitRateTable = lazy(() => import('../components/context/KbHitRateTable'))\nconst SkillStatsTable = lazy(() => import('../components/context/SkillStatsTable'))\nconst AgentDelegationTable = lazy(() => import('../components/context/AgentDelegationTable'))\nconst SkillsDistillTab = lazy(() => import('../components/distill/SkillsDistillTab'))\n\nconst TabPane = Tabs.TabPane\n\ntype CtxTab = 'kb' | 'skills' | 'agents' | 'distill'\nconst KNOWN: readonly CtxTab[] = ['kb', 'skills', 'agents', 'distill'] as const\n\nfunction PaneFallback() {\n return (\n <div style={{ padding: 24, color: 'var(--color-text-3)', fontSize: 13 }}>\n 加载中…\n </div>\n )\n}\n\nexport default function ContextInsightsPage() {\n const { tab, setTab } = useTabsParam<CtxTab>(KNOWN, 'kb')\n const handleChange = (key: string) => setTab(key as CtxTab)\n\n return (\n <div data-testid=\"context-insights\" data-tab={tab} style={{ padding: 16, display: 'flex', flexDirection: 'column', gap: 12 }}>\n {/* Header */}\n <Card bordered={false} bodyStyle={{ padding: '12px 16px' }} style={{ background: 'var(--color-bg-1)' }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 12, flexWrap: 'wrap' }}>\n <Typography.Title heading={5} style={{ margin: 0 }}>AI 在拿什么</Typography.Title>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n Claude 写代码时调用了哪些 KB / Skill / Agent · 近 7d\n </Typography.Text>\n <div style={{ marginLeft: 'auto' }}>\n <ProjectSwitcher />\n </div>\n </div>\n </Card>\n\n {/* Tabs */}\n <Card bordered bodyStyle={{ padding: 12 }}>\n <Tabs activeTab={tab} onChange={handleChange} type=\"line\">\n <TabPane\n key=\"kb\"\n title={<span><IconBook /> 📚 KB 命中</span>}\n >\n <Suspense fallback={<PaneFallback />}>\n <KbHitRateTable />\n </Suspense>\n </TabPane>\n <TabPane\n key=\"skills\"\n title={<span><IconTool /> 🔧 Skill 调用</span>}\n >\n <Suspense fallback={<PaneFallback />}>\n <SkillStatsTable />\n </Suspense>\n </TabPane>\n <TabPane\n key=\"agents\"\n title={<span><IconRobot /> 🤖 Agent 委托</span>}\n >\n <Suspense fallback={<PaneFallback />}>\n <AgentDelegationTable />\n </Suspense>\n </TabPane>\n <TabPane\n key=\"distill\"\n title={<span><IconExperiment /> 🧪 蒸馏</span>}\n >\n <Suspense fallback={<PaneFallback />}>\n <SkillsDistillTab />\n </Suspense>\n </TabPane>\n </Tabs>\n </Card>\n </div>\n )\n}\n"],"file":"assets/ContextInsightsPage-oUk7_I8u.js"}
@@ -1,2 +0,0 @@
1
- import{j as e}from"./react-vendor-tkvCrao7.js";import{u as d}from"./query-S6X1S7K9.js";import{c,f as m}from"./index-BIYnq1Dx.js";import{T as a,t as h,S as p,u as n,f as u}from"./arco-Bhi3a6Qp.js";import"./react-router-JVUrkhdd.js";import"./vendor-DWgdB1eY.js";import"./lucide-CnlPQoG8.js";const x={alive:"var(--color-success)",stale:"var(--color-warning)",dead:"var(--color-danger, #f53f3f)"};function y(t){return t==null?"no heartbeat":c(Date.now()-t)}function f(t){return t==null?"—":m(t,{includeSeconds:!0})}function C(){const{data:t,isLoading:s,error:o,refetch:i}=d({queryKey:["daemon-health-page"],queryFn:async()=>{const r=await fetch("/api/health");if(!r.ok)throw new Error(`HTTP ${r.status}`);return r.json()},refetchInterval:15e3,retry:1});return e.jsxs("div",{style:{maxWidth:640,margin:"0 auto"},children:[e.jsxs("div",{style:{marginBottom:16,display:"flex",alignItems:"center",justifyContent:"space-between"},children:[e.jsx(a.Title,{heading:4,style:{margin:0},children:"Daemon Health"}),e.jsx(h,{size:"small",onClick:()=>i(),children:"Refresh"})]}),s&&e.jsx("div",{style:{textAlign:"center",padding:32},children:e.jsx(p,{})}),o&&e.jsx(n,{children:e.jsxs(a.Text,{type:"error",children:["Failed to load health data: ",String(o)]})}),t&&e.jsxs(u,{direction:"vertical",size:16,style:{width:"100%"},children:[e.jsxs(n,{children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,marginBottom:16},children:[e.jsx("span",{style:{width:12,height:12,borderRadius:"50%",background:x[t.daemon.status]??"#999",display:"inline-block"}}),e.jsx(a.Title,{heading:5,style:{margin:0},children:t.daemon.status.toUpperCase()})]}),e.jsx("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:13},children:e.jsx("tbody",{children:[["Status",t.daemon.status],["PID",t.daemon.pid??"—"],["Heartbeat age",y(t.daemon.heartbeat_age_ms)],["Started at",f(t.daemon.started_at)],["Version",t.daemon.version??"—"]].map(([r,l])=>e.jsxs("tr",{style:{borderBottom:"1px solid var(--color-border-2)"},children:[e.jsx("td",{style:{padding:"8px 4px",color:"var(--color-text-3)",width:140},children:r}),e.jsx("td",{style:{padding:"8px 4px",fontFamily:"monospace"},children:String(l)})]},String(r)))})})]}),e.jsx(n,{children:e.jsxs(a.Text,{type:"secondary",style:{fontSize:12},children:["Historical uptime chart — coming in next spec (requires daemon_health table). For now, run ",e.jsx("code",{children:"cf daemon status"})," in your terminal for recent history."]})})]})]})}export{C as default};
2
- //# sourceMappingURL=DaemonHealthPage-DG2fyOP7.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DaemonHealthPage-DG2fyOP7.js","sources":["../../src/pages/DaemonHealthPage.tsx"],"sourcesContent":["/**\n * DaemonHealthPage — placeholder page for /daemon-health.\n *\n * Displays current daemon health JSON and provides a link back.\n * Historical uptime chart is deferred to the next spec (daemon_health table).\n *\n * Spec: docs/design/2026-05-28/0843-daemon-watchdog-spec.md §5 Commit 3 Q4\n */\n\nimport { useQuery } from '@tanstack/react-query'\nimport { Card, Typography, Space, Button, Spin } from '@arco-design/web-react'\nimport { formatLocalDisplay, formatRelative } from '../utils/time'\n\ninterface HealthResponse {\n daemon: {\n status: 'alive' | 'stale' | 'dead'\n pid: number | null\n heartbeat_age_ms: number | null\n started_at: number | null\n version: string | null\n }\n}\n\nconst STATUS_COLORS = {\n alive: 'var(--color-success)',\n stale: 'var(--color-warning)',\n dead: 'var(--color-danger, #f53f3f)',\n}\n\nfunction formatAge(ms: number | null): string {\n if (ms == null) return 'no heartbeat'\n // Convert age-in-ms to a past timestamp, then format relative\n return formatRelative(Date.now() - ms)\n}\n\nfunction formatTs(ts: number | null): string {\n if (ts == null) return '—'\n return formatLocalDisplay(ts, { includeSeconds: true })\n}\n\nexport default function DaemonHealthPage() {\n const { data, isLoading, error, refetch } = useQuery<HealthResponse>({\n queryKey: ['daemon-health-page'],\n queryFn: async () => {\n const res = await fetch('/api/health')\n if (!res.ok) throw new Error(`HTTP ${res.status}`)\n return res.json()\n },\n refetchInterval: 15_000,\n retry: 1,\n })\n\n return (\n <div style={{ maxWidth: 640, margin: '0 auto' }}>\n <div style={{ marginBottom: 16, display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>\n <Typography.Title heading={4} style={{ margin: 0 }}>\n Daemon Health\n </Typography.Title>\n <Button size=\"small\" onClick={() => refetch()}>\n Refresh\n </Button>\n </div>\n\n {isLoading && (\n <div style={{ textAlign: 'center', padding: 32 }}>\n <Spin />\n </div>\n )}\n\n {error && (\n <Card>\n <Typography.Text type=\"error\">\n Failed to load health data: {String(error)}\n </Typography.Text>\n </Card>\n )}\n\n {data && (\n <Space direction=\"vertical\" size={16} style={{ width: '100%' }}>\n <Card>\n <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 16 }}>\n <span\n style={{\n width: 12,\n height: 12,\n borderRadius: '50%',\n background: STATUS_COLORS[data.daemon.status] ?? '#999',\n display: 'inline-block',\n }}\n />\n <Typography.Title heading={5} style={{ margin: 0 }}>\n {data.daemon.status.toUpperCase()}\n </Typography.Title>\n </div>\n\n <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13 }}>\n <tbody>\n {[\n ['Status', data.daemon.status],\n ['PID', data.daemon.pid ?? '—'],\n ['Heartbeat age', formatAge(data.daemon.heartbeat_age_ms)],\n ['Started at', formatTs(data.daemon.started_at)],\n ['Version', data.daemon.version ?? '—'],\n ].map(([label, value]) => (\n <tr key={String(label)} style={{ borderBottom: '1px solid var(--color-border-2)' }}>\n <td style={{ padding: '8px 4px', color: 'var(--color-text-3)', width: 140 }}>\n {label}\n </td>\n <td style={{ padding: '8px 4px', fontFamily: 'monospace' }}>\n {String(value)}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </Card>\n\n <Card>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n Historical uptime chart — coming in next spec (requires daemon_health table).\n For now, run <code>cf daemon status</code> in your terminal for recent history.\n </Typography.Text>\n </Card>\n </Space>\n )}\n </div>\n )\n}\n"],"names":["STATUS_COLORS","formatAge","ms","formatRelative","formatTs","ts","formatLocalDisplay","DaemonHealthPage","data","isLoading","error","refetch","useQuery","res","jsxs","jsx","Typography","Button","Spin","Card","Space","label","value"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{r as x,j as e}from"./react-vendor-tkvCrao7.js";import{b,u as f,c as S,k as C}from"./query-S6X1S7K9.js";import{T as i,b as l,f as g,t as y,u as I,d as w,X as F,E as v,R as c,U as L,O as _}from"./arco-Bhi3a6Qp.js";import"./vendor-DWgdB1eY.js";async function D(s){const t=new URLSearchParams({limit:"50"});s!=="all"&&t.set("status",s);const a=await fetch(`/api/decisions?${t.toString()}`);if(!a.ok)throw new Error(`API ${a.status}`);return a.json()}async function P(s){const t=await fetch(`/api/decisions/${s}`);if(!t.ok)throw new Error(`API ${t.status}`);return t.json()}async function $(s){const t=await fetch(`/api/decisions/${s}/approve`,{method:"POST"});if(!t.ok)throw new Error(`API ${t.status}`);return t.json()}function T(s){return s==="pending"?e.jsx(l,{color:"orange",size:"small",children:"pending"}):s==="resolved"?e.jsx(l,{color:"green",size:"small",children:"resolved"}):s==="bypassed"?e.jsx(l,{color:"gray",size:"small",children:"bypassed"}):e.jsx(l,{color:"red",size:"small",children:"expired"})}function j(s){if(!s)return[];try{const t=JSON.parse(s);return Array.isArray(t)?t:[]}catch{return[]}}function O(s){try{return new Date(s.includes("T")?s:s.replace(" ","T")+"Z").toISOString().slice(0,16).replace("T"," ")}catch{return s}}function Q(){const[s,t]=x.useState("all"),[a,d]=x.useState(null),h=b(),{data:n,isLoading:o}=f({queryKey:["decisions-list",s],queryFn:()=>D(s),placeholderData:C,refetchInterval:3e4}),{data:p,isLoading:k}=f({queryKey:["decisions-detail",a],queryFn:()=>P(a),enabled:!!a}),m=S({mutationFn:r=>$(r),onSuccess:()=>{_.success("决策已批准"),h.invalidateQueries({queryKey:["decisions-list"]}),h.invalidateQueries({queryKey:["decisions-detail"]})},onError:r=>_.error(`批准失败: ${r.message}`)}),z=x.useMemo(()=>[{title:"id",dataIndex:"id",width:110,render:r=>e.jsx(i.Text,{style:{fontFamily:"monospace",fontSize:12},children:r})},{title:"状态",dataIndex:"status",width:100,render:r=>T(r)},{title:"workflow",dataIndex:"workflow_type",width:110,render:r=>e.jsx(l,{size:"small",children:r})},{title:"trigger_prompt",dataIndex:"trigger_prompt",ellipsis:!0,render:r=>r.length>80?e.jsxs("span",{title:r,children:[r.slice(0,80),e.jsx("span",{style:{color:"var(--color-text-3)"},children:"…"})]}):r},{title:"推荐 agents",dataIndex:"recommended_agents",width:200,render:r=>r?r.split(",").map(u=>e.jsx(l,{size:"small",color:"arcoblue",children:u.trim()},u.trim())):e.jsx("span",{style:{color:"var(--color-text-3)"},children:"—"})},{title:"创建时间",dataIndex:"created_at",width:150,render:r=>e.jsx("span",{style:{fontSize:12},children:O(r)})},{title:"操作",dataIndex:"id",width:200,render:(r,u)=>e.jsxs(g,{size:"small",children:[e.jsx(y,{size:"mini",onClick:()=>d(r),children:"查看"}),u.status==="pending"&&e.jsx(y,{type:"primary",size:"mini",loading:m.isPending&&m.variables===r,onClick:()=>m.mutate(r),children:"批准"})]})}],[m]);return e.jsxs("div",{style:{padding:0},children:[e.jsx(I,{bordered:!0,title:"决策记录",extra:e.jsxs(c.Group,{type:"button",size:"small",value:s,onChange:r=>t(r),children:[e.jsx(c,{value:"all",children:"全部"}),e.jsx(c,{value:"pending",children:"待批准"}),e.jsx(c,{value:"resolved",children:"已批准"}),e.jsx(c,{value:"bypassed",children:"已 bypass"}),e.jsx(c,{value:"expired",children:"过期"})]}),style:{marginBottom:16},children:o?e.jsx(w,{animation:!0}):n&&n.length>0?e.jsx(F,{data:n,columns:z,rowKey:"id",pagination:{pageSize:20,showTotal:!0},size:"small"}):e.jsx(v,{description:"暂无决策"})}),e.jsx(L,{title:p?`决策 #${p.id}`:"决策详情",visible:!!a,onCancel:()=>d(null),onOk:()=>d(null),width:640,footer:null,children:k?e.jsx(w,{animation:!0}):p?e.jsx(q,{detail:p,onApprove:()=>m.mutate(p.id)}):e.jsx(v,{description:"未找到决策"})})]})}function q({detail:s,onApprove:t}){const a=j(s.options_json),d=j(s.risks_json),h=j(s.open_questions_json);return e.jsxs("div",{children:[e.jsx("div",{style:{marginBottom:12},children:e.jsxs(g,{size:"small",children:[T(s.status),e.jsx(l,{size:"small",children:s.workflow_type}),s.status==="pending"&&e.jsx(y,{type:"primary",size:"small",onClick:t,children:"批准"})]})}),e.jsx(i.Title,{heading:6,children:"Trigger prompt"}),e.jsx(i.Paragraph,{style:{background:"var(--color-fill-1)",padding:8,borderRadius:4},children:s.trigger_prompt}),s.recommendation&&e.jsxs(e.Fragment,{children:[e.jsx(i.Title,{heading:6,children:"推荐"}),e.jsx(i.Paragraph,{children:s.recommendation})]}),a.length>0&&e.jsxs(e.Fragment,{children:[e.jsx(i.Title,{heading:6,children:"Options"}),e.jsx("ul",{style:{paddingLeft:18},children:a.map((n,o)=>e.jsxs("li",{children:[e.jsx("strong",{children:n.name??`Option ${o+1}`}),n.loc?` — LOC ${n.loc}`:"",n.risk?` — risk ${n.risk}`:""]},o))})]}),d.length>0&&e.jsxs(e.Fragment,{children:[e.jsx(i.Title,{heading:6,children:"Risks"}),e.jsx("ul",{style:{paddingLeft:18},children:d.map((n,o)=>e.jsx("li",{children:n},o))})]}),h.length>0&&e.jsxs(e.Fragment,{children:[e.jsx(i.Title,{heading:6,children:"Open Questions"}),e.jsx("ul",{style:{paddingLeft:18},children:h.map((n,o)=>e.jsx("li",{children:n},o))})]}),s.recommended_agents&&e.jsxs(e.Fragment,{children:[e.jsx(i.Title,{heading:6,children:"推荐 agents"}),e.jsx(g,{size:"small",wrap:!0,children:s.recommended_agents.split(",").map(n=>e.jsx(l,{color:"arcoblue",children:n.trim()},n.trim()))})]}),s.recommended_skills&&e.jsxs(e.Fragment,{children:[e.jsx(i.Title,{heading:6,style:{marginTop:12},children:"推荐 skills"}),e.jsx(g,{size:"small",wrap:!0,children:s.recommended_skills.split(",").map(n=>e.jsx(l,{color:"cyan",children:n.trim()},n.trim()))})]}),s.related_spawns.length>0&&e.jsxs(e.Fragment,{children:[e.jsxs(i.Title,{heading:6,style:{marginTop:12},children:["关联 spawn (",s.related_spawns.length,")"]}),e.jsx("ul",{style:{paddingLeft:18},children:s.related_spawns.map(n=>e.jsxs("li",{children:[n.routed_to_name??"(unknown)"," — ts=",new Date(n.ts).toISOString().slice(0,19),n.obeyed===1?" ✅":n.obeyed===0?" ❌":" ⏳"]},n.id))})]}),(s.related_changelogs??[]).length>0&&e.jsxs(e.Fragment,{children:[e.jsxs(i.Title,{heading:6,style:{marginTop:12},children:["关联 changelog (",(s.related_changelogs??[]).length,")"]}),e.jsx("ul",{style:{paddingLeft:18,fontFamily:"monospace",fontSize:12},children:(s.related_changelogs??[]).map(n=>e.jsx("li",{children:n},n))})]}),s.decision_doc_path&&e.jsxs(i.Paragraph,{style:{marginTop:12,fontSize:12,color:"var(--color-text-3)"},children:["Decision doc: ",e.jsx("code",{children:s.decision_doc_path})]})]})}export{Q as default};
2
- //# sourceMappingURL=DecisionsPage-CMAPEnKb.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DecisionsPage-CMAPEnKb.js","sources":["../../src/pages/DecisionsPage.tsx"],"sourcesContent":["/**\n * /decisions — 决策列表 + 详情 (spec 1527 Commit 4).\n *\n * 端到端 pipeline 第 ⑤ 步: 让用户在 Web 上看到 decision-maker 产出的决策,\n * 一键 Approve,并查看关联 spawn / changelog (来自 routing_events.decision_id\n * 回填 + best-effort docs/implementation 文件名匹配).\n *\n * Q3 (spec 1527 Open Questions): read + approve only — 不让用户在 Web 上编辑\n * recommendation / options_json. 想改 → 走 cf decisions update CLI.\n *\n * 数据源:\n * - GET /api/decisions?limit=50&status=...\n * - GET /api/decisions/:id (含 related_spawns + related_changelogs)\n * - POST /api/decisions/:id/approve\n */\n\nimport { useMemo, useState } from 'react'\nimport { useQuery, useMutation, useQueryClient, keepPreviousData } from '@tanstack/react-query'\nimport Card from '@arco-design/web-react/es/Card'\nimport Table from '@arco-design/web-react/es/Table'\nimport Tag from '@arco-design/web-react/es/Tag'\nimport Button from '@arco-design/web-react/es/Button'\nimport Drawer from '@arco-design/web-react/es/Drawer'\nimport Typography from '@arco-design/web-react/es/Typography'\nimport Skeleton from '@arco-design/web-react/es/Skeleton'\nimport Empty from '@arco-design/web-react/es/Empty'\nimport Message from '@arco-design/web-react/es/Message'\nimport Radio from '@arco-design/web-react/es/Radio'\nimport Space from '@arco-design/web-react/es/Space'\n\n// ─── Types (mirror /api/decisions response shape) ────────────────────────\n\ninterface DecisionRow {\n id: string\n session_id: string\n project_path: string\n trigger_prompt: string\n workflow_type: string\n suggested_agent: string | null\n status: 'pending' | 'resolved' | 'bypassed' | 'expired'\n options_json: string | null\n recommendation: string | null\n risks_json: string | null\n open_questions_json: string | null\n decision_doc_path: string | null\n recommended_agents: string | null\n recommended_skills: string | null\n approved_at: string | null\n approved_by: string | null\n created_at: string\n expires_at: string\n}\n\ninterface RelatedSpawn {\n id: number\n routed_to_name: string | null\n ts: number\n obeyed: number | null\n}\n\ninterface DecisionDetail extends DecisionRow {\n related_spawns: RelatedSpawn[]\n spawn_count: number\n related_changelogs?: string[]\n}\n\ntype StatusFilter = 'all' | 'pending' | 'resolved' | 'bypassed' | 'expired'\n\n// ─── API helpers ─────────────────────────────────────────────────────────\n\nasync function fetchList(status: StatusFilter): Promise<DecisionRow[]> {\n const params = new URLSearchParams({ limit: '50' })\n if (status !== 'all') params.set('status', status)\n const res = await fetch(`/api/decisions?${params.toString()}`)\n if (!res.ok) throw new Error(`API ${res.status}`)\n return res.json()\n}\n\nasync function fetchDetail(id: string): Promise<DecisionDetail> {\n const res = await fetch(`/api/decisions/${id}`)\n if (!res.ok) throw new Error(`API ${res.status}`)\n return res.json()\n}\n\nasync function postApprove(id: string): Promise<{ ok: boolean; status?: string }> {\n const res = await fetch(`/api/decisions/${id}/approve`, { method: 'POST' })\n if (!res.ok) throw new Error(`API ${res.status}`)\n return res.json()\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────\n\nfunction statusTag(s: DecisionRow['status']) {\n if (s === 'pending') return <Tag color=\"orange\" size=\"small\">pending</Tag>\n if (s === 'resolved') return <Tag color=\"green\" size=\"small\">resolved</Tag>\n if (s === 'bypassed') return <Tag color=\"gray\" size=\"small\">bypassed</Tag>\n return <Tag color=\"red\" size=\"small\">expired</Tag>\n}\n\nfunction safeJsonArr<T>(s: string | null): T[] {\n if (!s) return []\n try {\n const v = JSON.parse(s)\n return Array.isArray(v) ? (v as T[]) : []\n } catch {\n return []\n }\n}\n\nfunction tsLabel(iso: string): string {\n try {\n const d = new Date(iso.includes('T') ? iso : iso.replace(' ', 'T') + 'Z')\n return d.toISOString().slice(0, 16).replace('T', ' ')\n } catch {\n return iso\n }\n}\n\n// ─── Page ────────────────────────────────────────────────────────────────\n\nexport default function DecisionsPage() {\n const [status, setStatus] = useState<StatusFilter>('all')\n const [activeId, setActiveId] = useState<string | null>(null)\n const queryClient = useQueryClient()\n\n const { data: rows, isLoading } = useQuery({\n queryKey: ['decisions-list', status],\n queryFn: () => fetchList(status),\n placeholderData: keepPreviousData,\n refetchInterval: 30_000,\n })\n\n const { data: detail, isLoading: isDetailLoading } = useQuery({\n queryKey: ['decisions-detail', activeId],\n queryFn: () => fetchDetail(activeId!),\n enabled: !!activeId,\n })\n\n const approveMutation = useMutation({\n mutationFn: (id: string) => postApprove(id),\n onSuccess: () => {\n Message.success('决策已批准')\n queryClient.invalidateQueries({ queryKey: ['decisions-list'] })\n queryClient.invalidateQueries({ queryKey: ['decisions-detail'] })\n },\n onError: (err: Error) => Message.error(`批准失败: ${err.message}`),\n })\n\n const columns = useMemo(\n () => [\n {\n title: 'id',\n dataIndex: 'id',\n width: 110,\n render: (id: string) => (\n <Typography.Text style={{ fontFamily: 'monospace', fontSize: 12 }}>{id}</Typography.Text>\n ),\n },\n {\n title: '状态',\n dataIndex: 'status',\n width: 100,\n render: (s: DecisionRow['status']) => statusTag(s),\n },\n {\n title: 'workflow',\n dataIndex: 'workflow_type',\n width: 110,\n render: (w: string) => <Tag size=\"small\">{w}</Tag>,\n },\n {\n title: 'trigger_prompt',\n dataIndex: 'trigger_prompt',\n ellipsis: true,\n render: (p: string) =>\n p.length > 80 ? (\n <span title={p}>\n {p.slice(0, 80)}\n <span style={{ color: 'var(--color-text-3)' }}>…</span>\n </span>\n ) : (\n p\n ),\n },\n {\n title: '推荐 agents',\n dataIndex: 'recommended_agents',\n width: 200,\n render: (a: string | null) =>\n a ? a.split(',').map((x) => <Tag key={x.trim()} size=\"small\" color=\"arcoblue\">{x.trim()}</Tag>) : (\n <span style={{ color: 'var(--color-text-3)' }}>—</span>\n ),\n },\n {\n title: '创建时间',\n dataIndex: 'created_at',\n width: 150,\n render: (t: string) => <span style={{ fontSize: 12 }}>{tsLabel(t)}</span>,\n },\n {\n title: '操作',\n dataIndex: 'id',\n width: 200,\n render: (id: string, row: DecisionRow) => (\n <Space size=\"small\">\n <Button size=\"mini\" onClick={() => setActiveId(id)}>\n 查看\n </Button>\n {row.status === 'pending' && (\n <Button\n type=\"primary\"\n size=\"mini\"\n loading={approveMutation.isPending && approveMutation.variables === id}\n onClick={() => approveMutation.mutate(id)}\n >\n 批准\n </Button>\n )}\n </Space>\n ),\n },\n ],\n [approveMutation],\n )\n\n return (\n <div style={{ padding: 0 }}>\n <Card\n bordered\n title=\"决策记录\"\n extra={\n <Radio.Group\n type=\"button\"\n size=\"small\"\n value={status}\n onChange={(v) => setStatus(v as StatusFilter)}\n >\n <Radio value=\"all\">全部</Radio>\n <Radio value=\"pending\">待批准</Radio>\n <Radio value=\"resolved\">已批准</Radio>\n <Radio value=\"bypassed\">已 bypass</Radio>\n <Radio value=\"expired\">过期</Radio>\n </Radio.Group>\n }\n style={{ marginBottom: 16 }}\n >\n {isLoading ? (\n <Skeleton animation />\n ) : rows && rows.length > 0 ? (\n <Table\n data={rows}\n columns={columns as never}\n rowKey=\"id\"\n pagination={{ pageSize: 20, showTotal: true }}\n size=\"small\"\n />\n ) : (\n <Empty description=\"暂无决策\" />\n )}\n </Card>\n\n <Drawer\n title={detail ? `决策 #${detail.id}` : '决策详情'}\n visible={!!activeId}\n onCancel={() => setActiveId(null)}\n onOk={() => setActiveId(null)}\n width={640}\n footer={null}\n >\n {isDetailLoading ? (\n <Skeleton animation />\n ) : detail ? (\n <DecisionDetailView detail={detail} onApprove={() => approveMutation.mutate(detail.id)} />\n ) : (\n <Empty description=\"未找到决策\" />\n )}\n </Drawer>\n </div>\n )\n}\n\n// ─── Detail view (read-only per Q3) ──────────────────────────────────────\n\nfunction DecisionDetailView({\n detail,\n onApprove,\n}: {\n detail: DecisionDetail\n onApprove: () => void\n}) {\n const options = safeJsonArr<{ name?: string; risk?: string; loc?: string }>(detail.options_json)\n const risks = safeJsonArr<string>(detail.risks_json)\n const oqs = safeJsonArr<string>(detail.open_questions_json)\n\n return (\n <div>\n <div style={{ marginBottom: 12 }}>\n <Space size=\"small\">\n {statusTag(detail.status)}\n <Tag size=\"small\">{detail.workflow_type}</Tag>\n {detail.status === 'pending' && (\n <Button type=\"primary\" size=\"small\" onClick={onApprove}>\n 批准\n </Button>\n )}\n </Space>\n </div>\n\n <Typography.Title heading={6}>Trigger prompt</Typography.Title>\n <Typography.Paragraph style={{ background: 'var(--color-fill-1)', padding: 8, borderRadius: 4 }}>\n {detail.trigger_prompt}\n </Typography.Paragraph>\n\n {detail.recommendation && (\n <>\n <Typography.Title heading={6}>推荐</Typography.Title>\n <Typography.Paragraph>{detail.recommendation}</Typography.Paragraph>\n </>\n )}\n\n {options.length > 0 && (\n <>\n <Typography.Title heading={6}>Options</Typography.Title>\n <ul style={{ paddingLeft: 18 }}>\n {options.map((o, i) => (\n <li key={i}>\n <strong>{o.name ?? `Option ${i + 1}`}</strong>\n {o.loc ? ` — LOC ${o.loc}` : ''}\n {o.risk ? ` — risk ${o.risk}` : ''}\n </li>\n ))}\n </ul>\n </>\n )}\n\n {risks.length > 0 && (\n <>\n <Typography.Title heading={6}>Risks</Typography.Title>\n <ul style={{ paddingLeft: 18 }}>\n {risks.map((r, i) => (\n <li key={i}>{r}</li>\n ))}\n </ul>\n </>\n )}\n\n {oqs.length > 0 && (\n <>\n <Typography.Title heading={6}>Open Questions</Typography.Title>\n <ul style={{ paddingLeft: 18 }}>\n {oqs.map((q, i) => (\n <li key={i}>{q}</li>\n ))}\n </ul>\n </>\n )}\n\n {detail.recommended_agents && (\n <>\n <Typography.Title heading={6}>推荐 agents</Typography.Title>\n <Space size=\"small\" wrap>\n {detail.recommended_agents.split(',').map((a) => (\n <Tag key={a.trim()} color=\"arcoblue\">\n {a.trim()}\n </Tag>\n ))}\n </Space>\n </>\n )}\n\n {detail.recommended_skills && (\n <>\n <Typography.Title heading={6} style={{ marginTop: 12 }}>\n 推荐 skills\n </Typography.Title>\n <Space size=\"small\" wrap>\n {detail.recommended_skills.split(',').map((s) => (\n <Tag key={s.trim()} color=\"cyan\">\n {s.trim()}\n </Tag>\n ))}\n </Space>\n </>\n )}\n\n {detail.related_spawns.length > 0 && (\n <>\n <Typography.Title heading={6} style={{ marginTop: 12 }}>\n 关联 spawn ({detail.related_spawns.length})\n </Typography.Title>\n <ul style={{ paddingLeft: 18 }}>\n {detail.related_spawns.map((s) => (\n <li key={s.id}>\n {s.routed_to_name ?? '(unknown)'} — ts={new Date(s.ts).toISOString().slice(0, 19)}\n {s.obeyed === 1 ? ' ✅' : s.obeyed === 0 ? ' ❌' : ' ⏳'}\n </li>\n ))}\n </ul>\n </>\n )}\n\n {(detail.related_changelogs ?? []).length > 0 && (\n <>\n <Typography.Title heading={6} style={{ marginTop: 12 }}>\n 关联 changelog ({(detail.related_changelogs ?? []).length})\n </Typography.Title>\n <ul style={{ paddingLeft: 18, fontFamily: 'monospace', fontSize: 12 }}>\n {(detail.related_changelogs ?? []).map((p) => (\n <li key={p}>{p}</li>\n ))}\n </ul>\n </>\n )}\n\n {detail.decision_doc_path && (\n <Typography.Paragraph style={{ marginTop: 12, fontSize: 12, color: 'var(--color-text-3)' }}>\n Decision doc: <code>{detail.decision_doc_path}</code>\n </Typography.Paragraph>\n )}\n </div>\n )\n}\n"],"names":["fetchList","status","params","res","fetchDetail","id","postApprove","statusTag","jsx","Tag","safeJsonArr","v","tsLabel","iso","DecisionsPage","setStatus","useState","activeId","setActiveId","queryClient","useQueryClient","rows","isLoading","useQuery","keepPreviousData","detail","isDetailLoading","approveMutation","useMutation","Message","err","columns","useMemo","Typography","s","w","p","jsxs","a","x","t","row","Space","Button","Card","Radio","Skeleton","Table","Empty","Drawer","DecisionDetailView","onApprove","options","risks","oqs","Fragment","o","i","r","q"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{r as g,j as e}from"./react-vendor-tkvCrao7.js";import{b as k,u as z,c as P}from"./query-S6X1S7K9.js";import{a as A}from"./auth-Bnf8ZcqN.js";import{T as s,f as m,t as j,u as r,S as _,b,K as F,ah as S}from"./arco-Bhi3a6Qp.js";import"./vendor-DWgdB1eY.js";const O={pass:"green",warn:"orange",fail:"red",skip:"gray"};function d({label:c,value:h,color:a}){return e.jsxs(r,{style:{minWidth:120,textAlign:"center"},bodyStyle:{padding:12},children:[e.jsx(s.Text,{type:"secondary",style:{fontSize:12},children:c}),e.jsx("div",{style:{fontSize:24,fontWeight:600,color:a??"inherit",marginTop:4},children:h})]})}function q(){var u;const c=k(),[h,a]=g.useState(!1),[n,T]=g.useState(null),{data:i,isLoading:w,error:f,refetch:v}=z({queryKey:["diagnostics-page"],queryFn:async()=>{const t=await fetch("/api/diagnostics?refresh=1");if(!t.ok)throw new Error(`HTTP ${t.status}`);return t.json()},refetchInterval:3e4,retry:1}),p=P({mutationFn:async()=>{const t=await A("/api/diagnostics/fix",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({confirm:!0})});if(!t.ok){const y=await t.json().catch(()=>null);throw new Error((y==null?void 0:y.message)??`HTTP ${t.status}`)}return t.json()},onSuccess:t=>{T(t),S.success({content:t.ok?"Fixes applied":"Some fixes failed (see output)"}),c.invalidateQueries({queryKey:["diagnostics-page"]}),c.invalidateQueries({queryKey:["diagnostics-badge"]})},onError:t=>{S.error({content:`Fix failed: ${String(t)}`})}}),l=(i==null?void 0:i.checks.filter(t=>t.fixable_by==="cf fix"&&t.status!=="pass"&&t.status!=="skip"))??[],o=((u=i==null?void 0:i.meta)==null?void 0:u.current_project_path)??null,x=!o,C=l.length===0||p.isPending||x;return e.jsxs("div",{style:{maxWidth:920,margin:"0 auto",paddingBottom:32},children:[e.jsxs("div",{style:{marginBottom:16,display:"flex",alignItems:"center",justifyContent:"space-between"},children:[e.jsx(s.Title,{heading:4,style:{margin:0},children:"诊断"}),e.jsxs(m,{children:[e.jsx(j,{size:"small",onClick:()=>v(),children:"刷新"}),e.jsx(j,{size:"small",type:"primary",status:"warning",disabled:C,onClick:()=>a(!0),children:x?"无项目上下文":l.length===0?"无可修复项":`一键修复 (${l.length})`})]})]}),i&&e.jsx(r,{style:{marginBottom:16,borderLeft:`4px solid ${x?"#f53f3f":"#3491fa"}`},bodyStyle:{padding:12},children:o?e.jsxs(s.Text,{children:[e.jsx(s.Text,{type:"secondary",style:{marginRight:8},children:"当前项目:"}),e.jsx(s.Text,{code:!0,children:o}),e.jsx(s.Text,{type:"secondary",style:{marginLeft:8,fontSize:12},children:"(最近活跃)"})]}):e.jsx(s.Text,{type:"warning",children:"尚无项目活动 — 在某个项目目录下打开 Claude Code 让 daemon 记录事件后,项目级检查 (5/6) 与一键修复才会启用。"})}),w&&e.jsx("div",{style:{textAlign:"center",padding:32},children:e.jsx(_,{})}),f&&e.jsx(r,{children:e.jsxs(s.Text,{type:"error",children:["加载诊断失败: ",String(f)]})}),i&&e.jsxs(m,{direction:"vertical",size:16,style:{width:"100%"},children:[e.jsxs("div",{style:{display:"flex",gap:12,flexWrap:"wrap"},children:[e.jsx(d,{label:"PASS",value:i.summary.pass,color:"#00b42a"}),e.jsx(d,{label:"WARN",value:i.summary.warn,color:"#ff7d00"}),e.jsx(d,{label:"FAIL",value:i.summary.fail,color:"#f53f3f"}),e.jsx(d,{label:"SKIP",value:i.summary.skip,color:"#86909c"}),e.jsx(d,{label:"可自动修复",value:i.summary.fixable,color:"#3491fa"})]}),e.jsx(r,{title:"9 项检查",children:e.jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:13},children:[e.jsx("thead",{children:e.jsxs("tr",{style:{background:"var(--color-fill-1)"},children:[e.jsx("th",{style:{padding:8,textAlign:"left",width:60},children:"#"}),e.jsx("th",{style:{padding:8,textAlign:"left",width:80},children:"状态"}),e.jsx("th",{style:{padding:8,textAlign:"left",width:180},children:"检查项"}),e.jsx("th",{style:{padding:8,textAlign:"left"},children:"详情"})]})}),e.jsx("tbody",{children:i.checks.map(t=>e.jsxs("tr",{style:{borderBottom:"1px solid var(--color-border-2)"},children:[e.jsx("td",{style:{padding:8,fontFamily:"monospace"},children:t.id}),e.jsx("td",{style:{padding:8},children:e.jsx(b,{color:O[t.status],children:t.status.toUpperCase()})}),e.jsx("td",{style:{padding:8,fontFamily:"monospace"},children:t.name}),e.jsxs("td",{style:{padding:8},children:[e.jsx("div",{children:t.message}),t.details&&e.jsx("div",{style:{fontSize:12,color:"var(--color-text-3)",marginTop:4},children:t.details}),t.fix_hint&&(t.status==="warn"||t.status==="fail")&&e.jsxs("div",{style:{marginTop:4,fontSize:12},children:[e.jsx(s.Text,{code:!0,children:t.fix_hint}),t.fixable_by==="cf fix"&&e.jsx(b,{color:"cyan",size:"small",style:{marginLeft:6},children:"fixable"})]})]})]},t.id))})]})}),n&&e.jsxs(r,{title:`修复结果 (exit ${n.exit_code})`,children:[e.jsx(s.Paragraph,{code:!0,children:n.command}),n.cwd&&e.jsxs(s.Paragraph,{type:"secondary",style:{fontSize:12,marginTop:-8},children:["cwd: ",e.jsx(s.Text,{code:!0,children:n.cwd})]}),n.stdout&&e.jsx("pre",{style:{fontSize:12,whiteSpace:"pre-wrap",background:"var(--color-fill-1)",padding:8,borderRadius:4},children:n.stdout}),n.stderr&&e.jsx("pre",{style:{fontSize:12,whiteSpace:"pre-wrap",color:"#f53f3f",background:"var(--color-fill-1)",padding:8,borderRadius:4},children:n.stderr})]}),e.jsx(r,{children:e.jsxs(s.Text,{type:"secondary",style:{fontSize:12},children:["生成时间: ",i.generated_at]})})]}),e.jsxs(F,{title:"确认自动修复",visible:h,onCancel:()=>a(!1),onOk:()=>{a(!1),p.mutate()},okText:"确认运行",cancelText:"取消",okButtonProps:{status:"warning",loading:p.isPending,disabled:x},children:[o?e.jsxs(r,{style:{marginBottom:12,background:"var(--color-fill-1)"},bodyStyle:{padding:12},children:[e.jsx(s.Text,{type:"secondary",style:{fontSize:12},children:"将在以下目录执行:"}),e.jsx("div",{style:{marginTop:4},children:e.jsx(s.Text,{code:!0,style:{fontSize:13},children:o})})]}):e.jsx(s.Text,{type:"error",children:"没有可用的项目上下文 — 修复被阻止以免污染 daemon 目录。"}),e.jsxs(s.Paragraph,{children:["以下 ",l.length," 项将通过 ",e.jsx(s.Text,{code:!0,children:"cf fix --apply --yes"})," 自动修复:"]}),e.jsx("ul",{style:{paddingLeft:20},children:l.map(t=>e.jsxs("li",{style:{marginBottom:4},children:["#",t.id," ",t.name," → ",e.jsx(s.Text,{code:!0,children:t.fix_hint})]},t.id))})]})]})}export{q as default};
2
- //# sourceMappingURL=DiagnosticsPage-DQd-Zm4r.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DiagnosticsPage-DQd-Zm4r.js","sources":["../../src/pages/DiagnosticsPage.tsx"],"sourcesContent":["/**\n * DiagnosticsPage — `/diagnostics` view.\n *\n * Renders the 9-check doctor report + a one-click \"Run all auto-fixes\" button.\n * The fix button opens a confirm modal listing planned commands before\n * POSTing to /api/diagnostics/fix with `{ confirm: true }`.\n *\n * Spec: docs/design/2026-06-01/1030-cf-doctor-diagnostic-spec.md\n */\n\nimport { useState } from 'react'\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport {\n Button,\n Card,\n Modal,\n Notification,\n Space,\n Spin,\n Tag,\n Typography,\n} from '@arco-design/web-react'\nimport { authFetch } from '../utils/auth'\n\ntype Status = 'pass' | 'warn' | 'fail' | 'skip'\n\ninterface CheckResult {\n id: number\n name: string\n status: Status\n message: string\n details?: string\n fix_hint?: string\n fixable_by?: 'cf fix' | 'manual'\n}\n\ninterface DiagnosticsMeta {\n current_project_path: string | null\n project_source: 'recent-event' | 'none'\n}\n\ninterface DiagnosticsResponse {\n summary: { pass: number; warn: number; fail: number; skip: number; fixable: number }\n checks: CheckResult[]\n generated_at: string\n /** spec e5b845c4: project resolved by the server (most-recent or null). */\n meta?: DiagnosticsMeta\n}\n\ninterface FixResponse {\n ok: boolean\n exit_code: number | null\n stdout: string\n stderr: string\n command: string\n /** spec e5b845c4: cwd actually used by the spawned `cf fix`. */\n cwd?: string\n}\n\nconst STATUS_COLOR: Record<Status, string> = {\n pass: 'green',\n warn: 'orange',\n fail: 'red',\n skip: 'gray',\n}\n\nfunction SummaryCard({ label, value, color }: { label: string; value: number; color?: string }) {\n return (\n <Card style={{ minWidth: 120, textAlign: 'center' }} bodyStyle={{ padding: 12 }}>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>{label}</Typography.Text>\n <div style={{ fontSize: 24, fontWeight: 600, color: color ?? 'inherit', marginTop: 4 }}>\n {value}\n </div>\n </Card>\n )\n}\n\nexport default function DiagnosticsPage() {\n const qc = useQueryClient()\n const [modalOpen, setModalOpen] = useState(false)\n const [fixOutput, setFixOutput] = useState<FixResponse | null>(null)\n\n const { data, isLoading, error, refetch } = useQuery<DiagnosticsResponse>({\n queryKey: ['diagnostics-page'],\n queryFn: async () => {\n const res = await fetch('/api/diagnostics?refresh=1')\n if (!res.ok) throw new Error(`HTTP ${res.status}`)\n return res.json()\n },\n refetchInterval: 30_000,\n retry: 1,\n })\n\n const fixMutation = useMutation<FixResponse>({\n mutationFn: async () => {\n const res = await authFetch('/api/diagnostics/fix', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ confirm: true }),\n })\n if (!res.ok) {\n const body = (await res.json().catch(() => null)) as { message?: string } | null\n throw new Error(body?.message ?? `HTTP ${res.status}`)\n }\n return res.json()\n },\n onSuccess: (out) => {\n setFixOutput(out)\n Notification.success({ content: out.ok ? 'Fixes applied' : 'Some fixes failed (see output)' })\n qc.invalidateQueries({ queryKey: ['diagnostics-page'] })\n qc.invalidateQueries({ queryKey: ['diagnostics-badge'] })\n },\n onError: (err) => {\n Notification.error({ content: `Fix failed: ${String(err)}` })\n },\n })\n\n const fixable = data?.checks.filter((c) => c.fixable_by === 'cf fix' && c.status !== 'pass' && c.status !== 'skip') ?? []\n const projectPath = data?.meta?.current_project_path ?? null\n const noProject = !projectPath\n const fixDisabled = fixable.length === 0 || fixMutation.isPending || noProject\n\n return (\n <div style={{ maxWidth: 920, margin: '0 auto', paddingBottom: 32 }}>\n <div style={{ marginBottom: 16, display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>\n <Typography.Title heading={4} style={{ margin: 0 }}>诊断</Typography.Title>\n <Space>\n <Button size=\"small\" onClick={() => refetch()}>刷新</Button>\n <Button\n size=\"small\"\n type=\"primary\"\n status=\"warning\"\n disabled={fixDisabled}\n onClick={() => setModalOpen(true)}\n >\n {noProject\n ? '无项目上下文'\n : fixable.length === 0\n ? '无可修复项'\n : `一键修复 (${fixable.length})`}\n </Button>\n </Space>\n </div>\n\n {/* spec e5b845c4: surface the project that the server picked. */}\n {data && (\n <Card\n style={{\n marginBottom: 16,\n borderLeft: `4px solid ${noProject ? '#f53f3f' : '#3491fa'}`,\n }}\n bodyStyle={{ padding: 12 }}\n >\n {projectPath ? (\n <Typography.Text>\n <Typography.Text type=\"secondary\" style={{ marginRight: 8 }}>当前项目:</Typography.Text>\n <Typography.Text code>{projectPath}</Typography.Text>\n <Typography.Text type=\"secondary\" style={{ marginLeft: 8, fontSize: 12 }}>\n (最近活跃)\n </Typography.Text>\n </Typography.Text>\n ) : (\n <Typography.Text type=\"warning\">\n 尚无项目活动 — 在某个项目目录下打开 Claude Code 让 daemon 记录事件后,项目级检查 (5/6) 与一键修复才会启用。\n </Typography.Text>\n )}\n </Card>\n )}\n\n {isLoading && (\n <div style={{ textAlign: 'center', padding: 32 }}><Spin /></div>\n )}\n {error && (\n <Card>\n <Typography.Text type=\"error\">加载诊断失败: {String(error)}</Typography.Text>\n </Card>\n )}\n\n {data && (\n <Space direction=\"vertical\" size={16} style={{ width: '100%' }}>\n <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap' }}>\n <SummaryCard label=\"PASS\" value={data.summary.pass} color=\"#00b42a\" />\n <SummaryCard label=\"WARN\" value={data.summary.warn} color=\"#ff7d00\" />\n <SummaryCard label=\"FAIL\" value={data.summary.fail} color=\"#f53f3f\" />\n <SummaryCard label=\"SKIP\" value={data.summary.skip} color=\"#86909c\" />\n <SummaryCard label=\"可自动修复\" value={data.summary.fixable} color=\"#3491fa\" />\n </div>\n\n <Card title=\"9 项检查\">\n <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13 }}>\n <thead>\n <tr style={{ background: 'var(--color-fill-1)' }}>\n <th style={{ padding: 8, textAlign: 'left', width: 60 }}>#</th>\n <th style={{ padding: 8, textAlign: 'left', width: 80 }}>状态</th>\n <th style={{ padding: 8, textAlign: 'left', width: 180 }}>检查项</th>\n <th style={{ padding: 8, textAlign: 'left' }}>详情</th>\n </tr>\n </thead>\n <tbody>\n {data.checks.map((c) => (\n <tr key={c.id} style={{ borderBottom: '1px solid var(--color-border-2)' }}>\n <td style={{ padding: 8, fontFamily: 'monospace' }}>{c.id}</td>\n <td style={{ padding: 8 }}><Tag color={STATUS_COLOR[c.status]}>{c.status.toUpperCase()}</Tag></td>\n <td style={{ padding: 8, fontFamily: 'monospace' }}>{c.name}</td>\n <td style={{ padding: 8 }}>\n <div>{c.message}</div>\n {c.details && (\n <div style={{ fontSize: 12, color: 'var(--color-text-3)', marginTop: 4 }}>{c.details}</div>\n )}\n {c.fix_hint && (c.status === 'warn' || c.status === 'fail') && (\n <div style={{ marginTop: 4, fontSize: 12 }}>\n <Typography.Text code>{c.fix_hint}</Typography.Text>\n {c.fixable_by === 'cf fix' && (\n <Tag color=\"cyan\" size=\"small\" style={{ marginLeft: 6 }}>fixable</Tag>\n )}\n </div>\n )}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </Card>\n\n {fixOutput && (\n <Card title={`修复结果 (exit ${fixOutput.exit_code})`}>\n <Typography.Paragraph code>{fixOutput.command}</Typography.Paragraph>\n {fixOutput.cwd && (\n <Typography.Paragraph type=\"secondary\" style={{ fontSize: 12, marginTop: -8 }}>\n cwd: <Typography.Text code>{fixOutput.cwd}</Typography.Text>\n </Typography.Paragraph>\n )}\n {fixOutput.stdout && (\n <pre style={{ fontSize: 12, whiteSpace: 'pre-wrap', background: 'var(--color-fill-1)', padding: 8, borderRadius: 4 }}>\n {fixOutput.stdout}\n </pre>\n )}\n {fixOutput.stderr && (\n <pre style={{ fontSize: 12, whiteSpace: 'pre-wrap', color: '#f53f3f', background: 'var(--color-fill-1)', padding: 8, borderRadius: 4 }}>\n {fixOutput.stderr}\n </pre>\n )}\n </Card>\n )}\n\n <Card>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n 生成时间: {data.generated_at}\n </Typography.Text>\n </Card>\n </Space>\n )}\n\n <Modal\n title=\"确认自动修复\"\n visible={modalOpen}\n onCancel={() => setModalOpen(false)}\n onOk={() => {\n setModalOpen(false)\n fixMutation.mutate()\n }}\n okText=\"确认运行\"\n cancelText=\"取消\"\n okButtonProps={{\n status: 'warning',\n loading: fixMutation.isPending,\n disabled: noProject,\n }}\n >\n {/* spec e5b845c4 OQ#4: P0 safety — always show target cwd so user\n can verify before letting `cf project init` write to disk. */}\n {projectPath ? (\n <Card\n style={{ marginBottom: 12, background: 'var(--color-fill-1)' }}\n bodyStyle={{ padding: 12 }}\n >\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n 将在以下目录执行:\n </Typography.Text>\n <div style={{ marginTop: 4 }}>\n <Typography.Text code style={{ fontSize: 13 }}>{projectPath}</Typography.Text>\n </div>\n </Card>\n ) : (\n <Typography.Text type=\"error\">\n 没有可用的项目上下文 — 修复被阻止以免污染 daemon 目录。\n </Typography.Text>\n )}\n <Typography.Paragraph>\n 以下 {fixable.length} 项将通过 <Typography.Text code>cf fix --apply --yes</Typography.Text> 自动修复:\n </Typography.Paragraph>\n <ul style={{ paddingLeft: 20 }}>\n {fixable.map((c) => (\n <li key={c.id} style={{ marginBottom: 4 }}>\n #{c.id} {c.name} → <Typography.Text code>{c.fix_hint}</Typography.Text>\n </li>\n ))}\n </ul>\n </Modal>\n </div>\n )\n}\n"],"names":["STATUS_COLOR","SummaryCard","label","value","color","jsxs","Card","jsx","Typography","DiagnosticsPage","qc","useQueryClient","modalOpen","setModalOpen","useState","fixOutput","setFixOutput","data","isLoading","error","refetch","useQuery","res","fixMutation","useMutation","authFetch","body","out","Notification","err","fixable","c","projectPath","_a","noProject","fixDisabled","Space","Button","Spin","Tag","Modal"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{j as e}from"./react-vendor-tkvCrao7.js";import{u as c}from"./query-S6X1S7K9.js";import{d as x,E as d,T as s,b as i,X as p}from"./arco-Bhi3a6Qp.js";import"./vendor-DWgdB1eY.js";const f={pass:"green",warn:"orange",fail:"red"},u={pass:"通过",warn:"警告",fail:"失败"};async function y(){const r=await fetch("/api/drift/report?days=7");if(!r.ok)throw{status:r.status,message:`HTTP ${r.status}`};return r.json()}function m(r){return typeof r=="object"&&r!==null&&"message"in r}function S(){const{data:r,isLoading:l,error:n}=c({queryKey:["drift-report-7d"],queryFn:y,staleTime:3e5});if(l)return e.jsx(x,{animation:!0,text:{rows:8}});if(n){const t=m(n)?n:{message:String(n)},o=t.status?`HTTP ${t.status} — `:"";return e.jsx(d,{description:e.jsxs("span",{children:[e.jsx(s.Text,{type:"error",children:"Drift 报表暂不可用"}),e.jsx("br",{}),e.jsxs(s.Text,{type:"secondary",style:{fontSize:12},children:[o,t.message]})]})})}if(!r)return e.jsx(d,{description:"无数据",imgSrc:""});const a=r.checks.reduce((t,o)=>(t[o.status]+=1,t),{pass:0,warn:0,fail:0});return e.jsxs("div",{children:[e.jsxs(s.Title,{heading:6,style:{marginBottom:4},children:["CLAUDE.md 行为漂移报表 (近 ",r.period.days," 天)"]}),e.jsxs(s.Paragraph,{type:"secondary",style:{fontSize:13,marginBottom:12},children:["来源 ",e.jsx("code",{children:"/api/drift/report"}),". 比对 CLAUDE.md 声明的规则与实际事件流。"]}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:16,marginBottom:16,padding:"12px 16px",background:"var(--color-fill-2)",borderRadius:4,flexWrap:"wrap"},"data-testid":"drift-summary",children:[e.jsxs("div",{children:[e.jsx(s.Text,{type:"secondary",style:{fontSize:12},children:"合规分"}),e.jsxs("div",{style:{fontSize:24,fontWeight:600,fontVariantNumeric:"tabular-nums"},children:[r.overallScore,e.jsx(s.Text,{type:"secondary",style:{fontSize:12,marginLeft:4},children:"/100"})]})]}),e.jsxs("div",{style:{display:"flex",gap:8},children:[e.jsxs(i,{color:"green",children:["通过 ",a.pass]}),e.jsxs(i,{color:"orange",children:["警告 ",a.warn]}),e.jsxs(i,{color:"red",children:["失败 ",a.fail]})]})]}),r.checks.length===0?e.jsx(d,{description:"无检查项",imgSrc:""}):e.jsx(p,{data:r.checks,rowKey:"rule",pagination:!1,borderCell:!0,size:"small",columns:[{title:"规则",dataIndex:"rule",width:180,render:t=>e.jsx("strong",{style:{fontSize:13},children:t})},{title:"状态",dataIndex:"status",width:100,render:t=>e.jsx(i,{color:f[t],children:u[t]})},{title:"期望",dataIndex:"expected",render:t=>e.jsx(s.Text,{style:{fontSize:12},children:t})},{title:"实际",dataIndex:"actual",render:t=>e.jsx(s.Text,{style:{fontSize:12},children:t})},{title:"说明",dataIndex:"detail",render:t=>t?e.jsx(s.Text,{type:"secondary",style:{fontSize:12},children:t}):e.jsx("span",{style:{color:"var(--color-text-4)"},children:"—"})}]})]})}export{S as default};
2
- //# sourceMappingURL=DriftTab-DqpepOhI.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DriftTab-DqpepOhI.js","sources":["../../src/components/resources/DriftTab.tsx"],"sourcesContent":["/**\n * DriftTab — /violations?tab=drift (C-4 rework).\n *\n * Surfaces /api/drift/report as an Arco Table over `checks[]` instead of the\n * previous raw JSON wall. Each row is one declarative rule from\n * DriftDetector: { rule, expected, actual, status, detail? }.\n *\n * Header strip shows overallScore + counts per status (pass/warn/fail) so the\n * user can scan compliance at a glance.\n *\n * Error path now surfaces the HTTP status explicitly (was silently swallowing\n * 404s as `String(error)` rendered \"Error: HTTP 404\" with no context).\n *\n * See: tests/unit/web/routes-drift.test.ts for the locked response contract.\n */\nimport { useQuery } from '@tanstack/react-query'\nimport Skeleton from '@arco-design/web-react/es/Skeleton'\nimport Typography from '@arco-design/web-react/es/Typography'\nimport Empty from '@arco-design/web-react/es/Empty'\nimport Table from '@arco-design/web-react/es/Table'\nimport Tag from '@arco-design/web-react/es/Tag'\n\ninterface DriftCheck {\n rule: string\n expected: string\n actual: string\n status: 'pass' | 'warn' | 'fail'\n detail?: string\n}\ninterface DriftReport {\n generatedAt: string\n period: { days: number; since: string }\n checks: DriftCheck[]\n overallScore: number\n}\n\nconst STATUS_COLOR: Record<DriftCheck['status'], string> = {\n pass: 'green',\n warn: 'orange',\n fail: 'red',\n}\n\nconst STATUS_LABEL: Record<DriftCheck['status'], string> = {\n pass: '通过',\n warn: '警告',\n fail: '失败',\n}\n\ninterface ApiError {\n status?: number\n message: string\n}\n\nasync function fetchDrift(): Promise<DriftReport> {\n const r = await fetch('/api/drift/report?days=7')\n if (!r.ok) {\n const err: ApiError = { status: r.status, message: `HTTP ${r.status}` }\n throw err\n }\n return r.json()\n}\n\nfunction isApiError(e: unknown): e is ApiError {\n return typeof e === 'object' && e !== null && 'message' in e\n}\n\nexport default function DriftTab() {\n const { data, isLoading, error } = useQuery<DriftReport>({\n queryKey: ['drift-report-7d'],\n queryFn: fetchDrift,\n staleTime: 5 * 60_000,\n })\n\n if (isLoading) return <Skeleton animation text={{ rows: 8 }} />\n\n if (error) {\n const apiErr: ApiError = isApiError(error) ? error : { message: String(error) }\n const statusPrefix = apiErr.status ? `HTTP ${apiErr.status} — ` : ''\n return (\n <Empty\n description={\n <span>\n <Typography.Text type=\"error\">Drift 报表暂不可用</Typography.Text>\n <br />\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n {statusPrefix}\n {apiErr.message}\n </Typography.Text>\n </span>\n }\n />\n )\n }\n\n if (!data) return <Empty description=\"无数据\" imgSrc=\"\" />\n\n const counts = data.checks.reduce(\n (acc, c) => {\n acc[c.status] += 1\n return acc\n },\n { pass: 0, warn: 0, fail: 0 } as Record<DriftCheck['status'], number>,\n )\n\n return (\n <div>\n <Typography.Title heading={6} style={{ marginBottom: 4 }}>\n CLAUDE.md 行为漂移报表 (近 {data.period.days} 天)\n </Typography.Title>\n <Typography.Paragraph type=\"secondary\" style={{ fontSize: 13, marginBottom: 12 }}>\n 来源 <code>/api/drift/report</code>. 比对 CLAUDE.md 声明的规则与实际事件流。\n </Typography.Paragraph>\n\n {/* Header strip: overall score + status counts */}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 16,\n marginBottom: 16,\n padding: '12px 16px',\n background: 'var(--color-fill-2)',\n borderRadius: 4,\n flexWrap: 'wrap',\n }}\n data-testid=\"drift-summary\"\n >\n <div>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>合规分</Typography.Text>\n <div style={{ fontSize: 24, fontWeight: 600, fontVariantNumeric: 'tabular-nums' }}>\n {data.overallScore}\n <Typography.Text type=\"secondary\" style={{ fontSize: 12, marginLeft: 4 }}>/100</Typography.Text>\n </div>\n </div>\n <div style={{ display: 'flex', gap: 8 }}>\n <Tag color=\"green\">通过 {counts.pass}</Tag>\n <Tag color=\"orange\">警告 {counts.warn}</Tag>\n <Tag color=\"red\">失败 {counts.fail}</Tag>\n </div>\n </div>\n\n {data.checks.length === 0 ? (\n <Empty description=\"无检查项\" imgSrc=\"\" />\n ) : (\n <Table\n data={data.checks}\n rowKey=\"rule\"\n pagination={false}\n borderCell\n size=\"small\"\n columns={[\n {\n title: '规则',\n dataIndex: 'rule',\n width: 180,\n render: (val: string) => <strong style={{ fontSize: 13 }}>{val}</strong>,\n },\n {\n title: '状态',\n dataIndex: 'status',\n width: 100,\n render: (val: DriftCheck['status']) => (\n <Tag color={STATUS_COLOR[val]}>{STATUS_LABEL[val]}</Tag>\n ),\n },\n {\n title: '期望',\n dataIndex: 'expected',\n render: (val: string) => (\n <Typography.Text style={{ fontSize: 12 }}>{val}</Typography.Text>\n ),\n },\n {\n title: '实际',\n dataIndex: 'actual',\n render: (val: string) => (\n <Typography.Text style={{ fontSize: 12 }}>{val}</Typography.Text>\n ),\n },\n {\n title: '说明',\n dataIndex: 'detail',\n render: (val?: string) =>\n val ? (\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>{val}</Typography.Text>\n ) : (\n <span style={{ color: 'var(--color-text-4)' }}>—</span>\n ),\n },\n ]}\n />\n )}\n </div>\n )\n}\n"],"names":["STATUS_COLOR","STATUS_LABEL","fetchDrift","isApiError","e","DriftTab","data","isLoading","error","useQuery","jsx","Skeleton","apiErr","statusPrefix","Empty","Typography","jsxs","counts","acc","c","Tag","Table","val"],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- import{r as h,j as e}from"./react-vendor-tkvCrao7.js";import{d as Ve,u as qe}from"./react-router-JVUrkhdd.js";import{u as T}from"./query-S6X1S7K9.js";import{e as Ge,G as Ie,R as Ye,t as Qe,d as $,E as Xe,b as ye,T as Ze}from"./arco-Bhi3a6Qp.js";import{R as V,A as Re,T as q,a as E,P as Je,b as et,C as tt,L as ze,c as nt,d as Te,X as De,Y as Ae,e as ot,f as st}from"./charts-BuHQWDbQ.js";import{O as I,a as C}from"./outcome-DUn1NjlC.js";import{p as je}from"./index-BIYnq1Dx.js";import"./vendor-DWgdB1eY.js";import"./lucide-CnlPQoG8.js";const it="#52c41a",at="#f5222d",rt="#86909c";function lt(t,n,c,o=""){const i=t-n;if(i===0)return{text:"vs 上周 0 →",color:rt};const a=i>0?"↑":"↓",g=(c?i<0:i>0)?at:it,l=i>0?"+":"",f=Number.isInteger(i)?`${i}`:i.toFixed(1);return{text:`vs 上周 ${l}${f}${o} ${a}`,color:g}}function ct({label:t,value:n,sparkData:c,sparkColor:o="#1890ff",thisVal:i,prevVal:a,higherIsBetter:u,suffix:g="",tooltip:l,onClick:f}){const x=lt(i,a,u,g),b=c.map((j,_)=>({i:_,v:j})),p=`spark-grad-${t.replace(/\s+/g,"-")}-${o.replace("#","")}`;return e.jsxs("div",{onClick:f,style:{background:"#fff",borderRadius:8,boxShadow:"0 1px 3px rgba(0,0,0,0.05)",padding:20,cursor:f?"pointer":"default",height:"100%",display:"flex",flexDirection:"column",gap:8,transition:"box-shadow 0.15s"},onMouseEnter:j=>{f&&(j.currentTarget.style.boxShadow="0 2px 8px rgba(0,0,0,0.10)")},onMouseLeave:j=>{f&&(j.currentTarget.style.boxShadow="0 1px 3px rgba(0,0,0,0.05)")},children:[e.jsxs("div",{style:{fontSize:12,color:"#86909c",fontWeight:500,display:"flex",alignItems:"center",gap:4},children:[e.jsx("span",{children:t}),l?e.jsx(Ge,{content:l,position:"top",children:e.jsx("span",{"aria-label":"explain",style:{cursor:"help",fontSize:11,color:"#86909c",border:"1px solid var(--color-border-2)",borderRadius:"50%",width:14,height:14,lineHeight:"12px",textAlign:"center",display:"inline-block"},onClick:j=>j.stopPropagation(),children:"?"})}):null]}),e.jsx("div",{style:{fontSize:32,fontWeight:600,color:"#1d2129",lineHeight:1.1,fontVariantNumeric:"tabular-nums"},children:n}),e.jsx("div",{style:{height:40,marginTop:2},children:b.length>0&&e.jsx(V,{width:"100%",height:"100%",children:e.jsxs(Re,{data:b,margin:{top:2,right:0,left:0,bottom:0},children:[e.jsx("defs",{children:e.jsxs("linearGradient",{id:p,x1:"0",y1:"0",x2:"0",y2:"1",children:[e.jsx("stop",{offset:"0%",stopColor:o,stopOpacity:.35}),e.jsx("stop",{offset:"100%",stopColor:o,stopOpacity:.02})]})}),e.jsx(q,{cursor:!1,contentStyle:{fontSize:11,padding:"4px 8px",borderRadius:4},formatter:j=>[`${j}${g}`,t],labelFormatter:()=>""}),e.jsx(E,{type:"monotone",dataKey:"v",stroke:o,strokeWidth:1.5,fill:`url(#${p})`,isAnimationActive:!1})]})})}),e.jsx("div",{style:{fontSize:11,color:x.color,fontWeight:500,fontVariantNumeric:"tabular-nums"},children:x.text})]})}const P=h.memo(ct);function dt({success:t,partial:n,failed:c,abandoned:o,height:i=240}){const a=t+n+c+o,u=a>0?Math.round(t/a*1e3)/10:0,g=[{name:I.success,value:t,key:"success"},{name:I.partial,value:n,key:"partial"},{name:I.failed,value:c,key:"failed"},{name:I.abandoned,value:o,key:"abandoned"}].filter(l=>l.value>0);return a===0?e.jsx("div",{style:{height:i,display:"flex",alignItems:"center",justifyContent:"center",color:"#86909c",fontSize:13},children:"近期无已分类任务数据"}):e.jsxs("div",{style:{position:"relative",height:i},children:[e.jsx(V,{width:"100%",height:"100%",children:e.jsxs(Je,{children:[e.jsx(et,{data:g,dataKey:"value",nameKey:"name",cx:"50%",cy:"50%",innerRadius:"60%",outerRadius:"85%",paddingAngle:2,stroke:"none",isAnimationActive:!1,children:g.map(l=>e.jsx(tt,{fill:C[l.key]},l.key))}),e.jsx(q,{contentStyle:{fontSize:12,padding:"6px 10px",borderRadius:4},formatter:(l,f)=>{const x=typeof l=="number"?l:Number(l)||0,b=a>0?Math.round(x/a*100):0;return[`${x} (${b}%)`,String(f)]}}),e.jsx(ze,{verticalAlign:"bottom",iconType:"circle",iconSize:8,wrapperStyle:{fontSize:11}})]})}),e.jsxs("div",{style:{position:"absolute",inset:0,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",pointerEvents:"none",paddingBottom:24},children:[e.jsx("div",{style:{fontSize:28,fontWeight:600,color:"#1d2129",lineHeight:1.1,fontVariantNumeric:"tabular-nums"},children:a}),e.jsxs("div",{style:{fontSize:11,color:"#86909c",marginTop:2},children:["总任务 · 成功率"," ",e.jsxs("span",{style:{color:"#52c41a",fontWeight:600},children:[u,"%"]})]})]})]})}const ut=h.memo(dt),be="#1890ff",we="#52c41a",ft="#f5222d",W="#86909c";function ht(t,n){let c=0;for(let o=t.length-1;o>=0;o--){const i=t[o].value;if(i==null)break;if(i<n)c++;else break}return c}function pt({title:t,subtitle:n,data:c,currentValue:o,target:i,height:a=240}){const u=ht(c,i),g=u>=3,l=c.some(f=>f.value!=null);return e.jsxs("div",{style:{background:"#fff",borderRadius:8,boxShadow:"0 1px 3px rgba(0,0,0,0.05)",padding:20,height:"100%",display:"flex",flexDirection:"column"},children:[e.jsx("div",{style:{fontSize:14,fontWeight:600,color:"#1d2129"},children:t}),n&&e.jsx("div",{style:{fontSize:12,color:W,marginTop:2},children:n}),e.jsxs("div",{style:{display:"flex",alignItems:"baseline",gap:12,marginTop:8,marginBottom:4},children:[e.jsx("div",{style:{fontSize:32,fontWeight:600,color:"#1d2129",lineHeight:1.1,fontVariantNumeric:"tabular-nums"},children:o==null?"--":`${o}%`}),e.jsxs("div",{style:{fontSize:12,color:W},children:["目标 ",i,"%"]}),g&&e.jsxs("div",{style:{fontSize:11,color:ft,fontWeight:500},children:["连续 ",u," 天低于目标"]})]}),e.jsx("div",{style:{flex:1,minHeight:a},children:l?e.jsx(V,{width:"100%",height:a,children:e.jsxs(nt,{data:c,margin:{top:8,right:16,left:0,bottom:0},children:[e.jsx(Te,{strokeDasharray:"3 3",stroke:"#f0f0f0"}),e.jsx(De,{dataKey:"date",fontSize:11,stroke:W}),e.jsx(Ae,{domain:[0,100],fontSize:11,stroke:W,tickFormatter:f=>`${f}%`}),e.jsx(q,{contentStyle:{fontSize:12,borderRadius:4},formatter:f=>[f==null?"--":`${f}%`,t]}),e.jsx(ot,{y:i,stroke:we,strokeDasharray:"4 4",label:{value:`目标 ${i}%`,position:"right",fontSize:10,fill:we}}),e.jsx(st,{type:"monotone",dataKey:"value",stroke:be,strokeWidth:2,dot:{r:3,fill:be},activeDot:{r:5},connectNulls:!1,isAnimationActive:!1})]})}):e.jsxs("div",{style:{height:a,display:"flex",alignItems:"center",justifyContent:"center",color:W,fontSize:13},children:["近 ",c.length," 天无数据"]})})]})}const ve=h.memo(pt),mt="#1890ff",M="#86909c",xt="#fafafa";function gt(t,n){return t<=0||n<=0?"#ffffff":`rgba(24, 144, 255, ${(.1+.85*Math.min(1,t/n)).toFixed(3)})`}function yt({rows:t,dateLabels:n,title:c="KB 命中热力图",subtitle:o}){const[i,a]=h.useState(null),u=h.useMemo(()=>{let l=0;for(const f of t)for(const x of f.days)x>l&&(l=x);return l},[t]),g=u>0;return e.jsxs("div",{style:{background:"#fff",borderRadius:8,boxShadow:"0 1px 3px rgba(0,0,0,0.05)",padding:20,height:"100%",display:"flex",flexDirection:"column"},children:[e.jsx("div",{style:{fontSize:14,fontWeight:600,color:"#1d2129"},children:c}),e.jsx("div",{style:{fontSize:12,color:M,marginTop:2,marginBottom:12},children:o||`Top ${t.length} pages · 近 ${n.length} 天`}),g?e.jsxs(e.Fragment,{children:[e.jsx("div",{style:{flex:1,overflow:"hidden"},children:e.jsxs("table",{style:{width:"100%",borderCollapse:"separate",borderSpacing:2,fontSize:11,tableLayout:"fixed"},children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{style:{textAlign:"left",color:M,fontWeight:500,paddingRight:6,width:"38%"},children:"page"}),n.map(l=>e.jsx("th",{style:{color:M,fontWeight:500,textAlign:"center"},children:l},l)),e.jsx("th",{style:{color:M,fontWeight:500,textAlign:"right",paddingLeft:6,width:"12%"},children:"total"})]})}),e.jsx("tbody",{children:t.map(l=>{const f=l.total===0;return e.jsxs("tr",{style:{background:f?xt:"transparent"},children:[e.jsx("td",{title:l.name,style:{fontFamily:"monospace",color:f?M:"#1d2129",paddingRight:6,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:l.name}),l.days.map((x,b)=>e.jsx("td",{onMouseEnter:()=>a({row:l.name,col:b,v:x}),onMouseLeave:()=>a(null),style:{background:gt(x,u),height:22,borderRadius:3,cursor:"default",textAlign:"center",color:x/u>.55?"#fff":"#1d2129",fontVariantNumeric:"tabular-nums"},children:x>0?x:""},b)),e.jsx("td",{style:{textAlign:"right",paddingLeft:6,fontWeight:600,fontVariantNumeric:"tabular-nums",color:f?M:"#1d2129"},children:l.total})]},l.name)})})]})}),e.jsxs("div",{style:{marginTop:12,display:"flex",alignItems:"center",justifyContent:"space-between",fontSize:11,color:M},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6},children:[e.jsx("span",{children:"少"}),[.15,.35,.55,.75,.95].map(l=>e.jsx("span",{style:{display:"inline-block",width:14,height:14,borderRadius:3,background:`rgba(24, 144, 255, ${l})`}},l)),e.jsxs("span",{children:["多 (max=",u,")"]})]}),e.jsx("div",{style:{minHeight:14},children:i&&e.jsxs("span",{children:[e.jsx("span",{style:{fontFamily:"monospace",color:"#1d2129"},children:i.row})," · ",n[i.col]," · ",e.jsxs("span",{style:{color:mt,fontWeight:600},children:[i.v," hits"]})]})})]})]}):e.jsxs("div",{style:{height:240,display:"flex",alignItems:"center",justifyContent:"center",color:M,fontSize:13},children:["近 ",n.length," 天无 KB 命中数据"]})]})}const jt=h.memo(yt),bt="#52c41a",wt="#faad14",Be="#f5222d",te="#86909c",vt="#f0f0f0";function kt(t){return t>=.8?bt:t>=.6?wt:Be}function St({rows:t,title:n="Skill 调用 Top 10",subtitle:c}){const o=[...t].sort((a,u)=>u.invocations-a.invocations).slice(0,10),i=o.reduce((a,u)=>Math.max(a,u.invocations),0);return e.jsxs("div",{style:{background:"#fff",borderRadius:8,boxShadow:"0 1px 3px rgba(0,0,0,0.05)",padding:20,height:"100%",display:"flex",flexDirection:"column"},children:[e.jsx("div",{style:{fontSize:14,fontWeight:600,color:"#1d2129"},children:n}),e.jsx("div",{style:{fontSize:12,color:te,marginTop:2,marginBottom:12},children:c||"按调用次数倒排 · 颜色=成功率"}),o.length===0?e.jsx("div",{style:{height:240,display:"flex",alignItems:"center",justifyContent:"center",color:te,fontSize:13},children:"近期无 Skill 调用数据"}):e.jsx("div",{style:{flex:1,display:"flex",flexDirection:"column",gap:6},children:o.map(a=>{const u=i>0?a.invocations/i*100:0,g=kt(a.success_rate),l=(a.zero_result_rate??0)>=.3;return e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,fontSize:12},children:[e.jsx("div",{title:a.skill_id,style:{width:"32%",fontFamily:"monospace",color:"#1d2129",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:a.skill_id}),e.jsx("div",{style:{flex:1,position:"relative",height:18,background:vt,borderRadius:3},children:e.jsx("div",{style:{position:"absolute",left:0,top:0,bottom:0,width:`${u}%`,background:g,borderRadius:3,transition:"width 0.2s"}})}),e.jsxs("div",{style:{width:110,textAlign:"right",fontVariantNumeric:"tabular-nums",color:te},children:[e.jsx("span",{style:{color:"#1d2129",fontWeight:600},children:a.invocations})," · ",e.jsxs("span",{style:{color:g},children:[Math.round(a.success_rate*100),"%"]})]}),l&&e.jsx("div",{style:{fontSize:10,color:Be,fontWeight:500,whiteSpace:"nowrap"},children:"⚠ 0 命中率高"})]},a.skill_id)})})]})}const _t=h.memo(St),F="#86909c",Ct="#52c41a",$t="#f5222d",Mt="#f0f0f0";function It(t,n){return t.total<=0||n<=0?Mt:t.failed/t.total>.3?`rgba(245, 34, 45, ${(.3+.65*Math.min(1,t.total/n)).toFixed(3)})`:`rgba(82, 196, 26, ${(.2+.75*Math.min(1,t.total/n)).toFixed(3)})`}function Rt(t){if(t.length===0)return[];const n=[],c=(new Date(t[0].date).getDay()+6)%7;let o=Array(7).fill(null);for(let a=0;a<c;a++)o[a]=null;let i=c;for(const a of t)o[i]=a,i++,i===7&&(n.push(o),o=Array(7).fill(null),i=0);return i!==0&&n.push(o),n}const zt=["一","二","三","四","五","六","日"];function Tt({days:t,title:n="近 30 天任务活跃度",subtitle:c}){const[o,i]=h.useState(null),a=h.useMemo(()=>Rt(t),[t]),u=h.useMemo(()=>t.reduce((f,x)=>Math.max(f,x.total),0),[t]),g=h.useMemo(()=>t.reduce((f,x)=>f+x.total,0),[t]),l=u>0;return e.jsxs("div",{style:{background:"#fff",borderRadius:8,boxShadow:"0 1px 3px rgba(0,0,0,0.05)",padding:20,height:"100%",display:"flex",flexDirection:"column"},children:[e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"baseline"},children:[e.jsxs("div",{children:[e.jsx("div",{style:{fontSize:14,fontWeight:600,color:"#1d2129"},children:n}),e.jsx("div",{style:{fontSize:12,color:F,marginTop:2},children:c||`${t.length} 天 · 共 ${g} 个 task · 失败主导日标红`})]}),e.jsxs("div",{style:{fontSize:11,color:F,fontVariantNumeric:"tabular-nums"},children:["max/day ",u]})]}),l?e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:{display:"flex",gap:6,marginTop:16,flex:1},children:[e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:3,paddingTop:0},children:zt.map((f,x)=>e.jsx("div",{style:{fontSize:10,color:F,height:18,lineHeight:"18px",visibility:x%2===0?"visible":"hidden"},children:f},f))}),e.jsx("div",{style:{display:"flex",gap:3,flex:1},children:a.map((f,x)=>e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:3,flex:1},children:f.map((b,p)=>e.jsx("div",{onMouseEnter:()=>b&&i(b),onMouseLeave:()=>i(null),style:{height:18,borderRadius:3,background:b?It(b,u):"transparent",cursor:(b&&b.total>0,"default")}},p))},x))})]}),e.jsxs("div",{style:{marginTop:14,display:"flex",alignItems:"center",justifyContent:"space-between",fontSize:11,color:F},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6},children:[e.jsx("span",{children:"少"}),[.2,.4,.6,.8,.95].map(f=>e.jsx("span",{style:{display:"inline-block",width:14,height:14,borderRadius:3,background:`rgba(82, 196, 26, ${f})`}},f)),e.jsx("span",{children:"多"}),e.jsxs("span",{style:{marginLeft:12,display:"inline-flex",alignItems:"center",gap:4},children:[e.jsx("span",{style:{display:"inline-block",width:14,height:14,borderRadius:3,background:"rgba(245, 34, 45, 0.75)"}}),"失败 > 30%"]})]}),e.jsx("div",{style:{minHeight:14},children:o&&e.jsxs("span",{children:[e.jsx("span",{style:{fontFamily:"monospace",color:"#1d2129"},children:o.date})," · ",e.jsxs("span",{style:{color:"#1d2129",fontWeight:600},children:[o.total," tasks"]})," · ",e.jsxs("span",{style:{color:Ct},children:[o.succeeded," ok"]})," · ",e.jsxs("span",{style:{color:$t},children:[o.failed," fail"]})]})})]})]}):e.jsxs("div",{style:{flex:1,minHeight:200,display:"flex",alignItems:"center",justifyContent:"center",color:F,fontSize:13},children:["近 ",t.length," 天无 task 数据"]})]})}const Dt=h.memo(Tt),ne="#86909c",At="#1890ff",Bt="#faad14",Lt="#f5222d";function Ot(t){const n=t.toLowerCase();return n.includes("hard")||n.includes("deny")?"deny":n.includes("warn")||n.includes("soft")?"warn":"other"}function Wt(t){return t==="deny"?Lt:t==="warn"?Bt:At}function ke(t){return t==="deny"?"deny":t==="warn"?"warn":"mixed"}function Ft({rules:t,title:n="近 7 天拦截规则 Top 10",subtitle:c="PreToolUse 命中分布 — 高频规则可能扰民,需调优"}){const o=t.slice(0,10),i=o.reduce((a,u)=>Math.max(a,u.n),0);return e.jsxs("div",{style:{background:"#fff",borderRadius:8,boxShadow:"0 1px 3px rgba(0,0,0,0.05)",padding:20,height:"100%",display:"flex",flexDirection:"column"},children:[e.jsx("div",{style:{fontSize:14,fontWeight:600,color:"#1d2129"},children:n}),e.jsx("div",{style:{fontSize:12,color:ne,marginTop:2,marginBottom:16},children:c}),o.length===0||i===0?e.jsx("div",{style:{flex:1,minHeight:200,display:"flex",alignItems:"center",justifyContent:"center",color:ne,fontSize:13},children:"无拦截规则命中数据(健康)"}):e.jsx("div",{style:{flex:1,display:"flex",flexDirection:"column",gap:8},children:o.map(a=>{const u=Ot(a.rule_id),g=Wt(u),l=Math.max(2,Math.round(a.n/i*100));return e.jsxs("div",{title:`${a.rule_id} · ${a.n} hits · ${ke(u)}`,children:[e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",fontSize:11,marginBottom:3,color:"#1d2129"},children:[e.jsx("span",{style:{fontFamily:"monospace",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",maxWidth:"70%"},children:a.rule_id}),e.jsxs("span",{style:{fontVariantNumeric:"tabular-nums",color:ne},children:[a.n," hits · ",e.jsx("span",{style:{color:g},children:ke(u)})]})]}),e.jsx("div",{style:{background:"#f0f0f0",borderRadius:3,overflow:"hidden",height:10},children:e.jsx("div",{style:{width:`${l}%`,height:"100%",background:g,borderRadius:3,transition:"width 0.3s"}})})]},a.rule_id)})})]})}const Et=h.memo(Ft),B=Ie.Row,S=Ie.Col,oe="#1890ff",Kt="#f5222d";function H(t,n,c,o){const i=Array(n).fill(0),a=864e5,u=Date.now();for(const g of t){const l=new Date(c(g)).getTime();if(!Number.isFinite(l))continue;const f=n-1-Math.floor((u-l)/a);f>=0&&f<n&&(i[f]+=o(g))}return i}async function Se(t){const n=await fetch(`/api/insights/agent-board?window=${t}`);if(!n.ok)throw new Error(`agent-board ${n.status}`);return n.json()}async function _e(t){const n=await fetch(`/api/insights/tuning?window=${t}`);if(n.status===410)return null;if(!n.ok)throw new Error(`tuning ${n.status}`);return n.json()}async function Ce(t){const n=await fetch(`/api/violations?days=${t}&limit=1`);if(!n.ok)throw new Error(`violations ${n.status}`);const c=await n.json();return{total_in_window:c.total_in_window??0,total_by_signal_in_window:c.total_by_signal_in_window??{routing_disobeyed:0,user_keyword:0,tool_intercept:0}}}async function Ut(t){const n=await fetch(`/api/insights/commit-activity?days=${t}`);if(!n.ok)throw new Error(`commit-activity ${n.status}`);return n.json()}function $e(t){if(!t)return[];const n=[];for(const c of Object.values(t.lanes||{}))n.push(...c);return n}function Nt(t,n){const c=new Map,o=Date.now();for(let i=n-1;i>=0;i--){const a=new Date(o-i*864e5).toISOString().slice(0,10);c.set(a,{success:0,partial:0,failed:0,abandoned:0})}for(const i of t){if(!i.outcome)continue;const a=(i.start_time||"").slice(0,10),u=c.get(a);u&&u[i.outcome]++}return[...c.entries()].map(([i,a])=>({date:i.slice(5),...a}))}function se(t,n=60){return t?t.length>n?`${t.slice(0,n)}…`:t:""}function Me(t,n,c,o){var b;const i=(n==null?void 0:n.summary.session_outcome)??{success:0,partial:0,failed:0,abandoned:0},a=i.success+i.partial+i.failed+i.abandoned,u=t.reduce((p,j)=>{var _,G;return p+(((_=j.intercepts)==null?void 0:_.deny)??0)+(((G=j.intercepts)==null?void 0:G.warn)??0)},0),g=o??u,f=((n==null?void 0:n.summary.skill_top)??[]).filter(p=>p.n===0).map(p=>p.skill_id),x=t.filter(p=>p.outcome==="failed").sort((p,j)=>(j.start_time||"").localeCompare(p.start_time||""));return{total:c??t.length,success:i.success,partial:i.partial,failed:i.failed,abandoned:i.abandoned,classified:a,successRate:a>0?Math.round(i.success/a*1e3)/10:0,failedRate:a>0?Math.round(i.failed/a*1e3)/10:0,kbInjectCount:(n==null?void 0:n.summary.kb_inject_count)??0,workflowAcceptance:(n==null?void 0:n.summary.workflow_acceptance_ratio)??0,interceptObeyed:(n==null?void 0:n.summary.intercept_obeyed_ratio)??0,interceptCount:g,zeroSkillCount:f.length,zeroSkillNames:f,topFailedTitle:((b=x[0])==null?void 0:b.title)??null}}function D(t,n,c){const o=t-n;if(o===0)return{delta:0,arrow:"→",worsened:!1,text:"0"};const i=o>0?"↑":"↓",a=c?o<0:o>0,u=o>0?"+":"";return{delta:o,arrow:i,worsened:a,text:`${u}${Number.isInteger(o)?o:o.toFixed(1)}`}}function Pt(t,n){const c=[],o=Math.round(t.workflowAcceptance*100);c.push(`过去 7 天提交了 ${t.total} 个任务(上周 ${n.total}),编排推荐采纳率 ${o}%。`);const i=t.kbInjectCount>n.kbInjectCount?"✓ 上升":t.kbInjectCount===n.kbInjectCount?"→ 持平":"⚠ 下降",a=t.zeroSkillCount>0?`Skill ${t.zeroSkillNames[0]} 0 触发 ⚠`:"Skill 调用正常 ✓";c.push(`KB 注入 ${t.kbInjectCount} 次(上周 ${n.kbInjectCount})${i};${a}。`);const u=D(t.failed,n.failed,!1),g=t.failed>n.failed?`失败上升,建议关注 "${se(t.topFailedTitle||"失败任务",32)}"`:t.failed<n.failed?"失败下降,状态改善 ✓":"失败与上周持平";return c.push(`失败任务 ${t.failed} 个(上周 ${n.failed})${u.arrow} ${g}。`),c}function Ht(t,n,c,o){var u,g;const a=[`# 整体健康度周报(${new Date().toISOString().slice(0,16).replace("T"," ")})`,"","## TL;DR",...c.map(l=>`- ${l}`),"","## 本周 vs 上周","| 指标 | 本周 | 上周 | Δ |","|---|---|---|---|",`| 总任务 | ${t.total} | ${n.total} | ${D(t.total,n.total,!0).text} |`,`| 成功率 | ${t.successRate}% | ${n.successRate}% | ${D(t.successRate,n.successRate,!0).text}% |`,`| 失败数 | ${t.failed} | ${n.failed} | ${D(t.failed,n.failed,!1).text} |`,`| KB 注入次数 | ${t.kbInjectCount} | ${n.kbInjectCount} | ${D(t.kbInjectCount,n.kbInjectCount,!0).text} |`,`| 编排采纳率 | ${Math.round(t.workflowAcceptance*100)}% | ${Math.round(n.workflowAcceptance*100)}% | ${D(Math.round(t.workflowAcceptance*100),Math.round(n.workflowAcceptance*100),!0).text}% |`,`| 拦截次数 | ${t.interceptCount} | ${n.interceptCount} | ${D(t.interceptCount,n.interceptCount,!0).text} |`,"","## 编排遵守率",`- C4 主线程听劝率:${Math.round(t.interceptObeyed*100)}%`,`- C8 Agent 推荐采纳率:${Math.round(t.workflowAcceptance*100)}%`,""];return(u=o==null?void 0:o.kb_top_pages)!=null&&u.length&&(a.push("## KB Top 5"),o.kb_top_pages.slice(0,5).forEach(l=>a.push(`- ${l.name} — cited ${l.cited}`)),a.push("")),(g=o==null?void 0:o.skill_top)!=null&&g.length&&(a.push("## Skill Top 5"),o.skill_top.slice(0,5).forEach(l=>a.push(`- ${l.skill_id} — n=${l.n}, success=${Math.round((l.success_rate??0)*100)}%`)),a.push("")),a.join(`
2
- `)}function Vt(t,n){const c=new Blob([t],{type:"text/markdown;charset=utf-8"}),o=URL.createObjectURL(c),i=document.createElement("a");i.href=o,i.download=n,document.body.appendChild(i),i.click(),document.body.removeChild(i),URL.revokeObjectURL(o)}function nn(){var me;const[t,n]=Ve(),c=qe(),o=parseInt(t.get("window")||"7",10)===30?30:7,i=o,a=o*2,[u,g]=h.useState(!1);h.useEffect(()=>{const s=setTimeout(()=>g(!0),1e3);return()=>clearTimeout(s)},[]);const{data:l,isLoading:f}=T({queryKey:["hh-board-this",i],queryFn:()=>Se(i),refetchInterval:6e4,refetchIntervalInBackground:!1}),{data:x,isLoading:b}=T({queryKey:["hh-board-long",a],queryFn:()=>Se(a),enabled:u}),{data:p,isLoading:j}=T({queryKey:["hh-tuning-this",i],queryFn:()=>_e(i)}),{data:_,isLoading:G}=T({queryKey:["hh-tuning-long",a],queryFn:()=>_e(a),enabled:u}),{data:R}=T({queryKey:["hh-violations-this",i],queryFn:()=>Ce(i),staleTime:6e4,refetchIntervalInBackground:!1}),{data:L}=T({queryKey:["hh-violations-long",a],queryFn:()=>Ce(a),enabled:u,staleTime:6e4}),ie=R==null?void 0:R.total_by_signal_in_window.tool_intercept,ae=h.useMemo(()=>{if((L==null?void 0:L.total_by_signal_in_window.tool_intercept)==null)return;const s=(R==null?void 0:R.total_by_signal_in_window.tool_intercept)??0;return Math.max(0,L.total_by_signal_in_window.tool_intercept-s)},[L,R]),re=f||j,v=h.useMemo(()=>$e(l),[l]),le=h.useMemo(()=>$e(x),[x]),ce=h.useMemo(()=>Date.now()-i*864e5,[i]),de=h.useMemo(()=>le.filter(s=>je(s.start_time).getTime()<ce),[le,ce]),Y=h.useMemo(()=>{if(!_)return null;if(!p)return _.summary;const s=_.summary,d=p.summary,r=(m,y)=>Math.max(0,m-y);return{...s,kb_inject_count:r(s.kb_inject_count,d.kb_inject_count),session_outcome:{success:r(s.session_outcome.success,d.session_outcome.success),partial:r(s.session_outcome.partial,d.session_outcome.partial),failed:r(s.session_outcome.failed,d.session_outcome.failed),abandoned:r(s.session_outcome.abandoned,d.session_outcome.abandoned),unclassified:r(s.session_outcome.unclassified,d.session_outcome.unclassified)}}},[_,p]),K=l==null?void 0:l.total_in_window,ue=h.useMemo(()=>{if((x==null?void 0:x.total_in_window)!=null)return(l==null?void 0:l.total_in_window)==null?x.total_in_window:Math.max(0,x.total_in_window-l.total_in_window)},[x,l]),w=h.useMemo(()=>Me(v,p??null,K,ie),[v,p,K,ie]),z=h.useMemo(()=>Me(de,Y?{summary:Y}:null,ue,ae),[de,Y,ue,ae]),Q=h.useMemo(()=>Pt(w,z),[w,z]),fe=h.useMemo(()=>Nt(v,o),[v,o]),X=((me=p==null?void 0:p.summary.rule_violations_top)==null?void 0:me.slice(0,5))??[],he=h.useMemo(()=>{const s=v.filter(r=>r.outcome==="failed").sort((r,m)=>(m.start_time||"").localeCompare(r.start_time||"")).slice(0,3).map(r=>({kind:"failed",task_id:r.task_id,label:se(r.title||"(空)",60),detail:"失败"})),d=v.map(r=>{var m,y;return{card:r,total:(((m=r.intercepts)==null?void 0:m.deny)??0)+(((y=r.intercepts)==null?void 0:y.warn)??0)}}).filter(r=>r.total>=5).sort((r,m)=>m.total-r.total).slice(0,3).map(r=>({kind:"intercept",task_id:r.card.task_id,label:se(r.card.title||"(空)",60),detail:`${r.total} 次拦截`}));return[...s,...d].slice(0,5)},[v]),Le=s=>{const d=new URLSearchParams(t);d.set("window",String(s)),n(d,{replace:!0})},Oe=()=>{const s=Ht(w,z,Q,(p==null?void 0:p.summary)??null),d=new Date().toISOString().slice(0,10);Vt(s,`health-weekly-${d}.md`)},U=h.useMemo(()=>H(v,o,s=>s.start_time,()=>1),[v,o]),Z=h.useMemo(()=>{const s=U.reduce((m,y)=>m+y,0),d=K;if(s===0||d==null||d===s)return U;const r=d/s;return U.map(m=>Math.round(m*r))},[U,K]),We=h.useMemo(()=>H(v,o,s=>s.start_time,s=>s.outcome==="failed"?1:0),[v,o]),Fe=h.useMemo(()=>{const s=H(v,o,r=>r.start_time,r=>r.outcome==="success"?1:0),d=H(v,o,r=>r.start_time,r=>r.outcome==="success"||r.outcome==="partial"||r.outcome==="failed"||r.outcome==="abandoned"?1:0);return s.map((r,m)=>d[m]>0?Math.round(r/d[m]*100):0)},[v,o]),Ee=h.useMemo(()=>{const s=w.kbInjectCount;if(s===0)return Array(o).fill(0);const d=s/o,r=Z,m=r.reduce((y,k)=>y+k,0)||1;return r.map(y=>Math.round(y/m*s)||(d>=1?Math.round(d):0))},[w.kbInjectCount,Z,o]),O=h.useMemo(()=>{const s=Date.now(),d=[];for(let r=o-1;r>=0;r--)d.push(new Date(s-r*864e5).toISOString().slice(5,10));return d},[o]),A=h.useMemo(()=>{const s=Array.from({length:o},()=>[]),d=Date.now();for(const r of v){const m=je(r.start_time).getTime();if(!Number.isFinite(m))continue;const y=o-1-Math.floor((d-m)/864e5);y>=0&&y<o&&s[y].push(r)}return s},[v,o]),J=h.useMemo(()=>O.map((s,d)=>{const m=(A[d]||[]).filter(k=>{var xe,ge;return(((xe=k.intercepts)==null?void 0:xe.deny)??0)+(((ge=k.intercepts)==null?void 0:ge.warn)??0)>0});if(m.length===0)return{date:s,value:null};const y=m.filter(k=>k.outcome!=="failed").length;return{date:s,value:Math.round(y/m.length*100)}}),[O,A]),ee=h.useMemo(()=>O.map((s,d)=>{const m=(A[d]||[]).filter(k=>k.outcome==="success"||k.outcome==="partial"||k.outcome==="failed"||k.outcome==="abandoned");if(m.length===0)return{date:s,value:null};const y=m.filter(k=>k.outcome==="success"||k.outcome==="partial").length;return{date:s,value:Math.round(y/m.length*100)}}),[O,A]),Ke=h.useMemo(()=>{const s=[...J].reverse().find(d=>d.value!=null);return(s==null?void 0:s.value)??null},[J]),Ue=h.useMemo(()=>{const s=[...ee].reverse().find(d=>d.value!=null);return(s==null?void 0:s.value)??null},[ee]),pe=h.useMemo(()=>{const s=new Map;A.forEach((d,r)=>{for(const m of d)for(const y of m.kb_pages||[])s.has(y.name)||s.set(y.name,Array(o).fill(0)),s.get(y.name)[r]+=y.cited??0});for(const d of(p==null?void 0:p.summary.kb_top_pages)??[])s.has(d.name)||s.set(d.name,Array(o).fill(0));return[...s.entries()].map(([d,r])=>({name:d,days:r,total:r.reduce((m,y)=>m+y,0)})).sort((d,r)=>r.total-d.total).slice(0,8)},[A,p,o]),Ne=h.useMemo(()=>((p==null?void 0:p.summary.skill_top)??[]).map(s=>({skill_id:s.skill_id,invocations:s.n,success_rate:s.success_rate??0})),[p]),{data:N}=T({queryKey:["hh-commit-activity-30d"],queryFn:()=>Ut(30),staleTime:6e4,refetchIntervalInBackground:!1}),Pe=h.useMemo(()=>{const s=N==null?void 0:N.daily;if(!s){const r=Date.now(),m=[];for(let y=29;y>=0;y--)m.push({date:new Date(r-y*864e5).toISOString().slice(0,10),total:0,succeeded:0,failed:0});return m}return s.map(d=>({date:d.date,total:d.total,succeeded:d.succeeded,failed:d.failed}))},[N]),He=h.useMemo(()=>{var s;return((s=p==null?void 0:p.summary.rule_violations_top)==null?void 0:s.slice(0,10))??[]},[p]);return e.jsxs("div",{style:{padding:24,background:"#fafafa",minHeight:"100%"},children:[e.jsxs(B,{align:"center",justify:"space-between",style:{marginBottom:20},children:[e.jsxs(S,{children:[e.jsx("div",{style:{fontSize:24,fontWeight:600,color:"#1d2129",lineHeight:1.2},children:"整体健康度"}),e.jsxs("div",{style:{fontSize:12,color:"#86909c",marginTop:4},children:["Past ",o," days · 当前项目"]})]}),e.jsx(S,{children:e.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center"},children:[e.jsx(Ye.Group,{type:"button",size:"small",value:o,onChange:s=>Le(s),options:[{label:"近 7 天",value:7},{label:"近 30 天",value:30}]}),e.jsx(Qe,{size:"small",type:"primary",onClick:Oe,disabled:re,children:"导出周报"})]})})]}),e.jsxs(B,{gutter:[16,16],style:{marginBottom:16},children:[e.jsx(S,{xs:24,sm:12,md:6,children:e.jsx(P,{label:"总任务",value:w.total,sparkData:Z,sparkColor:oe,thisVal:w.total,prevVal:z.total,higherIsBetter:!0})}),e.jsx(S,{xs:24,sm:12,md:6,children:e.jsx(P,{label:"成功率",value:`${w.successRate}%`,suffix:"%",sparkData:Fe,sparkColor:oe,thisVal:w.successRate,prevVal:z.successRate,higherIsBetter:!0})}),e.jsx(S,{xs:24,sm:12,md:6,children:e.jsx(P,{label:"失败数",value:w.failed,sparkData:We,sparkColor:Kt,thisVal:w.failed,prevVal:z.failed,higherIsBetter:!1,onClick:()=>c("/tasks?outcome=failed")})}),e.jsx(S,{xs:24,sm:12,md:6,children:e.jsx(P,{label:"≈ KB 注入",value:w.kbInjectCount,sparkData:Ee,sparkColor:oe,thisVal:w.kbInjectCount,prevVal:z.kbInjectCount,higherIsBetter:!0,tooltip:"近似分布:后端只返回窗口总数,前端按每日任务数比例分摊到 sparkline。等待 /api/insights/kb-inject-daily 完整支持。"})})]}),e.jsxs(B,{gutter:[16,16],style:{marginBottom:16},children:[e.jsx(S,{xs:24,md:12,children:e.jsxs("div",{style:{background:"#fff",borderRadius:8,boxShadow:"0 1px 3px rgba(0,0,0,0.05)",padding:20},children:[e.jsxs("div",{style:{fontSize:13,fontWeight:600,color:"#1d2129",marginBottom:12},children:["Outcome ",o,"d 趋势"]}),f?e.jsx("div",{style:{height:240},children:e.jsx($,{animation:!0})}):fe.every(s=>s.success+s.partial+s.failed+s.abandoned===0)?e.jsxs("div",{style:{height:240,display:"flex",alignItems:"center",justifyContent:"center",color:"#86909c",fontSize:13},children:["近 ",o," 天无已分类任务数据"]}):e.jsx(V,{width:"100%",height:240,children:e.jsxs(Re,{data:fe,margin:{top:8,right:16,left:0,bottom:0},children:[e.jsx(Te,{strokeDasharray:"3 3",stroke:"#f0f0f0"}),e.jsx(De,{dataKey:"date",fontSize:11,stroke:"#86909c"}),e.jsx(Ae,{fontSize:11,allowDecimals:!1,stroke:"#86909c"}),e.jsx(q,{contentStyle:{fontSize:12,borderRadius:4}}),e.jsx(ze,{wrapperStyle:{fontSize:11},iconType:"circle"}),e.jsx(E,{type:"monotone",dataKey:"success",stackId:"a",stroke:C.success,fill:C.success,fillOpacity:.6,name:I.success}),e.jsx(E,{type:"monotone",dataKey:"partial",stackId:"a",stroke:C.partial,fill:C.partial,fillOpacity:.6,name:I.partial}),e.jsx(E,{type:"monotone",dataKey:"failed",stackId:"a",stroke:C.failed,fill:C.failed,fillOpacity:.6,name:I.failed}),e.jsx(E,{type:"monotone",dataKey:"abandoned",stackId:"a",stroke:C.abandoned,fill:C.abandoned,fillOpacity:.6,name:I.abandoned})]})})]})}),e.jsx(S,{xs:24,md:12,children:e.jsxs("div",{style:{background:"#fff",borderRadius:8,boxShadow:"0 1px 3px rgba(0,0,0,0.05)",padding:20},children:[e.jsx("div",{style:{fontSize:13,fontWeight:600,color:"#1d2129",marginBottom:12},children:"Outcome 总览"}),j?e.jsx("div",{style:{height:240},children:e.jsx($,{animation:!0})}):e.jsx(ut,{success:w.success,partial:w.partial,failed:w.failed,abandoned:w.abandoned,height:240})]})})]}),e.jsxs(B,{gutter:[16,16],style:{marginBottom:16},children:[e.jsx(S,{xs:24,md:12,children:j?e.jsx("div",{style:{background:"#fff",borderRadius:8,padding:20,boxShadow:"0 1px 3px rgba(0,0,0,0.05)"},children:e.jsx($,{animation:!0})}):e.jsx(ve,{title:"C4 主线程听劝率",subtitle:`近 ${o} 天每日有拦截 task 中未失败比例`,data:J,currentValue:Ke,target:70})}),e.jsx(S,{xs:24,md:12,children:j?e.jsx("div",{style:{background:"#fff",borderRadius:8,padding:20,boxShadow:"0 1px 3px rgba(0,0,0,0.05)"},children:e.jsx($,{animation:!0})}):e.jsx(ve,{title:"C8 Spec 采纳率",subtitle:`近 ${o} 天每日完成 task 中 success+partial 比例`,data:ee,currentValue:Ue,target:60})})]}),e.jsxs(B,{gutter:[16,16],style:{marginBottom:16},children:[e.jsx(S,{xs:24,md:12,children:f?e.jsx("div",{style:{background:"#fff",borderRadius:8,padding:20,boxShadow:"0 1px 3px rgba(0,0,0,0.05)"},children:e.jsx($,{animation:!0})}):e.jsx(jt,{rows:pe,dateLabels:O,title:"KB 命中热力图",subtitle:`Top ${pe.length} pages · 近 ${o} 天 daily 命中`})}),e.jsx(S,{xs:24,md:12,children:j?e.jsx("div",{style:{background:"#fff",borderRadius:8,padding:20,boxShadow:"0 1px 3px rgba(0,0,0,0.05)"},children:e.jsx($,{animation:!0})}):e.jsx(_t,{rows:Ne,title:"Skill 调用 Top 10",subtitle:`近 ${o} 天调用次数 · 颜色=成功率`})})]}),e.jsxs(B,{gutter:[16,16],style:{marginBottom:16},children:[e.jsx(S,{xs:24,md:12,children:e.jsx(Dt,{days:Pe})}),e.jsx(S,{xs:24,md:12,children:e.jsx(Et,{rules:He})})]}),e.jsxs("div",{style:{background:"#fff",borderRadius:8,boxShadow:"0 1px 3px rgba(0,0,0,0.05)",padding:20,marginBottom:16},children:[e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"baseline",marginBottom:12},children:[e.jsxs("div",{children:[e.jsx("div",{style:{fontSize:14,fontWeight:600,color:"#1d2129"},children:"TL;DR 周报摘要"}),e.jsxs("div",{style:{fontSize:12,color:"#86909c",marginTop:2},children:["基于近 ",o," 天指标自动生成 · 点击「导出周报」下载 Markdown"]})]}),e.jsx("a",{onClick:()=>c("/violations"),style:{cursor:"pointer",fontSize:12,color:"#1890ff"},children:"查看 violations →"})]}),re&&Q.length===0?e.jsx($,{animation:!0}):e.jsx("div",{style:{fontSize:13,lineHeight:1.9,color:"#1d2129"},children:Q.map((s,d)=>e.jsx("div",{children:s},d))}),e.jsxs("div",{style:{marginTop:16,paddingTop:12,borderTop:"1px solid #f0f0f0"},children:[e.jsx("div",{style:{fontSize:13,fontWeight:600,color:"#1d2129",marginBottom:8},children:"本周异常"}),f?e.jsx($,{animation:!0}):he.length===0&&X.length===0?e.jsx(Xe,{description:"无明显异常项",style:{padding:12}}):e.jsxs(e.Fragment,{children:[he.map((s,d)=>e.jsxs("div",{onClick:()=>{const r=new URLSearchParams;r.set("task",s.task_id),c(`/tasks?${r.toString()}`)},style:{padding:"6px 0",cursor:"pointer",display:"flex",gap:10,alignItems:"center",borderBottom:"1px dashed #f0f0f0"},children:[e.jsx(ye,{color:s.kind==="failed"?"red":"orange",size:"small",style:{flexShrink:0},children:s.kind==="failed"?"失败":"高拦截"}),e.jsx("div",{style:{flex:1,minWidth:0,fontSize:12},children:s.label}),e.jsx(Ze.Text,{type:"secondary",style:{fontSize:11},children:s.detail})]},d)),X.length>0&&e.jsxs("div",{style:{padding:"8px 0 0",fontSize:11,color:"#86909c",display:"flex",alignItems:"center",flexWrap:"wrap",gap:4},children:[e.jsx("span",{children:"Top 违规规则:"}),X.map(s=>e.jsxs(ye,{size:"small",color:"red",children:[s.rule_id," × ",s.n]},s.rule_id))]})]})]})]})]})}export{nn as default};
3
- //# sourceMappingURL=HealthHomePage-CN6zNIie.js.map