@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
@@ -1,41 +1,101 @@
1
1
  import { SessionId } from '@deepseek-ai/dsh-session';
2
- import { installRoleTools, buildReadOnlyWriteGuard, buildDTWriteGuard, buildPlanWriteGuard, registerDtTaskChain, unregisterDtTaskChain } from '../roles/toolsets.js';
2
+ import { writeFileSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { probeOcr } from '../services/ocr-cli.js';
5
+ import { installRoleTools, buildReadOnlyWriteGuard, buildDTWriteGuard, buildPlanWriteGuard, buildKbWriteGuard, registerDtTaskChain, unregisterDtTaskChain } from '../roles/toolsets.js';
6
+ import { ensureLocalKbRoot } from '../wiki/local-kb.js';
7
+ import { installCleanFsTools } from '../roles/clean-fs-tools.js';
3
8
  import { buildModelCandidates, isModelUnavailableError } from './model-candidates.js';
4
- import { attachSessionToWorkspace, resolveOrCreateWorkspace } from './workspace-attach.js';
5
9
  import { toolName } from './session-events.js';
10
+ import { attachSessionToWorkspace, resolveOrCreateWorkspace } from './workspace-attach.js';
6
11
  import { isPathInside, resolveTargetRepoDir } from './target-repo.js';
7
12
  import { injectGitCredentials, resolveGitPatFromCtx } from './git-credentials.js';
8
- /** M3(B):目标仓库在会话工作空间外、已 claim+block 等待用户授权且尚未建会话的任务集合(key=taskId)。
13
+ /** 目标仓库在会话工作空间外、已 claim+block 等待用户授权且尚未建会话的任务集合(key=taskId)。
9
14
  * 人工放行后再次调度会重新询问;已授权后从集合移除。仅进程内记忆,重启后从事件日志恢复(block 事件仍在)。 */
10
15
  const permissionBlockedTasks = new Set();
11
- /** D4 goal 条件启用(spec FR6):spec 卡六段或父交接命中关键词 → 注入目标模式指令。 */
16
+ /** goal 条件启用:spec 卡六段或父交接命中关键词 → 注入目标模式指令。 */
12
17
  const GOAL_MODE_KEYWORDS = ['/goal', '目标模式', 'goal mode'];
13
- /** RC4:瞬时基础设施错误(会话 live 锁/网络超时)与任务质量失败区分——infra 不计入 attempts 重试预算。 */
18
+ /** 瞬时基础设施错误(会话 live 锁/网络超时)与任务质量失败区分——infra 不计入 attempts 重试预算。 */
14
19
  function isInfraError(err) {
15
20
  return /cannot prepare session|while it is live|timeout|ETIMEDOUT|ECONNREFUSED|ECONNRESET|socket/i.test(String(err));
16
21
  }
22
+ /** 关键事件追加落盘 storageDir/dispatcher.log(与 dispatcher.ts 同一文件、同一行格式)——
23
+ * agent-runner 未注入 logFile,按 dispatcher 同款方式经 configProvider 派生 storageDir;
24
+ * 写失败静默忽略(日志只是观测面,事件日志才是事实源)。 */
25
+ function logToDispatcherLog(configProvider, msg) {
26
+ try {
27
+ const storageDir = configProvider.getEffective().storageDir.replace('$DSH_HOME', process.env.DSH_HOME ?? process.cwd());
28
+ writeFileSync(join(storageDir, 'dispatcher.log'), new Date().toISOString() + ' ' + msg + '\n', { flag: 'a' });
29
+ }
30
+ catch { /* 忽略写失败 */ }
31
+ }
32
+ /** 组合标记存储:按 Agent 实例(incarnation)键控的进程内 WeakMap。
33
+ * 机制取舍(探明宿主 lib 后确定):
34
+ * - 不用 session.append('kanban/role-composition'):自定义事件类型不在宿主 KNOWN_SESSION_EVENT_TYPES
35
+ * (dsh-session/lib/types/known-event-types.js),持久化读路径 assertEventsSupported
36
+ * (dsh-session-persistence/lib/index.js:1117)对未标 ignorable 的未知类型整份拒绝加载
37
+ * (SessionFormatUnsupportedError)→ 会话日志变成无法 resume 的毒日志;且 append 公共 API
38
+ * 不暴露 ignorable 信封字段,无法规避。
39
+ * - 不用 agentCtx.provide:cordis 服务 store 的 isolate 键解析到根作用域
40
+ * (cordis/lib/index.js provide → ctx.root[symbols.isolate][name]),多 agent 同名 provide 冲突。
41
+ * - WeakMap 按 incarnation 键控:GUI 重开同名会话是新 Agent 实例 → 查不到标记 → 不盲用;
42
+ * 实例被回收标记随 GC 消失,无泄漏。 */
43
+ const roleCompositions = new WeakMap();
44
+ /** 写入角色组合标记(setup 在 installRoleTools 成功后调用;导出仅供测试直接构造标记场景)。 */
45
+ export function markRoleComposition(agent, marker) {
46
+ if (agent && typeof agent === 'object')
47
+ roleCompositions.set(agent, marker);
48
+ }
49
+ /** 只读判定:该 agent incarnation 是否带角色组合标记(全局 guard 消费;不读 marker 内容)。
50
+ * 与 markRoleComposition 同一 WeakMap 单一事实源;未标记 incarnation(GUI 新开/子代理)
51
+ * 返回 false。 */
52
+ export function isRoleComposed(agent) {
53
+ return !!agent && typeof agent === 'object' && roleCompositions.has(agent);
54
+ }
17
55
  /** 每任务一次性角色 agent:创建/resume、上下文组装、协议违规检测。 */
18
56
  export class AgentRunner {
19
57
  ctx;
20
58
  kanban;
21
- config;
59
+ configProvider;
22
60
  wiki;
23
61
  defaultModel;
24
- constructor(ctx, kanban, config, wiki, defaultModel) { this.ctx = ctx; this.kanban = kanban; this.config = config; this.wiki = wiki; this.defaultModel = defaultModel; }
62
+ probeOcrFn;
63
+ constructor(ctx, kanban, configProvider, wiki, defaultModel, deps) {
64
+ this.ctx = ctx;
65
+ this.kanban = kanban;
66
+ this.configProvider = configProvider;
67
+ this.wiki = wiki;
68
+ this.defaultModel = defaultModel;
69
+ this.probeOcrFn = deps?.probeOcrFn ?? probeOcr;
70
+ }
25
71
  buildContext(task, state, resume) {
26
72
  const parts = [`# Task ${task.id}: ${task.title}`, `assignee=${task.assignee} mode=${task.mode}`];
27
- // Q3:权限提示仅对受限角色显示(v 无写、d/execute 全权、p/w 全权但受工具级写护栏约束——写边界不靠 prompt 软约束)
73
+ // 权限提示仅对受限角色显示(v 无写、d/execute 全权、p/w 全权但受工具级写护栏约束——写边界不靠 prompt 软约束)
28
74
  if (task.assignee !== 'v' && !(task.assignee === 'd' && task.mode === 'execute') && task.assignee !== 'p' && task.assignee !== 'w') {
29
75
  parts.push('权限提示:你的权限范围固定在会话工作区(workspace-write),越权操作(如 sandbox_permissions 升级写工作区外)会被自动拒绝且不可重试。遇到拒绝不要重试被拒操作,改用工作区内可行方式记录结果,然后调用 kanban_complete。');
30
76
  }
31
- // A3/B5:D(execute) = 唯一执行者(danger-full-access,无权限提示)——目标仓库内实际写代码 + git 提交推送
77
+ // D(execute) = 唯一执行者(danger-full-access,无权限提示)——目标仓库内实际写代码 + git 提交推送
32
78
  if (task.assignee === 'd' && task.mode === 'execute') {
33
79
  parts.push('## 执行者职责\n你是链路唯一执行者(不是只读对齐/校验):在目标仓库(见 Body 的 TARGET_REPO)内 git worktree/branch → 按规格卡 solution/testing 改代码/README → git commit → git push → 自检(跑测试/构建)。本会话为 full-access(可写目标仓库与 git 凭据已注入),不要做只读对齐/校验交差。调用 kanban_complete 时 metadata 必须带 git 产物证据:changed_files(数组)+ commit_hash 与 push 至少其一,否则完成会被拒绝、链路不会收尾。');
34
80
  }
35
81
  if (task.body)
36
82
  parts.push(`## Body
37
83
  ${task.body}`);
38
- // P1-1:规格卡六段 + 附件注入(经 Chain.specCardId),角色 agent 的输入契约,原汁原味
84
+ // W local KB 模式:注入本地库根 + llm-wiki 用法 + 排序原则 + 交付约定(remote 模式不注入)。
85
+ // 库内复制/移动补句:DIRECT cp/mv/mkdir 工具永远匹配不到 KB 目标(无 path/file_path
86
+ // 实参)会被护栏拒绝——必须显式指引 W 用 write 工具做库内复制/移动。
87
+ if (task.assignee === 'w' && this.configProvider.mode === 'local') {
88
+ const kbRoot = ensureLocalKbRoot();
89
+ parts.push('## 知识库(本地模式)', `- 本地库根:${kbRoot}(llm-wiki 原生结构;只读仓库源码,唯一可写区域为该库根);库内复制/移动一律用 write 工具(cp/mv 会被护栏拒绝)`, '- 经 skill 工具加载 llm-wiki 完成查写(query/ingest/crystallize);库未初始化时先按其 init 工作流初始化(幂等)', '- 检索排序原则:相关性优先 7 : 新鲜度 3', '- 交付:page_path = 库根下 wiki/** 相对路径(如 wiki/sources/ch_<chainId>/t_<taskId>.md);kb_url = 空串', '- 本地模式不 ingest 外部 URL;wiki_search/wiki_read/wiki_write 不可用(未注册)');
90
+ }
91
+ // D/DT local 库根注入(审查修订):d:execute local 文案称「库根见运行时上下文」,
92
+ // 此处必须真的注入,否则 D 不知道去哪读计划;DT fs 写评审页同理。
93
+ if ((task.assignee === 'd' || task.assignee === 'dt') && this.configProvider.mode === 'local') {
94
+ parts.push('## 本地知识库(local KB mode)', `- 本地库根:${ensureLocalKbRoot()}`, task.assignee === 'd'
95
+ ? '- 实施计划原文 = 父任务交接 page_path(库根下 wiki/** 相对路径)→ 直接 fs 读 <库根>/<page_path>;KB 经验召回经 skill 工具加载 llm-wiki(本地库)'
96
+ : '- 评审页经 fs 写 <库根>/wiki/queries/ch_<chainId>/review/<name>.md(库根外一律只读)');
97
+ }
98
+ // 规格卡六段 + 附件注入(经 Chain.specCardId),角色 agent 的输入契约,原汁原味
39
99
  const chain = state.chains.get(task.chainId);
40
100
  const specCard = chain?.specCardId ? state.specCards.get(chain.specCardId) : null;
41
101
  if (specCard) {
@@ -56,7 +116,7 @@ ${task.body}`);
56
116
  parts.push(`- metadata: ${JSON.stringify(h.metadata)}`);
57
117
  }
58
118
  }
59
- // 0.1.0 delegation(spec FR6):D(execute) 目标模式条件注入——spec 卡/父交接命中
119
+ // 0.1.0 delegationD(execute) 目标模式条件注入——spec 卡/父交接命中
60
120
  // GOAL_MODE_KEYWORDS 才注入;否则默认执行(行为不变)。
61
121
  if (task.assignee === 'd' && task.mode === 'execute') {
62
122
  const specText = specCard
@@ -70,7 +130,7 @@ ${task.body}`);
70
130
  }
71
131
  }
72
132
  if (resume) {
73
- // B2:resume 注入运行历史与上次失败原因(不只次数),返工/重试同会话可参考前因
133
+ // resume 注入运行历史与上次失败原因(不只次数),返工/重试同会话可参考前因
74
134
  const lastFail = state.events.filter((e) => e.taskId === task.id && e.kind === 'task/failed').at(-1);
75
135
  const reason = lastFail ? String(lastFail.payload['reason'] ?? '') : '';
76
136
  parts.push(`## Prior attempts: ${task.attempts} (resume session)` + (reason ? `\nlast failure: ${reason}` : ''));
@@ -126,12 +186,12 @@ ${task.body}`);
126
186
  // todo(V 建卡默认态,无父任务即就绪)/ ready / failed(重试)均可调度;其余状态拒
127
187
  if (task.status !== 'ready' && task.status !== 'todo' && task.status !== 'failed')
128
188
  throw new Error('task not schedulable: ' + task.status);
129
- // 0.1.0 delegation(spec FR2):DT 任务运行期注册 chainId(全局子代理 guard 的
189
+ // 0.1.0 delegationDT 任务运行期注册 chainId(全局子代理 guard 的
130
190
  // wiki review namespace 同步解析源);runTask 结束注销。
131
191
  if (task.assignee === 'dt')
132
192
  registerDtTaskChain(task.id, task.chainId);
133
193
  try {
134
- // M2(Q5)+归组:角色会话 cwd 恒为主 agent 工作空间(Chain.workspaceDir)。
194
+ // 归组:角色会话 cwd 恒为主 agent 工作空间(Chain.workspaceDir)。
135
195
  // 缺失时询问用户注册工作区;仍不可得 → block('workspace-unknown'),绝不静默落 kanban 存储目录。
136
196
  const chain = state.chains.get(task.chainId);
137
197
  let sessionCwd = chain?.workspaceDir ?? null;
@@ -139,16 +199,16 @@ ${task.body}`);
139
199
  sessionCwd = await resolveOrCreateWorkspace(this.ctx, null, 'task ' + task.id + ' ' + task.assignee + '/' + task.mode);
140
200
  }
