@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,63 @@
1
+ // src/tools/ocr-review-tools.ts
2
+ /** ocr_review 工具:把 ocr CLI 三子命令(preview/rule/managed)封装为 cordis 工具,DT 评审角色工具面注册。
3
+ * 依赖全注入可换 fake(tests),缺省用 ocr-cli 真实现。 */
4
+ import { defineTool } from '@deepseek-ai/dsh-tools';
5
+ import { INSTALL_GUIDANCE, managedProviderReady, probeOcr, runOcr } from '../services/ocr-cli.js';
6
+ import { buildOcrArgs, parseManagedJson, parsePreviewJson, shouldSuggestManaged, SUGGEST_MANAGED_FILES } from '../domain/ocr-review.js';
7
+ /** 托管未配置时的降级引导:不改道执行,交还调用方决策。 */
8
+ const MANAGED_FALLBACK_TEXT = '托管模式未配置 LLM——本次按委托模式执行:改调 sub=\'preview\' 获取评审范围后自行评审';
9
+ const SUBS = ['preview', 'rule', 'managed'];
10
+ /** 构造 ocr_review 工具定义(defineTool 返回形态,与 kanban-tools 一致)。 */
11
+ export function buildOcrReviewTool(deps) {
12
+ const runOcrFn = deps.runOcrFn ?? runOcr;
13
+ const probeFn = deps.probeFn ?? probeOcr;
14
+ const managedReadyFn = deps.managedReadyFn ?? managedProviderReady;
15
+ return defineTool({
16
+ name: 'ocr_review',
17
+ description: 'Review code changes via the ocr CLI. Three subcommands: '
18
+ + "'preview' — first step of delegated review; lists reviewable files and branch metadata "
19
+ + '(JSON output: mode/files/excluded/mergeBase) so you can review them yourself; '
20
+ + "'rule' — batch-fetch review rule groups for the file paths returned by preview; "
21
+ + "'managed' — full hosted review where ocr uses its own configured LLM and returns normalized findings JSON "
22
+ + "(requires prior wiring: ocr config provider=dsh-managed). "
23
+ + "Start with 'preview' to scope the review; prefer 'managed' for large change sets when the managed provider is configured.",
24
+ parameters: {
25
+ sub: { type: 'string', required: true, description: "'preview' | 'rule' | 'managed'" },
26
+ repo: { type: 'string', description: '仓库根绝对路径;缺省用当前工作目录' },
27
+ from: { type: 'string', description: 'base 分支/引用(range 模式)' },
28
+ to: { type: 'string', description: '目标分支/引用(range 模式,默认 HEAD)' },
29
+ commit: { type: 'string', description: '单次提交审查' },
30
+ paths: { type: 'array', items: { type: 'string' }, description: 'rule 子命令的文件路径列表' },
31
+ },
32
+ output: { schema: { type: 'json' }, render: (_a, v) => [{ type: 'text', text: String(v) }] },
33
+ async execute(args) {
34
+ const probe = await probeFn();
35
+ if (!probe.installed)
36
+ return INSTALL_GUIDANCE;
37
+ if (args.sub === 'managed' && !managedReadyFn())
38
+ return MANAGED_FALLBACK_TEXT;
39
+ if (!SUBS.includes(args.sub))
40
+ throw new Error(`ocr_review: invalid sub '${args.sub}' (expected 'preview' | 'rule' | 'managed')`);
41
+ if (args.sub === 'rule' && (!args.paths || args.paths.length === 0))
42
+ throw new Error("ocr_review: sub='rule' requires non-empty paths (file path list)");
43
+ if (args.sub === 'managed' && !args.commit && !args.from)
44
+ throw new Error("ocr_review: sub='managed' requires commit or from (base ref)");
45
+ const res = await runOcrFn(buildOcrArgs(args.sub, { repo: args.repo, from: args.from, to: args.to, commit: args.commit, paths: args.paths }), { cwd: deps.cwd?.() ?? process.cwd(), timeoutMs: 600_000 });
46
+ if (res.error && !res.stdout)
47
+ throw new Error(`ocr_review: ${res.error} ${res.stderr.slice(0, 500)}`.trim());
48
+ if (args.sub === 'preview') {
49
+ const preview = parsePreviewJson(res.stdout);
50
+ if (shouldSuggestManaged(preview.files.length)) {
51
+ return JSON.stringify({ ...preview, suggestion: `文件较多(N>${SUGGEST_MANAGED_FILES}),可在配置面板切换托管模式` });
52
+ }
53
+ return JSON.stringify(preview);
54
+ }
55
+ if (args.sub === 'rule')
56
+ return res.stdout.slice(0, 8000);
57
+ const report = parseManagedJson(res.stdout);
58
+ if (report.status !== 'completed' && res.error)
59
+ return JSON.stringify({ ...report, message: res.error });
60
+ return JSON.stringify(report);
61
+ },
62
+ });
63
+ }
@@ -20,8 +20,10 @@ export interface PlanningToolDeps {
20
20
  spawnPrefetch?(prompt: string, workspaceDir: string, parentAgent?: Agent, signal?: AbortSignal): Promise<string>;
21
21
  tempDir(): string;
22
22
  pagePrefix?: string;
23
+ /** KB 双模式:local 时 checklist/learning 落本地库命名空间(wiki/queries/checklists/、wiki/synthesis/learnings/),缺省 remote。 */
24
+ kbMode?: 'remote' | 'local';
23
25
  ownerSessionId?: string;
24
- /** 斜杠命令前缀路由(决策12 单一事实源),用于 description 文案派生。 */
26
+ /** 斜杠命令前缀路由(单一事实源),用于 description 文案派生。 */
25
27
  prefixRoutes: PrefixRoutes;
26
28
  defaultModel?: AgentModelOptions;
27
29
  /** 清单落库成功回调(kb 与 temp 两分支各调一次),供 main-session-tools 回写 planningBySession。 */
@@ -32,6 +34,11 @@ export interface PlanningToolDeps {
32
34
  }): void;
