openplanr 3.2.0 → 3.4.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 (411) hide show
  1. package/CHANGELOG.md +73 -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/ship.d.ts.map +1 -1
  10. package/dist/cli/commands/ship.js +2 -0
  11. package/dist/cli/commands/ship.js.map +1 -1
  12. package/dist/cli/commands/spec.d.ts +2 -1
  13. package/dist/cli/commands/spec.d.ts.map +1 -1
  14. package/dist/cli/commands/spec.js +45 -5
  15. package/dist/cli/commands/spec.js.map +1 -1
  16. package/dist/dashboard/.vite/manifest.json +2 -2
  17. package/dist/dashboard/assets/index-Cv4Vwhuw.css +2 -0
  18. package/dist/dashboard/assets/index-CvQAlBy3.js +75 -0
  19. package/dist/dashboard/assets/index-CvQAlBy3.js.map +1 -0
  20. package/dist/dashboard/dashboard-manifest.json +14 -14
  21. package/dist/dashboard/index.html +2 -2
  22. package/dist/services/claude-plugin-service.d.ts +5 -0
  23. package/dist/services/claude-plugin-service.d.ts.map +1 -1
  24. package/dist/services/claude-plugin-service.js +18 -2
  25. package/dist/services/claude-plugin-service.js.map +1 -1
  26. package/dist/services/codex-plugin-service.d.ts.map +1 -1
  27. package/dist/services/codex-plugin-service.js +11 -3
  28. package/dist/services/codex-plugin-service.js.map +1 -1
  29. package/dist/services/design-artifact-service.d.ts +20 -1
  30. package/dist/services/design-artifact-service.d.ts.map +1 -1
  31. package/dist/services/design-artifact-service.js +137 -18
  32. package/dist/services/design-artifact-service.js.map +1 -1
  33. package/dist/services/runtime-manager/codex-discovery.d.ts +1 -3
  34. package/dist/services/runtime-manager/codex-discovery.d.ts.map +1 -1
  35. package/dist/services/runtime-manager/codex-discovery.js +3 -16
  36. package/dist/services/runtime-manager/codex-discovery.js.map +1 -1
  37. package/dist/services/runtime-manager/doctor.d.ts +25 -0
  38. package/dist/services/runtime-manager/doctor.d.ts.map +1 -1
  39. package/dist/services/runtime-manager/doctor.js +480 -0
  40. package/dist/services/runtime-manager/doctor.js.map +1 -1
  41. package/dist/services/runtime-manager/errors.d.ts +12 -0
  42. package/dist/services/runtime-manager/errors.d.ts.map +1 -0
  43. package/dist/services/runtime-manager/errors.js +14 -0
  44. package/dist/services/runtime-manager/errors.js.map +1 -0
  45. package/dist/services/runtime-manager/global-state.d.ts +7 -0
  46. package/dist/services/runtime-manager/global-state.d.ts.map +1 -1
  47. package/dist/services/runtime-manager/global-state.js +116 -0
  48. package/dist/services/runtime-manager/global-state.js.map +1 -1
  49. package/dist/services/runtime-manager/host-version-probe.d.ts +8 -0
  50. package/dist/services/runtime-manager/host-version-probe.d.ts.map +1 -0
  51. package/dist/services/runtime-manager/host-version-probe.js +14 -0
  52. package/dist/services/runtime-manager/host-version-probe.js.map +1 -0
  53. package/dist/services/runtime-manager/install-plan.d.ts +25 -0
  54. package/dist/services/runtime-manager/install-plan.d.ts.map +1 -1
  55. package/dist/services/runtime-manager/install-plan.js +305 -0
  56. package/dist/services/runtime-manager/install-plan.js.map +1 -1
  57. package/dist/services/runtime-manager/inventory.d.ts +6 -0
  58. package/dist/services/runtime-manager/inventory.d.ts.map +1 -1
  59. package/dist/services/runtime-manager/inventory.js +16 -1
  60. package/dist/services/runtime-manager/inventory.js.map +1 -1
  61. package/dist/services/runtime-manager/legacy-adapters.d.ts +9 -0
  62. package/dist/services/runtime-manager/legacy-adapters.d.ts.map +1 -0
  63. package/dist/services/runtime-manager/legacy-adapters.js +187 -0
  64. package/dist/services/runtime-manager/legacy-adapters.js.map +1 -0
  65. package/dist/services/runtime-manager/paths.d.ts +18 -0
  66. package/dist/services/runtime-manager/paths.d.ts.map +1 -0
  67. package/dist/services/runtime-manager/paths.js +83 -0
  68. package/dist/services/runtime-manager/paths.js.map +1 -0
  69. package/dist/services/runtime-manager/runtime-package.d.ts +21 -0
  70. package/dist/services/runtime-manager/runtime-package.d.ts.map +1 -1
  71. package/dist/services/runtime-manager/runtime-package.js +77 -0
  72. package/dist/services/runtime-manager/runtime-package.js.map +1 -1
  73. package/dist/services/runtime-manager/storage.d.ts +47 -0
  74. package/dist/services/runtime-manager/storage.d.ts.map +1 -0
  75. package/dist/services/runtime-manager/storage.js +604 -0
  76. package/dist/services/runtime-manager/storage.js.map +1 -0
  77. package/dist/services/runtime-manager-service.d.ts +7 -17
  78. package/dist/services/runtime-manager-service.d.ts.map +1 -1
  79. package/dist/services/runtime-manager-service.js +32 -1695
  80. package/dist/services/runtime-manager-service.js.map +1 -1
  81. package/dist/services/ship-checks/contract.d.ts +15 -1
  82. package/dist/services/ship-checks/contract.d.ts.map +1 -1
  83. package/dist/services/ship-checks/contract.js +1 -1
  84. package/dist/services/ship-checks/contract.js.map +1 -1
  85. package/dist/services/ship-checks/coverage.d.ts +4 -0
  86. package/dist/services/ship-checks/coverage.d.ts.map +1 -0
  87. package/dist/services/ship-checks/coverage.js +113 -0
  88. package/dist/services/ship-checks/coverage.js.map +1 -0
  89. package/dist/services/ship-checks/discover.d.ts.map +1 -1
  90. package/dist/services/ship-checks/discover.js +5 -1
  91. package/dist/services/ship-checks/discover.js.map +1 -1
  92. package/dist/services/ship-checks/package-contents.d.ts +4 -0
  93. package/dist/services/ship-checks/package-contents.d.ts.map +1 -0
  94. package/dist/services/ship-checks/package-contents.js +91 -0
  95. package/dist/services/ship-checks/package-contents.js.map +1 -0
  96. package/dist/services/ship-checks/packages.d.ts +2 -0
  97. package/dist/services/ship-checks/packages.d.ts.map +1 -1
  98. package/dist/services/ship-checks/packages.js +4 -0
  99. package/dist/services/ship-checks/packages.js.map +1 -1
  100. package/dist/services/ship-checks/scope.js +2 -1
  101. package/dist/services/ship-checks/scope.js.map +1 -1
  102. package/dist/services/spec-service.d.ts +18 -0
  103. package/dist/services/spec-service.d.ts.map +1 -1
  104. package/dist/services/spec-service.js +174 -9
  105. package/dist/services/spec-service.js.map +1 -1
  106. package/dist/templates/spec/spec-shaped.md.hbs +1 -1
  107. package/dist/templates/spec/spec.md.hbs +2 -2
  108. package/dist/utils/splice-managed-block.js +1 -1
  109. package/dist/utils/splice-managed-block.js.map +1 -1
  110. package/docs/CLI.md +86 -2
  111. package/lib/host-packages/adapter-registry.json +5 -5
  112. package/lib/host-packages/capability-map.json +3 -3
  113. package/lib/host-packages/claude/.claude-plugin/marketplace.json +3 -3
  114. package/lib/host-packages/claude/openplanr/.claude-plugin/plugin.json +6 -6
  115. package/lib/host-packages/claude/openplanr/.openplanr-content.json +94 -146
  116. package/lib/host-packages/claude/openplanr/README.md +12 -12
  117. package/lib/host-packages/claude/openplanr/agents/planr-qa.md +5 -3
  118. package/lib/host-packages/claude/openplanr/references/agents/shared/modes/shared/task-context-resolution.md +4 -4
  119. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-artifact-shell.mjs +2 -4
  120. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-document.mjs +110 -25
  121. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-handoff.mjs +851 -57
  122. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-review-state-store.mjs +45 -0
  123. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-review.mjs +65 -74
  124. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-runtime-home.mjs +0 -1
  125. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-share-cli-bridge.mjs +321 -0
  126. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-shared-artifact-support-dependencies-design-support-protocol-contracts-d707e49b.mjs +1652 -0
  127. package/lib/host-packages/{openai/openplanr/runtime/design/scripts/design-shared-artifact-support-protocol-contracts-ea2cd15e.mjs → claude/openplanr/runtime/design/scripts/design-shared-artifact-support-protocol-contracts-9f6918b0.mjs} +537 -5
  128. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-shared-design-support-0bac378d.mjs +137 -0
  129. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design.mjs +374 -61
  130. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +32 -59
  131. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/02-artifact-review-ui.js +138 -133
  132. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/03-protocol-contracts.js +1 -5608
  133. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/04-artifact-review-ui.js +2568 -0
  134. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources.json +10 -74
  135. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/package.json +4 -4
  136. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/share.js +8 -2
  137. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/02-react.js +2 -2
  138. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/09-react-dom-client-public-roots.js +5 -5
  139. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/12-protocol-contracts.js +72 -2
  140. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/13-design-review-experience.js +14 -7
  141. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/15-canvas-engine.js +71 -34
  142. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/21-design-studio.js +28 -14
  143. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources.json +12 -12
  144. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/package.json +6 -2
  145. package/lib/host-packages/{openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.20.0 → claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0}/design-document.schema.json +131 -4
  146. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-review-bundle.schema.json +822 -0
  147. package/lib/host-packages/claude/openplanr/runtime/plan/scripts/design-protocol-contracts.mjs +616 -4775
  148. package/lib/host-packages/claude/openplanr/runtime/plan/scripts/design.mjs +219 -424
  149. package/lib/host-packages/claude/openplanr/runtime/plan/scripts/runtime/packages/protocol/package.json +6 -2
  150. package/lib/host-packages/claude/openplanr/skills/delegate/SKILL.md +2 -1
  151. package/lib/host-packages/claude/openplanr/skills/delegate/references/integration-review.md +26 -20
  152. package/lib/host-packages/claude/openplanr/skills/delegate/references/operator-guide.md +25 -1
  153. package/lib/host-packages/claude/openplanr/skills/delegate/references/run-handoff.md +2 -2
  154. package/lib/host-packages/claude/openplanr/skills/delegate/references/worktree-custody.md +17 -9
  155. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/adapters/claude.mjs +15 -3
  156. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/adapters/codex.mjs +38 -2
  157. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/adapters/native.mjs +5 -0
  158. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/custody.mjs +217 -10
  159. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/handoff.mjs +1080 -0
  160. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/integrate.mjs +96 -201
  161. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/integration-files.mjs +3 -382
  162. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/presentation.mjs +29 -12
  163. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/run-contract.mjs +11 -0
  164. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/run-execution.mjs +1 -1
  165. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/run-lifecycle.mjs +14 -10
  166. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/run-preparation.mjs +4 -0
  167. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/run-record.mjs +2 -2
  168. package/lib/host-packages/claude/openplanr/skills/design/references/design-system.md +17 -2
  169. package/lib/host-packages/claude/openplanr/skills/design/references/generation.md +60 -2
  170. package/lib/host-packages/claude/openplanr/skills/design/references/utilities.md +23 -7
  171. package/lib/host-packages/claude/openplanr/skills/design/schemas/design-document.schema.json +131 -4
  172. package/lib/host-packages/claude/openplanr/skills/design-loop/references/design-system.md +17 -2
  173. package/lib/host-packages/claude/openplanr/skills/design-loop/references/generation.md +60 -2
  174. package/lib/host-packages/claude/openplanr/skills/design-loop/references/utilities.md +23 -7
  175. package/lib/host-packages/claude/openplanr/skills/design-loop/schemas/design-document.schema.json +131 -4
  176. package/lib/host-packages/claude/openplanr/skills/design-review/references/design-system.md +17 -2
  177. package/lib/host-packages/claude/openplanr/skills/design-review/references/generation.md +60 -2
  178. package/lib/host-packages/claude/openplanr/skills/design-review/references/utilities.md +23 -7
  179. package/lib/host-packages/claude/openplanr/skills/design-review/schemas/design-document.schema.json +131 -4
  180. package/lib/host-packages/claude/openplanr/skills/investigate/SKILL.md +2 -1
  181. package/lib/host-packages/claude/openplanr/skills/investigate/references/fail-first.md +40 -0
  182. package/lib/host-packages/claude/openplanr/skills/plan/SKILL.md +21 -11
  183. package/lib/host-packages/claude/openplanr/skills/plan/schemas/design-document.schema.json +131 -4
  184. package/lib/host-packages/claude/openplanr/skills/ship/SKILL.md +51 -18
  185. package/lib/host-packages/claude/openplanr/skills/ship/references/fail-first.md +40 -0
  186. package/lib/host-packages/claude/openplanr/skills/ship/references/result-contract.md +7 -3
  187. package/lib/host-packages/claude/openplanr/skills/spec/SKILL.md +6 -0
  188. package/lib/host-packages/claude/openplanr/skills/spec/references/specification-contract.md +3 -1
  189. package/lib/host-packages/cursor/openplanr/.openplanr-content.json +91 -143
  190. package/lib/host-packages/cursor/openplanr/manifest.json +1 -1
  191. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/references/integration-review.md +26 -20
  192. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/references/operator-guide.md +25 -1
  193. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/references/run-handoff.md +2 -2
  194. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/references/worktree-custody.md +17 -9
  195. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/adapters/claude.mjs +15 -3
  196. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/adapters/codex.mjs +38 -2
  197. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/adapters/native.mjs +5 -0
  198. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/custody.mjs +217 -10
  199. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/handoff.mjs +1080 -0
  200. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/integrate.mjs +96 -201
  201. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/integration-files.mjs +3 -382
  202. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/presentation.mjs +29 -12
  203. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/run-contract.mjs +11 -0
  204. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/run-execution.mjs +1 -1
  205. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/run-lifecycle.mjs +14 -10
  206. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/run-preparation.mjs +4 -0
  207. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/run-record.mjs +2 -2
  208. package/lib/host-packages/cursor/openplanr/rules/planr-delegate.mdc +2 -1
  209. package/lib/host-packages/cursor/openplanr/rules/planr-design/references/design-system.md +17 -2
  210. package/lib/host-packages/cursor/openplanr/rules/planr-design/references/generation.md +60 -2
  211. package/lib/host-packages/cursor/openplanr/rules/planr-design/references/utilities.md +23 -7
  212. package/lib/host-packages/cursor/openplanr/rules/planr-design/schemas/design-document.schema.json +131 -4
  213. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/references/design-system.md +17 -2
  214. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/references/generation.md +60 -2
  215. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/references/utilities.md +23 -7
  216. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/schemas/design-document.schema.json +131 -4
  217. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/references/design-system.md +17 -2
  218. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/references/generation.md +60 -2
  219. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/references/utilities.md +23 -7
  220. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/schemas/design-document.schema.json +131 -4
  221. package/lib/host-packages/cursor/openplanr/rules/planr-investigate/references/fail-first.md +40 -0
  222. package/lib/host-packages/cursor/openplanr/rules/planr-investigate.mdc +2 -1
  223. package/lib/host-packages/cursor/openplanr/rules/planr-plan/schemas/design-document.schema.json +131 -4
  224. package/lib/host-packages/cursor/openplanr/rules/planr-plan.mdc +21 -11
  225. package/lib/host-packages/cursor/openplanr/rules/planr-ship/references/fail-first.md +40 -0
  226. package/lib/host-packages/cursor/openplanr/rules/planr-ship/references/result-contract.md +7 -3
  227. package/lib/host-packages/cursor/openplanr/rules/planr-ship.mdc +51 -18
  228. package/lib/host-packages/cursor/openplanr/rules/planr-spec/references/specification-contract.md +3 -1
  229. package/lib/host-packages/cursor/openplanr/rules/planr-spec.mdc +6 -0
  230. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-artifact-shell.mjs +2 -4
  231. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-document.mjs +110 -25
  232. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-handoff.mjs +851 -57
  233. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-review-state-store.mjs +45 -0
  234. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-review.mjs +65 -74
  235. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-runtime-home.mjs +0 -1
  236. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-share-cli-bridge.mjs +321 -0
  237. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-shared-artifact-support-dependencies-design-support-protocol-contracts-d707e49b.mjs +1652 -0
  238. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/{design-shared-artifact-support-protocol-contracts-ea2cd15e.mjs → design-shared-artifact-support-protocol-contracts-9f6918b0.mjs} +537 -5
  239. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-shared-design-support-0bac378d.mjs +137 -0
  240. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design.mjs +374 -61
  241. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +32 -59
  242. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/02-artifact-review-ui.js +138 -133
  243. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/03-protocol-contracts.js +1 -5608
  244. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/04-artifact-review-ui.js +2568 -0
  245. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources.json +10 -74
  246. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/package.json +4 -4
  247. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/share.js +8 -2
  248. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/02-react.js +2 -2
  249. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/09-react-dom-client-public-roots.js +5 -5
  250. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/12-protocol-contracts.js +72 -2
  251. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/13-design-review-experience.js +14 -7
  252. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/15-canvas-engine.js +71 -34
  253. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/21-design-studio.js +28 -14
  254. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources.json +12 -12
  255. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/package.json +6 -2
  256. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/{v1.20.0 → v1.22.0}/design-document.schema.json +131 -4
  257. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-review-bundle.schema.json +822 -0
  258. package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/design-protocol-contracts.mjs +616 -4775
  259. package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/design.mjs +219 -424
  260. package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/runtime/packages/protocol/package.json +6 -2
  261. package/lib/host-packages/openai/.claude-plugin/marketplace.json +3 -3
  262. package/lib/host-packages/openai/openplanr/.codex-plugin/plugin.json +2 -2
  263. package/lib/host-packages/openai/openplanr/.openplanr-content.json +98 -150
  264. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-artifact-shell.mjs +2 -4
  265. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-document.mjs +110 -25
  266. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-handoff.mjs +851 -57
  267. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-review-state-store.mjs +45 -0
  268. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-review.mjs +65 -74
  269. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-runtime-home.mjs +0 -1
  270. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-share-cli-bridge.mjs +321 -0
  271. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-shared-artifact-support-dependencies-design-support-protocol-contracts-d707e49b.mjs +1652 -0
  272. package/lib/host-packages/{claude/openplanr/runtime/design/scripts/design-shared-artifact-support-protocol-contracts-ea2cd15e.mjs → openai/openplanr/runtime/design/scripts/design-shared-artifact-support-protocol-contracts-9f6918b0.mjs} +537 -5
  273. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-shared-design-support-0bac378d.mjs +137 -0
  274. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design.mjs +374 -61
  275. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +32 -59
  276. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/02-artifact-review-ui.js +138 -133
  277. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/03-protocol-contracts.js +1 -5608
  278. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/04-artifact-review-ui.js +2568 -0
  279. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources.json +10 -74
  280. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/package.json +4 -4
  281. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/share.js +8 -2
  282. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/02-react.js +2 -2
  283. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/09-react-dom-client-public-roots.js +5 -5
  284. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/12-protocol-contracts.js +72 -2
  285. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/13-design-review-experience.js +14 -7
  286. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/15-canvas-engine.js +71 -34
  287. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/21-design-studio.js +28 -14
  288. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources.json +12 -12
  289. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/package.json +6 -2
  290. package/lib/host-packages/{claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.20.0 → openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0}/design-document.schema.json +131 -4
  291. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-review-bundle.schema.json +822 -0
  292. package/lib/host-packages/openai/openplanr/runtime/plan/scripts/design-protocol-contracts.mjs +616 -4775
  293. package/lib/host-packages/openai/openplanr/runtime/plan/scripts/design.mjs +219 -424
  294. package/lib/host-packages/openai/openplanr/runtime/plan/scripts/runtime/packages/protocol/package.json +6 -2
  295. package/lib/host-packages/openai/openplanr/skills/delegate/SKILL.md +2 -1
  296. package/lib/host-packages/openai/openplanr/skills/delegate/openplanr.skill.json +1 -1
  297. package/lib/host-packages/openai/openplanr/skills/delegate/references/integration-review.md +26 -20
  298. package/lib/host-packages/openai/openplanr/skills/delegate/references/operator-guide.md +25 -1
  299. package/lib/host-packages/openai/openplanr/skills/delegate/references/run-handoff.md +2 -2
  300. package/lib/host-packages/openai/openplanr/skills/delegate/references/worktree-custody.md +17 -9
  301. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/adapters/claude.mjs +15 -3
  302. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/adapters/codex.mjs +38 -2
  303. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/adapters/native.mjs +5 -0
  304. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/custody.mjs +217 -10
  305. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/handoff.mjs +1080 -0
  306. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/integrate.mjs +96 -201
  307. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/integration-files.mjs +3 -382
  308. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/presentation.mjs +29 -12
  309. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/run-contract.mjs +11 -0
  310. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/run-execution.mjs +1 -1
  311. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/run-lifecycle.mjs +14 -10
  312. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/run-preparation.mjs +4 -0
  313. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/run-record.mjs +2 -2
  314. package/lib/host-packages/openai/openplanr/skills/design/references/design-system.md +17 -2
  315. package/lib/host-packages/openai/openplanr/skills/design/references/generation.md +60 -2
  316. package/lib/host-packages/openai/openplanr/skills/design/references/utilities.md +23 -7
  317. package/lib/host-packages/openai/openplanr/skills/design/schemas/design-document.schema.json +131 -4
  318. package/lib/host-packages/openai/openplanr/skills/design-loop/references/design-system.md +17 -2
  319. package/lib/host-packages/openai/openplanr/skills/design-loop/references/generation.md +60 -2
  320. package/lib/host-packages/openai/openplanr/skills/design-loop/references/utilities.md +23 -7
  321. package/lib/host-packages/openai/openplanr/skills/design-loop/schemas/design-document.schema.json +131 -4
  322. package/lib/host-packages/openai/openplanr/skills/design-review/references/design-system.md +17 -2
  323. package/lib/host-packages/openai/openplanr/skills/design-review/references/generation.md +60 -2
  324. package/lib/host-packages/openai/openplanr/skills/design-review/references/utilities.md +23 -7
  325. package/lib/host-packages/openai/openplanr/skills/design-review/schemas/design-document.schema.json +131 -4
  326. package/lib/host-packages/openai/openplanr/skills/investigate/SKILL.md +2 -1
  327. package/lib/host-packages/openai/openplanr/skills/investigate/agents/openai.yaml +1 -1
  328. package/lib/host-packages/openai/openplanr/skills/investigate/openplanr.skill.json +12 -1
  329. package/lib/host-packages/openai/openplanr/skills/investigate/references/fail-first.md +40 -0
  330. package/lib/host-packages/openai/openplanr/skills/plan/SKILL.md +21 -11
  331. package/lib/host-packages/openai/openplanr/skills/plan/openplanr.skill.json +1 -1
  332. package/lib/host-packages/openai/openplanr/skills/plan/schemas/design-document.schema.json +131 -4
  333. package/lib/host-packages/openai/openplanr/skills/ship/SKILL.md +51 -18
  334. package/lib/host-packages/openai/openplanr/skills/ship/agents/openai.yaml +1 -1
  335. package/lib/host-packages/openai/openplanr/skills/ship/openplanr.skill.json +12 -1
  336. package/lib/host-packages/openai/openplanr/skills/ship/references/fail-first.md +40 -0
  337. package/lib/host-packages/openai/openplanr/skills/ship/references/result-contract.md +7 -3
  338. package/lib/host-packages/openai/openplanr/skills/spec/SKILL.md +6 -0
  339. package/lib/host-packages/openai/openplanr/skills/spec/openplanr.skill.json +1 -1
  340. package/lib/host-packages/openai/openplanr/skills/spec/references/specification-contract.md +3 -1
  341. package/lib/json-schema.mjs +4 -0
  342. package/package.json +16 -16
  343. package/dist/dashboard/assets/index-BU5fzjyz.css +0 -1
  344. package/dist/dashboard/assets/index-L8qtwqv6.js +0 -572
  345. package/dist/dashboard/assets/index-L8qtwqv6.js.map +0 -1
  346. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-chunked-workspace-client.mjs +0 -555
  347. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-compression.mjs +0 -4180
  348. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-encrypted-workspace-client.mjs +0 -647
  349. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-owner-custody.mjs +0 -129
  350. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-resource-pack.mjs +0 -698
  351. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-runtime-support-6774fd3d5d02.mjs +0 -24
  352. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-share.mjs +0 -1993
  353. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-shared-artifact-support-dependencies-design-support-protocol-contracts-3d9b1a86.mjs +0 -1020
  354. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-shared-protocol-contracts-75a938cc.mjs +0 -222
  355. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-shared-protocol-contracts-b5f28f94.mjs +0 -5778
  356. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-upload-spool.mjs +0 -198
  357. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/04-compression.js +0 -4175
  358. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/05-artifact-sharing.js +0 -65
  359. 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
  360. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/07-artifact-sharing.js +0 -62
  361. 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
  362. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-paste.schema.json +0 -49
  363. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-review-workspace.schema.json +0 -108
  364. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-workspace-create.schema.json +0 -170
  365. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-workspace-event.schema.json +0 -97
  366. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-workspace-revision.schema.json +0 -56
  367. package/lib/host-packages/claude/openplanr/skills/delegate/scripts/integration-transaction.mjs +0 -958
  368. package/lib/host-packages/cursor/openplanr/rules/planr-delegate/scripts/integration-transaction.mjs +0 -958
  369. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-chunked-workspace-client.mjs +0 -555
  370. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-compression.mjs +0 -4180
  371. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-encrypted-workspace-client.mjs +0 -647
  372. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-owner-custody.mjs +0 -129
  373. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-resource-pack.mjs +0 -698
  374. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-runtime-support-6774fd3d5d02.mjs +0 -24
  375. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-share.mjs +0 -1993
  376. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-shared-artifact-support-dependencies-design-support-protocol-contracts-3d9b1a86.mjs +0 -1020
  377. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-shared-protocol-contracts-75a938cc.mjs +0 -222
  378. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-shared-protocol-contracts-b5f28f94.mjs +0 -5778
  379. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-upload-spool.mjs +0 -198
  380. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/04-compression.js +0 -4175
  381. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/05-artifact-sharing.js +0 -65
  382. 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
  383. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/07-artifact-sharing.js +0 -62
  384. 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
  385. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-paste.schema.json +0 -49
  386. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-review-workspace.schema.json +0 -108
  387. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-workspace-create.schema.json +0 -170
  388. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-workspace-event.schema.json +0 -97
  389. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-workspace-revision.schema.json +0 -56
  390. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-chunked-workspace-client.mjs +0 -555
  391. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-compression.mjs +0 -4180
  392. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-encrypted-workspace-client.mjs +0 -647
  393. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-owner-custody.mjs +0 -129
  394. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-resource-pack.mjs +0 -698
  395. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-runtime-support-6774fd3d5d02.mjs +0 -24
  396. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-share.mjs +0 -1993
  397. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-shared-artifact-support-dependencies-design-support-protocol-contracts-3d9b1a86.mjs +0 -1020
  398. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-shared-protocol-contracts-75a938cc.mjs +0 -222
  399. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-shared-protocol-contracts-b5f28f94.mjs +0 -5778
  400. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-upload-spool.mjs +0 -198
  401. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/04-compression.js +0 -4175
  402. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/05-artifact-sharing.js +0 -65
  403. 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
  404. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/07-artifact-sharing.js +0 -62
  405. 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
  406. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-paste.schema.json +0 -49
  407. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-review-workspace.schema.json +0 -108
  408. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-workspace-create.schema.json +0 -170
  409. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-workspace-event.schema.json +0 -97
  410. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-workspace-revision.schema.json +0 -56
  411. package/lib/host-packages/openai/openplanr/skills/delegate/scripts/integration-transaction.mjs +0 -958