141
201
  if (!sessionCwd) {
142
- await this.kanban.comment(taskId, `链未绑定工作区(Chain.workspaceDir 缺失且用户未提供工作区路径)。请重新 ${this.config.prefixRoutes.plan} 绑定主 agent 工作空间后重试。`, 'system');
202
+ await this.kanban.comment(taskId, `链未绑定工作区(Chain.workspaceDir 缺失且用户未提供工作区路径)。请重新 ${this.configProvider.getEffective().prefixRoutes.plan} 绑定主 agent 工作空间后重试。`, 'system');
143
203
  await this.kanban.claimTask(taskId, 'system');
144
204
  await this.kanban.blockTask(taskId, 'workspace-unknown: 链未绑定工作区(Chain.workspaceDir 缺失)', 'system');
145
205
  return;
146
206
  }
147
- // R20 D(execute):目标仓库解析(供 M3 前置授权判定 + B4 git 凭据注入目标 + 上下文);
148
- // 会话 cwd 不再指向仓库(会话必须在主 agent 工作空间,见 Q5)。
207
+ // D(execute):目标仓库解析(供前置授权判定 + git 凭据注入目标 + 上下文);
208
+ // 会话 cwd 不再指向仓库(会话必须在主 agent 工作空间)。
149
209
  const isDExecute = task.assignee === 'd' && task.mode === 'execute';