33
35
  /** memory.enabled;false 时 planning_memory_recall 返回 disabled 提示(planning_learning_save 不受影响)。 */
34
36
  memoryEnabled?: boolean;
37
+ /** 闸1:/plan: 捕获的当前工作区(main-session-tools 注入);非 null 且与清单 localPath 不一致 → 阻断落库。 */
38
+ resolveWorkspaceDir?: () => string | null;
39
+ /** 蜂群模式分叉:main-session-tools 注入 () => planningBySession.get('session_main')?.mode ?? null。
40
+ * 'swarm' 时 checklist_save 成功返回体附 nextStep 确认闸指引;前缀模式返回体不变。 */
41
+ flowMode?: () => 'swarm' | 'prefix' | null;
35
42
  }
36
43
  /** 主 agent 规划期工具:需求澄清清单落库(KB 优先/临时目录兜底)+ 只读仓库预取(子代理)。 */
37
44
  export declare function buildPlanningTools(deps: PlanningToolDeps): import("@deepseek-ai/dsh-tools").ToolDefinition[];
@@ -1,19 +1,26 @@
1
1
  // src/tools/planning-tools.ts
2
2
  import { defineTool } from '@deepseek-ai/dsh-tools';
3
+ import {} from '@deepseek-ai/dsh-util-values';
3
4
  import { validatePlanningChecklist, formatChecklistBody } from '../domain/planning-checklist.js';
4
5
  import { validatePrefetchManifest } from '../domain/prefetch-manifest.js';
5
- import { buildChecklistSlug, CHECKLIST_PAGE_PREFIX, assertAllowedWikiPagePath } from '../wiki/page-path.js';
6
+ import { buildChecklistSlug, KB_PAGE_NAMESPACES_HINT, LOCAL_CHECKLIST_PREFIX, LOCAL_LEARNING_BASE, assertAllowedWikiPagePath, assertLocalKbPagePath } from '../wiki/page-path.js';
6
7
  import { validateLearning, formatLearningBody, buildRepoSlug } from '../domain/memory.js';
7
8
  const isWikiError = (e) => e instanceof Error && e.code === 'kb-unreachable';
8
9
  /** 主 agent 规划期工具:需求澄清清单落库(KB 优先/临时目录兜底)+ 只读仓库预取(子代理)。 */