@@ -0,0 +1,1652 @@
1
+ import {
2
+ Parser,
3
+ defaultTreeAdapter
4
+ } from "./design-parse5-parser.mjs";
5
+ import {
6
+ NS,
7
+ TAG_NAMES,
8
+ hasUnescapedText
9
+ } from "./design-parse5-tokenizer.mjs";
10
+ import {
11
+ MAX_ARTIFACT_HTML_BYTES,
12
+ validateJson
13
+ } from "./design-shared-artifact-support-protocol-contracts-9f6918b0.mjs";
14
+
15
+ // packages/artifact/lib/artifact/local-document.mjs
16
+ import { createHash } from "node:crypto";
17
+ import { readFileSync, realpathSync, statSync } from "node:fs";
18
+ import { dirname, extname, isAbsolute, relative, resolve } from "node:path";
19
+ import { Script } from "node:vm";
20
+
21
+ // node_modules/entities/dist/escape.js
22
+ var getCodePoint = typeof String.prototype.codePointAt === "function" ? (input, index) => input.codePointAt(index) : (
23
+ // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
24
+ (c, index) => (c.charCodeAt(index) & 64512) === 55296 ? (c.charCodeAt(index) - 55296) * 1024 + c.charCodeAt(index + 1) - 56320 + 65536 : c.charCodeAt(index)
25
+ );
26
+ function getEscaper(regex, map) {
27
+ return function escape(data) {
28
+ let match;
29
+ let lastIndex = 0;
30
+ let result = "";
31
+ while (match = regex.exec(data)) {
32
+ if (lastIndex !== match.index) {
33
+ result += data.substring(lastIndex, match.index);
34
+ }
35
+ result += map.get(match[0].charCodeAt(0));
36
+ lastIndex = match.index + 1;
37
+ }
38
+ return result + data.substring(lastIndex);
39
+ };
40
+ }
41
+ var escapeAttribute = /* @__PURE__ */ getEscaper(/["&\u00A0]/g, /* @__PURE__ */ new Map([
42
+ [34, """],
43
+ [38, "&"],
44
+ [160, " "]
45
+ ]));
46
+ var escapeText = /* @__PURE__ */ getEscaper(/[&<>\u00A0]/g, /* @__PURE__ */ new Map([
47
+ [38, "&amp;"],
48
+ [60, "&lt;"],
49
+ [62, "&gt;"],
50
+ [160, "&nbsp;"]
51
+ ]));
52
+
53
+ // node_modules/parse5/dist/serializer/index.js
54
+ var VOID_ELEMENTS = /* @__PURE__ */ new Set([
55
+ TAG_NAMES.AREA,
56
+ TAG_NAMES.BASE,
57
+ TAG_NAMES.BASEFONT,
58
+ TAG_NAMES.BGSOUND,
59
+ TAG_NAMES.BR,
60
+ TAG_NAMES.COL,
61
+ TAG_NAMES.EMBED,
62
+ TAG_NAMES.FRAME,
63
+ TAG_NAMES.HR,
64
+ TAG_NAMES.IMG,
65
+ TAG_NAMES.INPUT,
66
+ TAG_NAMES.KEYGEN,
67
+ TAG_NAMES.LINK,
68
+ TAG_NAMES.META,
69
+ TAG_NAMES.PARAM,
70
+ TAG_NAMES.SOURCE,
71
+ TAG_NAMES.TRACK,
72
+ TAG_NAMES.WBR
73
+ ]);
74
+ function isVoidElement(node, options) {
75
+ return options.treeAdapter.isElementNode(node) && options.treeAdapter.getNamespaceURI(node) === NS.HTML && VOID_ELEMENTS.has(options.treeAdapter.getTagName(node));
76
+ }
77
+ var defaultOpts = { treeAdapter: defaultTreeAdapter, scriptingEnabled: true };
78
+ function serialize(node, options) {
79
+ const opts = { ...defaultOpts, ...options };
80
+ if (isVoidElement(node, opts)) {
81
+ return "";
82
+ }
83
+ return serializeChildNodes(node, opts);
84
+ }
85
+ function serializeChildNodes(parentNode, options) {
86
+ let html = "";
87
+ const container = options.treeAdapter.isElementNode(parentNode) && options.treeAdapter.getTagName(parentNode) === TAG_NAMES.TEMPLATE && options.treeAdapter.getNamespaceURI(parentNode) === NS.HTML ? options.treeAdapter.getTemplateContent(parentNode) : parentNode;
88
+ const childNodes = options.treeAdapter.getChildNodes(container);
89
+ if (childNodes) {
90
+ for (const currentNode of childNodes) {
91
+ html += serializeNode(currentNode, options);
92
+ }
93
+ }
94
+ return html;
95
+ }
96
+ function serializeNode(node, options) {
97
+ if (options.treeAdapter.isElementNode(node)) {
98
+ return serializeElement(node, options);
99
+ }
100
+ if (options.treeAdapter.isTextNode(node)) {
101
+ return serializeTextNode(node, options);
102
+ }
103
+ if (options.treeAdapter.isCommentNode(node)) {
104
+ return serializeCommentNode(node, options);
105
+ }
106
+ if (options.treeAdapter.isDocumentTypeNode(node)) {
107
+ return serializeDocumentTypeNode(node, options);
108
+ }
109
+ return "";
110
+ }
111
+ function serializeElement(node, options) {
112
+ const tn = options.treeAdapter.getTagName(node);
113
+ return `<${tn}${serializeAttributes(node, options)}>${isVoidElement(node, options) ? "" : `${serializeChildNodes(node, options)}</${tn}>`}`;
114
+ }
115
+ function serializeAttributes(node, { treeAdapter }) {
116
+ let html = "";
117
+ for (const attr2 of treeAdapter.getAttrList(node)) {
118
+ html += " ";
119
+ if (attr2.namespace) {
120
+ switch (attr2.namespace) {
121
+ case NS.XML: {
122
+ html += `xml:${attr2.name}`;
123
+ break;
124
+ }
125
+ case NS.XMLNS: {
126
+ if (attr2.name !== "xmlns") {
127
+ html += "xmlns:";
128
+ }
129
+ html += attr2.name;
130
+ break;
131
+ }
132
+ case NS.XLINK: {
133
+ html += `xlink:${attr2.name}`;
134
+ break;
135
+ }
136
+ default: {
137
+ html += `${attr2.prefix}:${attr2.name}`;
138
+ }
139
+ }
140
+ } else {
141
+ html += attr2.name;
142
+ }
143
+ html += `="${escapeAttribute(attr2.value)}"`;
144
+ }
145
+ return html;
146
+ }
147
+ function serializeTextNode(node, options) {
148
+ const { treeAdapter } = options;
149
+ const content = treeAdapter.getTextNodeContent(node);
150
+ const parent = treeAdapter.getParentNode(node);
151
+ const parentTn = parent && treeAdapter.isElementNode(parent) && treeAdapter.getTagName(parent);
152
+ return parentTn && treeAdapter.getNamespaceURI(parent) === NS.HTML && hasUnescapedText(parentTn, options.scriptingEnabled) ? content : escapeText(content);
153
+ }
154
+ function serializeCommentNode(node, { treeAdapter }) {
155
+ return `<!--${treeAdapter.getCommentNodeContent(node)}-->`;
156
+ }
157
+ function serializeDocumentTypeNode(node, { treeAdapter }) {
158
+ return `<!DOCTYPE ${treeAdapter.getDocumentTypeNodeName(node)}>`;
159
+ }
160
+
161
+ // node_modules/parse5/dist/index.js
162
+ function parse(html, options) {
163
+ return Parser.parse(html, options);
164
+ }
165
+ function parseFragment(fragmentContext, html, options) {
166
+ if (typeof fragmentContext === "string") {
167
+ options = html;
168
+ html = fragmentContext;
169
+ fragmentContext = null;
170
+ }
171
+ const parser = Parser.getFragmentParser(fragmentContext, options);
172
+ parser.tokenizer.write(html, true);
173
+ return parser.getFragment();
174
+ }
175
+
176
+ // packages/artifact/lib/artifact/local-document.mjs
177
+ var MIME = {
178
+ ".png": "image/png",
179
+ ".jpg": "image/jpeg",
180
+ ".jpeg": "image/jpeg",
181
+ ".svg": "image/svg+xml",
182
+ ".webp": "image/webp",
183
+ ".avif": "image/avif",
184
+ ".gif": "image/gif",
185
+ ".woff": "font/woff",
186
+ ".woff2": "font/woff2",
187
+ ".ttf": "font/ttf",
188
+ ".ico": "image/x-icon"
189
+ };
190
+ var children = (node) => [...node.childNodes ?? [], ...node.content?.childNodes ?? []];
191
+ var attr = (node, name) => node.attrs?.find((item2) => item2.name === name);
192
+ var isPropToken = (value) => typeof value === "string" && value.length <= 128 && /^[a-z][a-z0-9-]*(?![\s\S])/u.test(value);
193
+ var text = (node) => children(node).map((item2) => item2.value ?? "").join("");
194
+ function setText(node, value) {
195
+ node.childNodes = [{ nodeName: "#text", value, parentNode: node }];
196
+ }
197
+ function element(name, value) {
198
+ const node = parseFragment(`<${name}></${name}>`).childNodes[0];
199
+ setText(node, value);
200
+ return node;
201
+ }
202
+ function parseBodySource(html) {
203
+ const roots = [];
204
+ const parser = new Parser({ sourceCodeLocationInfo: true });
205
+ const onStartTag = parser.onStartTag.bind(parser);
206
+ parser.onStartTag = (token) => {
207
+ if (token.tagName === "body") roots.push(token);
208
+ onStartTag(token);
209
+ };
210
+ parser.tokenizer.write(html, true);
211
+ const body = parser.document.childNodes.find((node) => node.tagName === "html")?.childNodes.find((node) => node.tagName === "body");
212
+ const root = roots.length === 1 && body?.sourceCodeLocation?.startTag?.startOffset === roots[0].location?.startOffset ? roots[0] : null;
213
+ return { document: parser.document, roots, root };
214
+ }
215
+ function inspectLocalDocumentBody(html) {
216
+ const { root } = parseBodySource(html);
217
+ return root ? { attrs: root.attrs, location: root.location } : null;
218
+ }
219
+ function resolveLocalDocumentFile(root, path, from = root) {
220
+ if (typeof path !== "string" || !path || /^(?:[a-z][a-z\d+.-]*:|\/|\\)/iu.test(path))
221
+ throw new Error(`Expected a local relative asset: ${path}`);
222
+ const candidate = resolve(from, path);
223
+ const inside = (file) => {
224
+ const r = relative(root, file);
225
+ return r !== ".." && !r.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) && !isAbsolute(r);
226
+ };
227
+ if (!inside(candidate)) throw new Error(`Asset escapes design root: ${path}`);
228
+ const actual = realpathSync(candidate);
229
+ if (!inside(actual) || !statSync(actual).isFile())
230
+ throw new Error(`Asset is not a contained regular file: ${path}`);
231
+ return actual;
232
+ }
233
+ function bundleLocalDocument({
234
+ root: inputRoot,
235
+ source,
236
+ sharedStyles = [],
237
+ screenId,
238
+ maxBytes = MAX_ARTIFACT_HTML_BYTES,
239
+ readSource,
240
+ passive = false,
241
+ screenProps
242
+ }) {
243
+ const root = realpathSync(inputRoot);
244
+ const files = /* @__PURE__ */ new Map();
245
+ const mediaStack = /* @__PURE__ */ new Set();
246
+ let svgDepth = 0;
247
+ let cssExpansionBytes = 0;
248
+ let cssExpansions = 0;
249
+ let bytes = 0;
250
+ function read(path, from = root) {
251
+ const checked = readSource?.(path, from);
252
+ const file = checked?.file ?? resolveLocalDocumentFile(root, path, from);
253
+ if (!files.has(file)) {
254
+ const value = checked?.value ?? readFileSync(file);
255
+ bytes += value.length;
256
+ if (bytes > maxBytes || files.size >= 1e3)
257
+ throw new Error("Design source exceeds the local asset budget.");
258
+ files.set(file, value);
259
+ }
260
+ return { file, value: files.get(file) };
261
+ }
262
+ function asset(ref, from) {
263
+ if (/^#/iu.test(ref)) return ref;
264
+ if (/^data:/iu.test(ref)) {
265
+ if (!passive) return ref;
266
+ const match = /^data:([^;,]+)(;base64)?,([\s\S]*)$/iu.exec(ref);
267
+ if (!match || !Object.values(MIME).includes(match[1].toLowerCase()))
268
+ throw new Error("Passive design media must be a supported image or font.");
269
+ if (match[1].toLowerCase() !== "image/svg+xml") return ref;
270
+ const svg = match[2] ? Buffer.from(match[3], "base64").toString("utf8") : decodeURIComponent(match[3]);
271
+ return `data:image/svg+xml;base64,${Buffer.from(passiveSvg(svg, from)).toString("base64")}`;
272
+ }
273
+ const fragmentIndex = ref.indexOf("#");
274
+ const fragment = fragmentIndex < 0 ? "" : ref.slice(fragmentIndex);
275
+ const { file, value } = read(fragmentIndex < 0 ? ref : ref.slice(0, fragmentIndex), from);
276
+ if (!MIME[extname(file).toLowerCase()]) throw new Error(`Unsupported local media: ${ref}`);
277
+ let payload = value;
278
+ if (passive && extname(file).toLowerCase() === ".svg") {
279
+ if (mediaStack.has(file) || mediaStack.size >= 16)
280
+ throw new Error("Circular or excessively nested SVG media cannot be published.");
281
+ mediaStack.add(file);
282
+ try {
283
+ payload = Buffer.from(passiveSvg(value.toString("utf8"), dirname(file)));
284
+ } finally {
285
+ mediaStack.delete(file);
286
+ }
287
+ }
288
+ return `data:${MIME[extname(file).toLowerCase()]};base64,${payload.toString("base64")}${fragment}`;
289
+ }
290
+ function passiveSvg(value, from) {
291
+ if (++svgDepth > 16) throw new Error("Excessively nested SVG media cannot be published.");
292
+ try {
293
+ const fragment = parseFragment(value);
294
+ if (!fragment.childNodes.some((node) => node.tagName === "svg"))
295
+ throw new Error("SVG media must contain an SVG drawing.");
296
+ const queue2 = [...children(fragment)];
297
+ while (queue2.length) {
298
+ const node = queue2.shift();
299
+ if (["script", "foreignObject", "iframe", "object", "embed"].includes(node.tagName)) {
300
+ node.parentNode.childNodes = node.parentNode.childNodes.filter((child) => child !== node);
301
+ continue;
302
+ }
303
+ node.attrs = (node.attrs ?? []).filter((item2) => !/^on/iu.test(item2.name));
304
+ if (node.tagName === "style") setText(node, css(text(node), from));
305
+ for (const item2 of node.attrs) {
306
+ if (item2.name === "style") item2.value = css(item2.value, from);
307
+ if (["href", "src"].includes(item2.name)) item2.value = asset(item2.value, from);
308
+ }
309
+ queue2.unshift(...children(node));
310
+ }
311
+ return serialize(fragment);
312
+ } finally {
313
+ svgDepth--;
314
+ }
315
+ }
316
+ function replaceCss(value, pattern, replacement) {
317
+ const parts = [];
318
+ let offset = 0, outputBytes = 0;
319
+ function append(part) {
320
+ const size = Buffer.byteLength(part);
321
+ outputBytes += size;
322
+ cssExpansionBytes += size;
323
+ if (outputBytes > maxBytes || cssExpansionBytes > maxBytes * 8)
324
+ throw new Error("Stylesheet expansion exceeds the local asset budget.");
325
+ parts.push(part);
326
+ }
327
+ for (const match of value.matchAll(pattern)) {
328
+ append(value.slice(offset, match.index));
329
+ append(replacement(...match));
330
+ offset = match.index + match[0].length;
331
+ }
332
+ append(value.slice(offset));
333
+ return parts.join("");
334
+ }
335
+ function css(value, from, stack = /* @__PURE__ */ new Set()) {
336
+ if (++cssExpansions > 4096)
337
+ throw new Error("Stylesheet expansion complexity exceeds the local asset budget.");
338
+ let result = replaceCss(
339
+ value,
340
+ /@import\s+(?:url\(\s*)?["']([^"']+)["']\s*\)?\s*([^;]*);/giu,
341
+ (_all, ref, media) => {
342
+ const next = read(ref, from);
343
+ if (stack.has(next.file)) throw new Error(`Circular stylesheet import: ${ref}`);
344
+ const expanded = css(
345
+ next.value.toString("utf8"),
346
+ dirname(next.file),
347
+ /* @__PURE__ */ new Set([...stack, next.file])
348
+ );
349
+ return media.trim() ? `@media ${media.trim()}{${expanded}}` : expanded;
350
+ }
351
+ );
352
+ if (/@import\b/iu.test(result)) throw new Error("Use quoted local stylesheet imports.");
353
+ result = replaceCss(
354
+ result,
355
+ /url\(\s*(["']?)(.*?)\1\s*\)/giu,
356
+ (_all, _quote, ref) => `url("${asset(ref, from)}")`
357
+ );
358
+ return replaceCss(result, /<\/style/giu, () => "<\\/style");
359
+ }
360
+ function js(value, label) {
361
+ try {
362
+ new Script(value, { filename: label });
363
+ } catch (error) {
364
+ throw new Error(
365
+ `Use compiled, self-contained browser JavaScript in ${label}: ${error.message}`
366
+ );
367
+ }
368
+ return value.replace(/<\/script/giu, "<\\/script");
369
+ }
370
+ const input = read(source.html);
371
+ const propEntries = Object.entries(screenProps ?? {});
372
+ let document;
373
+ if (propEntries.length) {
374
+ const parsed = parseBodySource(input.value.toString("utf8"));
375
+ if (!parsed.root)
376
+ throw new Error(
377
+ `Screen ${screenId} source ${source.html} requires a single authored <body> root for props; found ${parsed.roots.length}.`
378
+ );
379
+ document = parsed.document;
380
+ } else document = parse(input.value.toString("utf8"));
381
+ let head, body;
382
+ const deferredScripts = [];
383
+ const queue = [...children(document)];
384
+ while (queue.length) {
385
+ const node = queue.shift();
386
+ if (node.tagName === "head") head = node;
387
+ if (node.tagName === "body") body = node;
388
+ if (["base", "iframe", "frame", "frameset", "object", "embed"].includes(node.tagName))
389
+ throw new Error(
390
+ `Unsupported <${node.tagName}> in a local design. Use local controls and button handlers.`
391
+ );
392
+ if (node.tagName === "meta" && attr(node, "http-equiv")?.value.toLowerCase() === "refresh")
393
+ throw new Error("Design screens cannot redirect.");
394
+ if (node.tagName === "style") setText(node, css(text(node), dirname(input.file)));
395
+ if (node.tagName === "link" && attr(node, "rel")?.value.toLowerCase().split(/\s+/u).includes("stylesheet")) {
396
+ const linked = read(attr(node, "href")?.value, dirname(input.file));
397
+ node.tagName = "style";
398
+ node.nodeName = "style";
399
+ node.attrs = [];
400
+ setText(
401
+ node,
402
+ css(linked.value.toString("utf8"), dirname(linked.file), /* @__PURE__ */ new Set([linked.file]))
403
+ );
404
+ }
405
+ if (node.tagName === "script") {
406
+ const src = attr(node, "src");
407
+ if (passive) {
408
+ if (src) read(src.value, dirname(input.file));
409
+ node.parentNode.childNodes = node.parentNode.childNodes.filter((child) => child !== node);
410
+ continue;
411
+ }
412
+ const type = attr(node, "type")?.value.trim().toLowerCase();
413
+ if (type === "module")
414
+ throw new Error("Compile module scripts before using them in a portable design.");
415
+ if (!type || /(?:javascript|ecmascript)/u.test(type)) {
416
+ const linked = src ? read(src.value, dirname(input.file)) : null;
417
+ setText(
418
+ node,
419
+ js(linked ? linked.value.toString("utf8") : text(node), linked?.file ?? input.file)
420
+ );
421
+ if (src && attr(node, "defer")) {
422
+ deferredScripts.push(node);
423
+ node.parentNode.childNodes = node.parentNode.childNodes.filter((child) => child !== node);
424
+ }
425
+ node.attrs = (node.attrs ?? []).filter(
426
+ (item2) => !["src", "async", "defer"].includes(item2.name)
427
+ );
428
+ }
429
+ }
430
+ if (passive) node.attrs = (node.attrs ?? []).filter((item2) => !/^on/iu.test(item2.name));
431
+ for (const item2 of node.attrs ?? []) {
432
+ if (item2.name === "style") item2.value = css(item2.value, dirname(input.file));
433
+ if (["src", "poster"].includes(item2.name))
434
+ item2.value = asset(item2.value, dirname(input.file));
435
+ if (item2.name === "srcset")
436
+ throw new Error("Use a local src and responsive CSS for portable design images.");
437
+ if (["action", "formaction", "target", "formtarget"].includes(item2.name) && item2.value.trim())
438
+ throw new Error("Design forms must use local submit handlers without navigation targets.");
439
+ if (item2.name === "href" && !item2.value.startsWith("#")) {
440
+ if (node.tagName === "link" || node.namespaceURI === "http://www.w3.org/2000/svg")
441
+ item2.value = asset(item2.value, dirname(input.file));
442
+ else if (node.tagName === "a")
443
+ throw new Error('Use data-design-navigate="screen-id" for prototype navigation.');
444
+ }
445
+ }
446
+ queue.unshift(...children(node));
447
+ }
448
+ const prepend = [];
449
+ for (const path of [...sharedStyles, ...source.styles ?? []]) {
450
+ const linked = read(path);
451
+ prepend.push(
452
+ element(
453
+ "style",
454
+ css(linked.value.toString("utf8"), dirname(linked.file), /* @__PURE__ */ new Set([linked.file]))
455
+ )
456
+ );
457
+ }
458
+ head.childNodes = [...prepend, ...head.childNodes];
459
+ for (const node of prepend) node.parentNode = head;
460
+ for (const path of source.scripts ?? []) {
461
+ const linked = read(path);
462
+ if (passive) continue;
463
+ const node = element("script", js(linked.value.toString("utf8"), path));
464
+ node.parentNode = body;
465
+ body.childNodes.push(node);
466
+ }
467
+ for (const node of deferredScripts) {
468
+ node.parentNode = body;
469
+ body.childNodes.push(node);
470
+ }
471
+ body.attrs.push({ name: "data-planr-screen", value: screenId });
472
+ if (propEntries.length) {
473
+ const classes = (attr(body, "class")?.value ?? "").split(/\s+/u).filter(Boolean).filter((item2) => !propEntries.some(([name]) => item2.startsWith(`prop-${name}-`)));
474
+ for (const [name, value] of propEntries) {
475
+ if (!isPropToken(name) || !(typeof value === "boolean" || isPropToken(value)))
476
+ throw new TypeError(
477
+ `Screen ${screenId} source ${source.html} has invalid prop ${name}: ${JSON.stringify(value)}.`
478
+ );
479
+ const attribute = `data-prop-${name}`;
480
+ body.attrs = body.attrs.filter((item2) => item2.name !== attribute);
481
+ body.attrs.push({ name: attribute, value: String(value) });
482
+ const prefix = `prop-${name}-`;
483
+ classes.push(`${prefix}${value}`);
484
+ }
485
+ body.attrs = body.attrs.filter((item2) => item2.name !== "class");
486
+ body.attrs.push({ name: "class", value: classes.join(" ") });
487
+ }
488
+ const html = serialize(document);
489
+ if (Buffer.byteLength(html) > maxBytes)
490
+ throw new Error("Bundled design exceeds the output budget.");
491
+ return {
492
+ html,
493
+ files: [...files.keys()].map((path) => relative(root, path)),
494
+ sourceDigests: Object.fromEntries(
495
+ [...files].map(([path, value]) => [
496
+ relative(root, path),
497
+ createHash("sha256").update(value).digest("hex")
498
+ ])
499
+ ),
500
+ inputBytes: bytes,
501
+ bytes: Buffer.byteLength(html)
502
+ };
503
+ }
504
+
505
+ // packages/protocol/src/design-contracts.mjs
506
+ var DESIGN_DOCUMENT_VERSION = "1.0.0";
507
+ function initialFrameHeight(document) {
508
+ const fixed = document.frames.flatMap(
509
+ ({ height }) => typeof height === "number" && Number.isInteger(height) ? [height] : []
510
+ );
511
+ return fixed.length ? Math.max(...fixed) : 900;
512
+ }
513
+ var freeze = (value) => {
514
+ if (value && typeof value === "object") {
515
+ for (const nested of Object.values(value)) freeze(nested);
516
+ Object.freeze(value);
517
+ }
518
+ return value;
519
+ };
520
+ var FRAME_SCHEMA = {
521
+ type: "array",
522
+ minItems: 1,
523
+ items: {
524
+ type: "object",
525
+ additionalProperties: false,
526
+ required: ["id", "label", "width", "height"],
527
+ properties: {
528
+ id: { $ref: "#/$defs/id" },
529
+ label: { $ref: "#/$defs/text" },
530
+ width: { type: "integer", minimum: 1, maximum: 16384 },
531
+ height: { type: "integer", minimum: 1, maximum: 16384 }
532
+ }
533
+ }
534
+ };
535
+ var DESIGN_DOCUMENT_V1_SCHEMA = freeze({
536
+ $schema: "https://json-schema.org/draft/2020-12/schema",
537
+ $id: "https://openplanr.dev/schemas/v1.9.0/design-document.schema.json",
538
+ "x-openplanr-contract": { id: "design-document", version: "1.9.0" },
539
+ title: "OpenPlanr authored design document",
540
+ type: "object",
541
+ additionalProperties: false,
542
+ required: [
543
+ "kind",
544
+ "schemaVersion",
545
+ "id",
546
+ "title",
547
+ "brief",
548
+ "frames",
549
+ "screens",
550
+ "screenOrder",
551
+ "variants",
552
+ "selectedVariant",
553
+ "defaultView"
554
+ ],
555
+ properties: {
556
+ kind: { const: "openplanr-design-document" },
557
+ schemaVersion: { const: DESIGN_DOCUMENT_VERSION },
558
+ id: { $ref: "#/$defs/id" },
559
+ title: { $ref: "#/$defs/text" },
560
+ brief: {
561
+ type: "object",
562
+ additionalProperties: false,
563
+ required: ["text", "source", "provenance"],
564
+ properties: {
565
+ text: { $ref: "#/$defs/text" },
566
+ source: { enum: ["spec", "png", "describe"] },
567
+ provenance: { enum: ["spec", "inferred"] },
568
+ references: { type: "array", items: { $ref: "#/$defs/text" }, uniqueItems: true }
569
+ }
570
+ },
571
+ designSystem: {
572
+ type: "object",
573
+ additionalProperties: false,
574
+ properties: {
575
+ path: { $ref: "#/$defs/localPath" },
576
+ tokens: { $ref: "#/$defs/localPath" },
577
+ spacing: {
578
+ type: "array",
579
+ minItems: 1,
580
+ uniqueItems: true,
581
+ items: { type: "number", minimum: 0, maximum: 16384 }
582
+ }
583
+ }
584
+ },
585
+ assets: { $ref: "#/$defs/paths" },
586
+ frames: FRAME_SCHEMA,
587
+ screens: {
588
+ type: "array",
589
+ minItems: 1,
590
+ items: {
591
+ type: "object",
592
+ additionalProperties: false,
593
+ required: ["id", "title", "source"],
594
+ properties: {
595
+ id: { $ref: "#/$defs/id" },
596
+ title: { $ref: "#/$defs/text" },
597
+ description: { $ref: "#/$defs/text" },
598
+ source: { $ref: "#/$defs/source" },
599
+ anchors: { $ref: "#/$defs/ids" }
600
+ }
601
+ }
602
+ },
603
+ screenOrder: { type: "array", minItems: 1, items: { $ref: "#/$defs/id" }, uniqueItems: true },
604
+ flows: {
605
+ type: "array",
606
+ items: {
607
+ type: "object",
608
+ additionalProperties: false,
609
+ required: ["id", "title", "screens"],
610
+ properties: {
611
+ id: { $ref: "#/$defs/id" },
612
+ title: { $ref: "#/$defs/text" },
613
+ screens: { type: "array", minItems: 1, items: { $ref: "#/$defs/id" } }
614
+ }
615
+ }
616
+ },
617
+ variants: {
618
+ type: "array",
619
+ minItems: 1,
620
+ items: {
621
+ type: "object",
622
+ additionalProperties: false,
623
+ required: ["id", "label", "status"],
624
+ properties: {
625
+ id: { $ref: "#/$defs/id" },
626
+ label: { $ref: "#/$defs/text" },
627
+ description: { $ref: "#/$defs/text" },
628
+ status: { enum: ["ready", "failed"] },
629
+ issue: { $ref: "#/$defs/text" },
630
+ sources: { type: "object", additionalProperties: { $ref: "#/$defs/source" } }
631
+ },
632
+ if: { properties: { status: { const: "failed" } } },
633
+ then: { required: ["issue"] }
634
+ }
635
+ },
636
+ selectedVariant: { $ref: "#/$defs/id" },
637
+ defaultView: { enum: ["canvas", "prototype", "walkthrough"] }
638
+ },
639
+ $defs: {
640
+ id: { type: "string", minLength: 1, maxLength: 128, pattern: "^[A-Za-z][A-Za-z0-9_-]*$" },
641
+ text: { type: "string", minLength: 1, pattern: "\\S" },
642
+ ids: { type: "array", items: { $ref: "#/$defs/id" }, uniqueItems: true },
643
+ localPath: {
644
+ type: "string",
645
+ minLength: 1,
646
+ description: "Path relative to the authored document directory. No URL, traversal, encoded path, query or fragment.",
647
+ pattern: "^(?!/)(?!.*(?:^|/)\\.{1,2}(?:/|$))(?!.*//)(?!.*[/ ]$)[^\\\\:\\u0000-\\u001F%?#]+$"
648
+ },
649
+ paths: { type: "array", items: { $ref: "#/$defs/localPath" }, uniqueItems: true },
650
+ source: {
651
+ type: "object",
652
+ additionalProperties: false,
653
+ required: ["html"],
654
+ properties: {
655
+ html: { $ref: "#/$defs/localPath" },
656
+ styles: { $ref: "#/$defs/paths" },
657
+ scripts: { $ref: "#/$defs/paths" }
658
+ }
659
+ }
660
+ }
661
+ });
662
+ var DESIGN_DOCUMENT_V120_SCHEMA = freeze({
663
+ ...DESIGN_DOCUMENT_V1_SCHEMA,
664
+ $id: "https://openplanr.dev/schemas/v1.20.0/design-document.schema.json",
665
+ "x-openplanr-contract": { id: "design-document", version: "1.20.0" },
666
+ properties: {
667
+ .../** @type {Record<string, unknown>} */
668
+ DESIGN_DOCUMENT_V1_SCHEMA.properties,
669
+ frames: {
670
+ ...FRAME_SCHEMA,
671
+ items: {
672
+ ...FRAME_SCHEMA.items,
673
+ properties: {
674
+ ...FRAME_SCHEMA.items.properties,
675
+ height: { anyOf: [{ type: "integer", minimum: 1, maximum: 16384 }, { const: "auto" }] }
676
+ }
677
+ }
678
+ },
679
+ layout: {
680
+ type: "object",
681
+ additionalProperties: false,
682
+ properties: {
683
+ boards: {
684
+ type: "object",
685
+ description: "Keys are screenId, screenId/frameId or screenId/frameId/variantId; each ID must exist in the document.",
686
+ additionalProperties: {
687
+ type: "object",
688
+ additionalProperties: false,
689
+ required: ["x", "y"],
690
+ properties: {
691
+ x: { $ref: "#/$defs/coordinate" },
692
+ y: { $ref: "#/$defs/coordinate" },
693
+ title: { $ref: "#/$defs/text" }
694
+ }
695
+ }
696
+ },
697
+ sections: {
698
+ type: "array",
699
+ items: {
700
+ type: "object",
701
+ additionalProperties: false,
702
+ required: ["id", "x", "y", "text"],
703
+ properties: {
704
+ id: { $ref: "#/$defs/id" },
705
+ x: { $ref: "#/$defs/coordinate" },
706
+ y: { $ref: "#/$defs/coordinate" },
707
+ text: { $ref: "#/$defs/text" },
708
+ maxW: { type: "integer", minimum: 1, maximum: 16384 }
709
+ }
710
+ }
711
+ }
712
+ }
713
+ }
714
+ },
715
+ $defs: {
716
+ .../** @type {Record<string, unknown>} */
717
+ DESIGN_DOCUMENT_V1_SCHEMA.$defs,
718
+ coordinate: { type: "number", minimum: -1e7, maximum: 1e7 }
719
+ }
720
+ });
721
+ var PROP_TOKEN_SCHEMA = {
722
+ type: "string",
723
+ minLength: 1,
724
+ maxLength: 128,
725
+ pattern: "^[a-z][a-z0-9-]*(?![\\s\\S])"
726
+ };
727
+ var propTokenPattern = new RegExp(PROP_TOKEN_SCHEMA.pattern, "u");
728
+ var isPropToken2 = (value) => typeof value === "string" && value.length <= PROP_TOKEN_SCHEMA.maxLength && propTokenPattern.test(value);
729
+ var currentDocument = (
730
+ /** @type {{ properties: Record<string, unknown>; [key: string]: unknown }} */
731
+ structuredClone(DESIGN_DOCUMENT_V120_SCHEMA)
732
+ );
733
+ currentDocument.$id = "https://openplanr.dev/schemas/v1.22.0/design-document.schema.json";
734
+ currentDocument["x-openplanr-contract"] = { id: "design-document", version: "1.22.0" };
735
+ currentDocument.properties.schemaVersion = { enum: ["1.0.0", "1.1.0"] };
736
+ var screenSchema = (
737
+ /** @type {{ items: { properties: Record<string, unknown> } }} */
738
+ currentDocument.properties.screens
739
+ );
740
+ screenSchema.items.properties.props = {
741
+ type: "object",
742
+ propertyNames: PROP_TOKEN_SCHEMA,
743
+ additionalProperties: {
744
+ oneOf: [
745
+ {
746
+ type: "object",
747
+ additionalProperties: false,
748
+ required: ["type", "options", "default"],
749
+ properties: {
750
+ type: { const: "enum" },
751
+ options: {
752
+ type: "array",
753
+ minItems: 1,
754
+ uniqueItems: true,
755
+ items: PROP_TOKEN_SCHEMA
756
+ },
757
+ default: PROP_TOKEN_SCHEMA
758
+ }
759
+ },
760
+ {
761
+ type: "object",
762
+ additionalProperties: false,
763
+ required: ["type", "default"],
764
+ properties: { type: { const: "boolean" }, default: { type: "boolean" } }
765
+ }
766
+ ]
767
+ }
768
+ };
769
+ var variantSchema = (
770
+ /** @type {{ items: { properties: Record<string, unknown> } }} */
771
+ currentDocument.properties.variants
772
+ );
773
+ variantSchema.items.properties.props = {
774
+ type: "object",
775
+ propertyNames: { $ref: "#/$defs/id" },
776
+ additionalProperties: {
777
+ type: "object",
778
+ propertyNames: PROP_TOKEN_SCHEMA,
779
+ additionalProperties: { anyOf: [PROP_TOKEN_SCHEMA, { type: "boolean" }] }
780
+ }
781
+ };
782
+ currentDocument.allOf = [
783
+ {
784
+ if: { properties: { schemaVersion: { const: "1.1.0" } }, required: ["schemaVersion"] },
785
+ else: {
786
+ properties: {
787
+ screens: { items: { not: { required: ["props"] } } },
788
+ variants: { items: { not: { required: ["props"] } } }
789
+ }
790
+ }
791
+ }
792
+ ];
793
+ var DESIGN_DOCUMENT_SCHEMA = freeze(currentDocument);
794
+ function validateDesignProps(document) {
795
+ const errors = [];
796
+ const checkToken = (value, path) => {
797
+ if (!isPropToken2(value))
798
+ errors.push(
799
+ `${path}: ${JSON.stringify(value)} must be a lowercase token matching ${PROP_TOKEN_SCHEMA.pattern} with at most ${PROP_TOKEN_SCHEMA.maxLength} characters`
800
+ );
801
+ };
802
+ const screens = new Map(document.screens.map((screen) => [screen.id, screen]));
803
+ for (const [index, screen] of document.screens.entries()) {
804
+ for (const [name, prop] of Object.entries(screen.props ?? {})) {
805
+ const path = `$.screens[${index}].props.${name}`;
806
+ checkToken(name, path);
807
+ if (prop.type === "enum") {
808
+ for (const [optionIndex, option] of prop.options.entries())
809
+ checkToken(option, `${path}.options[${optionIndex}]`);
810
+ checkToken(prop.default, `${path}.default`);
811
+ if (!prop.options.includes(prop.default))
812
+ errors.push(`${path}.default: '${prop.default}' is not an enum option`);
813
+ }
814
+ }
815
+ }
816
+ for (const [index, variant] of document.variants.entries()) {
817
+ for (const [screenId, values] of Object.entries(variant.props ?? {})) {
818
+ const screen = screens.get(screenId);
819
+ const path = `$.variants[${index}].props.${screenId}`;
820
+ if (!screen) {
821
+ errors.push(`${path}: unknown screen '${screenId}'`);
822
+ continue;
823
+ }
824
+ for (const [name, value] of Object.entries(values)) {
825
+ checkToken(name, `${path}.${name}`);
826
+ if (typeof value === "string") checkToken(value, `${path}.${name}`);
827
+ const props = screen.props ?? {};
828
+ const prop = Object.hasOwn(props, name) ? props[name] : void 0;
829
+ if (!prop) errors.push(`${path}.${name}: unknown prop '${name}' on screen '${screenId}'`);
830
+ else if (prop.type === "boolean" && typeof value !== "boolean")
831
+ errors.push(`${path}.${name}: expected a boolean, received ${JSON.stringify(value)}`);
832
+ else if (prop.type === "enum" && (typeof value !== "string" || !prop.options.includes(value)))
833
+ errors.push(`${path}.${name}: ${JSON.stringify(value)} is not an enum option`);
834
+ }
835
+ }
836
+ }
837
+ return errors;
838
+ }
839
+ function validateDesignDocument(value) {
840
+ const errors = validateJson(value, DESIGN_DOCUMENT_SCHEMA).map(
841
+ ({ path, detail }) => `${path}: ${detail}`
842
+ );
843
+ if (value?.schemaVersion === "1.0.0" && ["screens", "variants"].some(
844
+ (field) => Array.isArray(value[field]) && value[field].some((item2) => item2 && Object.hasOwn(item2, "props"))
845
+ ))
846
+ errors.push('$.schemaVersion: props require schemaVersion "1.1.0"');
847
+ if (errors.length > 0) return { ok: false, errors };
848
+ errors.push(...validateDesignProps(value));
849
+ for (const field of ["frames", "screens", "flows", "variants"]) {
850
+ const seen = /* @__PURE__ */ new Set();
851
+ for (const [index, item2] of (value[field] ?? []).entries()) {
852
+ if (seen.has(item2.id))
853
+ errors.push(`$.${field}[${index}].id: duplicate identity '${item2.id}'`);
854
+ seen.add(item2.id);
855
+ }
856
+ }
857
+ const screenIds = new Set(value.screens.map(({ id: id2 }) => id2));
858
+ const orderedIds = new Set(value.screenOrder);
859
+ for (const id2 of value.screenOrder) {
860
+ if (!screenIds.has(id2)) errors.push(`$.screenOrder: unknown screen '${id2}'`);
861
+ }
862
+ for (const id2 of screenIds) {
863
+ if (!orderedIds.has(id2)) errors.push(`$.screenOrder: missing screen '${id2}'`);
864
+ }
865
+ for (const [index, flow] of (value.flows ?? []).entries()) {
866
+ for (const id2 of flow.screens) {
867
+ if (!screenIds.has(id2)) errors.push(`$.flows[${index}].screens: unknown screen '${id2}'`);
868
+ }
869
+ }
870
+ for (const [index, variant] of value.variants.entries()) {
871
+ for (const id2 of Object.keys(variant.sources ?? {})) {
872
+ if (!screenIds.has(id2)) errors.push(`$.variants[${index}].sources: unknown screen '${id2}'`);
873
+ }
874
+ }
875
+ const frameIds = new Set(value.frames.map(({ id: id2 }) => id2));
876
+ const variantIds = new Set(value.variants.map(({ id: id2 }) => id2));
877
+ for (const [key, position] of Object.entries(value.layout?.boards ?? {})) {
878
+ const parts = key.split("/");
879
+ const path = `$.layout.boards['${key}']`;
880
+ if (parts.length > 3 || parts.some((id2) => !/^[A-Za-z][A-Za-z0-9_-]{0,127}$/.test(id2))) {
881
+ errors.push(`${path}: expected screenId, screenId/frameId or screenId/frameId/variantId`);
882
+ } else {
883
+ const [screenId, frameId, variantId] = parts;
884
+ if (!screenIds.has(screenId)) errors.push(`${path}: unknown screen '${screenId}'`);
885
+ if (frameId !== void 0 && !frameIds.has(frameId))
886
+ errors.push(`${path}: unknown frame '${frameId}'`);
887
+ if (variantId !== void 0 && !variantIds.has(variantId))
888
+ errors.push(`${path}: unknown variant '${variantId}'`);
889
+ }
890
+ for (const axis of ["x", "y"]) {
891
+ if (!Number.isFinite(position[axis]))
892
+ errors.push(`${path}.${axis}: expected a finite coordinate`);
893
+ }
894
+ }
895
+ const sectionIds = /* @__PURE__ */ new Set();
896
+ for (const [index, section] of (value.layout?.sections ?? []).entries()) {
897
+ if (sectionIds.has(section.id))
898
+ errors.push(`$.layout.sections[${index}].id: duplicate identity '${section.id}'`);
899
+ sectionIds.add(section.id);
900
+ for (const axis of ["x", "y"]) {
901
+ if (!Number.isFinite(section[axis]))
902
+ errors.push(`$.layout.sections[${index}].${axis}: expected a finite coordinate`);
903
+ }
904
+ }
905
+ const selected = value.variants.find(({ id: id2 }) => id2 === value.selectedVariant);
906
+ if (!selected) errors.push(`$.selectedVariant: unknown variant '${value.selectedVariant}'`);
907
+ else if (selected.status !== "ready")
908
+ errors.push("$.selectedVariant: selected variant must be ready");
909
+ for (const [index, spacing] of (value.designSystem?.spacing ?? []).entries()) {
910
+ if (!Number.isFinite(spacing))
911
+ errors.push(`$.designSystem.spacing[${index}]: expected a finite spacing value`);
912
+ }
913
+ return { ok: errors.length === 0, errors };
914
+ }
915
+ function assertDesignDocument(value) {
916
+ const result = validateDesignDocument(value);
917
+ if (!result.ok) throw new TypeError(`Invalid design document:
918
+ ${result.errors.join("\n")}`);
919
+ return value;
920
+ }
921
+
922
+ // packages/protocol/src/canonical-json.mjs
923
+ var hasOwn = (value, key) => Object.hasOwn(value, key);
924
+ function assertUnicodeScalarString(value, path) {
925
+ for (let index = 0; index < value.length; index += 1) {
926
+ const code = value.charCodeAt(index);
927
+ if (code >= 55296 && code <= 56319) {
928
+ const next = value.charCodeAt(index + 1);
929
+ if (!(next >= 56320 && next <= 57343)) {
930
+ throw new TypeError(`JCS cannot canonicalize a lone high surrogate at ${path}.`);
931
+ }
932
+ index += 1;
933
+ } else if (code >= 56320 && code <= 57343) {
934
+ throw new TypeError(`JCS cannot canonicalize a lone low surrogate at ${path}.`);
935
+ }
936
+ }
937
+ }
938
+ function serialize2(value, path, seen) {
939
+ if (value === null) return "null";
940
+ if (typeof value === "boolean") return value ? "true" : "false";
941
+ if (typeof value === "string") {
942
+ assertUnicodeScalarString(value, path);
943
+ return JSON.stringify(value);
944
+ }
945
+ if (typeof value === "number") {
946
+ if (!Number.isFinite(value)) throw new TypeError(`JCS requires a finite number at ${path}.`);
947
+ return JSON.stringify(value);
948
+ }
949
+ if (typeof value !== "object")
950
+ throw new TypeError(`JCS cannot canonicalize ${typeof value} at ${path}.`);
951
+ if (seen.has(value)) throw new TypeError(`JCS cannot canonicalize a cycle at ${path}.`);
952
+ seen.add(value);
953
+ try {
954
+ if (Array.isArray(value)) {
955
+ const entries2 = [];
956
+ for (let index = 0; index < value.length; index += 1) {
957
+ if (!hasOwn(value, index))
958
+ throw new TypeError(`JCS cannot canonicalize a sparse array at ${path}[${index}].`);
959
+ entries2.push(serialize2(value[index], `${path}[${index}]`, seen));
960
+ }
961
+ return `[${entries2.join(",")}]`;
962
+ }
963
+ const prototype = Object.getPrototypeOf(value);
964
+ if (prototype !== Object.prototype && prototype !== null) {
965
+ throw new TypeError(`JCS requires a plain JSON object at ${path}.`);
966
+ }
967
+ const entries = Object.keys(value).sort().map((key) => {
968
+ assertUnicodeScalarString(key, `${path} key`);
969
+ return `${JSON.stringify(key)}:${serialize2(value[key], `${path}.${key}`, seen)}`;
970
+ });
971
+ return `{${entries.join(",")}}`;
972
+ } finally {
973
+ seen.delete(value);
974
+ }
975
+ }
976
+ function canonicalizeJson(value) {
977
+ return serialize2(value, "$", /* @__PURE__ */ new Set());
978
+ }
979
+ var SHA256_K = /* @__PURE__ */ new Int32Array([
980
+ 1116352408,
981
+ 1899447441,
982
+ 3049323471,
983
+ 3921009573,
984
+ 961987163,
985
+ 1508970993,
986
+ 2453635748,
987
+ 2870763221,
988
+ 3624381080,
989
+ 310598401,
990
+ 607225278,
991
+ 1426881987,
992
+ 1925078388,
993
+ 2162078206,
994
+ 2614888103,
995
+ 3248222580,
996
+ 3835390401,
997
+ 4022224774,
998
+ 264347078,
999
+ 604807628,
1000
+ 770255983,
1001
+ 1249150122,
1002
+ 1555081692,
1003
+ 1996064986,
1004
+ 2554220882,
1005
+ 2821834349,
1006
+ 2952996808,
1007
+ 3210313671,
1008
+ 3336571891,
1009
+ 3584528711,
1010
+ 113926993,
1011
+ 338241895,
1012
+ 666307205,
1013
+ 773529912,
1014
+ 1294757372,
1015
+ 1396182291,
1016
+ 1695183700,
1017
+ 1986661051,
1018
+ 2177026350,
1019
+ 2456956037,
1020
+ 2730485921,
1021
+ 2820302411,
1022
+ 3259730800,
1023
+ 3345764771,
1024
+ 3516065817,
1025
+ 3600352804,
1026
+ 4094571909,
1027
+ 275423344,
1028
+ 430227734,
1029
+ 506948616,
1030
+ 659060556,
1031
+ 883997877,
1032
+ 958139571,
1033
+ 1322822218,
1034
+ 1537002063,
1035
+ 1747873779,
1036
+ 1955562222,
1037
+ 2024104815,
1038
+ 2227730452,
1039
+ 2361852424,
1040
+ 2428436474,
1041
+ 2756734187,
1042
+ 3204031479,
1043
+ 3329325298
1044
+ ]);
1045
+ var rotr = (value, bits) => value >>> bits | value << 32 - bits;
1046
+ function sha256Hex(value) {
1047
+ const candidate = typeof value === "string" ? new TextEncoder().encode(value) : value;
1048
+ if (!ArrayBuffer.isView(candidate) || Object.prototype.toString.call(candidate) !== "[object Uint8Array]") {
1049
+ throw new TypeError("sha256Hex expects a string or Uint8Array.");
1050
+ }
1051
+ const input = new Uint8Array(candidate.buffer, candidate.byteOffset, candidate.byteLength);
1052
+ const paddedLength = Math.ceil((input.length + 9) / 64) * 64;
1053
+ const bytes = new Uint8Array(paddedLength);
1054
+ bytes.set(input);
1055
+ bytes[input.length] = 128;
1056
+ const view = new DataView(bytes.buffer);
1057
+ const bitLength = BigInt(input.length) * 8n;
1058
+ view.setUint32(paddedLength - 8, Number(bitLength >> 32n & 0xffffffffn));
1059
+ view.setUint32(paddedLength - 4, Number(bitLength & 0xffffffffn));
1060
+ let h0 = 1779033703;
1061
+ let h1 = 3144134277;
1062
+ let h2 = 1013904242;
1063
+ let h3 = 2773480762;
1064
+ let h4 = 1359893119;
1065
+ let h5 = 2600822924;
1066
+ let h6 = 528734635;
1067
+ let h7 = 1541459225;
1068
+ const words = new Int32Array(64);
1069
+ for (let offset = 0; offset < bytes.length; offset += 64) {
1070
+ for (let index = 0; index < 16; index += 1) words[index] = view.getUint32(offset + index * 4);
1071
+ for (let index = 16; index < 64; index += 1) {
1072
+ const s0 = rotr(words[index - 15], 7) ^ rotr(words[index - 15], 18) ^ words[index - 15] >>> 3;
1073
+ const s1 = rotr(words[index - 2], 17) ^ rotr(words[index - 2], 19) ^ words[index - 2] >>> 10;
1074
+ words[index] = words[index - 16] + s0 + words[index - 7] + s1 | 0;
1075
+ }
1076
+ let a = h0;
1077
+ let b = h1;
1078
+ let c = h2;
1079
+ let d = h3;
1080
+ let e = h4;
1081
+ let f = h5;
1082
+ let g = h6;
1083
+ let h = h7;
1084
+ for (let index = 0; index < 64; index += 1) {
1085
+ const s1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
1086
+ const choice = e & f ^ ~e & g;
1087
+ const temp1 = h + s1 + choice + SHA256_K[index] + words[index] | 0;
1088
+ const s0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
1089
+ const majority = a & b ^ a & c ^ b & c;
1090
+ const temp2 = s0 + majority | 0;
1091
+ h = g;
1092
+ g = f;
1093
+ f = e;
1094
+ e = d + temp1 | 0;
1095
+ d = c;
1096
+ c = b;
1097
+ b = a;
1098
+ a = temp1 + temp2 | 0;
1099
+ }
1100
+ h0 = h0 + a | 0;
1101
+ h1 = h1 + b | 0;
1102
+ h2 = h2 + c | 0;
1103
+ h3 = h3 + d | 0;
1104
+ h4 = h4 + e | 0;
1105
+ h5 = h5 + f | 0;
1106
+ h6 = h6 + g | 0;
1107
+ h7 = h7 + h | 0;
1108
+ }
1109
+ return [h0, h1, h2, h3, h4, h5, h6, h7].map((part) => (part >>> 0).toString(16).padStart(8, "0")).join("");
1110
+ }
1111
+ function deepFreeze(value) {
1112
+ if (value && typeof value === "object" && !Object.isFrozen(value)) {
1113
+ for (const nested of Object.values(value)) deepFreeze(nested);
1114
+ Object.freeze(value);
1115
+ }
1116
+ return value;
1117
+ }
1118
+ function assertPlainDataAt(value, label, depth, seen) {
1119
+ if (depth > 64) throw new TypeError(`${label} exceeds the maximum nesting depth.`);
1120
+ if (value === null || ["string", "boolean"].includes(typeof value)) return;
1121
+ if (typeof value === "number" && Number.isFinite(value)) return;
1122
+ if (typeof value !== "object" || seen.has(value))
1123
+ throw new TypeError(`${label} must be finite, acyclic JSON.`);
1124
+ if (!Array.isArray(value) && ![Object.prototype, null].includes(Object.getPrototypeOf(value)))
1125
+ throw new TypeError(`${label} must contain only plain JSON objects.`);
1126
+ seen.add(value);
1127
+ for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(value))) {
1128
+ if (["__proto__", "prototype", "constructor"].includes(key) || !Object.hasOwn(descriptor, "value"))
1129
+ throw new TypeError(`${label} contains a forbidden property.`);
1130
+ assertPlainDataAt(descriptor.value, label, depth + 1, seen);
1131
+ }
1132
+ seen.delete(value);
1133
+ }
1134
+ function assertPlainData(value, label) {
1135
+ assertPlainDataAt(value, label, 0, /* @__PURE__ */ new Set());
1136
+ }
1137
+
1138
+ // packages/protocol/src/design-review-bundle-contracts.mjs
1139
+ var DESIGN_WORKSPACE_VERSION = "1.0.0";
1140
+ var designProperties = (
1141
+ /** @type {Record<string, { items: { properties: Record<string, unknown>; required: string[] } }>} */
1142
+ structuredClone(DESIGN_DOCUMENT_V1_SCHEMA.properties)
1143
+ );
1144
+ for (const key of ["kind", "schemaVersion", "brief", "assets", "designSystem"])
1145
+ delete designProperties[key];
1146
+ delete designProperties.screens.items.properties.source;
1147
+ designProperties.screens.items.required = ["id", "title"];
1148
+ delete designProperties.variants.items.properties.sources;
1149
+ var DESIGN_REVIEW_BUNDLE_SCHEMA = {
1150
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1151
+ $id: "https://openplanr.dev/schemas/v1.9.0/design-review-bundle.schema.json",
1152
+ "x-openplanr-contract": { id: "design-review-bundle", version: "1.9.0" },
1153
+ type: "object",
1154
+ additionalProperties: false,
1155
+ properties: {
1156
+ kind: { const: "openplanr-design-review-bundle" },
1157
+ schemaVersion: { const: DESIGN_WORKSPACE_VERSION },
1158
+ design: {
1159
+ type: "object",
1160
+ additionalProperties: false,
1161
+ properties: designProperties,
1162
+ required: [
1163
+ "id",
1164
+ "title",
1165
+ "frames",
1166
+ "screens",
1167
+ "screenOrder",
1168
+ "variants",
1169
+ "selectedVariant",
1170
+ "defaultView"
1171
+ ]
1172
+ },
1173
+ envelope: {
1174
+ type: "object",
1175
+ required: ["schemaVersion", "artifacts", "viewer"]
1176
+ },
1177
+ entries: {
1178
+ type: "array",
1179
+ minItems: 1,
1180
+ maxItems: 256,
1181
+ items: {
1182
+ type: "object",
1183
+ additionalProperties: false,
1184
+ required: ["artifactId", "screenId", "variantId", "frameId"],
1185
+ properties: Object.fromEntries(
1186
+ ["artifactId", "screenId", "variantId", "frameId"].map((key) => [
1187
+ key,
1188
+ { type: "string", minLength: 1, maxLength: 128 }
1189
+ ])
1190
+ )
1191
+ }
1192
+ },
1193
+ state: {
1194
+ type: ["object", "null"],
1195
+ additionalProperties: false,
1196
+ properties: {
1197
+ positions: {
1198
+ type: "object",
1199
+ additionalProperties: {
1200
+ type: "object",
1201
+ additionalProperties: false,
1202
+ required: ["x", "y"],
1203
+ properties: {
1204
+ x: { type: "number", minimum: -1e7, maximum: 1e7 },
1205
+ y: { type: "number", minimum: -1e7, maximum: 1e7 }
1206
+ }
1207
+ }
1208
+ }
1209
+ }
1210
+ },
1211
+ revision: { type: "string", minLength: 1, maxLength: 128 },
1212
+ verification: {
1213
+ type: ["object", "null"],
1214
+ additionalProperties: false,
1215
+ properties: {
1216
+ status: { enum: ["verified", "unverified", "failed", "pending"] }
1217
+ }
1218
+ }
1219
+ },
1220
+ required: ["kind", "schemaVersion", "design", "envelope", "entries", "revision"],
1221
+ $defs: structuredClone(DESIGN_DOCUMENT_V1_SCHEMA.$defs)
1222
+ };
1223
+
1224
+ // packages/protocol/src/review-experience-contracts.mjs
1225
+ var text2 = { type: "string", maxLength: 16384 };
1226
+ var id = { type: "string", minLength: 1, maxLength: 128 };
1227
+ var digest = { type: "string", pattern: "^[a-f0-9]{64}$" };
1228
+ var texts = { type: "array", maxItems: 256, items: text2 };
1229
+ var closed = (properties, required = Object.keys(properties)) => ({
1230
+ type: "object",
1231
+ additionalProperties: false,
1232
+ properties,
1233
+ required
1234
+ });
1235
+ var list = (items, maxItems = 256) => ({ type: "array", maxItems, items });
1236
+ var schema = (name, properties, required) => ({
1237
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1238
+ $id: `https://openplanr.dev/schemas/v1.10.0/${name}.schema.json`,
1239
+ "x-openplanr-contract": { id: name, version: "1.10.0" },
1240
+ ...closed(properties, required)
1241
+ });
1242
+ var DESIGN_REVIEW_CONTEXT_SCHEMA = schema(
1243
+ "design-review-context",
1244
+ {
1245
+ kind: { const: "openplanr-design-review-context" },
1246
+ schemaVersion: { const: "1.0.0" },
1247
+ designId: id,
1248
+ brief: closed({ purpose: text2, requests: { ...texts, maxItems: 3 }, audience: text2 }, [
1249
+ "purpose",
1250
+ "requests"
1251
+ ]),
1252
+ revisionSummary: text2,
1253
+ implementation: closed({
1254
+ tokens: list(closed({ name: id, value: text2, description: text2 }, ["name", "value"]), 512),
1255
+ components: list(
1256
+ closed(
1257
+ {
1258
+ id,
1259
+ name: text2,
1260
+ screenIds: list(id),
1261
+ anchorIds: list(id),
1262
+ states: list(closed({ name: id, description: text2 })),
1263
+ notes: text2,
1264
+ responsive: text2,
1265
+ accessibility: text2
1266
+ },
1267
+ ["id", "name"]
1268
+ )
1269
+ ),
1270
+ responsive: texts,
1271
+ accessibility: texts
1272
+ })
1273
+ },
1274
+ ["kind", "schemaVersion", "designId", "brief", "implementation"]
1275
+ );
1276
+ var DESIGN_FINGERPRINT_SCHEMA = closed({
1277
+ screenId: id,
1278
+ variantId: id,
1279
+ frameId: id,
1280
+ contentDigest: digest,
1281
+ guidanceDigest: digest
1282
+ });
1283
+ var bundleV11 = {
1284
+ .../** @type {MutableSchema} */
1285
+ structuredClone(DESIGN_REVIEW_BUNDLE_SCHEMA),
1286
+ $id: "https://openplanr.dev/schemas/v1.10.0/design-review-bundle.schema.json",
1287
+ "x-openplanr-contract": { id: "design-review-bundle", version: "1.10.0" }
1288
+ };
1289
+ Object.assign(bundleV11.properties, {
1290
+ schemaVersion: { const: "1.1.0" },
1291
+ reviewContext: DESIGN_REVIEW_CONTEXT_SCHEMA,
1292
+ contextDigest: digest,
1293
+ fingerprints: list(DESIGN_FINGERPRINT_SCHEMA)
1294
+ });
1295
+ bundleV11.required.push("reviewContext", "contextDigest", "fingerprints");
1296
+ var DESIGN_REVIEW_BUNDLE_V11_SCHEMA = bundleV11;
1297
+ var bundleV12 = (
1298
+ /** @type {MutableSchema} */
1299
+ structuredClone(DESIGN_REVIEW_BUNDLE_V11_SCHEMA)
1300
+ );
1301
+ bundleV12.$id = "https://openplanr.dev/schemas/v1.16.0/design-review-bundle.schema.json";
1302
+ bundleV12["x-openplanr-contract"] = { id: "design-review-bundle", version: "1.16.0" };
1303
+ Object.assign(bundleV12.properties, {
1304
+ schemaVersion: { const: "1.2.0" },
1305
+ envelope: {
1306
+ type: "object",
1307
+ required: ["schemaVersion", "sources", "artifacts", "viewer"],
1308
+ properties: { schemaVersion: { const: "1.1.0" } }
1309
+ },
1310
+ entries: {
1311
+ .../** @type {Record<string, unknown>} */
1312
+ bundleV12.properties.entries,
1313
+ maxItems: 4096
1314
+ },
1315
+ fingerprints: list(DESIGN_FINGERPRINT_SCHEMA, 4096)
1316
+ });
1317
+ var bundleCurrent = (
1318
+ /** @type {MutableSchema} */
1319
+ structuredClone(bundleV12)
1320
+ );
1321
+ bundleCurrent.$id = "https://openplanr.dev/schemas/v1.20.0/design-review-bundle.schema.json";
1322
+ bundleCurrent["x-openplanr-contract"] = { id: "design-review-bundle", version: "1.20.0" };
1323
+ bundleCurrent.properties.schemaVersion = { enum: ["1.1.0", "1.2.0"] };
1324
+ bundleCurrent.properties.envelope = bundleV11.properties.envelope;
1325
+ bundleCurrent.allOf = [
1326
+ {
1327
+ if: { properties: { schemaVersion: { const: "1.2.0" } } },
1328
+ then: { properties: { envelope: bundleV12.properties.envelope } }
1329
+ }
1330
+ ];
1331
+ var currentDesign = (
1332
+ /** @type {MutableSchema} */
1333
+ bundleCurrent.properties.design
1334
+ );
1335
+ for (const key of ["frames", "layout"])
1336
+ currentDesign.properties[key] = /** @type {Record<string, unknown>} */
1337
+ DESIGN_DOCUMENT_V120_SCHEMA.properties[key];
1338
+ bundleCurrent.$defs = structuredClone(DESIGN_DOCUMENT_V120_SCHEMA.$defs);
1339
+ var currentEntries = (
1340
+ /** @type {{ items: { properties: Record<string, unknown> } }} */
1341
+ bundleCurrent.properties.entries
1342
+ );
1343
+ currentEntries.items.properties.height = { const: "auto" };
1344
+ var bundleProps = (
1345
+ /** @type {MutableSchema} */
1346
+ structuredClone(bundleCurrent)
1347
+ );
1348
+ bundleProps.$id = "https://openplanr.dev/schemas/v1.22.0/design-review-bundle.schema.json";
1349
+ bundleProps["x-openplanr-contract"] = { id: "design-review-bundle", version: "1.22.0" };
1350
+ var propsDesign = (
1351
+ /** @type {MutableSchema} */
1352
+ bundleProps.properties.design
1353
+ );
1354
+ var authoredProperties = (
1355
+ /** @type {Record<string, unknown>} */
1356
+ DESIGN_DOCUMENT_SCHEMA.properties
1357
+ );
1358
+ propsDesign.properties.schemaVersion = authoredProperties.schemaVersion;
1359
+ for (const key of ["screens", "variants"]) {
1360
+ const projected = (
1361
+ /** @type {{ items: { properties: Record<string, unknown> } }} */
1362
+ propsDesign.properties[key]
1363
+ );
1364
+ const authored = (
1365
+ /** @type {{ items: { properties: Record<string, unknown> } }} */
1366
+ authoredProperties[key]
1367
+ );
1368
+ projected.items.properties.props = authored.items.properties.props;
1369
+ }
1370
+ propsDesign.allOf = structuredClone(DESIGN_DOCUMENT_SCHEMA.allOf);
1371
+ var item = closed(
1372
+ {
1373
+ pinId: id,
1374
+ reviewId: id,
1375
+ screenId: id,
1376
+ revisionId: id,
1377
+ text: text2,
1378
+ refinement: text2,
1379
+ stale: { type: "boolean" },
1380
+ author: text2,
1381
+ reviewOf: digest,
1382
+ source: text2
1383
+ },
1384
+ ["pinId", "text"]
1385
+ );
1386
+ var DESIGN_HANDOFF_CONTENT_SCHEMA = closed({
1387
+ summary: text2,
1388
+ agreedChanges: list(item, 1e4),
1389
+ openQuestions: list(item, 1e4),
1390
+ deferred: list(item, 1e4),
1391
+ rejected: list(item, 1e4)
1392
+ });
1393
+ var DESIGN_HANDOFF_SCHEMA = schema(
1394
+ "design-review-handoff",
1395
+ {
1396
+ kind: { const: "openplanr-design-review-handoff" },
1397
+ schemaVersion: { const: "1.0.0" },
1398
+ title: text2,
1399
+ version: { type: "integer", minimum: 1 },
1400
+ status: { enum: ["draft", "approved"] },
1401
+ basis: closed({
1402
+ designId: id,
1403
+ sourceRevision: digest,
1404
+ contextDigest: digest,
1405
+ reviewOf: digest,
1406
+ selectedVariant: id,
1407
+ feedbackDigest: digest,
1408
+ verificationDigest: digest,
1409
+ feedbackWatermark: { type: "integer", minimum: 0 }
1410
+ }),
1411
+ content: DESIGN_HANDOFF_CONTENT_SCHEMA,
1412
+ contentHash: digest,
1413
+ markdown: { type: "string", maxLength: 2097152 },
1414
+ affectedScreens: list(id),
1415
+ verificationGaps: texts,
1416
+ reviewNotes: list(closed({ reviewId: id, text: text2 }), 1e4),
1417
+ approval: closed({ contentHash: digest, at: { type: "string", format: "date-time" } })
1418
+ },
1419
+ [
1420
+ "kind",
1421
+ "schemaVersion",
1422
+ "title",
1423
+ "version",
1424
+ "status",
1425
+ "basis",
1426
+ "content",
1427
+ "contentHash",
1428
+ "markdown",
1429
+ "affectedScreens",
1430
+ "verificationGaps",
1431
+ "reviewNotes"
1432
+ ]
1433
+ );
1434
+ var DESIGN_REVIEW_METADATA_PAYLOAD_SCHEMA = {
1435
+ ...schema(
1436
+ "design-review-metadata-payload",
1437
+ {
1438
+ schemaVersion: { const: "1.0.0" },
1439
+ kind: { enum: ["category", "disposition"] },
1440
+ author: { ...text2, minLength: 1, maxLength: 160 },
1441
+ reviewOf: digest,
1442
+ pinId: id,
1443
+ category: { enum: ["question", "suggestion", "blocker"] },
1444
+ disposition: { enum: ["accepted", "deferred", "rejected"] },
1445
+ reason: text2,
1446
+ updatedAt: { type: "string", format: "date-time" }
1447
+ },
1448
+ ["schemaVersion", "kind", "author", "reviewOf", "pinId", "updatedAt"]
1449
+ ),
1450
+ allOf: [
1451
+ {
1452
+ if: { properties: { kind: { const: "category" } } },
1453
+ then: { required: ["category"], not: { required: ["disposition"] } }
1454
+ },
1455
+ {
1456
+ if: { properties: { kind: { const: "disposition" } } },
1457
+ then: { required: ["disposition", "reason"], not: { required: ["category"] } }
1458
+ }
1459
+ ]
1460
+ };
1461
+ var payloadV11 = {
1462
+ .../** @type {MutableSchema} */
1463
+ structuredClone(DESIGN_REVIEW_METADATA_PAYLOAD_SCHEMA),
1464
+ $id: "https://openplanr.dev/schemas/v1.11.0/design-review-metadata-payload.schema.json",
1465
+ "x-openplanr-contract": { id: "design-review-metadata-payload", version: "1.11.0" }
1466
+ };
1467
+ Object.assign(payloadV11.properties, {
1468
+ schemaVersion: { const: "1.1.0" },
1469
+ category: { enum: ["question", "suggestion", "change-request", "blocker"] }
1470
+ });
1471
+ function assertReviewExperience(value, contract) {
1472
+ const errors = validateJson(value, contract);
1473
+ if (errors.length)
1474
+ throw new TypeError(
1475
+ `Invalid ${contract["x-openplanr-contract"]?.id ?? "review data"}: ${errors.slice(0, 4).map((item2) => `${item2.path} ${item2.detail}`).join("; ")}`
1476
+ );
1477
+ return value;
1478
+ }
1479
+ var REVIEW_EXPERIENCE_SCHEMAS = Object.freeze({
1480
+ "design-review-context": DESIGN_REVIEW_CONTEXT_SCHEMA,
1481
+ "design-review-bundle": DESIGN_REVIEW_BUNDLE_V11_SCHEMA,
1482
+ "design-review-handoff": DESIGN_HANDOFF_SCHEMA,
1483
+ "design-review-metadata-payload": DESIGN_REVIEW_METADATA_PAYLOAD_SCHEMA
1484
+ });
1485
+
1486
+ // packages/design/lib/design/context.mjs
1487
+ import { createHash as createHash2 } from "node:crypto";
1488
+ import { existsSync, readdirSync, readFileSync as readFileSync2, realpathSync as realpathSync2 } from "node:fs";
1489
+ import { dirname as dirname2, join, resolve as resolve2 } from "node:path";
1490
+ var reviewDigest = (value) => createHash2("sha256").update(canonicalizeJson(value)).digest("hex");
1491
+ function emptyReviewContext(document) {
1492
+ return {
1493
+ kind: "openplanr-design-review-context",
1494
+ schemaVersion: "1.0.0",
1495
+ designId: document.id,
1496
+ brief: { purpose: "", requests: [] },
1497
+ implementation: { tokens: [], components: [], responsive: [], accessibility: [] }
1498
+ };
1499
+ }
1500
+ function loadReviewContext(root, document, { readSource } = {}) {
1501
+ const file = join(root, "review-context.json");
1502
+ if (!existsSync(file)) return emptyReviewContext(document);
1503
+ const context = JSON.parse(
1504
+ readSource ? readSource("review-context.json", root).value.toString("utf8") : readFileSync2(resolveLocalDocumentFile(root, "review-context.json"), "utf8")
1505
+ );
1506
+ assertReviewExperience(context, DESIGN_REVIEW_CONTEXT_SCHEMA);
1507
+ if (context.designId !== document.id)
1508
+ throw new Error("Review context belongs to a different design.");
1509
+ const screens = new Set(document.screenOrder);
1510
+ const ids = /* @__PURE__ */ new Set();
1511
+ for (const component of context.implementation.components) {
1512
+ if (ids.has(component.id)) throw new Error("Review component identities must be unique.");
1513
+ ids.add(component.id);
1514
+ if (component.screenIds?.some((id2) => !screens.has(id2)))
1515
+ throw new Error(`Component ${component.id} references an unknown screen.`);
1516
+ }
1517
+ if (/(?:file:\/\/|\/(?:Users|home|private|tmp|var|etc|opt|Volumes)\/|[A-Za-z]:\\\\|\\\\\\\\)/u.test(
1518
+ JSON.stringify(context)
1519
+ ))
1520
+ throw new Error(
1521
+ "Review context contains a local filesystem path. Use share-safe implementation guidance."
1522
+ );
1523
+ return context;
1524
+ }
1525
+ function reviewFingerprints({ document, context, screen, variant, frame, sourceDigests }) {
1526
+ const components = context.implementation.components.filter(
1527
+ (component) => !component.screenIds?.length || component.screenIds.includes(screen.id)
1528
+ );
1529
+ const values = Object.hasOwn(variant.props ?? {}, screen.id) ? variant.props[screen.id] : {};
1530
+ return {
1531
+ screenId: screen.id,
1532
+ variantId: variant.id,
1533
+ frameId: frame.id,
1534
+ contentDigest: reviewDigest({
1535
+ files: Object.entries(sourceDigests).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0),
1536
+ width: frame.width,
1537
+ height: frame.height,
1538
+ ...screen.props === void 0 ? {} : {
1539
+ props: Object.fromEntries(
1540
+ Object.entries(screen.props).map(([name, declaration]) => [
1541
+ name,
1542
+ Object.hasOwn(values, name) ? values[name] : declaration.default
1543
+ ])
1544
+ )
1545
+ }
1546
+ }),
1547
+ guidanceDigest: reviewDigest({
1548
+ title: screen.title,
1549
+ description: screen.description ?? "",
1550
+ anchors: screen.anchors ?? [],
1551
+ variant: { label: variant.label, description: variant.description ?? "" },
1552
+ frameLabel: frame.label,
1553
+ components,
1554
+ tokens: context.implementation.tokens,
1555
+ responsive: context.implementation.responsive,
1556
+ accessibility: context.implementation.accessibility
1557
+ })
1558
+ };
1559
+ }
1560
+ function bundleDesignRevision(current, state = {}) {
1561
+ const { document } = current;
1562
+ const pick = (value, keys) => Object.fromEntries(
1563
+ keys.filter((key) => value?.[key] !== void 0).map((key) => [key, structuredClone(value[key])])
1564
+ );
1565
+ const context = current.reviewContext ?? emptyReviewContext(document);
1566
+ return {
1567
+ kind: "openplanr-design-review-bundle",
1568
+ schemaVersion: current.envelope.schemaVersion === "1.1.0" ? "1.2.0" : "1.1.0",
1569
+ design: {
1570
+ ...document.screens.some((screen) => screen.props !== void 0) || document.variants.some((variant) => variant.props !== void 0) ? { schemaVersion: document.schemaVersion } : {},
1571
+ ...pick(document, [
1572
+ "id",
1573
+ "title",
1574
+ "defaultView",
1575
+ "selectedVariant",
1576
+ "screenOrder",
1577
+ "frames",
1578
+ "flows",
1579
+ "layout"
1580
+ ]),
1581
+ screens: document.screens.map(
1582
+ (screen) => pick(screen, ["id", "title", "description", "anchors", "props"])
1583
+ ),
1584
+ selectedVariant: document.variants.some(
1585
+ (variant) => variant.id === state.selectedVariant && variant.status === "ready"
1586
+ ) ? state.selectedVariant : document.selectedVariant,
1587
+ variants: document.variants.filter((variant) => variant.status === "ready").map((variant) => pick(variant, ["id", "label", "status", "props"]))
1588
+ },
1589
+ envelope: structuredClone(current.envelope),
1590
+ entries: structuredClone(current.entries),
1591
+ state: {},
1592
+ revision: current.revision,
1593
+ verification: pick(current.verification ?? {}, ["status"]),
1594
+ reviewContext: context,
1595
+ contextDigest: current.contextDigest ?? reviewDigest(context),
1596
+ fingerprints: current.fingerprints ?? []
1597
+ };
1598
+ }
1599
+ var localRoot = (file) => realpathSync2(dirname2(resolve2(file)));
1600
+ function listDesignRevisions(file) {
1601
+ const root = localRoot(file);
1602
+ const pointer = JSON.parse(readFileSync2(join(root, ".design/current.json"), "utf8"));
1603
+ const revisions = readdirSync(join(root, ".design/revisions")).filter((name) => /^[a-f0-9]{64}$/u.test(name)).map((revision) => {
1604
+ const value = JSON.parse(
1605
+ readFileSync2(join(root, ".design/revisions", revision, "render.json"), "utf8")
1606
+ );
1607
+ return {
1608
+ revision,
1609
+ createdAt: value.manifest.generated_at,
1610
+ summary: value.reviewContext?.revisionSummary ?? "",
1611
+ fingerprints: value.fingerprints ?? []
1612
+ };
1613
+ }).sort((a, b) => b.createdAt.localeCompare(a.createdAt));
1614
+ return { revisions, currentRevision: pointer.revision };
1615
+ }
1616
+ function readDesignRevision(file, revision) {
1617
+ if (!/^[a-f0-9]{64}$/u.test(revision)) throw new Error("Invalid design revision identity.");
1618
+ const root = localRoot(file);
1619
+ const value = JSON.parse(
1620
+ readFileSync2(
1621
+ resolveLocalDocumentFile(root, `.design/revisions/${revision}/render.json`),
1622
+ "utf8"
1623
+ )
1624
+ );
1625
+ return bundleDesignRevision(value);
1626
+ }
1627
+
1628
+ export {
1629
+ serialize,
1630
+ parse,
1631
+ parseFragment,
1632
+ inspectLocalDocumentBody,
1633
+ resolveLocalDocumentFile,
1634
+ bundleLocalDocument,
1635
+ initialFrameHeight,
1636
+ DESIGN_DOCUMENT_SCHEMA,
1637
+ validateDesignProps,
1638
+ assertDesignDocument,
1639
+ canonicalizeJson,
1640
+ sha256Hex,
1641
+ deepFreeze,
1642
+ assertPlainData,
1643
+ DESIGN_HANDOFF_CONTENT_SCHEMA,
1644
+ DESIGN_HANDOFF_SCHEMA,
1645
+ assertReviewExperience,
1646
+ reviewDigest,
1647
+ emptyReviewContext,
1648
+ loadReviewContext,
1649
+ reviewFingerprints,
1650
+ listDesignRevisions,
1651
+ readDesignRevision
1652
+ };