150
210
  const dRepo = isDExecute ? resolveTargetRepoDir(task, state, sessionCwd) : null;
151
- // M3(B):D 目标仓库在会话工作空间外 → 跑 D 前先询问用户是否允许(一次授权,D 以 full-access 执行不再逐次提示)。
211
+ // D 目标仓库在会话工作空间外 → 跑 D 前先询问用户是否允许(一次授权,D 以 full-access 执行不再逐次提示)。
152
212
  // 不允许/无询问通道 → claim+block 等待人工放行(状态机要求 running 才能 block);
153
213
  // 放行后再次调度会重新询问。授权前不创建会话,permissionBlockedTasks 避免误走 resume。
154
214
  if (isDExecute && dRepo && !isPathInside(dRepo, sessionCwd)) {
@@ -162,7 +222,7 @@ ${task.body}`);
162
222
  }
163
223
  permissionBlockedTasks.delete(taskId);
164
224
  }
165
- // B2:resume 判定 = 有运行历史(attempts>0 或存在 claimed 事件)且不是「无会话授权阻塞」的任务;
225
+ // resume 判定 = 有运行历史(attempts>0 或存在 claimed 事件)且不是「无会话授权阻塞」的任务;
166
226
  // 后者虽有 claimed 事件但从未创建会话,必须走 create 而非 resume(否则 resume 不存在会话抛错)。
167
227
  const hasRunHistory = !permissionBlockedTasks.has(taskId) &&
168
228
  (task.attempts > 0 || state.events.some((e) => e.taskId === taskId && e.kind === 'task/claimed'));
@@ -174,7 +234,7 @@ ${task.body}`);
174
234
  // 里的 reasoningEffort 不被宿主消费,新建角色会话思考等级会落回宿主默认。改走 DSH agent/request
175
235
  // waterfall 逐请求强制(宿主 installModelSelection 同机制),作用域仅本角色会话;
176
236
  // effort 可由 per-role config 覆盖,默认 'high'(与 model-candidates.ts 默认一致)。
177
- const effort = this.config.roles?.models?.[task.assignee]?.reasoningEffort ?? 'high';
237
+ const effort = this.configProvider.getEffective().roles?.models?.[task.assignee]?.reasoningEffort ?? 'high';
178
238
  const scoped = agentCtx;
179
239
  scoped.on('agent/request', async (_payload, next) => {
180
240
  // 异常不吞:await next() 失败原样向上抛
@@ -182,14 +242,14 @@ ${task.body}`);
182
242
  return { ...resolved, reasoningEffort: effort };
183
243
  });
184
244
  // 角色 agent 等同委派子 agent:固定 approval=never(避免后台会话悬挂等审批)。
185
- // Q3:P/W/D = full access(跨目录读:P 读仓库/外部实证、W 读计划、D 执行);
245
+ // P/W/D = full access(跨目录读:P 读仓库/外部实证、W 读计划、D 执行);
186
246
  // 但 P 挂 plan 写护栏、W 挂只读护栏(写边界由工具级强制,防"改动源码",不靠 prompt 软约束);
187
247
  // PT/DT/V → workspace-write(评审/编排最小权限,PT/DT 只读护栏由 ToolGuard 独立保证)。
188
248
  const session = agentCtx.agent?.session;
189
249
  session?.append?.('approval/policy', { policy: 'never', source: 'delegation' });
190
250
  const fullAccess = isDExecute || task.assignee === 'p' || task.assignee === 'w';
191
251
  session?.append?.('sandbox/mode', fullAccess ? { mode: 'danger-full-access', source: 'delegation' } : { mode: 'workspace-write', source: 'delegation' });
192
- // 执行角色(P/W/D)先挂载 D22 裁剪 preset(kanban-p/w/d),把 shell/approval 等服务注入 agent scope;
252
+ // 执行角色(P/W/D)先挂载裁剪 preset(kanban-p/w/d),把 shell/approval 等服务注入 agent scope;
193
253
  // 不再整包继承官方 code preset:bash/fs/fs-search 由裁剪组合装配,run_code/jobs/skill/goal/
194
254
  // plan-mode/compaction/delegation/web/todo 按角色裁剪(组合文件随包分发 + 运行时安装到
195
255
  // $DSH_HOME/.agent-presets/,见 preset-installer.ts)。否则官方 apply 会抛
@@ -208,30 +268,56 @@ ${task.body}`);
208
268
  }
209
269
  }
210
270
  }
