@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,4 +0,0 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/HealthHomePage-CN6zNIie.js","assets/react-vendor-tkvCrao7.js","assets/react-router-JVUrkhdd.js","assets/vendor-DWgdB1eY.js","assets/query-S6X1S7K9.js","assets/arco-Bhi3a6Qp.js","assets/arco-DFQA6dO_.css","assets/charts-BuHQWDbQ.js","assets/outcome-DUn1NjlC.js","assets/lucide-CnlPQoG8.js","assets/TasksHubPage-03wsRRsJ.js","assets/ProjectSwitcher-D3lZMFd3.js","assets/auth-Bnf8ZcqN.js","assets/date-fns-sbWH3_uq.js","assets/ContextInsightsPage-oUk7_I8u.js","assets/useTabsParam-k8qte_0C.js","assets/SkillContentPage-DK5rgfgw.js","assets/MarkdownRenderer-DZmTl-8J.js","assets/syntax-highlighter-BkZfCDsz.js","assets/AgentContentPage-DkeRNxok.js","assets/ViolationsPage-DSiLr-9O.js","assets/SettingsPage-oLJBNzQj.js","assets/DaemonHealthPage-DG2fyOP7.js","assets/DiagnosticsPage-DQd-Zm4r.js","assets/DecisionsPage-CMAPEnKb.js","assets/NotFound-BQPh0vaF.js"])))=>i.map(i=>d[i]);
2
- import{r as i,j as e,h as re,R as oe}from"./react-vendor-tkvCrao7.js";import{u as _,a as q,O as ae,N,b as ie,R as le,c as h,B as ce}from"./react-router-JVUrkhdd.js";import{u as T,Q as de,a as ue}from"./query-S6X1S7K9.js";import{I as Q,a as Y,S as he,T as D,E as A,b as O,c as E,d as B,e as I,L as z,M as Z,f as V,g as me,h as xe,P as W,B as pe,i as fe,j as ge,k as be,A as ye,l as je,m as P,n as ke,o as we,p as ve,q as Se,r as Ce,s as Ie,C as Te,z as _e}from"./arco-Bhi3a6Qp.js";import{N as $e}from"./vendor-DWgdB1eY.js";import{X as Ee,I as Pe,C as Re,a as Le,b as De,T as Ae}from"./lucide-CnlPQoG8.js";(function(){const s=document.createElement("link").relList;if(s&&s.supports&&s.supports("modulepreload"))return;for(const n of document.querySelectorAll('link[rel="modulepreload"]'))c(n);new MutationObserver(n=>{for(const l of n)if(l.type==="childList")for(const a of l.addedNodes)a.tagName==="LINK"&&a.rel==="modulepreload"&&c(a)}).observe(document,{childList:!0,subtree:!0});function r(n){const l={};return n.integrity&&(l.integrity=n.integrity),n.referrerPolicy&&(l.referrerPolicy=n.referrerPolicy),n.crossOrigin==="use-credentials"?l.credentials="include":n.crossOrigin==="anonymous"?l.credentials="omit":l.credentials="same-origin",l}function c(n){if(n.ep)return;n.ep=!0;const l=r(n);fetch(n.href,l)}})();const Oe="modulepreload",ze=function(t){return"/"+t},H={},j=function(s,r,c){let n=Promise.resolve();if(r&&r.length>0){document.getElementsByTagName("link");const a=document.querySelector("meta[property=csp-nonce]"),d=(a==null?void 0:a.nonce)||(a==null?void 0:a.getAttribute("nonce"));n=Promise.allSettled(r.map(o=>{if(o=ze(o),o in H)return;H[o]=!0;const x=o.endsWith(".css"),g=x?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${o}"]${g}`))return;const p=document.createElement("link");if(p.rel=x?"stylesheet":Oe,x||(p.as="script"),p.crossOrigin="",p.href=o,d&&p.setAttribute("nonce",d),document.head.appendChild(p),x)return new Promise((S,u)=>{p.addEventListener("load",S),p.addEventListener("error",()=>u(new Error(`Unable to preload CSS for ${o}`)))})}))}function l(a){const d=new Event("vite:preloadError",{cancelable:!0});if(d.payload=a,window.dispatchEvent(d),!d.defaultPrevented)throw a}return n.then(a=>{for(const d of a||[])d.status==="rejected"&&l(d.reason);return s().catch(l)})},G={"/health":{tabLabel:"整体健康度",breadcrumbs:[{label:"整体健康度"}]},"/tasks":{tabLabel:"我的任务",breadcrumbs:[{label:"我的任务"}]},"/context":{tabLabel:"AI 在拿什么",breadcrumbs:[{label:"AI 在拿什么"}]},"/decisions":{tabLabel:"决策",breadcrumbs:[{label:"决策"}]},"/violations":{tabLabel:"出问题了",breadcrumbs:[{label:"出问题了"}]},"/tuning":{tabLabel:"调优",breadcrumbs:[{label:"调优"}]},"/settings":{tabLabel:"设置",breadcrumbs:[{label:"设置"}]},"/diagnostics":{tabLabel:"诊断",breadcrumbs:[{label:"诊断"}]},"/daemon-health":{tabLabel:"Daemon 健康",breadcrumbs:[{label:"Daemon 健康"}]}};function Me(t){const s=qe(t);return G[s]??null}new Set(Object.keys(G));function qe(t){return t.length>1&&t.endsWith("/")?t.slice(0,-1):t}const X="claude-forge:theme";function Ne(){try{const t=localStorage.getItem(X);if(t==="light"||t==="dark")return t}catch{}try{if(typeof window<"u"&&window.matchMedia)return window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}catch{}return"light"}function J(t){typeof document>"u"||(t==="dark"?document.body.setAttribute("arco-theme","dark"):document.body.removeAttribute("arco-theme"))}let $=Ne();const M=new Set;J($);function Ue(){return $}function Fe(t){if(t!==$){$=t;try{localStorage.setItem(X,t)}catch{}J(t),M.forEach(s=>s(t))}}function Be(t){return M.add(t),()=>{M.delete(t)}}function Ve(){const[t,s]=i.useState(Ue);return i.useEffect(()=>Be(s),[]),[t,Fe]}const We=250,R=5;async function L(t){const s=await fetch(t);if(!s.ok)throw new Error(`${t} → ${s.status}`);return s.json()}async function He(t){const s=t.trim().slice(0,200);if(!s)return{sessions:[],tasks:[],kb:[]};const r=encodeURIComponent(s),[c,n,l]=await Promise.allSettled([L(`/api/sessions?search=${r}&limit=${R}`),L(`/api/tasks?search=${r}&limit=${R}`),L(`/api/knowledge/query?q=${r}&strategy=keyword&max=${R}`)]);return{sessions:c.status==="fulfilled"?c.value:[],tasks:n.status==="fulfilled"?n.value.tasks??[]:[],kb:l.status==="fulfilled"?l.value.pages??[]:[]}}function Ke({onNavigate:t}){const s=_(),[r,c]=i.useState(""),[n,l]=i.useState(null),[a,d]=i.useState(!1),o=i.useRef(null),x=i.useRef(0);i.useEffect(()=>{o.current&&clearTimeout(o.current);const u=r.trim();if(!u){l(null),d(!1);return}d(!0);const f=++x.current;return o.current=setTimeout(async()=>{const k=await He(u);f===x.current&&(l(k),d(!1))},We),()=>{o.current&&clearTimeout(o.current)}},[r]);const g=i.useCallback(()=>{if(!n)return;const u=[{key:"sessions",path:"/tasks",n:n.sessions.length},{key:"tasks",path:"/tasks",n:n.tasks.length},{key:"kb",path:"/context?tab=kb",n:n.kb.length}],f=u.reduce((w,v)=>v.n>w.n?v:w,u[0]);if(f.n===0)return;const k=encodeURIComponent(r.trim()),m=f.path.includes("?")?`${f.path}&q=${k}`:`${f.path}?q=${k}`;s(m),t==null||t()},[n,r,s,t]),p=((n==null?void 0:n.sessions.length)??0)+((n==null?void 0:n.tasks.length)??0)+((n==null?void 0:n.kb.length)??0),S=i.useMemo(()=>n?[{label:"会话",path:"/tasks",items:n.sessions.map(u=>({key:`s-${u.session_id}`,label:u.first_prompt||`(${u.session_id.slice(0,8)})`,onClick:()=>{s(`/tasks?session=${encodeURIComponent(u.session_id)}`),t==null||t()}}))},{label:"任务",path:"/tasks",items:n.tasks.map(u=>({key:`t-${u.id}`,label:u.title||u.first_prompt||`(任务 ${u.id.slice(0,8)})`,onClick:()=>{s(`/tasks?task=${encodeURIComponent(u.id)}`),t==null||t()}}))},{label:"知识库",path:"/context?tab=kb",items:n.kb.map(u=>({key:`k-${u.page.name}`,label:u.page.title||u.page.name,onClick:()=>{s(`/context?tab=kb&page=${encodeURIComponent(u.page.name)}`),t==null||t()}}))}]:[],[n,s,t]);return e.jsxs("div",{style:{width:360,maxHeight:480,overflowY:"auto"},children:[e.jsx(Q.Search,{autoFocus:!0,value:r,onChange:c,onPressEnter:g,placeholder:"搜索 sessions / tasks / 知识库...",allowClear:!0,prefix:e.jsx(Y,{}),style:{width:"100%"}}),e.jsx("div",{style:{marginTop:12},children:a?e.jsx("div",{style:{display:"flex",justifyContent:"center",padding:"24px 0"},children:e.jsx(he,{size:20})}):n?p===0?e.jsx(A,{description:"无匹配结果",imgSrc:"",style:{padding:"12px 0"}}):e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:12},children:S.map(u=>u.items.length===0?null:e.jsxs("div",{children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,marginBottom:4},children:[e.jsx(D.Text,{style:{fontSize:11,color:"var(--color-text-3)"},children:u.label}),e.jsx(O,{size:"small",color:"gray",children:u.items.length})]}),e.jsx("ul",{style:{listStyle:"none",padding:0,margin:0},children:u.items.map(f=>e.jsx("li",{onClick:f.onClick,style:{padding:"6px 8px",fontSize:12,color:"var(--color-text-1)",cursor:"pointer",borderRadius:4,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},onMouseEnter:k=>{k.currentTarget.style.background="var(--color-fill-2)"},onMouseLeave:k=>{k.currentTarget.style.background="transparent"},children:f.label},f.key))})]},u.label))}):e.jsx(D.Text,{type:"secondary",style:{fontSize:12},children:"输入关键词后回车跳转到结果最多的页面。"})})]})}function Qe({onClose:t}){const s=_(),{data:r,isLoading:c}=T({queryKey:["notifications-violations"],queryFn:async()=>{const o=await fetch("/api/violations?days=7&limit=10");if(!o.ok)throw new Error("Failed");return o.json()},refetchOnMount:"always"}),{data:n,isLoading:l}=T({queryKey:["notifications-insights"],queryFn:async()=>{const o=await fetch("/api/insights?days=7");if(!o.ok)throw new Error("Failed");return o.json()},refetchOnMount:"always"}),a=(r==null?void 0:r.count)??0,d=((n==null?void 0:n.summary.critical)??0)+((n==null?void 0:n.summary.warn)??0);return e.jsx("div",{style:{width:360,maxHeight:480,overflowY:"auto"},children:e.jsxs(E,{defaultActiveTab:"violations",size:"mini",children:[e.jsx(E.TabPane,{title:`违规${a>0?` (${a})`:""}`,children:c?e.jsx(B,{text:{rows:3},animation:!0}):!r||r.count===0?e.jsx(A,{description:"近 7 天无违规",imgSrc:"",style:{padding:"12px 0"}}):e.jsx("ul",{style:{listStyle:"none",padding:0,margin:0},children:r.violations.map(o=>e.jsxs("li",{style:{padding:"8px 4px",borderBottom:"1px solid var(--color-border-2)"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:8},children:[e.jsx(O,{size:"small",color:o.signal==="user_keyword"?"red":"orange",children:o.signal==="user_keyword"?"关键词":"路由"}),e.jsx("span",{style:{fontSize:11,color:"var(--color-text-3)"},children:o.relativeTime})]}),e.jsxs("div",{style:{fontSize:12,color:"var(--color-text-1)",marginTop:4,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},title:o.summary,children:[o.summary.slice(0,60),o.summary.length>60?"…":""]})]},o.timestamp+o.summary.slice(0,16)))})},"violations"),e.jsx(E.TabPane,{title:`反模式${d>0?` (${d})`:""}`,children:l?e.jsx(B,{text:{rows:3},animation:!0}):!n||n.patterns.length===0?e.jsx(A,{description:"近 7 天无反模式",imgSrc:"",style:{padding:"12px 0"}}):e.jsx("ul",{style:{listStyle:"none",padding:0,margin:0},children:n.patterns.slice(0,10).map(o=>e.jsxs("li",{style:{padding:"8px 4px",borderBottom:"1px solid var(--color-border-2)",cursor:o.sessionId?"pointer":"default"},onClick:()=>{o.sessionId&&(s(`/tasks?session=${encodeURIComponent(o.sessionId)}`),t==null||t())},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6},children:[e.jsx(O,{size:"small",color:o.severity==="critical"?"red":o.severity==="warn"?"orange":"gray",children:o.severity}),e.jsx(D.Text,{style:{fontSize:12,fontWeight:500},children:o.title})]}),e.jsx("div",{style:{fontSize:11,color:"var(--color-text-3)",marginTop:4,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},title:o.description,children:o.description})]},o.id))})},"insights")]})})}function Dt(t){if(!t)return new Date(0);const s=t.trim();return s.endsWith("Z")||/[+-]\d{2}:\d{2}$/.test(s)?new Date(s):new Date(s+"Z")}function Ye(t){return t?t.endsWith("Z")?t:t+"Z":new Date().toISOString()}function ee(t){if(typeof t=="number")return new Date(t);try{return new Date(Ye(t))}catch{return new Date(0)}}function C(t){return t<10?`0${t}`:`${t}`}function At(t,s){try{const r=ee(t);if(isNaN(r.getTime()))return"—";const c=r.getFullYear(),n=C(r.getMonth()+1),l=C(r.getDate());if(s!=null&&s.dateOnly)return`${c}-${n}-${l}`;const a=C(r.getHours()),d=C(r.getMinutes()),o=`${c}-${n}-${l} ${a}:${d}`,x=s!=null&&s.includeSeconds?`:${C(r.getSeconds())}`:"",g=(s==null?void 0:s.tzSuffix)!==void 0?s.tzSuffix:"CST";return g?`${o}${x} ${g}`:`${o}${x}`}catch{return"—"}}function Ze(t){try{const s=ee(t);if(isNaN(s.getTime()))return"—";const r=Date.now()-s.getTime(),c=Math.floor(r/6e4);if(c<1)return"刚刚";if(c<60)return`${c} 分钟前`;const n=Math.floor(c/60);return n<24?`${n} 小时前`:`${Math.floor(n/24)} 天前`}catch{return"—"}}function Ge(t){return t==null?"no heartbeat":Ze(Date.now()-t)}const Xe={alive:{color:"#00b42a",label:"Daemon ALIVE",dotStyle:{background:"#00b42a"}},stale:{color:"#ff7d00",label:"Daemon STALE",dotStyle:{background:"#ff7d00"}},dead:{color:"#f53f3f",label:"Daemon DEAD",dotStyle:{background:"#f53f3f"}}};function Je(){var d,o,x;const t=_(),{data:s}=T({queryKey:["daemon-health"],queryFn:async()=>{const g=await fetch("/api/health");if(!g.ok)throw new Error("health check failed");return g.json()},refetchInterval:3e4,retry:!1,staleTime:15e3}),r=((d=s==null?void 0:s.daemon)==null?void 0:d.status)??"dead",c=Xe[r],n=((o=s==null?void 0:s.daemon)==null?void 0:o.heartbeat_age_ms)??null,l=(x=s==null?void 0:s.daemon)==null?void 0:x.pid,a=[`Status: ${r.toUpperCase()}`,l!=null?`PID: ${l}`:"PID: not running",`Heartbeat: ${Ge(n)}`].join(`
3
- `);return e.jsx(I,{content:e.jsx("span",{style:{whiteSpace:"pre-line"},children:a}),position:"bottom",children:e.jsxs("button",{onClick:()=>t("/daemon-health"),style:{display:"inline-flex",alignItems:"center",gap:5,border:"none",background:"transparent",cursor:"pointer",padding:"4px 8px",borderRadius:6,color:"var(--color-text-2)",fontSize:12},"aria-label":`daemon-badge-${r}`,children:[e.jsx("span",{style:{width:8,height:8,borderRadius:"50%",display:"inline-block",...c.dotStyle,...r==="alive"?{boxShadow:`0 0 0 2px ${c.color}33`,animation:"daemon-pulse 2s infinite"}:{}}}),e.jsx("span",{style:{color:c.color,fontWeight:500},children:r.toUpperCase()})]})})}function et(t){return t?t.summary.fail>0?"fail":t.summary.warn>0?"warn":"pass":"unknown"}const tt={pass:{color:"#00b42a",label:"Doctor OK"},warn:{color:"#ff7d00",label:"Doctor WARN"},fail:{color:"#f53f3f",label:"Doctor FAIL"},unknown:{color:"#86909c",label:"Doctor ?"}};function st(){const t=_(),{data:s}=T({queryKey:["diagnostics-badge"],queryFn:async()=>{const l=await fetch("/api/diagnostics");if(!l.ok)throw new Error("diagnostics failed");return l.json()},refetchInterval:6e4,retry:!1,staleTime:3e4}),r=et(s),c=tt[r],n=s?[`PASS=${s.summary.pass}`,`WARN=${s.summary.warn}`,`FAIL=${s.summary.fail}`,`SKIP=${s.summary.skip}`,s.summary.fixable>0?`${s.summary.fixable} fixable`:""].filter(Boolean).join(" · "):"Loading diagnostics…";return e.jsx(I,{content:n,position:"bottom",children:e.jsxs("button",{onClick:()=>t("/diagnostics"),style:{display:"inline-flex",alignItems:"center",gap:5,border:"none",background:"transparent",cursor:"pointer",padding:"4px 8px",borderRadius:6,color:"var(--color-text-2)",fontSize:12},"aria-label":`doctor-badge-${r}`,children:[e.jsx("span",{style:{width:8,height:8,borderRadius:"50%",display:"inline-block",background:c.color}}),e.jsx("span",{style:{color:c.color,fontWeight:500},children:c.label})]})})}const{Sider:nt,Header:rt,Content:ot}=z,at=Z.Item,it=[{key:"/health",label:"整体健康度",icon:e.jsx(ke,{})},{key:"/tasks",label:"我的任务",icon:e.jsx(we,{})},{key:"/context",label:"AI 在拿什么",icon:e.jsx(ve,{})},{key:"/decisions",label:"决策",icon:e.jsx(Se,{})},{key:"/violations",label:"出问题了",icon:e.jsx(Ce,{})},{key:"/settings",label:"设置",icon:e.jsx(Ie,{})}];function lt(t){const s=t.replace(/\/$/,"")||"/health";return s==="/health"||s.startsWith("/health/")?"/health":s==="/tasks"||s.startsWith("/tasks/")?"/tasks":s==="/context"||s.startsWith("/context/")?"/context":s==="/decisions"||s.startsWith("/decisions/")?"/decisions":s==="/violations"||s.startsWith("/violations/")?"/violations":s==="/settings"||s.startsWith("/settings/")?"/settings":"/health"}function ct(){const t=q(),s=_(),[r,c]=i.useState(!1),[n,l]=Ve(),a=i.useMemo(()=>lt(t.pathname),[t.pathname]),d=i.useCallback(m=>{m!==t.pathname&&s(m)},[t.pathname,s]),o=i.useMemo(()=>{const m=Me(t.pathname);return(m==null?void 0:m.breadcrumbs)??[{label:"整体健康度"}]},[t.pathname]),x=i.useCallback(()=>{l(n==="light"?"dark":"light")},[n,l]),[g,p]=i.useState(!1),[S,u]=i.useState(!1),{data:f}=T({queryKey:["notifications-badge"],queryFn:async()=>{var m,w;try{const[v,U]=await Promise.all([fetch("/api/violations?days=7&limit=1"),fetch("/api/insights?days=7")]),ne=v.ok?await v.json():{count:0},F=U.ok?await U.json():{summary:{critical:0,warn:0}};return{hasUnread:(ne.count??0)>0||(((m=F.summary)==null?void 0:m.critical)??0)+(((w=F.summary)==null?void 0:w.warn)??0)>0}}catch{return{hasUnread:!1}}},refetchInterval:6e4}),k=(f==null?void 0:f.hasUnread)??!1;return e.jsxs(z,{style:{minHeight:"100vh"},children:[e.jsxs(nt,{collapsed:r,collapsible:!0,collapsedWidth:64,width:220,trigger:null,breakpoint:"lg",style:{background:"var(--color-bg-2)",borderRight:"1px solid var(--color-border)"},children:[e.jsxs("div",{style:{height:64,display:"flex",alignItems:"center",justifyContent:r?"center":"flex-start",padding:r?0:"0 20px",borderBottom:"1px solid var(--color-border-2)",gap:10},children:[e.jsx("span",{className:"cf-brand-chip",children:"CF"}),!r&&e.jsx("span",{style:{fontSize:14,fontWeight:600,color:"var(--color-text-1)"},children:"Claude Forge"})]}),e.jsx(Z,{selectedKeys:[a],mode:"vertical",onClickMenuItem:d,style:{width:"100%",border:"none",background:"transparent"},children:it.map(m=>e.jsxs(at,{children:[m.icon,m.label]},m.key))}),!r&&e.jsxs("div",{style:{position:"absolute",bottom:0,left:0,right:0,padding:"12px 16px",borderTop:"1px solid var(--color-border-2)",fontSize:11,color:"var(--color-text-3)",display:"flex",justifyContent:"space-between"},children:[e.jsx("span",{children:"claude-forge"}),e.jsxs("span",{style:{fontFamily:"monospace"},children:["v","9.2.0"]})]})]}),e.jsxs(z,{children:[e.jsxs(rt,{style:{height:60,background:"var(--color-bg-2)",borderBottom:"1px solid var(--color-border)",display:"flex",alignItems:"center",justifyContent:"space-between",padding:"0 20px"},children:[e.jsxs(V,{size:12,children:[e.jsx(I,{content:r?"展开侧栏":"收起侧栏",children:e.jsx("button",{onClick:()=>c(m=>!m),style:{border:"none",background:"transparent",cursor:"pointer",color:"var(--color-text-2)",padding:6,display:"inline-flex",alignItems:"center"},"aria-label":"toggle-sider",children:r?e.jsx(me,{}):e.jsx(xe,{})})}),e.jsx(W,{trigger:"click",position:"bl",popupVisible:g,onVisibleChange:p,content:e.jsx(Ke,{onNavigate:()=>p(!1)}),children:e.jsx(Q.Search,{placeholder:"搜索 sessions / tasks / 知识库...",style:{width:280},allowClear:!0,readOnly:!0,prefix:e.jsx(Y,{}),onClick:()=>p(!0)})})]}),e.jsxs(V,{size:16,children:[e.jsx(Je,{}),e.jsx(st,{}),e.jsx(W,{trigger:"click",position:"br",popupVisible:S,onVisibleChange:u,content:e.jsx(Qe,{onClose:()=>u(!1)}),children:e.jsx(I,{content:"通知",children:e.jsx("button",{style:{border:"none",background:"transparent",cursor:"pointer",color:"var(--color-text-2)",padding:6,display:"inline-flex",alignItems:"center"},"aria-label":"notifications",children:e.jsx(pe,{dot:k,count:0,offset:[-2,2],children:e.jsx(fe,{})})})})}),e.jsx(I,{content:n==="light"?"切换深色主题":"切换浅色主题",children:e.jsx("button",{onClick:x,style:{border:"none",background:"transparent",cursor:"pointer",color:"var(--color-text-2)",padding:6,display:"inline-flex",alignItems:"center"},"aria-label":"toggle-theme",children:n==="light"?e.jsx(ge,{}):e.jsx(be,{})})}),e.jsx(ye,{size:32,style:{background:"linear-gradient(135deg,#165DFF,#722ED1)"},children:e.jsx(je,{})})]})]}),e.jsxs(ot,{style:{padding:0,background:"var(--color-bg-2)",display:"flex",flexDirection:"column",minHeight:"calc(100vh - 60px)"},children:[e.jsx("div",{style:{padding:"12px 20px 0"},children:e.jsx(P,{children:o.map((m,w)=>m.path?e.jsx(P.Item,{children:e.jsx("a",{onClick:v=>{v.preventDefault(),m.path&&s(m.path)},href:m.path,style:{color:"var(--color-text-2)"},children:m.label})},`${m.label}-${w}`):e.jsx(P.Item,{children:m.label},`${m.label}-${w}`))})}),e.jsx("div",{style:{padding:"16px 20px 24px",flex:1},children:e.jsx(ae,{})})]})]})]})}function te(t,s){const[r,c=""]=t.split("?"),n=new URLSearchParams(c),l=new URLSearchParams(s||"");for(const[d,o]of l.entries())n.has(d)||n.set(d,o);const a=n.toString();return a?`${r}?${a}`:r}function b({to:t}){const s=q(),r=te(t,s.search);return e.jsx(N,{to:r,replace:!0})}function K({base:t,param:s,tpl:r}){const c=ie(),n=q(),l=c[s]??"",a=r.replace("{}",encodeURIComponent(l)),d=te(`${t}${a}`,n.search);return e.jsx(N,{to:d,replace:!0})}const dt=i.lazy(()=>j(()=>import("./HealthHomePage-CN6zNIie.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9]))),ut=i.lazy(()=>j(()=>import("./TasksHubPage-03wsRRsJ.js"),__vite__mapDeps([10,1,2,3,4,5,6,11,12,13,9,8]))),ht=i.lazy(()=>j(()=>import("./ContextInsightsPage-oUk7_I8u.js"),__vite__mapDeps([14,1,5,3,6,11,4,2,15,9]))),mt=i.lazy(()=>j(()=>import("./SkillContentPage-DK5rgfgw.js"),__vite__mapDeps([16,1,2,3,4,5,6,17,18]))),xt=i.lazy(()=>j(()=>import("./AgentContentPage-DkeRNxok.js"),__vite__mapDeps([19,1,2,3,4,5,6,17,18]))),pt=i.lazy(()=>j(()=>import("./ViolationsPage-DSiLr-9O.js"),__vite__mapDeps([20,1,2,3,4,5,6,11,15,9]))),ft=i.lazy(()=>j(()=>import("./SettingsPage-oLJBNzQj.js"),__vite__mapDeps([21,1,5,3,6,15,2,4,9]))),gt=i.lazy(()=>j(()=>import("./DaemonHealthPage-DG2fyOP7.js"),__vite__mapDeps([22,1,4,5,3,6,2,9]))),bt=i.lazy(()=>j(()=>import("./DiagnosticsPage-DQd-Zm4r.js"),__vite__mapDeps([23,1,4,12,5,3,6]))),yt=i.lazy(()=>j(()=>import("./DecisionsPage-CMAPEnKb.js"),__vite__mapDeps([24,1,4,5,3,6]))),jt=i.lazy(()=>j(()=>import("./NotFound-BQPh0vaF.js"),__vite__mapDeps([25,1,2,3,5,6])));function y(){return e.jsx("div",{className:"flex items-center justify-center h-full py-16",children:e.jsxs("div",{className:"flex items-center gap-3 text-sm text-gray-500",children:[e.jsx("div",{className:"w-4 h-4 border-2 border-gray-300 border-t-blue-500 rounded-full animate-spin"}),"加载中..."]})})}function kt(){return e.jsx(le,{children:e.jsxs(h,{path:"/",element:e.jsx(ct,{}),children:[e.jsx(h,{index:!0,element:e.jsx(N,{to:"/health",replace:!0})}),e.jsx(h,{path:"health",element:e.jsx(i.Suspense,{fallback:e.jsx(y,{}),children:e.jsx(dt,{})})}),e.jsx(h,{path:"tasks",element:e.jsx(i.Suspense,{fallback:e.jsx(y,{}),children:e.jsx(ut,{})})}),e.jsx(h,{path:"context",element:e.jsx(i.Suspense,{fallback:e.jsx(y,{}),children:e.jsx(ht,{})})}),e.jsx(h,{path:"context/skill/:id",element:e.jsx(i.Suspense,{fallback:e.jsx(y,{}),children:e.jsx(mt,{})})}),e.jsx(h,{path:"context/agent/:name",element:e.jsx(i.Suspense,{fallback:e.jsx(y,{}),children:e.jsx(xt,{})})}),e.jsx(h,{path:"violations",element:e.jsx(i.Suspense,{fallback:e.jsx(y,{}),children:e.jsx(pt,{})})}),e.jsx(h,{path:"settings",element:e.jsx(i.Suspense,{fallback:e.jsx(y,{}),children:e.jsx(ft,{})})}),e.jsx(h,{path:"daemon-health",element:e.jsx(i.Suspense,{fallback:e.jsx(y,{}),children:e.jsx(gt,{})})}),e.jsx(h,{path:"diagnostics",element:e.jsx(i.Suspense,{fallback:e.jsx(y,{}),children:e.jsx(bt,{})})}),e.jsx(h,{path:"decisions",element:e.jsx(i.Suspense,{fallback:e.jsx(y,{}),children:e.jsx(yt,{})})}),e.jsx(h,{path:"tuning",element:e.jsx(b,{to:"/health"})}),e.jsx(h,{path:"dashboard",element:e.jsx(b,{to:"/health"})}),e.jsx(h,{path:"pipeline",element:e.jsx(b,{to:"/tasks"})}),e.jsx(h,{path:"resources",element:e.jsx(b,{to:"/context"})}),e.jsx(h,{path:"sessions",element:e.jsx(b,{to:"/tasks"})}),e.jsx(h,{path:"sessions/:id",element:e.jsx(K,{base:"/tasks",param:"id",tpl:"?session={}"})}),e.jsx(h,{path:"tasks/:taskId",element:e.jsx(K,{base:"/tasks",param:"taskId",tpl:"?task={}"})}),e.jsx(h,{path:"events",element:e.jsx(b,{to:"/tasks"})}),e.jsx(h,{path:"insights/pipeline",element:e.jsx(b,{to:"/tasks"})}),e.jsx(h,{path:"insights/timeline",element:e.jsx(b,{to:"/tasks"})}),e.jsx(h,{path:"insights/agent-board",element:e.jsx(b,{to:"/tasks"})}),e.jsx(h,{path:"insights/tuning",element:e.jsx(b,{to:"/health"})}),e.jsx(h,{path:"reports",element:e.jsx(b,{to:"/health"})}),e.jsx(h,{path:"knowledge",element:e.jsx(b,{to:"/context?tab=kb"})}),e.jsx(h,{path:"skills",element:e.jsx(b,{to:"/context?tab=skills"})}),e.jsx(h,{path:"*",element:e.jsx(i.Suspense,{fallback:e.jsx(y,{}),children:e.jsx(jt,{})})})]})})}const wt=i.createContext(null);let vt=1;function St({children:t}){const[s,r]=i.useState([]),c=i.useCallback(a=>{r(d=>d.filter(o=>o.id!==a))},[]),n=i.useCallback((a,d)=>{const o=vt++;r(x=>[...x,{id:o,type:a,message:d}]),setTimeout(()=>c(o),4e3)},[c]),l={show:n,success:a=>n("success",a),error:a=>n("error",a),warning:a=>n("warning",a),info:a=>n("info",a)};return e.jsxs(wt.Provider,{value:l,children:[t,e.jsx("div",{className:"fixed top-4 right-4 z-[9999] space-y-2 max-w-md",children:s.map(a=>e.jsx(Ct,{toast:a,onClose:()=>c(a.id)},a.id))})]})}function Ct({toast:t,onClose:s}){const r={success:e.jsx(De,{className:"h-5 w-5 text-green-500"}),error:e.jsx(Le,{className:"h-5 w-5 text-red-500"}),warning:e.jsx(Re,{className:"h-5 w-5 text-yellow-500"}),info:e.jsx(Pe,{className:"h-5 w-5 text-blue-500"})},c={success:"border-green-200",error:"border-red-200",warning:"border-yellow-200",info:"border-blue-200"};return e.jsxs("div",{className:$e("bg-white shadow-lg rounded-lg border px-4 py-3 flex items-start gap-3 animate-in slide-in-from-right",c[t.type]),children:[r[t.type],e.jsx("div",{className:"flex-1 text-sm text-gray-800",children:t.message}),e.jsx("button",{onClick:s,className:"text-gray-400 hover:text-gray-600",children:e.jsx(Ee,{className:"h-4 w-4"})})]})}const se=i.createContext(null);function Ot(){const t=i.useContext(se);if(!t)throw new Error("useConfirm must be used within ConfirmProvider");return t.confirm}function It({children:t}){var o;const[s,r]=i.useState({open:!1,options:null,resolve:null}),c=i.useCallback(x=>new Promise(g=>{r({open:!0,options:x,resolve:g})}),[]),n=x=>{s.resolve&&s.resolve(x),r({open:!1,options:null,resolve:null})},l=((o=s.options)==null?void 0:o.variant)||"danger",a={danger:"text-red-600",warning:"text-yellow-600",info:"text-blue-600"}[l],d={danger:"bg-red-600 hover:bg-red-700",warning:"bg-yellow-600 hover:bg-yellow-700",info:"bg-indigo-600 hover:bg-indigo-700"}[l];return e.jsxs(se.Provider,{value:{confirm:c},children:[t,s.open&&s.options&&e.jsxs("div",{className:"fixed inset-0 z-[9999] flex items-center justify-center",children:[e.jsx("div",{className:"absolute inset-0 bg-black bg-opacity-50",onClick:()=>n(!1)}),e.jsxs("div",{className:"relative bg-white rounded-lg shadow-xl max-w-md w-full mx-4 p-6",children:[e.jsxs("div",{className:"flex items-start gap-4",children:[e.jsx("div",{className:`flex-shrink-0 ${a}`,children:e.jsx(Ae,{className:"h-6 w-6"})}),e.jsxs("div",{className:"flex-1",children:[e.jsx("h3",{className:"text-lg font-semibold text-gray-900 mb-2",children:s.options.title}),e.jsx("p",{className:"text-sm text-gray-600 whitespace-pre-wrap",children:s.options.message})]})]}),e.jsxs("div",{className:"flex justify-end gap-2 mt-6",children:[e.jsx("button",{onClick:()=>n(!1),className:"px-4 py-2 text-sm text-gray-700 bg-white border border-gray-300 rounded hover:bg-gray-50",children:s.options.cancelText||"取消"}),e.jsx("button",{onClick:()=>n(!0),className:`px-4 py-2 text-sm text-white rounded ${d}`,children:s.options.confirmText||"确定"})]})]})]})]})}const Tt=new de({defaultOptions:{queries:{refetchOnWindowFocus:!1,retry:1,staleTime:6e4,gcTime:5*6e4}}});re.createRoot(document.getElementById("root")).render(e.jsx(oe.StrictMode,{children:e.jsx(ue,{client:Tt,children:e.jsx(Te,{locale:_e,children:e.jsx(St,{children:e.jsx(It,{children:e.jsx(ce,{children:e.jsx(kt,{})})})})})})}));export{j as _,Dt as a,Ve as b,Ze as c,At as f,ee as p,Ot as u};
4
- //# sourceMappingURL=index-BIYnq1Dx.js.map
@@ -1 +0,0 @@
1
- {"version":3,"mappings":"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","names":["ROUTE_META","resolveRouteMeta","pathname","clean","stripTrailingSlash","p","KEY","detect","saved","apply","current","subs","getTheme","setTheme","cb","subscribeTheme","useTheme","setT","useState","useEffect","DEBOUNCE_MS","PER_ENTITY_LIMIT","fetchJson","url","res","runAll","q","trimmed","encoded","sessRes","taskRes","kbRes","GlobalSearch","onNavigate","navigate","useNavigate","query","setQuery","results","setResults","loading","setLoading","timer","useRef","seqRef","seq","r","goToBestEntity","useCallback","counts","best","acc","c","target","totalHits","groups","useMemo","s","t","k","jsxs","jsx","Input","IconSearch","Spin","Empty","g","Typography","Tag","it","e","NotificationPanel","onClose","vio","vLoading","useQuery","ins","iLoading","vCount","iCount","Tabs","Skeleton","v","parseUTC","timestamp","normalizeTimestamp","parseTimestamp","ts","pad2","n","formatLocalDisplay","opts","d","yyyy","mm","dd","hh","min","base","withSec","suffix","formatRelative","diff","mins","hours","formatAge","ms","STATUS_CONFIG","DaemonBadge","data","status","_a","cfg","heartbeatAgeMs","_b","pid","_c","tooltipContent","Tooltip","pickStatus","DoctorBadge","Sider","Header","Content","ArcoLayout","MenuItem","Menu","NAV_ITEMS","IconDashboard","IconList","IconBook","IconBranch","IconExclamationCircle","IconSettings","deriveMenuKey","Layout","location","useLocation","collapsed","setCollapsed","theme","menuSelectedKey","handleMenuClick","key","breadcrumbs","meta","toggleTheme","searchOpen","setSearchOpen","notifOpen","setNotifOpen","notifBadge","vRes","iRes","i","hasUnread","item","Space","IconMenuUnfold","IconMenuFold","Popover","Badge","IconNotification","IconMoon","IconSun","Avatar","IconUser","Breadcrumb","Outlet","mergeSearch","to","currentSearch","path","toQuery","merged","LegacyRedirect","Navigate","ParamRedirect","param","tpl","params","useParams","HealthHomePage","lazy","TasksHubPage","ContextInsightsPage","SkillContentPage","AgentContentPage","ViolationsPage","SettingsPage","DaemonHealthPage","DiagnosticsPage","DecisionsPage","NotFound","PageFallback","App","Routes","Route","Suspense","ToastContext","createContext","nextId","ToastProvider","children","toasts","setToasts","remove","id","prev","show","type","message","value","msg","ToastItem","toast","icons","CheckCircle","XCircle","AlertCircle","Info","borderColors","clsx","X","ConfirmContext","useConfirm","ctx","useContext","ConfirmProvider","state","setState","confirm","options","resolve","handleClose","result","variant","iconColor","btnColor","AlertTriangle","queryClient","QueryClient","ReactDOM","React","QueryClientProvider","ConfigProvider","zhCN","BrowserRouter"],"ignoreList":[],"sources":["../../src/lib/breadcrumb-map.ts","../../src/lib/theme.ts","../../src/components/GlobalSearch.tsx","../../src/components/NotificationPanel.tsx","../../src/utils/time.ts","../../src/components/DaemonBadge.tsx","../../src/components/DoctorBadge.tsx","../../src/components/Layout.tsx","../../src/lib/legacy-redirect.tsx","../../src/App.tsx","../../src/components/Toast.tsx","../../src/components/Confirm.tsx","../../src/main.tsx"],"sourcesContent":["/**\n * Path → breadcrumb segments map.\n *\n * v4 IA (Step 1): 6 top-level routes (/health /tasks /context /violations\n * /tuning /settings) — 按\"用户问句\"命名 (spec §2)。所有 v3/v2 legacy\n * routes (/dashboard /pipeline /resources /sessions /tasks/:id /events\n * /knowledge /skills /reports /insights/*) 在 App.tsx 是\n * <LegacyRedirect> 条目,不需要 breadcrumb。\n * /ai-config 老路径在 sub-spec D R-C (spec 0902) 永久下线,落 NotFound。\n *\n * The breadcrumb is kept minimal — view / tab / section disambiguation\n * is shown by the page itself (Tabs, filters) rather than by the\n * breadcrumb chain.\n */\n\nexport interface BreadcrumbItem {\n label: string;\n /** When present, the segment is a link; otherwise it's a plain text leaf. */\n path?: string;\n}\n\nexport interface RouteMeta {\n /** Tab label shown in the multi-tab bar. */\n tabLabel: string;\n /** Crumbs for non-dynamic routes. Dynamic routes resolve dynamically. */\n breadcrumbs: BreadcrumbItem[];\n}\n\nexport const ROUTE_META: Record<string, RouteMeta> = {\n '/health': {\n tabLabel: '整体健康度',\n breadcrumbs: [{ label: '整体健康度' }],\n },\n '/tasks': {\n tabLabel: '我的任务',\n breadcrumbs: [{ label: '我的任务' }],\n },\n '/context': {\n tabLabel: 'AI 在拿什么',\n breadcrumbs: [{ label: 'AI 在拿什么' }],\n },\n '/decisions': {\n tabLabel: '决策',\n breadcrumbs: [{ label: '决策' }],\n },\n '/violations': {\n tabLabel: '出问题了',\n breadcrumbs: [{ label: '出问题了' }],\n },\n '/tuning': {\n tabLabel: '调优',\n breadcrumbs: [{ label: '调优' }],\n },\n '/settings': {\n tabLabel: '设置',\n breadcrumbs: [{ label: '设置' }],\n },\n '/diagnostics': {\n tabLabel: '诊断',\n breadcrumbs: [{ label: '诊断' }],\n },\n '/daemon-health': {\n tabLabel: 'Daemon 健康',\n breadcrumbs: [{ label: 'Daemon 健康' }],\n },\n};\n\n/**\n * Resolve breadcrumb + label for an arbitrary pathname. Returns null when\n * unknown so callers can fall back to a default (\"整体健康度\"). v4 has no\n * dynamic detail routes — DetailDrawer lives in the query string and\n * does not need its own breadcrumb.\n */\nexport function resolveRouteMeta(pathname: string): RouteMeta | null {\n const clean = stripTrailingSlash(pathname);\n return ROUTE_META[clean] ?? null;\n}\n\n/** Set of every concrete top-level pathname known to the router. */\nexport const KNOWN_ROUTES: ReadonlySet<string> = new Set(Object.keys(ROUTE_META));\n\n/**\n * Validator for arbitrary path keys. Kept for backward compatibility with\n * any external caller (previously used by the removed TabStore).\n */\nexport function isKnownRoute(key: string): boolean {\n const path = key.split('?')[0];\n const clean = stripTrailingSlash(path);\n return KNOWN_ROUTES.has(clean);\n}\n\nfunction stripTrailingSlash(p: string): string {\n return p.length > 1 && p.endsWith('/') ? p.slice(0, -1) : p;\n}\n","/**\n * Theme module — light / dark with localStorage persistence.\n *\n * Detection order on first read:\n * 1. localStorage `claude-forge:theme` (if `light` or `dark`)\n * 2. window.matchMedia('(prefers-color-scheme: dark)')\n * 3. fallback `light`\n *\n * Apply mechanism: Arco's dark mode uses `body[arco-theme='dark']`. We set or\n * remove that attribute; no ConfigProvider change required.\n *\n * Subscribers (e.g. Layout's toggle button) get notified via `subscribeTheme`.\n */\n\nimport { useEffect, useState } from 'react'\n\nexport type Theme = 'light' | 'dark'\n\nconst KEY = 'claude-forge:theme'\n\nfunction detect(): Theme {\n try {\n const saved = localStorage.getItem(KEY)\n if (saved === 'light' || saved === 'dark') return saved\n } catch {\n // localStorage may throw in restricted environments — ignore.\n }\n try {\n if (typeof window !== 'undefined' && window.matchMedia) {\n return window.matchMedia('(prefers-color-scheme: dark)').matches\n ? 'dark'\n : 'light'\n }\n } catch {\n // ignore\n }\n return 'light'\n}\n\nfunction apply(t: Theme): void {\n if (typeof document === 'undefined') return\n if (t === 'dark') {\n document.body.setAttribute('arco-theme', 'dark')\n } else {\n document.body.removeAttribute('arco-theme')\n }\n}\n\nlet current: Theme = detect()\nconst subs = new Set<(t: Theme) => void>()\n\n// Apply on module import so we don't flash the wrong theme.\napply(current)\n\nexport function getTheme(): Theme {\n return current\n}\n\nexport function setTheme(t: Theme): void {\n if (t === current) return\n current = t\n try {\n localStorage.setItem(KEY, t)\n } catch {\n // ignore\n }\n apply(t)\n subs.forEach((cb) => cb(t))\n}\n\nexport function toggleTheme(): Theme {\n const next: Theme = current === 'light' ? 'dark' : 'light'\n setTheme(next)\n return next\n}\n\nexport function subscribeTheme(cb: (t: Theme) => void): () => void {\n subs.add(cb)\n return () => {\n subs.delete(cb)\n }\n}\n\n/** React hook — returns [theme, setTheme]. */\nexport function useTheme(): [Theme, (t: Theme) => void] {\n const [t, setT] = useState<Theme>(getTheme)\n useEffect(() => subscribeTheme(setT), [])\n return [t, setTheme]\n}\n","/**\n * GlobalSearch — topbar Popover that fans out to 3 endpoints in parallel.\n *\n * Entities scanned (v4 + spec 3 partial revert):\n * - Sessions → /api/sessions?search= → land on /tasks?session=…\n * - Tasks → /api/tasks?search= → land on /tasks?task=…\n * - Knowledge → /api/knowledge/query?q=&… → land on /context?tab=kb&page=…\n *\n * v4 cleanup (C-1): removed the \"Events\" group entirely (no events landing\n * page in v4; the old /events route was a LegacyRedirect stub).\n *\n * Spec 3 partial revert (2026-05-27): the Knowledge group was deleted in the\n * original Option B cut and restored here after user feedback (/context page\n * + /api/knowledge route both came back).\n *\n * Behaviour:\n * - Debounce 250ms before firing the queries (Promise.allSettled — partial\n * failures don't block the rest).\n * - Enter jumps to the entity list page with the most matches, carrying\n * `?q=` (TasksHub) or `?tab=kb` (Context).\n * - Clicking a result row jumps to that entity's detail (or list w/ filter).\n * - ESC / external click closes the Popover (handled by Arco Popover).\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { useNavigate } from 'react-router-dom'\nimport Input from '@arco-design/web-react/es/Input'\nimport Spin from '@arco-design/web-react/es/Spin'\nimport Empty from '@arco-design/web-react/es/Empty'\nimport Typography from '@arco-design/web-react/es/Typography'\nimport Tag from '@arco-design/web-react/es/Tag'\nimport { IconSearch } from '@arco-design/web-react/icon'\n\ninterface SessionHit {\n session_id: string\n first_prompt: string\n}\ninterface TaskHit {\n id: string\n title?: string\n first_prompt?: string\n}\ninterface KbHit {\n page: { name: string; title?: string }\n score?: number\n}\n\ninterface AllResults {\n sessions: SessionHit[]\n tasks: TaskHit[]\n kb: KbHit[]\n}\n\nconst DEBOUNCE_MS = 250\nconst PER_ENTITY_LIMIT = 5\n\nasync function fetchJson<T>(url: string): Promise<T> {\n const res = await fetch(url)\n if (!res.ok) throw new Error(`${url} → ${res.status}`)\n return res.json() as Promise<T>\n}\n\nasync function runAll(q: string): Promise<AllResults> {\n const trimmed = q.trim().slice(0, 200)\n if (!trimmed) {\n return { sessions: [], tasks: [], kb: [] }\n }\n const encoded = encodeURIComponent(trimmed)\n const [sessRes, taskRes, kbRes] = await Promise.allSettled([\n fetchJson<SessionHit[]>(`/api/sessions?search=${encoded}&limit=${PER_ENTITY_LIMIT}`),\n fetchJson<{ tasks: TaskHit[] }>(`/api/tasks?search=${encoded}&limit=${PER_ENTITY_LIMIT}`),\n fetchJson<{ pages: KbHit[] }>(`/api/knowledge/query?q=${encoded}&strategy=keyword&max=${PER_ENTITY_LIMIT}`),\n ])\n return {\n sessions: sessRes.status === 'fulfilled' ? sessRes.value : [],\n tasks: taskRes.status === 'fulfilled' ? (taskRes.value.tasks ?? []) : [],\n kb: kbRes.status === 'fulfilled' ? (kbRes.value.pages ?? []) : [],\n }\n}\n\ninterface GlobalSearchProps {\n /** Called after the user navigates somewhere — Layout uses this to close\n * the Popover. */\n onNavigate?: () => void\n}\n\nexport default function GlobalSearch({ onNavigate }: GlobalSearchProps) {\n const navigate = useNavigate()\n const [query, setQuery] = useState('')\n const [results, setResults] = useState<AllResults | null>(null)\n const [loading, setLoading] = useState(false)\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null)\n const seqRef = useRef(0)\n\n useEffect(() => {\n if (timer.current) clearTimeout(timer.current)\n const q = query.trim()\n if (!q) {\n setResults(null)\n setLoading(false)\n return\n }\n setLoading(true)\n const seq = ++seqRef.current\n timer.current = setTimeout(async () => {\n const r = await runAll(q)\n if (seq !== seqRef.current) return // stale\n setResults(r)\n setLoading(false)\n }, DEBOUNCE_MS)\n return () => {\n if (timer.current) clearTimeout(timer.current)\n }\n }, [query])\n\n const goToBestEntity = useCallback(() => {\n if (!results) return\n // v4 (C-1): sessions/tasks both land at TasksHub (?q= is the search param\n // TasksHubPage reads, not ?search=). KB lands at the Context KB tab.\n const counts: Array<{ key: keyof AllResults; path: string; n: number }> = [\n { key: 'sessions', path: '/tasks', n: results.sessions.length },\n { key: 'tasks', path: '/tasks', n: results.tasks.length },\n { key: 'kb', path: '/context?tab=kb', n: results.kb.length },\n ]\n const best = counts.reduce((acc, c) => (c.n > acc.n ? c : acc), counts[0])\n if (best.n === 0) return\n const q = encodeURIComponent(query.trim())\n // Append ?q= to TasksHub; KB path already has its own query.\n const target = best.path.includes('?')\n ? `${best.path}&q=${q}`\n : `${best.path}?q=${q}`\n navigate(target)\n onNavigate?.()\n }, [results, query, navigate, onNavigate])\n\n const totalHits =\n (results?.sessions.length ?? 0) +\n (results?.tasks.length ?? 0) +\n (results?.kb.length ?? 0)\n\n const groups = useMemo(() => {\n if (!results) return []\n // v4 (C-1): all row clicks land directly on v4 routes — no /sessions/:id\n // → ParamRedirect → /tasks?session=… double-hop.\n return [\n {\n label: '会话',\n path: '/tasks',\n items: results.sessions.map((s) => ({\n key: `s-${s.session_id}`,\n label: s.first_prompt || `(${s.session_id.slice(0, 8)})`,\n onClick: () => {\n navigate(`/tasks?session=${encodeURIComponent(s.session_id)}`)\n onNavigate?.()\n },\n })),\n },\n {\n label: '任务',\n path: '/tasks',\n items: results.tasks.map((t) => ({\n key: `t-${t.id}`,\n label: t.title || t.first_prompt || `(任务 ${t.id.slice(0, 8)})`,\n onClick: () => {\n navigate(`/tasks?task=${encodeURIComponent(t.id)}`)\n onNavigate?.()\n },\n })),\n },\n {\n label: '知识库',\n path: '/context?tab=kb',\n items: results.kb.map((k) => ({\n key: `k-${k.page.name}`,\n label: k.page.title || k.page.name,\n onClick: () => {\n // ContextInsightsPage may consume ?page= for deep-scroll into a\n // specific KB page; for now landing on the KB tab is enough.\n navigate(`/context?tab=kb&page=${encodeURIComponent(k.page.name)}`)\n onNavigate?.()\n },\n })),\n },\n ]\n }, [results, navigate, onNavigate])\n\n return (\n <div style={{ width: 360, maxHeight: 480, overflowY: 'auto' }}>\n <Input.Search\n autoFocus\n value={query}\n onChange={setQuery}\n onPressEnter={goToBestEntity}\n placeholder=\"搜索 sessions / tasks / 知识库...\"\n allowClear\n prefix={<IconSearch />}\n style={{ width: '100%' }}\n />\n <div style={{ marginTop: 12 }}>\n {loading ? (\n <div style={{ display: 'flex', justifyContent: 'center', padding: '24px 0' }}>\n <Spin size={20} />\n </div>\n ) : !results ? (\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n 输入关键词后回车跳转到结果最多的页面。\n </Typography.Text>\n ) : totalHits === 0 ? (\n <Empty description=\"无匹配结果\" imgSrc=\"\" style={{ padding: '12px 0' }} />\n ) : (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>\n {groups.map((g) =>\n g.items.length === 0 ? null : (\n <div key={g.label}>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n marginBottom: 4,\n }}\n >\n <Typography.Text style={{ fontSize: 11, color: 'var(--color-text-3)' }}>\n {g.label}\n </Typography.Text>\n <Tag size=\"small\" color=\"gray\">{g.items.length}</Tag>\n </div>\n <ul style={{ listStyle: 'none', padding: 0, margin: 0 }}>\n {g.items.map((it) => (\n <li\n key={it.key}\n onClick={it.onClick}\n style={{\n padding: '6px 8px',\n fontSize: 12,\n color: 'var(--color-text-1)',\n cursor: 'pointer',\n borderRadius: 4,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = 'var(--color-fill-2)'\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = 'transparent'\n }}\n >\n {it.label}\n </li>\n ))}\n </ul>\n </div>\n ),\n )}\n </div>\n )}\n </div>\n </div>\n )\n}\n","/**\n * NotificationPanel — topbar bell Popover content.\n *\n * Two tabs:\n * - 违规 → /api/violations?days=7&limit=10\n * - 反模式 → /api/insights?days=7 (severity = critical | warn | info)\n *\n * v1 doesn't track read-state — the red dot is purely a function of \"any\n * violations or any critical/warn anti-patterns in the past 7 days\".\n */\n\nimport { useQuery } from '@tanstack/react-query'\nimport { useNavigate } from 'react-router-dom'\nimport Tabs from '@arco-design/web-react/es/Tabs'\nimport Empty from '@arco-design/web-react/es/Empty'\nimport Tag from '@arco-design/web-react/es/Tag'\nimport Skeleton from '@arco-design/web-react/es/Skeleton'\nimport Typography from '@arco-design/web-react/es/Typography'\n\ninterface ApiViolation {\n timestamp: string\n summary: string\n signal: 'routing_disobeyed' | 'user_keyword'\n detectedKeyword: string | null\n expectedAgent: string | null\n relativeTime: string\n}\ninterface ViolationsResponse {\n count: number\n violations: ApiViolation[]\n}\n\ninterface AntiPattern {\n id: string\n type: string\n severity: 'critical' | 'warn' | 'info'\n title: string\n description: string\n detectedAt: string\n sessionId?: string\n}\ninterface InsightsResponse {\n summary: { total: number; critical: number; warn: number; info: number }\n patterns: AntiPattern[]\n}\n\ninterface NotificationPanelProps {\n onClose?: () => void\n}\n\nexport default function NotificationPanel({ onClose }: NotificationPanelProps) {\n const navigate = useNavigate()\n\n const { data: vio, isLoading: vLoading } = useQuery({\n queryKey: ['notifications-violations'],\n queryFn: async (): Promise<ViolationsResponse> => {\n const res = await fetch('/api/violations?days=7&limit=10')\n if (!res.ok) throw new Error('Failed')\n return res.json()\n },\n refetchOnMount: 'always',\n })\n\n const { data: ins, isLoading: iLoading } = useQuery({\n queryKey: ['notifications-insights'],\n queryFn: async (): Promise<InsightsResponse> => {\n const res = await fetch('/api/insights?days=7')\n if (!res.ok) throw new Error('Failed')\n return res.json()\n },\n refetchOnMount: 'always',\n })\n\n const vCount = vio?.count ?? 0\n const iCount = (ins?.summary.critical ?? 0) + (ins?.summary.warn ?? 0)\n\n return (\n <div style={{ width: 360, maxHeight: 480, overflowY: 'auto' }}>\n <Tabs defaultActiveTab=\"violations\" size=\"mini\">\n <Tabs.TabPane key=\"violations\" title={`违规${vCount > 0 ? ` (${vCount})` : ''}`}>\n {vLoading ? (\n <Skeleton text={{ rows: 3 }} animation />\n ) : !vio || vio.count === 0 ? (\n <Empty description=\"近 7 天无违规\" imgSrc=\"\" style={{ padding: '12px 0' }} />\n ) : (\n <ul style={{ listStyle: 'none', padding: 0, margin: 0 }}>\n {vio.violations.map((v) => (\n <li\n key={v.timestamp + v.summary.slice(0, 16)}\n style={{\n padding: '8px 4px',\n borderBottom: '1px solid var(--color-border-2)',\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>\n <Tag size=\"small\" color={v.signal === 'user_keyword' ? 'red' : 'orange'}>\n {v.signal === 'user_keyword' ? '关键词' : '路由'}\n </Tag>\n <span style={{ fontSize: 11, color: 'var(--color-text-3)' }}>{v.relativeTime}</span>\n </div>\n <div\n style={{\n fontSize: 12,\n color: 'var(--color-text-1)',\n marginTop: 4,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n title={v.summary}\n >\n {v.summary.slice(0, 60)}\n {v.summary.length > 60 ? '…' : ''}\n </div>\n </li>\n ))}\n </ul>\n )}\n </Tabs.TabPane>\n <Tabs.TabPane key=\"insights\" title={`反模式${iCount > 0 ? ` (${iCount})` : ''}`}>\n {iLoading ? (\n <Skeleton text={{ rows: 3 }} animation />\n ) : !ins || ins.patterns.length === 0 ? (\n <Empty description=\"近 7 天无反模式\" imgSrc=\"\" style={{ padding: '12px 0' }} />\n ) : (\n <ul style={{ listStyle: 'none', padding: 0, margin: 0 }}>\n {ins.patterns.slice(0, 10).map((p) => (\n <li\n key={p.id}\n style={{\n padding: '8px 4px',\n borderBottom: '1px solid var(--color-border-2)',\n cursor: p.sessionId ? 'pointer' : 'default',\n }}\n onClick={() => {\n if (p.sessionId) {\n // v4 (C-2): direct to /tasks?session=… avoids\n // /sessions/:id → ParamRedirect double-hop.\n navigate(`/tasks?session=${encodeURIComponent(p.sessionId)}`)\n onClose?.()\n }\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>\n <Tag\n size=\"small\"\n color={\n p.severity === 'critical' ? 'red' : p.severity === 'warn' ? 'orange' : 'gray'\n }\n >\n {p.severity}\n </Tag>\n <Typography.Text style={{ fontSize: 12, fontWeight: 500 }}>\n {p.title}\n </Typography.Text>\n </div>\n <div\n style={{\n fontSize: 11,\n color: 'var(--color-text-3)',\n marginTop: 4,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n title={p.description}\n >\n {p.description}\n </div>\n </li>\n ))}\n </ul>\n )}\n </Tabs.TabPane>\n </Tabs>\n </div>\n )\n}\n","/**\n * SQLite stores ISO timestamps without 'Z' suffix.\n * JS `new Date()` treats such strings as local time, causing an offset.\n * This helper ensures the timestamp is always parsed as UTC.\n *\n * @deprecated Use parseTimestamp() for new code.\n */\nexport function parseUTC(timestamp: string | null | undefined): Date {\n if (!timestamp) return new Date(0);\n const s = timestamp.trim();\n if (s.endsWith('Z') || /[+-]\\d{2}:\\d{2}$/.test(s)) {\n return new Date(s);\n }\n return new Date(s + 'Z');\n}\n\n// ─── Mirrored from src/core/utils/time.ts (spec 1635) ─────────────────────\n// Browser-compatible: no process.env, no Node-only APIs.\n\n/**\n * 归一化时间戳,确保带 Z 后缀\n */\nfunction normalizeTimestamp(timestamp: string): string {\n if (!timestamp) return new Date().toISOString();\n return timestamp.endsWith('Z') ? timestamp : timestamp + 'Z';\n}\n\n/**\n * 将\"可能 naive 的 UTC ISO 串\"安全转换为 Date 实例。\n * string 入参走 normalizeTimestamp 补 Z;number 入参直通 new Date(n)(毫秒值)。\n * 非法输入返回 epoch(不抛错)。\n *\n * 例:'2026-05-27T08:24:13.123' (naive UTC) → Date 表示 16:24 local (UTC+8)\n */\nexport function parseTimestamp(ts: string | number): Date {\n if (typeof ts === 'number') {\n return new Date(ts);\n }\n try {\n return new Date(normalizeTimestamp(ts));\n } catch {\n return new Date(0);\n }\n}\n\nfunction pad2(n: number): string {\n return n < 10 ? `0${n}` : `${n}`;\n}\n\n/**\n * 格式化为本地时区显示,默认 `2026-05-27 16:24 CST`。\n * opts.includeSeconds: 输出 `2026-05-27 16:24:13 CST`\n * opts.dateOnly: 输出 `2026-05-27`\n * opts.tzSuffix: 默认 'CST';传 '' 跳过后缀\n * 非法输入返回 '—'。\n */\nexport function formatLocalDisplay(\n ts: string | number,\n opts?: { includeSeconds?: boolean; dateOnly?: boolean; tzSuffix?: string },\n): string {\n try {\n const d = parseTimestamp(ts);\n if (isNaN(d.getTime())) return '—';\n const yyyy = d.getFullYear();\n const mm = pad2(d.getMonth() + 1);\n const dd = pad2(d.getDate());\n if (opts?.dateOnly) return `${yyyy}-${mm}-${dd}`;\n const hh = pad2(d.getHours());\n const min = pad2(d.getMinutes());\n const base = `${yyyy}-${mm}-${dd} ${hh}:${min}`;\n const withSec = opts?.includeSeconds ? `:${pad2(d.getSeconds())}` : '';\n const suffix = opts?.tzSuffix !== undefined ? opts.tzSuffix : 'CST';\n return suffix ? `${base}${withSec} ${suffix}` : `${base}${withSec}`;\n } catch {\n return '—';\n }\n}\n\n/**\n * 格式化为 UTC 显示,`2026-05-27 08:24 UTC`。\n * opts.includeSeconds: 加 `:13`\n * opts.dateOnly: 仅 `2026-05-27`(UTC 日期)\n * 非法输入返回 '—'。\n */\nexport function formatUTCDisplay(\n ts: string | number,\n opts?: { includeSeconds?: boolean; dateOnly?: boolean },\n): string {\n try {\n const d = parseTimestamp(ts);\n if (isNaN(d.getTime())) return '—';\n const yyyy = d.getUTCFullYear();\n const mm = pad2(d.getUTCMonth() + 1);\n const dd = pad2(d.getUTCDate());\n if (opts?.dateOnly) return `${yyyy}-${mm}-${dd}`;\n const hh = pad2(d.getUTCHours());\n const min = pad2(d.getUTCMinutes());\n const base = `${yyyy}-${mm}-${dd} ${hh}:${min}`;\n const withSec = opts?.includeSeconds ? `:${pad2(d.getUTCSeconds())}` : '';\n return `${base}${withSec} UTC`;\n } catch {\n return '—';\n }\n}\n\n/**\n * 相对时间:`刚刚` / `5 分钟前` / `2 小时前` / `3 天前`。\n * 非法或未来时间返回 '刚刚'。\n */\nexport function formatRelative(ts: string | number): string {\n try {\n const d = parseTimestamp(ts);\n if (isNaN(d.getTime())) return '—';\n const diff = Date.now() - d.getTime();\n const mins = Math.floor(diff / 60000);\n if (mins < 1) return '刚刚';\n if (mins < 60) return `${mins} 分钟前`;\n const hours = Math.floor(mins / 60);\n if (hours < 24) return `${hours} 小时前`;\n return `${Math.floor(hours / 24)} 天前`;\n } catch {\n return '—';\n }\n}\n\n/**\n * 本地日期串(用于文件名),`2026-05-27`(本地时区)。\n * 省略参数时使用 Date.now()。\n */\nexport function formatLocalDateForFilename(ts?: string | number): string {\n const d = ts !== undefined ? parseTimestamp(ts) : new Date();\n if (isNaN(d.getTime())) return formatLocalDateForFilename();\n const yyyy = d.getFullYear();\n const mm = pad2(d.getMonth() + 1);\n const dd = pad2(d.getDate());\n return `${yyyy}-${mm}-${dd}`;\n}\n","/**\n * DaemonBadge — top-bar indicator for daemon liveness.\n *\n * Polls /api/health every 30s and renders a small colored dot + label:\n * green = ALIVE (heartbeat fresh)\n * orange = STALE (heartbeat > 3min ago but PID still alive)\n * red = DEAD (no PID or heartbeat absent)\n *\n * Clicking the badge navigates to /daemon-health.\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 { useNavigate } from 'react-router-dom'\nimport { Tooltip } from '@arco-design/web-react'\nimport { 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\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\nconst STATUS_CONFIG = {\n alive: {\n color: '#00b42a', // green\n label: 'Daemon ALIVE',\n dotStyle: { background: '#00b42a' },\n },\n stale: {\n color: '#ff7d00', // orange\n label: 'Daemon STALE',\n dotStyle: { background: '#ff7d00' },\n },\n dead: {\n color: '#f53f3f', // red\n label: 'Daemon DEAD',\n dotStyle: { background: '#f53f3f' },\n },\n} as const\n\nexport default function DaemonBadge() {\n const navigate = useNavigate()\n\n const { data } = useQuery<HealthResponse>({\n queryKey: ['daemon-health'],\n queryFn: async () => {\n const res = await fetch('/api/health')\n if (!res.ok) throw new Error('health check failed')\n return res.json()\n },\n refetchInterval: 30_000,\n retry: false,\n staleTime: 15_000,\n })\n\n const status = data?.daemon?.status ?? 'dead'\n const cfg = STATUS_CONFIG[status]\n const heartbeatAgeMs = data?.daemon?.heartbeat_age_ms ?? null\n const pid = data?.daemon?.pid\n\n const tooltipContent = [\n `Status: ${status.toUpperCase()}`,\n pid != null ? `PID: ${pid}` : 'PID: not running',\n `Heartbeat: ${formatAge(heartbeatAgeMs)}`,\n ].join('\\n')\n\n return (\n <Tooltip\n content={<span style={{ whiteSpace: 'pre-line' }}>{tooltipContent}</span>}\n position=\"bottom\"\n >\n <button\n onClick={() => navigate('/daemon-health')}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: 5,\n border: 'none',\n background: 'transparent',\n cursor: 'pointer',\n padding: '4px 8px',\n borderRadius: 6,\n color: 'var(--color-text-2)',\n fontSize: 12,\n }}\n aria-label={`daemon-badge-${status}`}\n >\n <span\n style={{\n width: 8,\n height: 8,\n borderRadius: '50%',\n display: 'inline-block',\n ...cfg.dotStyle,\n ...(status === 'alive'\n ? {\n boxShadow: `0 0 0 2px ${cfg.color}33`,\n animation: 'daemon-pulse 2s infinite',\n }\n : {}),\n }}\n />\n <span style={{ color: cfg.color, fontWeight: 500 }}>{status.toUpperCase()}</span>\n </button>\n </Tooltip>\n )\n}\n","/**\n * DoctorBadge — top-bar indicator for `cf doctor` aggregate health.\n *\n * Polls /api/diagnostics every 60s. Colors:\n * green = all checks pass (or only skip)\n * orange = some warn but no fail\n * red = at least one fail\n *\n * Clicking the badge navigates to /diagnostics.\n *\n * Spec: docs/design/2026-06-01/1030-cf-doctor-diagnostic-spec.md\n */\n\nimport { useQuery } from '@tanstack/react-query'\nimport { useNavigate } from 'react-router-dom'\nimport { Tooltip } from '@arco-design/web-react'\n\ninterface DiagnosticsResponse {\n summary: {\n pass: number\n warn: number\n fail: number\n skip: number\n fixable: number\n }\n checks: Array<{ id: number; name: string; status: string }>\n generated_at: string\n}\n\ntype BadgeStatus = 'pass' | 'warn' | 'fail' | 'unknown'\n\nfunction pickStatus(d: DiagnosticsResponse | undefined): BadgeStatus {\n if (!d) return 'unknown'\n if (d.summary.fail > 0) return 'fail'\n if (d.summary.warn > 0) return 'warn'\n return 'pass'\n}\n\nconst STATUS_CONFIG: Record<BadgeStatus, { color: string; label: string }> = {\n pass: { color: '#00b42a', label: 'Doctor OK' },\n warn: { color: '#ff7d00', label: 'Doctor WARN' },\n fail: { color: '#f53f3f', label: 'Doctor FAIL' },\n unknown: { color: '#86909c', label: 'Doctor ?' },\n}\n\nexport default function DoctorBadge() {\n const navigate = useNavigate()\n const { data } = useQuery<DiagnosticsResponse>({\n queryKey: ['diagnostics-badge'],\n queryFn: async () => {\n const res = await fetch('/api/diagnostics')\n if (!res.ok) throw new Error('diagnostics failed')\n return res.json()\n },\n refetchInterval: 60_000,\n retry: false,\n staleTime: 30_000,\n })\n\n const status = pickStatus(data)\n const cfg = STATUS_CONFIG[status]\n\n const tooltipContent = data\n ? [\n `PASS=${data.summary.pass}`,\n `WARN=${data.summary.warn}`,\n `FAIL=${data.summary.fail}`,\n `SKIP=${data.summary.skip}`,\n data.summary.fixable > 0 ? `${data.summary.fixable} fixable` : '',\n ]\n .filter(Boolean)\n .join(' · ')\n : 'Loading diagnostics…'\n\n return (\n <Tooltip content={tooltipContent} position=\"bottom\">\n <button\n onClick={() => navigate('/diagnostics')}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: 5,\n border: 'none',\n background: 'transparent',\n cursor: 'pointer',\n padding: '4px 8px',\n borderRadius: 6,\n color: 'var(--color-text-2)',\n fontSize: 12,\n }}\n aria-label={`doctor-badge-${status}`}\n >\n <span\n style={{\n width: 8,\n height: 8,\n borderRadius: '50%',\n display: 'inline-block',\n background: cfg.color,\n }}\n />\n <span style={{ color: cfg.color, fontWeight: 500 }}>{cfg.label}</span>\n </button>\n </Tooltip>\n )\n}\n","/**\n * Top-level Arco Layout for claude-forge web.\n *\n * Implements PR3-arco-1 + post-arco-2 cleanup:\n * - <Layout.Sider> with 220↔64 collapse + sectioned <Menu>\n * - <Layout.Header> with brand chip + search + topbar icons + avatar\n * - <Layout.Content> renders <Breadcrumb> + active page <Outlet>\n *\n * Multi-tab UI has been removed (user decision: sidebar-only navigation).\n * Breadcrumb is kept as an independent component driven by breadcrumb-map.\n */\n\nimport { Outlet, useLocation, useNavigate } from 'react-router-dom'\nimport { useCallback, useMemo, useState } from 'react'\nimport {\n Layout as ArcoLayout,\n Menu,\n Breadcrumb,\n Input,\n Space,\n Avatar,\n Tooltip,\n Popover,\n Badge,\n} from '@arco-design/web-react'\nimport { useQuery } from '@tanstack/react-query'\nimport {\n IconBook,\n IconSettings,\n IconSearch,\n IconNotification,\n IconSun,\n IconMoon,\n IconMenuFold,\n IconMenuUnfold,\n IconUser,\n IconDashboard,\n IconList,\n IconExclamationCircle,\n IconBranch,\n} from '@arco-design/web-react/icon'\n\nimport {\n resolveRouteMeta,\n ROUTE_META,\n} from '../lib/breadcrumb-map'\nimport { useTheme } from '../lib/theme'\nimport GlobalSearch from './GlobalSearch'\nimport NotificationPanel from './NotificationPanel'\nimport DaemonBadge from './DaemonBadge'\nimport DoctorBadge from './DoctorBadge'\n\nconst { Sider, Header, Content } = ArcoLayout\nconst MenuItem = Menu.Item\n\nconst PIN_DASHBOARD_KEY = '/health'\n\n// --- sidebar nav model -------------------------------------------------------\n\ninterface NavItem {\n key: string\n label: string\n icon: React.ReactNode\n}\n\n/**\n * v4 IA + spec 3 partial revert (2026-05-27): 一级 nav 5 项(用户反馈砍掉的\n * 5 page 里 4 page 实际日常需要 — /context, /context/skill, /context/agent,\n * /settings 全部恢复 active)。\n *\n * 仍然隐藏:/tuning(obeyed-ratio 在 HealthHomePage \"C4 主线程听劝率\" 卡片\n * 已可见,无独立入口)。\n *\n * Revert /tuning recipe 见 docs/implementation/2026-05-27/1404-spec3-*-changelog.md § 5.\n */\nconst NAV_ITEMS: NavItem[] = [\n { key: '/health', label: '整体健康度', icon: <IconDashboard /> },\n { key: '/tasks', label: '我的任务', icon: <IconList /> },\n { key: '/context', label: 'AI 在拿什么', icon: <IconBook /> },\n { key: '/decisions', label: '决策', icon: <IconBranch /> },\n { key: '/violations', label: '出问题了', icon: <IconExclamationCircle /> },\n { key: '/settings', label: '设置', icon: <IconSettings /> },\n]\n\n// --- helpers -----------------------------------------------------------------\n\n/** Match the sidebar Menu's selectedKey for a given pathname (v4 IA + spec 3 partial revert). */\nfunction deriveMenuKey(pathname: string): string {\n const clean = pathname.replace(/\\/$/, '') || '/health'\n if (clean === '/health' || clean.startsWith('/health/')) return '/health'\n if (clean === '/tasks' || clean.startsWith('/tasks/')) return '/tasks'\n if (clean === '/context' || clean.startsWith('/context/')) return '/context'\n if (clean === '/decisions' || clean.startsWith('/decisions/')) return '/decisions'\n if (clean === '/violations' || clean.startsWith('/violations/')) return '/violations'\n if (clean === '/settings' || clean.startsWith('/settings/')) return '/settings'\n // Fallback for transient legacy paths before redirect kicks in (e.g. while\n // /tuning LegacyRedirect is mid-flight to /health).\n return '/health'\n}\n\n// --- component ---------------------------------------------------------------\n\nexport default function Layout() {\n const location = useLocation()\n const navigate = useNavigate()\n const [collapsed, setCollapsed] = useState(false)\n const [theme, setTheme] = useTheme()\n\n // --- menu handlers ---------------------------------------------------------\n\n const menuSelectedKey = useMemo(\n () => deriveMenuKey(location.pathname),\n [location.pathname],\n )\n\n const handleMenuClick = useCallback(\n (key: string) => {\n if (key !== location.pathname) navigate(key)\n },\n [location.pathname, navigate],\n )\n\n // --- breadcrumb ------------------------------------------------------------\n\n const breadcrumbs = useMemo(() => {\n const meta = resolveRouteMeta(location.pathname)\n return meta?.breadcrumbs ?? [{ label: '整体健康度' }]\n }, [location.pathname])\n\n // --- theme toggle (wired in PR3-arco-4, persisted via lib/theme) -----------\n\n const toggleTheme = useCallback(() => {\n setTheme(theme === 'light' ? 'dark' : 'light')\n }, [theme, setTheme])\n\n // --- topbar search + notifications (PR3-arco-4) ---------------------------\n\n const [searchOpen, setSearchOpen] = useState(false)\n const [notifOpen, setNotifOpen] = useState(false)\n\n // Red dot: any violation OR any critical/warn anti-pattern in past 7d.\n const { data: notifBadge } = useQuery({\n queryKey: ['notifications-badge'],\n queryFn: async (): Promise<{ hasUnread: boolean }> => {\n try {\n const [vRes, iRes] = await Promise.all([\n fetch('/api/violations?days=7&limit=1'),\n fetch('/api/insights?days=7'),\n ])\n const v = vRes.ok ? await vRes.json() : { count: 0 }\n const i = iRes.ok ? await iRes.json() : { summary: { critical: 0, warn: 0 } }\n return {\n hasUnread:\n (v.count ?? 0) > 0 ||\n (i.summary?.critical ?? 0) + (i.summary?.warn ?? 0) > 0,\n }\n } catch {\n return { hasUnread: false }\n }\n },\n refetchInterval: 60000,\n })\n const hasUnread = notifBadge?.hasUnread ?? false\n\n // --- render ----------------------------------------------------------------\n\n return (\n <ArcoLayout style={{ minHeight: '100vh' }}>\n <Sider\n collapsed={collapsed}\n collapsible\n collapsedWidth={64}\n width={220}\n trigger={null}\n breakpoint=\"lg\"\n style={{\n background: 'var(--color-bg-2)',\n borderRight: '1px solid var(--color-border)',\n }}\n >\n <div\n style={{\n height: 64,\n display: 'flex',\n alignItems: 'center',\n justifyContent: collapsed ? 'center' : 'flex-start',\n padding: collapsed ? 0 : '0 20px',\n borderBottom: '1px solid var(--color-border-2)',\n gap: 10,\n }}\n >\n <span className=\"cf-brand-chip\">CF</span>\n {!collapsed && (\n <span style={{ fontSize: 14, fontWeight: 600, color: 'var(--color-text-1)' }}>\n Claude Forge\n </span>\n )}\n </div>\n\n <Menu\n selectedKeys={[menuSelectedKey]}\n mode=\"vertical\"\n onClickMenuItem={handleMenuClick}\n style={{ width: '100%', border: 'none', background: 'transparent' }}\n >\n {NAV_ITEMS.map((item) => (\n <MenuItem key={item.key}>\n {item.icon}\n {item.label}\n </MenuItem>\n ))}\n </Menu>\n\n {!collapsed && (\n <div\n style={{\n position: 'absolute',\n bottom: 0,\n left: 0,\n right: 0,\n padding: '12px 16px',\n borderTop: '1px solid var(--color-border-2)',\n fontSize: 11,\n color: 'var(--color-text-3)',\n display: 'flex',\n justifyContent: 'space-between',\n }}\n >\n <span>claude-forge</span>\n <span style={{ fontFamily: 'monospace' }}>v{__APP_VERSION__}</span>\n </div>\n )}\n </Sider>\n\n <ArcoLayout>\n <Header\n style={{\n height: 60,\n background: 'var(--color-bg-2)',\n borderBottom: '1px solid var(--color-border)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '0 20px',\n }}\n >\n <Space size={12}>\n <Tooltip content={collapsed ? '展开侧栏' : '收起侧栏'}>\n <button\n onClick={() => setCollapsed((c) => !c)}\n style={{\n border: 'none',\n background: 'transparent',\n cursor: 'pointer',\n color: 'var(--color-text-2)',\n padding: 6,\n display: 'inline-flex',\n alignItems: 'center',\n }}\n aria-label=\"toggle-sider\"\n >\n {collapsed ? <IconMenuUnfold /> : <IconMenuFold />}\n </button>\n </Tooltip>\n <Popover\n trigger=\"click\"\n position=\"bl\"\n popupVisible={searchOpen}\n onVisibleChange={setSearchOpen}\n content={\n <GlobalSearch onNavigate={() => setSearchOpen(false)} />\n }\n >\n <Input.Search\n placeholder=\"搜索 sessions / tasks / 知识库...\"\n style={{ width: 280 }}\n allowClear\n readOnly\n prefix={<IconSearch />}\n onClick={() => setSearchOpen(true)}\n />\n </Popover>\n </Space>\n\n <Space size={16}>\n {/* Daemon health badge (watchdog spec 0843) */}\n <DaemonBadge />\n {/* Doctor diagnostic badge (spec 1a41b43a) */}\n <DoctorBadge />\n <Popover\n trigger=\"click\"\n position=\"br\"\n popupVisible={notifOpen}\n onVisibleChange={setNotifOpen}\n content={\n <NotificationPanel onClose={() => setNotifOpen(false)} />\n }\n >\n <Tooltip content=\"通知\">\n <button\n style={{\n border: 'none',\n background: 'transparent',\n cursor: 'pointer',\n color: 'var(--color-text-2)',\n padding: 6,\n display: 'inline-flex',\n alignItems: 'center',\n }}\n aria-label=\"notifications\"\n >\n <Badge dot={hasUnread} count={0} offset={[-2, 2]}>\n <IconNotification />\n </Badge>\n </button>\n </Tooltip>\n </Popover>\n <Tooltip content={theme === 'light' ? '切换深色主题' : '切换浅色主题'}>\n <button\n onClick={toggleTheme}\n style={{\n border: 'none',\n background: 'transparent',\n cursor: 'pointer',\n color: 'var(--color-text-2)',\n padding: 6,\n display: 'inline-flex',\n alignItems: 'center',\n }}\n aria-label=\"toggle-theme\"\n >\n {theme === 'light' ? <IconMoon /> : <IconSun />}\n </button>\n </Tooltip>\n <Avatar\n size={32}\n style={{ background: 'linear-gradient(135deg,#165DFF,#722ED1)' }}\n >\n <IconUser />\n </Avatar>\n </Space>\n </Header>\n\n <Content\n style={{\n padding: 0,\n background: 'var(--color-bg-2)',\n display: 'flex',\n flexDirection: 'column',\n minHeight: 'calc(100vh - 60px)',\n }}\n >\n <div style={{ padding: '12px 20px 0' }}>\n <Breadcrumb>\n {breadcrumbs.map((c, i) =>\n c.path ? (\n <Breadcrumb.Item key={`${c.label}-${i}`}>\n <a\n onClick={(e) => {\n e.preventDefault()\n if (c.path) navigate(c.path)\n }}\n href={c.path}\n style={{ color: 'var(--color-text-2)' }}\n >\n {c.label}\n </a>\n </Breadcrumb.Item>\n ) : (\n <Breadcrumb.Item key={`${c.label}-${i}`}>{c.label}</Breadcrumb.Item>\n ),\n )}\n </Breadcrumb>\n </div>\n\n <div style={{ padding: '16px 20px 24px', flex: 1 }}>\n <Outlet />\n </div>\n </Content>\n </ArcoLayout>\n </ArcoLayout>\n )\n}\n\n// Surface the known-routes set for tests / dev tools.\nexport { ROUTE_META, PIN_DASHBOARD_KEY }\n","/**\n * Legacy URL redirect React components — Phase E UI refactor (Step 8).\n *\n * Pure data + resolver live in `legacy-redirect-map.ts` (re-exported here\n * for backward-compat). These components are mounted by App.tsx routes.\n *\n * - <LegacyRedirect to=\".../?q=...\" /> plain redirect (no params)\n * - <ParamRedirect base=\"...\" param=\"...\" /> reads :param from URL and\n * forwards it as a query value\n *\n * Both use react-router-dom <Navigate replace> so the browser back button\n * does not loop on the old URL. The redirect entries are kept for 30 days\n * (spec § 3); cleanup tracked as a follow-up task.\n */\nimport { Navigate, useLocation, useParams } from 'react-router-dom'\n\nexport {\n LEGACY_REDIRECTS,\n resolveLegacyRedirect,\n type LegacyRedirectEntry,\n} from './legacy-redirect-map'\n\n/**\n * Merge two query strings. Keys present in `target` win over `current`\n * (so explicit redirect params override original ones), but any extra\n * params from `current` (e.g. `?session_id=xxx`) are preserved.\n */\nfunction mergeSearch(to: string, currentSearch: string): string {\n const [path, toQuery = ''] = to.split('?')\n const merged = new URLSearchParams(toQuery)\n const current = new URLSearchParams(currentSearch || '')\n for (const [k, v] of current.entries()) {\n if (!merged.has(k)) merged.set(k, v)\n }\n const q = merged.toString()\n return q ? `${path}?${q}` : path\n}\n\nexport function LegacyRedirect({ to }: { to: string }) {\n const location = useLocation()\n const target = mergeSearch(to, location.search)\n return <Navigate to={target} replace />\n}\n\n/**\n * Reads URL param `param` (e.g. `:id` or `:taskId`) and substitutes it\n * into the `tpl` query value. Template uses `{}` placeholder. Any\n * additional query string on the incoming URL is preserved (P2 fix).\n *\n * Example:\n * <ParamRedirect base=\"/pipeline\" param=\"id\" tpl=\"?view=session&session={}\" />\n * /sessions/abc123 → /pipeline?view=session&session=abc123\n * /sessions/abc123?foo=bar → /pipeline?view=session&session=abc123&foo=bar\n */\nexport function ParamRedirect({\n base,\n param,\n tpl,\n}: {\n base: string\n param: string\n tpl: string\n}) {\n const params = useParams<Record<string, string>>()\n const location = useLocation()\n const v = params[param] ?? ''\n const query = tpl.replace('{}', encodeURIComponent(v))\n const target = mergeSearch(`${base}${query}`, location.search)\n return <Navigate to={target} replace />\n}\n","import { lazy, Suspense } from 'react'\nimport { Routes, Route, Navigate } from 'react-router-dom'\nimport Layout from './components/Layout'\nimport { LegacyRedirect, ParamRedirect } from './lib/legacy-redirect'\n\n// v4 IA + spec 3 partial revert (2026-05-27): 7 active pages (3 keeper +\n// 4 restored after user feedback). Only /tuning stays hidden.\n// /health (默认) → HealthHomePage (整体健康度) — obeyed-ratio KPI ROW 3\n// /tasks → TasksHubPage (我的任务)\n// /context → ContextInsightsPage (AI 在拿什么 / 知识库入口)\n// /context/skill/:id → SkillContentPage (Skill 详情)\n// /context/agent/:name → AgentContentPage (Agent 详情)\n// /violations → ViolationsPage (出问题了)\n// /settings → SettingsPage (AI 设置)\n//\n// Still hidden (revert recipe in docs/implementation/2026-05-27/1404-spec3-*-changelog.md):\n// /tuning — obeyed-ratio 详情在 /health → \"C4 主线程听劝率\" 已可见\n//\n// 老 URL (v2: /sessions /tasks/:id /events /knowledge /skills /insights/*;\n// v3: /dashboard /pipeline /resources) 全部 LegacyRedirect 到 keeper page.\n// /ai-config 老路径在 sub-spec D R-C (spec 0902) 被永久删除(AI 配置面下线),\n// 不再 redirect — 现在落到 catch-all NotFound。\nconst HealthHomePage = lazy(() => import('./pages/HealthHomePage'))\nconst TasksHubPage = lazy(() => import('./pages/TasksHubPage'))\nconst ContextInsightsPage = lazy(() => import('./pages/ContextInsightsPage'))\nconst SkillContentPage = lazy(() => import('./pages/SkillContentPage'))\nconst AgentContentPage = lazy(() => import('./pages/AgentContentPage'))\nconst ViolationsPage = lazy(() => import('./pages/ViolationsPage'))\nconst SettingsPage = lazy(() => import('./pages/SettingsPage'))\nconst DaemonHealthPage = lazy(() => import('./pages/DaemonHealthPage'))\nconst DiagnosticsPage = lazy(() => import('./pages/DiagnosticsPage'))\nconst DecisionsPage = lazy(() => import('./pages/DecisionsPage'))\nconst NotFound = lazy(() => import('./components/NotFound'))\n\nfunction PageFallback() {\n return (\n <div className=\"flex items-center justify-center h-full py-16\">\n <div className=\"flex items-center gap-3 text-sm text-gray-500\">\n <div className=\"w-4 h-4 border-2 border-gray-300 border-t-blue-500 rounded-full animate-spin\" />\n 加载中...\n </div>\n </div>\n )\n}\n\nexport default function App() {\n return (\n <Routes>\n <Route path=\"/\" element={<Layout />}>\n {/* index → /health (v4 default) */}\n <Route index element={<Navigate to=\"/health\" replace />} />\n\n {/* === v4 active routes (3 keeper + 4 restored, spec 3 partial revert) === */}\n <Route\n path=\"health\"\n element={\n <Suspense fallback={<PageFallback />}>\n <HealthHomePage />\n </Suspense>\n }\n />\n <Route\n path=\"tasks\"\n element={\n <Suspense fallback={<PageFallback />}>\n <TasksHubPage />\n </Suspense>\n }\n />\n <Route\n path=\"context\"\n element={\n <Suspense fallback={<PageFallback />}>\n <ContextInsightsPage />\n </Suspense>\n }\n />\n {/* Skill / Agent content viewer (full-page fallback from drawer) */}\n <Route\n path=\"context/skill/:id\"\n element={\n <Suspense fallback={<PageFallback />}>\n <SkillContentPage />\n </Suspense>\n }\n />\n <Route\n path=\"context/agent/:name\"\n element={\n <Suspense fallback={<PageFallback />}>\n <AgentContentPage />\n </Suspense>\n }\n />\n <Route\n path=\"violations\"\n element={\n <Suspense fallback={<PageFallback />}>\n <ViolationsPage />\n </Suspense>\n }\n />\n <Route\n path=\"settings\"\n element={\n <Suspense fallback={<PageFallback />}>\n <SettingsPage />\n </Suspense>\n }\n />\n\n {/* === watchdog spec 0843: /daemon-health placeholder page === */}\n <Route\n path=\"daemon-health\"\n element={\n <Suspense fallback={<PageFallback />}>\n <DaemonHealthPage />\n </Suspense>\n }\n />\n\n {/* === spec 1a41b43a (2026-06-01): cf doctor /diagnostics page === */}\n <Route\n path=\"diagnostics\"\n element={\n <Suspense fallback={<PageFallback />}>\n <DiagnosticsPage />\n </Suspense>\n }\n />\n\n {/* === spec 1527 Commit 4: decision pipeline /decisions page === */}\n <Route\n path=\"decisions\"\n element={\n <Suspense fallback={<PageFallback />}>\n <DecisionsPage />\n </Suspense>\n }\n />\n\n {/* === spec 3 still-hidden page (only /tuning now) ===\n obeyed-ratio 在 HealthHomePage 已可见, /tuning revert recipe 见 changelog § 5. */}\n <Route path=\"tuning\" element={<LegacyRedirect to=\"/health\" />} />\n\n {/* === v3 legacy redirects === */}\n <Route path=\"dashboard\" element={<LegacyRedirect to=\"/health\" />} />\n <Route path=\"pipeline\" element={<LegacyRedirect to=\"/tasks\" />} />\n <Route path=\"resources\" element={<LegacyRedirect to=\"/context\" />} />\n\n {/* === v2 legacy redirects === */}\n <Route path=\"sessions\" element={<LegacyRedirect to=\"/tasks\" />} />\n <Route\n path=\"sessions/:id\"\n element={<ParamRedirect base=\"/tasks\" param=\"id\" tpl=\"?session={}\" />}\n />\n <Route\n path=\"tasks/:taskId\"\n element={<ParamRedirect base=\"/tasks\" param=\"taskId\" tpl=\"?task={}\" />}\n />\n <Route path=\"events\" element={<LegacyRedirect to=\"/tasks\" />} />\n <Route path=\"insights/pipeline\" element={<LegacyRedirect to=\"/tasks\" />} />\n <Route path=\"insights/timeline\" element={<LegacyRedirect to=\"/tasks\" />} />\n <Route path=\"insights/agent-board\" element={<LegacyRedirect to=\"/tasks\" />} />\n <Route path=\"insights/tuning\" element={<LegacyRedirect to=\"/health\" />} />\n <Route path=\"reports\" element={<LegacyRedirect to=\"/health\" />} />\n <Route path=\"knowledge\" element={<LegacyRedirect to=\"/context?tab=kb\" />} />\n <Route path=\"skills\" element={<LegacyRedirect to=\"/context?tab=skills\" />} />\n {/* /ai-config 永久下线 (sub-spec D R-C, spec 0902) — 不再 redirect,\n 落到 catch-all NotFound 给老链接 holder 明确反馈。 */}\n\n {/* === v4 catch-all 404 (C-3) === */}\n <Route\n path=\"*\"\n element={\n <Suspense fallback={<PageFallback />}>\n <NotFound />\n </Suspense>\n }\n />\n </Route>\n </Routes>\n )\n}\n","import { createContext, useContext, useState, useCallback, ReactNode } from 'react'\nimport { CheckCircle, XCircle, AlertCircle, Info, X } from 'lucide-react'\nimport clsx from 'clsx'\n\ntype ToastType = 'success' | 'error' | 'warning' | 'info'\n\ninterface Toast {\n id: number\n type: ToastType\n message: string\n}\n\ninterface ToastContextValue {\n show: (type: ToastType, message: string) => void\n success: (message: string) => void\n error: (message: string) => void\n warning: (message: string) => void\n info: (message: string) => void\n}\n\nconst ToastContext = createContext<ToastContextValue | null>(null)\n\nexport function useToast() {\n const ctx = useContext(ToastContext)\n if (!ctx) throw new Error('useToast must be used within ToastProvider')\n return ctx\n}\n\nlet nextId = 1\n\nexport function ToastProvider({ children }: { children: ReactNode }) {\n const [toasts, setToasts] = useState<Toast[]>([])\n\n const remove = useCallback((id: number) => {\n setToasts(prev => prev.filter(t => t.id !== id))\n }, [])\n\n const show = useCallback((type: ToastType, message: string) => {\n const id = nextId++\n setToasts(prev => [...prev, { id, type, message }])\n setTimeout(() => remove(id), 4000)\n }, [remove])\n\n const value: ToastContextValue = {\n show,\n success: (msg) => show('success', msg),\n error: (msg) => show('error', msg),\n warning: (msg) => show('warning', msg),\n info: (msg) => show('info', msg),\n }\n\n return (\n <ToastContext.Provider value={value}>\n {children}\n <div className=\"fixed top-4 right-4 z-[9999] space-y-2 max-w-md\">\n {toasts.map(t => (\n <ToastItem key={t.id} toast={t} onClose={() => remove(t.id)} />\n ))}\n </div>\n </ToastContext.Provider>\n )\n}\n\nfunction ToastItem({ toast, onClose }: { toast: Toast; onClose: () => void }) {\n const icons = {\n success: <CheckCircle className=\"h-5 w-5 text-green-500\" />,\n error: <XCircle className=\"h-5 w-5 text-red-500\" />,\n warning: <AlertCircle className=\"h-5 w-5 text-yellow-500\" />,\n info: <Info className=\"h-5 w-5 text-blue-500\" />,\n }\n const borderColors = {\n success: 'border-green-200',\n error: 'border-red-200',\n warning: 'border-yellow-200',\n info: 'border-blue-200',\n }\n\n return (\n <div\n className={clsx(\n 'bg-white shadow-lg rounded-lg border px-4 py-3 flex items-start gap-3 animate-in slide-in-from-right',\n borderColors[toast.type]\n )}\n >\n {icons[toast.type]}\n <div className=\"flex-1 text-sm text-gray-800\">{toast.message}</div>\n <button onClick={onClose} className=\"text-gray-400 hover:text-gray-600\">\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n )\n}\n","import { createContext, useContext, useState, useCallback, ReactNode } from 'react'\nimport { AlertTriangle } from 'lucide-react'\n\ninterface ConfirmOptions {\n title: string\n message: string\n confirmText?: string\n cancelText?: string\n variant?: 'danger' | 'warning' | 'info'\n}\n\ninterface ConfirmContextValue {\n confirm: (options: ConfirmOptions) => Promise<boolean>\n}\n\nconst ConfirmContext = createContext<ConfirmContextValue | null>(null)\n\nexport function useConfirm() {\n const ctx = useContext(ConfirmContext)\n if (!ctx) throw new Error('useConfirm must be used within ConfirmProvider')\n return ctx.confirm\n}\n\nexport function ConfirmProvider({ children }: { children: ReactNode }) {\n const [state, setState] = useState<{\n open: boolean\n options: ConfirmOptions | null\n resolve: ((value: boolean) => void) | null\n }>({ open: false, options: null, resolve: null })\n\n const confirm = useCallback((options: ConfirmOptions): Promise<boolean> => {\n return new Promise((resolve) => {\n setState({ open: true, options, resolve })\n })\n }, [])\n\n const handleClose = (result: boolean) => {\n if (state.resolve) state.resolve(result)\n setState({ open: false, options: null, resolve: null })\n }\n\n const variant = state.options?.variant || 'danger'\n const iconColor = {\n danger: 'text-red-600',\n warning: 'text-yellow-600',\n info: 'text-blue-600',\n }[variant]\n const btnColor = {\n danger: 'bg-red-600 hover:bg-red-700',\n warning: 'bg-yellow-600 hover:bg-yellow-700',\n info: 'bg-indigo-600 hover:bg-indigo-700',\n }[variant]\n\n return (\n <ConfirmContext.Provider value={{ confirm }}>\n {children}\n {state.open && state.options && (\n <div className=\"fixed inset-0 z-[9999] flex items-center justify-center\">\n <div\n className=\"absolute inset-0 bg-black bg-opacity-50\"\n onClick={() => handleClose(false)}\n />\n <div className=\"relative bg-white rounded-lg shadow-xl max-w-md w-full mx-4 p-6\">\n <div className=\"flex items-start gap-4\">\n <div className={`flex-shrink-0 ${iconColor}`}>\n <AlertTriangle className=\"h-6 w-6\" />\n </div>\n <div className=\"flex-1\">\n <h3 className=\"text-lg font-semibold text-gray-900 mb-2\">\n {state.options.title}\n </h3>\n <p className=\"text-sm text-gray-600 whitespace-pre-wrap\">\n {state.options.message}\n </p>\n </div>\n </div>\n <div className=\"flex justify-end gap-2 mt-6\">\n <button\n onClick={() => handleClose(false)}\n className=\"px-4 py-2 text-sm text-gray-700 bg-white border border-gray-300 rounded hover:bg-gray-50\"\n >\n {state.options.cancelText || '取消'}\n </button>\n <button\n onClick={() => handleClose(true)}\n className={`px-4 py-2 text-sm text-white rounded ${btnColor}`}\n >\n {state.options.confirmText || '确定'}\n </button>\n </div>\n </div>\n </div>\n )}\n </ConfirmContext.Provider>\n )\n}\n","import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { BrowserRouter } from 'react-router-dom'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { ConfigProvider } from '@arco-design/web-react'\nimport zhCN from '@arco-design/web-react/es/locale/zh-CN'\nimport App from './App'\nimport { ToastProvider } from './components/Toast'\nimport { ConfirmProvider } from './components/Confirm'\n\n// Apply theme attribute to <body> before first paint to avoid light/dark flash.\nimport './lib/theme'\n\n// Style load order matters — see ./index.css header.\nimport '@arco-design/web-react/dist/css/arco.css'\nimport './styles/arco-override.css'\nimport './styles/arco-tweaks.css'\nimport './index.css'\n\nconst queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n refetchOnWindowFocus: false,\n retry: 1,\n // Perf: cache-first for route switches. 60s staleTime means revisiting\n // /health or /tasks within a minute reuses cached data (0ms backend wait).\n // 5min gcTime keeps inactive query cache around for navigation patterns.\n staleTime: 60_000,\n gcTime: 5 * 60_000,\n },\n },\n})\n\nReactDOM.createRoot(document.getElementById('root')!).render(\n <React.StrictMode>\n <QueryClientProvider client={queryClient}>\n <ConfigProvider locale={zhCN}>\n <ToastProvider>\n <ConfirmProvider>\n <BrowserRouter>\n <App />\n </BrowserRouter>\n </ConfirmProvider>\n </ToastProvider>\n </ConfigProvider>\n </QueryClientProvider>\n </React.StrictMode>,\n)\n"],"file":"assets/index-BIYnq1Dx.js"}
@@ -1,2 +0,0 @@
1
- import{r as i}from"./react-vendor-tkvCrao7.js";import{d as m}from"./react-router-JVUrkhdd.js";function P(r,t,s){return r&&t.includes(r)?r:s}function l(r,t,s="tab"){const[e,a]=m(),n=e.get(s),u=i.useMemo(()=>P(n,r,t),[n,r,t]),b=i.useCallback(o=>{const c=new URLSearchParams(e);o===t?c.delete(s):c.set(s,o),a(c,{replace:!1})},[e,a,t,s]);return{tab:u,setTab:b}}export{l as u};
2
- //# sourceMappingURL=useTabsParam-k8qte_0C.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useTabsParam-k8qte_0C.js","sources":["../../src/hooks/useTabsParam.ts"],"sourcesContent":["/**\n * useTabsParam — generic ?tab=<key> URL-param state hook.\n *\n * Three v4 IA pages (Context / Violations / Settings) all reimplemented the\n * same scaffold: a `KNOWN[]` array, a `parseTab` clamp, and a `handleChange`\n * that wrote/deleted the URL param. This hook consolidates that logic so the\n * pages keep their own `<Tabs>` JSX but share the URL-state plumbing.\n *\n * Design notes:\n * - We DO NOT wrap Arco `<Tabs>` — that's over-abstraction. Each page still\n * owns its tab JSX (tab titles, lazy-loading, icons differ per page).\n * - When `tab === defaultKey`, the URL param is DELETED (clean URLs) — this\n * matches existing behavior in all 3 call sites pre-refactor.\n * - The `paramName` arg defaults to `'tab'`. SettingsPage passes `'section'`.\n *\n * Pure logic (`clampTab`) is exported separately so unit tests can cover it\n * without mounting React / react-router.\n */\n\nimport { useCallback, useMemo } from 'react'\nimport { useSearchParams } from 'react-router-dom'\n\n/**\n * Clamp an arbitrary string (or null) to the known tab set.\n * Returns `defaultKey` if `raw` is null, empty, or not in `known`.\n */\nexport function clampTab<K extends string>(\n raw: string | null,\n known: readonly K[],\n defaultKey: K,\n): K {\n if (!raw) return defaultKey\n if ((known as readonly string[]).includes(raw)) return raw as K\n return defaultKey\n}\n\nexport interface UseTabsParamResult<K extends string> {\n tab: K\n setTab: (key: K) => void\n}\n\nexport function useTabsParam<K extends string>(\n known: readonly K[],\n defaultKey: K,\n paramName: string = 'tab',\n): UseTabsParamResult<K> {\n const [searchParams, setSearchParams] = useSearchParams()\n const raw = searchParams.get(paramName)\n const tab = useMemo(() => clampTab(raw, known, defaultKey), [raw, known, defaultKey])\n\n const setTab = useCallback(\n (key: K) => {\n const next = new URLSearchParams(searchParams)\n if (key === defaultKey) next.delete(paramName)\n else next.set(paramName, key)\n setSearchParams(next, { replace: false })\n },\n // searchParams identity is stable per render from react-router; setSearchParams is also stable.\n [searchParams, setSearchParams, defaultKey, paramName],\n )\n\n return { tab, setTab }\n}\n"],"names":["clampTab","raw","known","defaultKey","useTabsParam","paramName","searchParams","setSearchParams","useSearchParams","tab","useMemo","setTab","useCallback","key","next"],"mappings":"8FA0BO,SAASA,EACdC,EACAC,EACAC,EACG,CACH,OAAKF,GACAC,EAA4B,SAASD,CAAG,EAAUA,EADtCE,CAGnB,CAOO,SAASC,EACdF,EACAC,EACAE,EAAoB,MACG,CACvB,KAAM,CAACC,EAAcC,CAAe,EAAIC,EAAA,EAClCP,EAAMK,EAAa,IAAID,CAAS,EAChCI,EAAMC,EAAAA,QAAQ,IAAMV,EAASC,EAAKC,EAAOC,CAAU,EAAG,CAACF,EAAKC,EAAOC,CAAU,CAAC,EAE9EQ,EAASC,EAAAA,YACZC,GAAW,CACV,MAAMC,EAAO,IAAI,gBAAgBR,CAAY,EACzCO,IAAQV,EAAYW,EAAK,OAAOT,CAAS,EACxCS,EAAK,IAAIT,EAAWQ,CAAG,EAC5BN,EAAgBO,EAAM,CAAE,QAAS,EAAA,CAAO,CAC1C,EAEA,CAACR,EAAcC,EAAiBJ,EAAYE,CAAS,CAAA,EAGvD,MAAO,CAAE,IAAAI,EAAK,OAAAE,CAAA,CAChB"}