@xiaobuyu/nodesign 0.0.1 → 0.0.3

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 (358) hide show
  1. package/README.md +156 -106
  2. package/bin/nodesign.js +0 -0
  3. package/package.json +1 -1
  4. package/server/api/README.md +45 -45
  5. package/server/api/_guard.js +75 -75
  6. package/server/api/admin.js +187 -187
  7. package/server/api/assets/docx-page.js +103 -103
  8. package/server/api/assets/helpers.js +42 -22
  9. package/server/api/assets/notes.js +194 -144
  10. package/server/api/assets.js +891 -896
  11. package/server/api/board.js +134 -57
  12. package/server/api/browse.js +138 -138
  13. package/server/api/canvas.js +444 -444
  14. package/server/api/chatai.js +324 -324
  15. package/server/api/exports/build-standalone.js +980 -980
  16. package/server/api/exports/cards.js +118 -118
  17. package/server/api/exports/docx-pdf.js +46 -46
  18. package/server/api/exports/export-page.js +142 -142
  19. package/server/api/exports/handoff.js +147 -147
  20. package/server/api/exports.js +690 -690
  21. package/server/api/instruction.js +75 -75
  22. package/server/api/me.js +116 -116
  23. package/server/api/memory.js +185 -185
  24. package/server/api/pending-changes.js +366 -366
  25. package/server/api/plugins.js +164 -164
  26. package/server/api/projects.js +220 -220
  27. package/server/api/publish.js +64 -64
  28. package/server/api/recent.js +73 -73
  29. package/server/api/sessions.js +589 -589
  30. package/server/api/skills.js +77 -77
  31. package/server/api/standalone-fit.js +168 -168
  32. package/server/api/turn-compose.js +180 -180
  33. package/server/api/turn-inflight.js +44 -44
  34. package/server/auth/README.md +17 -17
  35. package/server/auth/middleware.js +138 -138
  36. package/server/auth/origin-guard.js +71 -71
  37. package/server/auth/session.js +108 -108
  38. package/server/auth/tier.js +113 -113
  39. package/server/auth/users-store.js +348 -348
  40. package/server/edit/README.md +29 -29
  41. package/server/engine/README.md +113 -113
  42. package/server/engine/agent/agent-shared.js +550 -550
  43. package/server/engine/agent/auto-mode-default-hard-deny.txt +4 -4
  44. package/server/engine/agent/auto-mode-rules.js +78 -78
  45. package/server/engine/agent/context.js +418 -418
  46. package/server/engine/agent/events.js +465 -464
  47. package/server/engine/agent/hooks/canvas-validate.js +199 -199
  48. package/server/engine/agent/hooks/failure.js +120 -120
  49. package/server/engine/agent/hooks/file-events.js +75 -75
  50. package/server/engine/agent/hooks/lifecycle.js +233 -233
  51. package/server/engine/agent/hooks/post-canvas-focus.js +80 -80
  52. package/server/engine/agent/hooks/post-guidance.js +206 -206
  53. package/server/engine/agent/hooks/post-subagent-report.js +104 -104
  54. package/server/engine/agent/hooks/post-trim.js +58 -58
  55. package/server/engine/agent/hooks/pre-board-neighborhood.js +34 -34
  56. package/server/engine/agent/hooks/pre-defaults.js +84 -84
  57. package/server/engine/agent/hooks/pre-injectors.js +277 -277
  58. package/server/engine/agent/hooks/pre-performance-log-guard.js +78 -78
  59. package/server/engine/agent/hooks/pre-starter-files.js +61 -61
  60. package/server/engine/agent/hooks/pre-workspace-scope-guard.js +78 -78
  61. package/server/engine/agent/hooks/site-validate.js +94 -94
  62. package/server/engine/agent/hooks/tool-prompts.js +31 -31
  63. package/server/engine/agent/hooks/turn-state-memory.js +56 -56
  64. package/server/engine/agent/hooks/user-prompt-submit.js +258 -215
  65. package/server/engine/agent/hooks.js +354 -354
  66. package/server/engine/agent/init-contract.js +69 -69
  67. package/server/engine/agent/isolation.js +159 -159
  68. package/server/engine/agent/model-table.js +292 -292
  69. package/server/engine/agent/plugin-loader.js +266 -266
  70. package/server/engine/agent/prompts/nodesign-prelude.md +388 -336
  71. package/server/engine/agent/prompts/tools/ask-user-question-protocol.md +71 -71
  72. package/server/engine/agent/prompts/tools/direct-edit-protocol.md +98 -98
  73. package/server/engine/agent/prompts/tools/generate-image-cookbook.gemini-gateway.md +583 -583
  74. package/server/engine/agent/prompts/tools/generate-image-cookbook.md +483 -483
  75. package/server/engine/agent/prompts/tools/hybrid-reference.md +100 -100
  76. package/server/engine/agent/prompts/tools/paint-still-cookbook.md +270 -270
  77. package/server/engine/agent/prompts/tools/roll-film-cookbook.md +70 -70
  78. package/server/engine/agent/prompts/tools/site-reference.md +106 -106
  79. package/server/engine/agent/prompts/tools/tweaks-syntax.md +125 -125
  80. package/server/engine/agent/prompts/tools/vision-checker-dispatch.md +48 -48
  81. package/server/engine/agent/session-loop.js +1035 -1024
  82. package/server/engine/agent/session-model.js +164 -164
  83. package/server/engine/agent/skill.js +204 -204
  84. package/server/engine/agent/task-events.js +78 -78
  85. package/server/engine/agents/ds-extractor.md +132 -132
  86. package/server/engine/agents/explorer.md +190 -190
  87. package/server/engine/agents/index.js +230 -230
  88. package/server/engine/agents/schemas/design-system.json +156 -156
  89. package/server/engine/agents/schemas/tweak-schema.json +113 -113
  90. package/server/engine/agents/tweak-proposer.md +127 -127
  91. package/server/engine/agents/vision-checker.md +254 -254
  92. package/server/engine/browse/capture.js +422 -422
  93. package/server/engine/browse/card.js +137 -137
  94. package/server/engine/browse/handover.js +59 -59
  95. package/server/engine/browse/page-digest.js +119 -119
  96. package/server/engine/browse/refs.js +196 -196
  97. package/server/engine/browse/registry.js +307 -307
  98. package/server/engine/browse/screencast.js +170 -170
  99. package/server/engine/browse/state.js +121 -121
  100. package/server/engine/chatai/chat-log.js +79 -79
  101. package/server/engine/chatai/index.js +193 -193
  102. package/server/engine/chatai/openai-compat.js +152 -152
  103. package/server/engine/chatai/orchestrate.js +309 -309
  104. package/server/engine/chatai/perform.js +40 -40
  105. package/server/engine/chatai/summarize.js +79 -79
  106. package/server/engine/mcp/capability-gate.js +52 -52
  107. package/server/engine/mcp/index.js +351 -339
  108. package/server/engine/mcp/param-sanitizer.js +142 -142
  109. package/server/engine/mcp/tools/arrange-on-board.js +124 -124
  110. package/server/engine/mcp/tools/artifact-session.js +278 -278
  111. package/server/engine/mcp/tools/browse-computer.js +421 -421
  112. package/server/engine/mcp/tools/browse-find-batch.js +183 -183
  113. package/server/engine/mcp/tools/browse-screenshot.js +157 -157
  114. package/server/engine/mcp/tools/browse.js +480 -480
  115. package/server/engine/mcp/tools/build-docx.js +101 -101
  116. package/server/engine/mcp/tools/clear-pending-changes.js +99 -99
  117. package/server/engine/mcp/tools/create-on-board.js +152 -155
  118. package/server/engine/mcp/tools/crystallize-skill.js +168 -168
  119. package/server/engine/mcp/tools/edit-sketch.js +167 -0
  120. package/server/engine/mcp/tools/explain-style.js +237 -237
  121. package/server/engine/mcp/tools/export-handoff.js +133 -133
  122. package/server/engine/mcp/tools/expose-tweaks.js +149 -149
  123. package/server/engine/mcp/tools/generate-image.js +842 -842
  124. package/server/engine/mcp/tools/get-computed-styles.js +164 -164
  125. package/server/engine/mcp/tools/get-pending-changes.js +205 -205
  126. package/server/engine/mcp/tools/h3box-ssh.js +84 -84
  127. package/server/engine/mcp/tools/helpers/acquire-page.js +82 -82
  128. package/server/engine/mcp/tools/helpers/motion-lab.js +554 -554
  129. package/server/engine/mcp/tools/helpers/motion-scroll.js +112 -112
  130. package/server/engine/mcp/tools/helpers/perception-page.js +215 -215
  131. package/server/engine/mcp/tools/helpers/reference-download.js +103 -103
  132. package/server/engine/mcp/tools/helpers/rembg-bridge.py +80 -80
  133. package/server/engine/mcp/tools/helpers/shot-pipeline.js +280 -280
  134. package/server/engine/mcp/tools/highlight.js +68 -68
  135. package/server/engine/mcp/tools/list-pages.js +222 -222
  136. package/server/engine/mcp/tools/look-at-board.js +124 -0
  137. package/server/engine/mcp/tools/lookup-tags.js +59 -59
  138. package/server/engine/mcp/tools/navigate-to-page.js +60 -60
  139. package/server/engine/mcp/tools/organize-board.js +64 -64
  140. package/server/engine/mcp/tools/paint-still.js +434 -434
  141. package/server/engine/mcp/tools/pin-to-board.js +130 -130
  142. package/server/engine/mcp/tools/preview-deck.js +130 -130
  143. package/server/engine/mcp/tools/profile-scroll.js +305 -305
  144. package/server/engine/mcp/tools/publish-site.js +102 -102
  145. package/server/engine/mcp/tools/query-elements.js +195 -195
  146. package/server/engine/mcp/tools/read-board.js +190 -103
  147. package/server/engine/mcp/tools/read-document.js +93 -93
  148. package/server/engine/mcp/tools/read-page.js +264 -264
  149. package/server/engine/mcp/tools/read-tavern-json.js +143 -143
  150. package/server/engine/mcp/tools/read-user-view.js +59 -0
  151. package/server/engine/mcp/tools/record-decision.js +140 -140
  152. package/server/engine/mcp/tools/relate-on-board.js +112 -110
  153. package/server/engine/mcp/tools/report-issue.js +115 -115
  154. package/server/engine/mcp/tools/roll-film.js +266 -266
  155. package/server/engine/mcp/tools/screenshot-docx.js +138 -138
  156. package/server/engine/mcp/tools/screenshot-url.js +195 -195
  157. package/server/engine/mcp/tools/screenshot.js +583 -583
  158. package/server/engine/mcp/tools/sketch-on-board.js +337 -0
  159. package/server/engine/mcp/tools/tier-gate.js +96 -96
  160. package/server/engine/mcp/tools/trace-motion.js +215 -215
  161. package/server/engine/mcp/tools/web-search.js +548 -548
  162. package/server/engine/mcp/tools/write-on-board.js +130 -0
  163. package/server/engine/motion/inventory.js +349 -349
  164. package/server/engine/perception/session.js +235 -235
  165. package/server/engine/plugins/nodesign/.claude-plugin/plugin.json +5 -5
  166. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/SKILL.md +199 -192
  167. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/canvas.template.html +667 -667
  168. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/hybrid-grid.md +22 -22
  169. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/image-led-cover.md +25 -25
  170. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/portrait.md +23 -23
  171. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/quote-backdrop.md +21 -21
  172. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/section-divider.md +23 -23
  173. package/server/engine/plugins/nodesign/skills/deskskill-engine-mini/patterns/text-led.md +21 -21
  174. package/server/engine/plugins/nodesign/skills/docx-craft/SKILL.md +169 -162
  175. package/server/engine/plugins/nodesign/skills/docx-craft/references/token-schema.md +407 -407
  176. package/server/engine/plugins/nodesign/skills/docx-craft//346/226/207/346/241/243.template.json +80 -80
  177. package/server/engine/plugins/nodesign/skills/rp-craft/SKILL.md +235 -228
  178. package/server/engine/plugins/nodesign/skills/rp-craft/patterns//346/274/224/345/207/272/351/241/265-/346/234/200/345/260/217/345/256/236/347/216/260.html +78 -78
  179. package/server/engine/plugins/nodesign/skills/rp-craft//346/274/224/345/207/272.template.js +268 -268
  180. package/server/engine/plugins/nodesign/skills/site-craft/SKILL.md +330 -323
  181. package/server/engine/plugins/nodesign/skills/site-craft/patterns/build-lane.md +134 -134
  182. package/server/engine/plugins/nodesign/skills/site-craft/patterns/cutout-collage.md +61 -61
  183. package/server/engine/plugins/nodesign/skills/site-craft/patterns/mock-app.md +163 -163
  184. package/server/engine/plugins/nodesign/skills/site-craft/patterns/page-transitions.md +86 -86
  185. package/server/engine/runs/active-runs.js +698 -698
  186. package/server/engine/runs/board-tasklist.js +130 -0
  187. package/server/engine/runs/live-turn.js +252 -252
  188. package/server/engine/runs/store.js +364 -364
  189. package/server/engine/runs/turn-relay.js +217 -217
  190. package/server/engine/runtime/workspace.js +164 -164
  191. package/server/index.js +3 -0
  192. package/server/lib/artifact-file-path.js +80 -80
  193. package/server/lib/artifact-target.js +284 -284
  194. package/server/lib/asset-refs.js +239 -239
  195. package/server/lib/async-queue.js +104 -104
  196. package/server/lib/auto-relations.js +130 -130
  197. package/server/lib/binding-types.js +72 -60
  198. package/server/lib/board-graph-export.js +191 -0
  199. package/server/lib/board-groups.js +167 -0
  200. package/server/lib/board-hero.js +76 -0
  201. package/server/lib/board-kind-sizes.js +85 -62
  202. package/server/lib/board-relations.js +133 -133
  203. package/server/lib/browse-proxy.js +180 -180
  204. package/server/lib/canvas-id.js +36 -36
  205. package/server/lib/chalk.js +121 -0
  206. package/server/lib/cover.js +227 -227
  207. package/server/lib/danbooru-tags.js +291 -291
  208. package/server/lib/doc-extract.js +156 -156
  209. package/server/lib/docx/build-from-source.js +260 -260
  210. package/server/lib/docx/build.js +490 -490
  211. package/server/lib/docx/dump-styles.js +287 -287
  212. package/server/lib/docx/fonts/nodesign-cjk.conf +164 -164
  213. package/server/lib/docx/merge-runs.js +129 -129
  214. package/server/lib/docx/numbering.js +218 -218
  215. package/server/lib/docx/order.js +152 -152
  216. package/server/lib/docx/rawzip.js +172 -172
  217. package/server/lib/docx/render.js +92 -92
  218. package/server/lib/docx/text-lint.js +225 -225
  219. package/server/lib/docx/tokens.js +335 -335
  220. package/server/lib/docx/units.js +29 -29
  221. package/server/lib/docx/xml.js +291 -291
  222. package/server/lib/docx-pages.js +187 -187
  223. package/server/lib/export-collect.js +289 -289
  224. package/server/lib/export-package.js +210 -210
  225. package/server/lib/html-srcset.js +145 -145
  226. package/server/lib/image-variant.js +460 -460
  227. package/server/lib/ingress/forward-openai-chat.js +305 -305
  228. package/server/lib/ingress/openai-chat.js +491 -491
  229. package/server/lib/ingress/session-notice.js +66 -66
  230. package/server/lib/ingress/session-routes.js +68 -68
  231. package/server/lib/ingress/slot-probe.js +130 -130
  232. package/server/lib/ingress/upstream-billing.js +52 -52
  233. package/server/lib/ingress/upstream-fail-streak.js +72 -72
  234. package/server/lib/ingress/upstream-truncation.js +48 -48
  235. package/server/lib/issues-store.js +182 -182
  236. package/server/lib/kinds/deck.js +72 -72
  237. package/server/lib/kinds/docx.js +283 -283
  238. package/server/lib/kinds/file-kinds.js +113 -113
  239. package/server/lib/kinds/index.js +202 -202
  240. package/server/lib/kinds/site.js +161 -161
  241. package/server/lib/model-ingress.js +543 -543
  242. package/server/lib/moderation.js +255 -255
  243. package/server/lib/notice-store.js +103 -103
  244. package/server/lib/plugin-install.js +104 -104
  245. package/server/lib/plugin-validator.js +721 -721
  246. package/server/lib/publish-store.js +115 -115
  247. package/server/lib/quick-summary.js +52 -52
  248. package/server/lib/quota.js +270 -270
  249. package/server/lib/rate-window.js +29 -29
  250. package/server/lib/reference-assets.js +92 -92
  251. package/server/lib/region-shot.js +135 -135
  252. package/server/lib/safe-path.js +73 -73
  253. package/server/lib/sdk-session.js +33 -33
  254. package/server/lib/showcase-store.js +92 -92
  255. package/server/lib/site-publish.js +465 -465
  256. package/server/lib/sketch-layout.js +277 -0
  257. package/server/lib/ssrf-guard.js +432 -432
  258. package/server/lib/task-scan.js +158 -158
  259. package/server/lib/tavern-json.js +154 -154
  260. package/server/lib/video-variant.js +237 -237
  261. package/server/lib/workspace-path.js +33 -33
  262. package/server/ops/fix-sdk-musl.mjs +40 -40
  263. package/server/ops/install-macos-fonts.sh +114 -114
  264. package/server/ops/macos-fonts.conf +336 -336
  265. package/server/ops/sandbox-shim/bwrap +57 -57
  266. package/server/projects/assets-summary.js +119 -119
  267. package/server/projects/auto-name.js +53 -53
  268. package/server/projects/board-limits.js +12 -0
  269. package/server/projects/board-sanitize.js +252 -0
  270. package/server/projects/board-store.js +507 -640
  271. package/server/projects/move-entry.js +103 -103
  272. package/server/projects/store.js +270 -270
  273. package/server/projects/ui-config.js +60 -54
  274. package/server/projects/viewpoint-store.js +78 -0
  275. package/server/projects/workspace-templates.js +53 -53
  276. package/server/projects/workspace.js +1025 -1025
  277. package/server/runtime/local-config.js +177 -177
  278. package/server/runtime/profile.js +72 -72
  279. package/server/services/rembg-service.py +334 -334
  280. package/server/shared/README.md +25 -25
  281. package/server/shared/deck.js +54 -54
  282. package/server/shared/time.js +49 -49
  283. package/server/style-pipeline/README.md +53 -53
  284. package/server/ws/broker.js +39 -36
  285. package/server/ws/browse-channel.js +177 -177
  286. package/server/ws/index.js +386 -386
  287. package/web/README.md +89 -89
  288. package/web/dist/assets/BrowserWindow-P_vIdh-G.js +11 -0
  289. package/web/dist/assets/{DeckWindow-4G0xX7P3.js → DeckWindow-BpLv5082.js} +3 -3
  290. package/web/dist/assets/{DocxWindow-BXQsoPkh.js → DocxWindow-DSAU1-tD.js} +4 -4
  291. package/web/dist/assets/MermaidBlock-DR1GikCv.js +313 -0
  292. package/web/dist/assets/SiteWindow-92uBuRRR.js +18 -0
  293. package/web/dist/assets/abnfDiagram-VCTEODGH-uA8Esix4.js +1 -0
  294. package/web/dist/assets/arc-D_khH_xN.js +1 -0
  295. package/web/dist/assets/architectureDiagram-5GKGNRK7-DydJHqOt.js +36 -0
  296. package/web/dist/assets/blockDiagram-NRAW4CY4-B7wBbKiW.js +129 -0
  297. package/web/dist/assets/c4Diagram-UCG6FXSJ-6mrH0x7Y.js +38 -0
  298. package/web/dist/assets/channel-DGkccMO1.js +1 -0
  299. package/web/dist/assets/chunk-2Q5K7J3B-Cuikho5Q.js +1 -0
  300. package/web/dist/assets/chunk-5VM5RSS4-3-KZ5AUz.js +15 -0
  301. package/web/dist/assets/chunk-F27PBJKO-Bkwq2gGU.js +1 -0
  302. package/web/dist/assets/chunk-G27WJ6UU-BLyQzdGE.js +231 -0
  303. package/web/dist/assets/chunk-JWPE2WC7-B7HxxQds.js +1 -0
  304. package/web/dist/assets/chunk-LCL6LL3I-CtXrnUwF.js +206 -0
  305. package/web/dist/assets/chunk-POPQ4Y6H-dxddZlXt.js +1 -0
  306. package/web/dist/assets/chunk-SVP7TREG-DpkmrgHn.js +88 -0
  307. package/web/dist/assets/chunk-XXDRQBXY-BwZ7RbpQ.js +1 -0
  308. package/web/dist/assets/classDiagram-DTDB5LWJ-BGscw3OD.js +1 -0
  309. package/web/dist/assets/classDiagram-v2-JRS7N3AN-BGscw3OD.js +1 -0
  310. package/web/dist/assets/cose-bilkent-JH36ORCC-DGFOsMUt.js +1 -0
  311. package/web/dist/assets/cynefin-OW5HDTMX-DUwn3ehS.js +178 -0
  312. package/web/dist/assets/cynefinDiagram-5FMLGOSQ-DlLAOZ9x.js +62 -0
  313. package/web/dist/assets/cytoscape.esm-BjAbmLdb.js +331 -0
  314. package/web/dist/assets/dagre-3AP2YEHR-CyourLfz.js +4 -0
  315. package/web/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
  316. package/web/dist/assets/diagram-S7CK7UJ4-BTMbx2np.js +30 -0
  317. package/web/dist/assets/diagram-UQ7AKVKN-UK94_1-P.js +41 -0
  318. package/web/dist/assets/diagram-VSXAHHWV-C7zS-v9v.js +3 -0
  319. package/web/dist/assets/diagram-VX7I27RA-DKJRa6CK.js +24 -0
  320. package/web/dist/assets/diagram-Z3DM3KII-kUbAfGAp.js +24 -0
  321. package/web/dist/assets/ebnfDiagram-PWID7BFC-CVW16_vb.js +1 -0
  322. package/web/dist/assets/erDiagram-SSCWMZ5O-BRQMFQ5y.js +99 -0
  323. package/web/dist/assets/flowDiagram-A5DVABFB-S34LpLtK.js +168 -0
  324. package/web/dist/assets/ganttDiagram-EL5Y4UJY-BFiqk1-G.js +292 -0
  325. package/web/dist/assets/gitGraphDiagram-WWUBYQGX-LZsrdyyv.js +106 -0
  326. package/web/dist/assets/index-GAamh1p4.js +2152 -0
  327. package/web/dist/assets/infoDiagram-RXCK75RN-0DvN6KIp.js +2 -0
  328. package/web/dist/assets/init-Gi6I4Gst.js +1 -0
  329. package/web/dist/assets/ishikawaDiagram-5VMMS53U-CaY3A-Bx.js +70 -0
  330. package/web/dist/assets/journeyDiagram-EYS64GPL-BBeiaCrj.js +139 -0
  331. package/web/dist/assets/kanban-definition-3QL26DDD-ux42DRXQ.js +89 -0
  332. package/web/dist/assets/layout-CnXiF_NB.js +1 -0
  333. package/web/dist/assets/linear-BMW0u6G6.js +1 -0
  334. package/web/dist/assets/mindmap-definition-FBJOCRG2-hUxSpdKn.js +96 -0
  335. package/web/dist/assets/ordinal-Cboi1Yqb.js +1 -0
  336. package/web/dist/assets/pegDiagram-XKGWAZYB-aCaQPH0w.js +1 -0
  337. package/web/dist/assets/{pending-edit-apply-DTjo2geW.js → pending-edit-apply-AcdOQ9Ij.js} +6 -6
  338. package/web/dist/assets/pieDiagram-E7YTZNPT-CmOEZ8zg.js +39 -0
  339. package/web/dist/assets/quadrantDiagram-AXDQQJYC-VW6fAhsV.js +7 -0
  340. package/web/dist/assets/railroadDiagram-O6MQD6OU-CKJ7Ba5K.js +1 -0
  341. package/web/dist/assets/requirementDiagram-EFPCY7ZU-pNGkq9Vw.js +84 -0
  342. package/web/dist/assets/{rotate-cw-LMT3x1Zj.js → rotate-cw-KAfChbGV.js} +1 -1
  343. package/web/dist/assets/sankeyDiagram-P5KCCOFB-BIMmDTfZ.js +40 -0
  344. package/web/dist/assets/sequenceDiagram-WJ2MYXX4-BBW7wzKY.js +162 -0
  345. package/web/dist/assets/sizeCapture-X5ZJPWSS-DdkXmLYR.js +1 -0
  346. package/web/dist/assets/{square-dashed-mouse-pointer-CBoAkfhi.js → square-dashed-mouse-pointer-CDUlhUP7.js} +1 -1
  347. package/web/dist/assets/stateDiagram-HBIQ2CUA-W313Uz16.js +1 -0
  348. package/web/dist/assets/stateDiagram-v2-4QOOHH4V-DDhJBZzf.js +1 -0
  349. package/web/dist/assets/swimlanes-XN3QIQJK-C29TL26K.js +1 -0
  350. package/web/dist/assets/swimlanesDiagram-VK2B7HYN-BfN-Xdmu.js +8 -0
  351. package/web/dist/assets/timeline-definition-24CTP7MA-CF0JMObX.js +120 -0
  352. package/web/dist/assets/vennDiagram-4TSXK5OY-DrDFsaH3.js +34 -0
  353. package/web/dist/assets/wardleyDiagram-VM6X3IG4-CVrnRIS_.js +78 -0
  354. package/web/dist/assets/xychartDiagram-S5SC5T6Z-BvkN1zsT.js +7 -0
  355. package/web/dist/index.html +17 -17
  356. package/web/dist/assets/BrowserWindow-Dc7J7CYc.js +0 -11
  357. package/web/dist/assets/SiteWindow-D6eS-2gM.js +0 -18
  358. package/web/dist/assets/index-Cbl3ATvp.js +0 -2125