211
- await installRoleTools(agentCtx, task.assignee, { kanban: this.kanban, wiki: this.wiki, taskId: task.id });
271
+ await installRoleTools(agentCtx, task.assignee, { kanban: this.kanban, wiki: this.wiki, taskId: task.id, kbMode: this.configProvider.mode });
272
+ // danger-full-access 会话(P、D(execute))write/edit/bash 菜单去毒
273
+ // (agent scope shadow 注册干净版盖住宿主带毒版本 + execute 剥参转发,详见 src/roles/clean-fs-tools.ts)。
274
+ // 挂载点选在 setup 内、preset.mount 之后:shadow 需经 get(name, agent) 取 preset standing
275
+ // 祖先层里的宿主原定义(kanban-p/d 的 fs/bash 由 preset 提供),且必须在会话开始前完成注册。
276
+ // 仅 P 与 D(execute):两者是 danger-full-access 天花板,escalation 参数无更宽可升(必被拒);
277
+ // PT/DT 是 workspace-write(sandbox_permissions 扩权到天花板是合法功能,剥了破坏官方能力);
278
+ // W 虽 fullAccess 但只读护栏全拒 write,shadow 无意义(最小挂载面,V 无执行工具不涉及)。
279
+ if (task.assignee === 'p' || isDExecute) {
280
+ installCleanFsTools(agentCtx, agentCtx.agent);
281
+ }
282
+ // 组合标记——角色工具面成功组合后,把 { role, taskId } 记到进程内 WeakMap(键=Agent 实例)。
283
+ // 宿主探明:setup 收到的 agentCtx.agent 与发布后 agents.get(id) 返回的是同一 Agent 实例
284
+ // (dsh-agent types/index.d.ts:38 `agent?: Agent` 安装为 Agent.ctx own property),
285
+ // 故此处键入的实例即 resumeOrReuse 里 agents.get 命中的实例。agentCtx.agent 缺失(宿主变体)时
286
+ // 不写标记 → live 复用走工具面校验路径(kanban_complete 可见性),能力无损。
287
+ const liveAgent = agentCtx.agent;
288
+ if (liveAgent)
289
+ markRoleComposition(liveAgent, { role: task.assignee, taskId: task.id });
212
290
  // 只读评审角色(PT/DT)注册 ToolGuard:拦截 tracked source 写入 / git mutation / 含写标记 bash。
213
291
  // 以 dsh-tools 类型为准:tools.guard(execution => reason|undefined),execution.name/arguments 为实际字段。
214
292
  if (task.assignee === 'pt' || task.assignee === 'dt') {
215
293
  const repoRoot = dRepo ?? sessionCwd; // DT 评审目标仓库;PT 以会话工作区为只读边界
216
294
  const toolsSvc = agentCtx.tools;
217
- // DT 额外叠加 wiki review namespace 收窄(projects/<chain>/review/)
295
+ // DT 额外叠加 wiki review namespace 收窄(projects/<repoSlug>/<chain>/review/);
296
+ // local KB 模式:DT 改用 KB 写护栏(唯一可写区域=本地库根,评审页经 fs 写库根),
297
+ // remote 模式仍用 DT 收窄护栏(库根外全只读 + review namespace)。
298
+ const kbMode = this.configProvider.mode;
218
299
  const guardFn = task.assignee === 'dt'
219
- ? buildDTWriteGuard(repoRoot, task.chainId)
300
+ ? (kbMode === 'local' ? buildKbWriteGuard(ensureLocalKbRoot()) : buildDTWriteGuard(repoRoot, task.chainId))
220
301
  : buildReadOnlyWriteGuard(repoRoot);
221
302
  toolsSvc?.guard?.((e) => guardFn(e));
222
303
  }
223
- // Q3:P/W 挂写护栏(wsRoot = 链 workspaceDir = sessionCwd,同 PT/DT 解析方式)。
304
+ // P/W 挂写护栏(wsRoot = 链 workspaceDir = sessionCwd,同 PT/DT 解析方式)。
224
305
  // P = plan 写护栏(openspec/changes/** 内可写,禁改源码);W = 只读护栏(交付=读计划→wiki API,
225
- // fs 零写——I2 起全名拦截,repo 外/workspace 内任意路径 fs 写一律拒,不再依赖 repoRoot 边界)。
306
+ // fs 零写——全名拦截,repo 外/workspace 内任意路径 fs 写一律拒,不再依赖 repoRoot 边界)。
226
307
  // 挂载方式同 PT/DT:tools.guard 是注册方法(dsh-tools 类型),execution 以 { name, arguments } 传入。
227
308
  if (task.assignee === 'p' || task.assignee === 'w') {
228
309
  const toolsSvc = agentCtx.tools;
310
+ // local KB 模式:W 改用 KB 写护栏(唯一可写区域=本地库根,交付页经 write 写库根),
311
+ // remote 模式 W 仍只读护栏(fs 零写);P 恒为 plan 写护栏(与 KB 模式无关)。
312
+ const kbMode = this.configProvider.mode;
229
313
  const guardFn = task.assignee === 'p'
230
314
  ? buildPlanWriteGuard(sessionCwd)
231
- : buildReadOnlyWriteGuard(sessionCwd);
315
+ : (kbMode === 'local' && task.assignee === 'w')
316
+ ? buildKbWriteGuard(ensureLocalKbRoot())
317
+ : buildReadOnlyWriteGuard(sessionCwd);
232
318
  toolsSvc?.guard?.((e) => guardFn(e));
233
319
  }
234
- // M4:D(execute) 注入 git 凭据(repo-local http extraheader,GitLab glpat-* 用 oauth2 basic)。
320
+ // D(execute) 注入 git 凭据(repo-local http extraheader,GitLab glpat-* 用 oauth2 basic)。
235
321
  // 由插件进程(不受 D 会话沙箱限制)写入 <repo>/.git/config;PAT 经 DSH 凭据服务/env 解析;
236
322
  // 注入失败仅告警(用户自带凭据/SSH 的仓库不受影响),未配置 PAT 不注入。
237
323
  if (isDExecute && dRepo) {
@@ -246,18 +332,31 @@ ${task.body}`);
246
332
  }
247
333
  };
248
334
  try {
249
- // R1:claim 后任何异常(buildContext/spawn)→ failTask(attempts+1)→ 调度器重派/看门狗熔断;
335
+ // claim 后任何异常(buildContext/spawn)→ failTask(attempts+1)→ 调度器重派/看门狗熔断;
250
336
  // 不留 "running 无 agent" 悬挂。
251
337
  await this.kanban.claimTask(taskId, 'system');
252
338
  console.error('[dsh-swarm][debug] runner claimed ' + taskId + ' attempts=' + task.attempts);
339
+ // DT spawn 前预检:评审角色依赖 ocr CLI,缺失时模型会在会话内穷尽探活最后才 block(真实事故,
340
+ // 白烧 30+ 步整轮预算)。这里在 spawn 之前直接 block 终态等人工安装——不走 failTask(attempts+1
341
+ // 会触发重派,而重派前 ocr 依旧缺失,纯烧重试预算)。插在 buildContext/模型候选与 create/resume
342
+ // 分叉之前:resume 路径(有运行历史的复用/resume)同样先过预检。
343
+ // probeOcr 内部已吞掉一切异常(网络/权限等一律降级为 installed=false,永不 throw),此处天然 fail-closed。
344
+ if (task.assignee === 'dt') {
345
+ const probe = await this.probeOcrFn();
346
+ if (!probe.installed) {
347
+ await this.kanban.blockTask(taskId, 'review-tool-unavailable: ocr 未安装——GUI 配置面板「评审引擎(ocr)」卡可一键安装,或终端执行 npm install -g @alibaba-group/open-code-review', 'system');
348
+ logToDispatcherLog(this.configProvider, '[ocr-precheck] dt task=' + taskId + ' blocked: ocr not installed');
349
+ return;
350
+ }
351
+ }
253
352
  context = this.buildContext(task, state, hasRunHistory);
254
- // 模型候选链(Task 12):primary + fallbacks,model/provider 不可用时静默切换下一候选;
353
+ // 模型候选链:primary + fallbacks,model/provider 不可用时静默切换下一候选;
255
354
  // 全部候选不可用 → block(model-unavailable) 抛给用户;非 model 错误 → failTask(原逻辑)。
256
- const candidates = buildModelCandidates(this.config, task.assignee, this.defaultModel);
355
+ const candidates = buildModelCandidates(this.configProvider.getEffective(), task.assignee, this.defaultModel);
257
356
  if (candidates.length === 0) {
258
357
  // 无任何候选配置:不传 agentOptions(用部署默认),单次尝试
259
358
  agent = hasRunHistory
260
- ? await this.resumeOrReuse(this.ctx.get('agents'), task.resumeSessionId ?? `kbn-${taskId}`, { setup })
359
+ ? await this.resumeOrReuse(this.ctx.get('agents'), task.resumeSessionId ?? `kbn-${taskId}`, { setup, role: task.assignee, taskId: task.id })
261
360
  : (await this.ctx.get('agents').create({
262
361
  sessionId: SessionId(`kbn-${taskId}`),
263
362
  meta: { cwd: sessionCwd },
@@ -272,7 +371,7 @@ ${task.body}`);
272
371
  // hasRunHistory → resumeOrReuse 直接返回 AgentLike(内部已解包 .agent);create 返回 { agent } 需解包。
