@joekytc/dsh-swarm 0.1.2 → 0.3.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 (603) hide show
  1. package/README.md +177 -140
  2. package/README.zh-CN.md +173 -126
  3. package/client/BoardCard.tsx +24 -2
  4. package/client/ConfigSection.tsx +162 -0
  5. package/client/ConfigSelect.tsx +71 -0
  6. package/client/KanbanBoard.tsx +3 -0
  7. package/client/KanbanTab.tsx +4 -3
  8. package/client/TaskDrawer.tsx +4 -26
  9. package/client/WorkflowRail.tsx +3 -1
  10. package/client/config-store.ts +92 -0
  11. package/client/config.css +110 -0
  12. package/client/index.ts +39 -4
  13. package/client/kanban.css +88 -2
  14. package/client/session-bridge.ts +39 -0
  15. package/client/timeline-model.ts +12 -1
  16. package/client/workflow-model.ts +3 -1
  17. package/lib/client.js +519 -56
  18. package/lib/config.d.ts +26 -2
  19. package/lib/config.js +20 -1
  20. package/lib/dispatcher/agent-runner.d.ts +37 -7
  21. package/lib/dispatcher/agent-runner.js +239 -86
  22. package/lib/dispatcher/chain-auditor.d.ts +4 -4
  23. package/lib/dispatcher/chain-auditor.js +14 -9
  24. package/lib/dispatcher/dispatcher.d.ts +69 -10
  25. package/lib/dispatcher/dispatcher.js +281 -42
  26. package/lib/dispatcher/event-waker.d.ts +1 -1
  27. package/lib/dispatcher/event-waker.js +2 -2
  28. package/lib/dispatcher/git-credentials.d.ts +2 -2
  29. package/lib/dispatcher/git-credentials.js +2 -2
  30. package/lib/dispatcher/model-candidates.d.ts +1 -1
  31. package/lib/dispatcher/model-candidates.js +1 -1
  32. package/lib/dispatcher/session-events.d.ts +12 -16
  33. package/lib/dispatcher/session-events.js +18 -6
  34. package/lib/dispatcher/target-repo.d.ts +2 -2
  35. package/lib/dispatcher/target-repo.js +3 -3
  36. package/lib/dispatcher/v-orchestrator.d.ts +44 -11
  37. package/lib/dispatcher/v-orchestrator.js +257 -49
  38. package/lib/dispatcher/watchdog.d.ts +1 -1
  39. package/lib/dispatcher/watchdog.js +2 -2
  40. package/lib/domain/config-override.d.ts +52 -0
  41. package/lib/domain/config-override.js +138 -0
  42. package/lib/domain/delivery-contract.d.ts +4 -3
  43. package/lib/domain/delivery-contract.js +30 -18
  44. package/lib/domain/delivery-evidence.d.ts +1 -1
  45. package/lib/domain/delivery-evidence.js +1 -1
  46. package/lib/domain/event-store.js +1 -1
  47. package/lib/domain/gate-policy.d.ts +26 -0
  48. package/lib/domain/gate-policy.js +44 -0
  49. package/lib/domain/im-message.d.ts +15 -0
  50. package/lib/domain/im-message.js +149 -0
  51. package/lib/domain/kanban-service.d.ts +28 -12
  52. package/lib/domain/kanban-service.js +73 -30
  53. package/lib/domain/memory.js +1 -1
  54. package/lib/domain/ocr-review.d.ts +47 -0
  55. package/lib/domain/ocr-review.js +105 -0
  56. package/lib/domain/permissions.js +6 -6
  57. package/lib/domain/planning-checklist.d.ts +5 -0
  58. package/lib/domain/planning-checklist.js +80 -6
  59. package/lib/domain/projection.js +8 -7
  60. package/lib/domain/review-evidence.js +1 -1
  61. package/lib/domain/state-machine.js +3 -2
  62. package/lib/domain/task-parents.js +1 -1
  63. package/lib/domain/types.d.ts +5 -5
  64. package/lib/index.js +28 -25
  65. package/lib/roles/clean-fs-tools.d.ts +22 -0
  66. package/lib/roles/clean-fs-tools.js +117 -0
  67. package/lib/roles/preset-installer.js +3 -3
  68. package/lib/roles/skill-installer.d.ts +6 -0
  69. package/lib/roles/skill-installer.js +32 -0
  70. package/lib/roles/toolsets.d.ts +71 -15
  71. package/lib/roles/toolsets.js +418 -68
  72. package/lib/roles/wiki-worker.d.ts +1 -0
  73. package/lib/roles/wiki-worker.js +12 -4
  74. package/lib/routes/kanban-http.d.ts +28 -2
  75. package/lib/routes/kanban-http.js +199 -6
  76. package/lib/routes/kanban-sse.d.ts +1 -1
  77. package/lib/routes/kanban-sse.js +1 -1
  78. package/lib/routes/planning-driver.d.ts +6 -2
  79. package/lib/routes/planning-driver.js +15 -7
  80. package/lib/routes/prefix-router.d.ts +19 -3
  81. package/lib/routes/prefix-router.js +40 -3
  82. package/lib/services/config-provider.d.ts +38 -0
  83. package/lib/services/config-provider.js +92 -0
  84. package/lib/services/gate-runner.d.ts +24 -0
  85. package/lib/services/gate-runner.js +87 -0
  86. package/lib/services/im-delivery.d.ts +94 -0
  87. package/lib/services/im-delivery.js +263 -0
  88. package/lib/services/kanban-provider.d.ts +6 -2
  89. package/lib/services/kanban-provider.js +41 -3
  90. package/lib/services/llm-catalog.d.ts +35 -0
  91. package/lib/services/llm-catalog.js +19 -0
  92. package/lib/services/ocr-cli.d.ts +35 -0
  93. package/lib/services/ocr-cli.js +128 -0
  94. package/lib/tools/kanban-tools.d.ts +2 -2
  95. package/lib/tools/kanban-tools.js +2 -1
  96. package/lib/tools/main-session-tools.d.ts +22 -3
  97. package/lib/tools/main-session-tools.js +135 -30
  98. package/lib/tools/ocr-review-tools.d.ts +11 -0
  99. package/lib/tools/ocr-review-tools.js +63 -0
  100. package/lib/tools/planning-tools.d.ts +8 -1
  101. package/lib/tools/planning-tools.js +44 -15
  102. package/lib/tools/prefetch-tools.js +1 -0
  103. package/lib/tools/spec-card-tools.js +1 -0
  104. package/lib/tools/wiki-tools.js +6 -5
  105. package/lib/wiki/kb-linkage.d.ts +9 -2
  106. package/lib/wiki/kb-linkage.js +3 -3
  107. package/lib/wiki/local-kb-client.d.ts +14 -0
  108. package/lib/wiki/local-kb-client.js +101 -0
  109. package/lib/wiki/local-kb.d.ts +6 -0
  110. package/lib/wiki/local-kb.js +25 -0
  111. package/lib/wiki/memory-recall.d.ts +14 -6
  112. package/lib/wiki/memory-recall.js +17 -13
  113. package/lib/wiki/page-path.d.ts +9 -3
  114. package/lib/wiki/page-path.js +33 -12
  115. package/lib/wiki/wiki-vault-client.d.ts +3 -3
  116. package/lib/wiki/wiki-vault-client.js +6 -6
  117. package/package.json +16 -11
  118. package/personas/kanban-d/agent.cordis.yml +5 -5
  119. package/personas/kanban-d/preset.yml +1 -1
  120. package/personas/kanban-dt/agent.cordis.yml +25 -7
  121. package/personas/kanban-dt/preset.yml +1 -1
  122. package/personas/kanban-p/agent.cordis.yml +19 -3
  123. package/personas/kanban-p/preset.yml +1 -1
  124. package/personas/kanban-pt/agent.cordis.yml +39 -9
  125. package/personas/kanban-pt/preset.yml +1 -1
  126. package/personas/kanban-v/agent.cordis.yml +3 -3
  127. package/personas/kanban-w/agent.cordis.yml +37 -18
  128. package/personas/kanban-w/preset.yml +1 -1
  129. package/personas/persona-d.md +1 -1
  130. package/personas/persona-dt.md +13 -5
  131. package/personas/persona-p.md +5 -2
  132. package/personas/persona-pt.md +13 -6
  133. package/personas/persona-v.md +2 -2
  134. package/personas/persona-w.md +11 -9
  135. package/personas/swarm/agent.cordis.yml +43 -0
  136. package/personas/swarm/preset.yml +5 -0
  137. package/skills/grill-me/SKILL.md +71 -0
  138. package/skills/llm-wiki-skill/.mise.toml +2 -0
  139. package/skills/llm-wiki-skill/.nvmrc +1 -0
  140. package/skills/llm-wiki-skill/AGENTS.md +173 -0
  141. package/skills/llm-wiki-skill/CHANGELOG.md +548 -0
  142. package/skills/llm-wiki-skill/CLAUDE.md +152 -0
  143. package/skills/llm-wiki-skill/HERMES.md +44 -0
  144. package/skills/llm-wiki-skill/README.en.md +261 -0
  145. package/skills/llm-wiki-skill/README.md +291 -0
  146. package/skills/llm-wiki-skill/SKILL.md +1133 -0
  147. package/skills/llm-wiki-skill/assets/graph-demo.gif +0 -0
  148. package/skills/llm-wiki-skill/assets/graph-preview.png +0 -0
  149. package/skills/llm-wiki-skill/deps/LICENSE-d3.txt +13 -0
  150. package/skills/llm-wiki-skill/deps/LICENSE-marked.txt +44 -0
  151. package/skills/llm-wiki-skill/deps/LICENSE-purify.txt +568 -0
  152. package/skills/llm-wiki-skill/deps/LICENSE-roughjs.txt +21 -0
  153. package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/SKILL.md +261 -0
  154. package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/references/config/first-time-setup.md +106 -0
  155. package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/cdp.ts +179 -0
  156. package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/constants.ts +13 -0
  157. package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/defuddle-converter.ts +58 -0
  158. package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/html-to-markdown.ts +135 -0
  159. package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/legacy-converter.ts +629 -0
  160. package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/main.ts +314 -0
  161. package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/markdown-conversion-shared.ts +305 -0
  162. package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/media-localizer.ts +317 -0
  163. package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/package.json +14 -0
  164. package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/paths.ts +29 -0
  165. package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/vendor/baoyu-chrome-cdp/package.json +9 -0
  166. package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/vendor/baoyu-chrome-cdp/src/index.test.ts +307 -0
  167. package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/vendor/baoyu-chrome-cdp/src/index.ts +523 -0
  168. package/skills/llm-wiki-skill/deps/d3.min.js +2 -0
  169. package/skills/llm-wiki-skill/deps/marked.min.js +6 -0
  170. package/skills/llm-wiki-skill/deps/purify.min.js +3 -0
  171. package/skills/llm-wiki-skill/deps/rough.min.js +7 -0
  172. package/skills/llm-wiki-skill/deps/youtube-transcript/SKILL.md +47 -0
  173. package/skills/llm-wiki-skill/deps/youtube-transcript/scripts/get_transcript.py +72 -0
  174. package/skills/llm-wiki-skill/designs/graph-edge-legibility/graph-edge-treatments.html +480 -0
  175. package/skills/llm-wiki-skill/docs/design/oriental-atlas/DESIGN.md +183 -0
  176. package/skills/llm-wiki-skill/docs/design/oriental-atlas/README.md +10 -0
  177. package/skills/llm-wiki-skill/docs/design/oriental-atlas/design-brief.md +170 -0
  178. package/skills/llm-wiki-skill/docs/design/oriental-atlas/oriental-editorial-atlas.html +1908 -0
  179. package/skills/llm-wiki-skill/docs/design/oriental-atlas/reviews/result-review.md +68 -0
  180. package/skills/llm-wiki-skill/docs/graph/2026-06-16-interaction-risk-audit.md +88 -0
  181. package/skills/llm-wiki-skill/docs/graph/2026-06-16-interaction-test-coverage-map.md +212 -0
  182. package/skills/llm-wiki-skill/docs/graph/performance/2026-06-18-phase-0-2-baseline.md +86 -0
  183. package/skills/llm-wiki-skill/docs/graph/performance/2026-06-18-phase-1-3-dom-svg-large-baseline.md +85 -0
  184. package/skills/llm-wiki-skill/docs/graph/performance/2026-06-18-phase-1-4-disposable-validation-gate.md +97 -0
  185. package/skills/llm-wiki-skill/docs/graph/performance/2026-06-18-phase-2-4-global-renderer-trial-matrix.md +168 -0
  186. package/skills/llm-wiki-skill/docs/graph/performance/2026-06-19-phase-6-1-sigma-graphology-trial.md +71 -0
  187. package/skills/llm-wiki-skill/docs/graph/performance/2026-06-19-phase-6-2-vis-network-trial.md +78 -0
  188. package/skills/llm-wiki-skill/docs/graph/performance/2026-06-19-phase-6-3-aggregation-fallback-trial.md +72 -0
  189. package/skills/llm-wiki-skill/docs/graph/performance/2026-06-19-phase-6-4-global-renderer-route-decision.md +94 -0
  190. package/skills/llm-wiki-skill/docs/graph/performance/2026-06-19-sigma-global-production-integration-result.md +102 -0
  191. package/skills/llm-wiki-skill/docs/graph/performance/artifacts/2026-06-18-phase-0-2/stage-4.5-offline-dense-wheel.json +9 -0
  192. package/skills/llm-wiki-skill/docs/graph/performance/artifacts/2026-06-18-phase-0-2/stage-4.5-offline-dense-wheel.png +0 -0
  193. package/skills/llm-wiki-skill/docs/graph/performance/artifacts/2026-06-18-phase-0-2/stage-4.5-offline-navigation.png +0 -0
  194. package/skills/llm-wiki-skill/docs/spark/2026-06-15-omp-tool-status-events-design.md +174 -0
  195. package/skills/llm-wiki-skill/docs/spark/2026-06-16-graph-interaction-geometry-design.md +832 -0
  196. package/skills/llm-wiki-skill/docs/spark/2026-06-16-graph-six-layer-architecture-design.md +577 -0
  197. package/skills/llm-wiki-skill/docs/spark/2026-06-17-static-renderer-coordination-split-design.md +172 -0
  198. package/skills/llm-wiki-skill/docs/spark/2026-06-18-large-graph-global-community-design.md +909 -0
  199. package/skills/llm-wiki-skill/docs/spark/2026-06-19-sigma-global-graph-renderer-design.md +360 -0
  200. package/skills/llm-wiki-skill/docs/spark/2026-06-20-paper-ui-port-design.md +162 -0
  201. package/skills/llm-wiki-skill/docs/spark/2026-06-20-paper-ui-v2-shell-alignment-design.md +384 -0
  202. package/skills/llm-wiki-skill/docs/spark/2026-06-21-graph-experience-completion-design.md +534 -0
  203. package/skills/llm-wiki-skill/docs/spark/2026-06-22-chat-auto-scroll-design.md +185 -0
  204. package/skills/llm-wiki-skill/docs/spark/2026-06-22-graph-community-node-visual-design.md +266 -0
  205. package/skills/llm-wiki-skill/docs/spark/2026-06-25-sigma-overlay-refactor-perf-design.md +170 -0
  206. package/skills/llm-wiki-skill/docs/spark/2026-06-26-global-sigma-community-spotlight-design.md +393 -0
  207. package/skills/llm-wiki-skill/docs/spark/mockups/2026-06-18-large-graph-global-community-flow.html +746 -0
  208. package/skills/llm-wiki-skill/install.ps1 +87 -0
  209. package/skills/llm-wiki-skill/install.sh +722 -0
  210. package/skills/llm-wiki-skill/package-lock.json +11171 -0
  211. package/skills/llm-wiki-skill/package.json +24 -0
  212. package/skills/llm-wiki-skill/packages/graph-engine/package.json +37 -0
  213. package/skills/llm-wiki-skill/packages/graph-engine/src/anim/.gitkeep +1 -0
  214. package/skills/llm-wiki-skill/packages/graph-engine/src/anim/index.ts +179 -0
  215. package/skills/llm-wiki-skill/packages/graph-engine/src/architecture.ts +79 -0
  216. package/skills/llm-wiki-skill/packages/graph-engine/src/diff.ts +121 -0
  217. package/skills/llm-wiki-skill/packages/graph-engine/src/facade.ts +1406 -0
  218. package/skills/llm-wiki-skill/packages/graph-engine/src/graph-node.ts +37 -0
  219. package/skills/llm-wiki-skill/packages/graph-engine/src/index.ts +25 -0
  220. package/skills/llm-wiki-skill/packages/graph-engine/src/layout/edge-geometry.ts +17 -0
  221. package/skills/llm-wiki-skill/packages/graph-engine/src/layout/index.ts +16 -0
  222. package/skills/llm-wiki-skill/packages/graph-engine/src/layout/spatial-index.ts +509 -0
  223. package/skills/llm-wiki-skill/packages/graph-engine/src/model/atlas.ts +18 -0
  224. package/skills/llm-wiki-skill/packages/graph-engine/src/model/index.ts +10 -0
  225. package/skills/llm-wiki-skill/packages/graph-engine/src/model/labels.ts +11 -0
  226. package/skills/llm-wiki-skill/packages/graph-engine/src/model/layout.ts +81 -0
  227. package/skills/llm-wiki-skill/packages/graph-engine/src/model/learning.ts +8 -0
  228. package/skills/llm-wiki-skill/packages/graph-engine/src/model/legacy-helpers.ts +1379 -0
  229. package/skills/llm-wiki-skill/packages/graph-engine/src/model/queue.ts +7 -0
  230. package/skills/llm-wiki-skill/packages/graph-engine/src/model/storage.ts +4 -0
  231. package/skills/llm-wiki-skill/packages/graph-engine/src/model/visibility.ts +9 -0
  232. package/skills/llm-wiki-skill/packages/graph-engine/src/render/.gitkeep +1 -0
  233. package/skills/llm-wiki-skill/packages/graph-engine/src/render/adapter.ts +443 -0
  234. package/skills/llm-wiki-skill/packages/graph-engine/src/render/aggregation-containers.ts +64 -0
  235. package/skills/llm-wiki-skill/packages/graph-engine/src/render/community-cloud-geometry.ts +178 -0
  236. package/skills/llm-wiki-skill/packages/graph-engine/src/render/community-wash.ts +238 -0
  237. package/skills/llm-wiki-skill/packages/graph-engine/src/render/community-washes.ts +19 -0
  238. package/skills/llm-wiki-skill/packages/graph-engine/src/render/compat-contract.ts +14 -0
  239. package/skills/llm-wiki-skill/packages/graph-engine/src/render/controller.ts +705 -0
  240. package/skills/llm-wiki-skill/packages/graph-engine/src/render/controls.ts +288 -0
  241. package/skills/llm-wiki-skill/packages/graph-engine/src/render/dom-svg-renderer.ts +180 -0
  242. package/skills/llm-wiki-skill/packages/graph-engine/src/render/edges.ts +51 -0
  243. package/skills/llm-wiki-skill/packages/graph-engine/src/render/geometry.ts +380 -0
  244. package/skills/llm-wiki-skill/packages/graph-engine/src/render/gestures.ts +673 -0
  245. package/skills/llm-wiki-skill/packages/graph-engine/src/render/graph-renderer-root.ts +387 -0
  246. package/skills/llm-wiki-skill/packages/graph-engine/src/render/hit-testing.ts +56 -0
  247. package/skills/llm-wiki-skill/packages/graph-engine/src/render/host-dom.ts +14 -0
  248. package/skills/llm-wiki-skill/packages/graph-engine/src/render/hover-card.ts +37 -0
  249. package/skills/llm-wiki-skill/packages/graph-engine/src/render/index.ts +213 -0
  250. package/skills/llm-wiki-skill/packages/graph-engine/src/render/keyboard.ts +48 -0
  251. package/skills/llm-wiki-skill/packages/graph-engine/src/render/legend.ts +25 -0
  252. package/skills/llm-wiki-skill/packages/graph-engine/src/render/minimap.ts +45 -0
  253. package/skills/llm-wiki-skill/packages/graph-engine/src/render/model.ts +1339 -0
  254. package/skills/llm-wiki-skill/packages/graph-engine/src/render/node-drag-lifecycle.ts +94 -0
  255. package/skills/llm-wiki-skill/packages/graph-engine/src/render/nodes.ts +103 -0
  256. package/skills/llm-wiki-skill/packages/graph-engine/src/render/offline-reader.ts +209 -0
  257. package/skills/llm-wiki-skill/packages/graph-engine/src/render/overlays-presenter.ts +192 -0
  258. package/skills/llm-wiki-skill/packages/graph-engine/src/render/overlays.ts +73 -0
  259. package/skills/llm-wiki-skill/packages/graph-engine/src/render/pin-position.ts +51 -0
  260. package/skills/llm-wiki-skill/packages/graph-engine/src/render/preview.ts +65 -0
  261. package/skills/llm-wiki-skill/packages/graph-engine/src/render/relation-focus.ts +91 -0
  262. package/skills/llm-wiki-skill/packages/graph-engine/src/render/render-context.ts +85 -0
  263. package/skills/llm-wiki-skill/packages/graph-engine/src/render/render-pipeline.ts +871 -0
  264. package/skills/llm-wiki-skill/packages/graph-engine/src/render/render-styles.ts +1405 -0
  265. package/skills/llm-wiki-skill/packages/graph-engine/src/render/renderer-surface.ts +75 -0
  266. package/skills/llm-wiki-skill/packages/graph-engine/src/render/search.ts +57 -0
  267. package/skills/llm-wiki-skill/packages/graph-engine/src/render/sigma-coordinates.ts +44 -0
  268. package/skills/llm-wiki-skill/packages/graph-engine/src/render/sigma-global-drag.ts +246 -0
  269. package/skills/llm-wiki-skill/packages/graph-engine/src/render/sigma-global-renderer.ts +1425 -0
  270. package/skills/llm-wiki-skill/packages/graph-engine/src/render/sigma-overlay-svg.ts +121 -0
  271. package/skills/llm-wiki-skill/packages/graph-engine/src/render/simulation-bridge.ts +59 -0
  272. package/skills/llm-wiki-skill/packages/graph-engine/src/render/state.ts +262 -0
  273. package/skills/llm-wiki-skill/packages/graph-engine/src/render/toolbar.ts +40 -0
  274. package/skills/llm-wiki-skill/packages/graph-engine/src/render/viewport.ts +336 -0
  275. package/skills/llm-wiki-skill/packages/graph-engine/src/select/.gitkeep +1 -0
  276. package/skills/llm-wiki-skill/packages/graph-engine/src/select/index.ts +189 -0
  277. package/skills/llm-wiki-skill/packages/graph-engine/src/sim/index.ts +372 -0
  278. package/skills/llm-wiki-skill/packages/graph-engine/src/sim/pins.ts +84 -0
  279. package/skills/llm-wiki-skill/packages/graph-engine/src/summary/index.ts +447 -0
  280. package/skills/llm-wiki-skill/packages/graph-engine/src/themes/.gitkeep +1 -0
  281. package/skills/llm-wiki-skill/packages/graph-engine/src/themes/index.ts +8 -0
  282. package/skills/llm-wiki-skill/packages/graph-engine/src/themes/tokens.ts +117 -0
  283. package/skills/llm-wiki-skill/packages/graph-engine/src/types/d3-quadtree.d.ts +22 -0
  284. package/skills/llm-wiki-skill/packages/graph-engine/src/types.ts +531 -0
  285. package/skills/llm-wiki-skill/packages/graph-engine/test/aggregation-fallback-trial-adapter.test.ts +115 -0
  286. package/skills/llm-wiki-skill/packages/graph-engine/test/aggregation-fallback-trial-adapter.ts +222 -0
  287. package/skills/llm-wiki-skill/packages/graph-engine/test/anim.test.ts +121 -0
  288. package/skills/llm-wiki-skill/packages/graph-engine/test/architecture.test.ts +63 -0
  289. package/skills/llm-wiki-skill/packages/graph-engine/test/community-cloud-geometry.test.ts +86 -0
  290. package/skills/llm-wiki-skill/packages/graph-engine/test/community-wash.test.ts +97 -0
  291. package/skills/llm-wiki-skill/packages/graph-engine/test/diff.test.ts +133 -0
  292. package/skills/llm-wiki-skill/packages/graph-engine/test/facade.test.ts +1369 -0
  293. package/skills/llm-wiki-skill/packages/graph-engine/test/geometry.test.ts +147 -0
  294. package/skills/llm-wiki-skill/packages/graph-engine/test/gestures.test.ts +768 -0
  295. package/skills/llm-wiki-skill/packages/graph-engine/test/graph-layout.test.ts +110 -0
  296. package/skills/llm-wiki-skill/packages/graph-engine/test/helpers.test.ts +287 -0
  297. package/skills/llm-wiki-skill/packages/graph-engine/test/interaction-contract.test.ts +106 -0
  298. package/skills/llm-wiki-skill/packages/graph-engine/test/keyboard.test.ts +59 -0
  299. package/skills/llm-wiki-skill/packages/graph-engine/test/large-fixtures.test.ts +47 -0
  300. package/skills/llm-wiki-skill/packages/graph-engine/test/large-graph-fixtures.ts +420 -0
  301. package/skills/llm-wiki-skill/packages/graph-engine/test/learning.test.ts +259 -0
  302. package/skills/llm-wiki-skill/packages/graph-engine/test/node-drag-lifecycle.test.ts +166 -0
  303. package/skills/llm-wiki-skill/packages/graph-engine/test/overlays.test.ts +115 -0
  304. package/skills/llm-wiki-skill/packages/graph-engine/test/preview.test.ts +56 -0
  305. package/skills/llm-wiki-skill/packages/graph-engine/test/queue.test.ts +114 -0
  306. package/skills/llm-wiki-skill/packages/graph-engine/test/relation-focus.test.ts +115 -0
  307. package/skills/llm-wiki-skill/packages/graph-engine/test/render-model.test.ts +1030 -0
  308. package/skills/llm-wiki-skill/packages/graph-engine/test/renderer-adapter-contract.test.ts +271 -0
  309. package/skills/llm-wiki-skill/packages/graph-engine/test/renderer-boundary.test.ts +618 -0
  310. package/skills/llm-wiki-skill/packages/graph-engine/test/renderer-lifecycle.test.ts +1711 -0
  311. package/skills/llm-wiki-skill/packages/graph-engine/test/route-continuity.test.ts +284 -0
  312. package/skills/llm-wiki-skill/packages/graph-engine/test/runtime-state.test.ts +281 -0
  313. package/skills/llm-wiki-skill/packages/graph-engine/test/search-and-legend.test.ts +124 -0
  314. package/skills/llm-wiki-skill/packages/graph-engine/test/select.test.ts +168 -0
  315. package/skills/llm-wiki-skill/packages/graph-engine/test/sigma-coordinates.test.ts +50 -0
  316. package/skills/llm-wiki-skill/packages/graph-engine/test/sigma-global-renderer.test.ts +2210 -0
  317. package/skills/llm-wiki-skill/packages/graph-engine/test/sigma-trial-adapter.test.ts +82 -0
  318. package/skills/llm-wiki-skill/packages/graph-engine/test/sigma-trial-adapter.ts +271 -0
  319. package/skills/llm-wiki-skill/packages/graph-engine/test/sim.test.ts +207 -0
  320. package/skills/llm-wiki-skill/packages/graph-engine/test/simulation-bridge.test.ts +96 -0
  321. package/skills/llm-wiki-skill/packages/graph-engine/test/spatial-index.test.ts +222 -0
  322. package/skills/llm-wiki-skill/packages/graph-engine/test/state.test.ts +189 -0
  323. package/skills/llm-wiki-skill/packages/graph-engine/test/summary-contract.test.ts +422 -0
  324. package/skills/llm-wiki-skill/packages/graph-engine/test/themes.test.ts +62 -0
  325. package/skills/llm-wiki-skill/packages/graph-engine/test/toolbar.test.ts +64 -0
  326. package/skills/llm-wiki-skill/packages/graph-engine/test/viewport.test.ts +213 -0
  327. package/skills/llm-wiki-skill/packages/graph-engine/test/vis-network-trial-adapter.test.ts +82 -0
  328. package/skills/llm-wiki-skill/packages/graph-engine/test/vis-network-trial-adapter.ts +186 -0
  329. package/skills/llm-wiki-skill/packages/graph-engine/tsconfig.json +17 -0
  330. package/skills/llm-wiki-skill/packages/graph-engine/vite.config.ts +15 -0
  331. package/skills/llm-wiki-skill/platforms/claude/CLAUDE.md +37 -0
  332. package/skills/llm-wiki-skill/platforms/claude/companions/llm-wiki-upgrade/SKILL.md +95 -0
  333. package/skills/llm-wiki-skill/platforms/codex/AGENTS.md +23 -0
  334. package/skills/llm-wiki-skill/platforms/hermes/README.md +31 -0
  335. package/skills/llm-wiki-skill/platforms/openclaw/README.md +31 -0
  336. package/skills/llm-wiki-skill/scripts/adapter-state.sh +424 -0
  337. package/skills/llm-wiki-skill/scripts/build-graph-data.sh +395 -0
  338. package/skills/llm-wiki-skill/scripts/build-graph-html.sh +459 -0
  339. package/skills/llm-wiki-skill/scripts/cache.sh +352 -0
  340. package/skills/llm-wiki-skill/scripts/create-source-page.sh +100 -0
  341. package/skills/llm-wiki-skill/scripts/delete-helper.sh +68 -0
  342. package/skills/llm-wiki-skill/scripts/graph-analysis.js +732 -0
  343. package/skills/llm-wiki-skill/scripts/hook-session-start.sh +46 -0
  344. package/skills/llm-wiki-skill/scripts/init-wiki.sh +95 -0
  345. package/skills/llm-wiki-skill/scripts/lib/source-signal-eligibility.js +158 -0
  346. package/skills/llm-wiki-skill/scripts/lint-fix.sh +114 -0
  347. package/skills/llm-wiki-skill/scripts/lint-runner.sh +217 -0
  348. package/skills/llm-wiki-skill/scripts/runtime-context.sh +77 -0
  349. package/skills/llm-wiki-skill/scripts/shared-config.sh +83 -0
  350. package/skills/llm-wiki-skill/scripts/source-record-contract.tsv +10 -0
  351. package/skills/llm-wiki-skill/scripts/source-registry.sh +349 -0
  352. package/skills/llm-wiki-skill/scripts/source-registry.tsv +10 -0
  353. package/skills/llm-wiki-skill/scripts/source-signal-coverage.js +83 -0
  354. package/skills/llm-wiki-skill/scripts/validate-step1.sh +144 -0
  355. package/skills/llm-wiki-skill/scripts/wiki-compat.sh +267 -0
  356. package/skills/llm-wiki-skill/setup.sh +8 -0
  357. package/skills/llm-wiki-skill/templates/entity-template.md +30 -0
  358. package/skills/llm-wiki-skill/templates/graph-styles/wash/footer.html +27 -0
  359. package/skills/llm-wiki-skill/templates/graph-styles/wash/graph-wash-helpers.js +1326 -0
  360. package/skills/llm-wiki-skill/templates/graph-styles/wash/graph-wash.js +1009 -0
  361. package/skills/llm-wiki-skill/templates/graph-styles/wash/header.html +2002 -0
  362. package/skills/llm-wiki-skill/templates/index-en-template.md +51 -0
  363. package/skills/llm-wiki-skill/templates/index-template.md +51 -0
  364. package/skills/llm-wiki-skill/templates/log-en-template.md +11 -0
  365. package/skills/llm-wiki-skill/templates/log-template.md +11 -0
  366. package/skills/llm-wiki-skill/templates/overview-en-template.md +41 -0
  367. package/skills/llm-wiki-skill/templates/overview-template.md +41 -0
  368. package/skills/llm-wiki-skill/templates/purpose-en-template.md +16 -0
  369. package/skills/llm-wiki-skill/templates/purpose-template.md +16 -0
  370. package/skills/llm-wiki-skill/templates/query-template.md +19 -0
  371. package/skills/llm-wiki-skill/templates/schema-template.md +185 -0
  372. package/skills/llm-wiki-skill/templates/source-template.md +51 -0
  373. package/skills/llm-wiki-skill/templates/synthesis-template.md +25 -0
  374. package/skills/llm-wiki-skill/templates/topic-template.md +35 -0
  375. package/skills/llm-wiki-skill/tests/adapter-state.sh +338 -0
  376. package/skills/llm-wiki-skill/tests/browser/graph-aggregation-fallback-trial.ts +737 -0
  377. package/skills/llm-wiki-skill/tests/browser/graph-community-node-map.mjs +255 -0
  378. package/skills/llm-wiki-skill/tests/browser/graph-community-wash-interactions.mjs +170 -0
  379. package/skills/llm-wiki-skill/tests/browser/graph-default-behavior.mjs +630 -0
  380. package/skills/llm-wiki-skill/tests/browser/graph-density-preview.mjs +53 -0
  381. package/skills/llm-wiki-skill/tests/browser/graph-html-insights.mjs +41 -0
  382. package/skills/llm-wiki-skill/tests/browser/graph-large-performance.ts +689 -0
  383. package/skills/llm-wiki-skill/tests/browser/graph-node-slim.mjs +75 -0
  384. package/skills/llm-wiki-skill/tests/browser/graph-offline-phase-6.mjs +660 -0
  385. package/skills/llm-wiki-skill/tests/browser/graph-renderer-trial-shared.ts +291 -0
  386. package/skills/llm-wiki-skill/tests/browser/graph-sigma-global-production.ts +1437 -0
  387. package/skills/llm-wiki-skill/tests/browser/graph-sigma-graphology-trial.ts +949 -0
  388. package/skills/llm-wiki-skill/tests/browser/graph-stage-4-5.mjs +815 -0
  389. package/skills/llm-wiki-skill/tests/browser/graph-vis-network-trial.ts +762 -0
  390. package/skills/llm-wiki-skill/tests/browser/graph-workbench-interactions.mjs +730 -0
  391. package/skills/llm-wiki-skill/tests/browser/validate-graph-trial-result.mjs +149 -0
  392. package/skills/llm-wiki-skill/tests/expected/graph-data-empty.json +60 -0
  393. package/skills/llm-wiki-skill/tests/expected/graph-data-sample.json +396 -0
  394. package/skills/llm-wiki-skill/tests/expected/graph-interactive-basic.html +1736 -0
  395. package/skills/llm-wiki-skill/tests/expected/lint-output.txt +44 -0
  396. package/skills/llm-wiki-skill/tests/fixtures/coverage-sample-wiki/index.md +1 -0
  397. package/skills/llm-wiki-skill/tests/fixtures/coverage-sample-wiki/wiki/entities/Alpha.md +10 -0
  398. package/skills/llm-wiki-skill/tests/fixtures/coverage-sample-wiki/wiki/entities/Beta.md +7 -0
  399. package/skills/llm-wiki-skill/tests/fixtures/coverage-sample-wiki/wiki/entities/Delta.md +8 -0
  400. package/skills/llm-wiki-skill/tests/fixtures/coverage-sample-wiki/wiki/entities/Gamma.md +8 -0
  401. package/skills/llm-wiki-skill/tests/fixtures/coverage-sample-wiki/wiki/queries/20260422-abc.md +10 -0
  402. package/skills/llm-wiki-skill/tests/fixtures/coverage-sample-wiki/wiki/synthesis/Crystal.md +8 -0
  403. package/skills/llm-wiki-skill/tests/fixtures/coverage-sample-wiki/wiki/topics/Overview.md +9 -0
  404. package/skills/llm-wiki-skill/tests/fixtures/graph-data-empty-wiki/wiki/entities/.gitkeep +0 -0
  405. package/skills/llm-wiki-skill/tests/fixtures/graph-data-sample-wiki/purpose.md +3 -0
  406. package/skills/llm-wiki-skill/tests/fixtures/graph-data-sample-wiki/wiki/entities/Attention.md +7 -0
  407. package/skills/llm-wiki-skill/tests/fixtures/graph-data-sample-wiki/wiki/entities/Decoder.md +7 -0
  408. package/skills/llm-wiki-skill/tests/fixtures/graph-data-sample-wiki/wiki/entities/Encoder.md +7 -0
  409. package/skills/llm-wiki-skill/tests/fixtures/graph-data-sample-wiki/wiki/entities/GPT.md +7 -0
  410. package/skills/llm-wiki-skill/tests/fixtures/graph-data-sample-wiki/wiki/entities/Transformer.md +13 -0
  411. package/skills/llm-wiki-skill/tests/fixtures/graph-data-sample-wiki/wiki/sources/paper.md +9 -0
  412. package/skills/llm-wiki-skill/tests/fixtures/graph-data-sample-wiki/wiki/topics/arch.md +12 -0
  413. package/skills/llm-wiki-skill/tests/fixtures/graph-data-sample-wiki/wiki/topics/finetune.md +9 -0
  414. package/skills/llm-wiki-skill/tests/fixtures/graph-interactive-basic/wiki/graph-data.json +40 -0
  415. package/skills/llm-wiki-skill/tests/fixtures/graph-interactive-dense/wiki/graph-data.json +3965 -0
  416. package/skills/llm-wiki-skill/tests/fixtures/graph-interactive-multicomm/wiki/graph-data.json +212 -0
  417. package/skills/llm-wiki-skill/tests/fixtures/lint-sample-wiki/index.md +14 -0
  418. package/skills/llm-wiki-skill/tests/fixtures/lint-sample-wiki/wiki/entities/C++.md +6 -0
  419. package/skills/llm-wiki-skill/tests/fixtures/lint-sample-wiki/wiki/entities/Lonely.md +4 -0
  420. package/skills/llm-wiki-skill/tests/fixtures/lint-sample-wiki/wiki/entities/Other.md +8 -0
  421. package/skills/llm-wiki-skill/tests/fixtures/lint-sample-wiki/wiki/entities/Real.md +7 -0
  422. package/skills/llm-wiki-skill/tests/fixtures/lint-sample-wiki/wiki/sources/2026-01-01-test-source.md +15 -0
  423. package/skills/llm-wiki-skill/tests/fixtures/lint-sample-wiki/wiki/sources/2026-02-01-inline-img.md +12 -0
  424. package/skills/llm-wiki-skill/tests/fixtures/lint-sample-wiki/wiki/topics/AIbasic.md +3 -0
  425. package/skills/llm-wiki-skill/tests/graph-aggregation-fallback-trial.regression-1.sh +46 -0
  426. package/skills/llm-wiki-skill/tests/graph-analysis-helper.regression-1.sh +237 -0
  427. package/skills/llm-wiki-skill/tests/graph-browser-large-performance.regression-1.sh +39 -0
  428. package/skills/llm-wiki-skill/tests/graph-browser-stage-4-5.regression-1.sh +163 -0
  429. package/skills/llm-wiki-skill/tests/graph-build-failures.regression-1.sh +91 -0
  430. package/skills/llm-wiki-skill/tests/graph-community-node-map.regression-1.sh +107 -0
  431. package/skills/llm-wiki-skill/tests/graph-community-wash-interactions.regression-1.sh +35 -0
  432. package/skills/llm-wiki-skill/tests/graph-data-confidence-merge.regression-1.sh +309 -0
  433. package/skills/llm-wiki-skill/tests/graph-data-source-paths.regression-1.sh +49 -0
  434. package/skills/llm-wiki-skill/tests/graph-default-behavior.regression-1.sh +35 -0
  435. package/skills/llm-wiki-skill/tests/graph-html-a11y.regression-1.sh +50 -0
  436. package/skills/llm-wiki-skill/tests/graph-html-brand-link.regression-1.sh +47 -0
  437. package/skills/llm-wiki-skill/tests/graph-html-density.regression-1.sh +228 -0
  438. package/skills/llm-wiki-skill/tests/graph-html-drawer-neighbors.regression-1.sh +47 -0
  439. package/skills/llm-wiki-skill/tests/graph-html-insights.regression-1.sh +80 -0
  440. package/skills/llm-wiki-skill/tests/graph-html-long-label.regression-1.sh +92 -0
  441. package/skills/llm-wiki-skill/tests/graph-html-minimap.regression-1.sh +51 -0
  442. package/skills/llm-wiki-skill/tests/graph-html-mobile.regression-1.sh +48 -0
  443. package/skills/llm-wiki-skill/tests/graph-html-oriental-atlas-contract.regression-1.sh +94 -0
  444. package/skills/llm-wiki-skill/tests/graph-html-oriental-design-contract.regression-1.sh +82 -0
  445. package/skills/llm-wiki-skill/tests/graph-html-search.regression-1.sh +52 -0
  446. package/skills/llm-wiki-skill/tests/graph-html-styles.regression-1.sh +66 -0
  447. package/skills/llm-wiki-skill/tests/graph-html-toolbar.regression-1.sh +62 -0
  448. package/skills/llm-wiki-skill/tests/graph-offline-phase-6.regression-1.sh +51 -0
  449. package/skills/llm-wiki-skill/tests/graph-sigma-global-production.regression-1.sh +64 -0
  450. package/skills/llm-wiki-skill/tests/graph-sigma-graphology-trial.regression-1.sh +46 -0
  451. package/skills/llm-wiki-skill/tests/graph-vis-network-trial.regression-1.sh +46 -0
  452. package/skills/llm-wiki-skill/tests/graph-workbench-interactions.regression-1.sh +151 -0
  453. package/skills/llm-wiki-skill/tests/js/graph-wash-bootstrap.test.js +110 -0
  454. package/skills/llm-wiki-skill/tests/js/graph-wash-helpers.test.js +296 -0
  455. package/skills/llm-wiki-skill/tests/js/graph-wash-learning.test.js +260 -0
  456. package/skills/llm-wiki-skill/tests/js/graph-wash-queue.test.js +115 -0
  457. package/skills/llm-wiki-skill/tests/js/graph-wash-runtime-state.test.js +282 -0
  458. package/skills/llm-wiki-skill/tests/js/source-signal-coverage.test.js +48 -0
  459. package/skills/llm-wiki-skill/tests/js/source-signal-eligibility.test.js +202 -0
  460. package/skills/llm-wiki-skill/tests/lib/graph-html-engine-helpers.sh +110 -0
  461. package/skills/llm-wiki-skill/tests/lint-output.regression-1.sh +32 -0
  462. package/skills/llm-wiki-skill/tests/regression.sh +1754 -0
  463. package/skills/llm-wiki-skill/workbench/AGENTS.md +110 -0
  464. package/skills/llm-wiki-skill/workbench/CLAUDE.md +55 -0
  465. package/skills/llm-wiki-skill/workbench/LICENSE +21 -0
  466. package/skills/llm-wiki-skill/workbench/PRODUCT.md +1353 -0
  467. package/skills/llm-wiki-skill/workbench/README.md +30 -0
  468. package/skills/llm-wiki-skill/workbench/docs/current-kb-retrieval-design.md +587 -0
  469. package/skills/llm-wiki-skill/workbench/docs/graph-evolution-1-design.md +210 -0
  470. package/skills/llm-wiki-skill/workbench/docs/stage-2-design.md +1139 -0
  471. package/skills/llm-wiki-skill/workbench/docs/stage-3-design.md +1269 -0
  472. package/skills/llm-wiki-skill/workbench/docs/stage-3.5-design.md +1164 -0
  473. package/skills/llm-wiki-skill/workbench/docs/stage-4-design.md +504 -0
  474. package/skills/llm-wiki-skill/workbench/docs/stage-4.5-design.md +195 -0
  475. package/skills/llm-wiki-skill/workbench/docs/superpowers/specs/2026-05-28-resizable-preview-layout-design.md +165 -0
  476. package/skills/llm-wiki-skill/workbench/docs/superpowers/specs/2026-05-28-settings-panel-scroll-fix.md +50 -0
  477. package/skills/llm-wiki-skill/workbench/server/package.json +31 -0
  478. package/skills/llm-wiki-skill/workbench/server/src/agent.ts +457 -0
  479. package/skills/llm-wiki-skill/workbench/server/src/artifacts.ts +248 -0
  480. package/skills/llm-wiki-skill/workbench/server/src/auth.ts +164 -0
  481. package/skills/llm-wiki-skill/workbench/server/src/config.ts +130 -0
  482. package/skills/llm-wiki-skill/workbench/server/src/conversations.test.ts +159 -0
  483. package/skills/llm-wiki-skill/workbench/server/src/conversations.ts +270 -0
  484. package/skills/llm-wiki-skill/workbench/server/src/digest/batch.ts +189 -0
  485. package/skills/llm-wiki-skill/workbench/server/src/digest/concurrency.test.ts +36 -0
  486. package/skills/llm-wiki-skill/workbench/server/src/digest/concurrency.ts +31 -0
  487. package/skills/llm-wiki-skill/workbench/server/src/digest/subagent.ts +91 -0
  488. package/skills/llm-wiki-skill/workbench/server/src/extensions/artifacts.ts +81 -0
  489. package/skills/llm-wiki-skill/workbench/server/src/extensions/knowledge-base.ts +263 -0
  490. package/skills/llm-wiki-skill/workbench/server/src/extensions/new-wiki.ts +42 -0
  491. package/skills/llm-wiki-skill/workbench/server/src/extensions/synthesis.ts +172 -0
  492. package/skills/llm-wiki-skill/workbench/server/src/graph-watcher.test.ts +196 -0
  493. package/skills/llm-wiki-skill/workbench/server/src/graph.test.ts +113 -0
  494. package/skills/llm-wiki-skill/workbench/server/src/graph.ts +351 -0
  495. package/skills/llm-wiki-skill/workbench/server/src/index.ts +1148 -0
  496. package/skills/llm-wiki-skill/workbench/server/src/knowledge-bases.test.ts +30 -0
  497. package/skills/llm-wiki-skill/workbench/server/src/knowledge-bases.ts +321 -0
  498. package/skills/llm-wiki-skill/workbench/server/src/pages.test.ts +41 -0
  499. package/skills/llm-wiki-skill/workbench/server/src/pages.ts +160 -0
  500. package/skills/llm-wiki-skill/workbench/server/src/retrieval.test.ts +151 -0
  501. package/skills/llm-wiki-skill/workbench/server/src/retrieval.ts +427 -0
  502. package/skills/llm-wiki-skill/workbench/server/src/tool-status-events.test.ts +363 -0
  503. package/skills/llm-wiki-skill/workbench/server/src/tool-status-events.ts +616 -0
  504. package/skills/llm-wiki-skill/workbench/server/src/wiki-init.test.ts +19 -0
  505. package/skills/llm-wiki-skill/workbench/server/src/wiki-init.ts +188 -0
  506. package/skills/llm-wiki-skill/workbench/server/tsconfig.json +10 -0
  507. package/skills/llm-wiki-skill/workbench/tsconfig.json +20 -0
  508. package/skills/llm-wiki-skill/workbench/web/README.md +73 -0
  509. package/skills/llm-wiki-skill/workbench/web/components.json +21 -0
  510. package/skills/llm-wiki-skill/workbench/web/eslint.config.js +22 -0
  511. package/skills/llm-wiki-skill/workbench/web/index.html +16 -0
  512. package/skills/llm-wiki-skill/workbench/web/package.json +54 -0
  513. package/skills/llm-wiki-skill/workbench/web/src/App.tsx +1195 -0
  514. package/skills/llm-wiki-skill/workbench/web/src/components/AddExternalDialog.tsx +375 -0
  515. package/skills/llm-wiki-skill/workbench/web/src/components/AppearancePanel.tsx +158 -0
  516. package/skills/llm-wiki-skill/workbench/web/src/components/ArtifactView.tsx +15 -0
  517. package/skills/llm-wiki-skill/workbench/web/src/components/BatchDigestPanel.tsx +117 -0
  518. package/skills/llm-wiki-skill/workbench/web/src/components/ChatPanel.tsx +890 -0
  519. package/skills/llm-wiki-skill/workbench/web/src/components/CommandMenu.tsx +75 -0
  520. package/skills/llm-wiki-skill/workbench/web/src/components/ExportButtons.tsx +58 -0
  521. package/skills/llm-wiki-skill/workbench/web/src/components/GraphPanel.tsx +800 -0
  522. package/skills/llm-wiki-skill/workbench/web/src/components/GraphReader.tsx +52 -0
  523. package/skills/llm-wiki-skill/workbench/web/src/components/GraphSelection.tsx +100 -0
  524. package/skills/llm-wiki-skill/workbench/web/src/components/GraphSummaryDrawer.tsx +269 -0
  525. package/skills/llm-wiki-skill/workbench/web/src/components/MainViewTabs.tsx +69 -0
  526. package/skills/llm-wiki-skill/workbench/web/src/components/MarkdownView.tsx +106 -0
  527. package/skills/llm-wiki-skill/workbench/web/src/components/NewWikiDialog.tsx +103 -0
  528. package/skills/llm-wiki-skill/workbench/web/src/components/RefMenu.tsx +44 -0
  529. package/skills/llm-wiki-skill/workbench/web/src/components/RightDrawer.tsx +298 -0
  530. package/skills/llm-wiki-skill/workbench/web/src/components/SearchPanel.tsx +165 -0
  531. package/skills/llm-wiki-skill/workbench/web/src/components/SettingsPanel.tsx +320 -0
  532. package/skills/llm-wiki-skill/workbench/web/src/components/Sidebar.tsx +354 -0
  533. package/skills/llm-wiki-skill/workbench/web/src/components/ToolHistorySummary.tsx +111 -0
  534. package/skills/llm-wiki-skill/workbench/web/src/components/ToolStatusRunway.tsx +70 -0
  535. package/skills/llm-wiki-skill/workbench/web/src/components/TopBar.tsx +348 -0
  536. package/skills/llm-wiki-skill/workbench/web/src/components/renderers/DownloadOnlyRenderer.tsx +88 -0
  537. package/skills/llm-wiki-skill/workbench/web/src/components/renderers/HtmlRenderer.tsx +92 -0
  538. package/skills/llm-wiki-skill/workbench/web/src/components/ui/button.tsx +52 -0
  539. package/skills/llm-wiki-skill/workbench/web/src/components/ui/command.tsx +50 -0
  540. package/skills/llm-wiki-skill/workbench/web/src/components/ui/dialog.tsx +156 -0
  541. package/skills/llm-wiki-skill/workbench/web/src/components/ui/input.tsx +21 -0
  542. package/skills/llm-wiki-skill/workbench/web/src/components/ui/tooltip.tsx +57 -0
  543. package/skills/llm-wiki-skill/workbench/web/src/index.css +4204 -0
  544. package/skills/llm-wiki-skill/workbench/web/src/lib/api.ts +648 -0
  545. package/skills/llm-wiki-skill/workbench/web/src/lib/appearance.ts +114 -0
  546. package/skills/llm-wiki-skill/workbench/web/src/lib/drawer-layout.ts +41 -0
  547. package/skills/llm-wiki-skill/workbench/web/src/lib/drawer-state.ts +168 -0
  548. package/skills/llm-wiki-skill/workbench/web/src/lib/graph-reader.ts +25 -0
  549. package/skills/llm-wiki-skill/workbench/web/src/lib/graph-selection-drawer.ts +35 -0
  550. package/skills/llm-wiki-skill/workbench/web/src/lib/graph-selection.ts +96 -0
  551. package/skills/llm-wiki-skill/workbench/web/src/lib/graph-summary-actions.ts +184 -0
  552. package/skills/llm-wiki-skill/workbench/web/src/lib/legacy-tool-status.ts +113 -0
  553. package/skills/llm-wiki-skill/workbench/web/src/lib/model-roles.ts +20 -0
  554. package/skills/llm-wiki-skill/workbench/web/src/lib/search-filter.ts +104 -0
  555. package/skills/llm-wiki-skill/workbench/web/src/lib/sse.ts +72 -0
  556. package/skills/llm-wiki-skill/workbench/web/src/lib/tool-status-format.ts +170 -0
  557. package/skills/llm-wiki-skill/workbench/web/src/lib/tool-status-model.ts +392 -0
  558. package/skills/llm-wiki-skill/workbench/web/src/lib/utils.ts +10 -0
  559. package/skills/llm-wiki-skill/workbench/web/src/lib/view-status.ts +16 -0
  560. package/skills/llm-wiki-skill/workbench/web/src/lib/wiki-links.ts +32 -0
  561. package/skills/llm-wiki-skill/workbench/web/src/main.tsx +10 -0
  562. package/skills/llm-wiki-skill/workbench/web/test/api.test.ts +61 -0
  563. package/skills/llm-wiki-skill/workbench/web/test/app-shell-drawer-layout.test.tsx +48 -0
  564. package/skills/llm-wiki-skill/workbench/web/test/appearance-panel.test.tsx +121 -0
  565. package/skills/llm-wiki-skill/workbench/web/test/appearance.test.ts +262 -0
  566. package/skills/llm-wiki-skill/workbench/web/test/chat-host-source.test.tsx +22 -0
  567. package/skills/llm-wiki-skill/workbench/web/test/chat-panel-auto-scroll.test.tsx +311 -0
  568. package/skills/llm-wiki-skill/workbench/web/test/chat-panel-bubbles.test.tsx +48 -0
  569. package/skills/llm-wiki-skill/workbench/web/test/chat-panel-composer.test.tsx +86 -0
  570. package/skills/llm-wiki-skill/workbench/web/test/chat-panel-tool-status.test.tsx +26 -0
  571. package/skills/llm-wiki-skill/workbench/web/test/export-batch-paper.test.tsx +101 -0
  572. package/skills/llm-wiki-skill/workbench/web/test/graph-drawer-state.test.ts +257 -0
  573. package/skills/llm-wiki-skill/workbench/web/test/graph-panel-paper.test.tsx +200 -0
  574. package/skills/llm-wiki-skill/workbench/web/test/graph-reader-request.test.ts +32 -0
  575. package/skills/llm-wiki-skill/workbench/web/test/graph-reader.test.ts +62 -0
  576. package/skills/llm-wiki-skill/workbench/web/test/graph-selection-drawer.test.ts +56 -0
  577. package/skills/llm-wiki-skill/workbench/web/test/graph-selection.test.ts +83 -0
  578. package/skills/llm-wiki-skill/workbench/web/test/graph-summary-actions.test.ts +188 -0
  579. package/skills/llm-wiki-skill/workbench/web/test/main-view-tabs.test.tsx +34 -0
  580. package/skills/llm-wiki-skill/workbench/web/test/markdown-view.test.tsx +34 -0
  581. package/skills/llm-wiki-skill/workbench/web/test/popup-menus.test.tsx +85 -0
  582. package/skills/llm-wiki-skill/workbench/web/test/render.test.tsx +30 -0
  583. package/skills/llm-wiki-skill/workbench/web/test/render.tsx +38 -0
  584. package/skills/llm-wiki-skill/workbench/web/test/right-drawer-graph-summary.test.tsx +287 -0
  585. package/skills/llm-wiki-skill/workbench/web/test/right-drawer-interactions.test.tsx +182 -0
  586. package/skills/llm-wiki-skill/workbench/web/test/search-filter.test.ts +65 -0
  587. package/skills/llm-wiki-skill/workbench/web/test/search-panel.test.tsx +155 -0
  588. package/skills/llm-wiki-skill/workbench/web/test/setup-dom.ts +66 -0
  589. package/skills/llm-wiki-skill/workbench/web/test/sidebar-v2-source.test.ts +17 -0
  590. package/skills/llm-wiki-skill/workbench/web/test/sidebar.test.tsx +110 -0
  591. package/skills/llm-wiki-skill/workbench/web/test/tool-history-summary.test.tsx +150 -0
  592. package/skills/llm-wiki-skill/workbench/web/test/tool-status-format.test.ts +107 -0
  593. package/skills/llm-wiki-skill/workbench/web/test/tool-status-model.test.ts +324 -0
  594. package/skills/llm-wiki-skill/workbench/web/test/tool-status-runway.test.ts +159 -0
  595. package/skills/llm-wiki-skill/workbench/web/test/topbar.test.tsx +248 -0
  596. package/skills/llm-wiki-skill/workbench/web/test/visual/paper-ui.ts +898 -0
  597. package/skills/llm-wiki-skill/workbench/web/test/wiki-links.test.ts +23 -0
  598. package/skills/llm-wiki-skill/workbench/web/test-results/paper-ui/actual/.gitkeep +1 -0
  599. package/skills/llm-wiki-skill/workbench/web/test-results/paper-ui/baseline/.gitkeep +1 -0
  600. package/skills/llm-wiki-skill/workbench/web/tsconfig.app.json +30 -0
  601. package/skills/llm-wiki-skill/workbench/web/tsconfig.json +7 -0
  602. package/skills/llm-wiki-skill/workbench/web/tsconfig.node.json +24 -0
  603. package/skills/llm-wiki-skill/workbench/web/vite.config.ts +28 -0