@@ -1,104 +1,104 @@
1
- /**
2
- * server/lib/async-queue.js — push/pull 解耦的异步队列
3
- *
4
- * 用途:SDK Query streamInput 模式下,runAgent 需要一个 AsyncIterable<SDKUserMessage>
5
- * 持续 yield user message 让 query 一直活着;前端 POST /turn 把 message push 进
6
- * 队列,generator 那头 pull 后 yield 给 SDK。
7
- *
8
- * 行为:
9
- * - push(item) 立即返回;waiter 等着就唤醒一个,否则进 items 数组
10
- * - next() 返回 Promise;items 有就立刻 resolve,否则 Promise 挂着等 push / close
11
- * - close() 终结流;所有 pending waiter 收到 { done: true };后续 push 抛错
12
- * - return() 自动调 close(让 for-await-of 的 break 能正确收尾)
13
- *
14
- * 不是通用线程安全 queue —— 单事件循环内用,order 保证 FIFO。
15
- *
16
- * @template T
17
- */
18
- export class AsyncQueue {
19
- constructor() {
20
- /** @type {T[]} */
21
- this.items = [];
22
- /** @type {Array<(r: IteratorResult<T>) => void>} */
23
- this.waiters = [];
24
- this.closed = false;
25
- }
26
-
27
- /**
28
- * 当前积压 item 数量(已 push 未 pull 的)。
29
- * 给 UI "已排队 N 条" 显示用。
30
- */
31
- get size() {
32
- return this.items.length;
33
- }
34
-
35
- /**
36
- * 是否还有 active waiter 在等(agent 已 pull 完积压,正等下一条)。
37
- * 给"agent idle"判定用。
38
- */
39
- get isPending() {
40
- return this.waiters.length > 0;
41
- }
42
-
43
- /**
44
- * 推一个 item 进队列。
45
- * @param {T} item
46
- * @throws {Error} 已 close 时抛
47
- */
48
- push(item) {
49
- if (this.closed) {
50
- throw new Error('AsyncQueue: push after close');
51
- }
52
- if (this.waiters.length > 0) {
53
- const w = this.waiters.shift();
54
- w({ value: item, done: false });
55
- return;
56
- }
57
- this.items.push(item);
58
- }
59
-
60
- /**
61
- * 终结流。pending waiter 全部收到 done,items 里残留的 item 仍可 pull
62
- * 直到清空,再之后 next() 返回 done。
63
- *
64
- * 幂等:多次调用 noop。
65
- */
66
- close() {
67
- if (this.closed) return;
68
- this.closed = true;
69
- while (this.waiters.length > 0) {
70
- const w = this.waiters.shift();
71
- w({ value: undefined, done: true });
72
- }
73
- }
74
-
75
- // ── AsyncIterator protocol ──
76
-
77
- [Symbol.asyncIterator]() {
78
- return this;
79
- }
80
-
81
- /**
82
- * @returns {Promise<IteratorResult<T>>}
83
- */
84
- next() {
85
- if (this.items.length > 0) {
86
- return Promise.resolve({ value: this.items.shift(), done: false });
87
- }
88
- if (this.closed) {
89
- return Promise.resolve({ value: undefined, done: true });
90
- }
91
- return new Promise((resolve) => {
92
- this.waiters.push(resolve);
93
- });
94
- }
95
-
96
- /**
97
- * for-await-of 提前 break / throw 时被 runtime 调;触发 close。
98
- * @returns {Promise<IteratorResult<T>>}
99
- */
100
- return() {
101
- this.close();
102
- return Promise.resolve({ value: undefined, done: true });
103
- }
104
- }
1
+ /**
2
+ * server/lib/async-queue.js — push/pull 解耦的异步队列
3
+ *
4
+ * 用途:SDK Query streamInput 模式下,runAgent 需要一个 AsyncIterable<SDKUserMessage>
5
+ * 持续 yield user message 让 query 一直活着;前端 POST /turn 把 message push 进
6
+ * 队列,generator 那头 pull 后 yield 给 SDK。
7
+ *
8
+ * 行为:
9
+ * - push(item) 立即返回;waiter 等着就唤醒一个,否则进 items 数组
10
+ * - next() 返回 Promise;items 有就立刻 resolve,否则 Promise 挂着等 push / close
11
+ * - close() 终结流;所有 pending waiter 收到 { done: true };后续 push 抛错
12
+ * - return() 自动调 close(让 for-await-of 的 break 能正确收尾)
13
+ *
14
+ * 不是通用线程安全 queue —— 单事件循环内用,order 保证 FIFO。
15
+ *
16
+ * @template T
17
+ */
18
+ export class AsyncQueue {
19
+ constructor() {
20
+ /** @type {T[]} */
21
+ this.items = [];
22
+ /** @type {Array<(r: IteratorResult<T>) => void>} */
23
+ this.waiters = [];
24
+ this.closed = false;
25
+ }
26
+
27
+ /**
28
+ * 当前积压 item 数量(已 push 未 pull 的)。
29
+ * 给 UI "已排队 N 条" 显示用。
30
+ */
31
+ get size() {
32
+ return this.items.length;
33
+ }
34
+
35
+ /**
36
+ * 是否还有 active waiter 在等(agent 已 pull 完积压,正等下一条)。
37
+ * 给"agent idle"判定用。
38
+ */
39
+ get isPending() {
40
+ return this.waiters.length > 0;
41
+ }
42
+
43
+ /**
44
+ * 推一个 item 进队列。
45
+ * @param {T} item
46
+ * @throws {Error} 已 close 时抛
47
+ */
48
+ push(item) {
49
+ if (this.closed) {
50
+ throw new Error('AsyncQueue: push after close');
51
+ }
52
+ if (this.waiters.length > 0) {
53
+ const w = this.waiters.shift();
54
+ w({ value: item, done: false });
55
+ return;
56
+ }
57
+ this.items.push(item);
58
+ }
59
+
60
+ /**
61
+ * 终结流。pending waiter 全部收到 done,items 里残留的 item 仍可 pull
62
+ * 直到清空,再之后 next() 返回 done。
63
+ *
64
+ * 幂等:多次调用 noop。
65
+ */
66
+ close() {
67
+ if (this.closed) return;
68
+ this.closed = true;
69
+ while (this.waiters.length > 0) {
70
+ const w = this.waiters.shift();
71
+ w({ value: undefined, done: true });
72
+ }
73
+ }
74
+
75
+ // ── AsyncIterator protocol ──
76
+
77
+ [Symbol.asyncIterator]() {
78
+ return this;
79
+ }
80
+
81
+ /**
82
+ * @returns {Promise<IteratorResult<T>>}
83
+ */
84
+ next() {
85
+ if (this.items.length > 0) {
86
+ return Promise.resolve({ value: this.items.shift(), done: false });
87
+ }
88
+ if (this.closed) {
89
+ return Promise.resolve({ value: undefined, done: true });
90
+ }
91
+ return new Promise((resolve) => {
92
+ this.waiters.push(resolve);
93
+ });
94
+ }
95
+
96
+ /**
97
+ * for-await-of 提前 break / throw 时被 runtime 调;触发 close。
98
+ * @returns {Promise<IteratorResult<T>>}
99
+ */
100
+ return() {
101
+ this.close();
102
+ return Promise.resolve({ value: undefined, done: true });
103
+ }
104
+ }
@@ -1,130 +1,130 @@
1
- /**
2
- * server/lib/auto-relations.js — 自动落线层(2026-08-14,北极星路线 4)
3
- *
4
- * 有一类关系**不需要人或 agent 判断,机器可证**:html 里 `<img src>` 真实
5
- * 指向工作区里的一张图,就是铁打的「取材」。这层把它们落成 `by:'auto'` 的
6
- * ref 边 —— 关系密度从「靠自觉」变成「有底仓」,用户和 agent 的手画线在
7
- * 底仓之上做增量。
8
- *
9
- * 三条纪律:
10
- * 1. **只动自家的边**。自动边 id 恒为 `b:auto:ref:<hash>`(确定性 → 幂等),
11
- * 对账时新增缺的、删掉失效的,**其余 id 一根手指都不碰** —— 用户/agent
12
- * 画的线不归这层管。
13
- * 2. **引用得真实存在**才落线。悬空 src 是裂图体检的事,不是关系。
14
- * 3. **不画**。BindingLayer 对 auto+ref 不渲染 —— 一个站引三十张图,画出来
15
- * 是蜘蛛网不是版面。它们的消费方是 agent 上下文(digest 收拢成一行)和
16
- * 将来的主角判断(被 ref 指着的 = 素材,不该当 hero)。
17
- *
18
- * 触发:挂在 GET /artifacts 尾巴上 fire-and-forget(那里 manifests 现成),
19
- * 每项目 30s 节流。产物身份的拼法与 BoardCanvas 的物件 id 同构 ——
20
- * `deck:<file>` / `site:<root||''>` / 单页 `site:<entryRel>`。
21
- */
22
-
23
- import fs from 'node:fs/promises';
24
- import path from 'node:path';
25
- import crypto from 'node:crypto';
26
- import { readBoard, patchBoard } from '../projects/board-store.js';
27
-
28
- const MAX_HTML_BYTES = 512 * 1024;
29
- const AUTO_REF_PREFIX = 'b:auto:ref:';
30
- /** 每个项目对账节流(ms)—— /artifacts 是热接口,别把它变成扫盘器 */
31
- const THROTTLE_MS = 30_000;
32
- const lastRun = new Map();
33
-
34
- const hashId = (from, to) =>
35
- AUTO_REF_PREFIX + crypto.createHash('sha1').update(`${from}|${to}`).digest('hex').slice(0, 12);
36
-
37
- /**
38
- * 从一段 html 里抠出本地资源引用(src/href/poster + 内联 url())。
39
- * 返回**相对 html 所在目录**的原始引用串(未归一)。
40
- */
41
- export function extractRefs(html) {
42
- const out = new Set();
43
- const push = (raw) => {
44
- if (!raw) return;
45
- const v = raw.trim().replace(/^['"]|['"]$/g, '').split(/[?#]/)[0];
46
- if (!v || /^(https?:|data:|blob:|mailto:|javascript:|\/\/)/i.test(v)) return;
47
- out.add(v);
48
- };
49
- for (const m of html.matchAll(/<(?:img|video|audio|source|embed)\b[^>]*?\s(?:src|poster)\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/gi)) push(m[1]);
50
- for (const m of html.matchAll(/url\(\s*([^)]+?)\s*\)/gi)) push(m[1]);
51
- return [...out];
52
- }
53
-
54
- /** 引用串 → 工作区相对路径(越界/绝对路径丢弃)。baseDir 是 html 所在目录(工作区相对)。 */
55
- export function resolveRef(raw, baseDir) {
56
- try {
57
- const decoded = decodeURIComponent(raw);
58
- if (decoded.startsWith('/')) return null; // 站内绝对路径按约定不出现,出现也不猜
59
- const joined = path.posix.normalize(path.posix.join(baseDir || '.', decoded));
60
- if (joined.startsWith('..') || path.posix.isAbsolute(joined)) return null;
61
- return joined === '.' ? null : joined;
62
- } catch { return null; }
63
- }
64
-
65
- /**
66
- * 对账一个项目的自动 ref 边。
67
- *
68
- * @param {string} pid
69
- * @param {string} workspaceRoot 绝对路径
70
- * @param {Array} tasks /artifacts 已算好的 tasks(id/artifacts 同构前端)
71
- */
72
- export async function reconcileAutoRefs(pid, workspaceRoot, tasks) {
73
- // 期望集:{ bid: { from, to } }
74
- const desired = new Map();
75
- for (const t of tasks || []) {
76
- for (const a of t.artifacts || []) {
77
- // 产物身份(与 BoardCanvas 的物件 id 同一拼法)
78
- // ⚠️ 卡 id 按**形态**派生,别用「不是 deck 就是 site」的二分(2026-08-18 修)。
79
- // docx 上线之后那个三元把 .docx 产物算成了 `site:` 前缀 —— id 对不上,
80
- // 它的自动关系边落在一个不存在的端点上。规则跟前端 cardIdOf
81
- // (web/src/lib/board-kinds.js)必须一致,两边岔开就是"同一件东西两份实现"。
82
- const fromId = a.kind === 'site'
83
- ? `site:${a.single ? a.entryRel : (a.root || t.id)}`
84
- : `${a.kind || 'deck'}:${a.file}`;
85
- // 这件产物的 html 们(deck 一份;站点 = 各页,路径相对站根)
86
- const pages = a.kind === 'deck'
87
- ? [a.file]
88
- : (a.single ? [a.entryRel] : (a.pages || []).map(p => (a.root ? `${a.root}/${p}` : p)));
89
- for (const rel of pages) {
90
- if (!rel || !/\.html?$/i.test(rel)) continue;
91
- let html;
92
- try {
93
- const abs = path.join(workspaceRoot, rel);
94
- const st = await fs.stat(abs);
95
- if (st.size > MAX_HTML_BYTES) continue;
96
- html = await fs.readFile(abs, 'utf8');
97
- } catch { continue; }
98
- const baseDir = path.posix.dirname(rel.replace(/\\/g, '/'));
99
- for (const raw of extractRefs(html)) {
100
- const to = resolveRef(raw, baseDir === '.' ? '' : baseDir);
101
- if (!to || to === rel) continue;
102
- try { await fs.access(path.join(workspaceRoot, to)); } catch { continue; } // 悬空不落线
103
- desired.set(hashId(fromId, to), { from: fromId, to });
104
- }
105
- }
106
- }
107
- }
108
-
109
- // 现状 → diff。只碰 b:auto:ref:* 的条目。
110
- const board = await readBoard(pid);
111
- const patch = {};
112
- for (const [bid, b] of Object.entries(board.bindings || {})) {
113
- if (bid.startsWith(AUTO_REF_PREFIX) && !desired.has(bid)) patch[bid] = null;
114
- }
115
- for (const [bid, { from, to }] of desired) {
116
- const cur = board.bindings?.[bid];
117
- if (cur && cur.from === from && cur.to === to) continue;
118
- patch[bid] = { type: 'ref', from, to, by: 'auto' };
119
- }
120
- if (Object.keys(patch).length) await patchBoard(pid, { bindings: patch });
121
- return { desired: desired.size, changed: Object.keys(patch).length };
122
- }
123
-
124
- /** 节流版:/artifacts 尾巴上 fire-and-forget 用 */
125
- export function reconcileAutoRefsThrottled(pid, workspaceRoot, tasks) {
126
- const now = Date.now();
127
- if (now - (lastRun.get(pid) || 0) < THROTTLE_MS) return;
128
- lastRun.set(pid, now);
129
- reconcileAutoRefs(pid, workspaceRoot, tasks).catch(() => { /* fail-soft:对账绝不拖累清单接口 */ });
130
- }
1
+ /**
2
+ * server/lib/auto-relations.js — 自动落线层(2026-08-14,北极星路线 4)
3
+ *
4
+ * 有一类关系**不需要人或 agent 判断,机器可证**:html 里 `<img src>` 真实
5
+ * 指向工作区里的一张图,就是铁打的「取材」。这层把它们落成 `by:'auto'` 的
6
+ * ref 边 —— 关系密度从「靠自觉」变成「有底仓」,用户和 agent 的手画线在
7
+ * 底仓之上做增量。
8
+ *
9
+ * 三条纪律:
10
+ * 1. **只动自家的边**。自动边 id 恒为 `b:auto:ref:<hash>`(确定性 → 幂等),
11
+ * 对账时新增缺的、删掉失效的,**其余 id 一根手指都不碰** —— 用户/agent
12
+ * 画的线不归这层管。
13
+ * 2. **引用得真实存在**才落线。悬空 src 是裂图体检的事,不是关系。
14
+ * 3. **不画**。BindingLayer 对 auto+ref 不渲染 —— 一个站引三十张图,画出来
15
+ * 是蜘蛛网不是版面。它们的消费方是 agent 上下文(digest 收拢成一行)和
16
+ * 将来的主角判断(被 ref 指着的 = 素材,不该当 hero)。
17
+ *
18
+ * 触发:挂在 GET /artifacts 尾巴上 fire-and-forget(那里 manifests 现成),
19
+ * 每项目 30s 节流。产物身份的拼法与 BoardCanvas 的物件 id 同构 ——
20
+ * `deck:<file>` / `site:<root||''>` / 单页 `site:<entryRel>`。
21
+ */
22
+
23
+ import fs from 'node:fs/promises';
24
+ import path from 'node:path';
25
+ import crypto from 'node:crypto';
26
+ import { readBoard, patchBoard } from '../projects/board-store.js';
27
+
28
+ const MAX_HTML_BYTES = 512 * 1024;
29
+ const AUTO_REF_PREFIX = 'b:auto:ref:';
30
+ /** 每个项目对账节流(ms)—— /artifacts 是热接口,别把它变成扫盘器 */
31
+ const THROTTLE_MS = 30_000;
32
+ const lastRun = new Map();
33
+
34
+ const hashId = (from, to) =>
35
+ AUTO_REF_PREFIX + crypto.createHash('sha1').update(`${from}|${to}`).digest('hex').slice(0, 12);
36
+
37
+ /**
38
+ * 从一段 html 里抠出本地资源引用(src/href/poster + 内联 url())。
39
+ * 返回**相对 html 所在目录**的原始引用串(未归一)。
40
+ */
41
+ export function extractRefs(html) {
42
+ const out = new Set();
43
+ const push = (raw) => {
44
+ if (!raw) return;
45
+ const v = raw.trim().replace(/^['"]|['"]$/g, '').split(/[?#]/)[0];
46
+ if (!v || /^(https?:|data:|blob:|mailto:|javascript:|\/\/)/i.test(v)) return;
47
+ out.add(v);
48
+ };
49
+ for (const m of html.matchAll(/<(?:img|video|audio|source|embed)\b[^>]*?\s(?:src|poster)\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/gi)) push(m[1]);
50
+ for (const m of html.matchAll(/url\(\s*([^)]+?)\s*\)/gi)) push(m[1]);
51
+ return [...out];
52
+ }
53
+
54
+ /** 引用串 → 工作区相对路径(越界/绝对路径丢弃)。baseDir 是 html 所在目录(工作区相对)。 */
55
+ export function resolveRef(raw, baseDir) {
56
+ try {
57
+ const decoded = decodeURIComponent(raw);
58
+ if (decoded.startsWith('/')) return null; // 站内绝对路径按约定不出现,出现也不猜
59
+ const joined = path.posix.normalize(path.posix.join(baseDir || '.', decoded));
60
+ if (joined.startsWith('..') || path.posix.isAbsolute(joined)) return null;
61
+ return joined === '.' ? null : joined;
62
+ } catch { return null; }
63
+ }
64
+
65
+ /**
66
+ * 对账一个项目的自动 ref 边。
67
+ *
68
+ * @param {string} pid
69
+ * @param {string} workspaceRoot 绝对路径
70
+ * @param {Array} tasks /artifacts 已算好的 tasks(id/artifacts 同构前端)
71
+ */
72
+ export async function reconcileAutoRefs(pid, workspaceRoot, tasks) {
73
+ // 期望集:{ bid: { from, to } }
74
+ const desired = new Map();
75
+ for (const t of tasks || []) {
76
+ for (const a of t.artifacts || []) {
77
+ // 产物身份(与 BoardCanvas 的物件 id 同一拼法)
78
+ // ⚠️ 卡 id 按**形态**派生,别用「不是 deck 就是 site」的二分(2026-08-18 修)。
79
+ // docx 上线之后那个三元把 .docx 产物算成了 `site:` 前缀 —— id 对不上,
80
+ // 它的自动关系边落在一个不存在的端点上。规则跟前端 cardIdOf
81
+ // (web/src/lib/board-kinds.js)必须一致,两边岔开就是"同一件东西两份实现"。
82
+ const fromId = a.kind === 'site'
83
+ ? `site:${a.single ? a.entryRel : (a.root || t.id)}`
84
+ : `${a.kind || 'deck'}:${a.file}`;
85
+ // 这件产物的 html 们(deck 一份;站点 = 各页,路径相对站根)
86
+ const pages = a.kind === 'deck'
87
+ ? [a.file]
88
+ : (a.single ? [a.entryRel] : (a.pages || []).map(p => (a.root ? `${a.root}/${p}` : p)));
89
+ for (const rel of pages) {
90
+ if (!rel || !/\.html?$/i.test(rel)) continue;
91
+ let html;
92
+ try {
93
+ const abs = path.join(workspaceRoot, rel);
94
+ const st = await fs.stat(abs);
95
+ if (st.size > MAX_HTML_BYTES) continue;
96
+ html = await fs.readFile(abs, 'utf8');
97
+ } catch { continue; }
98
+ const baseDir = path.posix.dirname(rel.replace(/\\/g, '/'));
99
+ for (const raw of extractRefs(html)) {
100
+ const to = resolveRef(raw, baseDir === '.' ? '' : baseDir);
101
+ if (!to || to === rel) continue;
102
+ try { await fs.access(path.join(workspaceRoot, to)); } catch { continue; } // 悬空不落线
103
+ desired.set(hashId(fromId, to), { from: fromId, to });
104
+ }
105
+ }
106
+ }
107
+ }
108
+
109
+ // 现状 → diff。只碰 b:auto:ref:* 的条目。
110
+ const board = await readBoard(pid);
111
+ const patch = {};
112
+ for (const [bid, b] of Object.entries(board.bindings || {})) {
113
+ if (bid.startsWith(AUTO_REF_PREFIX) && !desired.has(bid)) patch[bid] = null;
114
+ }
115
+ for (const [bid, { from, to }] of desired) {
116
+ const cur = board.bindings?.[bid];
117
+ if (cur && cur.from === from && cur.to === to) continue;
118
+ patch[bid] = { type: 'ref', from, to, by: 'auto' };
119
+ }
120
+ if (Object.keys(patch).length) await patchBoard(pid, { bindings: patch });
121
+ return { desired: desired.size, changed: Object.keys(patch).length };
122
+ }
123
+
124
+ /** 节流版:/artifacts 尾巴上 fire-and-forget 用 */
125
+ export function reconcileAutoRefsThrottled(pid, workspaceRoot, tasks) {
126
+ const now = Date.now();
127
+ if (now - (lastRun.get(pid) || 0) < THROTTLE_MS) return;
128
+ lastRun.set(pid, now);
129
+ reconcileAutoRefs(pid, workspaceRoot, tasks).catch(() => { /* fail-soft:对账绝不拖累清单接口 */ });
130
+ }
@@ -1,60 +1,72 @@
1
- /**
2
- * 关系线的语义词汇表 —— 画布上一条线「是什么意思」的**唯一真相**。
3
- *
4
- * ## 为什么关系要单独存一张表
5
- *
6
- * 北极星是「任务文件夹能排出登录墙那种版面」。手摆之所以好看,是因为每张纸的
7
- * 位置在回答「它和旁边那张什么关系」。而系统此前只知道每个产物的**尺寸和
8
- * mtime** —— 关系数据不到位,再好的布局算法也只能排出「错落有致的网格」。
9
- *
10
- * 所以关系是 board.json 里的一等公民,跟 objects / zones 平级:
11
- *
12
- * bindings: { "<id>": { type, from, to, label?, by? } }
13
- *
14
- * 端点 `from` / `to` 是 **object id 或 zone id**(用户明确要求文件夹之间也能连线)。
15
- * 线本身不存坐标 —— 端点一移动,线自己跟着走。这是 tldraw `TLBinding` 的思路:
16
- * 关系是独立记录,不是形状的属性,箭头形状本身不存端点坐标。**抄的是思路,
17
- * 不是代码**(tldraw 是专有许可证)。
18
- *
19
- * ## 为什么是这五种
20
- *
21
- * 挑的标准是「这条关系能不能改变布局决定」。能影响摆放的才收,纯装饰的不收。
22
- * 每一种都对应创作过程里一件真实发生的事:
23
- *
24
- * - **改自**:一个产物是另一个的下一版。这是版本谱系,最该被看见的一条 ——
25
- * 用户翻旧版找的就是它。
26
- * - **批注**:一段文字在说某个东西。annotation 形态存在的理由。
27
- * - **顺序**:分镜、章节、流程的先后。它决定读序,也就决定排布方向。
28
- * - **取材**:这张图用在那个 deck 里 / 这份资料喂给了那篇稿。跨任务的引用。
29
- * - **对照**:并列比较(proto-暖调 vs proto-冷调)。无向,且**明确要求并排**,
30
- * 是唯一一条直接给布局下指令的关系。
31
- *
32
- * ## 明确不做成线的:「成组」
33
- *
34
- * 「这几件属于同一批」的正确画法是**圈一个框**,不是两两连线 —— n 个成员
35
- * 两两连线是 n(n-1)/2 条,五件就是十条,画面直接糊掉。成组用已有的 zone
36
- * (工作区 / 文件夹)表达,agent 建文件夹收纳就是在表达成组。
37
- */
38
-
39
- /**
40
- * 词汇表。`directed` 决定渲染时画不画箭头,也决定 from/to 能不能互换。
41
- * `label` 是没写自定义文字时线上显示的默认词。
42
- */
43
- export const BINDING_TYPES = {
44
- 'derives-from': { label: '改自', directed: true },
45
- annotates: { label: '批注', directed: true },
46
- flow: { label: '接着', directed: true },
47
- ref: { label: '取材', directed: true },
48
- contrast: { label: '对照', directed: false },
49
- // 关联(2026-08-14,手动连线上线时加):五种预定义都不合身时的逃生舱。
50
- // 含义由线上的 label 定义(用户写一句,agent 逐字读)。收它不违反
51
- // 「纯装饰不收」——它对布局说「摆近点」(affinity),对 agent 说 label 那句话。
52
- link: { label: '关联', directed: false },
53
- };
54
-
55
- /** 词汇表 id 列表,校验和 parity 断言都用它。 */
56
- export const BINDING_TYPE_IDS = Object.keys(BINDING_TYPES);
57
-
58
- export function isBindingType(t) {
59
- return Object.prototype.hasOwnProperty.call(BINDING_TYPES, t);
60
- }
1
+ /**
2
+ * 关系线的语义词汇表 —— 画布上一条线「是什么意思」的**唯一真相**。
3
+ *
4
+ * ## 为什么关系要单独存一张表
5
+ *
6
+ * 北极星是「任务文件夹能排出登录墙那种版面」。手摆之所以好看,是因为每张纸的
7
+ * 位置在回答「它和旁边那张什么关系」。而系统此前只知道每个产物的**尺寸和
8
+ * mtime** —— 关系数据不到位,再好的布局算法也只能排出「错落有致的网格」。
9
+ *
10
+ * 所以关系是 board.json 里的一等公民,跟 objects / zones 平级:
11
+ *
12
+ * bindings: { "<id>": { type, from, to, label?, by? } }
13
+ *
14
+ * 端点 `from` / `to` 是 **object id 或 zone id**(用户明确要求文件夹之间也能连线)。
15
+ * 线本身不存坐标 —— 端点一移动,线自己跟着走。这是 tldraw `TLBinding` 的思路:
16
+ * 关系是独立记录,不是形状的属性,箭头形状本身不存端点坐标。**抄的是思路,
17
+ * 不是代码**(tldraw 是专有许可证)。
18
+ *
19
+ * ## 为什么是这五种
20
+ *
21
+ * 挑的标准是「这条关系能不能改变布局决定」。能影响摆放的才收,纯装饰的不收。
22
+ * 每一种都对应创作过程里一件真实发生的事:
23
+ *
24
+ * - **改自**:一个产物是另一个的下一版。这是版本谱系,最该被看见的一条 ——
25
+ * 用户翻旧版找的就是它。
26
+ * - **批注**:一段文字在说某个东西。annotation 形态存在的理由。
27
+ * - **顺序**:分镜、章节、流程的先后。它决定读序,也就决定排布方向。
28
+ * - **取材**:这张图用在那个 deck 里 / 这份资料喂给了那篇稿。跨任务的引用。
29
+ * - **对照**:并列比较(proto-暖调 vs proto-冷调)。无向,且**明确要求并排**,
30
+ * 是唯一一条直接给布局下指令的关系。
31
+ *
32
+ * ## 明确不做成线的:「成组」
33
+ *
34
+ * 「这几件属于同一批」的正确画法是**圈一个框**,不是两两连线 —— n 个成员
35
+ * 两两连线是 n(n-1)/2 条,五件就是十条,画面直接糊掉。成组用已有的 zone
36
+ * (工作区 / 文件夹)表达,agent 建文件夹收纳就是在表达成组。
37
+ */
38
+
39
+ /**
40
+ * 词汇表。`directed` 决定渲染时画不画箭头,也决定 from/to 能不能互换。
41
+ * `label` 是没写自定义文字时线上显示的默认词。
42
+ */
43
+ export const BINDING_TYPES = {
44
+ 'derives-from': { label: '改自', directed: true },
45
+ annotates: { label: '批注', directed: true },
46
+ flow: { label: '接着', directed: true },
47
+ ref: { label: '取材', directed: true },
48
+ contrast: { label: '对照', directed: false },
49
+ // 关联(2026-08-14,手动连线上线时加):五种预定义都不合身时的逃生舱。
50
+ // 含义由线上的 label 定义(用户写一句,agent 逐字读)。收它不违反
51
+ // 「纯装饰不收」——它对布局说「摆近点」(affinity),对 agent 说 label 那句话。
52
+ link: { label: '关联', directed: false },
53
+ };
54
+
55
+ /** 词汇表 id 列表,校验和 parity 断言都用它。 */
56
+ export const BINDING_TYPE_IDS = Object.keys(BINDING_TYPES);
57
+
58
+ /**
59
+ * 材质(2026-08-23 黑板):与语义正交的第二个轴。
60
+ * ink 墨线 —— 版面线的默认材质,安静
61
+ * pencil 手绘 —— 铅笔抖动,像人顺手拉的一笔
62
+ * yarn 丝线 —— 侦探板上的红线 + 图钉,推理态、声量大
63
+ * 前端 board-bindings.js 的 BINDING_MATERIALS 必须与这份 id 一一对应(parity 测试)。
64
+ */
65
+ export const BINDING_MATERIALS = ['ink', 'pencil', 'yarn'];
66
+ export function isBindingMaterial(m) {
67
+ return BINDING_MATERIALS.includes(m);
68
+ }
69
+
70
+ export function isBindingType(t) {
71
+ return Object.prototype.hasOwnProperty.call(BINDING_TYPES, t);
72
+ }