273
372
  // 统一归一化为 AgentLike,避免二次解包(h.agent=undefined → if(!agent) 误标 failed)。
274
373
  const h = hasRunHistory
275
- ? await this.resumeOrReuse(agents, task.resumeSessionId ?? `kbn-${taskId}`, { agentOptions: candidate, setup })
374
+ ? await this.resumeOrReuse(agents, task.resumeSessionId ?? `kbn-${taskId}`, { agentOptions: candidate, setup, role: task.assignee, taskId: task.id })
276
375
  : (await agents.create({ sessionId: SessionId(`kbn-${taskId}`), meta: { cwd: sessionCwd }, agentOptions: candidate, setup })).agent;
277
376
  agent = h;
278
377
  // 切换成功且非首选 → 发可审计 model/fallback 评论(记录证据,不弹用户)
@@ -302,7 +401,7 @@ ${task.body}`);
302
401
  }
303
402
  }
304
403
  catch (err) {
305
- // P0-5/R1:claim/buildContext/spawn 失败也走 failed(attempts 递增)→ 调度器重派/看门狗熔断;不再让任务永久 claimed
404
+ // claim/buildContext/spawn 失败也走 failed(attempts 递增)→ 调度器重派/看门狗熔断;不再让任务永久 claimed
306
405
  console.error('[dsh-swarm][debug] runner spawn error ' + taskId + ': ' + String(err));
307
406
  try {
308
407
  await this.kanban.failTask(taskId, 'runner-error: ' + String(err), 'system', { infra: isInfraError(err) });
@@ -315,6 +414,11 @@ ${task.body}`);
315
414
  }
316
415
  if (!agent)
317
416
  return; // 防御:候选链耗尽已在上方 block(model-unavailable)/throw 处理
417
+ // 本轮增量事件基线——agent 拿到之后、followup 之前记录。
418
+ // 0.1.2(DSH-0.1.2-A4-03):Session.events 已移除 → followup 前记录 seq 基线,
419
+ // snapshotEvents(eventsBase) 即「本轮新增事件」(排除旧 incarnation 持久化事件),
420
+ // 供 protocol_violation 时识别 comment-only 收尾(交付滞留 comments,会话10事故形态)。
421
+ const eventsBase = Number(agent.session.seq);
318
422
  // 归组:角色会话 attach 到 cwd 对应工作区(无则询问创建;失败不阻断)
319
423
  const attachId = task.resumeSessionId ?? `kbn-${task.id}`;
320
424
  await attachSessionToWorkspace(this.ctx, attachId, sessionCwd, 'task ' + task.id + ' ' + task.assignee + '/' + task.mode);