9
10
  export function buildPlanningTools(deps) {
11
+ const local = deps.kbMode === 'local';
12
+ // checklist 前缀双模式:remote → projects/<repoSlug>/checklists/(repoSlug 段在 pagePath 拼接);
13
+ // local → wiki/queries/checklists/(local 时 LocalWikiClient.write 仅接受 wiki/** 相对路径,projects/ 会被 kb-rejected)
10
14
  const pagePrefix = deps.pagePrefix ?? 'projects/';
15
+ const checklistPrefix = local ? LOCAL_CHECKLIST_PREFIX : pagePrefix;
11
16
  const session = deps.ownerSessionId ?? 'session_main';
17
+ const SWARM_NEXT_STEP = '向用户征求确认;仅当用户回复含明确肯定语义(确认/开干/开跑/开始/go 等)才调 kanban_route{intent:\'openspec\'} 建链;模糊、岔开话题、只提修改意见 = 未确认,继续澄清。禁止未确认建链。';
18
+ const swarmNext = () => (deps.flowMode?.() === 'swarm' ? { nextStep: SWARM_NEXT_STEP } : {});
12
19
  return [
13
20
  defineTool({
14
21
  name: 'planning_checklist_save',
15
22
  description: 'Save the converged requirement-clarification checklist (structured schema) to KB, falling back to a temp dir if KB is unreachable. Returns ref/path + authoritative repo path. restoreRef (optional) = existing KB page path to overwrite in place (recovery path when in-memory context was lost); omit for first-time save (creates a new timestamped page).',
16
- parameters: { checklist: { type: 'json', required: true, description: 'Structured PlanningChecklist: spec six sections + manifest(repo.files) + clarifications + doubts. checklist.requirementName (optional) = ' + deps.prefixRoutes.plan + ' rest first sentence, used for the checklist page title 【需求】, same source as the task-card title' }, restoreRef: { type: 'string', description: 'Optional KB page path to overwrite in place (recovery path); omit for new save' } },
23
+ parameters: { checklist: { type: 'json', required: true, description: 'Structured PlanningChecklist: {requirementName?, spec: {problem, solution, user_stories, impl_decisions, testing, out_of_scope}, manifest, clarifications, doubts: Array<{"q": string, "resolved": boolean, "answer"?: string}>, risks?}. spec.user_stories: array of plain strings — each element ONE sentence "As a <role>, I want <capability>, so that <benefit>"; NEVER objects/nested. spec.impl_decisions: array of plain strings — one decision per element; NEVER objects. clarifications: non-empty required — record every Q&A asked during this planning round; Array<{"q": string, "a": string}> with keys exactly "q"/"a" (NOT "question"/"answer"). risks (optional): Array<{"description": string, "source": string, "mitigation": string}> — register real risks/non-blocking concerns surfaced during clarification; omit or [] when none. checklist.requirementName (optional) = ' + deps.prefixRoutes.plan + ' rest first sentence, used for the checklist page title 【需求】, same source as the task-card title' }, restoreRef: { type: 'string', description: 'Optional KB page path to overwrite in place (recovery path); omit for new save' } },
17
24
  output: { schema: { type: 'json' }, render: (_a, v) => [{ type: 'text', text: JSON.stringify(v) }] },
18
25
  async execute(args) {
19
26
  const caller = deps.getCaller();
@@ -23,13 +30,17 @@ export function buildPlanningTools(deps) {
23
30
  if (errors.length > 0)
24
31
  throw new Error('invalid planning checklist: ' + errors.join('; '));
25
32
  const checklist = args.checklist;
33
+ const wsDir = deps.resolveWorkspaceDir?.() ?? null;
34
+ if (wsDir && checklist.manifest.repo.localPath !== wsDir) {
35
+ throw new Error(`[workspace-mismatch] 清单 manifest.repo.localPath (${checklist.manifest.repo.localPath}) 与当前工作区 (${wsDir}) 不一致。请在目标仓库工作区内重新执行 ${deps.prefixRoutes.plan} 重新澄清落库(不可跳过)。`);
36
+ }
26
37
  const body = formatChecklistBody(checklist);
27
38
  // 恢复路径(内存丢失后重建):传 restoreRef 则覆盖原页,不产生重复页
28
- if (args.restoreRef && args.restoreRef.startsWith(pagePrefix)) {
39
+ if (args.restoreRef && args.restoreRef.startsWith(checklistPrefix)) {
29
40
  try {
30
41
  await deps.wiki.write(args.restoreRef, body);
31
42
  deps.onChecklistSaved?.({ ref: args.restoreRef, source: 'kb', checklist });
32
- return { ok: true, ref: args.restoreRef, source: 'kb', repoPath: checklist.manifest.repo.localPath };
43
+ return { ok: true, ref: args.restoreRef, source: 'kb', repoPath: checklist.manifest.repo.localPath, ...swarmNext() };
33
44
  }
34
45
  catch (err) {
35
46
  if (!isWikiError(err))
@@ -37,11 +48,14 @@ export function buildPlanningTools(deps) {
37
48
  // KB 不可达 → 落临时目录兜底(不覆盖原页),回调仍回填内存
38
49
  }
39
50
  }
40
- const pagePath = `${CHECKLIST_PAGE_PREFIX}${buildChecklistSlug(checklist.requirementName ?? checklist.spec.problem)}-${Date.now().toString(36)}.md`;
51
+ const slug = buildChecklistSlug(checklist.requirementName ?? checklist.spec.problem);
52
+ const pagePath = local
53
+ ? `${checklistPrefix}${slug}-${Date.now().toString(36)}.md`
54
+ : `${pagePrefix}${buildRepoSlug(checklist.manifest.repo.localPath)}/checklists/${slug}-${Date.now().toString(36)}.md`;
41
55
  try {
42
56
  await deps.wiki.write(pagePath, body);
43
57
  deps.onChecklistSaved?.({ ref: pagePath, source: 'kb', checklist });
44
- return { ok: true, ref: pagePath, source: 'kb', repoPath: checklist.manifest.repo.localPath };
58
+ return { ok: true, ref: pagePath, source: 'kb', repoPath: checklist.manifest.repo.localPath, ...swarmNext() };
45
59
  }
46
60
  catch (err) {
47
61
  if (!isWikiError(err))
@@ -52,7 +66,7 @@ export function buildPlanningTools(deps) {
52
66
  mkdirSync(deps.tempDir(), { recursive: true });
53
67
  writeFileSync(local, body, 'utf8');
54
68
  deps.onChecklistSaved?.({ ref: local, source: 'temp', checklist });
55
- return { ok: true, ref: local, source: 'temp', repoPath: checklist.manifest.repo.localPath };
69
+ return { ok: true, ref: local, source: 'temp', repoPath: checklist.manifest.repo.localPath, ...swarmNext() };
56
70
  }
57
71
  },
58
72
  }),
@@ -86,7 +100,7 @@ export function buildPlanningTools(deps) {
86
100
  }),
87
101
  defineTool({
88
102
  name: 'planning_learning_save',
89
- description: 'Save a distilled learning (experience) to the knowledge base. scope=chain → projects/<chainId>/learnings/ (requirement-level); scope=project → projects/<repoSlug>/learnings/ (repo-level, repoSlug derived from the chain workspaceDir). Returns ref. Soft-fails {ok:false,reason:"kb-unreachable"} when KB is unreachable (no temp fallback).',
103
+ description: 'Save a distilled learning (experience) to the knowledge base. Remote KB: scope=chain → projects/<repoSlug>/<chainId>/learnings/ (requirement-level); scope=project → projects/<repoSlug>/learnings/ (repo-level). repoSlug is derived from the chain workspaceDir; both scopes require chain.workspaceDir. Local KB: both scopes → wiki/synthesis/learnings/<chainId|repoSlug>/. Returns ref. Soft-fails {ok:false,reason:"kb-unreachable"} when KB is unreachable (no temp fallback).',
90
104
  parameters: {
91
105
  learning: { type: 'json', required: true, description: 'LearningEntry: { title (≤80 chars), lesson, evidence (mechanical chain/task id — required), tags: string[] }' },
92
106
  scope: { type: 'string', enum: ['chain', 'project'], required: true, description: '"chain" (requirement-level) | "project" (repo-level)' },
@@ -110,13 +124,23 @@ export function buildPlanningTools(deps) {
110
124
  throw new Error('unknown chain: ' + args.chainId);
111
125
  const entry = args.learning;
112
126
  let prefix;
113
- if (args.scope === 'chain') {
114
- prefix = `projects/${args.chainId}/learnings/`;
127
+ if (local) {
128
+ // local:scope=chain 直接挂 chainId;scope=project 挂 repoSlug(需 workspaceDir)
129
+ if (args.scope === 'chain') {
130
+ prefix = `${LOCAL_LEARNING_BASE}${args.chainId}/`;
131
+ }
132
+ else {
133
+ if (!chain.workspaceDir)
134
+ throw new Error('scope=project requires chain.workspaceDir (target repo) — chain has none');
135
+ prefix = `${LOCAL_LEARNING_BASE}${buildRepoSlug(chain.workspaceDir)}/`;
136
+ }
115
137
  }
116
138
  else {
139
+ // remote:两 scope 均要求 chain.workspaceDir,统一挂 projects/<repoSlug>/
117
140
  if (!chain.workspaceDir)
118
- throw new Error('scope=project requires chain.workspaceDir (target repo) — chain has none');
119
- prefix = `projects/${buildRepoSlug(chain.workspaceDir)}/learnings/`;
141
+ throw new Error('learning save requires chain.workspaceDir (target repo) — chain has none');
142
+ const wsRoot = `${pagePrefix}${buildRepoSlug(chain.workspaceDir)}/`;
143
+ prefix = args.scope === 'chain' ? `${wsRoot}${args.chainId}/learnings/` : `${wsRoot}learnings/`;
120
144
  }
121
145
  const pagePath = `${prefix}${buildChecklistSlug(entry.title)}-${Date.now().toString(36)}.md`;
122
146
  try {
@@ -132,9 +156,9 @@ export function buildPlanningTools(deps) {
132
156
  }),
133
157
  defineTool({
134
158
  name: 'planning_memory_recall',
135
- description: 'Recall KB memory for planning. path mode: read a full page (whitelist: projects/checklists/, projects/learnings/, projects/<slug>/learnings/, projects/ch_*/learnings/, projects/ch_*/t_*.md, projects/ch_*/review/) truncated to 8000 chars. query mode: full-text search returning top 5 {path,title,score}. Returns {ok:false,reason:"kb-unreachable"} on KB failure; {ok:false,reason:"disabled"} when memory is disabled.',
159
+ description: 'Recall KB memory for planning. path mode: read a full page truncated to 8000 chars. path mode whitelist: remote = ' + KB_PAGE_NAMESPACES_HINT + '; local = any wiki/** relative path inside the local KB root. query mode: full-text search returning top 5 {path,title,score}. Returns {ok:false,reason:"kb-unreachable"} on KB failure; {ok:false,reason:"disabled"} when memory is disabled.',
136
160
  parameters: {
137
- path: { type: 'string', description: 'KB page path to read in full (mutually exclusive with query)' },
161
+ path: { type: 'string', description: 'KB page path to read in full (mutually exclusive with query). remote mode: projects/ namespace path; local mode: wiki/** relative path inside the local KB root.' },
138
162
  query: { type: 'string', description: 'Full-text query; returns top 5 result paths (mutually exclusive with path)' },
139
163
  },
140
164
  output: { schema: { type: 'json' }, render: (_a, v) => [{ type: 'text', text: JSON.stringify(v) }] },
@@ -149,7 +173,12 @@ export function buildPlanningTools(deps) {
149
173
  if (hasPath === hasQuery)
150
174
  throw new Error('provide exactly one of path|query');
151
175
  if (hasPath) {
152
- assertAllowedWikiPagePath(args.path);
176
+ // path 白名单按 KB 双模式分支:remote → projects/** 命名空间;local → wiki/**(
177
+ // local 的 checklist/learning 全落 wiki/ 前缀,用 projects/ 白名单会把 local 读腿全拒)
178
+ if (local)
179
+ assertLocalKbPagePath(args.path);
180
+ else
181
+ assertAllowedWikiPagePath(args.path);
153
182
  try {
154
183
  const d = await deps.wiki.read(args.path);
155
184
  const content = d.rawMd.length > 8000 ? d.rawMd.slice(0, 8000) + '…' : d.rawMd;
@@ -1,4 +1,5 @@
1
1
  import { defineTool } from '@deepseek-ai/dsh-tools';
2
+ import {} from '@deepseek-ai/dsh-util-values';
2
3
  import { can } from '../domain/permissions.js';
3
4
  function guard(action, caller) {
4
5
  if (!can(action, caller.actor, null))
@@ -1,4 +1,5 @@
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) {
@@ -1,6 +1,7 @@
1
1
  import { defineTool } from '@deepseek-ai/dsh-tools';
2
+ import {} from '@deepseek-ai/dsh-util-values';
2
3
  import { can } from '../domain/permissions.js';
3
- import { assertAllowedWikiPagePath } from '../wiki/page-path.js';
4
+ import { assertAllowedWikiPagePath, KB_PAGE_NAMESPACES_HINT } from '../wiki/page-path.js';
4
5
  function guard(action, caller) {
5
6
  if (!can(action, caller.actor, null))
6
7
  throw new Error('permission denied: ' + action);
@@ -34,7 +35,7 @@ export function buildWikiTools(wiki, getCaller) {
34
35
  }),
35
36
  defineTool({
36
37
  name: 'wiki_write',
37
- description: 'Write a wiki-vault page under the configured pagePrefix (W only).',
38
+ description: 'Write a wiki-vault page under projects/<repoSlug>/ namespaces (W only). pagePath must match: ' + KB_PAGE_NAMESPACES_HINT,
38
39
  parameters: {
39
40
  pagePath: { type: 'string', required: true },
40
41
  content: { type: 'string', required: true },
@@ -43,11 +44,11 @@ export function buildWikiTools(wiki, getCaller) {
43
44
  async execute(args) {
44
45
  const caller = getCaller();
45
46
  guard('wiki-write', caller);
46
- // Q3&5:工具边界强校验——只允许 projects/checklists/、projects/ch_*/t_*.md、projects/ch_*/review/
47
- // 三类命名空间(page-path.ts 白名单),杜绝 LLM 自造路径/拼错层级导致 kb_url 无法跳转。
47
+ // 工具边界强校验——只允许 projects/<repoSlug>/ 白名单命名空间(KB_PAGE_NAMESPACES_HINT 五类,
48
+ // page-path.ts),杜绝 LLM 自造路径/拼错层级导致 kb_url 无法跳转。
48
49
  assertAllowedWikiPagePath(args.pagePath);
49
50
  const out = await wiki.write(args.pagePath, args.content);
50
- // Q4:工具直接拼完整 kb_url(host 用 config.wikiVault.baseUrl,杜绝 LLM 手写错域名)。
51
+ // 工具直接拼完整 kb_url(host 用 config.wikiVault.baseUrl,杜绝 LLM 手写错域名)。
51
52
  // W 角色交付闸(kanban_complete w:kb)同时校验 host 前缀,双保险。
52
53
  const base = wiki.baseUrl.replace(/\/$/, '');
53
54
  return { path: out.path, kb_url: `${base}/#/page/${args.pagePath}` };
@@ -1,9 +1,16 @@
1
- import type { WikiVaultClient } from './wiki-vault-client.js';
2
1
  import type { BoardState } from '../domain/types.js';
2
+ /** kb-linkage 所需最小 wiki 面(WikiVaultClient / LocalWikiClient 均满足,双模式客户端注入)。 */
3
+ type KbWikiClient = {
4
+ read(pagePath: string): Promise<{
5
+ rawMd: string;
6
+ }>;
7
+ write(pagePath: string, content: string): Promise<unknown>;
8
+ };
3
9
  /**
4
10
  * 机械互链登记:链上 w:kb 任务完成时调用。
5
11
  * - 清单页:追加/更新「关联文档」区块,列出链上全部已 done 的 W2/W3 页。
6
12
  * - 当前页:写回清单页链接(清单 ref 来自规格卡 kind:'kb' 附件)。
7
13
  * 幂等(containsLine / 区块就地替换);任何 wiki 读/写失败均静默跳过,不抛错。
8
14
  */
9
- export declare function syncKbLinks(wiki: WikiVaultClient, state: BoardState, taskId: string): Promise<void>;
15
+ export declare function syncKbLinks(wiki: KbWikiClient, state: BoardState, taskId: string): Promise<void>;
16
+ export {};
@@ -49,9 +49,9 @@ export async function syncKbLinks(wiki, state, taskId) {
49
49
  if (!chain?.specCardId)
50
50
  return;
51
51
  const spec = state.specCards.get(chain.specCardId);
52
- // 清单页 ref:kind:'kb' 附件;仅接受 projects/ 命名空间(临时目录兜底路径不是 KB 页,跳过)
52
+ // 清单页 ref:kind:'kb' 附件;接受 projects/(remote)或 wiki/(local)命名空间(临时目录兜底路径不是 KB 页,跳过)
53
53
  const checklistRef = spec?.attachments.find((a) => a.kind === 'kb')?.ref ?? null;
54
- const checklistPath = checklistRef && checklistRef.startsWith('projects/') ? checklistRef : null;
54
+ const checklistPath = checklistRef && (checklistRef.startsWith('projects/') || checklistRef.startsWith('wiki/')) ? checklistRef : null;
55
55
  // 链上已 done 的 W2/W3 页(含当前任务所属页)
56
56
  const pages = [...state.tasks.values()]
57
57
  .filter((t) => t.chainId === task.chainId && t.assignee === 'w' && t.mode === 'kb' && t.status === 'done')
@@ -61,7 +61,7 @@ export async function syncKbLinks(wiki, state, taskId) {
61
61
  ? state.handoffs.get(t.id).metadata.page_path
62
62
  : null,
63
63
  }))
64
- .filter((p) => p.pagePath !== null && p.pagePath.startsWith('projects/'));
64
+ .filter((p) => p.pagePath !== null && (p.pagePath.startsWith('projects/') || p.pagePath.startsWith('wiki/')));
65
65
  if (pages.length === 0)
66
66
  return;
67
67
  // 1) 清单页:登记全部 W2/W3 页链接
@@ -0,0 +1,14 @@
1
+ import { type WikiSearchResult } from './wiki-vault-client.js';
2
+ export declare class LocalWikiClient {
3
+ readonly baseUrl = "";
4
+ readonly root: string;
5
+ constructor(root: string);
6
+ private abs;
7
+ write(pagePath: string, content: string): Promise<{
8
+ path: string;
9
+ }>;
10
+ read(pagePath: string): Promise<{
11
+ rawMd: string;
12
+ }>;
13
+ search(q: string): Promise<WikiSearchResult[]>;
14
+ }
@@ -0,0 +1,101 @@
1
+ // src/wiki/local-kb-client.ts
2
+ // 本地 KB 客户端(llm-wiki 目录结构):与 WikiVaultClient 同构的 search/read/write 面,
3
+ // local 模式下替换注入(planning 工具 / kb-linkage / memory-recall 复用既有逻辑,零分支扩散)。
4
+ // 排序原则:相关性优先 7 : 新鲜度 3(0.7*scoreNorm + 0.3*mtimeNorm)。
5
+ import { readdirSync, readFileSync, writeFileSync, mkdirSync, statSync, existsSync } from 'node:fs';
6
+ import { join, dirname, resolve, sep } from 'node:path';
7
+ import { WikiError } from './wiki-vault-client.js';
8
+ import { isInsideKbRoot } from './local-kb.js';
9
+ import { assertLocalKbPagePath } from './page-path.js';
10
+ export class LocalWikiClient {
11
+ baseUrl = '';
12
+ root;
13
+ constructor(root) { this.root = root; }
14
+ abs(pagePath) {
15
+ assertLocalKbPagePath(pagePath); // 白名单单一来源(wiki/**、拒 .. 与绝对路径),勿内联重复
16
+ const t = resolve(this.root, pagePath);
17
+ if (!isInsideKbRoot(this.root, t))
18
+ throw new WikiError('kb-rejected', undefined, `kb-rejected: path escapes local KB root: ${pagePath}`);
19
+ return t;
20
+ }
21
+ async write(pagePath, content) {
22
+ const t = this.abs(pagePath);
23
+ try {
24
+ mkdirSync(dirname(t), { recursive: true });
25
+ writeFileSync(t, content, 'utf8');
26
+ }
27
+ catch (err) {
28
+ // 降级链依赖:fs 失败归一 kb-unreachable(planning 工具按 code 判定 temp 兜底/软失败)
29
+ throw new WikiError('kb-unreachable', undefined, `kb-unreachable: local KB write failed: ${String(err)}`);
30
+ }
31
+ return { path: pagePath };
32
+ }
33
+ async read(pagePath) {
34
+ const t = this.abs(pagePath);
35
+ if (!existsSync(t))
36
+ throw new WikiError('kb-rejected', undefined, `kb-rejected: page not found: ${pagePath}`);
37
+ try {
38
+ return { rawMd: readFileSync(t, 'utf8') };
39
+ }
40
+ catch (err) {
41
+ throw new WikiError('kb-unreachable', undefined, `kb-unreachable: local KB read failed: ${String(err)}`);
42
+ }
43
+ }
44
+ async search(q) {
45
+ const needle = String(q ?? '').toLowerCase().trim();
46
+ if (!needle)
47
+ return [];
48
+ const hits = [];
49
+ const walk = (dir) => {
50
+ let entries = [];
51
+ try {
52
+ entries = readdirSync(dir);
53
+ }
54
+ catch {
55
+ return;
56
+ }
57
+ for (const e of entries) {
58
+ const p = join(dir, e);
59
+ const st = statSync(p);
60
+ if (st.isDirectory()) {
61
+ walk(p);
62
+ continue;
63
+ }
64
+ if (!e.endsWith('.md'))
65
+ continue;
66
+ let text = '';
67
+ try {
68
+ text = readFileSync(p, 'utf8');
69
+ }
70
+ catch {
71
+ continue;
72
+ }
73
+ const lower = text.toLowerCase();
74
+ const n = lower.split(needle).length - 1;
75
+ if (n === 0)
76
+ continue;
77
+ hits.push({
78
+ path: p.slice(this.root.length + 1).split(sep).join('/'),
79
+ title: text.split('\n')[0]?.replace(/^#\s*/, '').trim() || e,
80
+ score: n,
81
+ mtime: Math.floor(st.mtimeMs / 1000),
82
+ hits: n,
83
+ });
84
+ }
85
+ };
86
+ walk(this.root);
87
+ if (hits.length === 0)
88
+ return [];
89
+ const maxHits = Math.max(...hits.map((h) => h.hits));
90
+ const times = hits.map((h) => h.mtime);
91
+ const minT = Math.min(...times);
92
+ const maxT = Math.max(...times);
93
+ const span = maxT - minT || 1;
94
+ return hits
95
+ .map((h) => ({
96
+ ...h,
97
+ score: Number((0.7 * (h.hits / maxHits) + 0.3 * ((h.mtime - minT) / span)).toFixed(4)),
98
+ }))
99
+ .sort((a, b) => b.score - a.score);
100
+ }
101
+ }
@@ -0,0 +1,6 @@
1
+ export declare function localKbRoot(): string;
2
+ /** 尽力创建库根(幂等);失败由调用方告警 + block(kb-unreachable)。 */
3
+ export declare function ensureLocalKbRoot(root?: string): string;
4
+ /** target 须为绝对路径且解析后落在 root 内(resolve 折叠重复斜杠;相对路径 fail-closed,
5
+ * 因为 bash/fs 里的相对目标语义属会话 cwd 而非库根,护栏不可猜测)。 */
6
+ export declare function isInsideKbRoot(root: string, target: string): boolean;
@@ -0,0 +1,25 @@
1
+ // src/wiki/local-kb.ts
2
+ // 本地 KB(llm-wiki)库根工具(设计:独立 <DSH_HOME>/storages/kanban/wiki/,隔离用户个人 ~/.llm-wiki-path)。
3
+ import { homedir } from 'node:os';
4
+ import { join, resolve, sep } from 'node:path';
5
+ import { mkdirSync } from 'node:fs';
6
+ export function localKbRoot() {
7
+ const dshHome = process.env.DSH_HOME ?? join(homedir(), '.dsh');
8
+ return join(dshHome, 'storages', 'kanban', 'wiki');
9
+ }
10
+ /** 尽力创建库根(幂等);失败由调用方告警 + block(kb-unreachable)。 */
11
+ export function ensureLocalKbRoot(root = localKbRoot()) {
12
+ mkdirSync(root, { recursive: true });
13
+ return root;
14
+ }
15
+ /** target 须为绝对路径且解析后落在 root 内(resolve 折叠重复斜杠;相对路径 fail-closed,
16
+ * 因为 bash/fs 里的相对目标语义属会话 cwd 而非库根,护栏不可猜测)。 */
17
+ export function isInsideKbRoot(root, target) {
18
+ if (!target)
19
+ return false;
20
+ // 相对路径 fail-closed:不与 root 拼接猜测(相对目标语义属会话 cwd)
21
+ if (resolve(target) !== target)
22
+ return false;
23
+ const r = resolve(root).replace(/\/+$/, '');
24
+ return resolve(target) === r || resolve(target).startsWith(r + sep);
25
+ }
@@ -1,16 +1,24 @@
1
- import type { WikiVaultClient, WikiSearchResult } from './wiki-vault-client.js';
2
- export declare function recallLearningIndex(wiki: WikiVaultClient, opts: {
1
+ import type { WikiSearchResult } from './wiki-vault-client.js';
2
+ /** KB 客户端最小检索面(WikiVaultClient / LocalWikiClient 均满足)。 */
3
+ type WikiSearchClient = {
4
+ search(q: string): Promise<WikiSearchResult[]>;
5
+ };
6
+ export declare function recallLearningIndex(wiki: WikiSearchClient, opts: {
3
7
  requirementName: string | null;
4
8
  workspaceDir: string | null;
9
+ kbMode?: 'remote' | 'local';
5
10
  }): Promise<WikiSearchResult[]>;
6
- export declare function recallDocIndex(wiki: WikiVaultClient, opts: {
11
+ export declare function recallDocIndex(wiki: WikiSearchClient, opts: {
7
12
  requirementName: string | null;
8
13
  workspaceDir: string | null;
14
+ kbMode?: 'remote' | 'local';
9
15
  }): Promise<WikiSearchResult[]>;
10
- export declare function recallMemoryIndex(wiki: WikiVaultClient, opts: {
16
+ export declare function recallMemoryIndex(wiki: WikiSearchClient, opts: {
11
17
  requirementName: string | null;
12
18
  workspaceDir: string | null;
13
19
  maxEntries: number;
20
+ kbMode?: 'remote' | 'local';
14
21
  }): Promise<string | null>;
15
- /** /openspec: 恢复路径复用:搜【需求】候选清单页(projects/ 前缀 top5)。 */
16
- export declare function searchChecklists(wiki: WikiVaultClient, pagePrefix?: string): Promise<string[]>;
22
+ /** /openspec: 恢复路径复用:搜【需求】候选清单页(pagePrefix 前缀 top5;local 调用方传 wiki/queries/checklists/)。 */
23
+ export declare function searchChecklists(wiki: WikiSearchClient, pagePrefix?: string): Promise<string[]>;
24
+ export {};
@@ -1,4 +1,5 @@
1
1
  import { buildMemoryIndexBlock, weightedRank, buildRepoSlug } from '../domain/memory.js';
2
+ import { isAllowedWikiPagePath } from './page-path.js';
2
3
  const TIMEOUT_MS = 6_000;
3
4
  async function withTimeout(p) {
4
5
  try {
@@ -8,26 +9,26 @@ async function withTimeout(p) {
8
9
  return null;
9
10
  }
10
11
  }
11
- /** 路1 范围:全局 + 当前仓库项目级 learnings(workspaceDir null仅全局)。 */
12
- function isScopedLearning(path, repoSlug) {
13
- if (path.startsWith('projects/learnings/'))
14
- return true;
15
- if (repoSlug && path.startsWith(`projects/${repoSlug}/learnings/`))
16
- return true;
17
- return false;
12
+ /** 路1 范围:remote = 当前仓库项目级 learnings(workspaceDir 无范围匹配;全局 learnings 命名空间已断代);
13
+ * local = wiki/synthesis/learnings/。 */
14
+ function isScopedLearning(path, repoSlug, kbMode = 'remote') {
15
+ if (kbMode === 'local')
16
+ return path.startsWith('wiki/synthesis/learnings/');
17
+ return !!repoSlug && path.startsWith(`projects/${repoSlug}/learnings/`);
18
18
  }
19
19
  export async function recallLearningIndex(wiki, opts) {
20
20
  const repoSlug = opts.workspaceDir ? buildRepoSlug(opts.workspaceDir) : null;
21
+ const kbMode = opts.kbMode ?? 'remote';
21
22
  if (opts.requirementName) {
22
23
  const r = await withTimeout(wiki.search(opts.requirementName));
23
24
  if (!r)
24
25
  return [];
25
- return weightedRank(r.filter((x) => isScopedLearning(x.path, repoSlug)), (x) => x.score, (x) => x.mtime);
26
+ return weightedRank(r.filter((x) => isScopedLearning(x.path, repoSlug, kbMode)), (x) => x.score, (x) => x.mtime);
26
27
  }
27
28
  const r = await withTimeout(wiki.search('【Learning】'));
28
29
  if (!r)
29
30
  return [];
30
- return r.filter((x) => isScopedLearning(x.path, repoSlug)).sort((a, b) => b.mtime - a.mtime);
31
+ return r.filter((x) => isScopedLearning(x.path, repoSlug, kbMode)).sort((a, b) => b.mtime - a.mtime);
31
32
  }
32
33
  export async function recallDocIndex(wiki, opts) {
33
34
  if (!opts.requirementName)
@@ -36,20 +37,23 @@ export async function recallDocIndex(wiki, opts) {
36
37
  if (!r)
37
38
  return [];
38
39
  const repoSlug = opts.workspaceDir ? buildRepoSlug(opts.workspaceDir) : null;
40
+ const kbMode = opts.kbMode ?? 'remote';
39
41
  return r
40
- .filter((x) => x.path.startsWith('projects/') && !isScopedLearning(x.path, repoSlug))
42
+ .filter((x) => kbMode === 'local'
43
+ ? x.path.startsWith('wiki/') && !isScopedLearning(x.path, repoSlug, 'local')
44
+ : isAllowedWikiPagePath(x.path) && !isScopedLearning(x.path, repoSlug, 'remote'))
41
45
  .sort((a, b) => b.score - a.score);
42
46
  }
43
47
  export async function recallMemoryIndex(wiki, opts) {
44
48
  const [learnings, docs] = await Promise.all([
45
- recallLearningIndex(wiki, { requirementName: opts.requirementName, workspaceDir: opts.workspaceDir }),
46
- recallDocIndex(wiki, { requirementName: opts.requirementName, workspaceDir: opts.workspaceDir }),
49
+ recallLearningIndex(wiki, { requirementName: opts.requirementName, workspaceDir: opts.workspaceDir, kbMode: opts.kbMode }),
50
+ recallDocIndex(wiki, { requirementName: opts.requirementName, workspaceDir: opts.workspaceDir, kbMode: opts.kbMode }),
47
51
  ]);
48
52
  const learningEntries = learnings.slice(0, Math.ceil(opts.maxEntries / 2)).map((r) => ({ kind: 'learning', title: r.title, path: r.path }));
49
53
  const docEntries = docs.slice(0, opts.maxEntries - learningEntries.length).map((r) => ({ kind: 'doc', title: r.title, path: r.path }));
50
54
  return buildMemoryIndexBlock([...learningEntries, ...docEntries]);
51
55
  }
52
- /** /openspec: 恢复路径复用:搜【需求】候选清单页(projects/ 前缀 top5)。 */
56
+ /** /openspec: 恢复路径复用:搜【需求】候选清单页(pagePrefix 前缀 top5;local 调用方传 wiki/queries/checklists/)。 */
53
57
  export async function searchChecklists(wiki, pagePrefix = 'projects/') {
54
58
  const r = await withTimeout(wiki.search('【需求】'));
55
59
  if (!r)
@@ -1,9 +1,15 @@
1
- export declare const CHECKLIST_PAGE_PREFIX = "projects/checklists/";
2
- export declare const LEARNINGS_PAGE_PREFIX = "projects/learnings/";
1
+ /** 命名空间提示(报错/工具 description 文案单一来源,禁止散落硬编码)。 */
2
+ export declare const KB_PAGE_NAMESPACES_HINT = "projects/<repoSlug>/checklists/\u3001projects/<repoSlug>/learnings/\u3001projects/<repoSlug>/ch_*/learnings/\u3001projects/<repoSlug>/ch_*/t_*.md\u3001projects/<repoSlug>/ch_*/review/\u3001projects/<repoSlug>/reviews/<topic>-<ymd>/";
3
3
  /** 从需求名(回退 problem)派生 URL 安全 slug:ASCII 化、空格/特殊字符→-、限长 40;全非 ASCII(如中文)兜底 'req'。 */
4
4
  export declare function buildChecklistSlug(name: string): string;
5
5
  export declare function isAllowedWikiPagePath(pagePath: string): boolean;
6
- /** 三级 learnings 路径谓词:全局 / 项目级 / 需求级。 */
6
+ /** learnings 路径谓词:项目级 / 需求级(均在 repoSlug 下)。 */
7
7
  export declare function isLearningsPath(pagePath: string): boolean;
8
8
  /** 工具边界硬校验:不符白名单直接抛 kb-rejected(wiki_write 用)。 */
9
9
  export declare function assertAllowedWikiPagePath(pagePath: string): void;
10
+ export declare const LOCAL_CHECKLIST_PREFIX = "wiki/queries/checklists/";
11
+ export declare const LOCAL_LEARNING_BASE = "wiki/synthesis/learnings/";
12
+ /** 本地模式交付白名单:KB 库根下 wiki/** 相对路径(拒绝对象路径、.. 穿越、空串)。 */
13
+ export declare function isLocalKbPagePath(pagePath: string): boolean;
14
+ /** 本地模式工具边界硬校验:不符直接抛 kb-rejected。 */
15
+ export declare function assertLocalKbPagePath(pagePath: string): void;