@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
@@ -0,0 +1,35 @@
1
+ export interface CatalogProvider {
2
+ id: string;
3
+ name: string;
4
+ }
5
+ export interface CatalogModel {
6
+ id: string;
7
+ name: string;
8
+ efforts: Array<{
9
+ id: string;
10
+ name: string;
11
+ }>;
12
+ }
13
+ export interface LlmCatalog {
14
+ providers: CatalogProvider[];
15
+ models: Record<string, CatalogModel[]>;
16
+ }
17
+ export interface LlmRuntimeLike {
18
+ listProviders(): Array<{
19
+ id: string;
20
+ name: string;
21
+ }>;
22
+ listModels(provider: string): Promise<Array<{
23
+ id: string;
24
+ name: string;
25
+ }>>;
26
+ resolveModelInfo(provider: string, model: string): Promise<{
27
+ reasoning?: {
28
+ efforts?: Array<{
29
+ id: string;
30
+ name: string;
31
+ }>;
32
+ };
33
+ }>;
34
+ }
35
+ export declare function buildLlmCatalog(llm: LlmRuntimeLike): Promise<LlmCatalog>;
@@ -0,0 +1,19 @@
1
+ export async function buildLlmCatalog(llm) {
2
+ const providers = llm.listProviders().map((p) => ({ id: p.id, name: p.name }));
3
+ const models = {};
4
+ for (const p of providers) {
5
+ const list = await llm.listModels(p.id);
6
+ const entries = [];
7
+ for (const m of list) {
8
+ let efforts = [];
9
+ try {
10
+ const info = await llm.resolveModelInfo(p.id, m.id);
11
+ efforts = (info.reasoning?.efforts ?? []).map((e) => ({ id: e.id, name: e.name }));
12
+ }
13
+ catch { /* effort 解析失败 → 空 */ }
14
+ entries.push({ id: m.id, name: m.name, efforts });
15
+ }
16
+ models[p.id] = entries;
17
+ }
18
+ return { providers, models };
19
+ }
@@ -0,0 +1,35 @@
1
+ /** ocr CLI runner(@alibaba-group/open-code-review 命令行):二进制定位、探活、执行与托管 provider 配置。
2
+ * 踩坑警告:插件进程 PATH 常缺 npm 全局 bin 目录,不能裸依赖 PATH 找 ocr(社区方案踩过)——
3
+ * 故按常见 npm 全局 bin 目录逐个探测并进程内缓存定位结果。 */
4
+ import { execFile } from 'node:child_process';
5
+ export declare const OCR_PACKAGE = "@alibaba-group/open-code-review";
6
+ export declare const OCR_MANAGED_PROVIDER_NAME = "dsh-managed";
7
+ export declare const INSTALL_GUIDANCE: string;
8
+ export type OcrCliDeps = {
9
+ execFileFn?: typeof execFile;
10
+ env?: NodeJS.ProcessEnv;
11
+ homedirFn?: () => string;
12
+ };
13
+ export declare function probeOcr(deps?: OcrCliDeps): Promise<{
14
+ installed: boolean;
15
+ version: string;
16
+ binPath: string | null;
17
+ }>;
18
+ export declare function runOcr(args: string[], opts: {
19
+ cwd: string;
20
+ timeoutMs?: number;
21
+ }, deps?: OcrCliDeps): Promise<{
22
+ stdout: string;
23
+ stderr: string;
24
+ error?: string;
25
+ }>;
26
+ export declare function managedProviderReady(deps?: OcrCliDeps): boolean;
27
+ export declare function wireManagedProvider(a: {
28
+ baseUrl: string;
29
+ protocol: 'openai' | 'anthropic';
30
+ apiKey: string;
31
+ model: string;
32
+ }, deps?: OcrCliDeps): Promise<{
33
+ ok: boolean;
34
+ log: string;
35
+ }>;
@@ -0,0 +1,128 @@
1
+ // src/services/ocr-cli.ts
2
+ /** ocr CLI runner(@alibaba-group/open-code-review 命令行):二进制定位、探活、执行与托管 provider 配置。
3
+ * 踩坑警告:插件进程 PATH 常缺 npm 全局 bin 目录,不能裸依赖 PATH 找 ocr(社区方案踩过)——
4
+ * 故按常见 npm 全局 bin 目录逐个探测并进程内缓存定位结果。 */
5
+ import { execFile } from 'node:child_process';
6
+ import { promisify } from 'node:util';
7
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
8
+ import { homedir } from 'node:os';
9
+ import { delimiter, join } from 'node:path';
10
+ export const OCR_PACKAGE = '@alibaba-group/open-code-review';
11
+ export const OCR_MANAGED_PROVIDER_NAME = 'dsh-managed';
12
+ export const INSTALL_GUIDANCE = [
13
+ `未检测到 ocr CLI(${OCR_PACKAGE})。`,
14
+ `请二选一安装:在 GUI 配置面板点击「安装 ocr」按钮;或在终端执行 \`npm install -g ${OCR_PACKAGE}\`。`,
15
+ '安装后执行 `ocr --version` 验证。',
16
+ '托管模式下 ocr 的模型 provider 由本插件统一接管配置,无需手工登录。',
17
+ ].join('');
18
+ const BIN_NAME = 'ocr';
19
+ /** 版本号分段数值比较(升序):'v22.22.2' 与 'v9.1.0' 字符串比较会错序,必须逐段转数字。 */
20
+ function versionAsc(a, b) {
21
+ const pa = a.replace(/^v/, '').split('.');
22
+ const pb = b.replace(/^v/, '').split('.');
23
+ for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
24
+ const d = Number(pa[i] ?? 0) - Number(pb[i] ?? 0);
25
+ if (d !== 0)
26
+ return d;
27
+ }
28
+ return 0;
29
+ }
30
+ /** 扫描目录序:进程 PATH(nvm 激活版本在其中)→ nvm versions 布局取最新 → 常见固定 bin 目录。
31
+ * 踩坑:标准 nvm 布局是 ~/.nvm/versions/node/<ver>/bin,~/.nvm/current 软链仅部分环境存在,
32
+ * 只扫后者会漏掉 npm install -g 的真实落点(GUI 安装成功但探活判未安装的根因)。 */
33
+ const scanBinDirs = (home, env) => {
34
+ const dirs = (env.PATH ?? '').split(delimiter).filter(Boolean);
35
+ const nvmRoot = join(home, '.nvm', 'versions', 'node');
36
+ try {
37
+ for (const v of readdirSync(nvmRoot).sort(versionAsc).reverse())
38
+ dirs.push(join(nvmRoot, v, 'bin'));
39
+ }
40
+ catch { /* 无 nvm 目录:跳过 */ }
41
+ dirs.push(join(home, '.nvm', 'current', 'bin'), '/opt/homebrew/bin', '/usr/local/bin', join(home, '.local', 'bin'));
42
+ return dirs;
43
+ };
44
+ /** 进程内缓存按 homedir 隔离,避免注入不同 home 时串路径;命中后仍需 existsSync 复核(文件可能已被删)。 */
45
+ let cached = null;
46
+ function resolveBin(deps = {}) {
47
+ const env = deps.env ?? process.env;
48
+ const fromEnv = env.OCR_OCR_BIN;
49
+ if (fromEnv)
50
+ return fromEnv; // 显式指定优先,不进缓存
51
+ const home = deps.homedirFn ? deps.homedirFn() : homedir();
52
+ if (cached && cached.homedir === home && existsSync(cached.binPath))
53
+ return cached.binPath;
54
+ for (const dir of scanBinDirs(home, env)) {
55
+ const candidate = join(dir, BIN_NAME);
56
+ if (existsSync(candidate)) {
57
+ cached = { homedir: home, binPath: candidate };
58
+ return candidate;
59
+ }
60
+ }
61
+ return null; // 未命中不缓存,留待下次重扫
62
+ }
63
+ export async function probeOcr(deps = {}) {
64
+ const binPath = resolveBin(deps);
65
+ if (!binPath)
66
+ return { installed: false, version: '', binPath: null };
67
+ try {
68
+ const run = promisify(deps.execFileFn ?? execFile);
69
+ // 始终传 options 对象:保持 (bin, args, opts, cb) 四参调用形态,promisify 包装的回调式 fake/真实现均兼容
70
+ const { stdout } = await run(binPath, ['--version'], {});
71
+ return { installed: true, version: stdout.split('\n')[0].trim(), binPath };
72
+ }
73
+ catch {
74
+ // 探活失败(含 ENOENT):定位结果仍保留,供上层展示/诊断
75
+ return { installed: false, version: '', binPath };
76
+ }
77
+ }
78
+ export async function runOcr(args, opts, deps = {}) {
79
+ const binPath = resolveBin(deps);
80
+ if (!binPath)
81
+ return { stdout: '', stderr: INSTALL_GUIDANCE, error: 'ocr-not-installed' };
82
+ const run = promisify(deps.execFileFn ?? execFile);
83
+ try {
84
+ const { stdout, stderr } = await run(binPath, args, {
85
+ cwd: opts.cwd,
86
+ timeout: opts.timeoutMs ?? 600_000,
87
+ maxBuffer: 64 * 1024 * 1024,
88
+ windowsHide: true,
89
+ });
90
+ return { stdout, stderr };
91
+ }
92
+ catch (err) {
93
+ // 绝不抛出:非零退出/超时/ENOENT 统一转结果对象(promisify 拒因自带 stdout/stderr)
94
+ const e = err;
95
+ return {
96
+ stdout: typeof e.stdout === 'string' ? e.stdout : '',
97
+ stderr: typeof e.stderr === 'string' ? e.stderr : '',
98
+ error: e.message ?? String(err),
99
+ };
100
+ }
101
+ }
102
+ export function managedProviderReady(deps = {}) {
103
+ try {
104
+ const home = deps.homedirFn ? deps.homedirFn() : homedir();
105
+ const cfg = JSON.parse(readFileSync(join(home, '.opencodereview', 'config.json'), 'utf8'));
106
+ return cfg.provider === OCR_MANAGED_PROVIDER_NAME && typeof cfg.model === 'string' && cfg.model.length > 0;
107
+ }
108
+ catch {
109
+ return false; // 文件不存在/解析失败/字段缺失一律视为未就绪
110
+ }
111
+ }
112
+ export async function wireManagedProvider(a, deps = {}) {
113
+ // ocr 官方非交互配置:五组 config set 按序写入自定义 provider
114
+ const steps = [
115
+ ['provider', ['config', 'set', 'provider', OCR_MANAGED_PROVIDER_NAME]],
116
+ ['model', ['config', 'set', 'model', a.model]],
117
+ ['providers.dsh-managed.url', ['config', 'set', 'providers.dsh-managed.url', a.baseUrl]],
118
+ ['providers.dsh-managed.protocol', ['config', 'set', 'providers.dsh-managed.protocol', a.protocol]],
119
+ ['providers.dsh-managed.api_key', ['config', 'set', 'providers.dsh-managed.api_key', a.apiKey]],
120
+ ];
121
+ const home = deps.homedirFn ? deps.homedirFn() : homedir();
122
+ for (const [name, args] of steps) {
123
+ const r = await runOcr(args, { cwd: home, timeoutMs: 120_000 }, deps);
124
+ if (r.error)
125
+ return { ok: false, log: `config set ${name} 失败: ${r.error} ${r.stderr.slice(0, 500)}`.trim() };
126
+ }
127
+ return { ok: true, log: 'ocr managed provider wired: dsh-managed' };
128
+ }
@@ -1,11 +1,11 @@
1
1
  import { KanbanService } from '../domain/kanban-service.js';