@@ -323,56 +427,63 @@ ${task.body}`);
323
427
  console.error('[dsh-swarm][debug] runner followup sent ' + taskId);
324
428
  await agent.whenIdle();
325
429
  console.error('[dsh-swarm][debug] runner whenIdle resolved ' + taskId);
326
- // 修复轮 6:session.events 条目形态为 {type, data:{name}},name data 下,需经 toolName 读取
327
- const used = agent.session.events.some((e) => {
328
- const n = toolName(e);
329
- return n === 'kanban_complete' || n === 'kanban_block';
330
- });
331
- if (!used) {
332
- // 防御:任务可能已被其他路径完成/归档(终态),此时 blockTask 会抛非法转换(done --task/blocked-->)
333
- const fresh = await this.kanban.snapshot();
334
- const cur = fresh.tasks.get(taskId);
335
- const terminal = cur && (cur.status === 'done' || cur.status === 'archived');
336
- if (terminal) {
337
- console.error('[dsh-swarm][debug] runner skip block ' + taskId + ' status=' + (cur ? cur.status : 'gone'));
430
+ // 终态判据(session 10 事故修复):whenIdle resolve 后一次 snapshot,只看任务真实状态——
431
+ // 不再扫 session.events 全历史工具名(旧 incarnation 的 kanban_* 事件会污染判据,
432
+ // 「历史上调过工具名」≠「本轮成功提交」,骗过检查后卡永驻 running)。
433
+ // 确定态(done/archived/blocked/failed,TaskStatus 全集见 src/domain/types.ts)→ 防御日志 skip:
434
+ // blocked 上再 block 抛非法转换;failed 交调度器重派,不做 violation block。
435
+ // 非确定态(running/ready/todo/triage)→ protocol_violation 流程(证据链保留)。
436
+ const fresh = await this.kanban.snapshot();
437
+ const cur = fresh.tasks.get(taskId);
438
+ const settled = !!cur &&
439
+ (cur.status === 'done' || cur.status === 'archived' || cur.status === 'blocked' || cur.status === 'failed');
440
+ if (settled) {
441
+ console.error('[dsh-swarm][debug] runner skip block ' + taskId + ' status=' + (cur ? cur.status : 'gone'));
442
+ }
443
+ else {
444
+ // 协议违规护栏:连续 protocol_violation 阻塞 ≥ maxProtocolViolations(默认 2)后,
445
+ // 下一次违规直接 gave_up(不再恢复,走 [blocked-final] 证据链抛给主 agent)。任意角色(含 pt/dt)统一。
446
+ const maxPV = this.configProvider.getEffective().dispatcher?.maxProtocolViolations ?? 2;
447
+ const priorViolations = fresh.events.filter((e) => e.taskId === taskId && e.kind === 'task/blocked' &&
448
+ String(e.payload['reason'] ?? '').startsWith('protocol_violation')).length;
449
+ const finalBlock = priorViolations >= maxPV;
450
+ const reason = finalBlock
451
+ ? 'gave_up: protocol_violation after ' + maxPV + ' review cycles without complete/block'
452
+ : 'protocol_violation: idle without complete/block';
453
+ await this.kanban.blockTask(taskId, reason, 'system');
454
+ // comment-only 收尾显形——放 block 之后(保证 block 一定先发生,
455
+ // 告警只追加在已阻塞卡上,不影响终态判据与 [blocked-final] 证据链快照)。
456
+ // 本轮增量事件命中 kanban_comment(经 toolName 兼容读取落盘/live 两形态)且未成功提交
457
+ // (能走到这里即终态判据已确认非确定态)→ 交付内容很可能滞留 comments,显形告警。
458
+ const commentOnly = agent.session.snapshotEvents(eventsBase).some((e) => toolName(e) === 'kanban_comment');
459
+ if (commentOnly) {
460
+ await this.kanban.comment(taskId, '[comment-only-closeout] 本轮仅用 kanban_comment 交付(无 complete/block)。交付内容可能滞留 comments(如角色工具缺失/会话被错误复用);请人工核对 comments 与产物后解除阻塞重派。', 'system');
338
461
  }
339
- else {
340
- // 协议违规护栏:连续 protocol_violation 阻塞 maxProtocolViolations(默认 2)后,
341
- // 下一次违规直接 gave_up(不再恢复,走 [blocked-final] 证据链抛给主 agent)。任意角色(含 pt/dt)统一。
342
- const maxPV = this.config.dispatcher?.maxProtocolViolations ?? 2;
343
- const priorViolations = fresh.events.filter((e) => e.taskId === taskId && e.kind === 'task/blocked' &&
344
- String(e.payload['reason'] ?? '').startsWith('protocol_violation')).length;
345
- const finalBlock = priorViolations >= maxPV;
346
- const reason = finalBlock
347
- ? 'gave_up: protocol_violation after ' + maxPV + ' review cycles without complete/block'
348
- : 'protocol_violation: idle without complete/block';
349
- await this.kanban.blockTask(taskId, reason, 'system');
350
- if (finalBlock) {
351
- // [blocked-final] 证据链:block 时间线 + 复核/评论时间线 + 最终 reason(system 确定性写入)
352
- const evs = fresh.events.filter((e) => e.taskId === taskId);
353
- const blockTimeline = evs
354
- .filter((e) => e.kind === 'task/blocked')
355
- .map((e) => ` - seq=${e.seq} at=${e.at} author=${e.author} reason=${String(e.payload['reason'] ?? '')}`)
356
- .join('\n');
357
- const reviewTimeline = evs
358
- .filter((e) => e.kind === 'task/commented')
359
- .map((e) => ` - seq=${e.seq} at=${e.at} author=${e.author}: ${String(e.payload['body'] ?? '')}`)
360
- .join('\n');
361
- await this.kanban.comment(taskId, [
362
- '[blocked-final] 协议违规超护栏,任务不再自动恢复(人工解除后仍按 gave_up 终态处理)。',
363
- '## block 时间线',
364
- blockTimeline,
365
- '## 复核/评论时间线',
366
- reviewTimeline || ' - (无复核评论)',
367
- '最终原因: ' + reason,
368
- ].join('\n'), 'system');
369
- }
462
+ if (finalBlock) {
463
+ // [blocked-final] 证据链:block 时间线 + 复核/评论时间线 + 最终 reason(system 确定性写入)
464
+ const evs = fresh.events.filter((e) => e.taskId === taskId);
465
+ const blockTimeline = evs
466
+ .filter((e) => e.kind === 'task/blocked')
467
+ .map((e) => ` - seq=${e.seq} at=${e.at} author=${e.author} reason=${String(e.payload['reason'] ?? '')}`)
468
+ .join('\n');
469
+ const reviewTimeline = evs
470
+ .filter((e) => e.kind === 'task/commented')
471
+ .map((e) => ` - seq=${e.seq} at=${e.at} author=${e.author}: ${String(e.payload['body'] ?? '')}`)
472
+ .join('\n');
473
+ await this.kanban.comment(taskId, [
474
+ '[blocked-final] 协议违规超护栏,任务不再自动恢复(人工解除后仍按 gave_up 终态处理)。',
475
+ '## block 时间线',
476
+ blockTimeline,
477
+ '## 复核/评论时间线',
478
+ reviewTimeline || ' - (无复核评论)',
479
+ '最终原因: ' + reason,
480
+ ].join('\n'), 'system');
370
481
  }
371
482
  }
372
483
  }
373
484
  catch (err) {
374
485
  console.error('[dsh-swarm][debug] runner error ' + taskId + ': ' + String(err));
375
- // 失败语义(P0-5 统一):发 failed 事件(attempts 递增),由调度器重派或看门狗熔断;不直接 block。
486
+ // 失败语义(统一):发 failed 事件(attempts 递增),由调度器重派或看门狗熔断;不直接 block。
376
487
  // 防御:任务可能已被完成/归档(终态),failTask 会抛非法转换(done --task/failed-->)
377
488
  try {
378
489
  await this.kanban.failTask(taskId, 'runner-error: ' + String(err), 'system', { infra: isInfraError(err) });
@@ -387,17 +498,59 @@ ${task.body}`);
387
498
  unregisterDtTaskChain(task.id);
388
499
  }
389
500
  }
