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,1755 +0,0 @@
1
-
2
-
3
- // lib/artifact/ui/review-outbox.mjs
4
- function createReviewOutbox({
5
- scope,
6
- indexedDB = globalThis.indexedDB,
7
- databaseName = "openplanr-review-outbox-v1",
8
- leaseMs = 3e4,
9
- now = Date.now,
10
- validatePayload = (payload) => payload !== null && typeof payload === "object"
11
- }) {
12
- for (const value of [scope.workspaceId, scope.revisionId, scope.actorId])
13
- if (typeof value !== "string" || !value || value.length > 512)
14
- throw new TypeError("Review custody requires workspace, revision and actor identities.");
15
- if (!Number.isFinite(leaseMs) || leaseMs < 300)
16
- throw new TypeError("A review lease must be at least 300ms.");
17
- const scopeKey = JSON.stringify([scope.workspaceId, scope.revisionId, scope.actorId]);
18
- const key = (id7) => {
19
- if (typeof id7 !== "string" || !id7 || id7.length > 512)
20
- throw new TypeError("A review operation needs a stable identity.");
21
- return JSON.stringify([scopeKey, id7]);
22
- };
23
- let closed7 = false, draining = null;
24
- const listeners = /* @__PURE__ */ new Set();
25
- const heartbeats = /* @__PURE__ */ new Set();
26
- const channel = typeof globalThis.BroadcastChannel === "function" ? new globalThis.BroadcastChannel(databaseName) : null;
27
- const notify = () => {
28
- listeners.forEach((listener) => {
29
- listener();
30
- });
31
- channel?.postMessage(scopeKey);
32
- };
33
- if (channel)
34
- channel.onmessage = (event) => {
35
- if (event.data === scopeKey)
36
- listeners.forEach((listener) => {
37
- listener();
38
- });
39
- };
40
- const database = new Promise((resolve, reject) => {
41
- if (!indexedDB) {
42
- reject(
43
- new Error(
44
- "Durable review storage is unavailable. Enable browser storage before sending feedback."
45
- )
46
- );
47
- return;
48
- }
49
- const request = indexedDB.open(databaseName, 1);
50
- request.onupgradeneeded = () => {
51
- const store = request.result.createObjectStore("operations", { keyPath: "key" });
52
- store.createIndex("scope", "scopeKey", { unique: false });
53
- };
54
- request.onerror = () => reject(request.error ?? new Error("Durable review storage could not open."));
55
- request.onblocked = () => reject(new Error("Close older review tabs to open durable review storage."));
56
- request.onsuccess = () => {
57
- const db = request.result;
58
- db.onversionchange = () => db.close();
59
- if (closed7) db.close();
60
- resolve(db);
61
- };
62
- });
63
- void database.catch(() => {
64
- });
65
- async function transaction(mode, work) {
66
- if (closed7) throw new Error("Review custody has closed.");
67
- const db = await database;
68
- return new Promise((resolve, reject) => {
69
- const tx = db.transaction("operations", mode), store = tx.objectStore("operations");
70
- let value;
71
- tx.oncomplete = () => resolve(value);
72
- tx.onerror = () => reject(tx.error ?? new Error("Review storage could not commit."));
73
- tx.onabort = () => reject(tx.error ?? new Error("Review storage did not commit."));
74
- const guard = (callback) => () => {
75
- try {
76
- callback();
77
- } catch (error) {
78
- try {
79
- tx.abort();
80
- } catch {
81
- }
82
- reject(error);
83
- }
84
- };
85
- guard(
86
- () => work(
87
- store,
88
- (next) => {
89
- value = next;
90
- },
91
- guard
92
- )
93
- )();
94
- });
95
- }
96
- const publicEntry = ({
97
- key: _key,
98
- scopeKey: _scope,
99
- leaseOwner: _owner,
100
- leaseUntil: _until,
101
- custodyInvalid: _invalid,
102
- invalidRecord: _record,
103
- ...entry
104
- }) => entry;
105
- function payloadValid(payload) {
106
- try {
107
- return validatePayload(payload);
108
- } catch {
109
- return false;
110
- }
111
- }
112
- function keyedIdentity(primaryKey) {
113
- if (typeof primaryKey !== "string") return null;
114
- try {
115
- const value = JSON.parse(primaryKey);
116
- return Array.isArray(value) && value.length === 2 && value[0] === scopeKey && typeof value[1] === "string" && value[1].length > 0 && value[1].length <= 512 ? value[1] : null;
117
- } catch {
118
- return null;
119
- }
120
- }
121
- function storedEntry(raw, primaryKey, store) {
122
- const record2 = raw !== null && typeof raw === "object" ? raw : null;
123
- const fromKey = keyedIdentity(primaryKey);
124
- if (record2?.scopeKey !== scopeKey && !fromKey) return null;
125
- const allowed = /* @__PURE__ */ new Set([
126
- "key",
127
- "scopeKey",
128
- "operationId",
129
- "payload",
130
- "status",
131
- "attempts",
132
- "createdAt",
133
- "nextAttemptAt",
134
- "errorCode",
135
- "leaseOwner",
136
- "leaseUntil",
137
- "custodyInvalid",
138
- "invalidRecord"
139
- ]);
140
- const finiteTime = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0;
141
- const integer3 = (value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
142
- if (record2 && Object.keys(record2).every((name) => allowed.has(name)) && fromKey !== null && fromKey === record2.operationId && record2.key === primaryKey && record2.scopeKey === scopeKey && Object.hasOwn(record2, "payload") && ["pending", "quarantined"].includes(String(record2.status)) && integer3(record2.attempts) && finiteTime(record2.createdAt) && finiteTime(record2.nextAttemptAt) && (record2.errorCode === void 0 || typeof record2.errorCode === "string" && record2.errorCode.length <= 120) && (record2.leaseOwner === void 0 && record2.leaseUntil === void 0 || typeof record2.leaseOwner === "string" && record2.leaseOwner.length > 0 && record2.leaseOwner.length <= 128 && finiteTime(record2.leaseUntil)) && (record2.custodyInvalid === true ? record2.status === "quarantined" && record2.errorCode === "malformed_custody" : record2.custodyInvalid === void 0 && record2.invalidRecord === void 0 && payloadValid(record2.payload)))
143
- return record2;
144
- const operationId = fromKey ?? `invalid-${globalThis.crypto.randomUUID()}`;
145
- const repaired = {
146
- key: key(operationId),
147
- scopeKey,
148
- operationId,
149
- payload: record2 && Object.hasOwn(record2, "payload") ? record2.payload : null,
150
- status: "quarantined",
151
- attempts: 0,
152
- createdAt: 0,
153
- nextAttemptAt: 0,
154
- errorCode: "malformed_custody",
155
- custodyInvalid: true,
156
- invalidRecord: raw
157
- };
158
- store.put(repaired);
159
- if (primaryKey !== repaired.key) store.delete(primaryKey);
160
- return repaired;
161
- }
162
- function readScoped(store, result, guard) {
163
- const entries = [];
164
- const seen = /* @__PURE__ */ new Set();
165
- const request = store.openCursor();
166
- request.onsuccess = guard(() => {
167
- const cursor = request.result;
168
- if (!cursor) {
169
- result(entries);
170
- return;
171
- }
172
- const entry = storedEntry(cursor.value, cursor.primaryKey, store);
173
- if (entry && !seen.has(entry.key)) {
174
- seen.add(entry.key);
175
- entries.push(entry);
176
- }
177
- cursor.continue();
178
- });
179
- }
180
- async function mutate(id7, update) {
181
- await transaction("readwrite", (store, _result, guard) => {
182
- const operationKey = key(id7);
183
- const request = store.get(operationKey);
184
- request.onsuccess = guard(() => {
185
- if (request.result === void 0) return;
186
- const entry = storedEntry(request.result, operationKey, store);
187
- if (entry) update(entry, store);
188
- });
189
- });
190
- notify();
191
- }
192
- async function claim(owner) {
193
- return transaction("readwrite", (store, result, guard) => {
194
- readScoped(
195
- store,
196
- (entries) => {
197
- const time = now();
198
- const next = entries.filter(
199
- (entry) => entry.status === "pending" && entry.nextAttemptAt <= time && (!entry.leaseUntil || entry.leaseUntil <= time)
200
- ).sort(
201
- (a, b) => a.createdAt - b.createdAt || a.operationId.localeCompare(b.operationId)
202
- )[0];
203
- if (!next) {
204
- result(null);
205
- return;
206
- }
207
- next.leaseOwner = owner;
208
- next.leaseUntil = time + leaseMs;
209
- store.put(next);
210
- result(next);
211
- },
212
- guard
213
- );
214
- });
215
- }
216
- return {
217
- async enqueue({ operationId, payload }) {
218
- const immutable = structuredClone(payload), operationKey = key(operationId);
219
- if (!payloadValid(immutable)) throw new TypeError("Prepared review custody is invalid.");
220
- await transaction("readwrite", (store, _result, guard) => {
221
- const request = store.get(operationKey);
222
- request.onsuccess = guard(() => {
223
- if (request.result !== void 0) {
224
- storedEntry(request.result, operationKey, store);
225
- return;
226
- }
227
- store.add({
228
- key: operationKey,
229
- scopeKey,
230
- operationId,
231
- payload: immutable,
232
- status: "pending",
233
- attempts: 0,
234
- createdAt: now(),
235
- nextAttemptAt: 0
236
- });
237
- });
238
- });
239
- notify();
240
- },
241
- async list() {
242
- return transaction("readwrite", (store, result, guard) => {
243
- readScoped(
244
- store,
245
- (entries) => result(
246
- entries.sort(
247
- (a, b) => a.createdAt - b.createdAt || a.operationId.localeCompare(b.operationId)
248
- ).map(publicEntry)
249
- ),
250
- guard
251
- );
252
- });
253
- },
254
- async retry(id7) {
255
- await mutate(id7, (entry, store) => {
256
- if (entry.custodyInvalid || entry.leaseUntil && entry.leaseUntil > now()) return;
257
- entry.status = "pending";
258
- entry.nextAttemptAt = 0;
259
- delete entry.errorCode;
260
- store.put(entry);
261
- });
262
- },
263
- async quarantine(id7, code) {
264
- await mutate(id7, (entry, store) => {
265
- if (entry.leaseUntil && entry.leaseUntil > now()) return;
266
- entry.status = "quarantined";
267
- entry.nextAttemptAt = 0;
268
- entry.errorCode = entry.custodyInvalid ? "malformed_custody" : String(code).slice(0, 120);
269
- store.put(entry);
270
- });
271
- },
272
- async remove(id7) {
273
- await mutate(id7, (entry, store) => {
274
- if (!entry.leaseUntil || entry.leaseUntil <= now()) store.delete(entry.key);
275
- });
276
- },
277
- drain(send) {
278
- if (draining) return draining;
279
- const owner = globalThis.crypto.randomUUID();
280
- draining = (async () => {
281
- while (!closed7) {
282
- const entry = await claim(owner);
283
- if (!entry) return;
284
- const heartbeat = globalThis.setInterval(
285
- () => {
286
- void mutate(entry.operationId, (current, store) => {
287
- if (current.leaseOwner === owner) {
288
- current.leaseUntil = now() + leaseMs;
289
- store.put(current);
290
- }
291
- }).catch(() => {
292
- });
293
- },
294
- Math.floor(leaseMs / 3)
295
- );
296
- heartbeats.add(heartbeat);
297
- let outcome;
298
- try {
299
- outcome = await send(publicEntry(entry));
300
- } catch {
301
- outcome = { status: "retry", code: "network" };
302
- } finally {
303
- globalThis.clearInterval(heartbeat);
304
- heartbeats.delete(heartbeat);
305
- }
306
- if (!outcome || !["delivered", "retry", "rejected"].includes(outcome.status))
307
- outcome = { status: "retry", code: "invalid-delivery-result" };
308
- await mutate(entry.operationId, (current, store) => {
309
- if (current.leaseOwner !== owner) return;
310
- if (outcome.status === "delivered") {
311
- store.delete(current.key);
312
- return;
313
- }
314
- delete current.leaseOwner;
315
- delete current.leaseUntil;
316
- current.attempts += 1;
317
- current.errorCode = typeof outcome.code === "string" ? outcome.code.slice(0, 120) : outcome.status;
318
- current.status = outcome.status === "rejected" ? "quarantined" : "pending";
319
- const requestedDelay = Number.isFinite(outcome.retryAfterMs) ? Math.max(0, Math.min(36e5, outcome.retryAfterMs)) : 0;
320
- current.nextAttemptAt = outcome.status === "retry" ? now() + Math.max(
321
- requestedDelay,
322
- Math.min(6e4, 1e3 * 2 ** Math.min(current.attempts - 1, 6))
323
- ) : 0;
324
- store.put(current);
325
- });
326
- }
327
- })().finally(() => {
328
- draining = null;
329
- });
330
- return draining;
331
- },
332
- subscribe(listener) {
333
- listeners.add(listener);
334
- return () => listeners.delete(listener);
335
- },
336
- close() {
337
- closed7 = true;
338
- for (const heartbeat of heartbeats) globalThis.clearInterval(heartbeat);
339
- heartbeats.clear();
340
- channel?.close();
341
- listeners.clear();
342
- void database.then((db) => db.close()).catch(() => {
343
- });
344
- }
345
- };
346
- }
347
-
348
- // lib/artifact/ui/durable-paste-share.mjs
349
- var retainedPreparation = /* @__PURE__ */ Symbol("private-paste-preparation-retained");
350
- function preparation(value) {
351
- assertPreparedArtifactPaste(value);
352
- return value;
353
- }
354
- function receipt(prepared, value) {
355
- const url = new URL(`/p/${prepared.body.id}`, prepared.origin);
356
- url.hash = `k=${prepared.key}&v=2`;
357
- if (!value || value.url !== url.toString() || value.deletionToken !== prepared.custodyToken || typeof value.expiresAt !== "string" || !Number.isFinite(Date.parse(value.expiresAt)))
358
- throw new Error("Paste receipt differs from saved private custody.");
359
- return value;
360
- }
361
- function createDurablePasteShare({
362
- scope,
363
- create,
364
- commit,
365
- indexedDB = globalThis.indexedDB,
366
- databaseName = "openplanr-paste-custody-v1"
367
- }) {
368
- const queues = /* @__PURE__ */ new Map();
369
- function queueFor(request) {
370
- const base = scope(), revisionId2 = `${base.revisionId}:${request.ttl ?? "7d"}`, identity = JSON.stringify({ ...base, revisionId: revisionId2 });
371
- let queue = queues.get(identity);
372
- if (!queue) {
373
- queue = createReviewOutbox({ scope: { ...base, revisionId: revisionId2 }, indexedDB, databaseName });
374
- queues.set(identity, queue);
375
- }
376
- return queue;
377
- }
378
- const activeReceipt = (entries) => entries.map((entry) => entry.payload).find(
379
- (value) => value?.kind === "paste-receipt" && typeof value.result?.expiresAt === "string" && Date.parse(value.result.expiresAt) > Date.now()
380
- );
381
- return {
382
- async run(request) {
383
- if (request.transport !== "short") return create(request);
384
- const queue = queueFor(request);
385
- let entries = await queue.list();
386
- const prior = activeReceipt(entries);
387
- if (prior) return receipt(preparation(prior.prepared), prior.result ?? null);
388
- let pending = entries.find(
389
- (entry) => entry.payload?.kind === "prepared-paste"
390
- );
391
- if (pending?.status === "quarantined")
392
- throw new Error(
393
- "The saved paste operation was rejected. Its private recovery custody is retained."
394
- );
395
- if (!pending) {
396
- try {
397
- await create({
398
- ...request,
399
- onPreparedPaste: async (value) => {
400
- const prepared = preparation(value);
401
- if (prepared.body.ttl !== (request.ttl ?? "7d"))
402
- throw new Error("Prepared paste expiry differs.");
403
- await queue.enqueue({
404
- operationId: prepared.body.creationId,
405
- payload: { kind: "prepared-paste", prepared }
406
- });
407
- throw retainedPreparation;
408
- }
409
- });
410
- } catch (error) {
411
- if (error !== retainedPreparation) throw error;
412
- }
413
- entries = await queue.list();
414
- pending = entries.find(
415
- (entry) => entry.payload?.kind === "prepared-paste"
416
- );
417
- if (!pending)
418
- throw new Error(
419
- "This host did not retain paste custody before publication. Update OpenPlanr and retry."
420
- );
421
- }
422
- await queue.retry(pending.operationId);
423
- let result = null;
424
- await queue.drain(async (entry) => {
425
- const value = entry.payload;
426
- if (value?.kind === "paste-receipt")
427
- return { status: "rejected", code: "private-custody-receipt" };
428
- try {
429
- const prepared = preparation(value?.prepared);
430
- const created = receipt(prepared, await commit(prepared));
431
- const receiptId = `${prepared.body.creationId}:receipt`;
432
- await queue.enqueue({
433
- operationId: receiptId,
434
- payload: { kind: "paste-receipt", prepared, result: created }
435
- });
436
- await queue.quarantine(receiptId, "private-custody-receipt");
437
- result = created;
438
- return { status: "delivered" };
439
- } catch (error) {
440
- const code = error?.code;
441
- return typeof code === "string" && ["E_ARTIFACT_SHARE_NETWORK", "E_ARTIFACT_PASTE_UNAVAILABLE"].includes(code) ? { status: "retry", code } : { status: "rejected", code: "paste-rejected" };
442
- }
443
- });
444
- if (result) return result;
445
- const completed = activeReceipt(await queue.list());
446
- if (completed) return receipt(preparation(completed.prepared), completed.result ?? null);
447
- throw new Error(
448
- "Paste publication is pending. Retry this share to resume the saved encrypted operation; another tab may be sending it."
449
- );
450
- },
451
- close() {
452
- for (const queue of queues.values()) queue.close();
453
- queues.clear();
454
- }
455
- };
456
- }
457
-
458
- // lib/artifact/ui/feedback-rail.mjs
459
- var ARTIFACT_REVIEW_CHANGE_EVENT = "planr:artifact-review-change";
460
- var ARTIFACT_REVIEW_SELECT_EVENT = "planr:artifact-review-select";
461
- var ARTIFACT_REVIEW_DRAFT_CHANGE_EVENT = "planr:artifact-review-draft-change";
462
- var ARTIFACT_REVIEW_LIMITS = Object.freeze({
463
- id: 128,
464
- authorName: 256,
465
- artifactId: 128,
466
- variant: 128,
467
- anchor: 512,
468
- screen: 128,
469
- text: 65536,
470
- pins: 1e4,
471
- replies: 1e4,
472
- viewport: 16384
473
- });
474
- var ARTIFACT_REVIEW_DECISIONS = Object.freeze([
475
- "pending",
476
- "approved",
477
- "changes_requested"
478
- ]);
479
- var ARTIFACT_REVIEW_INTENTS = Object.freeze(["fix", "improve", "question"]);
480
- var ARTIFACT_REVIEW_STATUSES = Object.freeze(["open", "addressed", "resolved"]);
481
- var REVIEW_OF_RE = /^[a-f0-9]{64}$/;
482
- var ArtifactReviewStateError = class extends Error {
483
- constructor(code, message) {
484
- super(message);
485
- this.name = "ArtifactReviewStateError";
486
- this.code = code;
487
- }
488
- };
489
- function invalid(message) {
490
- throw new ArtifactReviewStateError("E_ARTIFACT_REVIEW_INVALID", message);
491
- }
492
- function identityRequired() {
493
- throw new ArtifactReviewStateError(
494
- "E_ARTIFACT_REVIEW_IDENTITY_REQUIRED",
495
- "Enter your name before adding a comment."
496
- );
497
- }
498
- function clonePlain(value) {
499
- if (Array.isArray(value)) return value.map(clonePlain);
500
- if (!value || typeof value !== "object") return value;
501
- const clone = {};
502
- for (const [key, entry] of Object.entries(value)) clone[key] = clonePlain(entry);
503
- return clone;
504
- }
505
- function cloneFrozenArtifactReview(review) {
506
- return deepFreeze(clonePlain(review));
507
- }
508
- function boundedString(value, label, { min = 0, max, trim = false, pattern } = {}) {
509
- if (typeof value !== "string") invalid(`${label} must be a string.`);
510
- const normalized3 = trim ? value.trim() : value;
511
- if (normalized3.length < min || max !== void 0 && normalized3.length > max) {
512
- invalid(`${label} must contain ${min} through ${max ?? "unlimited"} characters.`);
513
- }
514
- if (pattern && !pattern.test(normalized3)) invalid(`${label} has an invalid format.`);
515
- return normalized3;
516
- }
517
- function optionalString(value, label, options) {
518
- if (value === void 0) return void 0;
519
- return boundedString(value, label, options);
520
- }
521
- function enumValue(value, values, label) {
522
- if (!values.includes(value)) invalid(`${label} must be one of: ${values.join(", ")}.`);
523
- return value;
524
- }
525
- function isoTimestamp(value, label) {
526
- const timestamp2 = value instanceof Date ? value.toISOString() : value;
527
- if (typeof timestamp2 !== "string" || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(timestamp2) || !Number.isFinite(Date.parse(timestamp2))) {
528
- invalid(`${label} must be an ISO-8601 date-time.`);
529
- }
530
- return timestamp2;
531
- }
532
- function dependencyTimestamp(now) {
533
- return isoTimestamp(now(), "now()");
534
- }
535
- function defaultNow() {
536
- return (/* @__PURE__ */ new Date()).toISOString();
537
- }
538
- function createSecureArtifactReviewId(cryptoProvider = globalThis.crypto) {
539
- const randomUuid = cryptoProvider?.randomUUID?.();
540
- if (randomUuid) return randomUuid;
541
- const bytes = new Uint8Array(16);
542
- if (typeof cryptoProvider?.getRandomValues !== "function") {
543
- throw new ArtifactReviewStateError(
544
- "E_ARTIFACT_REVIEW_UUID_UNAVAILABLE",
545
- "Secure UUID generation is unavailable in this browser."
546
- );
547
- }
548
- cryptoProvider.getRandomValues(bytes);
549
- bytes[6] = bytes[6] & 15 | 64;
550
- bytes[8] = bytes[8] & 63 | 128;
551
- const hex = [...bytes].map((value) => value.toString(16).padStart(2, "0")).join("");
552
- return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
553
- }
554
- function defaultCreateId() {
555
- return createSecureArtifactReviewId();
556
- }
557
- function dependencyId(createId, kind) {
558
- return boundedString(createId(kind), `${kind} id`, {
559
- min: 1,
560
- max: ARTIFACT_REVIEW_LIMITS.id,
561
- trim: true
562
- });
563
- }
564
- function uniqueDependencyId(createId, kind, existingIds) {
565
- for (let attempt = 0; attempt < 100; attempt += 1) {
566
- const candidate = dependencyId(createId, kind);
567
- if (!existingIds.has(candidate)) return candidate;
568
- }
569
- throw new ArtifactReviewStateError(
570
- "E_ARTIFACT_REVIEW_ID_COLLISION",
571
- `Could not create a unique ${kind} id.`
572
- );
573
- }
574
- function normalizeArtifactReviewIdentity(value, { allowEmpty = false } = {}) {
575
- if (value === null || value === void 0 || value === "") {
576
- if (allowEmpty) return null;
577
- identityRequired();
578
- }
579
- const source = typeof value === "string" ? { name: value } : value;
580
- if (!source || typeof source !== "object" || Array.isArray(source)) identityRequired();
581
- const name = boundedString(source.name, "author.name", {
582
- min: 1,
583
- max: ARTIFACT_REVIEW_LIMITS.authorName,
584
- trim: true
585
- });
586
- const id7 = optionalString(source.id, "author.id", {
587
- min: 1,
588
- max: ARTIFACT_REVIEW_LIMITS.id,
589
- trim: true
590
- });
591
- return deepFreeze(id7 === void 0 ? { name } : { id: id7, name });
592
- }
593
- function normalizeRegion(region) {
594
- if (!region || typeof region !== "object" || Array.isArray(region)) {
595
- invalid("pin.region must be an object.");
596
- }
597
- const finite3 = (value, label) => {
598
- if (typeof value !== "number" || !Number.isFinite(value)) invalid(`${label} must be finite.`);
599
- return value;
600
- };
601
- const x = finite3(region.x, "pin.region.x");
602
- const y = finite3(region.y, "pin.region.y");
603
- const w = finite3(region.w, "pin.region.w");
604
- const h = finite3(region.h, "pin.region.h");
605
- if (x >= 0 && y >= 0 && w >= 0 && h >= 0 && x + w <= 1 && y + h <= 1) {
606
- return { x, y, w, h };
607
- }
608
- const unit2 = (value) => Math.round(Math.min(1, Math.max(0, value)) * 1e6) / 1e6;
609
- const boundedX = unit2(x);
610
- const boundedY = unit2(y);
611
- return {
612
- x: boundedX,
613
- y: boundedY,
614
- w: Math.round(Math.min(unit2(w), 1 - boundedX) * 1e6) / 1e6,
615
- h: Math.round(Math.min(unit2(h), 1 - boundedY) * 1e6) / 1e6
616
- };
617
- }
618
- function normalizeViewport(viewport) {
619
- if (!viewport || typeof viewport !== "object" || Array.isArray(viewport)) {
620
- invalid("pin.viewport must be an object.");
621
- }
622
- const dimension = (value, label) => {
623
- if (!Number.isInteger(value) || value < 1 || value > ARTIFACT_REVIEW_LIMITS.viewport) {
624
- invalid(`${label} must be an integer from 1 through ${ARTIFACT_REVIEW_LIMITS.viewport}.`);
625
- }
626
- return value;
627
- };
628
- return {
629
- width: dimension(viewport.width, "pin.viewport.width"),
630
- height: dimension(viewport.height, "pin.viewport.height")
631
- };
632
- }
633
- function normalizeAnchor(anchor2) {
634
- if (anchor2 === void 0 || anchor2 === null) return void 0;
635
- if (typeof anchor2 !== "object" || Array.isArray(anchor2)) invalid("pin.anchor must be an object.");
636
- const planrId = boundedString(anchor2.planrId, "pin.anchor.planrId", {
637
- min: 1,
638
- max: ARTIFACT_REVIEW_LIMITS.anchor,
639
- trim: true
640
- });
641
- const screen = optionalString(anchor2.screen, "pin.anchor.screen", {
642
- min: 1,
643
- max: ARTIFACT_REVIEW_LIMITS.screen,
644
- trim: true
645
- });
646
- return screen === void 0 ? { planrId } : { planrId, screen };
647
- }
648
- function normalizeReply(reply2, label = "reply") {
649
- if (!reply2 || typeof reply2 !== "object" || Array.isArray(reply2))
650
- invalid(`${label} must be an object.`);
651
- return {
652
- id: boundedString(reply2.id, `${label}.id`, {
653
- min: 1,
654
- max: ARTIFACT_REVIEW_LIMITS.id,
655
- trim: true
656
- }),
657
- author: normalizeArtifactReviewIdentity(reply2.author),
658
- comment: boundedString(reply2.comment, `${label}.comment`, {
659
- min: 1,
660
- max: ARTIFACT_REVIEW_LIMITS.text,
661
- trim: true
662
- }),
663
- createdAt: isoTimestamp(reply2.createdAt, `${label}.createdAt`)
664
- };
665
- }
666
- function compareTimestampThenId(left, right) {
667
- const byTime = left.createdAt.localeCompare(right.createdAt);
668
- return byTime === 0 ? left.id.localeCompare(right.id) : byTime;
669
- }
670
- function normalizePin(pin, label = "pin") {
671
- if (!pin || typeof pin !== "object" || Array.isArray(pin)) invalid(`${label} must be an object.`);
672
- if (!Array.isArray(pin.replies) || pin.replies.length > ARTIFACT_REVIEW_LIMITS.replies) {
673
- invalid(`${label}.replies must contain no more than ${ARTIFACT_REVIEW_LIMITS.replies} items.`);
674
- }
675
- const replies = pin.replies.map(
676
- (reply2, index2) => normalizeReply(reply2, `${label}.replies[${index2}]`)
677
- );
678
- const replyIds = new Set(replies.map(({ id: id7 }) => id7));
679
- if (replyIds.size !== replies.length) invalid(`${label}.replies must have unique ids.`);
680
- const normalized3 = {
681
- id: boundedString(pin.id, `${label}.id`, {
682
- min: 1,
683
- max: ARTIFACT_REVIEW_LIMITS.id,
684
- trim: true
685
- }),
686
- author: normalizeArtifactReviewIdentity(pin.author),
687
- artifactId: boundedString(pin.artifactId, `${label}.artifactId`, {
688
- min: 1,
689
- max: ARTIFACT_REVIEW_LIMITS.artifactId,
690
- trim: true
691
- }),
692
- region: normalizeRegion(pin.region),
693
- viewport: normalizeViewport(pin.viewport),
694
- intent: enumValue(pin.intent, ARTIFACT_REVIEW_INTENTS, `${label}.intent`),
695
- status: enumValue(pin.status, ARTIFACT_REVIEW_STATUSES, `${label}.status`),
696
- comment: boundedString(pin.comment, `${label}.comment`, {
697
- min: 1,
698
- max: ARTIFACT_REVIEW_LIMITS.text,
699
- trim: true
700
- }),
701
- replies: replies.sort(compareTimestampThenId),
702
- createdAt: isoTimestamp(pin.createdAt, `${label}.createdAt`),
703
- updatedAt: isoTimestamp(pin.updatedAt, `${label}.updatedAt`)
704
- };
705
- const variant = optionalString(pin.variant, `${label}.variant`, {
706
- min: 1,
707
- max: ARTIFACT_REVIEW_LIMITS.variant,
708
- trim: true
709
- });
710
- const anchor2 = normalizeAnchor(pin.anchor);
711
- if (variant !== void 0) normalized3.variant = variant;
712
- if (anchor2 !== void 0) normalized3.anchor = anchor2;
713
- return normalized3;
714
- }
715
- function normalizeArtifactReview(review) {
716
- if (!review || typeof review !== "object" || Array.isArray(review)) {
717
- invalid("Artifact review must be an object.");
718
- }
719
- if (!Array.isArray(review.pins) || review.pins.length > ARTIFACT_REVIEW_LIMITS.pins) {
720
- invalid(`review.pins must contain no more than ${ARTIFACT_REVIEW_LIMITS.pins} items.`);
721
- }
722
- const pins = review.pins.map((pin, index2) => normalizePin(pin, `review.pins[${index2}]`));
723
- const pinIds = new Set(pins.map(({ id: id7 }) => id7));
724
- if (pinIds.size !== pins.length) invalid("review.pins must have unique ids.");
725
- const normalized3 = {
726
- schemaVersion: enumValue(review.schemaVersion, ["1.0.0"], "review.schemaVersion"),
727
- reviewId: boundedString(review.reviewId, "review.reviewId", {
728
- min: 1,
729
- max: ARTIFACT_REVIEW_LIMITS.id,
730
- trim: true
731
- }),
732
- reviewOf: boundedString(review.reviewOf, "review.reviewOf", {
733
- min: 64,
734
- max: 64,
735
- pattern: REVIEW_OF_RE
736
- }),
737
- decision: enumValue(review.decision, ARTIFACT_REVIEW_DECISIONS, "review.decision"),
738
- overall: boundedString(review.overall, "review.overall", {
739
- max: ARTIFACT_REVIEW_LIMITS.text
740
- }),
741
- pins: pins.sort(compareTimestampThenId)
742
- };
743
- if (review.createdAt !== void 0)
744
- normalized3.createdAt = isoTimestamp(review.createdAt, "review.createdAt");
745
- if (review.updatedAt !== void 0)
746
- normalized3.updatedAt = isoTimestamp(review.updatedAt, "review.updatedAt");
747
- return deepFreeze(normalized3);
748
- }
749
- function createArtifactReview({ reviewId, reviewOf, createId = defaultCreateId } = {}) {
750
- const normalizedReviewId = reviewId === void 0 ? dependencyId(createId, "review") : boundedString(reviewId, "reviewId", {
751
- min: 1,
752
- max: ARTIFACT_REVIEW_LIMITS.id,
753
- trim: true
754
- });
755
- return normalizeArtifactReview({
756
- schemaVersion: "1.0.0",
757
- reviewId: normalizedReviewId,
758
- reviewOf: boundedString(reviewOf, "reviewOf", {
759
- min: 64,
760
- max: 64,
761
- pattern: REVIEW_OF_RE
762
- }),
763
- decision: "pending",
764
- overall: "",
765
- pins: []
766
- });
767
- }
768
- function replacePin(review, pin) {
769
- return review.pins.map((candidate) => candidate.id === pin.id ? pin : candidate);
770
- }
771
- function findPin(review, pinId) {
772
- const normalizedId = boundedString(pinId, "pinId", {
773
- min: 1,
774
- max: ARTIFACT_REVIEW_LIMITS.id,
775
- trim: true
776
- });
777
- const pin = review.pins.find(({ id: id7 }) => id7 === normalizedId);
778
- if (!pin) {
779
- throw new ArtifactReviewStateError(
780
- "E_ARTIFACT_REVIEW_PIN_NOT_FOUND",
781
- `Unknown feedback pin: ${normalizedId}`
782
- );
783
- }
784
- return pin;
785
- }
786
- function preserveOptionalReviewTimestamps(review, next, timestamp2) {
787
- if (review.createdAt !== void 0) next.createdAt = review.createdAt;
788
- if (review.updatedAt !== void 0) next.updatedAt = timestamp2;
789
- return next;
790
- }
791
- function reduceArtifactReview(review, action, { createId = defaultCreateId, now = defaultNow } = {}) {
792
- const current = normalizeArtifactReview(review);
793
- if (!action || typeof action !== "object" || Array.isArray(action))
794
- invalid("Review action must be an object.");
795
- const timestamp2 = dependencyTimestamp(now);
796
- let next;
797
- switch (action.type) {
798
- case "add-pin": {
799
- if (current.pins.length >= ARTIFACT_REVIEW_LIMITS.pins) {
800
- invalid(`A review can contain at most ${ARTIFACT_REVIEW_LIMITS.pins} pins.`);
801
- }
802
- const author = normalizeArtifactReviewIdentity(action.author);
803
- const pinInput = action.pin && typeof action.pin === "object" ? action.pin : {};
804
- const pinId = pinInput.id === void 0 ? uniqueDependencyId(createId, "pin", new Set(current.pins.map(({ id: id7 }) => id7))) : boundedString(pinInput.id, "pin.id", {
805
- min: 1,
806
- max: ARTIFACT_REVIEW_LIMITS.id,
807
- trim: true
808
- });
809
- if (current.pins.some(({ id: id7 }) => id7 === pinId)) {
810
- throw new ArtifactReviewStateError(
811
- "E_ARTIFACT_REVIEW_ID_COLLISION",
812
- `Duplicate pin id: ${pinId}`
813
- );
814
- }
815
- const pin = normalizePin({
816
- ...pinInput,
817
- id: pinId,
818
- author,
819
- status: pinInput.status ?? "open",
820
- replies: [],
821
- createdAt: pinInput.createdAt ?? timestamp2,
822
- updatedAt: pinInput.updatedAt ?? timestamp2
823
- });
824
- next = preserveOptionalReviewTimestamps(
825
- current,
826
- {
827
- ...current,
828
- pins: [...current.pins, pin]
829
- },
830
- timestamp2
831
- );
832
- break;
833
- }
834
- case "add-reply": {
835
- const pin = findPin(current, action.pinId);
836
- if (pin.replies.length >= ARTIFACT_REVIEW_LIMITS.replies) {
837
- invalid(`A feedback thread can contain at most ${ARTIFACT_REVIEW_LIMITS.replies} replies.`);
838
- }
839
- const replyId = action.id === void 0 ? uniqueDependencyId(createId, "reply", new Set(pin.replies.map(({ id: id7 }) => id7))) : boundedString(action.id, "reply.id", {
840
- min: 1,
841
- max: ARTIFACT_REVIEW_LIMITS.id,
842
- trim: true
843
- });
844
- if (pin.replies.some(({ id: id7 }) => id7 === replyId)) {
845
- throw new ArtifactReviewStateError(
846
- "E_ARTIFACT_REVIEW_ID_COLLISION",
847
- `Duplicate reply id: ${replyId}`
848
- );
849
- }
850
- const reply2 = normalizeReply({
851
- id: replyId,
852
- author: normalizeArtifactReviewIdentity(action.author),
853
- comment: action.comment,
854
- createdAt: action.createdAt ?? timestamp2
855
- });
856
- const updatedPin = normalizePin({
857
- ...pin,
858
- replies: [...pin.replies, reply2],
859
- updatedAt: timestamp2
860
- });
861
- next = preserveOptionalReviewTimestamps(
862
- current,
863
- {
864
- ...current,
865
- pins: replacePin(current, updatedPin)
866
- },
867
- timestamp2
868
- );
869
- break;
870
- }
871
- case "set-status": {
872
- const pin = findPin(current, action.pinId);
873
- const updatedPin = normalizePin({
874
- ...pin,
875
- status: enumValue(action.status, ARTIFACT_REVIEW_STATUSES, "status"),
876
- updatedAt: timestamp2
877
- });
878
- next = preserveOptionalReviewTimestamps(
879
- current,
880
- {
881
- ...current,
882
- pins: replacePin(current, updatedPin)
883
- },
884
- timestamp2
885
- );
886
- break;
887
- }
888
- case "set-overall":
889
- next = preserveOptionalReviewTimestamps(
890
- current,
891
- {
892
- ...current,
893
- overall: boundedString(action.overall, "overall", { max: ARTIFACT_REVIEW_LIMITS.text })
894
- },
895
- timestamp2
896
- );
897
- break;
898
- case "set-decision":
899
- next = preserveOptionalReviewTimestamps(
900
- current,
901
- {
902
- ...current,
903
- decision: enumValue(action.decision, ARTIFACT_REVIEW_DECISIONS, "decision")
904
- },
905
- timestamp2
906
- );
907
- break;
908
- default:
909
- throw new ArtifactReviewStateError(
910
- "E_ARTIFACT_REVIEW_ACTION_UNKNOWN",
911
- `Unknown artifact review action: ${String(action.type)}`
912
- );
913
- }
914
- return normalizeArtifactReview(next);
915
- }
916
- function createArtifactReviewController({
917
- initialReview = null,
918
- reviewOf,
919
- reviewId,
920
- identity = null,
921
- createId = defaultCreateId,
922
- now = defaultNow
923
- } = {}) {
924
- let review = initialReview === null || initialReview === void 0 ? null : normalizeArtifactReview(initialReview);
925
- if (review && reviewOf !== void 0 && review.reviewOf !== reviewOf) {
926
- throw new ArtifactReviewStateError(
927
- "E_ARTIFACT_REVIEW_DIGEST_MISMATCH",
928
- "The initial review does not match the artifact envelope digest."
929
- );
930
- }
931
- let localIdentity = normalizeArtifactReviewIdentity(identity, { allowEmpty: true });
932
- let activePinId = null;
933
- let destroyed = false;
934
- const listeners = /* @__PURE__ */ new Set();
935
- const assertAlive = () => {
936
- if (destroyed) {
937
- throw new ArtifactReviewStateError(
938
- "E_ARTIFACT_REVIEW_DESTROYED",
939
- "Artifact review controller is destroyed."
940
- );
941
- }
942
- };
943
- const ensureReview = () => {
944
- review ??= createArtifactReview({ reviewId, reviewOf, createId });
945
- return review;
946
- };
947
- const getState = () => deepFreeze({
948
- review,
949
- identity: localIdentity,
950
- activePinId
951
- });
952
- const notify = (change) => {
953
- const state = getState();
954
- for (const listener of [...listeners]) listener(state, deepFreeze({ ...change }));
955
- };
956
- const controller = {
957
- getReview() {
958
- return review;
959
- },
960
- getState,
961
- getIdentity() {
962
- return localIdentity;
963
- },
964
- setIdentity(value) {
965
- assertAlive();
966
- localIdentity = normalizeArtifactReviewIdentity(value, { allowEmpty: true });
967
- notify({ type: "identity" });
968
- return localIdentity;
969
- },
970
- dispatch(action) {
971
- assertAlive();
972
- const authored = action?.type === "add-pin" || action?.type === "add-reply";
973
- const nextAction = authored && action.author === void 0 ? { ...action, author: localIdentity ?? identityRequired() } : action;
974
- const previousPinIds = nextAction?.type === "add-pin" ? new Set(review?.pins.map(({ id: id7 }) => id7) ?? []) : null;
975
- review = reduceArtifactReview(ensureReview(), nextAction, { createId, now });
976
- if (previousPinIds) {
977
- activePinId = review.pins.find(({ id: id7 }) => !previousPinIds.has(id7))?.id ?? activePinId;
978
- }
979
- notify({ type: "review", action: nextAction.type });
980
- return review;
981
- },
982
- replaceReview(value) {
983
- assertAlive();
984
- const next = value === null || value === void 0 ? null : normalizeArtifactReview(value);
985
- if (next && reviewOf !== void 0 && next.reviewOf !== reviewOf) {
986
- throw new ArtifactReviewStateError(
987
- "E_ARTIFACT_REVIEW_DIGEST_MISMATCH",
988
- "The replacement review does not match the artifact envelope digest."
989
- );
990
- }
991
- review = next;
992
- if (activePinId && !review?.pins.some(({ id: id7 }) => id7 === activePinId)) activePinId = null;
993
- notify({ type: "review-replaced" });
994
- return review;
995
- },
996
- selectPin(pinId) {
997
- assertAlive();
998
- if (pinId === null || pinId === void 0) {
999
- activePinId = null;
1000
- } else {
1001
- activePinId = findPin(ensureReview(), pinId).id;
1002
- }
1003
- notify({ type: "selection" });
1004
- return activePinId;
1005
- },
1006
- subscribe(listener) {
1007
- assertAlive();
1008
- if (typeof listener !== "function") invalid("Review subscriber must be a function.");
1009
- listeners.add(listener);
1010
- return () => listeners.delete(listener);
1011
- },
1012
- destroy() {
1013
- if (destroyed) return;
1014
- destroyed = true;
1015
- listeners.clear();
1016
- review = null;
1017
- localIdentity = null;
1018
- activePinId = null;
1019
- }
1020
- };
1021
- return Object.freeze(controller);
1022
- }
1023
- function createElement(document2, tagName, { className, text: text5, attributes = {} } = {}) {
1024
- const element = document2.createElement(tagName);
1025
- if (className) element.className = className;
1026
- if (text5 !== void 0) element.textContent = text5;
1027
- for (const [name, value] of Object.entries(attributes)) {
1028
- if (value !== void 0 && value !== null) element.setAttribute(name, String(value));
1029
- }
1030
- return element;
1031
- }
1032
- function artifactReviewThreadDomId(pinId) {
1033
- return annotationDomIds(pinId).thread;
1034
- }
1035
- function displayTimestamp(timestamp2) {
1036
- const canonical = new Date(timestamp2).toISOString();
1037
- return `${canonical.slice(0, 10)} ${canonical.slice(11, 16)} UTC`;
1038
- }
1039
- function renderReply(document2, reply2) {
1040
- const item2 = createElement(document2, "li", {
1041
- className: "planr-reply",
1042
- attributes: { "data-planr-reply-id": reply2.id }
1043
- });
1044
- const heading = createElement(document2, "header");
1045
- heading.append(createElement(document2, "strong", { text: reply2.author.name }));
1046
- const time = createElement(document2, "time", {
1047
- text: displayTimestamp(reply2.createdAt),
1048
- attributes: { datetime: reply2.createdAt }
1049
- });
1050
- heading.append(time);
1051
- item2.append(heading, createElement(document2, "p", { text: reply2.comment }));
1052
- return item2;
1053
- }
1054
- function renderReplyForm(document2, pin, expanded = false) {
1055
- const fieldId = `${annotationDomIds(pin.id).thread}-reply`;
1056
- const wrapper = createElement(document2, "div", { className: "planr-reply-editor" });
1057
- const toggle = createElement(document2, "button", {
1058
- className: "planr-reply-toggle",
1059
- text: expanded ? "− Reply" : "+ Reply",
1060
- attributes: {
1061
- type: "button",
1062
- id: `${fieldId}-toggle`,
1063
- "data-planr-reply-toggle": pin.id,
1064
- "aria-expanded": String(expanded),
1065
- "aria-controls": `${fieldId}-form`,
1066
- title: expanded ? "Collapse reply" : "Reply to this comment"
1067
- }
1068
- });
1069
- const form = createElement(document2, "form", {
1070
- className: "planr-reply-form",
1071
- attributes: {
1072
- "data-planr-reply-form": pin.id,
1073
- id: `${fieldId}-form`,
1074
- ...expanded ? {} : { hidden: "" }
1075
- }
1076
- });
1077
- const label = createElement(document2, "label", {
1078
- className: "planr-reply-label",
1079
- text: "Reply to thread",
1080
- attributes: { for: fieldId }
1081
- });
1082
- const textarea = createElement(document2, "textarea", {
1083
- attributes: {
1084
- id: fieldId,
1085
- name: "reply",
1086
- maxlength: ARTIFACT_REVIEW_LIMITS.text,
1087
- rows: 2,
1088
- placeholder: "Write a reply…",
1089
- required: "",
1090
- "aria-describedby": "planr-review-error"
1091
- }
1092
- });
1093
- const controls = createElement(document2, "div", { className: "planr-reply-controls" });
1094
- const hint = createElement(document2, "span", {
1095
- className: "planr-reply-hint",
1096
- text: "Ctrl/⌘ + Enter to send"
1097
- });
1098
- const submit = createElement(document2, "button", {
1099
- className: "planr-reply-send",
1100
- attributes: {
1101
- type: "submit",
1102
- disabled: "",
1103
- "aria-label": "Send reply",
1104
- title: "Send reply (Ctrl/⌘ + Enter)"
1105
- }
1106
- });
1107
- const svg = document2.createElementNS("http://www.w3.org/2000/svg", "svg");
1108
- for (const [name, value] of Object.entries({
1109
- viewBox: "0 0 24 24",
1110
- width: "16",
1111
- height: "16",
1112
- fill: "none",
1113
- stroke: "currentColor",
1114
- "stroke-width": "1.8",
1115
- "stroke-linecap": "round",
1116
- "stroke-linejoin": "round",
1117
- "aria-hidden": "true",
1118
- focusable: "false"
1119
- }))
1120
- svg.setAttribute(name, value);
1121
- const path = document2.createElementNS("http://www.w3.org/2000/svg", "path");
1122
- path.setAttribute("d", "M12 19V5m-6 6 6-6 6 6");
1123
- svg.append(path);
1124
- submit.append(svg);
1125
- controls.append(hint, submit);
1126
- form.append(label, textarea, controls);
1127
- wrapper.append(toggle, form);
1128
- return wrapper;
1129
- }
1130
- function renderThread(document2, pin, active, description = {}) {
1131
- const intentLabel = typeof description.intentLabel === "string" ? description.intentLabel.slice(0, 128) : pin.intent;
1132
- const article = createElement(document2, "article", {
1133
- className: `planr-thread${active ? " is-active" : ""}`,
1134
- attributes: {
1135
- id: artifactReviewThreadDomId(pin.id),
1136
- tabindex: "-1",
1137
- "data-planr-pin-id": pin.id,
1138
- "data-planr-intent": pin.intent,
1139
- "data-planr-status": pin.status,
1140
- "aria-controls": annotationDomIds(pin.id).pin,
1141
- "aria-label": `${intentLabel} comment by ${pin.author.name}`,
1142
- "data-planr-unread": description.unread === true ? "true" : "false",
1143
- ...description.compact ? { "data-planr-compact": "true" } : {}
1144
- }
1145
- });
1146
- const header = createElement(document2, "header");
1147
- const byline = createElement(document2, "div", { className: "planr-review-byline" });
1148
- byline.append(
1149
- createElement(document2, "strong", { text: pin.author.name }),
1150
- createElement(document2, "span", { className: "planr-intent", text: intentLabel })
1151
- );
1152
- const time = createElement(document2, "time", {
1153
- text: description.compact ? `${new Date(pin.createdAt).toISOString().slice(11, 16)} UTC` : displayTimestamp(pin.createdAt),
1154
- attributes: { datetime: pin.createdAt, title: displayTimestamp(pin.createdAt) }
1155
- });
1156
- header.append(byline, time);
1157
- const comment = createElement(document2, "p", {
1158
- className: "planr-thread-comment",
1159
- text: pin.comment
1160
- });
1161
- const lifecycle = createElement(document2, "div", { className: "planr-thread-actions" });
1162
- lifecycle.append(
1163
- createElement(document2, "span", {
1164
- className: "planr-thread-status",
1165
- text: pin.status,
1166
- attributes: { title: `Status: ${pin.status}` }
1167
- }),
1168
- createElement(document2, "button", {
1169
- text: pin.status === "resolved" ? "Reopen" : "Resolve",
1170
- attributes: {
1171
- type: "button",
1172
- "data-planr-thread-action": pin.status === "resolved" ? "reopen" : "resolve",
1173
- "data-planr-pin-id": pin.id
1174
- }
1175
- }),
1176
- createElement(document2, "button", {
1177
- text: "Show pin",
1178
- attributes: {
1179
- type: "button",
1180
- "data-planr-thread-focus": pin.id,
1181
- "aria-controls": annotationDomIds(pin.id).pin
1182
- }
1183
- })
1184
- );
1185
- const replies = createElement(document2, "ol", {
1186
- className: "planr-replies",
1187
- attributes: { "aria-label": "Replies" }
1188
- });
1189
- const earlierReplies = description.compact ? Math.max(0, pin.replies.length - (description.replyLimit || 2)) : 0;
1190
- for (const reply2 of pin.replies.slice(earlierReplies))
1191
- replies.append(renderReply(document2, reply2));
1192
- const editor = renderReplyForm(document2, pin, description.replyExpanded);
1193
- article.append(header, comment);
1194
- if (description.compact && pin.comment.length > 240) {
1195
- comment.dataset.planrCommentCollapsed = String(!description.commentExpanded);
1196
- article.append(
1197
- createElement(document2, "button", {
1198
- className: "planr-comment-expand",
1199
- text: description.commentExpanded ? "Show less" : "Read full comment",
1200
- attributes: {
1201
- type: "button",
1202
- id: `${annotationDomIds(pin.id).thread}-expand`,
1203
- "data-planr-comment-expand": pin.id,
1204
- "aria-expanded": String(Boolean(description.commentExpanded))
1205
- }
1206
- })
1207
- );
1208
- }
1209
- if (earlierReplies)
1210
- article.append(
1211
- createElement(document2, "button", {
1212
- className: "planr-history-expand",
1213
- text: `Show ${earlierReplies} earlier ${earlierReplies === 1 ? "reply" : "replies"}`,
1214
- attributes: {
1215
- type: "button",
1216
- id: `${annotationDomIds(pin.id).thread}-history`,
1217
- "data-planr-history-expand": pin.id,
1218
- "aria-expanded": "false"
1219
- }
1220
- })
1221
- );
1222
- if (pin.replies.length) article.append(replies);
1223
- if (description.compact) {
1224
- lifecycle.append(editor.querySelector("[data-planr-reply-toggle]"));
1225
- article.append(lifecycle, editor);
1226
- } else article.append(lifecycle, editor);
1227
- return article;
1228
- }
1229
- function decisionCopy(decision) {
1230
- if (decision === "approved") return "Review approved";
1231
- if (decision === "changes_requested") return "Changes requested";
1232
- return "Decision pending";
1233
- }
1234
- function mountArtifactFeedbackRail({
1235
- root,
1236
- document: document2 = root?.ownerDocument,
1237
- window = document2?.defaultView,
1238
- controller: providedController,
1239
- initialReview = null,
1240
- reviewOf,
1241
- reviewId,
1242
- identity = null,
1243
- createId = defaultCreateId,
1244
- now = defaultNow,
1245
- onSelectPin,
1246
- presentation: initialPresentation = {}
1247
- } = {}) {
1248
- if (!root || !document2 || !window) invalid("A browser root, document, and window are required.");
1249
- const slot = root.querySelector('[data-planr-slot="feedback-rail"]');
1250
- const identityInput = root.querySelector("[data-planr-reviewer-name]");
1251
- const identityStatus = root.querySelector("[data-planr-identity-status]");
1252
- const overall = root.querySelector("#planr-overall-note");
1253
- const decisionStatus = root.querySelector('[data-planr-slot="decision-status"]');
1254
- const decisionButtons = [...root.querySelectorAll("[data-planr-decision]")];
1255
- if (!slot || !identityInput || !overall || !decisionStatus || decisionButtons.length === 0) {
1256
- invalid("Artifact feedback renderer slots are missing.");
1257
- }
1258
- const ownsController = !providedController;
1259
- const controller = providedController ?? createArtifactReviewController({
1260
- initialReview,
1261
- reviewOf,
1262
- reviewId,
1263
- identity,
1264
- createId,
1265
- now
1266
- });
1267
- let destroyed = false;
1268
- let presentation = { ...initialPresentation };
1269
- const replyDrafts = /* @__PURE__ */ new Map();
1270
- const expandedReplies = /* @__PURE__ */ new Set();
1271
- const expandedHistory = /* @__PURE__ */ new Map(), expandedComments = /* @__PURE__ */ new Set();
1272
- let visibleLimit = Number.isInteger(initialPresentation.pageSize) ? initialPresentation.pageSize : Infinity;
1273
- const extraDrafts = /* @__PURE__ */ new Map();
1274
- let overallDirty = false;
1275
- let composing = false;
1276
- let renderQueued = false;
1277
- const captureDrafts = () => {
1278
- for (const form of slot.querySelectorAll("[data-planr-reply-form]")) {
1279
- const field = form.elements.namedItem("reply");
1280
- if (field) replyDrafts.set(form.dataset.planrReplyForm, field.value);
1281
- }
1282
- for (const field of slot.querySelectorAll("[data-planr-draft-key]")) {
1283
- if (typeof field.value === "string")
1284
- extraDrafts.set(field.dataset.planrDraftKey, field.value);
1285
- }
1286
- };
1287
- const snapshotDrafts = () => {
1288
- captureDrafts();
1289
- return cloneFrozenArtifactReview({
1290
- reviewOf: controller.getReview()?.reviewOf ?? reviewOf,
1291
- replies: Object.fromEntries(replyDrafts),
1292
- expandedReplies: [...expandedReplies],
1293
- fields: Object.fromEntries(extraDrafts),
1294
- overall: { value: overall.value, dirty: overallDirty },
1295
- identity: identityInput.value
1296
- });
1297
- };
1298
- const emitDraftChange = () => root.dispatchEvent(
1299
- new window.CustomEvent(ARTIFACT_REVIEW_DRAFT_CHANGE_EVENT, {
1300
- bubbles: true,
1301
- detail: snapshotDrafts()
1302
- })
1303
- );
1304
- const focusDescriptor = () => {
1305
- const element = document2.activeElement;
1306
- if (!element || !slot.contains(element)) return null;
1307
- const thread2 = element.closest("[data-planr-pin-id]");
1308
- return {
1309
- id: element.id,
1310
- pinId: thread2?.dataset.planrPinId,
1311
- draftKey: element.dataset.planrDraftKey,
1312
- action: element.dataset.planrThreadAction,
1313
- showPin: element.dataset.planrThreadFocus,
1314
- tag: element.tagName,
1315
- name: element.name,
1316
- start: element.selectionStart,
1317
- end: element.selectionEnd,
1318
- direction: element.selectionDirection
1319
- };
1320
- };
1321
- const restoreFocus = (descriptor) => {
1322
- if (!descriptor) return;
1323
- const thread2 = descriptor.pinId && document2.getElementById(artifactReviewThreadDomId(descriptor.pinId));
1324
- const target = descriptor.id && document2.getElementById(descriptor.id) || descriptor.draftKey && [...slot.querySelectorAll("[data-planr-draft-key]")].find(
1325
- (field) => field.dataset.planrDraftKey === descriptor.draftKey
1326
- ) || descriptor.action && [...thread2?.querySelectorAll("[data-planr-thread-action]") ?? []].find(
1327
- (button) => button.dataset.planrThreadAction === descriptor.action
1328
- ) || descriptor.showPin && thread2?.querySelector("[data-planr-thread-focus]") || [...thread2?.querySelectorAll("button,input,select,textarea") ?? []].find(
1329
- (field) => field.tagName === descriptor.tag && field.name === descriptor.name
1330
- );
1331
- target?.focus?.({ preventScroll: true });
1332
- if (Number.isInteger(descriptor.start))
1333
- target?.setSelectionRange?.(descriptor.start, descriptor.end, descriptor.direction);
1334
- };
1335
- const showError = (error) => {
1336
- const target = root.querySelector("#planr-review-error");
1337
- if (!target) return;
1338
- target.textContent = error?.message ?? String(error);
1339
- target.hidden = false;
1340
- };
1341
- const clearError = () => {
1342
- const target = root.querySelector("#planr-review-error");
1343
- if (!target) return;
1344
- target.textContent = "";
1345
- target.hidden = true;
1346
- };
1347
- const announce2 = (message) => {
1348
- decisionStatus.textContent = message;
1349
- const live = root.parentElement?.querySelector('[data-planr-slot="review-announcer"]') ?? document2.querySelector('[data-planr-slot="review-announcer"]');
1350
- if (live) live.textContent = message;
1351
- };
1352
- const updateCounts = (pins) => {
1353
- const label = `${pins.length} ${pins.length === 1 ? "comment" : "comments"}`;
1354
- for (const count2 of root.querySelectorAll(
1355
- '[data-planr-action="feedback"] .planr-count, .planr-review-rail > header .planr-count'
1356
- )) {
1357
- count2.textContent = String(pins.length);
1358
- count2.setAttribute("aria-label", label);
1359
- }
1360
- const commentsButton = root.querySelector('[data-planr-action="feedback"]');
1361
- commentsButton?.setAttribute("aria-label", commentsButton.dataset.planrReviewLabel || label);
1362
- if (commentsButton?.dataset.planrReviewLabel)
1363
- commentsButton.setAttribute("aria-description", label);
1364
- };
1365
- const render = ({ capture = true } = {}) => {
1366
- if (composing) {
1367
- renderQueued = true;
1368
- return;
1369
- }
1370
- if (capture) captureDrafts();
1371
- const focus = focusDescriptor();
1372
- const scroll = [];
1373
- for (let node2 = slot; node2 && root.contains(node2); node2 = node2.parentElement)
1374
- scroll.push([node2, node2.scrollTop, node2.scrollLeft]);
1375
- const state = controller.getState();
1376
- const { review, activePinId } = state;
1377
- const allPins = review?.pins ?? [];
1378
- const pins = typeof presentation.filterPin === "function" ? allPins.filter((pin) => presentation.filterPin(pin, state)) : allPins;
1379
- const activeIndex = pins.findIndex((pin) => pin.id === activePinId);
1380
- const visiblePins = pins.slice(0, visibleLimit);
1381
- if (activeIndex >= visibleLimit) visiblePins.push(pins[activeIndex]);
1382
- const fragment = document2.createDocumentFragment();
1383
- const list3 = createElement(document2, "div", {
1384
- className: "planr-thread-list",
1385
- attributes: { "aria-label": "Comment threads" }
1386
- });
1387
- if (pins.length === 0) {
1388
- list3.append(
1389
- createElement(document2, "p", {
1390
- className: "planr-review-empty",
1391
- text: typeof presentation.emptyMessage === "string" ? presentation.emptyMessage : allPins.length ? "No comments match these filters." : "No comments yet. Choose Add comment, then select a point or region in the artifact."
1392
- })
1393
- );
1394
- } else {
1395
- for (const pin of visiblePins) {
1396
- const thread2 = renderThread(document2, pin, pin.id === activePinId, {
1397
- ...presentation.describePin?.(pin, state),
1398
- compact: presentation.compact === true,
1399
- replyLimit: expandedHistory.get(pin.id) || 2,
1400
- commentExpanded: expandedComments.has(pin.id),
1401
- replyExpanded: expandedReplies.has(pin.id)
1402
- });
1403
- presentation.decorateThread?.({ element: thread2, pin, state, document: document2 });
1404
- const reply2 = thread2.querySelector('[name="reply"]');
1405
- if (replyDrafts.has(pin.id)) reply2.value = replyDrafts.get(pin.id);
1406
- thread2.querySelector(".planr-reply-send").disabled = !reply2.value.trim();
1407
- for (const field of thread2.querySelectorAll("[data-planr-draft-key]")) {
1408
- if (extraDrafts.has(field.dataset.planrDraftKey))
1409
- field.value = extraDrafts.get(field.dataset.planrDraftKey);
1410
- }
1411
- list3.append(thread2);
1412
- }
1413
- }
1414
- if (pins.length > visibleLimit)
1415
- list3.append(
1416
- createElement(document2, "button", {
1417
- className: "planr-threads-more",
1418
- text: `Show more comments · ${Math.min(visibleLimit, pins.length)} of ${pins.length}`,
1419
- attributes: { type: "button", "data-planr-threads-more": "" }
1420
- })
1421
- );
1422
- fragment.append(list3);
1423
- slot.replaceChildren(fragment);
1424
- const identityName2 = controller.getIdentity()?.name ?? "";
1425
- if (document2.activeElement !== identityInput) identityInput.value = identityName2;
1426
- if (identityStatus) {
1427
- identityStatus.dataset.planrIdentityReady = String(Boolean(identityName2));
1428
- identityStatus.textContent = identityName2 ? `Comments will appear as ${identityName2}.` : "Used to sign your comments.";
1429
- }
1430
- overall.maxLength = ARTIFACT_REVIEW_LIMITS.text;
1431
- if (!overallDirty && document2.activeElement !== overall) overall.value = review?.overall ?? "";
1432
- for (const button of decisionButtons) {
1433
- button.setAttribute(
1434
- "aria-pressed",
1435
- String(button.dataset.planrDecision === (review?.decision ?? "pending"))
1436
- );
1437
- }
1438
- decisionStatus.textContent = decisionCopy(review?.decision ?? "pending");
1439
- updateCounts(allPins);
1440
- restoreFocus(focus);
1441
- for (const [node2, top, left] of scroll) {
1442
- node2.scrollTop = top;
1443
- node2.scrollLeft = left;
1444
- }
1445
- const openMetric = root.querySelector('[data-planr-metric="open"]');
1446
- if (openMetric)
1447
- openMetric.textContent = `${allPins.filter(({ status }) => status !== "resolved").length} open`;
1448
- };
1449
- const focusThread = (pinId) => {
1450
- const thread2 = document2.getElementById(artifactReviewThreadDomId(pinId));
1451
- thread2?.focus({ preventScroll: true });
1452
- thread2?.scrollIntoView?.({ block: "nearest" });
1453
- };
1454
- const emitReview = (review) => {
1455
- const detail = cloneFrozenArtifactReview(review);
1456
- root.dispatchEvent(
1457
- new window.CustomEvent(ARTIFACT_REVIEW_CHANGE_EVENT, {
1458
- detail,
1459
- bubbles: true
1460
- })
1461
- );
1462
- };
1463
- const unsubscribe = controller.subscribe((state, change) => {
1464
- if (destroyed) return;
1465
- if (["review", "review-replaced", "selection"].includes(change.type)) render();
1466
- if (["review", "review-replaced"].includes(change.type) && state.review)
1467
- emitReview(state.review);
1468
- });
1469
- const onInput = (event) => {
1470
- if (event.target !== identityInput) return;
1471
- try {
1472
- controller.setIdentity(event.target.value ? { name: event.target.value } : null);
1473
- const name = controller.getIdentity()?.name ?? "";
1474
- if (identityStatus) {
1475
- identityStatus.dataset.planrIdentityReady = String(Boolean(name));
1476
- identityStatus.textContent = name ? `Comments will appear as ${name}.` : "Used to sign your comments.";
1477
- }
1478
- clearError();
1479
- } catch (error) {
1480
- showError(error);
1481
- }
1482
- };
1483
- const setReplyExpanded = (pinId, expanded, { focus = false } = {}) => {
1484
- const thread2 = document2.getElementById(artifactReviewThreadDomId(pinId));
1485
- const form = thread2?.querySelector("[data-planr-reply-form]");
1486
- const toggle = thread2?.querySelector("[data-planr-reply-toggle]");
1487
- if (!form || !toggle) return;
1488
- if (expanded) expandedReplies.add(pinId);
1489
- else expandedReplies.delete(pinId);
1490
- form.hidden = !expanded;
1491
- toggle.setAttribute("aria-expanded", String(expanded));
1492
- toggle.textContent = expanded ? "− Reply" : "+ Reply";
1493
- toggle.title = expanded ? "Collapse reply" : "Reply to this comment";
1494
- if (focus)
1495
- (expanded ? form.elements.namedItem("reply") : toggle).focus({ preventScroll: true });
1496
- emitDraftChange();
1497
- };
1498
- const onKeyDown = (event) => {
1499
- const form = event.target?.closest?.("[data-planr-reply-form]");
1500
- if (!form || event.isComposing) return;
1501
- if (event.key === "Escape") {
1502
- event.preventDefault();
1503
- event.stopPropagation();
1504
- setReplyExpanded(form.dataset.planrReplyForm, false, { focus: true });
1505
- } else if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
1506
- event.preventDefault();
1507
- if (form.elements.namedItem("reply").value.trim()) form.requestSubmit();
1508
- }
1509
- };
1510
- const emitSelection = (pinId) => {
1511
- controller.selectPin(pinId);
1512
- root.dispatchEvent(
1513
- new window.CustomEvent(ARTIFACT_REVIEW_SELECT_EVENT, {
1514
- detail: deepFreeze({ pinId, source: "thread" }),
1515
- bubbles: true
1516
- })
1517
- );
1518
- onSelectPin?.(pinId);
1519
- };
1520
- const onClick = (event) => {
1521
- if (event.target.closest?.("[data-planr-threads-more]")) {
1522
- visibleLimit += presentation.pageSize || 40;
1523
- render();
1524
- return;
1525
- }
1526
- const historyToggle = event.target.closest?.("[data-planr-history-expand]");
1527
- if (historyToggle) {
1528
- const id7 = historyToggle.dataset.planrHistoryExpand;
1529
- expandedHistory.set(id7, (expandedHistory.get(id7) || 2) + 20);
1530
- render();
1531
- return;
1532
- }
1533
- const commentToggle = event.target.closest?.("[data-planr-comment-expand]");
1534
- if (commentToggle) {
1535
- const id7 = commentToggle.dataset.planrCommentExpand;
1536
- if (expandedComments.has(id7)) expandedComments.delete(id7);
1537
- else expandedComments.add(id7);
1538
- render();
1539
- return;
1540
- }
1541
- const replyToggle = event.target?.closest?.("[data-planr-reply-toggle]");
1542
- if (replyToggle) {
1543
- setReplyExpanded(
1544
- replyToggle.dataset.planrReplyToggle,
1545
- replyToggle.getAttribute("aria-expanded") !== "true",
1546
- { focus: true }
1547
- );
1548
- return;
1549
- }
1550
- const action = event.target?.closest?.("[data-planr-thread-action]");
1551
- const focus = event.target?.closest?.("[data-planr-thread-focus]");
1552
- if (action) {
1553
- try {
1554
- const pinId = action.dataset.planrPinId;
1555
- controller.dispatch({
1556
- type: "set-status",
1557
- pinId,
1558
- status: action.dataset.planrThreadAction === "resolve" ? "resolved" : "open"
1559
- });
1560
- announce2(
1561
- action.dataset.planrThreadAction === "resolve" ? "Comment resolved" : "Comment reopened"
1562
- );
1563
- focusThread(pinId);
1564
- clearError();
1565
- } catch (error) {
1566
- showError(error);
1567
- }
1568
- return;
1569
- }
1570
- if (focus) emitSelection(focus.dataset.planrThreadFocus);
1571
- };
1572
- const onSubmit = (event) => {
1573
- const form = event.target?.closest?.("[data-planr-reply-form]");
1574
- if (!form) return;
1575
- event.preventDefault();
1576
- const textarea = form.elements.namedItem("reply");
1577
- const comment = textarea.value;
1578
- if (!comment.trim()) return;
1579
- const wasExpanded = expandedReplies.has(form.dataset.planrReplyForm);
1580
- try {
1581
- textarea.setAttribute("aria-invalid", "false");
1582
- textarea.value = "";
1583
- replyDrafts.delete(form.dataset.planrReplyForm);
1584
- expandedReplies.delete(form.dataset.planrReplyForm);
1585
- controller.dispatch({
1586
- type: "add-reply",
1587
- pinId: form.dataset.planrReplyForm,
1588
- comment
1589
- });
1590
- emitDraftChange();
1591
- announce2("Reply added");
1592
- focusThread(form.dataset.planrReplyForm);
1593
- clearError();
1594
- } catch (error) {
1595
- textarea.value = comment;
1596
- replyDrafts.set(form.dataset.planrReplyForm, comment);
1597
- if (wasExpanded) expandedReplies.add(form.dataset.planrReplyForm);
1598
- textarea?.setAttribute("aria-invalid", "true");
1599
- showError(error);
1600
- textarea?.focus();
1601
- }
1602
- };
1603
- const onOverallChange = () => {
1604
- try {
1605
- const value = overall.value;
1606
- controller.dispatch({ type: "set-overall", overall: value });
1607
- overallDirty = false;
1608
- announce2("Overall note updated");
1609
- clearError();
1610
- } catch (error) {
1611
- showError(error);
1612
- }
1613
- };
1614
- const onDecision = (event) => {
1615
- try {
1616
- const selected = event.currentTarget.dataset.planrDecision;
1617
- const decision = controller.getReview()?.decision === selected ? "pending" : selected;
1618
- controller.dispatch({ type: "set-decision", decision });
1619
- announce2(decisionCopy(decision));
1620
- clearError();
1621
- } catch (error) {
1622
- showError(error);
1623
- }
1624
- };
1625
- const onSelect = (event) => {
1626
- if (event.detail?.source === "thread" || typeof event.detail?.pinId !== "string") return;
1627
- try {
1628
- controller.selectPin(event.detail.pinId);
1629
- focusThread(event.detail.pinId);
1630
- } catch (error) {
1631
- showError(error);
1632
- }
1633
- };
1634
- let lastOpened = null;
1635
- const onThreadOpen = (event) => {
1636
- const thread2 = event.target.closest?.(".planr-thread[data-planr-pin-id]");
1637
- if (!thread2 || !slot.contains(thread2)) return;
1638
- const pin = controller.getReview()?.pins.find((entry) => entry.id === thread2.dataset.planrPinId);
1639
- const key = pin && `${pin.id}:${pin.replies.map((reply2) => reply2.id).join(",")}`;
1640
- if (!key || lastOpened === key) return;
1641
- lastOpened = key;
1642
- presentation.onThreadOpen?.(pin.id, controller.getState());
1643
- root.dispatchEvent(
1644
- new window.CustomEvent("planr:artifact-thread-open", {
1645
- bubbles: true,
1646
- detail: Object.freeze({ pinId: pin.id })
1647
- })
1648
- );
1649
- };
1650
- const onDraftInput = (event) => {
1651
- const form = event.target.closest?.("[data-planr-reply-form]");
1652
- if (form)
1653
- form.querySelector(".planr-reply-send").disabled = !form.elements.namedItem("reply").value.trim();
1654
- emitDraftChange();
1655
- };
1656
- const onOverallInput = () => {
1657
- overallDirty = true;
1658
- emitDraftChange();
1659
- };
1660
- const onCompositionStart = () => {
1661
- composing = true;
1662
- };
1663
- const onCompositionEnd = () => {
1664
- composing = false;
1665
- if (renderQueued) {
1666
- renderQueued = false;
1667
- render();
1668
- }
1669
- };
1670
- slot.addEventListener("input", onDraftInput);
1671
- slot.addEventListener("focusin", onThreadOpen);
1672
- slot.addEventListener("click", onThreadOpen);
1673
- slot.addEventListener("compositionstart", onCompositionStart);
1674
- slot.addEventListener("compositionend", onCompositionEnd);
1675
- overall.addEventListener("input", onOverallInput);
1676
- identityInput.addEventListener("input", onInput);
1677
- slot.addEventListener("click", onClick);
1678
- slot.addEventListener("submit", onSubmit);
1679
- slot.addEventListener("keydown", onKeyDown);
1680
- overall.addEventListener("change", onOverallChange);
1681
- for (const button of decisionButtons) button.addEventListener("click", onDecision);
1682
- root.addEventListener(ARTIFACT_REVIEW_SELECT_EVENT, onSelect);
1683
- render();
1684
- return Object.freeze({
1685
- controller,
1686
- getReview: () => controller.getReview(),
1687
- getState: () => controller.getState(),
1688
- getIdentity: () => controller.getIdentity(),
1689
- setIdentity: (value) => controller.setIdentity(value),
1690
- dispatch: (action) => controller.dispatch(action),
1691
- replaceReview: (review) => controller.replaceReview(review),
1692
- selectPin: (pinId) => controller.selectPin(pinId),
1693
- render,
1694
- setPresentation(options = {}) {
1695
- if (options.filterKey !== presentation.filterKey || options.pageSize !== void 0 && options.pageSize !== presentation.pageSize)
1696
- visibleLimit = options.pageSize || presentation.pageSize || Infinity;
1697
- presentation = { ...presentation, ...options };
1698
- render();
1699
- },
1700
- snapshotDrafts,
1701
- getReviewOf: () => controller.getReview()?.reviewOf ?? reviewOf,
1702
- restoreDrafts(snapshot2) {
1703
- const digest8 = controller.getReview()?.reviewOf ?? reviewOf;
1704
- if (!snapshot2 || snapshot2.reviewOf !== digest8) return false;
1705
- if (typeof snapshot2.identity === "string") {
1706
- const name = snapshot2.identity.slice(0, ARTIFACT_REVIEW_LIMITS.authorName);
1707
- controller.setIdentity(name.trim() ? { ...controller.getIdentity(), name } : null);
1708
- }
1709
- for (const [id7, value] of Object.entries(snapshot2.replies ?? {}).slice(
1710
- 0,
1711
- ARTIFACT_REVIEW_LIMITS.pins
1712
- )) {
1713
- if (id7.length <= ARTIFACT_REVIEW_LIMITS.id && typeof value === "string")
1714
- replyDrafts.set(id7, value.slice(0, ARTIFACT_REVIEW_LIMITS.text));
1715
- }
1716
- expandedReplies.clear();
1717
- const expanded = Array.isArray(snapshot2.expandedReplies) ? snapshot2.expandedReplies : [...replyDrafts.keys()];
1718
- for (const id7 of expanded.slice(0, ARTIFACT_REVIEW_LIMITS.pins))
1719
- if (typeof id7 === "string" && id7.length <= ARTIFACT_REVIEW_LIMITS.id)
1720
- expandedReplies.add(id7);
1721
- for (const [key, value] of Object.entries(snapshot2.fields ?? {}).slice(
1722
- 0,
1723
- ARTIFACT_REVIEW_LIMITS.pins
1724
- )) {
1725
- if (key.length <= 512 && typeof value === "string")
1726
- extraDrafts.set(key, value.slice(0, ARTIFACT_REVIEW_LIMITS.text));
1727
- }
1728
- overallDirty = snapshot2.overall?.dirty === true;
1729
- if (overallDirty && typeof snapshot2.overall?.value === "string")
1730
- overall.value = snapshot2.overall.value.slice(0, ARTIFACT_REVIEW_LIMITS.text);
1731
- render({ capture: false });
1732
- return true;
1733
- },
1734
- focusThread,
1735
- destroy() {
1736
- if (destroyed) return;
1737
- destroyed = true;
1738
- unsubscribe();
1739
- slot.removeEventListener("input", onDraftInput);
1740
- slot.removeEventListener("focusin", onThreadOpen);
1741
- slot.removeEventListener("click", onThreadOpen);
1742
- slot.removeEventListener("compositionstart", onCompositionStart);
1743
- slot.removeEventListener("compositionend", onCompositionEnd);
1744
- overall.removeEventListener("input", onOverallInput);
1745
- identityInput.removeEventListener("input", onInput);
1746
- slot.removeEventListener("click", onClick);
1747
- slot.removeEventListener("submit", onSubmit);
1748
- slot.removeEventListener("keydown", onKeyDown);
1749
- overall.removeEventListener("change", onOverallChange);
1750
- for (const button of decisionButtons) button.removeEventListener("click", onDecision);
1751
- root.removeEventListener(ARTIFACT_REVIEW_SELECT_EVENT, onSelect);
1752
- if (ownsController) controller.destroy();
1753
- }
1754
- });
1755
- }