2
2
  import { type Actor } from '../domain/permissions.js';
3
3
  /** 工具执行上下文:由角色 agent scope 注入;主会话=human;调度器=system。
4
- * boundTaskId:角色 agent 会话绑定的任务(AgentSessionRef.task_id,P1-4 会话绑定)。 */
4
+ * boundTaskId:角色 agent 会话绑定的任务(AgentSessionRef.task_id)。 */
5
5
  export interface ToolCaller {
6
6
  actor: Actor;
7
7
  boundTaskId?: string;
8
8
  }
9
- /** 工具定义工厂(P1-3):不直接注册;由 T15 toolsets 按角色 agent-scope 装配,或由主会话注册其专属子集。
9
+ /** 工具定义工厂:不直接注册;由 toolsets 按角色 agent-scope 装配,或由主会话注册其专属子集。
10
10
  * getCaller:装配方提供的闭包(捕获 actor/boundTaskId),execute 内取用——不依赖 execute 第二参数(DSH ToolRunContext 真实形状以官方为准)。 */
11
11
  export declare function buildKanbanTools(service: KanbanService, getCaller: () => ToolCaller): import("@deepseek-ai/dsh-tools").ToolDefinition[];
@@ -1,11 +1,12 @@
1
1
  import { defineTool } from '@deepseek-ai/dsh-tools';