390
- /** RC2:resume 前先查 agents registry 同名会话是否仍 live——live 则直接复用(后续 followup 续用),
391
- * 避免 block→unblock→重跑同一会话时 resume "cannot prepare session while it is live"
392
- * (对齐 VOrchestrator.getVAgent live 复用逻辑)。agents.get 未实现 → 防御回退 resume */
501
+ /** resume 前先查 agents registry 同名会话是否仍 live——live 且组合标记匹配(role+taskId 一致)才复用。
502
+ * 会话10事故根因A:此前对 live agent 盲复用——GUI 打开同名会话产生的默认组合 incarnation
503
+ * 没有角色 preset/kanban_complete 工具面(setup 被跳过),模型只能把交付塞 kanban_comment
504
+ * 现在标记缺失/不匹配时按宿主能力降级(探明结论):
505
+ * - (i) dispose 不可行:AgentHandle.dispose 仅创建者持有(dsh-agent types/index.d.ts:155-158,
506
+ * "ctx.agents.get(id) still returns a bare Agent"),无从释放他人 incarnation。
507
+ * - (ii) 修复可行(生产主路径):Agent.ctx 公开(runtime-types.d.ts:72)且经它访问的 tools 注册表
508
+ * 可枚举/可注册(ToolRuntime.get(name, scope) 返回该 scope 可见定义;register 经 traced ctx 落到
509
+ * 该 agent 的 scope 层)→ 重跑 setup 幂等补挂(effort/approval/sandbox/preset/角色工具/护栏),
510
+ * 补挂后必须验证 kanban_complete 可见才算修复成功。kanban_complete 是所有 runner 角色
511
+ * (p/w/d/pt/dt)都注册的任务工具,且全局面只读子集不含它(main-session-tools.ts:134),
512
+ * 故「scope 内可见 kanban_complete」⟺「该 incarnation 经我方角色 setup 组合过」。
513
+ * - (iii) 兜底:工具注册表不可达(异常宿主/测试桩)→ 抛错走 failTask。错误信息刻意不含
514
+ * isInfraError 关键词 → attempts+1 计入重试预算:每次重派都会撞同一个 live 错误 incarnation
515
+ * 直至重试预算耗尽——有界,不会形成无限重派循环(若误标 infra 则 attempts 不递增才会无限)。
516
+ * agents.get 未实现 → 回退 resume(原行为不回归)。 */
393
517
  async resumeOrReuse(agents, sessionId, opts) {
394
518
  const live = agents.get?.(sessionId);
395
- if (live)
396
- return live;
397
- const h = await agents.resume({ resumeSessionId: SessionId(sessionId), ...opts });
519
+ if (live) {
520
+ // 标记匹配(同 incarnation、同角色、同卡)→ 与 setup 组合完全一致 → 安全复用(原行为收窄版)
521
+ const marker = typeof live === 'object' && live !== null ? roleCompositions.get(live) : undefined;
522
+ if (marker && marker.role === opts.role && marker.taskId === opts.taskId)
523
+ return live;
524
+ // 标记缺失/不匹配 → 绝不盲用。工具注册表(live.ctx.tools,与 installRoleTools 同一访问路径):
525
+ const liveCtx = live.ctx;
526
+ const toolsSvc = liveCtx ? liveCtx.tools : undefined;
527
+ if (toolsSvc?.get) {
528
+ if (toolsSvc.get('kanban_complete', live)) {
529
+ // 工具面完备但标记缺失/不匹配:标记写入失败的历史 incarnation,或旧/手工数据把
530
+ // resumeSessionId 指向同角色其它卡(注:2026-09-07 起 createReworkTask 不再继承源卡
531
+ // resumeSessionId——返工卡走自己的 kbn-<id> 会话,此「跨卡复用」分支为 dead path 防御)——
532
+ // 验证过工具面后复用,不重复补挂(重复 register 同名工具会被 dsh-tools 拒绝)。
533
+ return live;
534
+ }
535
+ // GUI 默认组合 incarnation:缺 kanban_complete → 重跑 setup 幂等补挂后复用。
536
+ // setup 对 live ctx 的各步均可加:effort waterfall/approval+sandbox append(known 事件类型、
537
+ // latest-wins)/preset mount(bindings 覆盖)/角色工具(此前为默认组合,无同名冲突)/护栏。
538
+ await opts.setup(liveCtx);
539
+ if (toolsSvc.get('kanban_complete', live))
540
+ return live; // 修复后必须验证到位,防静默半修复
541
+ throw new Error('live session composition repair failed: kanban_complete still missing after re-setup (session ' + sessionId + ')');
542
+ }
543
+ // (iii):既无标记又无法访问工具注册表 → 拒绝盲复用(会复现事故),failTask 有界重试(见上)。
544
+ throw new Error('live session composition mismatch and unverifiable (no marker, no tool registry): ' + sessionId + ' — refusing blind reuse (incident root cause A)');
545
+ }
546
+ const { agentOptions, setup } = opts;
547
+ const resumeOpts = { resumeSessionId: SessionId(sessionId), setup };
548
+ if (agentOptions)
549
+ resumeOpts['agentOptions'] = agentOptions;
550
+ const h = await agents.resume(resumeOpts);
398
551
  return h.agent;
399
552
  }
400
- /** M3(B):D(execute) 目标仓库在会话工作空间外时,跑 D 前询问用户是否允许。
553
+ /** D(execute) 目标仓库在会话工作空间外时,跑 D 前询问用户是否允许。
401
554
  * 经 ctx.userQuestions(GUI 弹窗)单次询问;无询问通道或拒绝 → 返回 false(由调用方 claim+block 等待人工放行)。 */
402
555
  async requestRepoPermission(task, repo, sessionCwd) {
403
556
  const uq = this.ctx.get?.('userQuestions');
@@ -1,13 +1,13 @@
1
1
  import type { KanbanService } from '../domain/kanban-service.js';
2
2
  import type { AuditEvidence, Task } from '../domain/types.js';
3
3
  /**
4
- * D23 链完成验收核对:Chain(completed) 时核对主会话是否越权写工作区产物。
4
+ * 链完成验收核对:Chain(completed) 时核对主会话是否越权写工作区产物。
5
5
  *
6
- * 数据源(修复轮 7,修复「评估项目只读排查 run_code 被误判为越权写产物」):
6
+ * 数据源(修复「评估项目只读排查 run_code 被误判为越权写产物」):
7
7
  * 1. 主会话会话事件扫描(primary,尽力而为):枚举活 agent 注册表(ctx.agents.list),
8
8
  * 对 id 非 kbn-*(角色会话确定性 id:kbn-<taskId> / kbn-v-<chainId>)的会话,
9
9
  * 扫描其 session.events 中的工具调用。插件无法解析主会话真实 session id(路由只用
10
- * 逻辑 id 'session_main'),故以"非角色会话写 kanban 工作区"为近似。修复轮 7 收紧三点:
10
+ * 逻辑 id 'session_main'),故以"非角色会话写 kanban 工作区"为近似。收紧三点:
11
11
  * a. 作用域收窄:仅扫描会话工作区(session.header.cwd)位于本链发起工作区
12
12
  * (Chain.workspaceDir = /plan: 主 agent 所在工作空间)内的会话,
13
13
  * 排除其他项目的主会话(如 评估 项目里调试 dsh-swarm 的会话);
@@ -40,7 +40,7 @@ export declare class ChainAuditor {
40
40
  private readonly listLiveAgents;
41
41
  constructor(deps: ChainAuditorDeps);
42
42
  /** 执行核对,返回越权证据(空=通过,不阻塞汇报)。
43
- * @param workspaceDir 本链发起工作区(Chain.workspaceDir);提供时仅扫描工作区内的会话(修复轮 7)。 */
43
+ * @param workspaceDir 本链发起工作区(Chain.workspaceDir);提供时仅扫描工作区内的会话。 */
44
44
  check(chainId: string, workspaceDir?: string | null): Promise<AuditEvidence[]>;
45
45
  private reconcileArtifacts;
46
46
  }
@@ -5,12 +5,14 @@ import { eventType, toolArgs, toolName } from './session-events.js';
5
5
  import { isPathInside } from './target-repo.js';
6
6
  /** 直接写工具(无条件视为写能力;只读工具如 read/glob/grep 不算)。 */
