openplanr 3.3.0 → 3.5.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 (493) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/dist/cli/commands/artifact-design-share.d.ts +9 -0
  3. package/dist/cli/commands/artifact-design-share.d.ts.map +1 -0
  4. package/dist/cli/commands/artifact-design-share.js +200 -0
  5. package/dist/cli/commands/artifact-design-share.js.map +1 -0
  6. package/dist/cli/commands/artifact.d.ts.map +1 -1
  7. package/dist/cli/commands/artifact.js +5 -18
  8. package/dist/cli/commands/artifact.js.map +1 -1
  9. package/dist/cli/commands/design.d.ts +3 -0
  10. package/dist/cli/commands/design.d.ts.map +1 -0
  11. package/dist/cli/commands/design.js +137 -0
  12. package/dist/cli/commands/design.js.map +1 -0
  13. package/dist/cli/commands/groups/operations.d.ts.map +1 -1
  14. package/dist/cli/commands/groups/operations.js +2 -0
  15. package/dist/cli/commands/groups/operations.js.map +1 -1
  16. package/dist/cli/commands/ship.d.ts.map +1 -1
  17. package/dist/cli/commands/ship.js +2 -0
  18. package/dist/cli/commands/ship.js.map +1 -1
  19. package/dist/dashboard/.vite/manifest.json +2 -2
  20. package/dist/dashboard/assets/index-B-l_941W.js +75 -0
  21. package/dist/dashboard/assets/index-B-l_941W.js.map +1 -0
  22. package/dist/dashboard/assets/index-Cv4Vwhuw.css +2 -0
  23. package/dist/dashboard/dashboard-manifest.json +14 -14
  24. package/dist/dashboard/index.html +2 -2
  25. package/dist/services/design-artifact-service.d.ts +42 -1
  26. package/dist/services/design-artifact-service.d.ts.map +1 -1
  27. package/dist/services/design-artifact-service.js +198 -19
  28. package/dist/services/design-artifact-service.js.map +1 -1
  29. package/dist/services/runtime-manager/runtime-package.js +1 -1
  30. package/dist/services/runtime-manager/runtime-package.js.map +1 -1
  31. package/dist/services/ship-checks/contract.d.ts +3 -1
  32. package/dist/services/ship-checks/contract.d.ts.map +1 -1
  33. package/dist/services/ship-checks/contract.js +1 -1
  34. package/dist/services/ship-checks/contract.js.map +1 -1
  35. package/dist/services/ship-checks/discover.d.ts.map +1 -1
  36. package/dist/services/ship-checks/discover.js +2 -1
  37. package/dist/services/ship-checks/discover.js.map +1 -1
  38. package/dist/services/ship-checks/package-contents.d.ts +4 -0
  39. package/dist/services/ship-checks/package-contents.d.ts.map +1 -0
  40. package/dist/services/ship-checks/package-contents.js +91 -0
  41. package/dist/services/ship-checks/package-contents.js.map +1 -0
  42. package/dist/services/ship-checks/packages.d.ts +2 -0
  43. package/dist/services/ship-checks/packages.d.ts.map +1 -1
  44. package/dist/services/ship-checks/packages.js +4 -0
  45. package/dist/services/ship-checks/packages.js.map +1 -1
  46. package/dist/services/ship-checks/scope.js +2 -1
  47. package/dist/services/ship-checks/scope.js.map +1 -1
  48. package/dist/utils/splice-managed-block.js +1 -1
  49. package/dist/utils/splice-managed-block.js.map +1 -1
  50. package/docs/CLI.md +67 -1
  51. package/lib/host-packages/adapter-registry.json +5 -5
  52. package/lib/host-packages/capability-map.json +1 -1
  53. package/lib/host-packages/claude/.claude-plugin/marketplace.json +3 -3
  54. package/lib/host-packages/claude/openplanr/.claude-plugin/plugin.json +6 -6
  55. package/lib/host-packages/claude/openplanr/.openplanr-content.json +57 -429
  56. package/lib/host-packages/claude/openplanr/README.md +16 -16
  57. package/lib/host-packages/claude/openplanr/references/agents/shared/modes/shared/task-context-resolution.md +4 -4
  58. package/lib/host-packages/claude/openplanr/skills/artifact/references/design-sharing.md +2 -2
  59. package/lib/host-packages/claude/openplanr/skills/delegate/SKILL.md +2 -1
  60. package/lib/host-packages/claude/openplanr/skills/delegate/references/integration-review.md +26 -20
  61. package/lib/host-packages/claude/openplanr/skills/delegate/references/operator-guide.md +25 -1
  62. package/lib/host-packages/claude/openplanr/skills/delegate/references/run-handoff.md +2 -2
  63. package/lib/host-packages/claude/openplanr/skills/delegate/references/worktree-custody.md +17 -9
  64. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/adapters/claude.mjs +15 -3
  65. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/adapters/codex.mjs +38 -2
  66. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/adapters/native.mjs +5 -0
  67. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/custody.mjs +217 -10
  68. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/handoff.mjs +1080 -0
  69. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/integrate.mjs +96 -201
  70. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/integration-files.mjs +3 -382
  71. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/presentation.mjs +29 -12
  72. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/run-contract.mjs +11 -0
  73. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/run-execution.mjs +1 -1
  74. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/run-lifecycle.mjs +14 -10
  75. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/run-preparation.mjs +4 -0
  76. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/run-record.mjs +2 -2
  77. package/lib/host-packages/claude/openplanr/skills/design/SKILL.md +23 -12
  78. package/lib/host-packages/claude/openplanr/skills/design/references/design-system.md +2 -2
  79. package/lib/host-packages/claude/openplanr/skills/design/references/generation.md +3 -3
  80. package/lib/host-packages/claude/openplanr/skills/design/references/hosted-canvas.md +6 -3
  81. package/lib/host-packages/claude/openplanr/skills/design/references/review.md +6 -6
  82. package/lib/host-packages/claude/openplanr/skills/design/references/team-review.md +3 -4
  83. package/lib/host-packages/claude/openplanr/skills/design/references/utilities.md +78 -32
  84. package/lib/host-packages/claude/openplanr/skills/design-loop/SKILL.md +15 -7
  85. package/lib/host-packages/claude/openplanr/skills/design-loop/references/design-system.md +2 -2
  86. package/lib/host-packages/claude/openplanr/skills/design-loop/references/generation.md +3 -3
  87. package/lib/host-packages/claude/openplanr/skills/design-loop/references/review.md +6 -6
  88. package/lib/host-packages/claude/openplanr/skills/design-loop/references/team-review.md +3 -4
  89. package/lib/host-packages/claude/openplanr/skills/design-loop/references/utilities.md +78 -32
  90. package/lib/host-packages/claude/openplanr/skills/design-review/SKILL.md +25 -5
  91. package/lib/host-packages/claude/openplanr/skills/design-review/references/design-system.md +2 -2
  92. package/lib/host-packages/claude/openplanr/skills/design-review/references/generation.md +3 -3
  93. package/lib/host-packages/claude/openplanr/skills/design-review/references/review.md +6 -6
  94. package/lib/host-packages/claude/openplanr/skills/design-review/references/team-review.md +3 -4
  95. package/lib/host-packages/claude/openplanr/skills/design-review/references/utilities.md +78 -32
  96. package/lib/host-packages/claude/openplanr/skills/investigate/SKILL.md +1 -0
  97. package/lib/host-packages/claude/openplanr/skills/investigate/references/fail-first.md +40 -0
  98. package/lib/host-packages/claude/openplanr/skills/plan/SKILL.md +7 -3
  99. package/lib/host-packages/claude/openplanr/skills/ship/SKILL.md +22 -10
  100. package/lib/host-packages/claude/openplanr/skills/ship/references/fail-first.md +40 -0
  101. package/lib/host-packages/claude/openplanr/skills/ship/references/result-contract.md +7 -3
  102. package/lib/host-packages/cursor/openplanr/.openplanr-content.json +55 -427
  103. package/lib/host-packages/cursor/openplanr/manifest.json +1 -1
  104. package/lib/host-packages/cursor/openplanr/rules/planr-artifact/references/design-sharing.md +2 -2
  105. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/references/integration-review.md +26 -20
  106. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/references/operator-guide.md +25 -1
  107. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/references/run-handoff.md +2 -2
  108. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/references/worktree-custody.md +17 -9
  109. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/adapters/claude.mjs +15 -3
  110. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/adapters/codex.mjs +38 -2
  111. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/adapters/native.mjs +5 -0
  112. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/custody.mjs +217 -10
  113. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/handoff.mjs +1080 -0
  114. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/integrate.mjs +96 -201
  115. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/integration-files.mjs +3 -382
  116. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/presentation.mjs +29 -12
  117. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/run-contract.mjs +11 -0
  118. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/run-execution.mjs +1 -1
  119. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/run-lifecycle.mjs +14 -10
  120. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/run-preparation.mjs +4 -0
  121. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/run-record.mjs +2 -2
  122. package/lib/host-packages/cursor/openplanr/rules/planr-delegate.mdc +2 -1
  123. package/lib/host-packages/cursor/openplanr/rules/planr-design/references/design-system.md +2 -2
  124. package/lib/host-packages/cursor/openplanr/rules/planr-design/references/generation.md +3 -3
  125. package/lib/host-packages/cursor/openplanr/rules/planr-design/references/hosted-canvas.md +6 -3
  126. package/lib/host-packages/cursor/openplanr/rules/planr-design/references/review.md +6 -6
  127. package/lib/host-packages/cursor/openplanr/rules/planr-design/references/team-review.md +3 -4
  128. package/lib/host-packages/cursor/openplanr/rules/planr-design/references/utilities.md +78 -32
  129. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/references/design-system.md +2 -2
  130. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/references/generation.md +3 -3
  131. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/references/review.md +6 -6
  132. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/references/team-review.md +3 -4
  133. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/references/utilities.md +78 -32
  134. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop.mdc +15 -7
  135. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/references/design-system.md +2 -2
  136. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/references/generation.md +3 -3
  137. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/references/review.md +6 -6
  138. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/references/team-review.md +3 -4
  139. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/references/utilities.md +78 -32
  140. package/lib/host-packages/cursor/openplanr/rules/planr-design-review.mdc +25 -5
  141. package/lib/host-packages/cursor/openplanr/rules/planr-design.mdc +23 -12
  142. package/lib/host-packages/cursor/openplanr/rules/planr-investigate/references/fail-first.md +40 -0
  143. package/lib/host-packages/cursor/openplanr/rules/planr-investigate.mdc +1 -0
  144. package/lib/host-packages/cursor/openplanr/rules/planr-plan.mdc +7 -3
  145. package/lib/host-packages/cursor/openplanr/rules/planr-ship/references/fail-first.md +40 -0
  146. package/lib/host-packages/cursor/openplanr/rules/planr-ship/references/result-contract.md +7 -3
  147. package/lib/host-packages/cursor/openplanr/rules/planr-ship.mdc +22 -10
  148. package/lib/host-packages/openai/.claude-plugin/marketplace.json +3 -3
  149. package/lib/host-packages/openai/openplanr/.codex-plugin/plugin.json +2 -2
  150. package/lib/host-packages/openai/openplanr/.openplanr-content.json +62 -434
  151. package/lib/host-packages/openai/openplanr/skills/artifact/references/design-sharing.md +2 -2
  152. package/lib/host-packages/openai/openplanr/skills/delegate/SKILL.md +2 -1
  153. package/lib/host-packages/openai/openplanr/skills/delegate/openplanr.skill.json +1 -1
  154. package/lib/host-packages/openai/openplanr/skills/delegate/references/integration-review.md +26 -20
  155. package/lib/host-packages/openai/openplanr/skills/delegate/references/operator-guide.md +25 -1
  156. package/lib/host-packages/openai/openplanr/skills/delegate/references/run-handoff.md +2 -2
  157. package/lib/host-packages/openai/openplanr/skills/delegate/references/worktree-custody.md +17 -9
  158. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/adapters/claude.mjs +15 -3
  159. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/adapters/codex.mjs +38 -2
  160. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/adapters/native.mjs +5 -0
  161. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/custody.mjs +217 -10
  162. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/handoff.mjs +1080 -0
  163. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/integrate.mjs +96 -201
  164. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/integration-files.mjs +3 -382
  165. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/presentation.mjs +29 -12
  166. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/run-contract.mjs +11 -0
  167. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/run-execution.mjs +1 -1
  168. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/run-lifecycle.mjs +14 -10
  169. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/run-preparation.mjs +4 -0
  170. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/run-record.mjs +2 -2
  171. package/lib/host-packages/openai/openplanr/skills/design/SKILL.md +23 -12
  172. package/lib/host-packages/openai/openplanr/skills/design/openplanr.skill.json +0 -11
  173. package/lib/host-packages/openai/openplanr/skills/design/references/design-system.md +2 -2
  174. package/lib/host-packages/openai/openplanr/skills/design/references/generation.md +3 -3
  175. package/lib/host-packages/openai/openplanr/skills/design/references/hosted-canvas.md +6 -3
  176. package/lib/host-packages/openai/openplanr/skills/design/references/review.md +6 -6
  177. package/lib/host-packages/openai/openplanr/skills/design/references/team-review.md +3 -4
  178. package/lib/host-packages/openai/openplanr/skills/design/references/utilities.md +78 -32
  179. package/lib/host-packages/openai/openplanr/skills/design-loop/SKILL.md +15 -7
  180. package/lib/host-packages/openai/openplanr/skills/design-loop/openplanr.skill.json +0 -11
  181. package/lib/host-packages/openai/openplanr/skills/design-loop/references/design-system.md +2 -2
  182. package/lib/host-packages/openai/openplanr/skills/design-loop/references/generation.md +3 -3
  183. package/lib/host-packages/openai/openplanr/skills/design-loop/references/review.md +6 -6
  184. package/lib/host-packages/openai/openplanr/skills/design-loop/references/team-review.md +3 -4
  185. package/lib/host-packages/openai/openplanr/skills/design-loop/references/utilities.md +78 -32
  186. package/lib/host-packages/openai/openplanr/skills/design-review/SKILL.md +25 -5
  187. package/lib/host-packages/openai/openplanr/skills/design-review/openplanr.skill.json +0 -11
  188. package/lib/host-packages/openai/openplanr/skills/design-review/references/design-system.md +2 -2
  189. package/lib/host-packages/openai/openplanr/skills/design-review/references/generation.md +3 -3
  190. package/lib/host-packages/openai/openplanr/skills/design-review/references/review.md +6 -6
  191. package/lib/host-packages/openai/openplanr/skills/design-review/references/team-review.md +3 -4
  192. package/lib/host-packages/openai/openplanr/skills/design-review/references/utilities.md +78 -32
  193. package/lib/host-packages/openai/openplanr/skills/investigate/SKILL.md +1 -0
  194. package/lib/host-packages/openai/openplanr/skills/investigate/openplanr.skill.json +12 -1
  195. package/lib/host-packages/openai/openplanr/skills/investigate/references/fail-first.md +40 -0
  196. package/lib/host-packages/openai/openplanr/skills/plan/SKILL.md +7 -3
  197. package/lib/host-packages/openai/openplanr/skills/plan/openplanr.skill.json +0 -11
  198. package/lib/host-packages/openai/openplanr/skills/ship/SKILL.md +22 -10
  199. package/lib/host-packages/openai/openplanr/skills/ship/openplanr.skill.json +12 -1
  200. package/lib/host-packages/openai/openplanr/skills/ship/references/fail-first.md +40 -0
  201. package/lib/host-packages/openai/openplanr/skills/ship/references/result-contract.md +7 -3
  202. package/package.json +8 -8
  203. package/dist/dashboard/assets/index-BU5fzjyz.css +0 -1
  204. package/dist/dashboard/assets/index-B_96uzCl.js +0 -572
  205. package/dist/dashboard/assets/index-B_96uzCl.js.map +0 -1
  206. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-artifact-shell.mjs +0 -1774
  207. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-chunked-workspace-client.mjs +0 -555
  208. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-compression.mjs +0 -4180
  209. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-document.mjs +0 -2937
  210. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-encrypted-workspace-client.mjs +0 -647
  211. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-entities.mjs +0 -439
  212. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-handoff.mjs +0 -1576
  213. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-loopback-server.mjs +0 -359
  214. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-owner-custody.mjs +0 -129
  215. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-parse5-parser.mjs +0 -3970
  216. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-parse5-tokenizer.mjs +0 -3501
  217. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-resource-pack.mjs +0 -698
  218. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-review.mjs +0 -3385
  219. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-runtime-home.mjs +0 -39
  220. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-runtime-support-25485dbf1cb2.mjs +0 -24
  221. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-sandbox-guards.mjs +0 -1102
  222. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-share.mjs +0 -1993
  223. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-shared-artifact-support-dependencies-design-support-protocol-contracts-3d9b1a86.mjs +0 -1113
  224. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-shared-artifact-support-protocol-contracts-ea2cd15e.mjs +0 -505
  225. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-shared-protocol-contracts-75a938cc.mjs +0 -222
  226. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-shared-protocol-contracts-b5f28f94.mjs +0 -5907
  227. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-upload-spool.mjs +0 -198
  228. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design.mjs +0 -1430
  229. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +0 -2050
  230. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/lib/artifact/ui/studio-shell.css +0 -2
  231. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/01-module-runtime.js +0 -18
  232. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/02-artifact-review-ui.js +0 -809
  233. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/03-protocol-contracts.js +0 -5693
  234. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/04-compression.js +0 -4175
  235. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/05-artifact-sharing.js +0 -65
  236. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/06-artifact-review-ui.js +0 -1755
  237. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/07-artifact-sharing.js +0 -62
  238. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/08-artifact-review-ui.js +0 -2633
  239. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources.json +0 -124
  240. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/package.json +0 -65
  241. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/enhancements.css +0 -388
  242. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/handoff-center.css +0 -81
  243. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/share.css +0 -1
  244. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/share.js +0 -133
  245. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.css +0 -1159
  246. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/01-module-runtime.js +0 -30
  247. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/02-react.js +0 -900
  248. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/03-react-dom-client-fiber-foundations.js +0 -2261
  249. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/04-react-dom-client-reconciliation-hooks.js +0 -1595
  250. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/05-react-dom-client-render-phases.js +0 -1467
  251. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/06-react-dom-client-commit-effects.js +0 -1860
  252. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/07-react-dom-client-work-loop-scheduling.js +0 -914
  253. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/08-react-dom-client-dom-events-properties-hydration.js +0 -2578
  254. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/09-react-dom-client-public-roots.js +0 -582
  255. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/10-react.js +0 -17
  256. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/11-artifact-review-ui.js +0 -12
  257. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/12-protocol-contracts.js +0 -285
  258. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/13-design-review-experience.js +0 -2773
  259. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/14-studio-shell.js +0 -134
  260. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/15-canvas-engine.js +0 -2207
  261. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/16-design-review-experience.js +0 -16
  262. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/17-studio-shell.js +0 -8
  263. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/18-interface-primitives.js +0 -3883
  264. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/19-interface-primitives.js +0 -966
  265. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/20-studio-shell.js +0 -520
  266. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/21-design-studio.js +0 -1597
  267. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources.json +0 -311
  268. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/package.json +0 -159
  269. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/registries/artifact-theme.json +0 -64
  270. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.0.0/design-manifest.schema.json +0 -90
  271. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-envelope.schema.json +0 -142
  272. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-paste.schema.json +0 -49
  273. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-review.schema.json +0 -97
  274. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-bundle.schema.json +0 -584
  275. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-context.schema.json +0 -191
  276. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-handoff.schema.json +0 -407
  277. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-metadata-payload.schema.json +0 -106
  278. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-handoff-readiness.schema.json +0 -398
  279. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-implementation-handoff.schema.json +0 -518
  280. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-planning-lineage.schema.json +0 -106
  281. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-review-metadata-payload.schema.json +0 -107
  282. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.14.0/artifact-theme.schema.json +0 -316
  283. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.16.0/artifact-envelope.schema.json +0 -408
  284. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.16.0/design-review-bundle.schema.json +0 -590
  285. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-document.schema.json +0 -506
  286. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-review-bundle.schema.json +0 -822
  287. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-review-bundle.schema.json +0 -346
  288. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-review-workspace.schema.json +0 -108
  289. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-workspace-create.schema.json +0 -170
  290. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-workspace-event.schema.json +0 -97
  291. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-workspace-revision.schema.json +0 -56
  292. package/lib/host-packages/claude/openplanr/runtime/plan/scripts/design-protocol-contracts.mjs +0 -5468
  293. package/lib/host-packages/claude/openplanr/runtime/plan/scripts/design.mjs +0 -2844
  294. package/lib/host-packages/claude/openplanr/runtime/plan/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +0 -21
  295. package/lib/host-packages/claude/openplanr/runtime/plan/scripts/runtime/packages/protocol/package.json +0 -159
  296. package/lib/host-packages/claude/openplanr/runtime/plan/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-review.schema.json +0 -97
  297. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/integration-transaction.mjs +0 -958
  298. package/lib/host-packages/claude/openplanr/skills/design/scripts/design.mjs +0 -12
  299. package/lib/host-packages/claude/openplanr/skills/design-loop/scripts/design.mjs +0 -12
  300. package/lib/host-packages/claude/openplanr/skills/design-review/scripts/design.mjs +0 -12
  301. package/lib/host-packages/claude/openplanr/skills/plan/scripts/design.mjs +0 -12
  302. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/integration-transaction.mjs +0 -958
  303. package/lib/host-packages/cursor/openplanr/rules/planr-design/scripts/design.mjs +0 -12
  304. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/scripts/design.mjs +0 -12
  305. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/scripts/design.mjs +0 -12
  306. package/lib/host-packages/cursor/openplanr/rules/planr-plan/scripts/design.mjs +0 -12
  307. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-artifact-shell.mjs +0 -1774
  308. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-chunked-workspace-client.mjs +0 -555
  309. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-compression.mjs +0 -4180
  310. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-document.mjs +0 -2937
  311. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-encrypted-workspace-client.mjs +0 -647
  312. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-entities.mjs +0 -439
  313. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-handoff.mjs +0 -1576
  314. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-loopback-server.mjs +0 -359
  315. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-owner-custody.mjs +0 -129
  316. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-parse5-parser.mjs +0 -3970
  317. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-parse5-tokenizer.mjs +0 -3501
  318. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-resource-pack.mjs +0 -698
  319. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-review.mjs +0 -3385
  320. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-runtime-home.mjs +0 -39
  321. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-runtime-support-25485dbf1cb2.mjs +0 -24
  322. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-sandbox-guards.mjs +0 -1102
  323. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-share.mjs +0 -1993
  324. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-shared-artifact-support-dependencies-design-support-protocol-contracts-3d9b1a86.mjs +0 -1113
  325. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-shared-artifact-support-protocol-contracts-ea2cd15e.mjs +0 -505
  326. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-shared-protocol-contracts-75a938cc.mjs +0 -222
  327. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-shared-protocol-contracts-b5f28f94.mjs +0 -5907
  328. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-upload-spool.mjs +0 -198
  329. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design.mjs +0 -1430
  330. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +0 -2050
  331. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/lib/artifact/ui/studio-shell.css +0 -2
  332. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/01-module-runtime.js +0 -18
  333. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/02-artifact-review-ui.js +0 -809
  334. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/03-protocol-contracts.js +0 -5693
  335. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/04-compression.js +0 -4175
  336. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/05-artifact-sharing.js +0 -65
  337. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/06-artifact-review-ui.js +0 -1755
  338. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/07-artifact-sharing.js +0 -62
  339. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/08-artifact-review-ui.js +0 -2633
  340. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources.json +0 -124
  341. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/package.json +0 -65
  342. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/enhancements.css +0 -388
  343. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/handoff-center.css +0 -81
  344. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/share.css +0 -1
  345. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/share.js +0 -133
  346. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.css +0 -1159
  347. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/01-module-runtime.js +0 -30
  348. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/02-react.js +0 -900
  349. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/03-react-dom-client-fiber-foundations.js +0 -2261
  350. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/04-react-dom-client-reconciliation-hooks.js +0 -1595
  351. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/05-react-dom-client-render-phases.js +0 -1467
  352. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/06-react-dom-client-commit-effects.js +0 -1860
  353. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/07-react-dom-client-work-loop-scheduling.js +0 -914
  354. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/08-react-dom-client-dom-events-properties-hydration.js +0 -2578
  355. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/09-react-dom-client-public-roots.js +0 -582
  356. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/10-react.js +0 -17
  357. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/11-artifact-review-ui.js +0 -12
  358. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/12-protocol-contracts.js +0 -285
  359. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/13-design-review-experience.js +0 -2773
  360. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/14-studio-shell.js +0 -134
  361. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/15-canvas-engine.js +0 -2207
  362. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/16-design-review-experience.js +0 -16
  363. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/17-studio-shell.js +0 -8
  364. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/18-interface-primitives.js +0 -3883
  365. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/19-interface-primitives.js +0 -966
  366. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/20-studio-shell.js +0 -520
  367. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/21-design-studio.js +0 -1597
  368. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources.json +0 -311
  369. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/package.json +0 -159
  370. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/registries/artifact-theme.json +0 -64
  371. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.0.0/design-manifest.schema.json +0 -90
  372. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-envelope.schema.json +0 -142
  373. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-paste.schema.json +0 -49
  374. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-review.schema.json +0 -97
  375. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-bundle.schema.json +0 -584
  376. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-context.schema.json +0 -191
  377. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-handoff.schema.json +0 -407
  378. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-metadata-payload.schema.json +0 -106
  379. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-handoff-readiness.schema.json +0 -398
  380. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-implementation-handoff.schema.json +0 -518
  381. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-planning-lineage.schema.json +0 -106
  382. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-review-metadata-payload.schema.json +0 -107
  383. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.14.0/artifact-theme.schema.json +0 -316
  384. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.16.0/artifact-envelope.schema.json +0 -408
  385. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.16.0/design-review-bundle.schema.json +0 -590
  386. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-document.schema.json +0 -506
  387. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-review-bundle.schema.json +0 -822
  388. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-review-bundle.schema.json +0 -346
  389. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-review-workspace.schema.json +0 -108
  390. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-workspace-create.schema.json +0 -170
  391. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-workspace-event.schema.json +0 -97
  392. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-workspace-revision.schema.json +0 -56
  393. package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/design-protocol-contracts.mjs +0 -5468
  394. package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/design.mjs +0 -2844
  395. package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +0 -21
  396. package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/runtime/packages/protocol/package.json +0 -159
  397. package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-review.schema.json +0 -97
  398. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-artifact-shell.mjs +0 -1774
  399. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-chunked-workspace-client.mjs +0 -555
  400. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-compression.mjs +0 -4180
  401. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-document.mjs +0 -2937
  402. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-encrypted-workspace-client.mjs +0 -647
  403. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-entities.mjs +0 -439
  404. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-handoff.mjs +0 -1576
  405. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-loopback-server.mjs +0 -359
  406. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-owner-custody.mjs +0 -129
  407. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-parse5-parser.mjs +0 -3970
  408. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-parse5-tokenizer.mjs +0 -3501
  409. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-resource-pack.mjs +0 -698
  410. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-review.mjs +0 -3385
  411. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-runtime-home.mjs +0 -39
  412. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-runtime-support-25485dbf1cb2.mjs +0 -24
  413. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-sandbox-guards.mjs +0 -1102
  414. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-share.mjs +0 -1993
  415. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-shared-artifact-support-dependencies-design-support-protocol-contracts-3d9b1a86.mjs +0 -1113
  416. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-shared-artifact-support-protocol-contracts-ea2cd15e.mjs +0 -505
  417. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-shared-protocol-contracts-75a938cc.mjs +0 -222
  418. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-shared-protocol-contracts-b5f28f94.mjs +0 -5907
  419. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-upload-spool.mjs +0 -198
  420. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design.mjs +0 -1430
  421. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +0 -2050
  422. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/lib/artifact/ui/studio-shell.css +0 -2
  423. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/01-module-runtime.js +0 -18
  424. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/02-artifact-review-ui.js +0 -809
  425. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/03-protocol-contracts.js +0 -5693
  426. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/04-compression.js +0 -4175
  427. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/05-artifact-sharing.js +0 -65
  428. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/06-artifact-review-ui.js +0 -1755
  429. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/07-artifact-sharing.js +0 -62
  430. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/08-artifact-review-ui.js +0 -2633
  431. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources.json +0 -124
  432. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/package.json +0 -65
  433. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/enhancements.css +0 -388
  434. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/handoff-center.css +0 -81
  435. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/share.css +0 -1
  436. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/share.js +0 -133
  437. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.css +0 -1159
  438. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/01-module-runtime.js +0 -30
  439. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/02-react.js +0 -900
  440. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/03-react-dom-client-fiber-foundations.js +0 -2261
  441. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/04-react-dom-client-reconciliation-hooks.js +0 -1595
  442. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/05-react-dom-client-render-phases.js +0 -1467
  443. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/06-react-dom-client-commit-effects.js +0 -1860
  444. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/07-react-dom-client-work-loop-scheduling.js +0 -914
  445. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/08-react-dom-client-dom-events-properties-hydration.js +0 -2578
  446. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/09-react-dom-client-public-roots.js +0 -582
  447. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/10-react.js +0 -17
  448. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/11-artifact-review-ui.js +0 -12
  449. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/12-protocol-contracts.js +0 -285
  450. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/13-design-review-experience.js +0 -2773
  451. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/14-studio-shell.js +0 -134
  452. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/15-canvas-engine.js +0 -2207
  453. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/16-design-review-experience.js +0 -16
  454. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/17-studio-shell.js +0 -8
  455. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/18-interface-primitives.js +0 -3883
  456. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/19-interface-primitives.js +0 -966
  457. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/20-studio-shell.js +0 -520
  458. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/21-design-studio.js +0 -1597
  459. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources.json +0 -311
  460. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/package.json +0 -159
  461. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/registries/artifact-theme.json +0 -64
  462. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.0.0/design-manifest.schema.json +0 -90
  463. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-envelope.schema.json +0 -142
  464. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-paste.schema.json +0 -49
  465. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-review.schema.json +0 -97
  466. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-bundle.schema.json +0 -584
  467. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-context.schema.json +0 -191
  468. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-handoff.schema.json +0 -407
  469. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-metadata-payload.schema.json +0 -106
  470. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-handoff-readiness.schema.json +0 -398
  471. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-implementation-handoff.schema.json +0 -518
  472. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-planning-lineage.schema.json +0 -106
  473. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-review-metadata-payload.schema.json +0 -107
  474. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.14.0/artifact-theme.schema.json +0 -316
  475. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.16.0/artifact-envelope.schema.json +0 -408
  476. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.16.0/design-review-bundle.schema.json +0 -590
  477. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-document.schema.json +0 -506
  478. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-review-bundle.schema.json +0 -822
  479. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-review-bundle.schema.json +0 -346
  480. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-review-workspace.schema.json +0 -108
  481. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-workspace-create.schema.json +0 -170
  482. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-workspace-event.schema.json +0 -97
  483. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-workspace-revision.schema.json +0 -56
  484. package/lib/host-packages/openai/openplanr/runtime/plan/scripts/design-protocol-contracts.mjs +0 -5468
  485. package/lib/host-packages/openai/openplanr/runtime/plan/scripts/design.mjs +0 -2844
  486. package/lib/host-packages/openai/openplanr/runtime/plan/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +0 -21
  487. package/lib/host-packages/openai/openplanr/runtime/plan/scripts/runtime/packages/protocol/package.json +0 -159
  488. package/lib/host-packages/openai/openplanr/runtime/plan/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-review.schema.json +0 -97
  489. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/integration-transaction.mjs +0 -958
  490. package/lib/host-packages/openai/openplanr/skills/design/scripts/design.mjs +0 -12
  491. package/lib/host-packages/openai/openplanr/skills/design-loop/scripts/design.mjs +0 -12
  492. package/lib/host-packages/openai/openplanr/skills/design-review/scripts/design.mjs +0 -12
  493. package/lib/host-packages/openai/openplanr/skills/plan/scripts/design.mjs +0 -12