2
+ import {} from '@deepseek-ai/dsh-util-values';
2
3
  import { KanbanService } from '../domain/kanban-service.js';
3
4
  import { can } from '../domain/permissions.js';
4
5
  function guard(action, caller, task = null) {
5
6
  if (!can(action, caller.actor, task))
6
7
  throw new Error('permission denied: ' + action);
7
8
  }
8
- /** 工具定义工厂(P1-3):不直接注册;由 T15 toolsets 按角色 agent-scope 装配,或由主会话注册其专属子集。
9
+ /** 工具定义工厂:不直接注册;由 toolsets 按角色 agent-scope 装配,或由主会话注册其专属子集。
9
10
  * getCaller:装配方提供的闭包(捕获 actor/boundTaskId),execute 内取用——不依赖 execute 第二参数(DSH ToolRunContext 真实形状以官方为准)。 */
10
11
  export function buildKanbanTools(service, getCaller) {
11
12
  return [
@@ -1,5 +1,6 @@
1
1
  import type { Context } from '@deepseek-ai/cordis';
2
- import type { KanbanConfig } from '../config.js';
2
+ import type { PrefixRoutes } from '../config.js';
3
+ import type { ConfigProvider } from '../services/config-provider.js';
3
4
  import { type PlanningToolDeps } from './planning-tools.js';
4
5
  import type { PlanningChecklist } from '../domain/planning-checklist.js';
5
6
  /** v2 规划上下文(/plan: 捕获 → planning_checklist_save 回写 → /openspec: 建链)。模块级内存,随插件进程存活。 */
@@ -9,12 +10,30 @@ export interface PlanningContext {
9
10
  checklist: PlanningChecklist | null;
10
11
  checklistRef: string | null;
11
12
  checklistSource: 'kb' | 'temp' | null;
12
- /** T7:/plan: rest 原始需求描述(建链默认标题来源,优先级最高)。 */
13
+ /** /plan: rest 原始需求描述(建链默认标题来源,优先级最高)。 */
13
14
  requirementName: string | null;
15
+ /** 蜂群模式标记:kanban_route 触发方式(intent=swarm / 前缀=prefix);planning_checklist_save 指导文案分叉数据源。 */
16
+ mode?: 'swarm' | 'prefix' | null;
14
17
  }
15
18
  export declare const planningBySession: Map<string, PlanningContext>;
19
+ export declare const KANBAN_HANDOFF_RULE: (routes: PrefixRoutes, opts?: {
20
+ swarm?: boolean;
21
+ }) => string;
22
+ /** 防线③:/openspec: 成功后的逐链确定性叙述规则(2026-09-04 mtmgp81q:模型口播 ch_1_mtjrhkrf
23
+ * 与工具结果 ch_1_mtmgp81q 脱节)。逐字引用锚点 + firstCard 成败结论;整包缓存回放仍可能
24
+ * 绕过 prompt 层——最终防线是链级看门狗(防线①)。 */
25
+ export declare function buildOpenspecNarrationRule(r: {
26
+ chainId: string;
27
+ specCardId: string;
28
+ firstCard?: {
29
+ taskId: string;
30
+ status: string;
31
+ } | {
32
+ pending: true;
33
+ };
34
+ }): string;
16
35
  export declare function buildSpawnPrefetch(ctx: Context): PlanningToolDeps['spawnPrefetch'] | undefined;
17
36
  /** v2 主会话工具面:/plan: 捕获规划上下文(零副作用)→ planning_checklist_save 回写 → /openspec: 用清单建链。
18
37
  * 工具面 = kanban_route + 只读 kanban 子集 + spec_card_view + planning 工具;
19
38
  * 无 spec_card_edit/approve、无 kanban_create/complete/block(主会话越权写由工具面裁剪 + prefetch 子代理只读护栏双保险)。 */
20
- export declare function registerMainSessionTools(ctx: Context, config: KanbanConfig): void;
39
+ export declare function registerMainSessionTools(ctx: Context, configProvider: ConfigProvider): void;
@@ -1,25 +1,57 @@
1
1
  import { defineTool } from '@deepseek-ai/dsh-tools';
2
+ import {} from '@deepseek-ai/dsh-util-values';
2
3
  import { tmpdir } from 'node:os';
3
4
  import { KanbanProvider } from '../services/kanban-provider.js';
4
5
  import { buildKanbanTools } from './kanban-tools.js';
5
6
  import { buildSpecCardTools } from './spec-card-tools.js';
6
7
  import { buildPlanningTools } from './planning-tools.js';
7
8
  import { handlePlanRoute, handleOpenspecRoute, handleLearningRoute } from '../routes/prefix-router.js';
9
+ import { sendChainReport } from '../services/im-delivery.js';
8
10
  import { recallMemoryIndex, searchChecklists } from '../wiki/memory-recall.js';
9
11
  import { buildPlanningGuidance } from '../routes/planning-driver.js';
10
12
  import { attachSessionToWorkspace, resolveOrCreateWorkspace } from '../dispatcher/workspace-attach.js';
11
13
  import { PREFETCH_MANIFEST_SCHEMA } from '../domain/prefetch-manifest.js';
12
14
  import { WikiVaultClient } from '../wiki/wiki-vault-client.js';
15
+ import { LocalWikiClient } from '../wiki/local-kb-client.js';
16
+ import { ensureLocalKbRoot } from '../wiki/local-kb.js';
17
+ import { LOCAL_CHECKLIST_PREFIX } from '../wiki/page-path.js';
13
18
  export const planningBySession = new Map();
14
- const KANBAN_HANDOFF_RULE = (routes) => `
19
+ export const KANBAN_HANDOFF_RULE = (routes, opts) => {
20
+ const confirmLine = opts?.swarm
21
+ ? `- 澄清期:调 planning_prefetch(只读子代理)采集仓库事实 → 逐问用户收敛 → 调 planning_checklist_save 存需求澄清清单。
22
+ - 确认闸:清单落库后向用户征求确认;仅当用户回复含明确肯定语义(确认/开干/开跑/开始/go 等)才调 kanban_route{intent:'openspec'} 建链;模糊、岔开话题、只提修改意见 = 未确认,继续澄清。禁止未确认建链。`
23
+ : `- 澄清期:调 planning_prefetch(只读子代理)采集仓库事实 → 逐问用户收敛 → 调 planning_checklist_save 存需求澄清清单 → 提醒用户 ${routes.openspec} 确认。`;
24
+ const nextLine = opts?.swarm
25
+ ? `- 用户确认后你调 kanban_route{intent:'openspec'};链路进入 executing,V 自动串行建卡 p→(pt)→w2→d→dt→w3;你不要自己执行。`
26
+ : `- ${routes.openspec} 后链路进入 executing,V 自动串行建卡 p→(pt)→w2→d→dt→w3;你不要自己执行。`;
27
+ return `
15
28
  ## 主 agent 铁律(看板工作流 v2)
16
29
  - 你是计划者:只做需求澄清(grill-me)与最终收尾汇报;绝不执行任务本身。
17
30
  - 最高护栏:只读仓库——禁止 git 操作、禁止 write/edit 任何仓库源码;只允许写 KB(planning_checklist_save)与临时目录兜底。
18
- - 澄清期:调 planning_prefetch(只读子代理)采集仓库事实 → 逐问用户收敛 → 调 planning_checklist_save 存需求澄清清单 → 提醒用户 ${routes.openspec} 确认。
19
- - ${routes.openspec} 后链路进入 executing,V 自动串行建卡 p→(pt)→w2→d→dt→w3;你不要自己执行。
31
+ ${confirmLine}
32
+ ${nextLine}
20
33
  - 用 kanban_show / kanban_list / spec_card_view 观察进度,链完成后向用户汇报产物链接与轨迹入口。
21
34
  - 经验沉淀:链路完成后,用户可发 ${routes.learning}(或 ${routes.learning} <chainId>)沉淀本链经验;主 agent 消化机械证据包后调 planning_learning_save 入库。
35
+ - 叙述铁律:回复中的链号/卡号(ch_/sc_/t_ 编号)只能逐字复制自工具结果;建链成败以工具结果字段为准,禁止编造或沿用旧对话里的编号。
22
36
  `;
37
+ };
38
+ /** 防线③:/openspec: 成功后的逐链确定性叙述规则(2026-09-04 mtmgp81q:模型口播 ch_1_mtjrhkrf
39
+ * 与工具结果 ch_1_mtmgp81q 脱节)。逐字引用锚点 + firstCard 成败结论;整包缓存回放仍可能
40
+ * 绕过 prompt 层——最终防线是链级看门狗(防线①)。 */
41
+ export function buildOpenspecNarrationRule(r) {
42
+ const firstCardLine = !r.firstCard
43
+ ? '- 首卡结果未采集(旧返回体)。汇报前先调 kanban_show 复核链状态,以 kanban_show 复核后再汇报,禁止臆断建卡成功。'
44
+ : 'pending' in r.firstCard
45
+ ? `- 首卡尚未创建(等待超时,看门狗接管)。回复必须写明「首卡尚未创建,看门狗接管」,禁止声称建卡成功。`
46
+ : `- 首卡已创建:taskId=${r.firstCard.taskId}(status=${r.firstCard.status})。回复必须写明「首卡已创建」。`;
47
+ return [
48
+ '## 本次建链结果(回复必须逐字引用,禁止改写编号)',
49
+ `- chainId=${r.chainId}`,
50
+ `- specCardId=${r.specCardId}`,
51
+ firstCardLine,
52
+ '- 铁律:回复中的 ch_/sc_/t_ 编号只能逐字复制自本结果;禁止出现本结果之外的任何编号;禁止声称与本结果矛盾的建卡状态。',
53
+ ].join('\n');
54
+ }
23
55
  // 清单获取只有两条路:内存(路由1)> KB 候选页(路由2,LLM 读页重建)。禁止编造其他原因
24
56
  // ("先重试 / 查服务进程是否重启"类诊断是噪声:内存丢失唯一成因是插件重启,重启后按两条路恢复即可)。
25
57
  const RECOVERY_KB_GUIDANCE = (routes, candidates) => `
@@ -28,7 +60,7 @@ const RECOVERY_KB_GUIDANCE = (routes, candidates) => `
28
60
  ${candidates.map((c) => '- ' + c).join('\n')}
29
61
  恢复步骤(严格顺序):
30
62
  1. 读取候选页内容,对照当前需求判定哪一页是本次需求的需求澄清清单(页首行标题为「# 【需求】<需求名>」);
31
- 2. 消化该页内容,重建结构化 PlanningChecklist(spec 六段 + manifest + clarifications + doubtsrequirementName 取页标题中【需求】后的名称);
63
+ 2. 消化该页内容,重建结构化 PlanningChecklist(spec 六段 + manifest + clarifications + doubts + risks(风险点,若有),requirementName 取页标题中【需求】后的名称;恢复重建时 clarifications 允许登记单条无澄清说明,如 {"q": "本轮无澄清(恢复重建)", "a": "<来源页或原因>"},其余场景 clarifications 禁止为空);
32
64
  3. 调 planning_checklist_save(checklist, restoreRef=<该候选页路径>) 回存(覆盖原页,勿产生重复页);
33
65
  4. 回存成功后提示用户重新发送 ${routes.openspec} 确认。
34
66
  禁止:跳过恢复直接建链建卡;猜测清单内容;把恢复失败归因于"重试/进程检查"之外的任何原因。
@@ -89,17 +121,21 @@ export function buildSpawnPrefetch(ctx) {
89
121
  /** v2 主会话工具面:/plan: 捕获规划上下文(零副作用)→ planning_checklist_save 回写 → /openspec: 用清单建链。
90
122
  * 工具面 = kanban_route + 只读 kanban 子集 + spec_card_view + planning 工具;
91
123
  * 无 spec_card_edit/approve、无 kanban_create/complete/block(主会话越权写由工具面裁剪 + prefetch 子代理只读护栏双保险)。 */
92
- export function registerMainSessionTools(ctx, config) {
124
+ export function registerMainSessionTools(ctx, configProvider) {
93
125
  const registry = ctx.get('tools');
94
126
  if (!registry)
95
- return; // 测试裸 Context 无 tools 服务(P1-9 无 inject 依赖),跳过注册
127
+ return; // 测试裸 Context 无 tools 服务,跳过注册
96
128
  const provider = ctx.get('kanban');
97
129
  if (!provider)
98
130
  return;
99
131
  const service = provider.service;
100
- // 生产 wiring(src/index.ts:44)仅保证 tools+kanban 可用,无 wiki 服务 → config.wikiVault 自建
101
- //(与 dispatcher 构造同源);测试经 ctx.get('wiki') 注入 mock 客户端。
102
- const wiki = ctx.get('wiki') ?? new WikiVaultClient(config.wikiVault);
132
+ // 生产 wiring(src/index.ts)仅保证 tools+kanban 可用,无 wiki 服务 → configProvider 自建
133
+ //(与 dispatcher 构造同源,getEffective() 调用时热读取 baseUrl/pagePrefix);测试经 ctx.get('wiki') 注入 mock 客户端。
134
+ // 双模式:local 模式走 LocalWikiClient 本地检索(不发 HTTP),remote 用配置的 WikiVaultClient
135
+ const kbMode = configProvider.mode;
136
+ const wiki = kbMode === 'local'
137
+ ? new LocalWikiClient(ensureLocalKbRoot())
138
+ : (ctx.get('wiki') ?? new WikiVaultClient(() => configProvider.getEffective().wikiVault));
103
139
  const caller = () => ({ actor: 'human' });
104
140
  // 只读 kanban 子集(无 create/complete/block)
105
141
  const readOnly = new Set(['kanban_show', 'kanban_chain', 'kanban_list', 'kanban_comment']);
@@ -115,13 +151,16 @@ export function registerMainSessionTools(ctx, config) {
115
151
  }
116
152
  // planning 工具(清单落库 + 只读预取)——spawnPrefetch 由模块级 buildSpawnPrefetch 提供(可单测)
117
153
  for (const tool of buildPlanningTools({
118
- service, wiki,
154
+ service, wiki: wiki, // local 模式为 LocalWikiClient(write/read/search 同面,双模式客户端)
119
155
  getCaller: caller,
120
156
  spawnPrefetch: buildSpawnPrefetch(ctx),
121
157
  tempDir: () => `${tmpdir()}/dsh-swarm-checklists`, // KB 不可达时的临时兜底,放系统临时目录(不落插件源码/核心存储目录)
122
- pagePrefix: config.wikiVault?.pagePrefix ?? 'projects/', // 生成的清单页路径保持在该客户端配置的命名空间内(避免 kb-rejected)
123
- prefixRoutes: config.prefixRoutes,
124
- memoryEnabled: config.memory?.enabled ?? true,
158
+ pagePrefix: configProvider.getEffective().wikiVault?.pagePrefix ?? 'projects/', // 生成的清单页路径保持在该客户端配置的命名空间内(避免 kb-rejected)
159
+ kbMode: configProvider.mode, // 双模式:local 时 checklist/learning 落本地库命名空间(wiki/queries/checklists/、wiki/synthesis/learnings/)
160
+ prefixRoutes: configProvider.getEffective().prefixRoutes,
161
+ memoryEnabled: configProvider.getEffective().memory?.enabled ?? true,
162
+ resolveWorkspaceDir: () => planningBySession.get('session_main')?.workspaceDir ?? null,
163
+ flowMode: () => planningBySession.get('session_main')?.mode ?? null,
125
164
  ownerSessionId: 'session_main',
126
165
  onChecklistSaved({ ref, source, checklist }) {
127
166
  const cur = planningBySession.get('session_main') ?? { workspaceDir: null, sessionId: 'session_main', checklist: null, checklistRef: null, checklistSource: null, requirementName: null };
@@ -129,28 +168,40 @@ export function registerMainSessionTools(ctx, config) {
129
168
  },
130
169
  }))
131
170
  registry.register(tool);
132
- // kanban_route:/plan: 捕获规划上下文;/openspec: 用清单建链
133
- const { plan, openspec, learning } = config.prefixRoutes;
171
+ // kanban_route:/plan: 捕获规划上下文;/openspec: 用清单建链;/sms 手动投递链报告(前缀路由注册时快照,用于工具描述)
172
+ const { plan, openspec, learning, send } = configProvider.getEffective().prefixRoutes;
134
173
  registry.register(defineTool({
135
174
  name: 'kanban_route',
136
- description: `MUST be called when the human message starts with ${plan}, ${openspec}, or ${learning}. This is dsh-swarm planning, NOT the built-in /plan plan mode. ${plan} = zero side-effect + start grill-me (+ auto KB memory index); ${openspec} = create chain from saved checklist; ${learning} = distill experience from a chain (evidence pack + planning_learning_save).`,
137
- parameters: { message: { type: 'string', required: true } },
175
+ description: `Route hub for dsh-swarm kanban workflow (NOT the built-in /plan plan mode). Two trigger forms. (1) PREFIX form — MUST be called when the human message starts with ${plan}, ${openspec}, ${learning}, or ${send}; omit intent. (2) INTENT form (swarm preset sessions) — MUST be called with intent when the human expresses: a hands-on development requirement → intent='plan'; explicit approval to start the workflow after the checklist was saved → intent='openspec'; distill/retrospect lessons from a chain → intent='learning' (message = chainId or title words, may be empty = latest chain); deliver a chain report to the WeCom group → intent='send' (block notice: prefix message with 'blocked '). When intent is set, message = the user's raw words (no prefix). Ambiguous intent → do NOT call, ask the user instead. Semantics: ${plan} = zero side-effect + start grill-me (+ auto KB memory index); ${openspec} = create chain from saved checklist; ${learning} = distill experience from a chain (evidence pack + planning_learning_save); ${send} = manually deliver a chain report to the WeCom group (bare = latest completed chain; '${send} blocked [chainId]' = resend block notice; bypasses imDelivery.enabled; the message body is composed by system code — never compose or repeat it, only relay the delivery status).`,
176
+ parameters: { message: { type: 'string', required: true }, intent: { type: 'string', description: "swarm preset sessions: 'plan' | 'openspec' | 'learning' | 'send' — model-judged intent; omit for prefix-triggered calls" } },
138
177
  output: { schema: { type: 'json' }, render: (_a, v) => [{ type: 'text', text: JSON.stringify(v) }] },
139
178
  async execute(args, exec) {
140
- // M2(Q5)+归组:仅 /plan: 分支捕获主 agent 工作空间并可能询问注册——/openspec:/none 不触发,
141
- // 避免死代码副作用多弹一次 ask(/openspec: 实际用的是 planningBySession 已存的 workspaceDir)。
142
- // header.cwd 缺失或未注册时询问用户注册工作区;仍不可得保持 null(链任务随后 block 'workspace-unknown')。
143
- const plan = await handlePlanRoute(args.message, service, config.prefixRoutes, 'session_main');
179
+ // intent 路径(蜂群模式):handler 内部会重 parsePrefix(message),无前缀 message
180
+ // 会判成 none —— 因此 intent 命中时合成「前缀 + rest」消息再进 handler;handler 零改动、
181
+ // 前缀路径零感知。intent 优先于 message 前缀;非法 intent 回退 parsePrefix(none 兜底)。
182
+ // 简报矛盾修正:intent 命中时 message 若自带已知前缀(模型契约
183
+ // 违例,description 明文 raw words no prefix),原样拼接会使 rest 带旧前缀 → handler 内必
184
+ // chain-not-found → brief 断言不可能绿;故丢弃载荷只保留 intent 裸前缀
185
+ //(learning 裸 = 最近链,与既有 '/learning' 语义一致)。raw words 正常路径与简报逐字节一致。
186
+ const routes = configProvider.getEffective().prefixRoutes;
187
+ const INTENTS = ['plan', 'openspec', 'learning', 'send'];
188
+ const intent = INTENTS.includes(args.intent ?? '') ? args.intent : null;
189
+ const trimmed = args.message.trim();
190
+ const routeMessage = intent
191
+ ? `${routes[intent]}${trimmed && !INTENTS.some((k) => trimmed.startsWith(routes[k])) ? ' ' + trimmed : ''}`
192
+ : args.message;
193
+ const plan = await handlePlanRoute(routeMessage, service, routes, 'session_main');
144
194
  if (plan.kind === 'plan') {
145
195
  const headerCwd = exec?.agent?.session?.header?.cwd ?? null;
146
196
  const workspaceDir = await resolveOrCreateWorkspace(ctx, headerCwd, '主 agent 会话');
147
- planningBySession.set('session_main', { workspaceDir, sessionId: 'session_main', checklist: null, checklistRef: null, checklistSource: null, requirementName: plan.rest });
148
- let guidance = buildPlanningGuidance(config.prefixRoutes) + KANBAN_HANDOFF_RULE(config.prefixRoutes);
149
- if ((config.memory?.enabled ?? true) && workspaceDir) {
197
+ planningBySession.set('session_main', { workspaceDir, sessionId: 'session_main', checklist: null, checklistRef: null, checklistSource: null, requirementName: plan.rest, mode: intent ? 'swarm' : 'prefix' });
198
+ let guidance = buildPlanningGuidance(configProvider.getEffective().prefixRoutes, { swarm: intent === 'plan' }) + KANBAN_HANDOFF_RULE(configProvider.getEffective().prefixRoutes, { swarm: intent === 'plan' });
199
+ if ((configProvider.getEffective().memory?.enabled ?? true) && workspaceDir) {
150
200
  const idx = await recallMemoryIndex(wiki, {
151
201
  requirementName: plan.rest || null,
152
202
  workspaceDir,
153
- maxEntries: config.memory?.maxIndexEntries ?? 8,
203
+ maxEntries: configProvider.getEffective().memory?.maxIndexEntries ?? 8,
204
+ kbMode,
154
205
  });
155
206
  if (idx)
156
207
  guidance += '\n' + idx;
@@ -158,31 +209,85 @@ export function registerMainSessionTools(ctx, config) {
158
209
  return { kind: 'plan', guidance };
159
210
  }
160
211
  if (plan.kind === 'learning') {
161
- const r = await handleLearningRoute(args.message, service, config.prefixRoutes, 'session_main');
212
+ const r = await handleLearningRoute(routeMessage, service, configProvider.getEffective().prefixRoutes, 'session_main');
162
213
  if (r.error)
163
214
  return { kind: 'learning', error: r.error, guidance: r.guidance };
164
215
  return { kind: 'learning', chainId: r.chainId, brief: r.brief, guidance: r.guidance };
165
216
  }
217
+ if (plan.kind === 'send') {
218
+ // /sms 手动投递:rest 'blocked [chainId]' → 阻塞通知;其余 → 完成汇报(query = rest)。
219
+ // 红线:消息正文由 sendChainReport 内的领域函数渲染并发送,本分支只返回投递状态(绝不含正文)。
220
+ const rest = plan.rest;
221
+ const variant = rest.startsWith('blocked') ? 'blocked' : 'completion';
222
+ const query = variant === 'blocked' ? rest.slice('blocked'.length).trim() : rest;
223
+ const r = await sendChainReport(ctx, service, configProvider, { retryDelaysMs: [] }, variant, query);
224
+ if (r.ok) {
225
+ const noun = variant === 'blocked' ? '阻塞通知' : '完成汇报';
226
+ return {
227
+ kind: 'send', chainId: r.chainId, botId: r.botId, targetId: r.targetId,
228
+ guidance: `${noun}已投递企微群(/sms 手动触发)。请仅向用户确认投递成功与目标群,勿复述消息正文。`,
229
+ };
230
+ }
231
+ return { kind: 'send', error: r.error, guidance: r.guidance ?? '请将 error 字段原样转告用户,勿复述消息正文。' };
232
+ }
166
233
  if (plan.kind === 'none')
167
234
  return { kind: 'none' };
168
235
  // 路由1(内存):planningBySession 命中 → 直接建链
169
236
  const pctx = planningBySession.get('session_main');
170
237
  if (pctx?.checklist && pctx.checklistRef) {
238
+ // 恢复补捕①:内存有清单但 workspaceDir=null(主 agent 重启后清单经 KB 恢复、异常态)→
239
+ // 从 exec.agent.session.header.cwd 捡回工作区,路由1 继续正常建链。已有值绝不重解析
240
+ // (不重复弹 ask,对齐下方 /plan: 分支注释顾虑);解析 null(无 cwd/无通道/用户跳过)保持
241
+ // 现状 → 走 handleOpenspecRoute 的 workspace-unknown fail-fast(不吞错、不猜测路径)。
242
+ if (!pctx.workspaceDir) {
243
+ const headerCwd = exec?.agent?.session?.header?.cwd ?? null;
244
+ const workspaceDir = await resolveOrCreateWorkspace(ctx, headerCwd, '主 agent 会话(/openspec: 恢复)');
245
+ if (workspaceDir) {
246
+ pctx.workspaceDir = workspaceDir;
247
+ planningBySession.set('session_main', pctx);
248
+ }
249
+ }
250
+ // 闸2:清单落库的仓库与当前工作区不一致 → 硬拦不建链(KB 页路径带 repoSlug 维度的前提是链与工作区同源)
251
+ const localPath = pctx.checklist.manifest.repo.localPath;
252
+ if (pctx.workspaceDir && localPath !== pctx.workspaceDir) {
253
+ return {
254
+ kind: 'openspec', approved: false, reason: 'workspace-mismatch',
255
+ error: `[workspace-mismatch] 清单 manifest.repo.localPath (${localPath}) 与当前工作区 (${pctx.workspaceDir}) 不一致。请在目标仓库工作区内重新执行 ${configProvider.getEffective().prefixRoutes.plan} 重新澄清落库后再 ${configProvider.getEffective().prefixRoutes.openspec}(不可跳过)。`,
256
+ };
257
+ }
171
258
  const input = { workspaceDir: pctx.workspaceDir, checklist: pctx.checklist, checklistRef: pctx.checklistRef, requirementName: pctx.requirementName };
172
- const r = await handleOpenspecRoute(args.message, service, config.prefixRoutes, input, 'session_main');
173
- return { kind: 'openspec', chainId: r.chainId, specCardId: r.specCardId, approved: true, guidance: KANBAN_HANDOFF_RULE(config.prefixRoutes) };
259
+ const r = await handleOpenspecRoute(routeMessage, service, configProvider.getEffective().prefixRoutes, input, 'session_main');
260
+ // 护栏拦截(如 workspace-unknown):透传失败原因与恢复指引,不得伪装成建链成功
261
+ if (r.approved === false || !r.chainId || !r.specCardId) {
262
+ return { kind: 'openspec', approved: false, reason: r.reason ?? 'unknown', guidance: r.guidance };
263
+ }
264
+ return {
265
+ kind: 'openspec', chainId: r.chainId, specCardId: r.specCardId, approved: true, firstCard: r.firstCard,
266
+ guidance: KANBAN_HANDOFF_RULE(configProvider.getEffective().prefixRoutes, { swarm: planningBySession.get('session_main')?.mode === 'swarm' }) + '\n\n' + buildOpenspecNarrationRule({ chainId: r.chainId, specCardId: r.specCardId, firstCard: r.firstCard }),
267
+ };
174
268
  }
175
269
  // 路由2(知识库):内存丢失(插件重启)→ 搜 KB 候选清单页供 LLM 读页重建;搜不到/不可达 → 两条路皆空
270
+ // 恢复补捕②:无内存条目或工作区未捕获 → 从 header.cwd 捡回,写入 planningBySession(checklist 等
271
+ // 字段保持 cur 或空缺省),后续 planning_checklist_save 触发 onChecklistSaved 的 { ...cur } 展开自然
272
+ // 带上 workspaceDir。解析失败不阻塞恢复 guidance 返回(行为同现状,只是少捕一次)。
273
+ if (!planningBySession.get('session_main')?.workspaceDir) {
274
+ const headerCwd = exec?.agent?.session?.header?.cwd ?? null;
275
+ const workspaceDir = await resolveOrCreateWorkspace(ctx, headerCwd, '主 agent 会话(/openspec: 恢复)');
276
+ if (workspaceDir) {
277
+ const cur = planningBySession.get('session_main') ?? { workspaceDir: null, sessionId: 'session_main', checklist: null, checklistRef: null, checklistSource: null, requirementName: null };
278
+ planningBySession.set('session_main', { ...cur, workspaceDir });
279
+ }
280
+ }
176
281
  let candidates = [];
177
282
  try {
178
- candidates = await searchChecklists(wiki, config.wikiVault?.pagePrefix ?? 'projects/');
283
+ candidates = await searchChecklists(wiki, kbMode === 'local' ? LOCAL_CHECKLIST_PREFIX : (configProvider.getEffective().wikiVault?.pagePrefix ?? 'projects/'));
179
284
  }
180
285
  catch { /* KB 不可达/搜索失败 → 候选为空,走两条路皆空分支 */ }
181
286
  return {
182
287
  kind: 'openspec', approved: false, reason: 'no-checklist',
183
288
  recovery: candidates.length > 0 ? 'kb' : 'none',
184
289
  checklistCandidates: candidates,
185
- guidance: candidates.length > 0 ? RECOVERY_KB_GUIDANCE(config.prefixRoutes, candidates) : RECOVERY_NONE_GUIDANCE(config.prefixRoutes),
290
+ guidance: candidates.length > 0 ? RECOVERY_KB_GUIDANCE(configProvider.getEffective().prefixRoutes, candidates) : RECOVERY_NONE_GUIDANCE(configProvider.getEffective().prefixRoutes),
186
291
  };
187
292
  },
188
293
  }));
@@ -0,0 +1,11 @@
1
+ /** ocr_review 工具:把 ocr CLI 三子命令(preview/rule/managed)封装为 cordis 工具,DT 评审角色工具面注册。
2
+ * 依赖全注入可换 fake(tests),缺省用 ocr-cli 真实现。 */
3
+ import { type ToolDefinition as ToolDef } from '@deepseek-ai/dsh-tools';
4
+ import { managedProviderReady, probeOcr, runOcr } from '../services/ocr-cli.js';
5
+ /** 构造 ocr_review 工具定义(defineTool 返回形态,与 kanban-tools 一致)。 */
6
+ export declare function buildOcrReviewTool(deps: {
7
+ runOcrFn?: typeof runOcr;
8
+ probeFn?: typeof probeOcr;
9
+ managedReadyFn?: typeof managedProviderReady;
10
+ cwd?: () => string;
11
+ }): ToolDef;