7
7
  const DIRECT_WRITE_TOOLS = new Set(['write', 'edit', 'rm', 'mv', 'cp', 'mkdir', 'mkfile']);
8
- /** run_code:写能力载体,需结合派发子调用判定(修复轮 7)。 */
8
+ /** run_code:写能力载体,需结合派发子调用判定。 */
9
9
  const CODE_RUN_TOOLS = new Set(['run_code']);
10
10
  /** bash 命令中的写操作标记(写证据启发式;ls/cat/grep/git status 等只读不算)。
11
- * 重定向标记用 \s>>?(要求 > 前有空白),避免把 2>/dev/null、2>&1 等只读 stderr 重定向误判为写。 */
12
- const BASH_WRITE_RE = /(?:\b(?:touch|mkdir|rm|rmdir|mv|cp|tee|truncate|install|ln|dd|chmod|chown|make|cmake)\b|\bgit\s+(?:add|commit|push|mv|rm|checkout\s+-b|switch\s+-c|worktree\s+add|merge|rebase|reset|clean|restore|tag|remote\s+add)\b|\bpnpm\s+(?:add|install|remove|update|link)\b|\bnpm\s+(?:i|install|add|remove|uninstall|update)\b|\byarn\s+(?:add|remove)\b|\bbun\s+(?:add|install|remove)\b|\bsed\s+-i\b|\bperl\s+-i\b|\s>>?)/i;
13
- /** run_code/兜底 code 字符串中的 Python 写 API 标记(Fix round 2 F2 同源:audit 补 open( 兜底)。
11
+ * 重定向标记用 \s>>?(要求 > 前有空白),避免把 2>/dev/null、2>&1 等只读 stderr 重定向误判为写。
12
+ * git 细化(2026-09-08):merge(?!-base)merge-base 查询被误判;tag 只认带非 -l/-n 参数的
13
+ * 变更形态(tag -l/-n/裸 为列表查询),两份正则(toolsets/chain-auditor)改动须同步。 */
14
+ const BASH_WRITE_RE = /(?:\b(?:touch|mkdir|rm|rmdir|mv|cp|tee|truncate|install|ln|dd|chmod|chown|make|cmake)\b|\bgit\s+(?:add|commit|push|mv|rm|checkout\s+-b|switch\s+-c|worktree\s+add|merge(?!-base)|rebase|reset|clean|restore|tag\s+(?!-l\b|-n\b)\S+|remote\s+add)\b|\bpnpm\s+(?:add|install|remove|update|link)\b|\bnpm\s+(?:i|install|add|remove|uninstall|update)\b|\byarn\s+(?:add|remove)\b|\bbun\s+(?:add|install|remove)\b|\bsed\s+-i\b|\bperl\s+-i\b|\s>>?)/i;
15
+ /** run_code/兜底 code 字符串中的 Python 写 API 标记(audit 补 open( 兜底)。
14
16
  * open() 写模式精确版(读模式 'r' 不命中)、os. 模块写、pathlib Path 写、shutil 复制/移动/删除。 */
15
17
  const PY_CODE_WRITE_RE = /(?:\bopen\(\s*['"][^'"\n]*['"]\s*,\s*(?:(?:mode|encoding|errors|buffering|newline|closefd|opener|text)\s*=\s*)?['"][wa][^'"\n]*['"]|\bos\s*\.\s*(?:remove|unlink|write|rmdir|makedirs|rename)\b|\.(?:write_text|write_bytes|unlink|mkdir|rename)\(|shutil\s*\.\s*(?:copy|move|rmtree))/i;
16
18
  /** 从工具调用参数中收集含 workspacesRoot 的字符串值(文件路径线索)。 */
@@ -43,7 +45,7 @@ function dataField(e, key) {
43
45
  function hasWriteMarker(text) {
44
46
  return BASH_WRITE_RE.test(text) || PY_CODE_WRITE_RE.test(text);
45
47
  }
46
- /** 判定单个工具调用是否构成写证据(修复轮 7:行为判定 + 只读排除)。
48
+ /** 判定单个工具调用是否构成写证据(行为判定 + 只读排除)。
47
49
  * @param subs 该调用的 run_code 派发子调用(无则 null,走兜底/直接判定)。 */
48
50
  function handleCallEvidence(name, args, subs, root, paths) {
49
51
  if (DIRECT_WRITE_TOOLS.has(name)) {
@@ -142,24 +144,27 @@ export class ChainAuditor {
142
144
  this.listLiveAgents = deps.listLiveAgents ?? (() => []);
143
145
  }
144
146
  /** 执行核对,返回越权证据(空=通过,不阻塞汇报)。
145
- * @param workspaceDir 本链发起工作区(Chain.workspaceDir);提供时仅扫描工作区内的会话(修复轮 7)。 */
147
+ * @param workspaceDir 本链发起工作区(Chain.workspaceDir);提供时仅扫描工作区内的会话。 */
146
148
  async check(chainId, workspaceDir = null) {
147
149
  const evidence = [];
148
150
  // 源 1:主会话(非 kbn- 角色会话)写能力工具事件扫描
149
151
  for (const agent of this.listLiveAgents()) {
150
152
  if (String(agent.id ?? '').startsWith('kbn-'))
151
153
  continue; // 角色会话(P/W/D/V)跳过
152
- // 0.1.0 delegation 豁免(spec FR5):header.agentPreset 以 kanban- 开头 → 角色会话
154
+ // 0.1.0 delegation 豁免:header.agentPreset 以 kanban- 开头 → 角色会话
153
155
  // 的子代理(childSessionMeta 记录所 join 的 preset id),产物归属 git 证据链,
154
156
  // 不按"主会话越权"判定;源2(无主产物核对)仍兜底其误写链工作区根。
155
157
  const joinedPreset = agent.session?.header?.agentPreset;
156
158
  if (typeof joinedPreset === 'string' && joinedPreset.startsWith('kanban-'))
157
159
  continue;
158
- // 修复轮 7:作用域收窄——仅扫本链发起工作区内的会话;会话无 cwd(测试伪造)时保守保留扫描
160
+ // 作用域收窄——仅扫本链发起工作区内的会话;会话无 cwd(测试伪造)时保守保留扫描
159
161
  if (workspaceDir && agent.session?.header?.cwd && !isPathInside(agent.session.header.cwd, workspaceDir)) {
160
162
  continue;
161
163
  }
162
- const hit = sessionWriteEvidence(String(agent.id), this.workspacesRoot, agent.session?.events ?? []);
164
+ // 0.1.2(DSH-0.1.2-A4-03):Session.events 移除 → snapshotEvents() 优先,回退 events(旧宿主/测试)
165
+ const ses = agent.session;
166
+ const sessionEvents = ses?.snapshotEvents?.() ?? ses?.events ?? [];
167
+ const hit = sessionWriteEvidence(String(agent.id), this.workspacesRoot, sessionEvents);
163
168
  if (hit)
164
169
  evidence.push(hit);
165
170
  }