@@ -6,7 +6,7 @@ import { validateReviewEvidence } from './review-evidence.js';
6
6
  import { resolveTaskParents, nonTerminalSemanticParents } from './task-parents.js';
7
7
  let seqCounter = 0;
8
8
  const nid = (p) => `${p}_${(++seqCounter).toString(36)}_${Date.now().toString(36)}`;
9
- /** 首句:trim 后按首个换行或「。?! 」截断;超长兜底 40 字(T7 需求标题规范化)。 */
9
+ /** 首句:trim 后按首个换行或「。?! 」截断;超长兜底 40 字(需求标题规范化)。 */
10
10
  export function firstSentence(text) {
11
11
  const t = text.trim();
12
12
  const cut = t.search(/[\n。?!]/);
@@ -22,18 +22,23 @@ export function buildChainTitle(requirementName, _openspecRest, problem) {
22
22
  export class KanbanService {
23
23
  state;
24
24
  store;
25
- // Q4:kb_url host 前缀硬校验基准(config.wikiVault.baseUrl)。null = 不校验前缀(兼容测试/旧调用)。
26
- kbUrlBase;
25
+ // kb_url host 前缀硬校验基准(config.wikiVault.baseUrl)。null = 不校验前缀(兼容测试/旧调用)。
26
+ // 配置面板热生效:改为 getter,每次校验时取最新值——改 baseUrl 无需重建服务。
27
+ getKbUrlBase;
27
28
  emitQueue = Promise.resolve();
28
29
  listeners = new Set();
29
- // D23:链完成验收核对钩子(dispatcher 注入:读主会话事件/产物归属核对 → auditWarning)
30
+ // 链完成验收核对钩子(dispatcher 注入:读主会话事件/产物归属核对 → auditWarning)
30
31
  onChainCompletedHook = null;
31
- // Q3&5:W2/W3 完成互链登记钩子(dispatcher 注入:拿 page_path → 机械写三方互链,失败不阻塞完成)
32
+ // W2/W3 完成互链登记钩子(dispatcher 注入:拿 page_path → 机械写三方互链,失败不阻塞完成)
32
33
  onTaskCompletedHook = null;
33
- constructor(store, kbUrlBase) {
34
+ // 实测闸钩子(装配层注入:gate-policy 派生 + gate-runner 实测执行 + 分支核对)。
35
+ // null=未启用(行为不变);hook 返回 null=跳过(零感知,无 gate 事件)。
36
+ // **无 actor 参数——human 无豁免**(2026-09-02 决议收紧)。
37
+ gateHook = null;
38
+ constructor(store, getKbUrlBase) {
34
39
  this.store = store;
35
- this.kbUrlBase = kbUrlBase ?? null;
36
- // P0-3:同步重投影,消除"构造后立即调用基于空状态"的竞态
40
+ this.getKbUrlBase = getKbUrlBase ?? null;
41
+ // 同步重投影,消除"构造后立即调用基于空状态"的竞态
37
42
  this.state = project(store.readAllSync());
38
43
  }
39
44
  async emit(ev) {
@@ -49,20 +54,24 @@ export class KanbanService {
49
54
  await pending;
50
55
  return emitted;
51
56
  }
52
- /** D23:注入链完成核对钩子(由调度层设置;仅一个消费者)。 */
57
+ /** 注入链完成核对钩子(由调度层设置;仅一个消费者)。 */
53
58
  setOnChainCompleted(hook) {
54
59
  this.onChainCompletedHook = hook;
55
60
  }
56
- /** Q3&5:注入任务完成互链登记钩子(由调度层设置;仅一个消费者)。 */
61
+ /** 注入任务完成互链登记钩子(由调度层设置;仅一个消费者)。 */
57
62
  setOnTaskCompleted(hook) {
58
63
  this.onTaskCompletedHook = hook;
59
64
  }
60
- /** T22:订阅持久化后的看板事件;返回解除订阅函数。listener 异常不影响已落盘状态。 */
65
+ /** 注入实测闸钩子(由装配层设置;null=关闭实测闸,行为与旧版逐字节一致)。 */
66
+ setGateHook(hook) {
67
+ this.gateHook = hook;
68
+ }
69
+ /** 订阅持久化后的看板事件;返回解除订阅函数。listener 异常不影响已落盘状态。 */
61
70
  subscribe(listener) {
62
71
  this.listeners.add(listener);
63
72
  return () => { this.listeners.delete(listener); };
64
73
  }
65
- /** T22:返回 seq >= 入参 的事件(与 EventStore.readSince 同为 inclusive 语义)。 */
74
+ /** 返回 seq >= 入参 的事件(与 EventStore.readSince 同为 inclusive 语义)。 */
66
75
  async eventsSince(seq) {
67
76
  return this.store.readSince(seq);
68
77
  }
@@ -127,6 +136,24 @@ export class KanbanService {
127
136
  await this.emit({ chainId: card.chainId, taskId: null, kind: 'chain/executing', payload: {}, author: actor, at: Date.now() });
128
137
  return updated;
129
138
  }
139
+ /** 链级停滞终态(防线A,看门狗/V stall 超限专用机械记账):executing → blocked。
140
+ * 非 executing 调用即抛(fail-closed);人工恢复=GUI 删链重跑(blocked 无出边)。 */
141
+ async blockChain(chainId, reason) {
142
+ const chain = this.state.chains.get(chainId);
143
+ if (!chain)
144
+ throw new Error('unknown chain: ' + chainId);
145
+ if (chain.status !== 'executing')
146
+ throw new Error('blockChain requires executing chain, got: ' + chain.status);
147
+ await this.emit({ chainId, taskId: null, kind: 'chain/blocked', payload: { reason }, author: 'system', at: Date.now() });
148
+ }
149
+ /** IM 投递失败留痕(仅 system 机械记账):非状态转换注记事件,仅落盘供取证/GUI 观察。
150
+ * 投递是旁路通知,失败绝不 block 链(评审决议);留痕满足「禁止静默 skip」红线。 */
151
+ async noteImDeliveryFailed(chainId, detail, actor) {
152
+ if (actor !== 'system')
153
+ throw new Error('permission denied: only system may note im delivery failure');
154
+ await this.chainOf(chainId);
155
+ return this.emit({ chainId, taskId: null, kind: 'chain/im-delivery-failed', payload: { detail }, author: actor, at: Date.now() });
156
+ }
130
157
  async createTask(input, actor) {
131
158
  if (!can('create-task', actor, null))
132
159
  throw new Error('permission denied');
@@ -135,7 +162,7 @@ export class KanbanService {
135
162
  throw new Error('title required');
136
163
  const chain = await this.chainOf(input.chainId);
137
164
  const explicitParents = input.parents && input.parents.length > 0;
138
- // P0 硬拦(防御纵深):调用方未显式指定 parents(V 建全新阶段卡)时,按语义依赖查上游非终态——
165
+ // 硬拦(防御纵深):调用方未显式指定 parents(V 建全新阶段卡)时,按语义依赖查上游非终态——
139
166
  // 上游卡还卡着/未走完则拒绝建卡(防「P blocked 后仍建 PT」类事故)。显式 parents 的调用
140
167
  // (复审卡 parents=[rework.id]、createReworkTask)由调用方决定接链,不在此拦。
141
168
  if (!explicitParents) {
@@ -145,7 +172,7 @@ export class KanbanService {
145
172
  throw new Error(`create-task rejected: 上游 ${b} 未终态,下游 ${input.assignee}/${input.mode} 卡不能创建`);
146
173
  }
147
174
  }
148
- // 语义 parents 兜底:调用方(V 建卡)未显式指定 parents 时,按 R20 依赖自动接链上终态父任务,
175
+ // 语义 parents 兜底:调用方(V 建卡)未显式指定 parents 时,按语义依赖自动接链上终态父任务,
149
176
  // 保证「父交接注入」通道闭合(如 w2 接 P、dt 接 d)。兜底对已显式传 parents 的
150
177
  // 调用(复审卡 parents=[rework.id]、createReworkTask)不生效。
151
178
  const parents = input.parents && input.parents.length > 0
@@ -176,13 +203,13 @@ export class KanbanService {
176
203
  throw new Error('permission denied');
177
204
  if (!handoff.summary.trim())
178
205
  throw new Error('handoff summary required');
179
- // C2:D(execute) 完成必须带 git 产物证据(changed_files + commit/push 至少其一)——
180
- // 执行者语义硬校验;human 为信任锚(GUI 强制收尾)可豁免,但 C1 链完成门禁仍会拦截无证据链。
206
+ // D(execute) 完成必须带 git 产物证据(changed_files + commit/push 至少其一)——
207
+ // 执行者语义硬校验;human 为信任锚(GUI 强制收尾)可豁免,但链完成门禁仍会拦截无证据链。
181
208
  if (t.assignee === 'd' && t.mode === 'execute' && actor !== 'human' && !hasDeliveryEvidence(handoff)) {
182
209
  throw new Error('delivery evidence required: D(execute) complete must carry changed_files + (commit_hash|push)');
183
210
  }
184
211
  // TDD 声明闸(2026-08-26):D(execute) 完成必须带 tdd 声明(test_files 非空 或 skipped.reason 非空),
185
- // 否则抛错——防止 D 完全不声明测试;顺序真伪由 DT 评审闸兜底。human 信任锚可豁免(同 C2)。
212
+ // 否则抛错——防止 D 完全不声明测试;顺序真伪由 DT 评审闸兜底。human 信任锚可豁免(同上)。
186
213
  if (t.assignee === 'd' && t.mode === 'execute' && actor !== 'human' && !hasTddDeclaration(handoff)) {
187
214
  throw new Error('tdd declaration required: D(execute) complete must carry tdd = { test_files: [...] } or tdd = { skipped: { reason } }');
188
215
  }
@@ -203,7 +230,7 @@ export class KanbanService {
203
230
  // 从源头杜绝 done-but-missing(上游未产出 page_path 就不会成为 done 父卡 → V 不会建 D 卡)。
204
231
  // v2:pt_decision 为 P 卡硬键(needed 布尔必填;needed=true 时 reason 必填),缺则 blocked。
205
232
  {
206
- const missing = missingDeliveryKeys(t.assignee, t.mode, handoff, this.kbUrlBase ?? undefined);
233
+ const missing = missingDeliveryKeys(t.assignee, t.mode, handoff, this.getKbUrlBase?.() ?? undefined);
207
234
  if (missing.length > 0) {
208
235
  await this.emit({ chainId: t.chainId, taskId, kind: 'task/blocked', payload: { reason: 'delivery required: ' + missing.join(', ') }, author: 'system', at: Date.now() });
209
236
  throw new Error('delivery required: ' + missing.join(', '));
@@ -211,8 +238,20 @@ export class KanbanService {
211
238
  }
212
239
  // v2 断代:w:file 交付键随旧 w1 预取阶段移除,manifest 校验块同步删除
213
240
  // (validatePrefetchManifest 仍保留于 prefetch-manifest.ts,供清单 schema 校验复用)。
241
+ // 实测闸:hook 由装配层注入(gate-policy 派生 + gate-runner 实测执行 + 分支核对),
242
+ // hook 返回 null=跳过(未启用/非 D/旧卡/分支不一致)。**无 human 豁免**(2026-09-02 决议收紧);
243
+ // ok=false → gate-failed 事件 + 拒绝 complete(卡留 running,throw 经工具边界回 D 会话)。
244
+ if (this.gateHook) {
245
+ const verdict = await this.gateHook(t, handoff);
246
+ if (verdict !== null) {
247
+ await this.emit({ chainId: t.chainId, taskId, kind: verdict.ok ? 'task/gate-passed' : 'task/gate-failed',
248
+ payload: { detail: verdict.detail }, author: 'system', at: Date.now() });
249
+ if (!verdict.ok)
250
+ throw new Error('gate failed: ' + verdict.detail);
251
+ }
252
+ }
214
253
  await this.emit({ chainId: t.chainId, taskId, kind: 'task/completed', payload: { ...handoff }, author: actor, at: Date.now() });
215
- // Q3&5:W2/W3 完成 → 调度层互链登记(拿 page_path 机械写三方互链)。
254
+ // W2/W3 完成 → 调度层互链登记(拿 page_path 机械写三方互链)。
216
255
  // 仅 w:kb 触发(P/D/PT/DT 不涉 KB 页互链);钩子内异常不阻断 completeTask(登记失败仅记 warning)。
217
256
  if (t.assignee === 'w' && t.mode === 'kb' && this.onTaskCompletedHook) {
218
257
  try {
@@ -222,11 +261,11 @@ export class KanbanService {
222
261
  console.error('[dsh-swarm] task completion linkage hook failed: ' + String(error));
223
262
  }
224
263
  }
225
- // P0-3 链完成机械规则:仅当「最后完成的执行任务是 W3(w/kb)且链上 D(execute) 已 done 且
264
+ // 链完成机械规则:仅当「最后完成的执行任务是 W3(w/kb)且链上 D(execute) 已 done 且
226
265
  // 交付物证据满足(changed_files + commit/push)」且无未终态任务时 → 链 completed(不靠 agent 自觉)。
227
266
  // 收紧判据:中间阶段(如 P done 后 W2 尚未创建)无未终态任务也不得误收链。
228
- // C1:D(execute) 无产物证据 → 不判链完成(human 强制 complete 的 D 卡同样被拦截,防漂移被掩盖)。
229
- // 'align' 为旧链路兼容(只读对齐/校验语义已废弃,R20 起新卡一律 'execute')。
267
+ // D(execute) 无产物证据 → 不判链完成(human 强制 complete 的 D 卡同样被拦截,防漂移被掩盖)。
268
+ // 'align' 为旧链路兼容(只读对齐/校验语义已废弃,新卡一律 'execute')。
230
269
  const terminal = ['done', 'archived'];
231
270
  const chain = this.state.chains.get(t.chainId);
232
271
  const chainTasks = [...this.state.tasks.values()].filter((x) => x.chainId === t.chainId);
@@ -239,7 +278,7 @@ export class KanbanService {
239
278
  const w3Done = !!lastTask && lastTask.assignee === 'w' && lastTask.mode === 'kb' && dDone && dEvidenceOk;
240
279
  if (chain && chain.status === 'executing' && openTasks.length === 0 && w3Done) {
241
280
  await this.emit({ chainId: t.chainId, taskId: null, kind: 'chain/completed', payload: {}, author: 'system', at: Date.now() });
242
- // D23:链完成 → 调度层验收核对(主会话越权写产物 → chain/audit-warning)。
281
+ // 链完成 → 调度层验收核对(主会话越权写产物 → chain/audit-warning)。
243
282
  // 钩子内异常不阻断 completeTask 本身(核对失败仅记录,链路仍 completed)。
244
283
  if (this.onChainCompletedHook) {
245
284
  try {
@@ -252,14 +291,14 @@ export class KanbanService {
252
291
  }
253
292
  return this.state.tasks.get(taskId);
254
293
  }
255
- /** D23:链完成验收核对发警告(仅 system/dispatcher 可发)。Chain 状态保持 completed。 */
294
+ /** 链完成验收核对发警告(仅 system/dispatcher 可发)。Chain 状态保持 completed。 */
256
295
  async auditWarning(chainId, evidence, actor) {
257
296
  if (actor !== 'system')
258
297
  throw new Error('permission denied: only dispatcher may raise audit warnings');
259
298
  await this.chainOf(chainId);
260
299
  return this.emit({ chainId, taskId: null, kind: 'chain/audit-warning', payload: { evidence }, author: actor, at: Date.now() });
261
300
  }
262
- /** D23:用户确认产物归属(仅 human,GUI confirm-audit action)。放行最终汇报。 */
301
+ /** 用户确认产物归属(仅 human,GUI confirm-audit action)。放行最终汇报。 */
263
302
  async confirmAudit(chainId, actor) {
264
303
  if (!can('audit-confirm', actor, null))
265
304
  throw new Error('permission denied');
@@ -269,7 +308,7 @@ export class KanbanService {
269
308
  throw new Error('no audit warning for chain: ' + chainId);
270
309
  return this.emit({ chainId, taskId: null, kind: 'chain/audit-confirmed', payload: {}, author: actor, at: Date.now() });
271
310
  }
272
- /** T7:链标题改名(仅 human,GUI)。发 chain/title-updated 事件(非状态转换)。 */
311
+ /** 链标题改名(仅 human,GUI)。发 chain/title-updated 事件(非状态转换)。 */
273
312
  async updateChainTitle(chainId, title, actor) {
274
313
  if (!can('update-title', actor, null))
275
314
  throw new Error('permission denied');
@@ -362,7 +401,7 @@ export class KanbanService {
362
401
  await this.emit({ chainId: t.chainId, taskId, kind: 'task/archived', payload: {}, author: actor, at: Date.now() });
363
402
  return this.state.tasks.get(taskId);
364
403
  }
365
- /** T10.5:仅 draft 规格卡可挂附件(V 挂清单附件(/openspec: 建链)/ human GUI 上传)。 */
404
+ /** draft 规格卡可挂附件(V 挂清单附件(/openspec: 建链)/ human GUI 上传)。 */
366
405
  async addSpecCardAttachment(cardId, attachment, actor) {
367
406
  const card = this.state.specCards.get(cardId);
368
407
  if (!card)
@@ -397,7 +436,11 @@ export class KanbanService {
397
436
  return this.emit({ chainId: t.chainId, taskId: reviewTaskId, kind: 'review/gave-up', payload: { reviewTaskId, targetTaskId, reason }, author: actor, at: Date.now() });
398
437
  }
399
438
  /** 评审失败返工卡创建(评审失败闭环):原任务保持 done(不可变),新建返工卡继承 rework 字段。
400
- * 仅 system(can('create-rework-task')=system);V 建执行卡、system 建返工卡。 */
439
+ * 仅 system(can('create-rework-task')=system);V 建执行卡、system 建返工卡。
440
+ * 语义(2026-09-07 修正):返工=该卡自己的独立会话——resumeSessionId 不继承源卡会话(置 null),
441
+ * 首跑由 runTask create `kbn-<reworkId>`,卡自身失败重试再 resume 该会话;reworkOfTaskId 保留溯源。
442
+ * 旧实现继承 source.sessionId 造成三方错位:runTask 首跑不消费它(hasRunHistory=false→create 新会话)、
443
+ * UI(BoardCard resumeSessionId??sessionId)却跳到源卡会话 → 「返工在后台跑但哪都找不到它」。 */
401
444
  async createReworkTask(input, actor) {
402
445
  if (!can('create-rework-task', actor, null))
403
446
  throw new Error('permission denied');
@@ -411,7 +454,7 @@ export class KanbanService {
411
454
  assignee: source.assignee, status: 'todo', mode: source.mode, priority: 1,
412
455
  parents: [...source.parents], children: [], createdBy: 'auto', // system 自动创建(返工卡)
413
456
  attempts: 0, heartbeats: [],
414
- sessionId: '', reworkOfTaskId: source.id, resumeSessionId: source.sessionId,
457
+ sessionId: '', reworkOfTaskId: source.id, resumeSessionId: null,
415
458
  reviewAttempt: source.reviewAttempt + 1, reviewStatus: 'pending',
416
459
  };
417
460
  task.sessionId = 'kbn-' + task.id;
@@ -419,7 +462,7 @@ export class KanbanService {
419
462
  return task;
420
463
  }
421
464
  async snapshot() {
422
- // P0-3:重投影为权威(事件日志是唯一事实源;非法转换在此抛错)
465
+ // 重投影为权威(事件日志是唯一事实源;非法转换在此抛错)
423
466
  this.state = project(await this.store.readAll());
424
467
  return this.state;
425
468
  }
@@ -65,7 +65,7 @@ export function buildRepoSlug(workspaceDir) {
65
65
  const base = workspaceDir.replace(/\/+$/, '').split('/').pop() ?? '';
66
66
  return buildChecklistSlug(base);
67
67
  }
68
- // ── Task 4:证据包 + 链解析 ──────────────────────────────────────────
68
+ // ── 证据包 + 链解析 ──────────────────────────────────────────
69
69
  const truncate = (s, n) => (s.length > n ? s.slice(0, n) + '…' : s);
70
70
  /** 链上下文头:链标题 + 规格卡 problem 首行。 */
71
71
  function chainContext(state, chainId) {
@@ -0,0 +1,47 @@
1
+ /** OCR 委派子命令类型:预览 / 规则 / 托管评审。 */
2
+ export type OcrSub = 'preview' | 'rule' | 'managed';
3
+ /** OCR 调用可选参数集合。 */
4
+ export interface OcrArgsInput {
5
+ repo?: string;
6
+ from?: string;
7
+ to?: string;
8
+ commit?: string;
9
+ paths?: string[];
10
+ }
11
+ /** 构造 OCR CLI 参数:preview/rule 走 delegate,managed 走 review 并恒带 JSON 输出。 */
12
+ export declare function buildOcrArgs(sub: OcrSub, a: OcrArgsInput): string[];
13
+ /** 预览结果归一化结构。 */
14
+ export interface PreviewResult {
15
+ mode: string;
16
+ files: {
17
+ path: string;
18
+ status: string;
19
+ }[];
20
+ excluded: {
21
+ path: string;
22
+ reason: string;
23
+ }[];
24
+ mergeBase: string | null;
25
+ }
26
+ /** 解析 delegate preview 的 JSON 输出,失败或结构异常时回退 unknown。 */
27
+ export declare function parsePreviewJson(stdout: string): PreviewResult;
28
+ /** 托管评审结果归一化结构。 */
29
+ export interface ManagedResult {
30
+ status: string;
31
+ comments: {
32
+ path: string | null;
33
+ line: number | null;
34
+ severity: string | null;
35
+ message: string;
36
+ }[];
37
+ }
38
+ /** 解析 managed review 的 JSON 输出,失败时回退 unknown。 */
39
+ export declare function parseManagedJson(stdout: string): ManagedResult;
40
+ /** 建议切换托管评审的文件数阈值。 */
41
+ export declare const SUGGEST_MANAGED_FILES = 50;
42
+ /** 文件数严格超过阈值时建议托管评审。 */
43
+ export declare function shouldSuggestManaged(fileCount: number): boolean;
44
+ /** 生成独立评审页命名空间路径:projects/<slug>/reviews/<topic>-<ymd>/。 */
45
+ export declare function reviewPagePath(repoSlug: string, topic: string, ymd: string): string;
46
+ /** 判定路径是否为合法的独立评审页命名空间路径。 */
47
+ export declare function isStandaloneReviewNamespacePath(pagePath: string): boolean;
@@ -0,0 +1,105 @@
1
+ /** 构造 OCR CLI 参数:preview/rule 走 delegate,managed 走 review 并恒带 JSON 输出。 */
2
+ export function buildOcrArgs(sub, a) {
3
+ if (sub === 'preview') {
4
+ const args = ['delegate', 'preview'];
5
+ if (a.from)
6
+ args.push('--from', a.from);
7
+ if (a.to)
8
+ args.push('--to', a.to);
9
+ if (a.repo)
10
+ args.push('--repo', a.repo);
11
+ return args;
12
+ }
13
+ if (sub === 'rule') {
14
+ return ['delegate', 'rule', ...(a.paths ?? [])];
15
+ }
16
+ const args = ['review'];
17
+ if (a.commit)
18
+ args.push('--commit', a.commit);
19
+ else if (a.from || a.to) {
20
+ if (a.from)
21
+ args.push('--from', a.from);
22
+ if (a.to)
23
+ args.push('--to', a.to);
24
+ }
25
+ args.push('--format', 'json');
26
+ return args;
27
+ }
28
+ /** 解析失败的兜底结果。 */
29
+ const UNKNOWN_PREVIEW = { mode: 'unknown', files: [], excluded: [], mergeBase: null };
30
+ function isRecord(v) {
31
+ return typeof v === 'object' && v !== null && !Array.isArray(v);
32
+ }
33
+ /** 元素字段别名读取(path/filePath)。 */
34
+ function pathOf(el) {
35
+ return String(el.path ?? el.filePath ?? '');
36
+ }
37
+ function asArray(v) {
38
+ return Array.isArray(v) ? v.filter(isRecord) : [];
39
+ }
40
+ /** 解析 delegate preview 的 JSON 输出,失败或结构异常时回退 unknown。 */
41
+ export function parsePreviewJson(stdout) {
42
+ let obj;
43
+ try {
44
+ obj = JSON.parse(stdout);
45
+ }
46
+ catch {
47
+ return UNKNOWN_PREVIEW;
48
+ }
49
+ if (!isRecord(obj))
50
+ return UNKNOWN_PREVIEW;
51
+ const mergeBase = obj.merge_base ?? obj.mergeBase;
52
+ return {
53
+ mode: String(obj.mode ?? 'unknown'),
54
+ files: asArray(obj.files).map((el) => ({ path: pathOf(el), status: String(el.status ?? '') })),
55
+ excluded: asArray(obj.excluded).map((el) => ({ path: pathOf(el), reason: String(el.reason ?? '') })),
56
+ mergeBase: mergeBase == null ? null : String(mergeBase),
57
+ };
58
+ }
59
+ /** 解析 managed review 的 JSON 输出,失败时回退 unknown。 */
60
+ export function parseManagedJson(stdout) {
61
+ let obj;
62
+ try {
63
+ obj = JSON.parse(stdout);
64
+ }
65
+ catch {
66
+ return { status: 'unknown', comments: [] };
67
+ }
68
+ if (!isRecord(obj))
69
+ return { status: 'unknown', comments: [] };
70
+ const comments = asArray(obj.comments).map((el) => {
71
+ const rawLine = el.line ?? el.startLine;
72
+ const line = Number(rawLine);
73
+ const message = String(el.content ?? el.message ?? el.body ?? '');
74
+ return {
75
+ path: el.path == null && el.filePath == null ? null : pathOf(el),
76
+ line: Number.isNaN(line) ? null : line,
77
+ severity: el.severity == null && el.level == null ? null : String(el.severity ?? el.level),
78
+ message: message.slice(0, 2000),
79
+ };
80
+ });
81
+ return { status: String(obj.status ?? 'unknown'), comments };
82
+ }
83
+ /** 建议切换托管评审的文件数阈值。 */
84
+ export const SUGGEST_MANAGED_FILES = 50;
85
+ /** 文件数严格超过阈值时建议托管评审。 */
86
+ export function shouldSuggestManaged(fileCount) {
87
+ return fileCount > SUGGEST_MANAGED_FILES;
88
+ }
89
+ /** 评审主题清洗:小写化,非字母数字连续折叠为 -,去首尾 -,空则回退 review。 */
90
+ function sanitizeTopic(topic) {
91
+ const cleaned = topic.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
92
+ return cleaned || 'review';
93
+ }
94
+ /** 生成独立评审页命名空间路径:projects/<slug>/reviews/<topic>-<ymd>/。 */
95
+ export function reviewPagePath(repoSlug, topic, ymd) {
96
+ return `projects/${repoSlug}/reviews/${sanitizeTopic(topic)}-${ymd}/`;
97
+ }
98
+ /** 独立评审页命名空间路径匹配规则。 */
99
+ const REVIEW_NS_RE = /^projects\/[a-z0-9-]+\/reviews\/[a-z0-9-]+-[0-9]{4}-[0-9]{2}-[0-9]{2}\//;
100
+ /** 判定路径是否为合法的独立评审页命名空间路径。 */
101
+ export function isStandaloneReviewNamespacePath(pagePath) {
102
+ if (!pagePath || pagePath.startsWith('/') || pagePath.includes('..'))
103
+ return false;
104
+ return REVIEW_NS_RE.test(pagePath);
105
+ }
@@ -1,5 +1,5 @@
1
1
  export function can(action, actor, task, opts = {}) {
2
- // P1-4:会话绑定——角色 agent 只能操作其被 spawn 绑定的任务(boundTaskId=AgentSessionRef.task_id);
2
+ // 会话绑定——角色 agent 只能操作其被 spawn 绑定的任务(boundTaskId=AgentSessionRef.task_id);
3
3
  // 旧 own(仅查 assignee)允许"链上任意同角色任务",属跨任务越权,已废弃。
4
4
  const bound = opts.boundTaskId !== undefined && task !== null && opts.boundTaskId === task.id;
5
5
  switch (action) {
@@ -10,7 +10,7 @@ export function can(action, actor, task, opts = {}) {
10
10
  return actor === 'system';
11
11
  case 'complete':
12
12
  // 仅绑定该任务的 agent 会话(boundTaskId 匹配且角色=任务 assignee)、系统收尾,
13
- // 或 human(GUI 强制收尾,T27:human 为信任锚,不算越权);跨角色 bound 拒。
13
+ // 或 human(GUI 强制收尾,human 为信任锚,不算越权);跨角色 bound 拒。
14
14
  return actor === 'system' || actor === 'human' || (bound && actor === task.assignee);
15
15
  case 'block':
16
16
  return actor === 'system' || actor === 'human' || bound;
@@ -25,13 +25,13 @@ export function can(action, actor, task, opts = {}) {
25
25
  case 'spec-approve':
26
26
  return actor === 'human';
27
27
  case 'spec-edit':
28
- // P1-4:规格卡编辑仅 human(主会话前台);P 对规格卡只读
28
+ // 规格卡编辑仅 human(主会话前台);P 对规格卡只读
29
29
  return actor === 'human';
30
30
  case 'spec-attach':
31
31
  // V 挂清单附件到规格卡(/openspec: 建链);human 亦可(GUI 上传)
32
32
  return actor === 'v' || actor === 'human';
33
33
  case 'wiki-write':
34
- // 交付质量链:w 写 KB 正文;dt 仅写 projects/<chain>/review/ 评审命名空间(ToolGuard 层再收窄路径)
34
+ // 交付质量链:w 写 KB 正文;dt 仅写 projects/<repoSlug>/<chain>/review/ 评审命名空间(ToolGuard 层再收窄路径)
35
35
  return actor === 'w' || actor === 'dt';
36
36
  case 'wiki-read':
37
37
  // w/d 读 KB 正文;dt 需读 KB 校验(评审只读);pt 无 wiki 工具面
@@ -39,10 +39,10 @@ export function can(action, actor, task, opts = {}) {
39
39
  case 'prefetch':
40
40
  return actor === 'w';
41
41
  case 'audit-confirm':
42
- // D23:仅人类在 GUI 确认产物归属;system/角色均不可
42
+ // 仅人类在 GUI 确认产物归属;system/角色均不可
43
43
  return actor === 'human';
44
44
  case 'update-title':
45
- // T7:链/任务标题改名仅 human(GUI);V/角色均不可(防角色伪造链/卡标题)
45
+ // 链/任务标题改名仅 human(GUI);V/角色均不可(防角色伪造链/卡标题)
46
46
  return actor === 'human';
47
47
  case 'delete-chain':
48
48
  // 整链硬删除仅 human(GUI 二次确认);V/角色/system 均不可
@@ -13,6 +13,11 @@ export interface PlanningChecklist {
13
13
  resolved: boolean;
14
14
  answer?: string;
15
15
  }>;
16
+ risks?: Array<{
17
+ description: string;
18
+ source: string;
19
+ mitigation: string;
20
+ }>;
16
21
  }
17
22
  /** 需求澄清清单 schema 硬校验:返回错误列表(空数组=合法)。清单缺段即拒绝保存(硬闸,主 agent 会话内修正)。 */
18
23
  export declare function validatePlanningChecklist(raw: unknown): string[];
@@ -26,17 +26,80 @@ export function validatePlanningChecklist(raw) {
26
26
  }
27
27
  }
28
28
  for (const [label, key] of ARR_FIELDS) {
29
- if (!Array.isArray(spec[key]) || spec[key].some((v) => typeof v !== 'string')) {
30
- errors.push(`checklist.spec.${label} must be string[]`);
29
+ const arr = spec[key];
30
+ if (!Array.isArray(arr)) {
31
+ errors.push(`checklist.spec.${label} must be an array of plain strings (got: ${JSON.stringify(arr)})`);
32
+ continue;
33
+ }
34
+ // 校验器错误文案是模型的 prompt(2026-09-04 二次复发:对象数组只回裸文案,模型零回显无法自纠)——
35
+ // 必须带 got: 回显 + 拍平指引。判定逻辑不变:非数组或含非字符串元素即拒。
36
+ const badIdx = arr.findIndex((v) => typeof v !== 'string');
37
+ if (badIdx >= 0) {
38
+ errors.push(`checklist.spec.${label} must be an array of plain strings; element ${badIdx} is not a string (got: ${JSON.stringify(arr[badIdx])}). Flatten objects into one sentence per element, e.g. "As a <role>, I want <capability>, so that <benefit>" for ${label}`);
31
39
  }
32
40
  }
33
41
  }
34
42
  // manifest 复用 PrefetchManifest schema
35
43
  errors.push(...validatePrefetchManifest(c['manifest']).map((e) => 'checklist.' + e));
36
- // 澄清问答/疑问点
37
- for (const key of ['clarifications', 'doubts']) {
38
- if (!Array.isArray(c[key]))
39
- errors.push(`checklist.${key} must be an array`);
44
+ // 澄清问答/疑问点:数组 + 元素形状硬校验。渲染读 qa.q/qa.a——键名错会静默产出 undefined 页面
45
+ //(2026-09-04 事故:模型传 {question,answer} 过闸,落库 9 条全 undefined),故必须锁确切键名。
46
+ const clar = c['clarifications'];
47
+ if (!Array.isArray(clar)) {
48
+ errors.push('checklist.clarifications must be an array');
49
+ }
50
+ else {
51
+ // 硬闸非空(2026-09-04:[] 合法过闸 → KB 页渲染「(无)」→ 澄清问答静默丢失)。
52
+ // 恢复场景(restoreRef 旧页无澄清)走逃生口文案,不加代码分支。
53
+ if (clar.length === 0) {
54
+ errors.push('checklist.clarifications must be a non-empty array — record every clarification Q&A from this planning round. If this checklist genuinely had no clarification round (e.g. rebuilt from a legacy KB page via restoreRef), add one entry {"q": "本轮无澄清(恢复重建)", "a": "<来源页或原因>"}');
55
+ }
56
+ clar.forEach((el, i) => {
57
+ const o = el;
58
+ const ok = typeof o === 'object' && o !== null &&
59
+ typeof o['q'] === 'string' && o['q'].trim().length > 0 &&
60
+ typeof o['a'] === 'string' && o['a'].trim().length > 0;
61
+ if (!ok) {
62
+ const got = typeof o === 'object' && o !== null ? Object.keys(o).join(',') : JSON.stringify(el);
63
+ errors.push(`checklist.clarifications[${i}] must be {"q": string, "a": string} with both non-empty (got keys: ${got}) — use keys "q" and "a", not "question"/"answer"`);
64
+ }
65
+ });
66
+ }
67
+ const dbs = c['doubts'];
68
+ if (!Array.isArray(dbs)) {
69
+ errors.push('checklist.doubts must be an array');
70
+ }
71
+ else {
72
+ dbs.forEach((el, i) => {
73
+ const o = el;
74
+ const ok = typeof o === 'object' && o !== null &&
75
+ typeof o['q'] === 'string' && o['q'].trim().length > 0 &&
76
+ typeof o['resolved'] === 'boolean' &&
77
+ (o['answer'] === undefined || typeof o['answer'] === 'string');
78
+ if (!ok) {
79
+ const got = typeof o === 'object' && o !== null ? Object.keys(o).join(',') : JSON.stringify(el);
80
+ errors.push(`checklist.doubts[${i}] must be {"q": string, "resolved": boolean, "answer"?: string} (got keys: ${got}) — use keys "q", "resolved", "answer"`);
81
+ }
82
+ });
83
+ }
84
+ // 风险点(可选):存在则硬校验三要素键名。渲染读 r.description/r.source/r.mitigation——键名错会静默产出 undefined 行
85
+ const risks = c['risks'];
86
+ if (risks !== undefined) {
87
+ if (!Array.isArray(risks)) {
88
+ errors.push('checklist.risks must be an array when present');
89
+ }
90
+ else {
91
+ risks.forEach((el, i) => {
92
+ const o = el;
93
+ const ok = typeof o === 'object' && o !== null &&
94
+ typeof o['description'] === 'string' && o['description'].trim().length > 0 &&
95
+ typeof o['source'] === 'string' && o['source'].trim().length > 0 &&
96
+ typeof o['mitigation'] === 'string' && o['mitigation'].trim().length > 0;
97
+ if (!ok) {
98
+ const got = typeof o === 'object' && o !== null ? Object.keys(o).join(',') : JSON.stringify(el);
99
+ errors.push(`checklist.risks[${i}] must be {"description": string, "source": string, "mitigation": string} with all non-empty (got keys: ${got}) — use keys "description", "source", "mitigation"`);
100
+ }
101
+ });
102
+ }
40
103
  }
41
104
  return errors;
42
105
  }
@@ -47,6 +110,7 @@ export function buildChecklistTitle(c) {
47
110
  /** 需求澄清清单落库 body:标题【需求】+ 各段可读 markdown(非裸 JSON)。KB 与临时目录两分支共用。 */
48
111
  export function formatChecklistBody(c) {
49
112
  const { spec, manifest, clarifications, doubts } = c;
113
+ const risks = c.risks ?? [];
50
114
  const lines = [`# ${buildChecklistTitle(c)}`, '## Spec', ''];
51
115
  lines.push('### 问题描述 (problem)', spec.problem, '');
52
116
  lines.push('### 解决方案 (solution)', spec.solution, '');
@@ -71,6 +135,16 @@ export function formatChecklistBody(c) {
71
135
  });
72
136
  if (clarifications.length === 0)
73
137
  lines.push('(无)', '');
138
+ lines.push('## 风险点', '');
139
+ if (risks.length === 0) {
140
+ lines.push('(无)', '');
141
+ }
142
+ else {
143
+ for (const r of risks) {
144
+ lines.push(`- ${r.description}(来源: ${r.source};缓解: ${r.mitigation})`);
145
+ }
146
+ lines.push('');
147
+ }
74
148
  lines.push('## 疑问点', '');
75
149
  for (const d of doubts) {
76
150
  lines.push(d.resolved ? `- [x] ${d.q}${d.answer ? ` — ${d.answer}` : ''}` : `- [ ] ${d.q}`);
@@ -12,7 +12,8 @@ export function applyTo(state, ev) {
12
12
  }
13
13
  case 'chain/executing':
14
14
  case 'chain/completed':
15
- case 'chain/aborted': {
15
+ case 'chain/aborted':
16
+ case 'chain/blocked': {
16
17
  const c = state.chains.get(ev.chainId);
17
18
  if (!c)
18
19
  throw new Error('projection: unknown chain ' + ev.chainId);
@@ -26,7 +27,7 @@ export function applyTo(state, ev) {
26
27
  next.chains = new Map(state.chains).set(ev.chainId, { ...c, rootTaskId: String(ev.payload['rootTaskId'] ?? '') });
27
28
  break;
28
29
  }
29
- // D23:audit 事件不改 Chain 状态,只写验收核对视图(auditWarnings)
30
+ // audit 事件不改 Chain 状态,只写验收核对视图(auditWarnings)
30
31
  case 'chain/audit-warning': {
31
32
  const c = state.chains.get(ev.chainId);
32
33
  if (!c)
@@ -58,7 +59,7 @@ export function applyTo(state, ev) {
58
59
  });
59
60
  break;
60
61
  }
61
- // T7:链标题改名(非状态转换,只更新 title;快照重放可见)
62
+ // 链标题改名(非状态转换,只更新 title;快照重放可见)
62
63
  case 'chain/title-updated': {
63
64
  const c = state.chains.get(ev.chainId);
64
65
  if (!c)
@@ -66,7 +67,7 @@ export function applyTo(state, ev) {
66
67
  next.chains = new Map(state.chains).set(ev.chainId, { ...c, title: String(ev.payload['to'] ?? '') });
67
68
  break;
68
69
  }
69
- // T7:任务标题改名(非状态转换,只更新 title)
70
+ // 任务标题改名(非状态转换,只更新 title)
70
71
  case 'task/renamed': {
71
72
  if (!ev.taskId)
72
73
  throw new Error('projection: event without taskId');
@@ -80,7 +81,7 @@ export function applyTo(state, ev) {
80
81
  const p = ev.payload;
81
82
  if (!p.id || !p.assignee)
82
83
  throw new Error('projection: malformed task/created');
83
- // 归一化缺省字段,使最小 payload 的事件日志可回放(P0-3 回放为权威)
84
+ // 归一化缺省字段,使最小 payload 的事件日志可回放(回放为权威)
84
85
  const normalized = {
85
86
  ...p,
86
87
  status: p.status ?? 'todo',
@@ -112,11 +113,11 @@ export function applyTo(state, ev) {
112
113
  const updated = { ...t, status: transitionTask(t.status, ev.kind) };
113
114
  if (ev.kind === 'task/heartbeat')
114
115
  updated.heartbeats = [...t.heartbeats, ev.at];
115
- // RC4:infra 失败不计入 attempts(瞬时基础设施错误不烧重试预算);任务质量失败正常 +1
116
+ // infra 失败不计入 attempts(瞬时基础设施错误不烧重试预算);任务质量失败正常 +1
116
117
  if (ev.kind === 'task/failed' && !ev.payload['infra'])
117
118
  updated.attempts = t.attempts + 1;
118
119
  if (ev.kind === 'task/unblocked')
119
- updated.attempts = 0; // RC4:人工解除阻塞 → 重试预算重置
120
+ updated.attempts = 0; // 人工解除阻塞 → 重试预算重置
120
121
  if (ev.kind === 'task/completed') {
121
122
  const p = ev.payload;
122
123
  next.handoffs = new Map(state.handoffs).set(ev.taskId, p);