@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,630 @@
1
+ import assert from "node:assert/strict";
2
+ import { createRequire } from "node:module";
3
+ import { pathToFileURL } from "node:url";
4
+
5
+ const require = createRequire(import.meta.url);
6
+ const { chromium } = require("playwright");
7
+
8
+ const html = process.env.GRAPH_DEFAULT_BEHAVIOR_HTML || "";
9
+ assert.notEqual(html, "", "GRAPH_DEFAULT_BEHAVIOR_HTML must point at generated HTML");
10
+
11
+ const executablePath = process.env.GRAPH_DEFAULT_BEHAVIOR_CHROME_EXECUTABLE || "";
12
+ const browser = await chromium.launch(executablePath ? { executablePath } : {});
13
+
14
+ try {
15
+ const page = await browser.newPage({ viewport: { width: 1440, height: 960 } });
16
+ await page.goto(pathToFileURL(html).href);
17
+ await page.waitForSelector("[data-llm-wiki-graph-root='true']");
18
+ await page.waitForSelector("[data-viewport-layer='true']");
19
+ await page.waitForSelector(".node");
20
+
21
+ await page.locator(".node").first().click();
22
+ await page.waitForSelector(".graph-reader-body");
23
+ const computedPolicy = await graphDefaultPolicy(page);
24
+ await page.locator(".graph-reader-close").click();
25
+ await page.waitForSelector('.graph-reader[data-state="closed"]');
26
+
27
+ assert.equal(computedPolicy.root.userSelect, "none", "graph root should prevent browser text selection");
28
+ assert.equal(computedPolicy.root.touchAction, "none", "graph root should own touch and pinch gestures");
29
+ assert.equal(computedPolicy.root.overscrollBehavior, "contain", "graph root should contain scroll chaining");
30
+ assert.equal(computedPolicy.readerBody.userSelect, "text", "reader body should still allow selecting text");
31
+ assert.equal(computedPolicy.searchInput.userSelect, "text", "search input should still allow text editing");
32
+
33
+ const nodeShortcutWheel = await assertShortcutWheelZoomsGraph(page, await visibleNodeCenter(page), "node", { ctrlKey: true });
34
+ const blankShortcutWheel = await assertShortcutWheelZoomsGraph(page, await findBlankPoint(page), "blank graph", { metaKey: true });
35
+ const searchWheel = await assertShortcutWheelDoesNotZoomGraph(page, ".graph-search-input", "search input", { ctrlKey: true });
36
+ const blankDrag = await assertBlankDragDoesNotSelectText(page);
37
+ const cancellationBoundaries = await assertCancellationAndBlockerBoundaries(page);
38
+ const fastReleaseDrag = await assertFastReleasePinsFinalPointerPosition(page);
39
+ const keyboardOwnership = await assertKeyboardOwnership(page);
40
+
41
+ console.log(JSON.stringify({
42
+ html,
43
+ computedPolicy,
44
+ shortcutWheel: {
45
+ node: nodeShortcutWheel,
46
+ blank: blankShortcutWheel,
47
+ searchInput: searchWheel
48
+ },
49
+ blankDrag,
50
+ cancellationBoundaries,
51
+ fastReleaseDrag,
52
+ keyboardOwnership
53
+ }, null, 2));
54
+ } finally {
55
+ await browser.close();
56
+ }
57
+
58
+ async function assertShortcutWheelZoomsGraph(page, point, label, options) {
59
+ await resetSelection(page);
60
+ const beforeMetrics = await pageMetrics(page);
61
+ const beforeTransform = await layerTransform(page);
62
+ const eventResult = await dispatchWheelAt(page, point, {
63
+ deltaY: -420,
64
+ ctrlKey: options.ctrlKey === true,
65
+ metaKey: options.metaKey === true
66
+ });
67
+ assert.equal(eventResult.cancelled, true, `shortcut wheel over ${label} should cancel browser default`);
68
+ const afterTransform = await waitForLayerTransform(page, beforeTransform);
69
+ const afterMetrics = await pageMetrics(page);
70
+ assert.deepEqual(afterMetrics, beforeMetrics, `shortcut wheel over ${label} should not zoom the page`);
71
+ const realWheel = await assertModifiedMouseWheelZoomsGraph(page, point, label, options);
72
+ return {
73
+ point: roundedPoint(point),
74
+ beforeTransform,
75
+ afterTransform,
76
+ beforeMetrics,
77
+ afterMetrics,
78
+ eventResult,
79
+ realWheel
80
+ };
81
+ }
82
+
83
+ async function assertModifiedMouseWheelZoomsGraph(page, point, label, options) {
84
+ const beforeMetrics = await pageMetrics(page);
85
+ const beforeTransform = await layerTransform(page);
86
+ const modifier = options.metaKey === true ? "Meta" : "Control";
87
+ const client = await page.context().newCDPSession(page);
88
+ try {
89
+ await client.send("Input.dispatchMouseEvent", {
90
+ type: "mouseWheel",
91
+ x: point.x,
92
+ y: point.y,
93
+ deltaX: 0,
94
+ deltaY: -420,
95
+ modifiers: options.metaKey === true ? 4 : 2
96
+ });
97
+ } finally {
98
+ await client.detach().catch(() => {});
99
+ }
100
+ const afterTransform = await waitForLayerTransform(page, beforeTransform);
101
+ const afterMetrics = await pageMetrics(page);
102
+ assert.deepEqual(afterMetrics, beforeMetrics, `real modified wheel over ${label} should not zoom the page`);
103
+ return {
104
+ modifier,
105
+ beforeTransform,
106
+ afterTransform,
107
+ beforeMetrics,
108
+ afterMetrics
109
+ };
110
+ }
111
+
112
+ async function assertShortcutWheelDoesNotZoomGraph(page, selector, label, options) {
113
+ const beforeMetrics = await pageMetrics(page);
114
+ const beforeTransform = await layerTransform(page);
115
+ const eventResult = await dispatchWheelOnSelector(page, selector, {
116
+ deltaY: -420,
117
+ ctrlKey: options.ctrlKey === true,
118
+ metaKey: options.metaKey === true
119
+ });
120
+ assert.equal(eventResult.cancelled, false, `shortcut wheel over ${label} should remain a blocker`);
121
+ await page.waitForTimeout(80);
122
+ const afterTransform = await layerTransform(page);
123
+ const afterMetrics = await pageMetrics(page);
124
+ assert.equal(afterTransform, beforeTransform, `shortcut wheel over ${label} should not zoom graph`);
125
+ assert.deepEqual(afterMetrics, beforeMetrics, `synthetic shortcut wheel over ${label} should not change page metrics`);
126
+ return {
127
+ beforeTransform,
128
+ afterTransform,
129
+ beforeMetrics,
130
+ afterMetrics,
131
+ eventResult
132
+ };
133
+ }
134
+
135
+ async function assertBlankDragDoesNotSelectText(page) {
136
+ await resetSelection(page);
137
+ const point = await findBlankPoint(page);
138
+ const toolbar = await page.locator(".graph-toolbar-actions").boundingBox();
139
+ assert.ok(toolbar, "toolbar actions should exist for blank drag selection regression");
140
+
141
+ await page.mouse.move(point.x, point.y);
142
+ await page.mouse.down();
143
+ await page.mouse.move(toolbar.x + toolbar.width - 4, toolbar.y + toolbar.height / 2, { steps: 8 });
144
+ await page.mouse.up();
145
+ await page.waitForTimeout(80);
146
+
147
+ const state = await page.evaluate(() => {
148
+ const root = document.querySelector("[data-llm-wiki-graph-root='true']");
149
+ return {
150
+ selectionText: window.getSelection()?.toString() || "",
151
+ viewportDragging: root?.dataset.viewportDragging || "",
152
+ dragging: root?.dataset.dragging || ""
153
+ };
154
+ });
155
+ assert.equal(state.selectionText, "", "blank graph drag should not select toolbar text");
156
+ assert.equal(state.viewportDragging, "", "blank graph drag should not leave viewport dragging active");
157
+ assert.equal(state.dragging, "", "blank graph drag should not leave node dragging active");
158
+ return { start: roundedPoint(point), state };
159
+ }
160
+
161
+ async function assertCancellationAndBlockerBoundaries(page) {
162
+ await page.reload();
163
+ await page.waitForSelector("[data-llm-wiki-graph-root='true']");
164
+ await page.waitForSelector("[data-viewport-layer='true']");
165
+ await page.waitForSelector(".node");
166
+
167
+ const pointerCancel = await assertPointerCancelClearsNodeDrag(page);
168
+ const lostPointerCapture = await assertLostPointerCaptureClearsBlankPan(page);
169
+ const blockers = await assertPointerBlockersDoNotStartGestures(page);
170
+
171
+ return {
172
+ pointerCancel,
173
+ lostPointerCapture,
174
+ blockers
175
+ };
176
+ }
177
+
178
+ async function assertPointerCancelClearsNodeDrag(page) {
179
+ const before = await page.locator(".node").first().evaluate((node) => {
180
+ const rect = node.getBoundingClientRect();
181
+ return {
182
+ id: node.dataset.id || "",
183
+ pinned: node.dataset.pinned || "",
184
+ center: { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 }
185
+ };
186
+ });
187
+ assert.notEqual(before.id, "", "pointercancel regression should have a node target");
188
+
189
+ const move = { x: before.center.x + 80, y: before.center.y + 8 };
190
+ await dispatchPointer(page, `.node[data-id="${cssString(before.id)}"]`, "pointerdown", before.center, {
191
+ pointerId: 88,
192
+ button: 0,
193
+ buttons: 1
194
+ });
195
+ await dispatchPointer(page, "[data-llm-wiki-graph-root='true']", "pointermove", move, {
196
+ pointerId: 88,
197
+ button: 0,
198
+ buttons: 1
199
+ });
200
+ await page.waitForFunction(
201
+ (id) => {
202
+ const root = document.querySelector("[data-llm-wiki-graph-root='true']");
203
+ const node = document.querySelector(`.node[data-id="${CSS.escape(id)}"]`);
204
+ return root?.dataset.dragging === id && node?.classList.contains("is-dragging");
205
+ },
206
+ before.id,
207
+ { timeout: 3000 }
208
+ );
209
+
210
+ const cancelEvent = await dispatchPointer(page, "[data-llm-wiki-graph-root='true']", "pointercancel", move, {
211
+ pointerId: 88,
212
+ button: 0,
213
+ buttons: 0
214
+ });
215
+ await waitForClearInteraction(page, before.id);
216
+
217
+ const after = await graphInteractionState(page, before.id);
218
+ assert.equal(cancelEvent.cancelled, true, "pointercancel during node drag should prevent browser default");
219
+ assert.equal(after.dragging, "", "pointercancel should clear root dragging state");
220
+ assert.equal(after.nodeDragging, false, "pointercancel should clear node dragging class");
221
+ assert.equal(after.pinned, before.pinned, "pointercancel should not create or remove a node pin");
222
+
223
+ return {
224
+ id: before.id,
225
+ move: roundedPoint(move),
226
+ cancelEvent,
227
+ beforePinned: before.pinned,
228
+ after
229
+ };
230
+ }
231
+
232
+ async function assertLostPointerCaptureClearsBlankPan(page) {
233
+ const start = await findBlankPoint(page);
234
+ const move = { x: start.x + 96, y: start.y + 12 };
235
+
236
+ await dispatchPointer(page, "[data-llm-wiki-graph-root='true']", "pointerdown", start, {
237
+ pointerId: 89,
238
+ button: 0,
239
+ buttons: 1
240
+ });
241
+ await dispatchPointer(page, "[data-llm-wiki-graph-root='true']", "pointermove", move, {
242
+ pointerId: 89,
243
+ button: 0,
244
+ buttons: 1
245
+ });
246
+ await page.waitForFunction(
247
+ () => document.querySelector("[data-llm-wiki-graph-root='true']")?.dataset.viewportDragging === "true",
248
+ undefined,
249
+ { timeout: 3000 }
250
+ );
251
+
252
+ const lostEvent = await dispatchPointer(page, "[data-llm-wiki-graph-root='true']", "lostpointercapture", move, {
253
+ pointerId: 89,
254
+ button: 0,
255
+ buttons: 0
256
+ });
257
+ await page.waitForFunction(
258
+ () => (document.querySelector("[data-llm-wiki-graph-root='true']")?.dataset.viewportDragging || "") === "",
259
+ undefined,
260
+ { timeout: 3000 }
261
+ );
262
+
263
+ const state = await graphInteractionState(page);
264
+ assert.equal(state.viewportDragging, "", "lostpointercapture should clear viewport dragging state");
265
+ assert.equal(state.dragging, "", "lostpointercapture should not leave node dragging state");
266
+
267
+ return {
268
+ start: roundedPoint(start),
269
+ move: roundedPoint(move),
270
+ lostEvent,
271
+ state
272
+ };
273
+ }
274
+
275
+ async function assertPointerBlockersDoNotStartGestures(page) {
276
+ await page.locator(".node").first().click();
277
+ await page.waitForSelector('.graph-reader[data-state="open"]');
278
+
279
+ const cases = [
280
+ [".graph-search-input", "search input"],
281
+ [".graph-toolbar", "toolbar"],
282
+ [".mini-map", "minimap"],
283
+ [".graph-reader-body", "reader drawer"]
284
+ ];
285
+ const results = [];
286
+ for (let index = 0; index < cases.length; index += 1) {
287
+ const [selector, label] = cases[index];
288
+ const beforeTransform = await layerTransform(page);
289
+ const eventResult = await dispatchPointerOnSelector(page, selector, "pointerdown", {
290
+ pointerId: 100 + index,
291
+ button: 0,
292
+ buttons: 1
293
+ });
294
+ await page.waitForTimeout(60);
295
+ const state = await graphInteractionState(page);
296
+ const afterTransform = await layerTransform(page);
297
+
298
+ assert.equal(eventResult.cancelled, false, `${label} pointerdown should remain outside graph gesture ownership`);
299
+ assert.equal(state.dragging, "", `${label} pointerdown should not start node dragging`);
300
+ assert.equal(state.viewportDragging, "", `${label} pointerdown should not start blank panning`);
301
+ assert.equal(afterTransform, beforeTransform, `${label} pointerdown should not move the graph`);
302
+ results.push({ selector, label, eventResult, state });
303
+ }
304
+
305
+ await page.locator(".graph-reader-close").click();
306
+ await page.waitForSelector('.graph-reader[data-state="closed"]');
307
+ return results;
308
+ }
309
+
310
+ async function assertFastReleasePinsFinalPointerPosition(page) {
311
+ await page.reload();
312
+ await page.waitForSelector("[data-llm-wiki-graph-root='true']");
313
+ await page.waitForSelector("[data-viewport-layer='true']");
314
+ await page.waitForSelector(".node");
315
+
316
+ const before = await page.locator(".node").first().evaluate((node) => {
317
+ const rect = node.getBoundingClientRect();
318
+ return {
319
+ id: node.dataset.id || "",
320
+ center: { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 },
321
+ pinned: node.dataset.pinned || ""
322
+ };
323
+ });
324
+ assert.notEqual(before.id, "", "fast-release drag should have a node target");
325
+
326
+ const intermediate = { x: before.center.x + 18, y: before.center.y + 4 };
327
+ const release = { x: before.center.x + 280, y: before.center.y + 12 };
328
+ await dispatchPointer(page, `.node[data-id="${cssString(before.id)}"]`, "pointerdown", before.center, {
329
+ pointerId: 77,
330
+ button: 0,
331
+ buttons: 1
332
+ });
333
+ await dispatchPointer(page, "[data-llm-wiki-graph-root='true']", "pointermove", intermediate, {
334
+ pointerId: 77,
335
+ button: 0,
336
+ buttons: 1
337
+ });
338
+ await dispatchPointer(page, "[data-llm-wiki-graph-root='true']", "pointerup", release, {
339
+ pointerId: 77,
340
+ button: 0,
341
+ buttons: 0
342
+ });
343
+
344
+ await page.waitForSelector(`.node[data-id="${cssString(before.id)}"][data-pinned="true"]`);
345
+ await page.waitForTimeout(120);
346
+
347
+ const after = await page.locator(`.node[data-id="${cssString(before.id)}"]`).evaluate((node) => {
348
+ const rect = node.getBoundingClientRect();
349
+ return {
350
+ center: { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 },
351
+ pinned: node.dataset.pinned || ""
352
+ };
353
+ });
354
+ assert.ok(
355
+ after.center.x > before.center.x + 190,
356
+ `fast-release drag should commit close to the release point, not the last move point: ${JSON.stringify({ before, intermediate, release, after })}`
357
+ );
358
+ assert.equal(after.pinned, "true", "fast-release drag should still pin the node");
359
+ return {
360
+ id: before.id,
361
+ before: roundedPoint(before.center),
362
+ intermediate: roundedPoint(intermediate),
363
+ release: roundedPoint(release),
364
+ after: roundedPoint(after.center),
365
+ pinned: after.pinned
366
+ };
367
+ }
368
+
369
+ async function assertKeyboardOwnership(page) {
370
+ await page.reload();
371
+ await page.waitForSelector("[data-llm-wiki-graph-root='true']");
372
+ await page.waitForSelector(".graph-search");
373
+
374
+ await page.evaluate(() => {
375
+ if (document.activeElement instanceof HTMLElement) document.activeElement.blur();
376
+ document.body.focus();
377
+ });
378
+ const outsideGraph = await dispatchDocumentKey(page, "f", { ctrlKey: true });
379
+ await page.waitForTimeout(80);
380
+ assert.equal(outsideGraph.defaultPrevented, false, "graph should not steal search shortcut outside graph focus");
381
+ assert.equal(await graphSearchState(page), "closed", "search shortcut outside graph focus should not open graph search");
382
+
383
+ await page.locator("[data-llm-wiki-graph-root='true']").evaluate((root) => root.focus({ preventScroll: true }));
384
+ const insideGraph = await dispatchDocumentKey(page, "f", { ctrlKey: true });
385
+ await page.waitForSelector('.graph-search[data-state="open"]');
386
+ assert.equal(insideGraph.defaultPrevented, true, "graph should own search shortcut when graph is focused");
387
+
388
+ await page.evaluate(() => {
389
+ if (document.activeElement instanceof HTMLElement) document.activeElement.blur();
390
+ document.body.focus();
391
+ });
392
+ const outsideEscape = await dispatchDocumentKey(page, "Escape");
393
+ await page.waitForTimeout(80);
394
+ assert.equal(outsideEscape.defaultPrevented, false, "graph should not steal Escape outside graph focus");
395
+ assert.equal(await graphSearchState(page), "open", "Escape outside graph focus should not close graph search");
396
+
397
+ return {
398
+ outsideGraph,
399
+ insideGraph,
400
+ outsideEscape,
401
+ finalSearchState: await graphSearchState(page)
402
+ };
403
+ }
404
+
405
+ async function layerTransform(page) {
406
+ return page.locator("[data-viewport-layer='true']").evaluate((element) => element.style.transform);
407
+ }
408
+
409
+ async function waitForLayerTransform(page, previous) {
410
+ await page.waitForFunction(
411
+ (previous) => document.querySelector("[data-viewport-layer='true']")?.style.transform !== previous,
412
+ previous,
413
+ { timeout: 3000 }
414
+ );
415
+ return layerTransform(page);
416
+ }
417
+
418
+ async function pageMetrics(page) {
419
+ return page.evaluate(() => ({
420
+ devicePixelRatio: window.devicePixelRatio,
421
+ visualViewportScale: window.visualViewport?.scale || 1,
422
+ clientWidth: document.documentElement.clientWidth,
423
+ clientHeight: document.documentElement.clientHeight
424
+ }));
425
+ }
426
+
427
+ async function graphDefaultPolicy(page) {
428
+ return page.evaluate(() => {
429
+ const root = document.querySelector(".llm-wiki-graph-engine");
430
+ const readerBody = document.querySelector(".graph-reader-body");
431
+ const searchInput = document.querySelector(".graph-search-input");
432
+ if (!root || !readerBody || !searchInput) throw new Error("Missing graph policy elements");
433
+ const styleOf = (element) => {
434
+ const style = getComputedStyle(element);
435
+ return {
436
+ userSelect: style.userSelect,
437
+ touchAction: style.touchAction,
438
+ overscrollBehavior: style.overscrollBehavior
439
+ };
440
+ };
441
+ return {
442
+ root: styleOf(root),
443
+ readerBody: styleOf(readerBody),
444
+ searchInput: styleOf(searchInput)
445
+ };
446
+ });
447
+ }
448
+
449
+ async function visibleNodeCenter(page) {
450
+ return page.locator(".node").first().evaluate((node) => {
451
+ const rect = node.getBoundingClientRect();
452
+ return { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };
453
+ });
454
+ }
455
+
456
+ async function findBlankPoint(page) {
457
+ return page.evaluate(() => {
458
+ const root = document.querySelector("[data-llm-wiki-graph-root='true']");
459
+ if (!root) throw new Error("Missing graph root");
460
+ const rootRect = root.getBoundingClientRect();
461
+ const blocked = ".node,.community-wash,.edge,.graph-toolbar,.mini-map,.graph-search,.graph-reader,.graph-selection-panel";
462
+ for (let y = rootRect.top + 86; y < rootRect.bottom - 48; y += 34) {
463
+ for (let x = rootRect.left + 40; x < rootRect.right - 40; x += 42) {
464
+ const element = document.elementFromPoint(x, y);
465
+ if (element && root.contains(element) && !element.closest(blocked)) return { x, y };
466
+ }
467
+ }
468
+ throw new Error("Could not find blank graph point");
469
+ });
470
+ }
471
+
472
+ async function dispatchWheelAt(page, point, options) {
473
+ return page.evaluate(({ point, options }) => {
474
+ const target = document.elementFromPoint(point.x, point.y);
475
+ if (!target) throw new Error(`No event target at ${JSON.stringify(point)}`);
476
+ const event = new WheelEvent("wheel", {
477
+ bubbles: true,
478
+ cancelable: true,
479
+ clientX: point.x,
480
+ clientY: point.y,
481
+ deltaY: options.deltaY,
482
+ deltaMode: 0,
483
+ ctrlKey: options.ctrlKey,
484
+ metaKey: options.metaKey
485
+ });
486
+ const dispatchResult = target.dispatchEvent(event);
487
+ return {
488
+ cancelled: !dispatchResult,
489
+ defaultPrevented: event.defaultPrevented,
490
+ target: target.closest(".node") ? "node" : target.closest(".community-wash") ? "community-wash" : target.className?.toString?.() || target.tagName
491
+ };
492
+ }, { point, options });
493
+ }
494
+
495
+ async function dispatchWheelOnSelector(page, selector, options) {
496
+ return page.evaluate(({ selector, options }) => {
497
+ const target = document.querySelector(selector);
498
+ if (!target) throw new Error(`Missing selector ${selector}`);
499
+ const rect = target.getBoundingClientRect();
500
+ const event = new WheelEvent("wheel", {
501
+ bubbles: true,
502
+ cancelable: true,
503
+ clientX: rect.left + rect.width / 2,
504
+ clientY: rect.top + rect.height / 2,
505
+ deltaY: options.deltaY,
506
+ deltaMode: 0,
507
+ ctrlKey: options.ctrlKey,
508
+ metaKey: options.metaKey
509
+ });
510
+ const dispatchResult = target.dispatchEvent(event);
511
+ return {
512
+ cancelled: !dispatchResult,
513
+ defaultPrevented: event.defaultPrevented,
514
+ target: selector
515
+ };
516
+ }, { selector, options });
517
+ }
518
+
519
+ async function dispatchPointer(page, selector, type, point, options) {
520
+ return page.evaluate(({ selector, type, point, options }) => {
521
+ const target = document.querySelector(selector);
522
+ if (!target) throw new Error(`Missing selector ${selector}`);
523
+ const event = new PointerEvent(type, {
524
+ bubbles: true,
525
+ cancelable: true,
526
+ pointerId: options.pointerId,
527
+ pointerType: "mouse",
528
+ clientX: point.x,
529
+ clientY: point.y,
530
+ button: options.button,
531
+ buttons: options.buttons,
532
+ isPrimary: true
533
+ });
534
+ const dispatchResult = target.dispatchEvent(event);
535
+ return {
536
+ cancelled: !dispatchResult,
537
+ defaultPrevented: event.defaultPrevented
538
+ };
539
+ }, { selector, type, point, options });
540
+ }
541
+
542
+ async function dispatchDocumentKey(page, key, options = {}) {
543
+ return page.evaluate(({ key, options }) => {
544
+ const event = new KeyboardEvent("keydown", {
545
+ key,
546
+ bubbles: true,
547
+ cancelable: true,
548
+ ctrlKey: options.ctrlKey === true,
549
+ metaKey: options.metaKey === true
550
+ });
551
+ const dispatchResult = document.dispatchEvent(event);
552
+ return {
553
+ cancelled: !dispatchResult,
554
+ defaultPrevented: event.defaultPrevented,
555
+ activeTag: document.activeElement?.tagName || ""
556
+ };
557
+ }, { key, options });
558
+ }
559
+
560
+ async function graphSearchState(page) {
561
+ return page.locator(".graph-search").evaluate((element) => element.dataset.state || "");
562
+ }
563
+
564
+ async function graphInteractionState(page, nodeId = "") {
565
+ return page.evaluate((nodeId) => {
566
+ const root = document.querySelector("[data-llm-wiki-graph-root='true']");
567
+ const node = nodeId ? document.querySelector(`.node[data-id="${CSS.escape(nodeId)}"]`) : null;
568
+ return {
569
+ dragging: root?.dataset.dragging || "",
570
+ viewportDragging: root?.dataset.viewportDragging || "",
571
+ pinned: node?.dataset.pinned || "",
572
+ nodeDragging: Boolean(node?.classList.contains("is-dragging"))
573
+ };
574
+ }, nodeId);
575
+ }
576
+
577
+ async function waitForClearInteraction(page, nodeId = "") {
578
+ await page.waitForFunction(
579
+ (nodeId) => {
580
+ const root = document.querySelector("[data-llm-wiki-graph-root='true']");
581
+ const node = nodeId ? document.querySelector(`.node[data-id="${CSS.escape(nodeId)}"]`) : null;
582
+ return (root?.dataset.dragging || "") === ""
583
+ && (root?.dataset.viewportDragging || "") === ""
584
+ && !node?.classList.contains("is-dragging");
585
+ },
586
+ nodeId,
587
+ { timeout: 3000 }
588
+ );
589
+ }
590
+
591
+ async function resetSelection(page) {
592
+ await page.evaluate(() => window.getSelection()?.removeAllRanges());
593
+ }
594
+
595
+ function roundedPoint(point) {
596
+ return {
597
+ x: Math.round(point.x * 1000) / 1000,
598
+ y: Math.round(point.y * 1000) / 1000
599
+ };
600
+ }
601
+
602
+ function cssString(value) {
603
+ return String(value).replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
604
+ }
605
+
606
+ async function dispatchPointerOnSelector(page, selector, type, options) {
607
+ return page.evaluate(({ selector, type, options }) => {
608
+ const target = document.querySelector(selector);
609
+ if (!target) throw new Error(`Missing selector ${selector}`);
610
+ const rect = target.getBoundingClientRect();
611
+ const point = { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };
612
+ const event = new PointerEvent(type, {
613
+ bubbles: true,
614
+ cancelable: true,
615
+ pointerId: options.pointerId,
616
+ pointerType: "mouse",
617
+ clientX: point.x,
618
+ clientY: point.y,
619
+ button: options.button,
620
+ buttons: options.buttons,
621
+ isPrimary: true
622
+ });
623
+ const dispatchResult = target.dispatchEvent(event);
624
+ return {
625
+ cancelled: !dispatchResult,
626
+ defaultPrevented: event.defaultPrevented,
627
+ point
628
+ };
629
+ }, { selector, type, options });
630
+ }
@@ -0,0 +1,53 @@
1
+ import assert from "node:assert/strict";
2
+ import { createRequire } from "node:module";
3
+ import { pathToFileURL } from "node:url";
4
+
5
+ const require = createRequire(import.meta.url);
6
+ const { chromium } = require("playwright");
7
+
8
+ const html = process.env.GRAPH_DENSITY_PREVIEW_HTML || "";
9
+ assert.notEqual(html, "", "GRAPH_DENSITY_PREVIEW_HTML must point at generated HTML");
10
+
11
+ const browser = await chromium.launch();
12
+ try {
13
+ const page = await browser.newPage({ viewport: { width: 1440, height: 960 } });
14
+ await page.goto(pathToFileURL(html).href);
15
+ await page.waitForSelector("[data-llm-wiki-graph-root='true']");
16
+
17
+ const root = page.locator("[data-llm-wiki-graph-root='true']");
18
+ const totalNodes = await page.locator(".node").count();
19
+ const fullCards = await page.locator(".node:not(.is-compact):not(.is-point):not(.is-overview)").count();
20
+ assert.ok(totalNodes >= 120, `dense fixture should render many nodes, got ${totalNodes}`);
21
+ assert.ok(fullCards < totalNodes / 2, "dense fixture should not render every node as a full card");
22
+
23
+ const compact = page.locator(".node.is-compact").first();
24
+ await compact.waitFor();
25
+ await compact.hover();
26
+ await assertPreviewOpen(page, "compact node should open hover preview");
27
+
28
+ await page.mouse.move(20, 20);
29
+ await waitForPreviewState(page, "closed");
30
+
31
+ await page.waitForSelector(".node.is-point");
32
+ const point = page.locator(".node.is-point").first();
33
+ await point.evaluate((element) => {
34
+ element.dispatchEvent(new PointerEvent("pointerenter", { bubbles: true, pointerType: "mouse" }));
35
+ });
36
+ await assertPreviewOpen(page, "point node should open hover preview");
37
+ } finally {
38
+ await browser.close();
39
+ }
40
+
41
+ async function assertPreviewOpen(page, message) {
42
+ await page.waitForSelector(".graph-hover-preview[data-state='open']");
43
+ const preview = page.locator(".graph-hover-preview");
44
+ await preview.locator(".graph-hover-preview-title").waitFor();
45
+ await preview.locator(".graph-hover-preview-type").waitFor();
46
+ assert.equal(await preview.locator(".graph-hover-preview-summary").count(), 1, message);
47
+ }
48
+
49
+ async function waitForPreviewState(page, state) {
50
+ await page.waitForFunction((state) => {
51
+ return document.querySelector(".graph-hover-preview")?.dataset.state === state;
52
+ }, state);
53
+ }