@@ -1,1993 +0,0 @@
1
- import {
2
- assertDesignReviewBundle,
3
- assertDesignReviewMetadata,
4
- atomicJson,
5
- bundleDesignRevision,
6
- currentDesign,
7
- hash,
8
- readJson
9
- } from "./design-shared-artifact-support-dependencies-design-support-protocol-contracts-3d9b1a86.mjs";
10
- import {
11
- createEncryptedWorkspaceClient,
12
- createWorkspaceAddress
13
- } from "./design-encrypted-workspace-client.mjs";
14
- import {
15
- copyUploadSpool,
16
- persistUploadSpool,
17
- spoolChunkReader
18
- } from "./design-upload-spool.mjs";
19
- import {
20
- createChunkedWorkspaceClient
21
- } from "./design-chunked-workspace-client.mjs";
22
- import {
23
- PLANNING_FOLDER,
24
- ensurePrivateDirectory,
25
- readCustody,
26
- writeCustody
27
- } from "./design-owner-custody.mjs";
28
- import {
29
- configuredPlanrHome,
30
- planrHome
31
- } from "./design-runtime-home.mjs";
32
- import {
33
- acquireStartLock
34
- } from "./design-loopback-server.mjs";
35
- import {
36
- ARTIFACT_ERROR_CODES,
37
- PipelineError,
38
- canonicalSerialize,
39
- digestArtifactEnvelope,
40
- validateArtifactEnvelope,
41
- validateArtifactReview
42
- } from "./design-shared-artifact-support-protocol-contracts-ea2cd15e.mjs";
43
- import {
44
- DESIGN_WORKSPACE_API,
45
- DESIGN_WORKSPACE_CREATE_SCHEMA,
46
- DESIGN_WORKSPACE_EVENT_SCHEMA,
47
- DESIGN_WORKSPACE_MAX_BYTES,
48
- DESIGN_WORKSPACE_MAX_EVENT_BYTES,
49
- DESIGN_WORKSPACE_REVISION_SCHEMA,
50
- DESIGN_WORKSPACE_SCHEMA,
51
- DESIGN_WORKSPACE_VERSION,
52
- assertWorkspaceContract
53
- } from "./design-shared-protocol-contracts-b5f28f94.mjs";
54
- import {
55
- canonicalizeJson,
56
- deepFreeze,
57
- sha256Hex
58
- } from "./design-shared-protocol-contracts-75a938cc.mjs";
59
-
60
- // packages/design/lib/design/share-status.mjs
61
- import { existsSync, realpathSync } from "node:fs";
62
- import { homedir } from "node:os";
63
- import { dirname, isAbsolute, join, relative, resolve } from "node:path";
64
-
65
- // packages/design/lib/design/workspace-address.mjs
66
- var DESIGN_SHARE_BASE_URL = "https://share.openplanr.dev";
67
- var DESIGN_SHARE_REVIEW_PATH = "/d";
68
- var address = createWorkspaceAddress({
69
- label: "Design",
70
- reviewPath: DESIGN_SHARE_REVIEW_PATH,
71
- defaultBaseUrl: DESIGN_SHARE_BASE_URL
72
- });
73
- var normalizeWorkspaceBase = address.normalizeWorkspaceBase;
74
- var workspaceReviewUrl = (access) => `${address.workspaceReviewUrl(access)}${access.schemaVersion === "2.0.0" ? "?v=2" : ""}`;
75
-
76
- // packages/design/lib/design/share-status.mjs
77
- var FORMAT = "openplanr-design-owner-custody";
78
- function custodyLocation(file, options = {}, { allowMissing = false } = {}) {
79
- const current = currentDesign(file, options);
80
- const env = options.env ?? process.env;
81
- const root = resolve(options.custodyRoot ?? join(planrHome(env), "design-shares"));
82
- let project = current.root;
83
- for (let candidate = current.root; dirname(candidate) !== candidate; candidate = dirname(candidate)) {
84
- if (existsSync(join(candidate, ".git")) || existsSync(join(candidate, PLANNING_FOLDER))) {
85
- project = candidate;
86
- break;
87
- }
88
- }
89
- const key = hash(`${current.root}
90
- ${current.document.id}`);
91
- const path = join(root, `${key}.json`);
92
- const within = relative(project, root);
93
- if ((!allowMissing || existsSync(path)) && (within === "" || !within.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) && within !== ".." && !isAbsolute(within)))
94
- throw new Error(
95
- "Design owner keys must be stored outside the project. Set PLANR_HOME to a private user-level directory."
96
- );
97
- const legacyPath = !options.custodyRoot && !configuredPlanrHome(env) ? join(realpathSync(env.HOME || homedir()), ".openplanr", "design-shares", `${key}.json`) : null;
98
- return { root, path, current, legacyPath };
99
- }
100
- function presentationFingerprint(current, { legacy = false } = {}) {
101
- const state = readJson(join(current.root, ".design/studio-state.json"), { state: {} }).state;
102
- return hash(
103
- JSON.stringify({
104
- revision: current.revision,
105
- selectedVariant: state.selectedVariant ?? current.document.selectedVariant,
106
- ...legacy ? { positions: state.positions ?? {} } : {},
107
- verification: current.verification.status
108
- })
109
- );
110
- }
111
- var safeStatus = (record, current) => ({
112
- ok: true,
113
- shared: Boolean(record),
114
- title: current.document.title,
115
- localRevision: current.revision,
116
- retention: "until-revoked",
117
- ...record ? {
118
- id: record.custody.id,
119
- url: workspaceReviewUrl(record.custody),
120
- revision: record.custody.currentRevision ?? record.publishedRevision ?? null,
121
- publishedRevision: record.publishedRevision ?? null,
122
- hasUpdate: record.publishedRevision !== current.revision || ![
123
- presentationFingerprint(current),
124
- presentationFingerprint(current, { legacy: true })
125
- ].includes(record.publishedPresentation),
126
- epoch: record.custody.epoch,
127
- commentsPaused: Boolean(record.custody.commentsPaused ?? record.commentsPaused),
128
- revoked: Boolean(record.revoked),
129
- deleted: Boolean(record.deleted),
130
- pending: Boolean(
131
- record.custody.pendingCreate || record.custody.pendingMutation || record.pendingReviewMetadata?.length
132
- ),
133
- pendingAction: record.custody.pendingCreate ? "create" : record.custody.pendingMutation?.action ?? (record.pendingReviewMetadata?.length ? "review-metadata" : null),
134
- pendingReviewMetadata: Boolean(record.pendingReviewMetadata?.length)
135
- } : {}
136
- });
137
- function getDesignShareStatus(file, options = {}) {
138
- const { path, current, legacyPath } = custodyLocation(file, options);
139
- const record = readCustody(path, { label: "Design", format: FORMAT }) ?? (legacyPath ? readCustody(legacyPath, { label: "Design", format: FORMAT }) : null);
140
- return safeStatus(record, current);
141
- }
142
-
143
- // packages/design/lib/design/share.mjs
144
- import {
145
- closeSync,
146
- existsSync as existsSync4,
147
- fsyncSync,
148
- linkSync,
149
- mkdirSync as mkdirSync3,
150
- openSync,
151
- unlinkSync,
152
- writeFileSync as writeFileSync3
153
- } from "node:fs";
154
- import { basename, dirname as dirname4, join as join3, resolve as resolve3 } from "node:path";
155
-
156
- // packages/artifact/lib/artifact/import.mjs
157
- import {
158
- existsSync as existsSync3,
159
- lstatSync as lstatSync2,
160
- mkdirSync as mkdirSync2,
161
- readFileSync as readFileSync2,
162
- realpathSync as realpathSync2,
163
- renameSync as renameSync2,
164
- rmSync as rmSync2,
165
- statSync as statSync2,
166
- writeFileSync as writeFileSync2
167
- } from "node:fs";
168
- import { homedir as homedir2 } from "node:os";
169
- import { dirname as dirname3, isAbsolute as isAbsolute2, join as join2, relative as relative2, resolve as resolve2 } from "node:path";
170
-
171
- // packages/artifact/lib/artifact/internal/feedback.mjs
172
- var FEEDBACK_FILE = "feedback.json";
173
-
174
- // packages/artifact/lib/artifact/merge.mjs
175
- var ARTIFACT_REVIEW_STATE_VERSION = "1.0.0";
176
- var ARTIFACT_REVIEW_STATE_KIND = "artifact-review-state";
177
- var SHA256_RE = /^[a-f0-9]{64}$/;
178
- var ARTIFACT_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
179
- function conflict(message, details = void 0) {
180
- throw new PipelineError(
181
- ARTIFACT_ERROR_CODES.MERGE_CONFLICT,
182
- message,
183
- "Keep both reviews under different stable IDs or resolve the conflicting item explicitly.",
184
- details
185
- );
186
- }
187
- function assertUniqueReviewItemIds(review) {
188
- const pinIds = /* @__PURE__ */ new Set();
189
- for (const pin of review.pins ?? []) {
190
- if (pinIds.has(pin.id)) {
191
- throw new PipelineError(
192
- ARTIFACT_ERROR_CODES.REVIEW_INVALID,
193
- "Artifact review contains a duplicate pin ID."
194
- );
195
- }
196
- pinIds.add(pin.id);
197
- const replyIds = /* @__PURE__ */ new Set();
198
- for (const reply of pin.replies ?? []) {
199
- if (replyIds.has(reply.id)) {
200
- throw new PipelineError(
201
- ARTIFACT_ERROR_CODES.REVIEW_INVALID,
202
- "Artifact review contains a duplicate reply ID in one thread."
203
- );
204
- }
205
- replyIds.add(reply.id);
206
- }
207
- }
208
- return review;
209
- }
210
- function clone(value) {
211
- return structuredClone(value);
212
- }
213
- function same(a, b) {
214
- return canonicalSerialize(a) === canonicalSerialize(b);
215
- }
216
- function timeValue(value) {
217
- if (typeof value !== "string") return Number.NEGATIVE_INFINITY;
218
- const parsed = Date.parse(value);
219
- return Number.isFinite(parsed) ? parsed : Number.NEGATIVE_INFINITY;
220
- }
221
- function compareStable(a, b, idKey) {
222
- const aTime = a.createdAt ?? a.updatedAt ?? "";
223
- const bTime = b.createdAt ?? b.updatedAt ?? "";
224
- return aTime.localeCompare(bTime) || String(a[idKey]).localeCompare(String(b[idKey]));
225
- }
226
- function replyMap(replies) {
227
- const map = /* @__PURE__ */ new Map();
228
- for (const reply of replies ?? []) {
229
- const previous = map.get(reply.id);
230
- if (previous && !same(previous, reply)) {
231
- conflict("A reply ID refers to different immutable reply content.", { entity: "reply" });
232
- }
233
- map.set(reply.id, clone(reply));
234
- }
235
- return map;
236
- }
237
- function mergeReplies(stored = [], incoming = []) {
238
- const merged = replyMap(stored);
239
- for (const reply of incoming) {
240
- const previous = merged.get(reply.id);
241
- if (previous && !same(previous, reply)) {
242
- conflict("A reply ID refers to different immutable reply content.", { entity: "reply" });
243
- }
244
- if (!previous) merged.set(reply.id, clone(reply));
245
- }
246
- return [...merged.values()].sort((a, b) => compareStable(a, b, "id"));
247
- }
248
- var immutablePin = (pin) => ({
249
- id: pin.id,
250
- author: pin.author,
251
- artifactId: pin.artifactId,
252
- ...pin.variant === void 0 ? {} : { variant: pin.variant },
253
- region: pin.region,
254
- viewport: pin.viewport,
255
- ...pin.anchor === void 0 ? {} : { anchor: pin.anchor },
256
- createdAt: pin.createdAt
257
- });
258
- var mutablePin = (pin) => ({
259
- intent: pin.intent,
260
- status: pin.status,
261
- comment: pin.comment
262
- });
263
- function mergePin(stored, incoming) {
264
- if (!same(immutablePin(stored), immutablePin(incoming))) {
265
- conflict("A pin ID refers to different immutable geometry, author, or artifact content.", {
266
- entity: "pin"
267
- });
268
- }
269
- const replies = mergeReplies(stored.replies, incoming.replies);
270
- const storedTime = timeValue(stored.updatedAt);
271
- const incomingTime = timeValue(incoming.updatedAt);
272
- let selected = stored;
273
- if (incomingTime > storedTime) selected = incoming;
274
- if (incomingTime === storedTime && !same(mutablePin(stored), mutablePin(incoming))) {
275
- conflict("A pin has divergent mutable content at the same update time.", { entity: "pin" });
276
- }
277
- return { ...clone(selected), replies };
278
- }
279
- function mergePins(stored = [], incoming = []) {
280
- const merged = /* @__PURE__ */ new Map();
281
- for (const pin of stored) merged.set(pin.id, clone(pin));
282
- for (const pin of incoming) {
283
- const previous = merged.get(pin.id);
284
- merged.set(pin.id, previous ? mergePin(previous, pin) : clone(pin));
285
- }
286
- return [...merged.values()].sort((a, b) => compareStable(a, b, "id"));
287
- }
288
- var immutableReview = (review) => ({
289
- schemaVersion: review.schemaVersion,
290
- reviewId: review.reviewId,
291
- reviewOf: review.reviewOf,
292
- ...review.createdAt === void 0 ? {} : { createdAt: review.createdAt }
293
- });
294
- var mutableReview = (review) => ({ decision: review.decision, overall: review.overall });
295
- function mergeArtifactReviews(stored, incoming) {
296
- validateArtifactReview(stored);
297
- validateArtifactReview(incoming);
298
- assertUniqueReviewItemIds(stored);
299
- assertUniqueReviewItemIds(incoming);
300
- if (stored.reviewId !== incoming.reviewId) {
301
- conflict("Only reviews with the same review ID can be revision-merged.", {
302
- entity: "review"
303
- });
304
- }
305
- if (same(stored, incoming)) return stored;
306
- if (!same(immutableReview(stored), immutableReview(incoming))) {
307
- conflict("A review ID refers to a different digest or creation identity.", {
308
- entity: "review"
309
- });
310
- }
311
- const storedTime = timeValue(stored.updatedAt);
312
- const incomingTime = timeValue(incoming.updatedAt);
313
- let selected = stored;
314
- if (incomingTime > storedTime) selected = incoming;
315
- if (incomingTime === storedTime && !same(mutableReview(stored), mutableReview(incoming))) {
316
- conflict("A review has divergent verdict or overall feedback at the same update time.", {
317
- entity: "review"
318
- });
319
- }
320
- const merged = {
321
- ...clone(selected),
322
- pins: mergePins(stored.pins, incoming.pins)
323
- };
324
- validateArtifactReview(merged);
325
- return merged;
326
- }
327
- function validateReviewLedger(ledger) {
328
- if (!ledger || typeof ledger !== "object" || Array.isArray(ledger) || ledger.schemaVersion !== ARTIFACT_REVIEW_STATE_VERSION || ledger.kind !== ARTIFACT_REVIEW_STATE_KIND || !ARTIFACT_ID_RE.test(ledger.artifactId ?? "") || !SHA256_RE.test(ledger.currentReviewOf ?? "") || !Array.isArray(ledger.reviews)) {
329
- throw new PipelineError(
330
- ARTIFACT_ERROR_CODES.REVIEW_INVALID,
331
- "Artifact review state is not a valid versioned review ledger."
332
- );
333
- }
334
- const ids = /* @__PURE__ */ new Set();
335
- for (const entry of ledger.reviews) {
336
- if (!entry || typeof entry !== "object" || Array.isArray(entry) || typeof entry.stale !== "boolean" || !entry.review) {
337
- throw new PipelineError(
338
- ARTIFACT_ERROR_CODES.REVIEW_INVALID,
339
- "Artifact review ledger entry is invalid."
340
- );
341
- }
342
- validateArtifactReview(entry.review);
343
- assertUniqueReviewItemIds(entry.review);
344
- if (ids.has(entry.review.reviewId)) {
345
- throw new PipelineError(
346
- ARTIFACT_ERROR_CODES.REVIEW_INVALID,
347
- "Artifact review ledger IDs must be unique."
348
- );
349
- }
350
- ids.add(entry.review.reviewId);
351
- }
352
- return ledger;
353
- }
354
- function createReviewLedger({ artifactId, currentReviewOf, reviews = [] } = {}) {
355
- const ledger = {
356
- schemaVersion: ARTIFACT_REVIEW_STATE_VERSION,
357
- kind: ARTIFACT_REVIEW_STATE_KIND,
358
- artifactId,
359
- currentReviewOf,
360
- reviews: reviews.map((entry) => ({ review: clone(entry.review), stale: Boolean(entry.stale) }))
361
- };
362
- ledger.reviews.sort((a, b) => compareStable(a.review, b.review, "reviewId"));
363
- return validateReviewLedger(ledger);
364
- }
365
- function mergeReviewLedger(ledger, incoming, { stale = false } = {}) {
366
- validateReviewLedger(ledger);
367
- const reviews = Array.isArray(incoming) ? incoming : [incoming];
368
- const byId = new Map(
369
- ledger.reviews.map((entry) => [
370
- entry.review.reviewId,
371
- {
372
- review: clone(entry.review),
373
- stale: entry.stale
374
- }
375
- ])
376
- );
377
- for (const review of reviews) {
378
- validateArtifactReview(review);
379
- const previous = byId.get(review.reviewId);
380
- if (previous) {
381
- byId.set(review.reviewId, {
382
- review: mergeArtifactReviews(previous.review, review),
383
- stale: previous.stale || Boolean(stale)
384
- });
385
- } else {
386
- byId.set(review.reviewId, { review: clone(review), stale: Boolean(stale) });
387
- }
388
- }
389
- const merged = createReviewLedger({
390
- artifactId: ledger.artifactId,
391
- currentReviewOf: ledger.currentReviewOf,
392
- reviews: [...byId.values()]
393
- });
394
- return same(ledger, merged) ? ledger : merged;
395
- }
396
- function effectiveReviewDecision(value) {
397
- const entries = Array.isArray(value) ? value : value?.reviews ?? [];
398
- const decisions = entries.map((entry) => entry.review?.decision ?? entry.decision);
399
- if (decisions.includes("changes_requested")) return "changes_requested";
400
- if (decisions.includes("pending")) return "pending";
401
- return decisions.length > 0 && decisions.every((decision) => decision === "approved") ? "approved" : "pending";
402
- }
403
-
404
- // packages/artifact/lib/artifact/review.mjs
405
- import { randomBytes, randomUUID } from "node:crypto";
406
- import {
407
- existsSync as existsSync2,
408
- lstatSync,
409
- mkdirSync,
410
- readFileSync,
411
- renameSync,
412
- rmSync,
413
- statSync,
414
- writeFileSync
415
- } from "node:fs";
416
- import { dirname as dirname2 } from "node:path";
417
- var ARTIFACT_REVIEW_MAX_STATE_BYTES = 5 * 1024 * 1024;
418
- var reviewPathQueues = /* @__PURE__ */ new Map();
419
- function finalEntry(path, fs = { lstatSync }) {
420
- try {
421
- return fs.lstatSync(path);
422
- } catch (error) {
423
- if (error?.code === "ENOENT") return null;
424
- throw error;
425
- }
426
- }
427
- function clone2(value) {
428
- return structuredClone(value);
429
- }
430
- function canonicalObject(value) {
431
- if (Array.isArray(value)) return value.map(canonicalObject);
432
- if (!value || typeof value !== "object") return value;
433
- return Object.fromEntries(
434
- Object.keys(value).sort().map((key) => [key, canonicalObject(value[key])])
435
- );
436
- }
437
- function stableItemSort(a, b) {
438
- return String(a.createdAt ?? a.updatedAt ?? "").localeCompare(
439
- String(b.createdAt ?? b.updatedAt ?? "")
440
- ) || String(a.id ?? a.reviewId).localeCompare(String(b.id ?? b.reviewId));
441
- }
442
- function normalizeArtifactReview(review) {
443
- let normalized;
444
- try {
445
- normalized = clone2(review);
446
- } catch {
447
- throw new PipelineError(
448
- ARTIFACT_ERROR_CODES.REVIEW_INVALID,
449
- "Artifact review is not cloneable."
450
- );
451
- }
452
- try {
453
- validateArtifactReview(normalized);
454
- assertUniqueReviewItemIds(normalized);
455
- } catch (error) {
456
- if (error instanceof PipelineError) {
457
- throw new PipelineError(
458
- ARTIFACT_ERROR_CODES.REVIEW_INVALID,
459
- "Artifact review does not satisfy the Protocol v1.1 review contract.",
460
- "",
461
- { issues: error.details?.issues ?? [] }
462
- );
463
- }
464
- throw error;
465
- }
466
- normalized.pins = normalized.pins.map((pin) => ({
467
- ...pin,
468
- replies: [...pin.replies].sort(stableItemSort)
469
- })).sort(stableItemSort);
470
- validateArtifactReview(normalized);
471
- return normalized;
472
- }
473
- function serializeReviewState(value) {
474
- const normalized = value?.kind === "artifact-review-state" ? validateReviewLedger(clone2(value)) : normalizeArtifactReview(value);
475
- return `${JSON.stringify(canonicalObject(normalized), null, 2)}
476
- `;
477
- }
478
- function readArtifactReviewState(path, { allowMissing = false } = {}) {
479
- const entry = finalEntry(path);
480
- if (!entry) {
481
- if (allowMissing) return null;
482
- throw new PipelineError(
483
- ARTIFACT_ERROR_CODES.REVIEW_IMPORT,
484
- "Artifact review state does not exist."
485
- );
486
- }
487
- try {
488
- if (entry.isSymbolicLink() || !entry.isFile()) {
489
- throw new PipelineError(
490
- ARTIFACT_ERROR_CODES.SYMLINK_ESCAPE,
491
- "Artifact review state destination is not a regular file."
492
- );
493
- }
494
- if (statSync(path).size > ARTIFACT_REVIEW_MAX_STATE_BYTES) {
495
- throw new PipelineError(
496
- ARTIFACT_ERROR_CODES.REQUEST_LIMIT,
497
- `Artifact review state exceeds ${ARTIFACT_REVIEW_MAX_STATE_BYTES} bytes.`
498
- );
499
- }
500
- return validateReviewLedger(JSON.parse(readFileSync(path, "utf8")));
501
- } catch (error) {
502
- if (error instanceof PipelineError) throw error;
503
- throw new PipelineError(
504
- ARTIFACT_ERROR_CODES.REVIEW_INVALID,
505
- "Artifact review state is malformed."
506
- );
507
- }
508
- }
509
- function writeArtifactReviewState(path, ledger, { fileSystem = {}, suffix = `${process.pid}.${randomBytes(8).toString("hex")}` } = {}) {
510
- validateReviewLedger(ledger);
511
- const fs = { existsSync: existsSync2, lstatSync, mkdirSync, writeFileSync, renameSync, rmSync, ...fileSystem };
512
- const temporary = `${path}.${suffix}.tmp`;
513
- const serialized = serializeReviewState(ledger);
514
- if (Buffer.byteLength(serialized, "utf8") > ARTIFACT_REVIEW_MAX_STATE_BYTES) {
515
- throw new PipelineError(
516
- ARTIFACT_ERROR_CODES.REQUEST_LIMIT,
517
- `Artifact review state exceeds ${ARTIFACT_REVIEW_MAX_STATE_BYTES} bytes.`
518
- );
519
- }
520
- try {
521
- const initial = finalEntry(path, fs);
522
- if (initial) {
523
- const target = initial;
524
- if (target.isSymbolicLink() || !target.isFile()) throw new Error("unsafe final target");
525
- }
526
- fs.mkdirSync(dirname2(path), { recursive: true, mode: 448 });
527
- fs.writeFileSync(temporary, serialized, { mode: 384, flag: "wx" });
528
- const final = finalEntry(path, fs);
529
- if (final) {
530
- const target = final;
531
- if (target.isSymbolicLink() || !target.isFile()) throw new Error("unsafe final target");
532
- }
533
- fs.renameSync(temporary, path);
534
- } catch {
535
- try {
536
- fs.rmSync(temporary, { force: true });
537
- } catch {
538
- }
539
- throw new PipelineError(
540
- ARTIFACT_ERROR_CODES.REVIEW_WRITE,
541
- "Artifact review state could not be written atomically.",
542
- "Check destination permissions and retry; the previous review state was left unchanged."
543
- );
544
- }
545
- return ledger;
546
- }
547
- function withArtifactReviewLock(path, action) {
548
- const previous = reviewPathQueues.get(path) ?? Promise.resolve();
549
- const run = async () => {
550
- let release;
551
- try {
552
- release = await acquireStartLock(`${path}.lock`, { timeout: 15e3, stale: 3e4 });
553
- return await action();
554
- } catch (error) {
555
- if (error instanceof PipelineError) throw error;
556
- throw new PipelineError(
557
- ARTIFACT_ERROR_CODES.REVIEW_WRITE,
558
- "Artifact review state is busy or its cross-process lock is unavailable.",
559
- "Wait for the active review write to finish, then retry."
560
- );
561
- } finally {
562
- release?.();
563
- }
564
- };
565
- const operation = previous.then(run, run);
566
- const tail = operation.then(
567
- () => void 0,
568
- () => void 0
569
- );
570
- reviewPathQueues.set(path, tail);
571
- tail.finally(() => {
572
- if (reviewPathQueues.get(path) === tail) reviewPathQueues.delete(path);
573
- });
574
- return operation;
575
- }
576
- function normalizedExportInput(value) {
577
- if (value?.kind === "artifact-review-state") return validateReviewLedger(clone2(value));
578
- if (value?.review && value?.artifacts) return normalizeArtifactReview(value.review);
579
- return normalizeArtifactReview(value);
580
- }
581
- function markdownText(value) {
582
- return String(value ?? "").replace(/\r\n?/g, "\n").trim();
583
- }
584
- function renderPinMarkdown(pin, number) {
585
- const region = `${pin.region.x}, ${pin.region.y}, ${pin.region.w}, ${pin.region.h}`;
586
- const lines = [
587
- `### ${number}. ${pin.intent.toUpperCase()} \xB7 ${pin.status}`,
588
- "",
589
- `- Pin: \`${pin.id}\``,
590
- `- Artifact: \`${pin.artifactId}\`${pin.variant ? ` \xB7 variant \`${pin.variant}\`` : ""}`,
591
- `- Author: ${pin.author.name}`,
592
- `- Region: \`${region}\` at ${pin.viewport.width}\xD7${pin.viewport.height}`,
593
- ...pin.anchor ? [
594
- `- Anchor: \`${pin.anchor.planrId}\`${pin.anchor.screen ? ` \xB7 screen \`${pin.anchor.screen}\`` : ""}`
595
- ] : [],
596
- `- Updated: ${pin.updatedAt}`,
597
- "",
598
- markdownText(pin.comment)
599
- ];
600
- if (pin.replies.length > 0) {
601
- lines.push("", "#### Thread", "");
602
- for (const reply of pin.replies) {
603
- lines.push(`- **${reply.author.name}** (${reply.createdAt}): ${markdownText(reply.comment)}`);
604
- }
605
- }
606
- return lines.join("\n");
607
- }
608
- function reviewMarkdown(review, headingLevel = 2, stale = false) {
609
- const mark = "#".repeat(headingLevel);
610
- const lines = [
611
- `${mark} Review ${review.reviewId}${stale ? " \xB7 STALE" : ""}`,
612
- "",
613
- `- Digest: \`${review.reviewOf}\``,
614
- `- Decision: **${review.decision}**`,
615
- `- Pins: ${review.pins.length}`,
616
- ...review.createdAt ? [`- Created: ${review.createdAt}`] : [],
617
- ...review.updatedAt ? [`- Updated: ${review.updatedAt}`] : [],
618
- "",
619
- `${mark}# Overall feedback`,
620
- "",
621
- markdownText(review.overall) || "_No overall feedback._"
622
- ];
623
- if (review.pins.length > 0) {
624
- lines.push("", `${mark}# Pins`, "");
625
- review.pins.forEach((pin, index) => lines.push(renderPinMarkdown(pin, index + 1), ""));
626
- if (lines.at(-1) === "") lines.pop();
627
- }
628
- return lines.join("\n");
629
- }
630
- function exportArtifactReview(value, { format = "json" } = {}) {
631
- let normalized;
632
- try {
633
- normalized = normalizedExportInput(value);
634
- } catch (error) {
635
- if (error instanceof PipelineError) throw error;
636
- throw new PipelineError(
637
- ARTIFACT_ERROR_CODES.REVIEW_EXPORT,
638
- "Artifact review cannot be exported."
639
- );
640
- }
641
- if (format === "json") return serializeReviewState(normalized);
642
- if (format !== "markdown") {
643
- throw new PipelineError(
644
- ARTIFACT_ERROR_CODES.REVIEW_EXPORT,
645
- "Artifact review export format must be json or markdown."
646
- );
647
- }
648
- if (normalized.kind !== "artifact-review-state") {
649
- return `# OpenPlanr Artifact Review
650
-
651
- ${reviewMarkdown(normalized)}
652
- `;
653
- }
654
- const lines = [
655
- "# OpenPlanr Artifact Reviews",
656
- "",
657
- `- Artifact: \`${normalized.artifactId}\``,
658
- `- Current digest: \`${normalized.currentReviewOf}\``,
659
- `- Effective decision: **${effectiveReviewDecision(normalized)}**`,
660
- `- Reviews: ${normalized.reviews.length}`
661
- ];
662
- for (const entry of normalized.reviews) {
663
- lines.push("", reviewMarkdown(entry.review, 2, entry.stale));
664
- }
665
- return `${lines.join("\n")}
666
- `;
667
- }
668
-
669
- // packages/artifact/lib/artifact/import.mjs
670
- var ARTIFACT_ID_RE2 = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
671
- function pathError(code, message) {
672
- throw new PipelineError(
673
- code,
674
- message,
675
- "Choose a real, non-symlinked project or user review destination."
676
- );
677
- }
678
- function pathEntry(path, fs = { lstatSync: lstatSync2 }) {
679
- try {
680
- return fs.lstatSync(path);
681
- } catch (error) {
682
- if (error?.code === "ENOENT") return null;
683
- throw error;
684
- }
685
- }
686
- function inside(base, candidate) {
687
- const rel = relative2(base, candidate);
688
- return rel === "" || !rel.startsWith("..") && !isAbsolute2(rel);
689
- }
690
- function parseablePlanrConfig(root) {
691
- const path = join2(root, PLANNING_FOLDER, "config.json");
692
- if (!existsSync3(path)) return false;
693
- try {
694
- if (lstatSync2(path).isSymbolicLink()) return false;
695
- const value = JSON.parse(readFileSync2(path, "utf8"));
696
- return value && typeof value === "object" && !Array.isArray(value) && (typeof value.projectName === "string" && value.projectName.trim() !== "" || value.idPrefix && typeof value.idPrefix === "object" && !Array.isArray(value.idPrefix) && Object.keys(value.idPrefix).length > 0);
697
- } catch {
698
- return false;
699
- }
700
- }
701
- function hasGitMarker(root) {
702
- const marker = join2(root, ".git");
703
- if (!existsSync3(marker)) return false;
704
- try {
705
- const stat = lstatSync2(marker);
706
- if (stat.isSymbolicLink()) return false;
707
- if (stat.isDirectory()) {
708
- const head = join2(marker, "HEAD");
709
- return existsSync3(head) && lstatSync2(head).isFile();
710
- }
711
- if (!stat.isFile() || stat.size > 4096) return false;
712
- const match = /^gitdir:\s*(.+?)\s*$/u.exec(readFileSync2(marker, "utf8"));
713
- if (!match) return false;
714
- const gitDir = resolve2(root, match[1]);
715
- return existsSync3(gitDir) && statSync2(gitDir).isDirectory() && existsSync3(join2(gitDir, "HEAD")) && lstatSync2(join2(gitDir, "HEAD")).isFile();
716
- } catch {
717
- return false;
718
- }
719
- }
720
- function findArtifactProjectRoot(start = process.cwd(), { env = process.env } = {}) {
721
- let current;
722
- try {
723
- current = realpathSync2(resolve2(start));
724
- } catch {
725
- pathError(
726
- ARTIFACT_ERROR_CODES.REVIEW_IMPORT,
727
- "Artifact review working directory does not exist."
728
- );
729
- }
730
- const homeCandidate = resolve2(env.HOME ?? homedir2());
731
- let home = homeCandidate;
732
- try {
733
- home = realpathSync2(homeCandidate);
734
- } catch {
735
- }
736
- while (true) {
737
- if (current !== home && (parseablePlanrConfig(current) || hasGitMarker(current)))
738
- return current;
739
- const parent = dirname3(current);
740
- if (parent === current) return null;
741
- current = parent;
742
- }
743
- }
744
- function assertSafeDestination(base, relativeParts) {
745
- const absoluteBase = resolve2(base);
746
- if (existsSync3(absoluteBase) && lstatSync2(absoluteBase).isSymbolicLink()) {
747
- pathError(
748
- ARTIFACT_ERROR_CODES.SYMLINK_ESCAPE,
749
- "Artifact review destination base is a symlink."
750
- );
751
- }
752
- let realBase = absoluteBase;
753
- if (existsSync3(absoluteBase)) realBase = realpathSync2(absoluteBase);
754
- let current = absoluteBase;
755
- for (const part of relativeParts) {
756
- if (!part || part === "." || part === ".." || part.includes("/") || part.includes("\\") || part.includes("\0")) {
757
- pathError(
758
- ARTIFACT_ERROR_CODES.PATH_TRAVERSAL,
759
- "Artifact review destination contains an unsafe segment."
760
- );
761
- }
762
- current = join2(current, part);
763
- const entry = pathEntry(current);
764
- if (!entry) continue;
765
- if (entry.isSymbolicLink()) {
766
- pathError(
767
- ARTIFACT_ERROR_CODES.SYMLINK_ESCAPE,
768
- "Artifact review destination contains a symlink."
769
- );
770
- }
771
- if (!inside(realBase, realpathSync2(current))) {
772
- pathError(
773
- ARTIFACT_ERROR_CODES.PATH_TRAVERSAL,
774
- "Artifact review destination escapes its storage root."
775
- );
776
- }
777
- }
778
- if (!inside(absoluteBase, current)) {
779
- pathError(
780
- ARTIFACT_ERROR_CODES.PATH_TRAVERSAL,
781
- "Artifact review destination escapes its storage root."
782
- );
783
- }
784
- return current;
785
- }
786
- function resolveArtifactReviewDestination({
787
- cwd = process.cwd(),
788
- env = process.env,
789
- artifactId,
790
- designDir
791
- } = {}) {
792
- if (!ARTIFACT_ID_RE2.test(artifactId ?? "")) {
793
- pathError(
794
- ARTIFACT_ERROR_CODES.PATH_TRAVERSAL,
795
- "Artifact review ID is unsafe for local storage."
796
- );
797
- }
798
- if (designDir !== void 0) {
799
- const lexical = resolve2(designDir);
800
- if (!existsSync3(lexical) || !statSync2(lexical).isDirectory()) {
801
- pathError(ARTIFACT_ERROR_CODES.REVIEW_IMPORT, "Design review destination does not exist.");
802
- }
803
- if (lstatSync2(lexical).isSymbolicLink()) {
804
- pathError(
805
- ARTIFACT_ERROR_CODES.SYMLINK_ESCAPE,
806
- "Design review destination must be a real directory."
807
- );
808
- }
809
- const requested = realpathSync2(lexical);
810
- return Object.freeze({
811
- kind: "design",
812
- artifactId,
813
- directory: requested,
814
- path: join2(requested, FEEDBACK_FILE),
815
- reviewStatePath: join2(requested, "artifact-review-state.json")
816
- });
817
- }
818
- const projectRoot = findArtifactProjectRoot(cwd, { env });
819
- if (projectRoot) {
820
- const directory2 = assertSafeDestination(projectRoot, [
821
- PLANNING_FOLDER,
822
- "artifacts",
823
- artifactId
824
- ]);
825
- return Object.freeze({
826
- kind: "project",
827
- artifactId,
828
- root: projectRoot,
829
- directory: directory2,
830
- path: join2(directory2, "review-state.json")
831
- });
832
- }
833
- const root = resolve2(planrHome(env));
834
- const directory = assertSafeDestination(root, ["artifacts", artifactId]);
835
- return Object.freeze({
836
- kind: "user",
837
- artifactId,
838
- root,
839
- directory,
840
- path: join2(directory, "review-state.json")
841
- });
842
- }
843
- function reviewsFromDecoded(value) {
844
- if (!value || typeof value !== "object" || Array.isArray(value)) {
845
- throw new PipelineError(
846
- ARTIFACT_ERROR_CODES.REVIEW_IMPORT,
847
- "Decoded review payload is not an object."
848
- );
849
- }
850
- if (value.kind === "artifact-review-state") {
851
- validateReviewLedger(value);
852
- return value.reviews.map((entry) => ({ review: entry.review, stale: entry.stale }));
853
- }
854
- if (value.artifacts && value.viewer) {
855
- validateArtifactEnvelope(value);
856
- if (!value.review) {
857
- throw new PipelineError(
858
- ARTIFACT_ERROR_CODES.REVIEW_IMPORT,
859
- "Decoded artifact envelope contains no review."
860
- );
861
- }
862
- return [{ review: value.review, stale: false }];
863
- }
864
- if (value.review && !value.reviewId) return reviewsFromDecoded(value.review);
865
- validateArtifactReview(value);
866
- return [{ review: value, stale: false }];
867
- }
868
- async function decodeArtifactReviewSources(sources, { decodeSource, withMetadata = false } = {}) {
869
- const list = Array.isArray(sources) ? sources : [sources];
870
- if (list.length === 0) {
871
- throw new PipelineError(
872
- ARTIFACT_ERROR_CODES.REVIEW_IMPORT,
873
- "At least one artifact review source is required."
874
- );
875
- }
876
- const entries = [];
877
- for (let index = 0; index < list.length; index += 1) {
878
- const source = list[index];
879
- let decoded = source;
880
- if (typeof source === "string") {
881
- if (typeof decodeSource !== "function") {
882
- throw new PipelineError(
883
- ARTIFACT_ERROR_CODES.REVIEW_DECODER_REQUIRED,
884
- "String and URL review sources require an injected async decoder.",
885
- "Provide decodeSource(source, { index }); the review lifecycle has no transport dependency.",
886
- { sourceIndex: index }
887
- );
888
- }
889
- try {
890
- decoded = await decodeSource(source, { index });
891
- } catch {
892
- throw new PipelineError(
893
- ARTIFACT_ERROR_CODES.REVIEW_IMPORT,
894
- "Artifact review source could not be decoded.",
895
- "Verify the immutable review link and retry.",
896
- { sourceIndex: index }
897
- );
898
- }
899
- }
900
- try {
901
- entries.push(
902
- ...reviewsFromDecoded(decoded).map((entry) => ({
903
- review: structuredClone(entry.review),
904
- stale: Boolean(entry.stale)
905
- }))
906
- );
907
- } catch (error) {
908
- if (error instanceof PipelineError && error.code === ARTIFACT_ERROR_CODES.REVIEW_IMPORT) {
909
- error.details = { sourceIndex: index };
910
- throw error;
911
- }
912
- throw new PipelineError(
913
- ARTIFACT_ERROR_CODES.REVIEW_IMPORT,
914
- "Decoded artifact review does not satisfy the Protocol v1.1 contract.",
915
- "",
916
- { sourceIndex: index }
917
- );
918
- }
919
- }
920
- return withMetadata ? entries : entries.map((entry) => entry.review);
921
- }
922
-
923
- // packages/design/lib/design/workspace-client.mjs
924
- var encoder = new TextEncoder();
925
- var decoder = new TextDecoder("utf-8", { fatal: true });
926
- var PACKED_BUNDLE_KIND = "openplanr-design-review-bundle-packed";
927
- var PACKED_BUNDLE_MAX_BYTES = 128 * 1024 * 1024;
928
- var SHARED_BLOCK_MIN_LENGTH = 2048;
929
- var sharedBlockPattern = /(<(script|style)\b[^>]*>)([\s\S]*?)<\/\2\s*>/gi;
930
- async function deflateRaw(bytes) {
931
- const stream = new Blob([bytes]).stream().pipeThrough(new CompressionStream("deflate-raw"));
932
- return new Uint8Array(await new Response(stream).arrayBuffer());
933
- }
934
- async function inflateRaw(bytes, limit) {
935
- const reader = new Blob([bytes]).stream().pipeThrough(new DecompressionStream("deflate-raw")).getReader();
936
- const chunks = [];
937
- let size = 0;
938
- for (; ; ) {
939
- const { done, value } = await reader.read();
940
- if (done) break;
941
- size += value.byteLength;
942
- if (size > limit) {
943
- await reader.cancel();
944
- throw new RangeError("The shared design expands beyond its size limit.");
945
- }
946
- chunks.push(value);
947
- }
948
- const inflated = new Uint8Array(size);
949
- let offset = 0;
950
- for (const chunk of chunks) {
951
- inflated.set(chunk, offset);
952
- offset += chunk.byteLength;
953
- }
954
- return inflated;
955
- }
956
- async function packDesignReviewBundle(bundle) {
957
- if (bundle.envelope?.schemaVersion === "1.1.0")
958
- return {
959
- kind: PACKED_BUNDLE_KIND,
960
- version: 2,
961
- data: encodeWorkspaceBytes(await deflateRaw(encoder.encode(JSON.stringify(bundle))))
962
- };
963
- const pages = [];
964
- const pageIndex = /* @__PURE__ */ new Map();
965
- const blocks = [];
966
- const blockIndex = /* @__PURE__ */ new Map();
967
- const segmentsOf = (html) => {
968
- const segments = [];
969
- let offset = 0;
970
- for (const match of html.matchAll(sharedBlockPattern)) {
971
- const body = match[3];
972
- if (body.length < SHARED_BLOCK_MIN_LENGTH) continue;
973
- const start = match.index + match[1].length;
974
- segments.push(html.slice(offset, start));
975
- if (!blockIndex.has(body)) blockIndex.set(body, blocks.push(body) - 1);
976
- segments.push(blockIndex.get(body));
977
- offset = start + body.length;
978
- }
979
- segments.push(html.slice(offset));
980
- return segments;
981
- };
982
- const artifactPages = [];
983
- const artifacts = bundle.envelope.artifacts.map(({ html, ...artifact }) => {
984
- if (!pageIndex.has(html)) pageIndex.set(html, pages.push(segmentsOf(html)) - 1);
985
- artifactPages.push(pageIndex.get(html));
986
- return artifact;
987
- });
988
- const packed = {
989
- bundle: { ...bundle, envelope: { ...bundle.envelope, artifacts } },
990
- artifactPages,
991
- pages,
992
- blocks
993
- };
994
- return {
995
- kind: PACKED_BUNDLE_KIND,
996
- version: 1,
997
- data: encodeWorkspaceBytes(await deflateRaw(encoder.encode(JSON.stringify(packed))))
998
- };
999
- }
1000
- async function unpackDesignReviewBundle(value, { maxBytes = PACKED_BUNDLE_MAX_BYTES } = {}) {
1001
- if (value?.kind !== PACKED_BUNDLE_KIND) return value;
1002
- if (![1, 2].includes(value.version) || typeof value.data !== "string")
1003
- throw new Error("The shared design uses an unsupported packing.");
1004
- if (value.version === 2) {
1005
- const bundle2 = JSON.parse(
1006
- decoder.decode(await inflateRaw(decodeWorkspaceBytes(value.data), maxBytes))
1007
- );
1008
- return assertDesignReviewBundle(bundle2);
1009
- }
1010
- const { bundle, artifactPages, pages, blocks } = JSON.parse(
1011
- decoder.decode(await inflateRaw(decodeWorkspaceBytes(value.data), maxBytes))
1012
- );
1013
- const invalid2 = () => new Error("The shared design packing is invalid.");
1014
- if (!Array.isArray(bundle?.envelope?.artifacts) || !Array.isArray(pages) || !Array.isArray(blocks) || !Array.isArray(artifactPages) || artifactPages.length !== bundle.envelope.artifacts.length)
1015
- throw invalid2();
1016
- let expanded = 0;
1017
- const html = pages.map((segments) => {
1018
- if (!Array.isArray(segments)) throw invalid2();
1019
- const page = segments.map((segment) => {
1020
- if (typeof segment === "string") return segment;
1021
- if (!Number.isInteger(segment) || typeof blocks[segment] !== "string") throw invalid2();
1022
- return blocks[segment];
1023
- }).join("");
1024
- expanded += page.length;
1025
- if (expanded > maxBytes)
1026
- throw new RangeError("The shared design expands beyond its size limit.");
1027
- return page;
1028
- });
1029
- const artifacts = bundle.envelope.artifacts.map((artifact, index) => {
1030
- const page = html[artifactPages[index]];
1031
- if (page === void 0) throw invalid2();
1032
- return { ...artifact, html: page };
1033
- });
1034
- return { ...bundle, envelope: { ...bundle.envelope, artifacts } };
1035
- }
1036
- var client = createEncryptedWorkspaceClient({
1037
- domain: "openplanr-design-workspace/v1",
1038
- apiPath: DESIGN_WORKSPACE_API,
1039
- reviewPath: DESIGN_SHARE_REVIEW_PATH,
1040
- label: "Design",
1041
- defaultBaseUrl: DESIGN_SHARE_BASE_URL,
1042
- version: DESIGN_WORKSPACE_VERSION,
1043
- maxBytes: DESIGN_WORKSPACE_MAX_BYTES,
1044
- maxEventBytes: DESIGN_WORKSPACE_MAX_EVENT_BYTES,
1045
- schemas: {
1046
- create: DESIGN_WORKSPACE_CREATE_SCHEMA,
1047
- event: DESIGN_WORKSPACE_EVENT_SCHEMA,
1048
- revision: DESIGN_WORKSPACE_REVISION_SCHEMA,
1049
- workspace: DESIGN_WORKSPACE_SCHEMA
1050
- },
1051
- assertContract: assertWorkspaceContract,
1052
- assertBundle: assertDesignReviewBundle,
1053
- assertFeedback(payload) {
1054
- if (["category", "disposition"].includes(payload.kind)) assertDesignReviewMetadata(payload);
1055
- if (!["review", "direction", "category", "disposition"].includes(payload.kind))
1056
- throw new TypeError("Unknown design feedback kind.");
1057
- if (typeof payload.author !== "string" || !payload.author.trim() || payload.author.length > 160)
1058
- throw new TypeError("Enter your name before leaving feedback.");
1059
- return payload;
1060
- },
1061
- digestInput: (bundle) => bundle.envelope,
1062
- bundleDigest: (envelope) => sha256Hex(
1063
- canonicalizeJson({
1064
- schemaVersion: envelope.schemaVersion,
1065
- ...envelope.schemaVersion === "1.1.0" ? { sources: envelope.sources } : {},
1066
- artifacts: envelope.artifacts,
1067
- viewer: envelope.viewer
1068
- })
1069
- ),
1070
- packBundle: packDesignReviewBundle,
1071
- unpackBundle: unpackDesignReviewBundle
1072
- });
1073
- var {
1074
- encodeWorkspaceBytes,
1075
- decodeWorkspaceBytes,
1076
- newWorkspaceToken,
1077
- newWorkspaceId,
1078
- deriveWorkspaceAuthentication,
1079
- canonicalWorkspacePublicKey,
1080
- createWorkspaceSigner,
1081
- signWorkspaceValue,
1082
- verifyWorkspaceSignature,
1083
- workspaceEnvelopeDigest
1084
- } = client;
1085
- var chunked = createChunkedWorkspaceClient({
1086
- legacy: client,
1087
- domain: "openplanr-design-workspace/v1",
1088
- apiPath: DESIGN_WORKSPACE_API,
1089
- assertBundle: assertDesignReviewBundle,
1090
- assertFeedback: (payload) => {
1091
- if (["category", "disposition"].includes(payload.kind)) assertDesignReviewMetadata(payload);
1092
- if (!["review", "direction", "category", "disposition"].includes(payload.kind) || typeof payload.author !== "string" || !payload.author.trim() || payload.author.length > 160)
1093
- throw new TypeError("Invalid design feedback.");
1094
- return payload;
1095
- },
1096
- digestInput: (bundle) => bundle.envelope
1097
- });
1098
- var discoverWorkspaceCapabilities = chunked.capabilities;
1099
- var prepareChunkedWorkspace = chunked.prepareWorkspace;
1100
- var openWorkspaceRevision = chunked.openRevision;
1101
- var prepareWorkspace = (bundle, options = {}) => options.transport === "2" ? chunked.prepareWorkspace(bundle, options) : client.prepareWorkspace(bundle, options);
1102
- var commitWorkspace = (access, ...args) => (access.schemaVersion === "2.0.0" ? chunked : client).commitWorkspace(access, ...args);
1103
- var getWorkspace = (access, ...args) => (access.schemaVersion === "2.0.0" ? chunked : client).getWorkspace(access, ...args);
1104
- var decryptWorkspaceRevision = (access, ...args) => (access.schemaVersion === "2.0.0" ? chunked : client).decryptWorkspaceRevision(access, ...args);
1105
- var prepareWorkspaceMutation = (access, ...args) => (access.schemaVersion === "2.0.0" ? chunked : client).prepareWorkspaceMutation(access, ...args);
1106
- var commitWorkspaceMutation = (access, ...args) => (access.schemaVersion === "2.0.0" ? chunked : client).commitWorkspaceMutation(access, ...args);
1107
- var prepareWorkspaceEvent = (access, ...args) => (access.schemaVersion === "2.0.0" ? chunked : client).prepareWorkspaceEvent(access, ...args);
1108
- var appendWorkspaceEvent = (access, ...args) => (access.schemaVersion === "2.0.0" ? chunked : client).appendWorkspaceEvent(access, ...args);
1109
- var readWorkspaceEvents = (access, ...args) => (access.schemaVersion === "2.0.0" ? chunked : client).readWorkspaceEvents(access, ...args);
1110
-
1111
- // packages/artifact/lib/artifact/ui/annotations.mjs
1112
- var ARTIFACT_ANNOTATION_EVENTS = Object.freeze({
1113
- draft: "planr:artifact-annotation-draft",
1114
- focus: "planr:artifact-annotation-focus"
1115
- });
1116
- var ARTIFACT_ANNOTATION_LIMITS = Object.freeze({
1117
- dragThreshold: 4,
1118
- maxCommentLength: 65536,
1119
- maxIdentityLength: 256
1120
- });
1121
- var INTENTS = Object.freeze(["fix", "improve", "question"]);
1122
-
1123
- // packages/artifact/lib/artifact/ui/feedback-rail.mjs
1124
- var ARTIFACT_REVIEW_LIMITS = Object.freeze({
1125
- id: 128,
1126
- authorName: 256,
1127
- artifactId: 128,
1128
- variant: 128,
1129
- anchor: 512,
1130
- screen: 128,
1131
- text: 65536,
1132
- pins: 1e4,
1133
- replies: 1e4,
1134
- viewport: 16384
1135
- });
1136
- var ARTIFACT_REVIEW_DECISIONS = Object.freeze([
1137
- "pending",
1138
- "approved",
1139
- "changes_requested"
1140
- ]);
1141
- var ARTIFACT_REVIEW_INTENTS = Object.freeze(["fix", "improve", "question"]);
1142
- var ARTIFACT_REVIEW_STATUSES = Object.freeze(["open", "addressed", "resolved"]);
1143
- var REVIEW_OF_RE = /^[a-f0-9]{64}$/;
1144
- var ArtifactReviewStateError = class extends Error {
1145
- constructor(code, message) {
1146
- super(message);
1147
- this.name = "ArtifactReviewStateError";
1148
- this.code = code;
1149
- }
1150
- };
1151
- function invalid(message) {
1152
- throw new ArtifactReviewStateError("E_ARTIFACT_REVIEW_INVALID", message);
1153
- }
1154
- function identityRequired() {
1155
- throw new ArtifactReviewStateError(
1156
- "E_ARTIFACT_REVIEW_IDENTITY_REQUIRED",
1157
- "Enter your name before adding a comment."
1158
- );
1159
- }
1160
- function boundedString(value, label, { min = 0, max, trim = false, pattern } = {}) {
1161
- if (typeof value !== "string") invalid(`${label} must be a string.`);
1162
- const normalized = trim ? value.trim() : value;
1163
- if (normalized.length < min || max !== void 0 && normalized.length > max) {
1164
- invalid(`${label} must contain ${min} through ${max ?? "unlimited"} characters.`);
1165
- }
1166
- if (pattern && !pattern.test(normalized)) invalid(`${label} has an invalid format.`);
1167
- return normalized;
1168
- }
1169
- function optionalString(value, label, options) {
1170
- if (value === void 0) return void 0;
1171
- return boundedString(value, label, options);
1172
- }
1173
- function enumValue(value, values, label) {
1174
- if (!values.includes(value)) invalid(`${label} must be one of: ${values.join(", ")}.`);
1175
- return value;
1176
- }
1177
- function isoTimestamp(value, label) {
1178
- const timestamp = value instanceof Date ? value.toISOString() : value;
1179
- if (typeof timestamp !== "string" || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(timestamp) || !Number.isFinite(Date.parse(timestamp))) {
1180
- invalid(`${label} must be an ISO-8601 date-time.`);
1181
- }
1182
- return timestamp;
1183
- }
1184
- function normalizeArtifactReviewIdentity(value, { allowEmpty = false } = {}) {
1185
- if (value === null || value === void 0 || value === "") {
1186
- if (allowEmpty) return null;
1187
- identityRequired();
1188
- }
1189
- const source = typeof value === "string" ? { name: value } : value;
1190
- if (!source || typeof source !== "object" || Array.isArray(source)) identityRequired();
1191
- const name = boundedString(source.name, "author.name", {
1192
- min: 1,
1193
- max: ARTIFACT_REVIEW_LIMITS.authorName,
1194
- trim: true
1195
- });
1196
- const id = optionalString(source.id, "author.id", {
1197
- min: 1,
1198
- max: ARTIFACT_REVIEW_LIMITS.id,
1199
- trim: true
1200
- });
1201
- return deepFreeze(id === void 0 ? { name } : { id, name });
1202
- }
1203
- function normalizeRegion(region) {
1204
- if (!region || typeof region !== "object" || Array.isArray(region)) {
1205
- invalid("pin.region must be an object.");
1206
- }
1207
- const finite = (value, label) => {
1208
- if (typeof value !== "number" || !Number.isFinite(value)) invalid(`${label} must be finite.`);
1209
- return value;
1210
- };
1211
- const x = finite(region.x, "pin.region.x");
1212
- const y = finite(region.y, "pin.region.y");
1213
- const w = finite(region.w, "pin.region.w");
1214
- const h = finite(region.h, "pin.region.h");
1215
- if (x >= 0 && y >= 0 && w >= 0 && h >= 0 && x + w <= 1 && y + h <= 1) {
1216
- return { x, y, w, h };
1217
- }
1218
- const unit = (value) => Math.round(Math.min(1, Math.max(0, value)) * 1e6) / 1e6;
1219
- const boundedX = unit(x);
1220
- const boundedY = unit(y);
1221
- return {
1222
- x: boundedX,
1223
- y: boundedY,
1224
- w: Math.round(Math.min(unit(w), 1 - boundedX) * 1e6) / 1e6,
1225
- h: Math.round(Math.min(unit(h), 1 - boundedY) * 1e6) / 1e6
1226
- };
1227
- }
1228
- function normalizeViewport(viewport) {
1229
- if (!viewport || typeof viewport !== "object" || Array.isArray(viewport)) {
1230
- invalid("pin.viewport must be an object.");
1231
- }
1232
- const dimension = (value, label) => {
1233
- if (!Number.isInteger(value) || value < 1 || value > ARTIFACT_REVIEW_LIMITS.viewport) {
1234
- invalid(`${label} must be an integer from 1 through ${ARTIFACT_REVIEW_LIMITS.viewport}.`);
1235
- }
1236
- return value;
1237
- };
1238
- return {
1239
- width: dimension(viewport.width, "pin.viewport.width"),
1240
- height: dimension(viewport.height, "pin.viewport.height")
1241
- };
1242
- }
1243
- function normalizeAnchor(anchor) {
1244
- if (anchor === void 0 || anchor === null) return void 0;
1245
- if (typeof anchor !== "object" || Array.isArray(anchor)) invalid("pin.anchor must be an object.");
1246
- const planrId = boundedString(anchor.planrId, "pin.anchor.planrId", {
1247
- min: 1,
1248
- max: ARTIFACT_REVIEW_LIMITS.anchor,
1249
- trim: true
1250
- });
1251
- const screen = optionalString(anchor.screen, "pin.anchor.screen", {
1252
- min: 1,
1253
- max: ARTIFACT_REVIEW_LIMITS.screen,
1254
- trim: true
1255
- });
1256
- return screen === void 0 ? { planrId } : { planrId, screen };
1257
- }
1258
- function normalizeReply(reply, label = "reply") {
1259
- if (!reply || typeof reply !== "object" || Array.isArray(reply))
1260
- invalid(`${label} must be an object.`);
1261
- return {
1262
- id: boundedString(reply.id, `${label}.id`, {
1263
- min: 1,
1264
- max: ARTIFACT_REVIEW_LIMITS.id,
1265
- trim: true
1266
- }),
1267
- author: normalizeArtifactReviewIdentity(reply.author),
1268
- comment: boundedString(reply.comment, `${label}.comment`, {
1269
- min: 1,
1270
- max: ARTIFACT_REVIEW_LIMITS.text,
1271
- trim: true
1272
- }),
1273
- createdAt: isoTimestamp(reply.createdAt, `${label}.createdAt`)
1274
- };
1275
- }
1276
- function compareTimestampThenId(left, right) {
1277
- const byTime = left.createdAt.localeCompare(right.createdAt);
1278
- return byTime === 0 ? left.id.localeCompare(right.id) : byTime;
1279
- }
1280
- function normalizePin(pin, label = "pin") {
1281
- if (!pin || typeof pin !== "object" || Array.isArray(pin)) invalid(`${label} must be an object.`);
1282
- if (!Array.isArray(pin.replies) || pin.replies.length > ARTIFACT_REVIEW_LIMITS.replies) {
1283
- invalid(`${label}.replies must contain no more than ${ARTIFACT_REVIEW_LIMITS.replies} items.`);
1284
- }
1285
- const replies = pin.replies.map(
1286
- (reply, index) => normalizeReply(reply, `${label}.replies[${index}]`)
1287
- );
1288
- const replyIds = new Set(replies.map(({ id }) => id));
1289
- if (replyIds.size !== replies.length) invalid(`${label}.replies must have unique ids.`);
1290
- const normalized = {
1291
- id: boundedString(pin.id, `${label}.id`, {
1292
- min: 1,
1293
- max: ARTIFACT_REVIEW_LIMITS.id,
1294
- trim: true
1295
- }),
1296
- author: normalizeArtifactReviewIdentity(pin.author),
1297
- artifactId: boundedString(pin.artifactId, `${label}.artifactId`, {
1298
- min: 1,
1299
- max: ARTIFACT_REVIEW_LIMITS.artifactId,
1300
- trim: true
1301
- }),
1302
- region: normalizeRegion(pin.region),
1303
- viewport: normalizeViewport(pin.viewport),
1304
- intent: enumValue(pin.intent, ARTIFACT_REVIEW_INTENTS, `${label}.intent`),
1305
- status: enumValue(pin.status, ARTIFACT_REVIEW_STATUSES, `${label}.status`),
1306
- comment: boundedString(pin.comment, `${label}.comment`, {
1307
- min: 1,
1308
- max: ARTIFACT_REVIEW_LIMITS.text,
1309
- trim: true
1310
- }),
1311
- replies: replies.sort(compareTimestampThenId),
1312
- createdAt: isoTimestamp(pin.createdAt, `${label}.createdAt`),
1313
- updatedAt: isoTimestamp(pin.updatedAt, `${label}.updatedAt`)
1314
- };
1315
- const variant = optionalString(pin.variant, `${label}.variant`, {
1316
- min: 1,
1317
- max: ARTIFACT_REVIEW_LIMITS.variant,
1318
- trim: true
1319
- });
1320
- const anchor = normalizeAnchor(pin.anchor);
1321
- if (variant !== void 0) normalized.variant = variant;
1322
- if (anchor !== void 0) normalized.anchor = anchor;
1323
- return normalized;
1324
- }
1325
- function normalizeArtifactReview2(review) {
1326
- if (!review || typeof review !== "object" || Array.isArray(review)) {
1327
- invalid("Artifact review must be an object.");
1328
- }
1329
- if (!Array.isArray(review.pins) || review.pins.length > ARTIFACT_REVIEW_LIMITS.pins) {
1330
- invalid(`review.pins must contain no more than ${ARTIFACT_REVIEW_LIMITS.pins} items.`);
1331
- }
1332
- const pins = review.pins.map((pin, index) => normalizePin(pin, `review.pins[${index}]`));
1333
- const pinIds = new Set(pins.map(({ id }) => id));
1334
- if (pinIds.size !== pins.length) invalid("review.pins must have unique ids.");
1335
- const normalized = {
1336
- schemaVersion: enumValue(review.schemaVersion, ["1.0.0"], "review.schemaVersion"),
1337
- reviewId: boundedString(review.reviewId, "review.reviewId", {
1338
- min: 1,
1339
- max: ARTIFACT_REVIEW_LIMITS.id,
1340
- trim: true
1341
- }),
1342
- reviewOf: boundedString(review.reviewOf, "review.reviewOf", {
1343
- min: 64,
1344
- max: 64,
1345
- pattern: REVIEW_OF_RE
1346
- }),
1347
- decision: enumValue(review.decision, ARTIFACT_REVIEW_DECISIONS, "review.decision"),
1348
- overall: boundedString(review.overall, "review.overall", {
1349
- max: ARTIFACT_REVIEW_LIMITS.text
1350
- }),
1351
- pins: pins.sort(compareTimestampThenId)
1352
- };
1353
- if (review.createdAt !== void 0)
1354
- normalized.createdAt = isoTimestamp(review.createdAt, "review.createdAt");
1355
- if (review.updatedAt !== void 0)
1356
- normalized.updatedAt = isoTimestamp(review.updatedAt, "review.updatedAt");
1357
- return deepFreeze(normalized);
1358
- }
1359
-
1360
- // packages/design/lib/design/workspace-feedback.mjs
1361
- function workspaceReviewerId(publicKey) {
1362
- return sha256Hex(
1363
- canonicalizeJson({ kty: publicKey.kty, crv: publicKey.crv, x: publicKey.x, y: publicKey.y })
1364
- );
1365
- }
1366
- function mergeWorkspaceFeedback(events, { revisionId, reviewOf, ownerPublicKey } = {}) {
1367
- if (!Array.isArray(events) || !revisionId || !/^[a-f0-9]{64}$/u.test(reviewOf))
1368
- throw new TypeError("Feedback merge requires a revision and content digest.");
1369
- const pins = /* @__PURE__ */ new Map();
1370
- const pinOwners = /* @__PURE__ */ new Map();
1371
- const replyOwners = /* @__PURE__ */ new Map();
1372
- const overall = /* @__PURE__ */ new Map();
1373
- const directions = /* @__PURE__ */ new Map();
1374
- const seen = /* @__PURE__ */ new Map();
1375
- const revisionBases = /* @__PURE__ */ new Map();
1376
- const acceptedEventIds = [];
1377
- const issues = [];
1378
- const categories = {}, dispositions = {};
1379
- for (const event of [...events].sort((a, b) => a.sequence - b.sequence)) {
1380
- try {
1381
- if (!event || typeof event.id !== "string" || !event.id || typeof event.revisionId !== "string" || !/^[a-f0-9]{64}$/u.test(event.reviewOf ?? "") || !Number.isSafeInteger(event.sequence) || event.sequence < 1)
1382
- throw new TypeError("Shared feedback has an invalid event identity or revision.");
1383
- const eventHash = sha256Hex(canonicalizeJson(event));
1384
- if (seen.has(event.id)) {
1385
- if (seen.get(event.id) !== eventHash)
1386
- throw new TypeError("Shared feedback reuses an event identity with changed bytes.");
1387
- continue;
1388
- }
1389
- seen.set(event.id, eventHash);
1390
- const boundReviewOf = revisionBases.get(event.revisionId);
1391
- if (boundReviewOf && boundReviewOf !== event.reviewOf)
1392
- throw new TypeError("A shared revision identity is bound to conflicting design content.");
1393
- revisionBases.set(event.revisionId, event.reviewOf);
1394
- if (event.revisionId !== revisionId) continue;
1395
- if (event.reviewOf !== reviewOf || !event.publicKey?.x || !event.publicKey?.y)
1396
- throw new TypeError("Shared feedback has an invalid revision or signer.");
1397
- const signerId = workspaceReviewerId(event.publicKey);
1398
- const payload = event.payload;
1399
- if (!payload || typeof payload.author !== "string" || !payload.author.trim() || payload.author.length > 160 || payload.reviewOf !== reviewOf)
1400
- throw new TypeError("Shared feedback has an invalid author or digest.");
1401
- const author = { id: signerId, name: payload.author.trim() };
1402
- if (["category", "disposition"].includes(payload.kind)) {
1403
- assertDesignReviewMetadata(payload);
1404
- if (!pins.has(payload.pinId))
1405
- throw new TypeError("Review metadata targets an unknown pin.");
1406
- const owner = ownerPublicKey?.x === event.publicKey.x && ownerPublicKey?.y === event.publicKey.y;
1407
- if (payload.kind === "disposition" && !owner)
1408
- throw new TypeError("Only the design owner can record a disposition.");
1409
- if (payload.kind === "category" && !owner && pinOwners.get(payload.pinId) !== signerId)
1410
- throw new TypeError("Only the comment author or owner can change its category.");
1411
- if (payload.kind === "category") categories[payload.pinId] = payload.category;
1412
- else
1413
- dispositions[payload.pinId] = {
1414
- disposition: payload.disposition,
1415
- reason: payload.reason,
1416
- updatedAt: payload.updatedAt,
1417
- author: author.name
1418
- };
1419
- acceptedEventIds.push(event.id);
1420
- continue;
1421
- }
1422
- if (payload.kind === "direction") {
1423
- for (const value of [payload.ratings ?? {}, payload.remix ?? {}])
1424
- if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).length > 256)
1425
- throw new TypeError("Shared direction feedback is too large or invalid.");
1426
- const ratings = {};
1427
- const remix = {};
1428
- for (const [id, rating] of Object.entries(payload.ratings ?? {})) {
1429
- if (Number.isInteger(rating) && rating >= 1 && rating <= 5) ratings[id] = rating;
1430
- }
1431
- for (const [id, note] of Object.entries(payload.remix ?? {})) {
1432
- if (typeof note === "string" && note.length <= 8192) remix[id] = note;
1433
- }
1434
- directions.set(signerId, { signerId, author: author.name, revisionId, ratings, remix });
1435
- acceptedEventIds.push(event.id);
1436
- continue;
1437
- }
1438
- if (payload.kind !== "review" || payload.review?.reviewOf !== reviewOf)
1439
- throw new TypeError("Shared review snapshot does not match its signed revision.");
1440
- const review2 = normalizeArtifactReview2(payload.review);
1441
- const additions = review2.pins.filter((pin) => !pins.has(pin.id)).length;
1442
- if (pins.size + additions > ARTIFACT_REVIEW_LIMITS.pins)
1443
- throw new TypeError("Shared feedback exceeds the total pin limit.");
1444
- for (const incoming of review2.pins) {
1445
- const previous = pins.get(incoming.id);
1446
- const replies = /* @__PURE__ */ new Set([
1447
- ...(previous?.replies ?? []).map((reply) => reply.id),
1448
- ...incoming.replies.map((reply) => reply.id)
1449
- ]);
1450
- if (replies.size > ARTIFACT_REVIEW_LIMITS.replies)
1451
- throw new TypeError("Shared feedback exceeds the thread reply limit.");
1452
- }
1453
- overall.set(signerId, { author: author.name, note: review2.overall });
1454
- for (const incoming of review2.pins) {
1455
- const previous = pins.get(incoming.id);
1456
- if (!previous) {
1457
- pins.set(incoming.id, { ...structuredClone(incoming), author, replies: [] });
1458
- pinOwners.set(incoming.id, signerId);
1459
- } else if (pinOwners.get(incoming.id) === signerId) {
1460
- pins.set(incoming.id, {
1461
- ...previous,
1462
- comment: incoming.comment,
1463
- status: incoming.status,
1464
- updatedAt: incoming.updatedAt,
1465
- author,
1466
- replies: previous.replies
1467
- });
1468
- }
1469
- const pin = pins.get(incoming.id);
1470
- for (const reply of incoming.replies) {
1471
- const key = `${incoming.id}:${reply.id}`;
1472
- if (!replyOwners.has(key)) {
1473
- replyOwners.set(key, signerId);
1474
- pin.replies.push({ ...structuredClone(reply), author });
1475
- }
1476
- }
1477
- }
1478
- acceptedEventIds.push(event.id);
1479
- } catch (error) {
1480
- issues.push({ eventId: event.id, sequence: event.sequence, reason: error.message });
1481
- }
1482
- }
1483
- const review = normalizeArtifactReview2({
1484
- schemaVersion: "1.0.0",
1485
- reviewId: `shared-${revisionId}`,
1486
- reviewOf,
1487
- decision: "pending",
1488
- overall: [...overall.values()].filter(({ note }) => note).map(({ author, note }) => `${author}: ${note}`).join("\n\n").slice(0, 16384),
1489
- pins: [...pins.values()]
1490
- });
1491
- return {
1492
- review,
1493
- directions: [...directions.values()],
1494
- metadata: { categories, dispositions },
1495
- acceptedEventIds,
1496
- issues
1497
- };
1498
- }
1499
-
1500
- // packages/design/lib/design/share.mjs
1501
- function prepareDesignShareBundle(file) {
1502
- const current = currentDesign(file);
1503
- const saved = readJson(join3(current.root, ".design/studio-state.json"), { state: {} }).state;
1504
- return bundleDesignRevision(current, saved);
1505
- }
1506
- async function withCustody(file, options, action) {
1507
- const location = custodyLocation(file, options);
1508
- ensurePrivateDirectory(location.root, { label: "Design" });
1509
- const unlock = await acquireStartLock(`${location.path}.lock`);
1510
- try {
1511
- let record = readCustody(location.path, { label: "Design", format: FORMAT });
1512
- if (!record && location.legacyPath && existsSync4(location.legacyPath)) {
1513
- readCustody(location.legacyPath, { label: "Design", format: FORMAT });
1514
- const legacyUnlock = await acquireStartLock(`${location.legacyPath}.lock`);
1515
- try {
1516
- const legacy = readCustody(location.legacyPath, { label: "Design", format: FORMAT });
1517
- if (legacy && !existsSync4(location.path)) {
1518
- const temporary = `${location.path}.${newWorkspaceId()}.migration`;
1519
- const fd = openSync(temporary, "wx", 384);
1520
- try {
1521
- writeFileSync3(fd, `${JSON.stringify(legacy)}
1522
- `);
1523
- fsyncSync(fd);
1524
- } finally {
1525
- closeSync(fd);
1526
- }
1527
- try {
1528
- linkSync(temporary, location.path);
1529
- const directory = openSync(location.root, "r");
1530
- try {
1531
- fsyncSync(directory);
1532
- } finally {
1533
- closeSync(directory);
1534
- }
1535
- } finally {
1536
- unlinkSync(temporary);
1537
- }
1538
- }
1539
- record = readCustody(location.path, { label: "Design", format: FORMAT });
1540
- } finally {
1541
- legacyUnlock();
1542
- }
1543
- }
1544
- return await action({
1545
- ...location,
1546
- record,
1547
- save(value = record) {
1548
- record = value;
1549
- writeCustody(location.path, value, { label: "Design" });
1550
- }
1551
- });
1552
- } finally {
1553
- unlock();
1554
- }
1555
- }
1556
- function uploadOptions(custody, options) {
1557
- const body = custody.pendingCreate ?? (custody.pendingMutation?.action === "publish" ? custody.pendingMutation.body : null);
1558
- return {
1559
- fetchImpl: options.fetchImpl,
1560
- ...custody.schemaVersion === "2.0.0" && body ? { readChunk: spoolChunkReader(custody.spoolDirectory, body) } : {}
1561
- };
1562
- }
1563
- async function commitMutation(record, save, options) {
1564
- try {
1565
- return await commitWorkspaceMutation(
1566
- record.custody,
1567
- uploadOptions(record.custody, options)
1568
- );
1569
- } catch (error) {
1570
- if (error.status === 409 && record.custody.pendingMutation) {
1571
- const pending = structuredClone(record.custody.pendingMutation);
1572
- try {
1573
- const remote = await getWorkspace(record.custody, {
1574
- fetchImpl: options.fetchImpl
1575
- });
1576
- if (remote.version > pending.body.expectedVersion) {
1577
- record.conflictedMutation = {
1578
- ...pending,
1579
- localRevision: record.pendingRevision ?? null,
1580
- ...record.custody.spoolDirectory ? { spoolDirectory: record.custody.spoolDirectory } : {}
1581
- };
1582
- delete record.custody.spoolDirectory;
1583
- delete record.custody.pendingMutation;
1584
- delete record.pendingRevision;
1585
- save(record);
1586
- }
1587
- } catch {
1588
- }
1589
- }
1590
- throw error;
1591
- }
1592
- }
1593
- async function shareDesign(file, options = {}) {
1594
- return withCustody(file, options, async ({ record, current, save, root }) => {
1595
- if (record?.deleted)
1596
- throw new Error(
1597
- "This shared review was deleted. Create a new design identity to share a new review."
1598
- );
1599
- if (!record) {
1600
- let transport = options.transport;
1601
- if (!transport) {
1602
- try {
1603
- await discoverWorkspaceCapabilities({
1604
- baseUrl: options.baseUrl ?? options.env?.OPENPLANR_SHARE_BASE ?? process.env.OPENPLANR_SHARE_BASE ?? "https://share.openplanr.dev",
1605
- fetchImpl: options.fetchImpl
1606
- });
1607
- transport = "2";
1608
- } catch (error) {
1609
- if (![404, 426].includes(error.status)) throw error;
1610
- transport = "1";
1611
- }
1612
- }
1613
- let custody;
1614
- try {
1615
- custody = await prepareWorkspace(prepareDesignShareBundle(file), {
1616
- transport,
1617
- baseUrl: options.baseUrl ?? options.env?.OPENPLANR_SHARE_BASE ?? process.env.OPENPLANR_SHARE_BASE ?? "https://share.openplanr.dev"
1618
- });
1619
- } catch (error) {
1620
- if (transport === "1" && error.code === "E_WORKSPACE_PAYLOAD_TOO_LARGE")
1621
- throw Object.assign(
1622
- new Error(
1623
- "This sharing service needs the bounded resource upload upgrade. Retry after the hosted service is updated; your local work is unchanged."
1624
- ),
1625
- { code: "E_WORKSPACE_TRANSPORT_UNSUPPORTED", status: 426 }
1626
- );
1627
- throw error;
1628
- }
1629
- if (custody.schemaVersion === "2.0.0")
1630
- await persistUploadSpool(custody, join3(root, "uploads"));
1631
- record = {
1632
- schemaVersion: "1.0.0",
1633
- kind: FORMAT,
1634
- designId: current.document.id,
1635
- custody,
1636
- publishedRevision: null,
1637
- pendingRevision: current.revision,
1638
- pendingPresentation: presentationFingerprint(current),
1639
- lastEvent: 0
1640
- };
1641
- save(record);
1642
- }
1643
- if (record.custody.pendingCreate) {
1644
- await commitWorkspace(record.custody, uploadOptions(record.custody, options));
1645
- record.publishedRevision = record.pendingRevision;
1646
- record.publishedPresentation = record.pendingPresentation;
1647
- delete record.pendingRevision;
1648
- delete record.pendingPresentation;
1649
- save(record);
1650
- }
1651
- return safeStatus(record, current);
1652
- });
1653
- }
1654
- async function publishDesignShare(file, options = {}) {
1655
- return withCustody(file, options, async ({ record, current, save, root }) => {
1656
- if (!record || record.custody.pendingCreate)
1657
- throw new Error("Create the shared review before publishing an update.");
1658
- if (record.deleted || record.revoked)
1659
- throw new Error("Access was revoked or the review was deleted.");
1660
- if (record.custody.pendingMutation && record.custody.pendingMutation.action !== "publish")
1661
- throw new Error(
1662
- `Retry the pending ${record.custody.pendingMutation.action} operation first.`
1663
- );
1664
- if (!record.custody.pendingMutation) {
1665
- await getWorkspace(record.custody, { fetchImpl: options.fetchImpl });
1666
- await prepareWorkspaceMutation(
1667
- record.custody,
1668
- "publish",
1669
- prepareDesignShareBundle(file)
1670
- );
1671
- if (record.custody.schemaVersion === "2.0.0")
1672
- await persistUploadSpool(record.custody, join3(root, "uploads"));
1673
- record.pendingRevision = current.revision;
1674
- record.pendingPresentation = presentationFingerprint(current);
1675
- save(record);
1676
- }
1677
- await commitMutation(record, save, options);
1678
- record.publishedRevision = record.pendingRevision;
1679
- record.publishedPresentation = record.pendingPresentation;
1680
- delete record.pendingRevision;
1681
- delete record.pendingPresentation;
1682
- save(record);
1683
- return safeStatus(record, current);
1684
- });
1685
- }
1686
- async function manageDesignShare(file, action, options = {}) {
1687
- if (!["rotate", "pause", "resume", "revoke", "delete", "access"].includes(action))
1688
- throw new Error("Unknown design sharing action.");
1689
- return withCustody(file, options, async ({ record, current, save, root }) => {
1690
- if (!record || record.custody.pendingCreate) throw new Error("Create the shared review first.");
1691
- if (action === "access") {
1692
- if (record.revoked || record.deleted) throw new Error("This review is no longer accessible.");
1693
- return { ...safeStatus(record, current), token: record.custody.token };
1694
- }
1695
- if (action === "rotate") await flushOwnerMetadata(record, save, options);
1696
- if (record.custody.pendingMutation && record.custody.pendingMutation.action !== action)
1697
- throw new Error(
1698
- `Retry the pending ${record.custody.pendingMutation.action} operation first.`
1699
- );
1700
- if (!record.custody.pendingMutation) {
1701
- if (!record.revoked)
1702
- await getWorkspace(record.custody, { fetchImpl: options.fetchImpl });
1703
- await prepareWorkspaceMutation(record.custody, action);
1704
- save(record);
1705
- }
1706
- await commitMutation(record, save, options);
1707
- if (action === "pause" || action === "resume") record.commentsPaused = action === "pause";
1708
- if (action === "revoke") record.revoked = true;
1709
- if (action === "delete") record.deleted = true;
1710
- save(record);
1711
- return safeStatus(record, current);
1712
- });
1713
- }
1714
- async function flushOwnerMetadata(record, save, options) {
1715
- while (record.pendingReviewMetadata?.length) {
1716
- await appendWorkspaceEvent(record.custody, null, {
1717
- preparedEvent: record.pendingReviewMetadata[0],
1718
- fetchImpl: options.fetchImpl
1719
- });
1720
- record.pendingReviewMetadata.shift();
1721
- save(record);
1722
- }
1723
- }
1724
- async function publishDesignReviewMetadata(file, payload, { revisionId, ...options } = {}) {
1725
- const location = custodyLocation(file, options, { allowMissing: true });
1726
- if (!existsSync4(location.path) || !revisionId) return { shared: false };
1727
- return withCustody(file, options, async ({ record, save }) => {
1728
- if (!record || record.deleted || record.revoked || record.custody.pendingCreate)
1729
- return { shared: false };
1730
- const event = await prepareWorkspaceEvent(record.custody, payload, {
1731
- revisionId,
1732
- reviewOf: payload.reviewOf,
1733
- signer: {
1734
- privateKey: record.custody.ownerPrivateKey,
1735
- publicKey: record.custody.ownerPublicKey
1736
- }
1737
- });
1738
- record.pendingReviewMetadata ??= [];
1739
- record.pendingReviewMetadata.push(event);
1740
- save(record);
1741
- try {
1742
- await flushOwnerMetadata(record, save, options);
1743
- return { shared: true, pending: false };
1744
- } catch (error) {
1745
- return { shared: true, pending: true, error: error.message };
1746
- }
1747
- });
1748
- }
1749
- async function exportDesignShareRecovery(file, { output, ...options } = {}) {
1750
- if (!output) throw new Error("Recovery export requires a new private output path.");
1751
- return withCustody(file, options, async ({ record }) => {
1752
- if (!record) throw new Error("Create the shared review first.");
1753
- const target = resolve3(output);
1754
- mkdirSync3(dirname4(target), { recursive: true, mode: 448 });
1755
- const recovery = structuredClone(record);
1756
- if (record.custody.schemaVersion === "2.0.0" && (record.custody.pendingCreate || record.custody.pendingMutation?.action === "publish")) {
1757
- const spool = `${target}.upload`;
1758
- await copyUploadSpool(record.custody, spool);
1759
- recovery.recoverySpool = basename(spool);
1760
- recovery.custody.spoolDirectory = spool;
1761
- }
1762
- writeFileSync3(target, `${JSON.stringify(recovery, null, 2)}
1763
- `, { flag: "wx", mode: 384 });
1764
- return { ok: true, output: target };
1765
- });
1766
- }
1767
- async function importDesignShareRecovery(file, { input, ...options } = {}) {
1768
- if (!input) throw new Error("Recovery restore requires --input <private recovery file>.");
1769
- const recovered = readCustody(resolve3(input), {
1770
- label: "Design",
1771
- format: FORMAT,
1772
- recoveryInput: true
1773
- });
1774
- if (!recovered) throw new Error("Recovery file could not be found.");
1775
- const custody = recovered.custody;
1776
- workspaceReviewUrl(custody);
1777
- const proof = await signWorkspaceValue(
1778
- { recovery: custody.id, nonce: newWorkspaceId() },
1779
- custody.ownerPrivateKey
1780
- );
1781
- if (!await verifyWorkspaceSignature(proof, custody.ownerPublicKey))
1782
- throw new Error("Recovery private key does not match its owner identity.");
1783
- await deriveWorkspaceAuthentication(custody.token, custody.id);
1784
- if (!/^[A-Za-z0-9_-]{43}$/u.test(custody.ownerAuth ?? ""))
1785
- throw new Error("Recovery owner capability is invalid.");
1786
- return withCustody(file, options, async ({ record, current, save, root }) => {
1787
- if (recovered.designId !== current.document.id)
1788
- throw new Error("Recovery belongs to a different design.");
1789
- if (record && (record.custody.id !== custody.id || JSON.stringify(record.custody.ownerPublicKey) !== JSON.stringify(custody.ownerPublicKey)))
1790
- throw new Error(
1791
- "This design already has different owner keys. Recovery will not overwrite them."
1792
- );
1793
- if (record && record.custody.version > custody.version)
1794
- throw new Error("This recovery file is older than the locally saved owner keys.");
1795
- if (!custody.pendingCreate && !recovered.deleted && !recovered.revoked) {
1796
- await getWorkspace(custody, { fetchImpl: options.fetchImpl });
1797
- const bundle = await decryptWorkspaceRevision(custody, custody.currentRevision, {
1798
- fetchImpl: options.fetchImpl
1799
- });
1800
- if (bundle.design.id !== current.document.id)
1801
- throw new Error("Recovery belongs to a different design.");
1802
- }
1803
- if (custody.schemaVersion === "2.0.0" && (custody.pendingCreate || custody.pendingMutation?.action === "publish")) {
1804
- if (recovered.recoverySpool !== `${basename(resolve3(input))}.upload`)
1805
- throw new Error("Pending upload recovery requires its matching binary sidecar.");
1806
- custody.spoolDirectory = join3(dirname4(resolve3(input)), recovered.recoverySpool);
1807
- const pending = custody.pendingCreate ?? custody.pendingMutation.body;
1808
- const destination = join3(root, "uploads", custody.id, pending.operationId);
1809
- if (existsSync4(destination)) {
1810
- const { spoolChunkReader: spoolChunkReader2 } = await import("./design-runtime-support-25485dbf1cb2.mjs");
1811
- const reader = spoolChunkReader2(destination, pending);
1812
- for (const part of pending.manifest.chunks) await reader(part.index);
1813
- } else await copyUploadSpool(custody, destination);
1814
- custody.spoolDirectory = destination;
1815
- delete recovered.recoverySpool;
1816
- }
1817
- recovered.lastEvent = 0;
1818
- save(recovered);
1819
- return { ...safeStatus(recovered, current), restored: true };
1820
- });
1821
- }
1822
- async function syncDesignShare(file, options = {}) {
1823
- const location = custodyLocation(file, options, { allowMissing: true });
1824
- if (!existsSync4(location.path)) return { ok: true, shared: false, imported: 0 };
1825
- return withCustody(file, options, async ({ record, current, save, root }) => {
1826
- if (!record || record.custody.pendingCreate || record.deleted)
1827
- return { ok: true, shared: Boolean(record), imported: 0 };
1828
- await flushOwnerMetadata(record, save, options);
1829
- const reviewKey = `design-${hash(current.document.id).slice(0, 24)}`;
1830
- const reviewPath = resolveArtifactReviewDestination({
1831
- cwd: current.root,
1832
- env: options.env ?? process.env,
1833
- artifactId: reviewKey
1834
- }).path;
1835
- const currentDigest = digestArtifactEnvelope(current.envelope);
1836
- let imported = 0, hasMore = true, issues = [];
1837
- const ledgerPath = join3(current.root, ".design/shared-feedback.json");
1838
- while (hasMore) {
1839
- const page = await readWorkspaceEvents(record.custody, {
1840
- after: record.lastEvent ?? 0,
1841
- fetchImpl: options.fetchImpl
1842
- });
1843
- const earlier = readJson(ledgerPath, {
1844
- schemaVersion: "1.0.0",
1845
- events: [],
1846
- issues: [],
1847
- importedReviews: {}
1848
- });
1849
- const events = [...earlier.events];
1850
- const eventBytes = new Map(events.map((event) => [event.id, canonicalizeJson(event)]));
1851
- const revisionBases = /* @__PURE__ */ new Map();
1852
- for (const event of events) {
1853
- const previous = revisionBases.get(event.revisionId);
1854
- if (previous && previous !== event.reviewOf)
1855
- throw new Error(
1856
- "Saved shared feedback binds one revision to conflicting design content."
1857
- );
1858
- revisionBases.set(event.revisionId, event.reviewOf);
1859
- }
1860
- const pageIssues = [...page.issues ?? []];
1861
- for (const event of page.events ?? []) {
1862
- if (eventBytes.has(event.id)) {
1863
- if (eventBytes.get(event.id) !== canonicalizeJson(event))
1864
- pageIssues.push({
1865
- id: event.id,
1866
- sequence: event.sequence,
1867
- reason: "Shared feedback reuses an event identity with changed bytes."
1868
- });
1869
- continue;
1870
- }
1871
- try {
1872
- const boundReviewOf = revisionBases.get(event.revisionId);
1873
- if (boundReviewOf && boundReviewOf !== event.reviewOf)
1874
- throw new Error("A shared revision identity is bound to conflicting design content.");
1875
- const candidate = mergeWorkspaceFeedback([...events, event], {
1876
- revisionId: event.revisionId,
1877
- reviewOf: event.reviewOf,
1878
- ownerPublicKey: record.custody.ownerPublicKey
1879
- });
1880
- const invalid2 = candidate.issues?.find(
1881
- (issue) => (issue.id ?? issue.eventId) === event.id
1882
- );
1883
- if (invalid2) throw new Error(invalid2.reason);
1884
- events.push(event);
1885
- eventBytes.set(event.id, canonicalizeJson(event));
1886
- revisionBases.set(event.revisionId, event.reviewOf);
1887
- imported++;
1888
- } catch (error) {
1889
- pageIssues.push({ id: event.id, sequence: event.sequence, reason: error.message });
1890
- }
1891
- }
1892
- const revisions = /* @__PURE__ */ new Map();
1893
- for (const event of events) {
1894
- const previous = revisions.get(event.revisionId);
1895
- if (previous && previous !== event.reviewOf)
1896
- throw new Error(
1897
- "Saved shared feedback binds one revision to conflicting design content."
1898
- );
1899
- revisions.set(event.revisionId, event.reviewOf);
1900
- }
1901
- const importedReviews = { ...earlier.importedReviews ?? {} }, directions = [], metadataByRevision = {};
1902
- await withArtifactReviewLock(reviewPath, () => {
1903
- const ledger = readArtifactReviewState(reviewPath, { allowMissing: true }) ?? createReviewLedger({ artifactId: reviewKey, currentReviewOf: currentDigest });
1904
- const entries = new Map(ledger.reviews.map((entry) => [entry.review.reviewId, entry]));
1905
- for (const [revisionId, reviewOf] of revisions) {
1906
- const merged = mergeWorkspaceFeedback(events, {
1907
- revisionId,
1908
- reviewOf,
1909
- ownerPublicKey: record.custody.ownerPublicKey
1910
- });
1911
- metadataByRevision[revisionId] = merged.metadata;
1912
- directions.push(...merged.directions);
1913
- pageIssues.push(...merged.issues ?? []);
1914
- const review = structuredClone(merged.review);
1915
- const previous = entries.get(review.reviewId)?.review;
1916
- const previousImport = earlier.importedReviews?.[review.reviewId];
1917
- importedReviews[review.reviewId] = structuredClone(review);
1918
- if (previous) {
1919
- review.decision = previous.decision;
1920
- if (previousImport && previous.overall !== previousImport.overall)
1921
- review.overall = previous.overall;
1922
- review.pins = review.pins.map((pin) => {
1923
- const saved = previous.pins.find((item) => item.id === pin.id);
1924
- const importedPin = previousImport?.pins.find((item) => item.id === pin.id);
1925
- if (!saved) return pin;
1926
- const replies = new Map(
1927
- [...pin.replies, ...saved.replies].map((reply) => [reply.id, reply])
1928
- );
1929
- return {
1930
- ...pin,
1931
- ...importedPin && saved.status !== importedPin.status ? { status: saved.status, updatedAt: saved.updatedAt } : {},
1932
- replies: [...replies.values()]
1933
- };
1934
- });
1935
- }
1936
- entries.set(review.reviewId, { review, stale: reviewOf !== currentDigest });
1937
- }
1938
- writeArtifactReviewState(
1939
- reviewPath,
1940
- createReviewLedger({
1941
- artifactId: reviewKey,
1942
- currentReviewOf: currentDigest,
1943
- reviews: [...entries.values()]
1944
- })
1945
- );
1946
- });
1947
- issues = [
1948
- ...new Map(
1949
- [...earlier.issues ?? [], ...pageIssues].map((issue) => [
1950
- `${issue.id ?? issue.eventId}:${issue.sequence}`,
1951
- issue
1952
- ])
1953
- ).values()
1954
- ];
1955
- atomicJson(ledgerPath, {
1956
- schemaVersion: "1.0.0",
1957
- workspaceId: record.custody.id,
1958
- events,
1959
- issues,
1960
- directions,
1961
- metadataByRevision,
1962
- importedReviews
1963
- });
1964
- const next = page.cursor;
1965
- hasMore = Boolean(page.hasMore) && next > record.lastEvent;
1966
- record.lastEvent = next;
1967
- save(record);
1968
- }
1969
- return { ok: true, shared: true, imported, issues, reviewPath, ...safeStatus(record, current) };
1970
- });
1971
- }
1972
-
1973
- export {
1974
- createReviewLedger,
1975
- mergeReviewLedger,
1976
- effectiveReviewDecision,
1977
- ARTIFACT_REVIEW_MAX_STATE_BYTES,
1978
- normalizeArtifactReview,
1979
- readArtifactReviewState,
1980
- writeArtifactReviewState,
1981
- withArtifactReviewLock,
1982
- exportArtifactReview,
1983
- resolveArtifactReviewDestination,
1984
- decodeArtifactReviewSources,
1985
- getDesignShareStatus,
1986
- shareDesign,
1987
- publishDesignShare,
1988
- manageDesignShare,
1989
- publishDesignReviewMetadata,
1990
- exportDesignShareRecovery,
1991
- importDesignShareRecovery,
1992
- syncDesignShare
1993
- };