openplanr 3.4.0 → 3.6.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 (530) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/dist/cli/commands/backlog-commands.d.ts +3 -0
  3. package/dist/cli/commands/backlog-commands.d.ts.map +1 -0
  4. package/dist/cli/commands/backlog-commands.js +60 -0
  5. package/dist/cli/commands/backlog-commands.js.map +1 -0
  6. package/dist/cli/commands/company.d.ts.map +1 -1
  7. package/dist/cli/commands/company.js +17 -0
  8. package/dist/cli/commands/company.js.map +1 -1
  9. package/dist/cli/commands/design.d.ts +3 -0
  10. package/dist/cli/commands/design.d.ts.map +1 -0
  11. package/dist/cli/commands/design.js +137 -0
  12. package/dist/cli/commands/design.js.map +1 -0
  13. package/dist/cli/commands/groups/operations.d.ts.map +1 -1
  14. package/dist/cli/commands/groups/operations.js +2 -0
  15. package/dist/cli/commands/groups/operations.js.map +1 -1
  16. package/dist/cli/commands/planning-artifacts.d.ts.map +1 -1
  17. package/dist/cli/commands/planning-artifacts.js +13 -5
  18. package/dist/cli/commands/planning-artifacts.js.map +1 -1
  19. package/dist/dashboard/.vite/manifest.json +1 -1
  20. package/dist/dashboard/assets/{index-CvQAlBy3.js → index-C_OquZVk.js} +2 -2
  21. package/dist/dashboard/assets/{index-CvQAlBy3.js.map → index-C_OquZVk.js.map} +1 -1
  22. package/dist/dashboard/dashboard-manifest.json +13 -13
  23. package/dist/dashboard/index.html +1 -1
  24. package/dist/services/artifact-service.d.ts.map +1 -1
  25. package/dist/services/artifact-service.js +13 -6
  26. package/dist/services/artifact-service.js.map +1 -1
  27. package/dist/services/company-export-service.d.ts +41 -0
  28. package/dist/services/company-export-service.d.ts.map +1 -0
  29. package/dist/services/company-export-service.js +429 -0
  30. package/dist/services/company-export-service.js.map +1 -0
  31. package/dist/services/company-sync-service.d.ts +24 -1
  32. package/dist/services/company-sync-service.d.ts.map +1 -1
  33. package/dist/services/company-sync-service.js +36 -19
  34. package/dist/services/company-sync-service.js.map +1 -1
  35. package/dist/services/design-artifact-service.d.ts +22 -0
  36. package/dist/services/design-artifact-service.d.ts.map +1 -1
  37. package/dist/services/design-artifact-service.js +76 -16
  38. package/dist/services/design-artifact-service.js.map +1 -1
  39. package/dist/services/runtime-manager/runtime-package.js +1 -1
  40. package/dist/services/runtime-manager/runtime-package.js.map +1 -1
  41. package/docs/CLI.md +126 -1
  42. package/lib/backlog-item.d.mts +45 -1
  43. package/lib/backlog-item.mjs +302 -34
  44. package/lib/host-packages/adapter-registry.json +5 -5
  45. package/lib/host-packages/capability-map.json +1 -1
  46. package/lib/host-packages/claude/.claude-plugin/marketplace.json +2 -2
  47. package/lib/host-packages/claude/openplanr/.claude-plugin/icon.png +0 -0
  48. package/lib/host-packages/claude/openplanr/.claude-plugin/plugin.json +1 -1
  49. package/lib/host-packages/claude/openplanr/.openplanr-content.json +97 -413
  50. package/lib/host-packages/claude/openplanr/README.md +8 -8
  51. package/lib/host-packages/claude/openplanr/skills/artifact/references/design-sharing.md +2 -2
  52. package/lib/host-packages/claude/openplanr/skills/ceo-review/references/note-checklist.md +131 -0
  53. package/lib/host-packages/claude/openplanr/skills/ceo-review/references/operate-advisor-contract.md +2 -7
  54. package/lib/host-packages/claude/openplanr/skills/chair-review/SKILL.md +2 -7
  55. package/lib/host-packages/claude/openplanr/skills/chair-review/references/note-checklist.md +131 -0
  56. package/lib/host-packages/claude/openplanr/skills/challenger-review/SKILL.md +3 -7
  57. package/lib/host-packages/claude/openplanr/skills/challenger-review/references/note-checklist.md +131 -0
  58. package/lib/host-packages/claude/openplanr/skills/cmo-review/references/note-checklist.md +131 -0
  59. package/lib/host-packages/claude/openplanr/skills/cmo-review/references/operate-advisor-contract.md +2 -7
  60. package/lib/host-packages/claude/openplanr/skills/coo-review/references/note-checklist.md +131 -0
  61. package/lib/host-packages/claude/openplanr/skills/coo-review/references/operate-advisor-contract.md +2 -7
  62. package/lib/host-packages/claude/openplanr/skills/cpo-review/references/note-checklist.md +131 -0
  63. package/lib/host-packages/claude/openplanr/skills/cpo-review/references/operate-advisor-contract.md +2 -7
  64. package/lib/host-packages/claude/openplanr/skills/cto-review/references/note-checklist.md +131 -0
  65. package/lib/host-packages/claude/openplanr/skills/cto-review/references/operate-advisor-contract.md +2 -7
  66. package/lib/host-packages/claude/openplanr/skills/design/SKILL.md +23 -12
  67. package/lib/host-packages/claude/openplanr/skills/design/references/design-system.md +2 -2
  68. package/lib/host-packages/claude/openplanr/skills/design/references/generation.md +3 -3
  69. package/lib/host-packages/claude/openplanr/skills/design/references/hosted-canvas.md +6 -3
  70. package/lib/host-packages/claude/openplanr/skills/design/references/review.md +6 -6
  71. package/lib/host-packages/claude/openplanr/skills/design/references/team-review.md +3 -4
  72. package/lib/host-packages/claude/openplanr/skills/design/references/utilities.md +78 -38
  73. package/lib/host-packages/claude/openplanr/skills/design-loop/SKILL.md +15 -7
  74. package/lib/host-packages/claude/openplanr/skills/design-loop/references/design-system.md +2 -2
  75. package/lib/host-packages/claude/openplanr/skills/design-loop/references/generation.md +3 -3
  76. package/lib/host-packages/claude/openplanr/skills/design-loop/references/review.md +6 -6
  77. package/lib/host-packages/claude/openplanr/skills/design-loop/references/team-review.md +3 -4
  78. package/lib/host-packages/claude/openplanr/skills/design-loop/references/utilities.md +78 -38
  79. package/lib/host-packages/claude/openplanr/skills/design-review/SKILL.md +25 -5
  80. package/lib/host-packages/claude/openplanr/skills/design-review/references/design-system.md +2 -2
  81. package/lib/host-packages/claude/openplanr/skills/design-review/references/generation.md +3 -3
  82. package/lib/host-packages/claude/openplanr/skills/design-review/references/review.md +6 -6
  83. package/lib/host-packages/claude/openplanr/skills/design-review/references/team-review.md +3 -4
  84. package/lib/host-packages/claude/openplanr/skills/design-review/references/utilities.md +78 -38
  85. package/lib/host-packages/claude/openplanr/skills/investigate/SKILL.md +2 -3
  86. package/lib/host-packages/claude/openplanr/skills/investigate/references/backlog-filing.md +102 -0
  87. package/lib/host-packages/claude/openplanr/skills/investigate/references/findings.md +8 -16
  88. package/lib/host-packages/claude/openplanr/skills/operate/SKILL.md +73 -84
  89. package/lib/host-packages/claude/openplanr/skills/operate/references/note-checklist.md +131 -0
  90. package/lib/host-packages/claude/openplanr/skills/operate/references/return-contract.md +10 -0
  91. package/lib/host-packages/claude/openplanr/skills/plan/SKILL.md +23 -20
  92. package/lib/host-packages/claude/openplanr/skills/plan/references/planning-ids.md +53 -0
  93. package/lib/host-packages/claude/openplanr/skills/plan/references/return-contract.md +10 -0
  94. package/lib/host-packages/claude/openplanr/skills/plan-review/SKILL.md +6 -6
  95. package/lib/host-packages/claude/openplanr/skills/plan-review/references/return-contract.md +10 -0
  96. package/lib/host-packages/claude/openplanr/skills/release/SKILL.md +40 -139
  97. package/lib/host-packages/claude/openplanr/skills/release/references/cadence.md +10 -0
  98. package/lib/host-packages/claude/openplanr/skills/release/references/release-notes.md +1 -1
  99. package/lib/host-packages/claude/openplanr/skills/release/references/return-contract.md +10 -0
  100. package/lib/host-packages/claude/openplanr/skills/release/references/schemes.md +4 -2
  101. package/lib/host-packages/claude/openplanr/skills/ship/SKILL.md +37 -24
  102. package/lib/host-packages/claude/openplanr/skills/ship/references/backlog-filing.md +102 -0
  103. package/lib/host-packages/claude/openplanr/skills/ship/references/findings.md +8 -16
  104. package/lib/host-packages/claude/openplanr/skills/ship/references/return-contract.md +10 -0
  105. package/lib/host-packages/claude/openplanr/skills/spec/SKILL.md +9 -9
  106. package/lib/host-packages/claude/openplanr/skills/spec/references/return-contract.md +10 -0
  107. package/lib/host-packages/cursor/openplanr/.openplanr-content.json +94 -410
  108. package/lib/host-packages/cursor/openplanr/manifest.json +1 -1
  109. package/lib/host-packages/cursor/openplanr/rules/planr-artifact/references/design-sharing.md +2 -2
  110. package/lib/host-packages/cursor/openplanr/rules/planr-ceo-review/references/note-checklist.md +131 -0
  111. package/lib/host-packages/cursor/openplanr/rules/planr-ceo-review/references/operate-advisor-contract.md +2 -7
  112. package/lib/host-packages/cursor/openplanr/rules/planr-chair-review/references/note-checklist.md +131 -0
  113. package/lib/host-packages/cursor/openplanr/rules/planr-chair-review.mdc +2 -7
  114. package/lib/host-packages/cursor/openplanr/rules/planr-challenger-review/references/note-checklist.md +131 -0
  115. package/lib/host-packages/cursor/openplanr/rules/planr-challenger-review.mdc +3 -7
  116. package/lib/host-packages/cursor/openplanr/rules/planr-cmo-review/references/note-checklist.md +131 -0
  117. package/lib/host-packages/cursor/openplanr/rules/planr-cmo-review/references/operate-advisor-contract.md +2 -7
  118. package/lib/host-packages/cursor/openplanr/rules/planr-coo-review/references/note-checklist.md +131 -0
  119. package/lib/host-packages/cursor/openplanr/rules/planr-coo-review/references/operate-advisor-contract.md +2 -7
  120. package/lib/host-packages/cursor/openplanr/rules/planr-cpo-review/references/note-checklist.md +131 -0
  121. package/lib/host-packages/cursor/openplanr/rules/planr-cpo-review/references/operate-advisor-contract.md +2 -7
  122. package/lib/host-packages/cursor/openplanr/rules/planr-cto-review/references/note-checklist.md +131 -0
  123. package/lib/host-packages/cursor/openplanr/rules/planr-cto-review/references/operate-advisor-contract.md +2 -7
  124. package/lib/host-packages/cursor/openplanr/rules/planr-design/references/design-system.md +2 -2
  125. package/lib/host-packages/cursor/openplanr/rules/planr-design/references/generation.md +3 -3
  126. package/lib/host-packages/cursor/openplanr/rules/planr-design/references/hosted-canvas.md +6 -3
  127. package/lib/host-packages/cursor/openplanr/rules/planr-design/references/review.md +6 -6
  128. package/lib/host-packages/cursor/openplanr/rules/planr-design/references/team-review.md +3 -4
  129. package/lib/host-packages/cursor/openplanr/rules/planr-design/references/utilities.md +78 -38
  130. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/references/design-system.md +2 -2
  131. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/references/generation.md +3 -3
  132. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/references/review.md +6 -6
  133. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/references/team-review.md +3 -4
  134. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/references/utilities.md +78 -38
  135. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop.mdc +15 -7
  136. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/references/design-system.md +2 -2
  137. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/references/generation.md +3 -3
  138. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/references/review.md +6 -6
  139. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/references/team-review.md +3 -4
  140. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/references/utilities.md +78 -38
  141. package/lib/host-packages/cursor/openplanr/rules/planr-design-review.mdc +25 -5
  142. package/lib/host-packages/cursor/openplanr/rules/planr-design.mdc +23 -12
  143. package/lib/host-packages/cursor/openplanr/rules/planr-investigate/references/backlog-filing.md +102 -0
  144. package/lib/host-packages/cursor/openplanr/rules/planr-investigate/references/findings.md +8 -16
  145. package/lib/host-packages/cursor/openplanr/rules/planr-investigate.mdc +2 -3
  146. package/lib/host-packages/cursor/openplanr/rules/planr-operate/references/note-checklist.md +131 -0
  147. package/lib/host-packages/cursor/openplanr/rules/planr-operate/references/return-contract.md +10 -0
  148. package/lib/host-packages/cursor/openplanr/rules/planr-operate.mdc +73 -84
  149. package/lib/host-packages/cursor/openplanr/rules/planr-plan/references/planning-ids.md +53 -0
  150. package/lib/host-packages/cursor/openplanr/rules/planr-plan/references/return-contract.md +10 -0
  151. package/lib/host-packages/cursor/openplanr/rules/planr-plan-review/references/return-contract.md +10 -0
  152. package/lib/host-packages/cursor/openplanr/rules/planr-plan-review.mdc +6 -6
  153. package/lib/host-packages/cursor/openplanr/rules/planr-plan.mdc +23 -20
  154. package/lib/host-packages/cursor/openplanr/rules/planr-release/references/cadence.md +10 -0
  155. package/lib/host-packages/cursor/openplanr/rules/planr-release/references/release-notes.md +1 -1
  156. package/lib/host-packages/cursor/openplanr/rules/planr-release/references/return-contract.md +10 -0
  157. package/lib/host-packages/cursor/openplanr/rules/planr-release/references/schemes.md +4 -2
  158. package/lib/host-packages/cursor/openplanr/rules/planr-release.mdc +40 -139
  159. package/lib/host-packages/cursor/openplanr/rules/planr-ship/references/backlog-filing.md +102 -0
  160. package/lib/host-packages/cursor/openplanr/rules/planr-ship/references/findings.md +8 -16
  161. package/lib/host-packages/cursor/openplanr/rules/planr-ship/references/return-contract.md +10 -0
  162. package/lib/host-packages/cursor/openplanr/rules/planr-ship.mdc +37 -24
  163. package/lib/host-packages/cursor/openplanr/rules/planr-spec/references/return-contract.md +10 -0
  164. package/lib/host-packages/cursor/openplanr/rules/planr-spec.mdc +9 -9
  165. package/lib/host-packages/openai/.claude-plugin/marketplace.json +2 -2
  166. package/lib/host-packages/openai/openplanr/.codex-plugin/plugin.json +1 -1
  167. package/lib/host-packages/openai/openplanr/.openplanr-content.json +112 -428
  168. package/lib/host-packages/openai/openplanr/skills/artifact/references/design-sharing.md +2 -2
  169. package/lib/host-packages/openai/openplanr/skills/ceo-review/openplanr.skill.json +4 -4
  170. package/lib/host-packages/openai/openplanr/skills/ceo-review/references/note-checklist.md +131 -0
  171. package/lib/host-packages/openai/openplanr/skills/ceo-review/references/operate-advisor-contract.md +2 -7
  172. package/lib/host-packages/openai/openplanr/skills/chair-review/SKILL.md +2 -7
  173. package/lib/host-packages/openai/openplanr/skills/chair-review/openplanr.skill.json +4 -4
  174. package/lib/host-packages/openai/openplanr/skills/chair-review/references/note-checklist.md +131 -0
  175. package/lib/host-packages/openai/openplanr/skills/challenger-review/SKILL.md +3 -7
  176. package/lib/host-packages/openai/openplanr/skills/challenger-review/openplanr.skill.json +4 -4
  177. package/lib/host-packages/openai/openplanr/skills/challenger-review/references/note-checklist.md +131 -0
  178. package/lib/host-packages/openai/openplanr/skills/cmo-review/openplanr.skill.json +4 -4
  179. package/lib/host-packages/openai/openplanr/skills/cmo-review/references/note-checklist.md +131 -0
  180. package/lib/host-packages/openai/openplanr/skills/cmo-review/references/operate-advisor-contract.md +2 -7
  181. package/lib/host-packages/openai/openplanr/skills/coo-review/openplanr.skill.json +4 -4
  182. package/lib/host-packages/openai/openplanr/skills/coo-review/references/note-checklist.md +131 -0
  183. package/lib/host-packages/openai/openplanr/skills/coo-review/references/operate-advisor-contract.md +2 -7
  184. package/lib/host-packages/openai/openplanr/skills/cpo-review/openplanr.skill.json +4 -4
  185. package/lib/host-packages/openai/openplanr/skills/cpo-review/references/note-checklist.md +131 -0
  186. package/lib/host-packages/openai/openplanr/skills/cpo-review/references/operate-advisor-contract.md +2 -7
  187. package/lib/host-packages/openai/openplanr/skills/cto-review/openplanr.skill.json +4 -4
  188. package/lib/host-packages/openai/openplanr/skills/cto-review/references/note-checklist.md +131 -0
  189. package/lib/host-packages/openai/openplanr/skills/cto-review/references/operate-advisor-contract.md +2 -7
  190. package/lib/host-packages/openai/openplanr/skills/design/SKILL.md +23 -12
  191. package/lib/host-packages/openai/openplanr/skills/design/openplanr.skill.json +0 -11
  192. package/lib/host-packages/openai/openplanr/skills/design/references/design-system.md +2 -2
  193. package/lib/host-packages/openai/openplanr/skills/design/references/generation.md +3 -3
  194. package/lib/host-packages/openai/openplanr/skills/design/references/hosted-canvas.md +6 -3
  195. package/lib/host-packages/openai/openplanr/skills/design/references/review.md +6 -6
  196. package/lib/host-packages/openai/openplanr/skills/design/references/team-review.md +3 -4
  197. package/lib/host-packages/openai/openplanr/skills/design/references/utilities.md +78 -38
  198. package/lib/host-packages/openai/openplanr/skills/design-loop/SKILL.md +15 -7
  199. package/lib/host-packages/openai/openplanr/skills/design-loop/openplanr.skill.json +0 -11
  200. package/lib/host-packages/openai/openplanr/skills/design-loop/references/design-system.md +2 -2
  201. package/lib/host-packages/openai/openplanr/skills/design-loop/references/generation.md +3 -3
  202. package/lib/host-packages/openai/openplanr/skills/design-loop/references/review.md +6 -6
  203. package/lib/host-packages/openai/openplanr/skills/design-loop/references/team-review.md +3 -4
  204. package/lib/host-packages/openai/openplanr/skills/design-loop/references/utilities.md +78 -38
  205. package/lib/host-packages/openai/openplanr/skills/design-review/SKILL.md +25 -5
  206. package/lib/host-packages/openai/openplanr/skills/design-review/openplanr.skill.json +0 -11
  207. package/lib/host-packages/openai/openplanr/skills/design-review/references/design-system.md +2 -2
  208. package/lib/host-packages/openai/openplanr/skills/design-review/references/generation.md +3 -3
  209. package/lib/host-packages/openai/openplanr/skills/design-review/references/review.md +6 -6
  210. package/lib/host-packages/openai/openplanr/skills/design-review/references/team-review.md +3 -4
  211. package/lib/host-packages/openai/openplanr/skills/design-review/references/utilities.md +78 -38
  212. package/lib/host-packages/openai/openplanr/skills/investigate/SKILL.md +2 -3
  213. package/lib/host-packages/openai/openplanr/skills/investigate/openplanr.skill.json +4 -4
  214. package/lib/host-packages/openai/openplanr/skills/investigate/references/backlog-filing.md +102 -0
  215. package/lib/host-packages/openai/openplanr/skills/investigate/references/findings.md +8 -16
  216. package/lib/host-packages/openai/openplanr/skills/operate/SKILL.md +73 -84
  217. package/lib/host-packages/openai/openplanr/skills/operate/openplanr.skill.json +15 -4
  218. package/lib/host-packages/openai/openplanr/skills/operate/references/note-checklist.md +131 -0
  219. package/lib/host-packages/openai/openplanr/skills/operate/references/return-contract.md +10 -0
  220. package/lib/host-packages/openai/openplanr/skills/plan/SKILL.md +23 -20
  221. package/lib/host-packages/openai/openplanr/skills/plan/openplanr.skill.json +8 -8
  222. package/lib/host-packages/openai/openplanr/skills/plan/references/planning-ids.md +53 -0
  223. package/lib/host-packages/openai/openplanr/skills/plan/references/return-contract.md +10 -0
  224. package/lib/host-packages/openai/openplanr/skills/plan-review/SKILL.md +6 -6
  225. package/lib/host-packages/openai/openplanr/skills/plan-review/openplanr.skill.json +12 -1
  226. package/lib/host-packages/openai/openplanr/skills/plan-review/references/return-contract.md +10 -0
  227. package/lib/host-packages/openai/openplanr/skills/release/SKILL.md +40 -139
  228. package/lib/host-packages/openai/openplanr/skills/release/openplanr.skill.json +4 -4
  229. package/lib/host-packages/openai/openplanr/skills/release/references/cadence.md +10 -0
  230. package/lib/host-packages/openai/openplanr/skills/release/references/release-notes.md +1 -1
  231. package/lib/host-packages/openai/openplanr/skills/release/references/return-contract.md +10 -0
  232. package/lib/host-packages/openai/openplanr/skills/release/references/schemes.md +4 -2
  233. package/lib/host-packages/openai/openplanr/skills/ship/SKILL.md +37 -24
  234. package/lib/host-packages/openai/openplanr/skills/ship/openplanr.skill.json +9 -9
  235. package/lib/host-packages/openai/openplanr/skills/ship/references/backlog-filing.md +102 -0
  236. package/lib/host-packages/openai/openplanr/skills/ship/references/findings.md +8 -16
  237. package/lib/host-packages/openai/openplanr/skills/ship/references/return-contract.md +10 -0
  238. package/lib/host-packages/openai/openplanr/skills/spec/SKILL.md +9 -9
  239. package/lib/host-packages/openai/openplanr/skills/spec/openplanr.skill.json +12 -1
  240. package/lib/host-packages/openai/openplanr/skills/spec/references/return-contract.md +10 -0
  241. package/package.json +2 -2
  242. package/lib/host-packages/claude/openplanr/.claude-plugin/icon.svg +0 -11
  243. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-artifact-shell.mjs +0 -1772
  244. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-document.mjs +0 -2937
  245. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-entities.mjs +0 -439
  246. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-handoff.mjs +0 -2370
  247. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-loopback-server.mjs +0 -359
  248. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-parse5-parser.mjs +0 -3970
  249. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-parse5-tokenizer.mjs +0 -3501
  250. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-review-state-store.mjs +0 -45
  251. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-review.mjs +0 -3376
  252. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-runtime-home.mjs +0 -38
  253. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-sandbox-guards.mjs +0 -1102
  254. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-share-cli-bridge.mjs +0 -321
  255. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-shared-artifact-support-dependencies-design-support-protocol-contracts-d707e49b.mjs +0 -1652
  256. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-shared-artifact-support-protocol-contracts-9f6918b0.mjs +0 -1037
  257. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-shared-design-support-0bac378d.mjs +0 -137
  258. package/lib/host-packages/claude/openplanr/runtime/design/scripts/design.mjs +0 -1500
  259. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +0 -2023
  260. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/lib/artifact/ui/studio-shell.css +0 -2
  261. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/01-module-runtime.js +0 -18
  262. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/02-artifact-review-ui.js +0 -814
  263. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/03-protocol-contracts.js +0 -10
  264. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/04-artifact-review-ui.js +0 -2568
  265. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources.json +0 -60
  266. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/package.json +0 -65
  267. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/enhancements.css +0 -388
  268. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/handoff-center.css +0 -81
  269. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/share.css +0 -1
  270. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/share.js +0 -139
  271. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.css +0 -1159
  272. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/01-module-runtime.js +0 -30
  273. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/02-react.js +0 -900
  274. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/03-react-dom-client-fiber-foundations.js +0 -2261
  275. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/04-react-dom-client-reconciliation-hooks.js +0 -1595
  276. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/05-react-dom-client-render-phases.js +0 -1467
  277. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/06-react-dom-client-commit-effects.js +0 -1860
  278. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/07-react-dom-client-work-loop-scheduling.js +0 -914
  279. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/08-react-dom-client-dom-events-properties-hydration.js +0 -2578
  280. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/09-react-dom-client-public-roots.js +0 -582
  281. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/10-react.js +0 -17
  282. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/11-artifact-review-ui.js +0 -12
  283. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/12-protocol-contracts.js +0 -285
  284. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/13-design-review-experience.js +0 -2773
  285. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/14-studio-shell.js +0 -134
  286. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/15-canvas-engine.js +0 -2207
  287. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/16-design-review-experience.js +0 -16
  288. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/17-studio-shell.js +0 -8
  289. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/18-interface-primitives.js +0 -3883
  290. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/19-interface-primitives.js +0 -966
  291. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/20-studio-shell.js +0 -520
  292. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/21-design-studio.js +0 -1597
  293. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources.json +0 -311
  294. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/package.json +0 -163
  295. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/registries/artifact-theme.json +0 -64
  296. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.0.0/design-manifest.schema.json +0 -90
  297. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-envelope.schema.json +0 -142
  298. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-review.schema.json +0 -97
  299. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-bundle.schema.json +0 -584
  300. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-context.schema.json +0 -191
  301. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-handoff.schema.json +0 -407
  302. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-metadata-payload.schema.json +0 -106
  303. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-handoff-readiness.schema.json +0 -398
  304. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-implementation-handoff.schema.json +0 -518
  305. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-planning-lineage.schema.json +0 -106
  306. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-review-metadata-payload.schema.json +0 -107
  307. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.14.0/artifact-theme.schema.json +0 -316
  308. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.16.0/artifact-envelope.schema.json +0 -408
  309. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.16.0/design-review-bundle.schema.json +0 -590
  310. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-document.schema.json +0 -506
  311. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-review-bundle.schema.json +0 -822
  312. package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-review-bundle.schema.json +0 -346
  313. package/lib/host-packages/claude/openplanr/runtime/operate/scripts/errors.mjs +0 -8
  314. package/lib/host-packages/claude/openplanr/runtime/operate/scripts/operate-review-contract.mjs +0 -428
  315. package/lib/host-packages/claude/openplanr/runtime/operate/scripts/operate-review-note.mjs +0 -686
  316. package/lib/host-packages/claude/openplanr/runtime/operate/scripts/validate-note.mjs +0 -39
  317. package/lib/host-packages/claude/openplanr/runtime/plan/scripts/design-protocol-contracts.mjs +0 -1232
  318. package/lib/host-packages/claude/openplanr/runtime/plan/scripts/design.mjs +0 -2611
  319. package/lib/host-packages/claude/openplanr/runtime/plan/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +0 -21
  320. package/lib/host-packages/claude/openplanr/runtime/plan/scripts/runtime/packages/protocol/package.json +0 -163
  321. package/lib/host-packages/claude/openplanr/runtime/plan/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-review.schema.json +0 -97
  322. package/lib/host-packages/claude/openplanr/skills/ceo-review/scripts/validate-note.mjs +0 -12
  323. package/lib/host-packages/claude/openplanr/skills/chair-review/scripts/validate-note.mjs +0 -12
  324. package/lib/host-packages/claude/openplanr/skills/challenger-review/scripts/validate-note.mjs +0 -12
  325. package/lib/host-packages/claude/openplanr/skills/cmo-review/scripts/validate-note.mjs +0 -12
  326. package/lib/host-packages/claude/openplanr/skills/coo-review/scripts/validate-note.mjs +0 -12
  327. package/lib/host-packages/claude/openplanr/skills/cpo-review/scripts/validate-note.mjs +0 -12
  328. package/lib/host-packages/claude/openplanr/skills/cto-review/scripts/validate-note.mjs +0 -12
  329. package/lib/host-packages/claude/openplanr/skills/design/scripts/design.mjs +0 -12
  330. package/lib/host-packages/claude/openplanr/skills/design-loop/scripts/design.mjs +0 -12
  331. package/lib/host-packages/claude/openplanr/skills/design-review/scripts/design.mjs +0 -12
  332. package/lib/host-packages/claude/openplanr/skills/investigate/scripts/backlog-item.mjs +0 -339
  333. package/lib/host-packages/claude/openplanr/skills/operate/scripts/validate-note.mjs +0 -12
  334. package/lib/host-packages/claude/openplanr/skills/plan/scripts/design.mjs +0 -12
  335. package/lib/host-packages/claude/openplanr/skills/plan/scripts/planning-ids.mjs +0 -166
  336. package/lib/host-packages/claude/openplanr/skills/release/scripts/collect_changes.sh +0 -85
  337. package/lib/host-packages/claude/openplanr/skills/ship/scripts/backlog-item.mjs +0 -339
  338. package/lib/host-packages/claude/openplanr/skills/ship/scripts/discover-verification.mjs +0 -108
  339. package/lib/host-packages/cursor/openplanr/rules/planr-ceo-review/scripts/validate-note.mjs +0 -12
  340. package/lib/host-packages/cursor/openplanr/rules/planr-chair-review/scripts/validate-note.mjs +0 -12
  341. package/lib/host-packages/cursor/openplanr/rules/planr-challenger-review/scripts/validate-note.mjs +0 -12
  342. package/lib/host-packages/cursor/openplanr/rules/planr-cmo-review/scripts/validate-note.mjs +0 -12
  343. package/lib/host-packages/cursor/openplanr/rules/planr-coo-review/scripts/validate-note.mjs +0 -12
  344. package/lib/host-packages/cursor/openplanr/rules/planr-cpo-review/scripts/validate-note.mjs +0 -12
  345. package/lib/host-packages/cursor/openplanr/rules/planr-cto-review/scripts/validate-note.mjs +0 -12
  346. package/lib/host-packages/cursor/openplanr/rules/planr-design/scripts/design.mjs +0 -12
  347. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/scripts/design.mjs +0 -12
  348. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/scripts/design.mjs +0 -12
  349. package/lib/host-packages/cursor/openplanr/rules/planr-investigate/scripts/backlog-item.mjs +0 -339
  350. package/lib/host-packages/cursor/openplanr/rules/planr-operate/scripts/validate-note.mjs +0 -12
  351. package/lib/host-packages/cursor/openplanr/rules/planr-plan/scripts/design.mjs +0 -12
  352. package/lib/host-packages/cursor/openplanr/rules/planr-plan/scripts/planning-ids.mjs +0 -166
  353. package/lib/host-packages/cursor/openplanr/rules/planr-release/scripts/collect_changes.sh +0 -85
  354. package/lib/host-packages/cursor/openplanr/rules/planr-ship/scripts/backlog-item.mjs +0 -339
  355. package/lib/host-packages/cursor/openplanr/rules/planr-ship/scripts/discover-verification.mjs +0 -108
  356. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-artifact-shell.mjs +0 -1772
  357. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-document.mjs +0 -2937
  358. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-entities.mjs +0 -439
  359. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-handoff.mjs +0 -2370
  360. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-loopback-server.mjs +0 -359
  361. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-parse5-parser.mjs +0 -3970
  362. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-parse5-tokenizer.mjs +0 -3501
  363. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-review-state-store.mjs +0 -45
  364. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-review.mjs +0 -3376
  365. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-runtime-home.mjs +0 -38
  366. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-sandbox-guards.mjs +0 -1102
  367. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-share-cli-bridge.mjs +0 -321
  368. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-shared-artifact-support-dependencies-design-support-protocol-contracts-d707e49b.mjs +0 -1652
  369. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-shared-artifact-support-protocol-contracts-9f6918b0.mjs +0 -1037
  370. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-shared-design-support-0bac378d.mjs +0 -137
  371. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design.mjs +0 -1500
  372. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +0 -2023
  373. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/lib/artifact/ui/studio-shell.css +0 -2
  374. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/01-module-runtime.js +0 -18
  375. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/02-artifact-review-ui.js +0 -814
  376. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/03-protocol-contracts.js +0 -10
  377. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/04-artifact-review-ui.js +0 -2568
  378. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources.json +0 -60
  379. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/package.json +0 -65
  380. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/enhancements.css +0 -388
  381. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/handoff-center.css +0 -81
  382. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/share.css +0 -1
  383. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/share.js +0 -139
  384. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.css +0 -1159
  385. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/01-module-runtime.js +0 -30
  386. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/02-react.js +0 -900
  387. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/03-react-dom-client-fiber-foundations.js +0 -2261
  388. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/04-react-dom-client-reconciliation-hooks.js +0 -1595
  389. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/05-react-dom-client-render-phases.js +0 -1467
  390. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/06-react-dom-client-commit-effects.js +0 -1860
  391. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/07-react-dom-client-work-loop-scheduling.js +0 -914
  392. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/08-react-dom-client-dom-events-properties-hydration.js +0 -2578
  393. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/09-react-dom-client-public-roots.js +0 -582
  394. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/10-react.js +0 -17
  395. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/11-artifact-review-ui.js +0 -12
  396. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/12-protocol-contracts.js +0 -285
  397. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/13-design-review-experience.js +0 -2773
  398. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/14-studio-shell.js +0 -134
  399. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/15-canvas-engine.js +0 -2207
  400. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/16-design-review-experience.js +0 -16
  401. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/17-studio-shell.js +0 -8
  402. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/18-interface-primitives.js +0 -3883
  403. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/19-interface-primitives.js +0 -966
  404. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/20-studio-shell.js +0 -520
  405. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/21-design-studio.js +0 -1597
  406. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources.json +0 -311
  407. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/package.json +0 -163
  408. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/registries/artifact-theme.json +0 -64
  409. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.0.0/design-manifest.schema.json +0 -90
  410. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-envelope.schema.json +0 -142
  411. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-review.schema.json +0 -97
  412. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-bundle.schema.json +0 -584
  413. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-context.schema.json +0 -191
  414. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-handoff.schema.json +0 -407
  415. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-metadata-payload.schema.json +0 -106
  416. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-handoff-readiness.schema.json +0 -398
  417. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-implementation-handoff.schema.json +0 -518
  418. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-planning-lineage.schema.json +0 -106
  419. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-review-metadata-payload.schema.json +0 -107
  420. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.14.0/artifact-theme.schema.json +0 -316
  421. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.16.0/artifact-envelope.schema.json +0 -408
  422. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.16.0/design-review-bundle.schema.json +0 -590
  423. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-document.schema.json +0 -506
  424. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-review-bundle.schema.json +0 -822
  425. package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-review-bundle.schema.json +0 -346
  426. package/lib/host-packages/cursor/openplanr/runtime/operate/scripts/errors.mjs +0 -8
  427. package/lib/host-packages/cursor/openplanr/runtime/operate/scripts/operate-review-contract.mjs +0 -428
  428. package/lib/host-packages/cursor/openplanr/runtime/operate/scripts/operate-review-note.mjs +0 -686
  429. package/lib/host-packages/cursor/openplanr/runtime/operate/scripts/validate-note.mjs +0 -39
  430. package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/design-protocol-contracts.mjs +0 -1232
  431. package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/design.mjs +0 -2611
  432. package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +0 -21
  433. package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/runtime/packages/protocol/package.json +0 -163
  434. package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-review.schema.json +0 -97
  435. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-artifact-shell.mjs +0 -1772
  436. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-document.mjs +0 -2937
  437. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-entities.mjs +0 -439
  438. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-handoff.mjs +0 -2370
  439. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-loopback-server.mjs +0 -359
  440. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-parse5-parser.mjs +0 -3970
  441. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-parse5-tokenizer.mjs +0 -3501
  442. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-review-state-store.mjs +0 -45
  443. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-review.mjs +0 -3376
  444. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-runtime-home.mjs +0 -38
  445. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-sandbox-guards.mjs +0 -1102
  446. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-share-cli-bridge.mjs +0 -321
  447. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-shared-artifact-support-dependencies-design-support-protocol-contracts-d707e49b.mjs +0 -1652
  448. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-shared-artifact-support-protocol-contracts-9f6918b0.mjs +0 -1037
  449. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-shared-design-support-0bac378d.mjs +0 -137
  450. package/lib/host-packages/openai/openplanr/runtime/design/scripts/design.mjs +0 -1500
  451. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +0 -2023
  452. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/lib/artifact/ui/studio-shell.css +0 -2
  453. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/01-module-runtime.js +0 -18
  454. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/02-artifact-review-ui.js +0 -814
  455. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/03-protocol-contracts.js +0 -10
  456. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/04-artifact-review-ui.js +0 -2568
  457. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources.json +0 -60
  458. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/package.json +0 -65
  459. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/enhancements.css +0 -388
  460. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/handoff-center.css +0 -81
  461. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/share.css +0 -1
  462. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/share.js +0 -139
  463. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.css +0 -1159
  464. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/01-module-runtime.js +0 -30
  465. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/02-react.js +0 -900
  466. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/03-react-dom-client-fiber-foundations.js +0 -2261
  467. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/04-react-dom-client-reconciliation-hooks.js +0 -1595
  468. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/05-react-dom-client-render-phases.js +0 -1467
  469. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/06-react-dom-client-commit-effects.js +0 -1860
  470. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/07-react-dom-client-work-loop-scheduling.js +0 -914
  471. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/08-react-dom-client-dom-events-properties-hydration.js +0 -2578
  472. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/09-react-dom-client-public-roots.js +0 -582
  473. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/10-react.js +0 -17
  474. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/11-artifact-review-ui.js +0 -12
  475. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/12-protocol-contracts.js +0 -285
  476. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/13-design-review-experience.js +0 -2773
  477. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/14-studio-shell.js +0 -134
  478. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/15-canvas-engine.js +0 -2207
  479. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/16-design-review-experience.js +0 -16
  480. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/17-studio-shell.js +0 -8
  481. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/18-interface-primitives.js +0 -3883
  482. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/19-interface-primitives.js +0 -966
  483. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/20-studio-shell.js +0 -520
  484. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/21-design-studio.js +0 -1597
  485. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources.json +0 -311
  486. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/package.json +0 -163
  487. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/registries/artifact-theme.json +0 -64
  488. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.0.0/design-manifest.schema.json +0 -90
  489. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-envelope.schema.json +0 -142
  490. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-review.schema.json +0 -97
  491. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-bundle.schema.json +0 -584
  492. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-context.schema.json +0 -191
  493. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-handoff.schema.json +0 -407
  494. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.10.0/design-review-metadata-payload.schema.json +0 -106
  495. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-handoff-readiness.schema.json +0 -398
  496. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-implementation-handoff.schema.json +0 -518
  497. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-planning-lineage.schema.json +0 -106
  498. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.11.0/design-review-metadata-payload.schema.json +0 -107
  499. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.14.0/artifact-theme.schema.json +0 -316
  500. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.16.0/artifact-envelope.schema.json +0 -408
  501. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.16.0/design-review-bundle.schema.json +0 -590
  502. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-document.schema.json +0 -506
  503. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-review-bundle.schema.json +0 -822
  504. package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.9.0/design-review-bundle.schema.json +0 -346
  505. package/lib/host-packages/openai/openplanr/runtime/operate/scripts/errors.mjs +0 -8
  506. package/lib/host-packages/openai/openplanr/runtime/operate/scripts/operate-review-contract.mjs +0 -428
  507. package/lib/host-packages/openai/openplanr/runtime/operate/scripts/operate-review-note.mjs +0 -686
  508. package/lib/host-packages/openai/openplanr/runtime/operate/scripts/validate-note.mjs +0 -39
  509. package/lib/host-packages/openai/openplanr/runtime/plan/scripts/design-protocol-contracts.mjs +0 -1232
  510. package/lib/host-packages/openai/openplanr/runtime/plan/scripts/design.mjs +0 -2611
  511. package/lib/host-packages/openai/openplanr/runtime/plan/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +0 -21
  512. package/lib/host-packages/openai/openplanr/runtime/plan/scripts/runtime/packages/protocol/package.json +0 -163
  513. package/lib/host-packages/openai/openplanr/runtime/plan/scripts/runtime/packages/protocol/schemas/v1.1.0/artifact-review.schema.json +0 -97
  514. package/lib/host-packages/openai/openplanr/skills/ceo-review/scripts/validate-note.mjs +0 -12
  515. package/lib/host-packages/openai/openplanr/skills/chair-review/scripts/validate-note.mjs +0 -12
  516. package/lib/host-packages/openai/openplanr/skills/challenger-review/scripts/validate-note.mjs +0 -12
  517. package/lib/host-packages/openai/openplanr/skills/cmo-review/scripts/validate-note.mjs +0 -12
  518. package/lib/host-packages/openai/openplanr/skills/coo-review/scripts/validate-note.mjs +0 -12
  519. package/lib/host-packages/openai/openplanr/skills/cpo-review/scripts/validate-note.mjs +0 -12
  520. package/lib/host-packages/openai/openplanr/skills/cto-review/scripts/validate-note.mjs +0 -12
  521. package/lib/host-packages/openai/openplanr/skills/design/scripts/design.mjs +0 -12
  522. package/lib/host-packages/openai/openplanr/skills/design-loop/scripts/design.mjs +0 -12
  523. package/lib/host-packages/openai/openplanr/skills/design-review/scripts/design.mjs +0 -12
  524. package/lib/host-packages/openai/openplanr/skills/investigate/scripts/backlog-item.mjs +0 -339
  525. package/lib/host-packages/openai/openplanr/skills/operate/scripts/validate-note.mjs +0 -12
  526. package/lib/host-packages/openai/openplanr/skills/plan/scripts/design.mjs +0 -12
  527. package/lib/host-packages/openai/openplanr/skills/plan/scripts/planning-ids.mjs +0 -166
  528. package/lib/host-packages/openai/openplanr/skills/release/scripts/collect_changes.sh +0 -85
  529. package/lib/host-packages/openai/openplanr/skills/ship/scripts/backlog-item.mjs +0 -339
  530. package/lib/host-packages/openai/openplanr/skills/ship/scripts/discover-verification.mjs +0 -108
@@ -1,2370 +0,0 @@
1
- import {
2
- DESIGN_HANDOFF_CONTENT_SCHEMA,
3
- DESIGN_HANDOFF_SCHEMA,
4
- assertPlainData,
5
- assertReviewExperience,
6
- canonicalizeJson,
7
- deepFreeze,
8
- emptyReviewContext,
9
- reviewDigest,
10
- sha256Hex
11
- } from "./design-shared-artifact-support-dependencies-design-support-protocol-contracts-d707e49b.mjs";
12
- import {
13
- ARTIFACT_ERROR_CODES,
14
- PipelineError,
15
- canonicalSerialize,
16
- digestArtifactEnvelope,
17
- validateArtifactEnvelope,
18
- validateArtifactReview,
19
- validateJson
20
- } from "./design-shared-artifact-support-protocol-contracts-9f6918b0.mjs";
21
- import {
22
- assertDesignShareAvailable,
23
- getDesignShareStatus,
24
- publishDesignReviewMetadata
25
- } from "./design-share-cli-bridge.mjs";
26
- import {
27
- atomicJson,
28
- currentDesign,
29
- designSpecPath,
30
- hash,
31
- readJson
32
- } from "./design-shared-design-support-0bac378d.mjs";
33
- import {
34
- planrHome
35
- } from "./design-runtime-home.mjs";
36
- import {
37
- acquireStartLock
38
- } from "./design-loopback-server.mjs";
39
-
40
- // packages/design/lib/design/feedback-reader.mjs
41
- import { join as join2 } from "node:path";
42
-
43
- // packages/artifact/lib/artifact/import.mjs
44
- import {
45
- existsSync as existsSync2,
46
- lstatSync as lstatSync2,
47
- mkdirSync as mkdirSync2,
48
- readFileSync as readFileSync2,
49
- realpathSync,
50
- renameSync as renameSync2,
51
- rmSync as rmSync2,
52
- statSync as statSync2,
53
- writeFileSync as writeFileSync2
54
- } from "node:fs";
55
- import { homedir } from "node:os";
56
- import { dirname as dirname2, isAbsolute, join, relative, resolve } from "node:path";
57
-
58
- // packages/protocol/src/names.mjs
59
- var PLANNING_FOLDER = ".planr";
60
- var CLI_COMMAND = "openplanr";
61
-
62
- // packages/artifact/lib/artifact/internal/feedback.mjs
63
- var FEEDBACK_FILE = "feedback.json";
64
-
65
- // packages/artifact/lib/artifact/merge.mjs
66
- var ARTIFACT_REVIEW_STATE_VERSION = "1.0.0";
67
- var ARTIFACT_REVIEW_STATE_KIND = "artifact-review-state";
68
- var SHA256_RE = /^[a-f0-9]{64}$/;
69
- var ARTIFACT_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
70
- function conflict(message2, details = void 0) {
71
- throw new PipelineError(
72
- ARTIFACT_ERROR_CODES.MERGE_CONFLICT,
73
- message2,
74
- "Keep both reviews under different stable IDs or resolve the conflicting item explicitly.",
75
- details
76
- );
77
- }
78
- function assertUniqueReviewItemIds(review) {
79
- const pinIds = /* @__PURE__ */ new Set();
80
- for (const pin of review.pins ?? []) {
81
- if (pinIds.has(pin.id)) {
82
- throw new PipelineError(
83
- ARTIFACT_ERROR_CODES.REVIEW_INVALID,
84
- "Artifact review contains a duplicate pin ID."
85
- );
86
- }
87
- pinIds.add(pin.id);
88
- const replyIds = /* @__PURE__ */ new Set();
89
- for (const reply of pin.replies ?? []) {
90
- if (replyIds.has(reply.id)) {
91
- throw new PipelineError(
92
- ARTIFACT_ERROR_CODES.REVIEW_INVALID,
93
- "Artifact review contains a duplicate reply ID in one thread."
94
- );
95
- }
96
- replyIds.add(reply.id);
97
- }
98
- }
99
- return review;
100
- }
101
- function clone(value) {
102
- return structuredClone(value);
103
- }
104
- function same(a, b) {
105
- return canonicalSerialize(a) === canonicalSerialize(b);
106
- }
107
- function timeValue(value) {
108
- if (typeof value !== "string") return Number.NEGATIVE_INFINITY;
109
- const parsed = Date.parse(value);
110
- return Number.isFinite(parsed) ? parsed : Number.NEGATIVE_INFINITY;
111
- }
112
- function compareStable(a, b, idKey) {
113
- const aTime = a.createdAt ?? a.updatedAt ?? "";
114
- const bTime = b.createdAt ?? b.updatedAt ?? "";
115
- return aTime.localeCompare(bTime) || String(a[idKey]).localeCompare(String(b[idKey]));
116
- }
117
- function replyMap(replies) {
118
- const map = /* @__PURE__ */ new Map();
119
- for (const reply of replies ?? []) {
120
- const previous = map.get(reply.id);
121
- if (previous && !same(previous, reply)) {
122
- conflict("A reply ID refers to different immutable reply content.", { entity: "reply" });
123
- }
124
- map.set(reply.id, clone(reply));
125
- }
126
- return map;
127
- }
128
- function mergeReplies(stored = [], incoming = []) {
129
- const merged = replyMap(stored);
130
- for (const reply of incoming) {
131
- const previous = merged.get(reply.id);
132
- if (previous && !same(previous, reply)) {
133
- conflict("A reply ID refers to different immutable reply content.", { entity: "reply" });
134
- }
135
- if (!previous) merged.set(reply.id, clone(reply));
136
- }
137
- return [...merged.values()].sort((a, b) => compareStable(a, b, "id"));
138
- }
139
- var immutablePin = (pin) => ({
140
- id: pin.id,
141
- author: pin.author,
142
- artifactId: pin.artifactId,
143
- ...pin.variant === void 0 ? {} : { variant: pin.variant },
144
- region: pin.region,
145
- viewport: pin.viewport,
146
- ...pin.anchor === void 0 ? {} : { anchor: pin.anchor },
147
- createdAt: pin.createdAt
148
- });
149
- var mutablePin = (pin) => ({
150
- intent: pin.intent,
151
- status: pin.status,
152
- comment: pin.comment
153
- });
154
- function mergePin(stored, incoming) {
155
- if (!same(immutablePin(stored), immutablePin(incoming))) {
156
- conflict("A pin ID refers to different immutable geometry, author, or artifact content.", {
157
- entity: "pin"
158
- });
159
- }
160
- const replies = mergeReplies(stored.replies, incoming.replies);
161
- const storedTime = timeValue(stored.updatedAt);
162
- const incomingTime = timeValue(incoming.updatedAt);
163
- let selected = stored;
164
- if (incomingTime > storedTime) selected = incoming;
165
- if (incomingTime === storedTime && !same(mutablePin(stored), mutablePin(incoming))) {
166
- conflict("A pin has divergent mutable content at the same update time.", { entity: "pin" });
167
- }
168
- return { ...clone(selected), replies };
169
- }
170
- function mergePins(stored = [], incoming = []) {
171
- const merged = /* @__PURE__ */ new Map();
172
- for (const pin of stored) merged.set(pin.id, clone(pin));
173
- for (const pin of incoming) {
174
- const previous = merged.get(pin.id);
175
- merged.set(pin.id, previous ? mergePin(previous, pin) : clone(pin));
176
- }
177
- return [...merged.values()].sort((a, b) => compareStable(a, b, "id"));
178
- }
179
- var immutableReview = (review) => ({
180
- schemaVersion: review.schemaVersion,
181
- reviewId: review.reviewId,
182
- reviewOf: review.reviewOf,
183
- ...review.createdAt === void 0 ? {} : { createdAt: review.createdAt }
184
- });
185
- var mutableReview = (review) => ({ decision: review.decision, overall: review.overall });
186
- function mergeArtifactReviews(stored, incoming) {
187
- validateArtifactReview(stored);
188
- validateArtifactReview(incoming);
189
- assertUniqueReviewItemIds(stored);
190
- assertUniqueReviewItemIds(incoming);
191
- if (stored.reviewId !== incoming.reviewId) {
192
- conflict("Only reviews with the same review ID can be revision-merged.", {
193
- entity: "review"
194
- });
195
- }
196
- if (same(stored, incoming)) return stored;
197
- if (!same(immutableReview(stored), immutableReview(incoming))) {
198
- conflict("A review ID refers to a different digest or creation identity.", {
199
- entity: "review"
200
- });
201
- }
202
- const storedTime = timeValue(stored.updatedAt);
203
- const incomingTime = timeValue(incoming.updatedAt);
204
- let selected = stored;
205
- if (incomingTime > storedTime) selected = incoming;
206
- if (incomingTime === storedTime && !same(mutableReview(stored), mutableReview(incoming))) {
207
- conflict("A review has divergent verdict or overall feedback at the same update time.", {
208
- entity: "review"
209
- });
210
- }
211
- const merged = {
212
- ...clone(selected),
213
- pins: mergePins(stored.pins, incoming.pins)
214
- };
215
- validateArtifactReview(merged);
216
- return merged;
217
- }
218
- function validateReviewLedger(ledger) {
219
- if (!ledger || typeof ledger !== "object" || Array.isArray(ledger) || ledger.schemaVersion !== ARTIFACT_REVIEW_STATE_VERSION || ledger.kind !== ARTIFACT_REVIEW_STATE_KIND || !ARTIFACT_ID_RE.test(ledger.artifactId ?? "") || !SHA256_RE.test(ledger.currentReviewOf ?? "") || !Array.isArray(ledger.reviews)) {
220
- throw new PipelineError(
221
- ARTIFACT_ERROR_CODES.REVIEW_INVALID,
222
- "Artifact review state is not a valid versioned review ledger."
223
- );
224
- }
225
- const ids = /* @__PURE__ */ new Set();
226
- for (const entry of ledger.reviews) {
227
- if (!entry || typeof entry !== "object" || Array.isArray(entry) || typeof entry.stale !== "boolean" || !entry.review) {
228
- throw new PipelineError(
229
- ARTIFACT_ERROR_CODES.REVIEW_INVALID,
230
- "Artifact review ledger entry is invalid."
231
- );
232
- }
233
- validateArtifactReview(entry.review);
234
- assertUniqueReviewItemIds(entry.review);
235
- if (ids.has(entry.review.reviewId)) {
236
- throw new PipelineError(
237
- ARTIFACT_ERROR_CODES.REVIEW_INVALID,
238
- "Artifact review ledger IDs must be unique."
239
- );
240
- }
241
- ids.add(entry.review.reviewId);
242
- }
243
- return ledger;
244
- }
245
- function createReviewLedger({ artifactId, currentReviewOf, reviews = [] } = {}) {
246
- const ledger = {
247
- schemaVersion: ARTIFACT_REVIEW_STATE_VERSION,
248
- kind: ARTIFACT_REVIEW_STATE_KIND,
249
- artifactId,
250
- currentReviewOf,
251
- reviews: reviews.map((entry) => ({ review: clone(entry.review), stale: Boolean(entry.stale) }))
252
- };
253
- ledger.reviews.sort((a, b) => compareStable(a.review, b.review, "reviewId"));
254
- return validateReviewLedger(ledger);
255
- }
256
- function mergeReviewLedger(ledger, incoming, { stale = false } = {}) {
257
- validateReviewLedger(ledger);
258
- const reviews = Array.isArray(incoming) ? incoming : [incoming];
259
- const byId = new Map(
260
- ledger.reviews.map((entry) => [
261
- entry.review.reviewId,
262
- {
263
- review: clone(entry.review),
264
- stale: entry.stale
265
- }
266
- ])
267
- );
268
- for (const review of reviews) {
269
- validateArtifactReview(review);
270
- const previous = byId.get(review.reviewId);
271
- if (previous) {
272
- byId.set(review.reviewId, {
273
- review: mergeArtifactReviews(previous.review, review),
274
- stale: previous.stale || Boolean(stale)
275
- });
276
- } else {
277
- byId.set(review.reviewId, { review: clone(review), stale: Boolean(stale) });
278
- }
279
- }
280
- const merged = createReviewLedger({
281
- artifactId: ledger.artifactId,
282
- currentReviewOf: ledger.currentReviewOf,
283
- reviews: [...byId.values()]
284
- });
285
- return same(ledger, merged) ? ledger : merged;
286
- }
287
- function effectiveReviewDecision(value) {
288
- const entries = Array.isArray(value) ? value : value?.reviews ?? [];
289
- const decisions = entries.map((entry) => entry.review?.decision ?? entry.decision);
290
- if (decisions.includes("changes_requested")) return "changes_requested";
291
- if (decisions.includes("pending")) return "pending";
292
- return decisions.length > 0 && decisions.every((decision) => decision === "approved") ? "approved" : "pending";
293
- }
294
-
295
- // packages/artifact/lib/artifact/review.mjs
296
- import { randomBytes, randomUUID } from "node:crypto";
297
- import {
298
- existsSync,
299
- lstatSync,
300
- mkdirSync,
301
- readFileSync,
302
- renameSync,
303
- rmSync,
304
- statSync,
305
- writeFileSync
306
- } from "node:fs";
307
- import { dirname } from "node:path";
308
- var ARTIFACT_REVIEW_MAX_STATE_BYTES = 5 * 1024 * 1024;
309
- var reviewPathQueues = /* @__PURE__ */ new Map();
310
- function finalEntry(path, fs = { lstatSync }) {
311
- try {
312
- return fs.lstatSync(path);
313
- } catch (error) {
314
- if (error?.code === "ENOENT") return null;
315
- throw error;
316
- }
317
- }
318
- function clone2(value) {
319
- return structuredClone(value);
320
- }
321
- function canonicalObject(value) {
322
- if (Array.isArray(value)) return value.map(canonicalObject);
323
- if (!value || typeof value !== "object") return value;
324
- return Object.fromEntries(
325
- Object.keys(value).sort().map((key) => [key, canonicalObject(value[key])])
326
- );
327
- }
328
- function stableItemSort(a, b) {
329
- return String(a.createdAt ?? a.updatedAt ?? "").localeCompare(
330
- String(b.createdAt ?? b.updatedAt ?? "")
331
- ) || String(a.id ?? a.reviewId).localeCompare(String(b.id ?? b.reviewId));
332
- }
333
- function normalizeArtifactReview(review) {
334
- let normalized;
335
- try {
336
- normalized = clone2(review);
337
- } catch {
338
- throw new PipelineError(
339
- ARTIFACT_ERROR_CODES.REVIEW_INVALID,
340
- "Artifact review is not cloneable."
341
- );
342
- }
343
- try {
344
- validateArtifactReview(normalized);
345
- assertUniqueReviewItemIds(normalized);
346
- } catch (error) {
347
- if (error instanceof PipelineError) {
348
- throw new PipelineError(
349
- ARTIFACT_ERROR_CODES.REVIEW_INVALID,
350
- "Artifact review does not satisfy the Protocol v1.1 review contract.",
351
- "",
352
- { issues: error.details?.issues ?? [] }
353
- );
354
- }
355
- throw error;
356
- }
357
- normalized.pins = normalized.pins.map((pin) => ({
358
- ...pin,
359
- replies: [...pin.replies].sort(stableItemSort)
360
- })).sort(stableItemSort);
361
- validateArtifactReview(normalized);
362
- return normalized;
363
- }
364
- function serializeReviewState(value) {
365
- const normalized = value?.kind === "artifact-review-state" ? validateReviewLedger(clone2(value)) : normalizeArtifactReview(value);
366
- return `${JSON.stringify(canonicalObject(normalized), null, 2)}
367
- `;
368
- }
369
- function readArtifactReviewState(path, { allowMissing = false } = {}) {
370
- const entry = finalEntry(path);
371
- if (!entry) {
372
- if (allowMissing) return null;
373
- throw new PipelineError(
374
- ARTIFACT_ERROR_CODES.REVIEW_IMPORT,
375
- "Artifact review state does not exist."
376
- );
377
- }
378
- try {
379
- if (entry.isSymbolicLink() || !entry.isFile()) {
380
- throw new PipelineError(
381
- ARTIFACT_ERROR_CODES.SYMLINK_ESCAPE,
382
- "Artifact review state destination is not a regular file."
383
- );
384
- }
385
- if (statSync(path).size > ARTIFACT_REVIEW_MAX_STATE_BYTES) {
386
- throw new PipelineError(
387
- ARTIFACT_ERROR_CODES.REQUEST_LIMIT,
388
- `Artifact review state exceeds ${ARTIFACT_REVIEW_MAX_STATE_BYTES} bytes.`
389
- );
390
- }
391
- return validateReviewLedger(JSON.parse(readFileSync(path, "utf8")));
392
- } catch (error) {
393
- if (error instanceof PipelineError) throw error;
394
- throw new PipelineError(
395
- ARTIFACT_ERROR_CODES.REVIEW_INVALID,
396
- "Artifact review state is malformed."
397
- );
398
- }
399
- }
400
- function writeArtifactReviewState(path, ledger, { fileSystem = {}, suffix = `${process.pid}.${randomBytes(8).toString("hex")}` } = {}) {
401
- validateReviewLedger(ledger);
402
- const fs = { existsSync, lstatSync, mkdirSync, writeFileSync, renameSync, rmSync, ...fileSystem };
403
- const temporary = `${path}.${suffix}.tmp`;
404
- const serialized = serializeReviewState(ledger);
405
- if (Buffer.byteLength(serialized, "utf8") > ARTIFACT_REVIEW_MAX_STATE_BYTES) {
406
- throw new PipelineError(
407
- ARTIFACT_ERROR_CODES.REQUEST_LIMIT,
408
- `Artifact review state exceeds ${ARTIFACT_REVIEW_MAX_STATE_BYTES} bytes.`
409
- );
410
- }
411
- try {
412
- const initial = finalEntry(path, fs);
413
- if (initial) {
414
- const target = initial;
415
- if (target.isSymbolicLink() || !target.isFile()) throw new Error("unsafe final target");
416
- }
417
- fs.mkdirSync(dirname(path), { recursive: true, mode: 448 });
418
- fs.writeFileSync(temporary, serialized, { mode: 384, flag: "wx" });
419
- const final = finalEntry(path, fs);
420
- if (final) {
421
- const target = final;
422
- if (target.isSymbolicLink() || !target.isFile()) throw new Error("unsafe final target");
423
- }
424
- fs.renameSync(temporary, path);
425
- } catch {
426
- try {
427
- fs.rmSync(temporary, { force: true });
428
- } catch {
429
- }
430
- throw new PipelineError(
431
- ARTIFACT_ERROR_CODES.REVIEW_WRITE,
432
- "Artifact review state could not be written atomically.",
433
- "Check destination permissions and retry; the previous review state was left unchanged."
434
- );
435
- }
436
- return ledger;
437
- }
438
- function withArtifactReviewLock(path, action3) {
439
- const previous = reviewPathQueues.get(path) ?? Promise.resolve();
440
- const run = async () => {
441
- let release;
442
- try {
443
- release = await acquireStartLock(`${path}.lock`, { timeout: 15e3, stale: 3e4 });
444
- return await action3();
445
- } catch (error) {
446
- if (error instanceof PipelineError) throw error;
447
- throw new PipelineError(
448
- ARTIFACT_ERROR_CODES.REVIEW_WRITE,
449
- "Artifact review state is busy or its cross-process lock is unavailable.",
450
- "Wait for the active review write to finish, then retry."
451
- );
452
- } finally {
453
- release?.();
454
- }
455
- };
456
- const operation = previous.then(run, run);
457
- const tail = operation.then(
458
- () => void 0,
459
- () => void 0
460
- );
461
- reviewPathQueues.set(path, tail);
462
- tail.finally(() => {
463
- if (reviewPathQueues.get(path) === tail) reviewPathQueues.delete(path);
464
- });
465
- return operation;
466
- }
467
- function normalizedExportInput(value) {
468
- if (value?.kind === "artifact-review-state") return validateReviewLedger(clone2(value));
469
- if (value?.review && value?.artifacts) return normalizeArtifactReview(value.review);
470
- return normalizeArtifactReview(value);
471
- }
472
- function markdownText(value) {
473
- return String(value ?? "").replace(/\r\n?/g, "\n").trim();
474
- }
475
- function renderPinMarkdown(pin, number) {
476
- const region = `${pin.region.x}, ${pin.region.y}, ${pin.region.w}, ${pin.region.h}`;
477
- const lines = [
478
- `### ${number}. ${pin.intent.toUpperCase()} \xB7 ${pin.status}`,
479
- "",
480
- `- Pin: \`${pin.id}\``,
481
- `- Artifact: \`${pin.artifactId}\`${pin.variant ? ` \xB7 variant \`${pin.variant}\`` : ""}`,
482
- `- Author: ${pin.author.name}`,
483
- `- Region: \`${region}\` at ${pin.viewport.width}\xD7${pin.viewport.height}`,
484
- ...pin.anchor ? [
485
- `- Anchor: \`${pin.anchor.planrId}\`${pin.anchor.screen ? ` \xB7 screen \`${pin.anchor.screen}\`` : ""}`
486
- ] : [],
487
- `- Updated: ${pin.updatedAt}`,
488
- "",
489
- markdownText(pin.comment)
490
- ];
491
- if (pin.replies.length > 0) {
492
- lines.push("", "#### Thread", "");
493
- for (const reply of pin.replies) {
494
- lines.push(`- **${reply.author.name}** (${reply.createdAt}): ${markdownText(reply.comment)}`);
495
- }
496
- }
497
- return lines.join("\n");
498
- }
499
- function reviewMarkdown(review, headingLevel = 2, stale = false) {
500
- const mark = "#".repeat(headingLevel);
501
- const lines = [
502
- `${mark} Review ${review.reviewId}${stale ? " \xB7 STALE" : ""}`,
503
- "",
504
- `- Digest: \`${review.reviewOf}\``,
505
- `- Decision: **${review.decision}**`,
506
- `- Pins: ${review.pins.length}`,
507
- ...review.createdAt ? [`- Created: ${review.createdAt}`] : [],
508
- ...review.updatedAt ? [`- Updated: ${review.updatedAt}`] : [],
509
- "",
510
- `${mark}# Overall feedback`,
511
- "",
512
- markdownText(review.overall) || "_No overall feedback._"
513
- ];
514
- if (review.pins.length > 0) {
515
- lines.push("", `${mark}# Pins`, "");
516
- review.pins.forEach((pin, index) => lines.push(renderPinMarkdown(pin, index + 1), ""));
517
- if (lines.at(-1) === "") lines.pop();
518
- }
519
- return lines.join("\n");
520
- }
521
- function exportArtifactReview(value, { format = "json" } = {}) {
522
- let normalized;
523
- try {
524
- normalized = normalizedExportInput(value);
525
- } catch (error) {
526
- if (error instanceof PipelineError) throw error;
527
- throw new PipelineError(
528
- ARTIFACT_ERROR_CODES.REVIEW_EXPORT,
529
- "Artifact review cannot be exported."
530
- );
531
- }
532
- if (format === "json") return serializeReviewState(normalized);
533
- if (format !== "markdown") {
534
- throw new PipelineError(
535
- ARTIFACT_ERROR_CODES.REVIEW_EXPORT,
536
- "Artifact review export format must be json or markdown."
537
- );
538
- }
539
- if (normalized.kind !== "artifact-review-state") {
540
- return `# OpenPlanr Artifact Review
541
-
542
- ${reviewMarkdown(normalized)}
543
- `;
544
- }
545
- const lines = [
546
- "# OpenPlanr Artifact Reviews",
547
- "",
548
- `- Artifact: \`${normalized.artifactId}\``,
549
- `- Current digest: \`${normalized.currentReviewOf}\``,
550
- `- Effective decision: **${effectiveReviewDecision(normalized)}**`,
551
- `- Reviews: ${normalized.reviews.length}`
552
- ];
553
- for (const entry of normalized.reviews) {
554
- lines.push("", reviewMarkdown(entry.review, 2, entry.stale));
555
- }
556
- return `${lines.join("\n")}
557
- `;
558
- }
559
-
560
- // packages/artifact/lib/artifact/import.mjs
561
- var ARTIFACT_ID_RE2 = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
562
- function pathError(code, message2) {
563
- throw new PipelineError(
564
- code,
565
- message2,
566
- "Choose a real, non-symlinked project or user review destination."
567
- );
568
- }
569
- function pathEntry(path, fs = { lstatSync: lstatSync2 }) {
570
- try {
571
- return fs.lstatSync(path);
572
- } catch (error) {
573
- if (error?.code === "ENOENT") return null;
574
- throw error;
575
- }
576
- }
577
- function inside(base, candidate) {
578
- const rel = relative(base, candidate);
579
- return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
580
- }
581
- function parseablePlanrConfig(root) {
582
- const path = join(root, PLANNING_FOLDER, "config.json");
583
- if (!existsSync2(path)) return false;
584
- try {
585
- if (lstatSync2(path).isSymbolicLink()) return false;
586
- const value = JSON.parse(readFileSync2(path, "utf8"));
587
- return value && typeof value === "object" && !Array.isArray(value) && (typeof value.projectName === "string" && value.projectName.trim() !== "" || value.idPrefix && typeof value.idPrefix === "object" && !Array.isArray(value.idPrefix) && Object.keys(value.idPrefix).length > 0);
588
- } catch {
589
- return false;
590
- }
591
- }
592
- function hasGitMarker(root) {
593
- const marker = join(root, ".git");
594
- if (!existsSync2(marker)) return false;
595
- try {
596
- const stat = lstatSync2(marker);
597
- if (stat.isSymbolicLink()) return false;
598
- if (stat.isDirectory()) {
599
- const head = join(marker, "HEAD");
600
- return existsSync2(head) && lstatSync2(head).isFile();
601
- }
602
- if (!stat.isFile() || stat.size > 4096) return false;
603
- const match = /^gitdir:\s*(.+?)\s*$/u.exec(readFileSync2(marker, "utf8"));
604
- if (!match) return false;
605
- const gitDir = resolve(root, match[1]);
606
- return existsSync2(gitDir) && statSync2(gitDir).isDirectory() && existsSync2(join(gitDir, "HEAD")) && lstatSync2(join(gitDir, "HEAD")).isFile();
607
- } catch {
608
- return false;
609
- }
610
- }
611
- function findArtifactProjectRoot(start = process.cwd(), { env = process.env } = {}) {
612
- let current;
613
- try {
614
- current = realpathSync(resolve(start));
615
- } catch {
616
- pathError(
617
- ARTIFACT_ERROR_CODES.REVIEW_IMPORT,
618
- "Artifact review working directory does not exist."
619
- );
620
- }
621
- const homeCandidate = resolve(env.HOME ?? homedir());
622
- let home = homeCandidate;
623
- try {
624
- home = realpathSync(homeCandidate);
625
- } catch {
626
- }
627
- while (true) {
628
- if (current !== home && (parseablePlanrConfig(current) || hasGitMarker(current)))
629
- return current;
630
- const parent = dirname2(current);
631
- if (parent === current) return null;
632
- current = parent;
633
- }
634
- }
635
- function assertSafeDestination(base, relativeParts) {
636
- const absoluteBase = resolve(base);
637
- if (existsSync2(absoluteBase) && lstatSync2(absoluteBase).isSymbolicLink()) {
638
- pathError(
639
- ARTIFACT_ERROR_CODES.SYMLINK_ESCAPE,
640
- "Artifact review destination base is a symlink."
641
- );
642
- }
643
- let realBase = absoluteBase;
644
- if (existsSync2(absoluteBase)) realBase = realpathSync(absoluteBase);
645
- let current = absoluteBase;
646
- for (const part of relativeParts) {
647
- if (!part || part === "." || part === ".." || part.includes("/") || part.includes("\\") || part.includes("\0")) {
648
- pathError(
649
- ARTIFACT_ERROR_CODES.PATH_TRAVERSAL,
650
- "Artifact review destination contains an unsafe segment."
651
- );
652
- }
653
- current = join(current, part);
654
- const entry = pathEntry(current);
655
- if (!entry) continue;
656
- if (entry.isSymbolicLink()) {
657
- pathError(
658
- ARTIFACT_ERROR_CODES.SYMLINK_ESCAPE,
659
- "Artifact review destination contains a symlink."
660
- );
661
- }
662
- if (!inside(realBase, realpathSync(current))) {
663
- pathError(
664
- ARTIFACT_ERROR_CODES.PATH_TRAVERSAL,
665
- "Artifact review destination escapes its storage root."
666
- );
667
- }
668
- }
669
- if (!inside(absoluteBase, current)) {
670
- pathError(
671
- ARTIFACT_ERROR_CODES.PATH_TRAVERSAL,
672
- "Artifact review destination escapes its storage root."
673
- );
674
- }
675
- return current;
676
- }
677
- function resolveArtifactReviewDestination({
678
- cwd = process.cwd(),
679
- env = process.env,
680
- artifactId,
681
- designDir
682
- } = {}) {
683
- if (!ARTIFACT_ID_RE2.test(artifactId ?? "")) {
684
- pathError(
685
- ARTIFACT_ERROR_CODES.PATH_TRAVERSAL,
686
- "Artifact review ID is unsafe for local storage."
687
- );
688
- }
689
- if (designDir !== void 0) {
690
- const lexical = resolve(designDir);
691
- if (!existsSync2(lexical) || !statSync2(lexical).isDirectory()) {
692
- pathError(ARTIFACT_ERROR_CODES.REVIEW_IMPORT, "Design review destination does not exist.");
693
- }
694
- if (lstatSync2(lexical).isSymbolicLink()) {
695
- pathError(
696
- ARTIFACT_ERROR_CODES.SYMLINK_ESCAPE,
697
- "Design review destination must be a real directory."
698
- );
699
- }
700
- const requested = realpathSync(lexical);
701
- return Object.freeze({
702
- kind: "design",
703
- artifactId,
704
- directory: requested,
705
- path: join(requested, FEEDBACK_FILE),
706
- reviewStatePath: join(requested, "artifact-review-state.json")
707
- });
708
- }
709
- const projectRoot = findArtifactProjectRoot(cwd, { env });
710
- if (projectRoot) {
711
- const directory2 = assertSafeDestination(projectRoot, [
712
- PLANNING_FOLDER,
713
- "artifacts",
714
- artifactId
715
- ]);
716
- return Object.freeze({
717
- kind: "project",
718
- artifactId,
719
- root: projectRoot,
720
- directory: directory2,
721
- path: join(directory2, "review-state.json")
722
- });
723
- }
724
- const root = resolve(planrHome(env));
725
- const directory = assertSafeDestination(root, ["artifacts", artifactId]);
726
- return Object.freeze({
727
- kind: "user",
728
- artifactId,
729
- root,
730
- directory,
731
- path: join(directory, "review-state.json")
732
- });
733
- }
734
- function reviewsFromDecoded(value) {
735
- if (!value || typeof value !== "object" || Array.isArray(value)) {
736
- throw new PipelineError(
737
- ARTIFACT_ERROR_CODES.REVIEW_IMPORT,
738
- "Decoded review payload is not an object."
739
- );
740
- }
741
- if (value.kind === "artifact-review-state") {
742
- validateReviewLedger(value);
743
- return value.reviews.map((entry) => ({ review: entry.review, stale: entry.stale }));
744
- }
745
- if (value.artifacts && value.viewer) {
746
- validateArtifactEnvelope(value);
747
- if (!value.review) {
748
- throw new PipelineError(
749
- ARTIFACT_ERROR_CODES.REVIEW_IMPORT,
750
- "Decoded artifact envelope contains no review."
751
- );
752
- }
753
- return [{ review: value.review, stale: false }];
754
- }
755
- if (value.review && !value.reviewId) return reviewsFromDecoded(value.review);
756
- validateArtifactReview(value);
757
- return [{ review: value, stale: false }];
758
- }
759
- async function decodeArtifactReviewSources(sources, { decodeSource, withMetadata = false } = {}) {
760
- const list2 = Array.isArray(sources) ? sources : [sources];
761
- if (list2.length === 0) {
762
- throw new PipelineError(
763
- ARTIFACT_ERROR_CODES.REVIEW_IMPORT,
764
- "At least one artifact review source is required."
765
- );
766
- }
767
- const entries = [];
768
- for (let index = 0; index < list2.length; index += 1) {
769
- const source = list2[index];
770
- let decoded = source;
771
- if (typeof source === "string") {
772
- if (typeof decodeSource !== "function") {
773
- throw new PipelineError(
774
- ARTIFACT_ERROR_CODES.REVIEW_DECODER_REQUIRED,
775
- "String and URL review sources require an injected async decoder.",
776
- "Provide decodeSource(source, { index }); the review lifecycle has no transport dependency.",
777
- { sourceIndex: index }
778
- );
779
- }
780
- try {
781
- decoded = await decodeSource(source, { index });
782
- } catch {
783
- throw new PipelineError(
784
- ARTIFACT_ERROR_CODES.REVIEW_IMPORT,
785
- "Artifact review source could not be decoded.",
786
- "Verify the immutable review link and retry.",
787
- { sourceIndex: index }
788
- );
789
- }
790
- }
791
- try {
792
- entries.push(
793
- ...reviewsFromDecoded(decoded).map((entry) => ({
794
- review: structuredClone(entry.review),
795
- stale: Boolean(entry.stale)
796
- }))
797
- );
798
- } catch (error) {
799
- if (error instanceof PipelineError && error.code === ARTIFACT_ERROR_CODES.REVIEW_IMPORT) {
800
- error.details = { sourceIndex: index };
801
- throw error;
802
- }
803
- throw new PipelineError(
804
- ARTIFACT_ERROR_CODES.REVIEW_IMPORT,
805
- "Decoded artifact review does not satisfy the Protocol v1.1 contract.",
806
- "",
807
- { sourceIndex: index }
808
- );
809
- }
810
- }
811
- return withMetadata ? entries : entries.map((entry) => entry.review);
812
- }
813
-
814
- // packages/design/lib/design/feedback-reader.mjs
815
- var designReviewKey = (document) => `design-${hash(document.id).slice(0, 24)}`;
816
- function designReviewPath(file, env = process.env, options = {}) {
817
- const { root, document } = currentDesign(file, options);
818
- return resolveArtifactReviewDestination({
819
- cwd: root,
820
- env,
821
- artifactId: designReviewKey(document)
822
- }).path;
823
- }
824
- function readDesignFeedback(file, env = process.env, options = {}) {
825
- const current = currentDesign(file, options);
826
- const ledger = readArtifactReviewState(designReviewPath(file, env, options), {
827
- allowMissing: true
828
- });
829
- const digest2 = digestArtifactEnvelope(current.envelope);
830
- const pins = (ledger?.reviews ?? []).flatMap(
831
- (entry) => entry.review.pins.map((pin) => {
832
- const target = current.entries.find((item) => item.artifactId === pin.artifactId);
833
- const screen = target && current.document.screens.find((item) => item.id === target.screenId);
834
- const anchorMissing = pin.anchor?.planrId && screen?.anchors?.length && !screen.anchors.includes(pin.anchor.planrId) && pin.anchor.planrId !== screen.id;
835
- return {
836
- ...pin,
837
- reviewId: entry.review.reviewId,
838
- reviewOf: entry.review.reviewOf,
839
- ...entry.review.reviewId.startsWith("shared-") ? { revisionId: entry.review.reviewId.slice(7) } : {},
840
- stale: entry.stale || entry.review.reviewOf !== digest2 || !target || Boolean(anchorMissing),
841
- ...target ? { screenId: target.screenId, variantId: target.variantId } : {}
842
- };
843
- })
844
- );
845
- return {
846
- revision: current.revision,
847
- reviewPath: designReviewPath(file, env, options),
848
- pins,
849
- state: readJson(join2(current.root, ".design/studio-state.json"), {
850
- state: {},
851
- stateVersion: 0
852
- }).state,
853
- ledger,
854
- shared: readJson(join2(current.root, ".design/shared-feedback.json"), null)
855
- };
856
- }
857
-
858
- // packages/design/lib/design/handoff-reader.mjs
859
- import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
860
- import { dirname as dirname3, join as join3 } from "node:path";
861
-
862
- // packages/design/lib/design/handoff-format.mjs
863
- var safeMd = (text2) => String(text2).replaceAll("[", "\\[").replaceAll("]", "\\]").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
864
- function renderMarkdown(draft, title2) {
865
- const lines = [
866
- `# ${safeMd(title2)} \u2014 review handoff`,
867
- "",
868
- `Status: ${draft.status}. Source revision: ${draft.basis.sourceRevision}.`,
869
- "",
870
- draft.content.summary || "Owner summary has not been written.",
871
- ""
872
- ];
873
- for (const [key, label] of [
874
- ["agreedChanges", "Agreed changes"],
875
- ["openQuestions", "Open questions"],
876
- ["deferred", "Deferred"],
877
- ["rejected", "Rejected"]
878
- ]) {
879
- lines.push(`## ${label}`, "");
880
- for (const item of draft.content[key]) {
881
- lines.push(
882
- `- ${safeMd(item.refinement ?? item.text)} \u2014 ${safeMd(item.author ?? "Reviewer")}${item.stale ? " \xB7 original revision" : ""} [source comment](${item.source})`
883
- );
884
- if (item.refinement) lines.push(` Original comment: ${safeMd(item.text)}`);
885
- }
886
- if (!draft.content[key].length) lines.push("None recorded.");
887
- lines.push("");
888
- }
889
- lines.push(
890
- "## Overall review notes",
891
- "",
892
- ...draft.reviewNotes.map((note) => `- ${safeMd(note.text)} (${safeMd(note.reviewId)})`),
893
- ""
894
- );
895
- lines.push(
896
- "## Verification gaps",
897
- "",
898
- ...draft.verificationGaps.length ? draft.verificationGaps.map((value) => `- ${safeMd(value)}`) : ["None recorded."],
899
- "",
900
- "Plan and Ship remain separate user invocations.",
901
- ""
902
- );
903
- return lines.join("\n");
904
- }
905
-
906
- // packages/protocol/src/design-handoff-contracts.mjs
907
- var DESIGN_HANDOFF_PROTOCOL_VERSION = "1.11.0";
908
- var DESIGN_HANDOFF_CONTRACT_VERSION = "1.0.0";
909
- var DESIGN_HANDOFF_AUTHORITY = "prepare-plan";
910
- var DESIGN_HANDOFF_CHECK_IDS = Object.freeze([
911
- "current-revision",
912
- "selected-direction",
913
- "design-specification",
914
- "rendered-verification",
915
- "review-freshness",
916
- "review-dispositions",
917
- "unresolved-blockers",
918
- "approved-review-handoff"
919
- ]);
920
- var DESIGN_HANDOFF_SOURCE_KINDS = Object.freeze([
921
- "design-revision",
922
- "selected-direction",
923
- "design-specification",
924
- "rendered-verification",
925
- "review-context",
926
- "review-feedback",
927
- "review-metadata",
928
- "review-handoff",
929
- "screen",
930
- "frame",
931
- "component",
932
- "state",
933
- "flow",
934
- "token",
935
- "review-decision",
936
- "element-anchor"
937
- ]);
938
- var DESIGN_HANDOFF_REQUIREMENT_KINDS = Object.freeze([
939
- "behavior",
940
- "visual-state",
941
- "responsive",
942
- "accessibility",
943
- "content-data-assumption",
944
- "constraint",
945
- "verification-intent"
946
- ]);
947
- var DESIGN_HANDOFF_CONTRACT_FILES = Object.freeze({
948
- "design-handoff-readiness": "design-handoff-readiness.schema.json",
949
- "design-implementation-handoff": "design-implementation-handoff.schema.json",
950
- "design-planning-lineage": "design-planning-lineage.schema.json"
951
- });
952
- var text = { type: "string", minLength: 1, maxLength: 16384 };
953
- var title = { ...text, maxLength: 240 };
954
- var id = {
955
- type: "string",
956
- minLength: 1,
957
- maxLength: 160,
958
- pattern: "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
959
- };
960
- var digest = { type: "string", pattern: "^sha256:[a-f0-9]{64}$" };
961
- var relativePath = { type: "string", minLength: 1, maxLength: 4096 };
962
- var timestamp = { type: "string", format: "date-time" };
963
- var list = (items, maxItems = 1e3) => ({ type: "array", items, maxItems });
964
- var closed = (properties, required = Object.keys(properties)) => ({
965
- type: "object",
966
- additionalProperties: false,
967
- properties,
968
- required
969
- });
970
- var contract = (name, body) => ({
971
- $schema: "https://json-schema.org/draft/2020-12/schema",
972
- $id: `https://openplanr.dev/schemas/v1.11.0/${name}.schema.json`,
973
- "x-openplanr-contract": { id: name, version: DESIGN_HANDOFF_PROTOCOL_VERSION },
974
- ...body
975
- });
976
- var action = closed({ id, label: title });
977
- var anchor = {
978
- oneOf: [
979
- closed({ section: id }),
980
- closed({ screenId: id }),
981
- closed({ screenId: id, elementId: id }),
982
- closed({ reviewId: id, pinId: id })
983
- ]
984
- };
985
- var evidenceReference = closed(
986
- {
987
- id,
988
- kind: { enum: DESIGN_HANDOFF_SOURCE_KINDS },
989
- path: relativePath,
990
- revision: digest,
991
- digest,
992
- anchor
993
- },
994
- ["id", "kind", "path"]
995
- );
996
- var readinessCheck = closed(
997
- {
998
- id: { enum: DESIGN_HANDOFF_CHECK_IDS },
999
- status: { enum: ["pass", "attention", "blocked", "stale"] },
1000
- message: title,
1001
- evidenceRefs: list(id, 64),
1002
- recoveryAction: action
1003
- },
1004
- ["id", "status", "message", "evidenceRefs"]
1005
- );
1006
- var readinessRecord = closed({
1007
- kind: { const: "openplanr-design-handoff-readiness" },
1008
- schemaVersion: { const: DESIGN_HANDOFF_CONTRACT_VERSION },
1009
- scope: { const: "design-originated" },
1010
- authority: { const: "none" },
1011
- designId: id,
1012
- sourceRevision: { anyOf: [digest, { type: "null" }] },
1013
- selectedVariant: { anyOf: [id, { type: "null" }] },
1014
- status: { enum: ["ready", "attention", "blocked", "stale"] },
1015
- continuation: closed({
1016
- action: { const: DESIGN_HANDOFF_AUTHORITY },
1017
- available: { type: "boolean" }
1018
- }),
1019
- checks: list(readinessCheck, DESIGN_HANDOFF_CHECK_IDS.length),
1020
- evidence: list(evidenceReference, 1e4),
1021
- blockers: list({ enum: DESIGN_HANDOFF_CHECK_IDS }, DESIGN_HANDOFF_CHECK_IDS.length),
1022
- nextActions: list(action, DESIGN_HANDOFF_CHECK_IDS.length)
1023
- });
1024
- var readinessAbsence = closed({
1025
- kind: { const: "openplanr-design-handoff-readiness-absence" },
1026
- schemaVersion: { const: DESIGN_HANDOFF_CONTRACT_VERSION },
1027
- status: { const: "absent" },
1028
- reason: { enum: ["not-computed", "not-applicable", "unavailable"] },
1029
- message: title,
1030
- nextAction: action
1031
- });
1032
- var DESIGN_HANDOFF_READINESS_SCHEMA = contract("design-handoff-readiness", {
1033
- oneOf: [readinessRecord, readinessAbsence]
1034
- });
1035
- var requirement = closed({
1036
- id: { type: "string", pattern: "^REQ-[0-9]{3,}$" },
1037
- kind: { enum: DESIGN_HANDOFF_REQUIREMENT_KINDS },
1038
- statement: text,
1039
- sourceRefs: { ...list(id, 256), minItems: 1 },
1040
- verification: { ...list(text, 256), minItems: 1 }
1041
- });
1042
- var implementationHandoff = closed(
1043
- {
1044
- kind: { const: "openplanr-design-implementation-handoff" },
1045
- schemaVersion: { const: DESIGN_HANDOFF_CONTRACT_VERSION },
1046
- id,
1047
- version: { type: "integer", minimum: 1 },
1048
- status: { enum: ["draft", "approved", "superseded", "revoked"] },
1049
- authority: { const: DESIGN_HANDOFF_AUTHORITY },
1050
- title,
1051
- basis: closed({
1052
- designId: id,
1053
- sourceRevision: digest,
1054
- selectedVariant: id,
1055
- readiness: closed({ status: { enum: ["ready", "attention", "blocked", "stale"] }, digest }),
1056
- reviewHandoff: closed({ version: { type: "integer", minimum: 1 }, contentDigest: digest })
1057
- }),
1058
- sources: list(evidenceReference, 1e4),
1059
- requirements: { ...list(requirement, 1e4), minItems: 1 },
1060
- contentDigest: digest,
1061
- markdown: { type: "string", maxLength: 2097152 },
1062
- approval: closed({
1063
- actorId: id,
1064
- approvedAt: timestamp,
1065
- contentDigest: digest,
1066
- authority: { const: DESIGN_HANDOFF_AUTHORITY }
1067
- }),
1068
- supersededBy: closed({ id, version: { type: "integer", minimum: 1 }, contentDigest: digest }),
1069
- revocation: closed({ actorId: id, revokedAt: timestamp, reason: text })
1070
- },
1071
- [
1072
- "kind",
1073
- "schemaVersion",
1074
- "id",
1075
- "version",
1076
- "status",
1077
- "authority",
1078
- "title",
1079
- "basis",
1080
- "sources",
1081
- "requirements",
1082
- "contentDigest",
1083
- "markdown"
1084
- ]
1085
- );
1086
- implementationHandoff.allOf = [
1087
- {
1088
- if: { properties: { status: { const: "approved" } }, required: ["status"] },
1089
- then: {
1090
- required: ["approval"],
1091
- not: { anyOf: [{ required: ["supersededBy"] }, { required: ["revocation"] }] }
1092
- }
1093
- },
1094
- {
1095
- if: { properties: { status: { const: "superseded" } }, required: ["status"] },
1096
- then: { required: ["approval", "supersededBy"], not: { required: ["revocation"] } }
1097
- },
1098
- {
1099
- if: { properties: { status: { const: "revoked" } }, required: ["status"] },
1100
- then: { required: ["approval", "revocation"], not: { required: ["supersededBy"] } }
1101
- },
1102
- {
1103
- if: { properties: { status: { const: "draft" } }, required: ["status"] },
1104
- then: {
1105
- not: {
1106
- anyOf: [
1107
- { required: ["approval"] },
1108
- { required: ["supersededBy"] },
1109
- { required: ["revocation"] }
1110
- ]
1111
- }
1112
- }
1113
- }
1114
- ];
1115
- var DESIGN_IMPLEMENTATION_HANDOFF_SCHEMA = contract(
1116
- "design-implementation-handoff",
1117
- implementationHandoff
1118
- );
1119
- var lineageMapping = closed({
1120
- requirementId: { type: "string", pattern: "^REQ-[0-9]{3,}$" },
1121
- acceptanceRefs: {
1122
- ...list(
1123
- closed({
1124
- storyId: { type: "string", pattern: "^US-[0-9]{3,}$" },
1125
- acceptanceId: { type: "string", pattern: "^AC-[0-9]{3,}$" }
1126
- }),
1127
- 256
1128
- ),
1129
- minItems: 1
1130
- },
1131
- taskIds: { ...list({ type: "string", pattern: "^T-[0-9]{3,}$" }, 256), minItems: 1 }
1132
- });
1133
- var DESIGN_PLANNING_LINEAGE_SCHEMA = contract(
1134
- "design-planning-lineage",
1135
- closed({
1136
- kind: { const: "openplanr-design-planning-lineage" },
1137
- schemaVersion: { const: DESIGN_HANDOFF_CONTRACT_VERSION },
1138
- handoff: closed({ id, version: { type: "integer", minimum: 1 }, contentDigest: digest }),
1139
- specId: { type: "string", pattern: "^SPEC-[0-9]{3,}$" },
1140
- mappings: { ...list(lineageMapping, 1e4), minItems: 1 }
1141
- })
1142
- );
1143
- var DESIGN_HANDOFF_SCHEMAS = deepFreeze({
1144
- "design-handoff-readiness": DESIGN_HANDOFF_READINESS_SCHEMA,
1145
- "design-implementation-handoff": DESIGN_IMPLEMENTATION_HANDOFF_SCHEMA,
1146
- "design-planning-lineage": DESIGN_PLANNING_LINEAGE_SCHEMA
1147
- });
1148
- function distinct(items, select, label) {
1149
- const values = items.map(select);
1150
- if (new Set(values).size !== values.length) throw new TypeError(`Duplicate ${label}.`);
1151
- }
1152
- function isDesignHandoffRelativePath(value) {
1153
- return typeof value === "string" && value.length > 0 && value.length <= 4096 && !/^(?:[A-Za-z]:|\/|[A-Za-z][A-Za-z0-9+.-]*:)|[\\?#%\u0000-\u001f\u007f]/u.test(value) && value.split("/").every(
1154
- (part) => part && part !== "." && part !== ".." && !["__proto__", "prototype", "constructor"].includes(part)
1155
- );
1156
- }
1157
- function assertDesignHandoffContract(value, schemaOrName) {
1158
- const schema = typeof schemaOrName === "string" ? DESIGN_HANDOFF_SCHEMAS[schemaOrName] : schemaOrName;
1159
- if (!schema) throw new TypeError("Unknown design handoff contract.");
1160
- assertPlainData(value, "Design handoff data");
1161
- canonicalizeJson(value);
1162
- const errors = validateJson(value, schema);
1163
- if (errors.length)
1164
- throw new TypeError(
1165
- `Invalid ${schema["x-openplanr-contract"]?.id ?? "design handoff data"}: ${errors.slice(0, 5).map((error) => `${error.path} (${error.rule})`).join("; ")}`
1166
- );
1167
- return value;
1168
- }
1169
- function assertEvidenceReferences(evidence2) {
1170
- distinct(evidence2, (item) => item.id, "evidence reference identity");
1171
- for (const item of evidence2)
1172
- if (!isDesignHandoffRelativePath(item.path))
1173
- throw new TypeError("Design handoff evidence requires a repository-relative logical path.");
1174
- }
1175
- function assertProductCopy(value) {
1176
- if (/\b(?:hash|digest|checksum|sha[- ]?256|canonical(?:ize|ization)?)\b/iu.test(value))
1177
- throw new TypeError("Design readiness guidance must use product language.");
1178
- }
1179
- function assertDesignHandoffReadiness(value) {
1180
- assertDesignHandoffContract(value, DESIGN_HANDOFF_READINESS_SCHEMA);
1181
- if (value.kind.endsWith("-absence")) {
1182
- assertProductCopy(`${value.message} ${value.nextAction.label}`);
1183
- return value;
1184
- }
1185
- assertEvidenceReferences(value.evidence);
1186
- distinct(value.checks, (item) => item.id, "readiness check identity");
1187
- const expected = DESIGN_HANDOFF_CHECK_IDS.join("\n");
1188
- if (value.checks.map((item) => item.id).join("\n") !== expected)
1189
- throw new TypeError("Design readiness must contain every stable check in canonical order.");
1190
- const evidenceIds = new Set(value.evidence.map((item) => item.id));
1191
- for (const check of value.checks) {
1192
- distinct(check.evidenceRefs, (item) => item, "readiness evidence reference");
1193
- if (check.evidenceRefs.some((reference) => !evidenceIds.has(reference)))
1194
- throw new TypeError("Design readiness references missing evidence.");
1195
- assertProductCopy(`${check.message} ${check.recoveryAction?.label ?? ""}`);
1196
- }
1197
- const priority2 = { pass: 0, attention: 1, blocked: 2, stale: 3 };
1198
- const worst = value.checks.reduce(
1199
- (current, check) => priority2[check.status] > priority2[current] ? check.status : current,
1200
- "pass"
1201
- );
1202
- const expectedStatus = worst === "pass" ? "ready" : worst;
1203
- if (value.status !== expectedStatus)
1204
- throw new TypeError("Design readiness summary does not match its checks.");
1205
- const blockingIds = value.checks.filter((check) => ["blocked", "stale"].includes(check.status)).map((check) => check.id);
1206
- if (value.blockers.join("\n") !== blockingIds.join("\n"))
1207
- throw new TypeError("Design readiness blockers do not match its blocking checks.");
1208
- const actionable = value.checks.filter((check) => check.status !== "pass");
1209
- if (value.nextActions.length !== actionable.length || value.nextActions.some((actionValue, index) => {
1210
- const recoveryAction = actionable[index].recoveryAction;
1211
- return actionValue.id !== recoveryAction?.id || actionValue.label !== recoveryAction?.label;
1212
- }))
1213
- throw new TypeError("Design readiness next actions do not match its checks.");
1214
- if (value.continuation.available !== ["ready", "attention"].includes(value.status))
1215
- throw new TypeError("Design readiness continuation availability does not match its status.");
1216
- return value;
1217
- }
1218
- function designImplementationHandoffDigest(value) {
1219
- const projection = {
1220
- kind: value.kind,
1221
- schemaVersion: value.schemaVersion,
1222
- id: value.id,
1223
- version: value.version,
1224
- authority: value.authority,
1225
- title: value.title,
1226
- basis: value.basis,
1227
- sources: value.sources,
1228
- requirements: value.requirements,
1229
- markdown: value.markdown
1230
- };
1231
- return `sha256:${sha256Hex(canonicalizeJson(projection))}`;
1232
- }
1233
- function assertDesignImplementationHandoff(value) {
1234
- assertDesignHandoffContract(value, DESIGN_IMPLEMENTATION_HANDOFF_SCHEMA);
1235
- assertEvidenceReferences(value.sources);
1236
- distinct(value.requirements, (item) => item.id, "implementation requirement identity");
1237
- const sourceIds = new Set(value.sources.map((item) => item.id));
1238
- for (const item of value.requirements) {
1239
- distinct(item.sourceRefs, (reference) => reference, "requirement source reference");
1240
- if (item.sourceRefs.some((reference) => !sourceIds.has(reference)))
1241
- throw new TypeError("Implementation requirement references missing evidence.");
1242
- }
1243
- if (value.contentDigest !== designImplementationHandoffDigest(value))
1244
- throw new TypeError(
1245
- "Implementation handoff content does not match its recorded integrity value."
1246
- );
1247
- if (value.approval?.contentDigest !== void 0 && value.approval.contentDigest !== value.contentDigest)
1248
- throw new TypeError("Implementation handoff approval does not match its content.");
1249
- if (value.status !== "draft" && value.basis.readiness.status !== "ready")
1250
- throw new TypeError(
1251
- "Only a ready implementation handoff can be approved or retained as approved history."
1252
- );
1253
- if (value.supersededBy && value.supersededBy.id === value.id && value.supersededBy.version <= value.version)
1254
- throw new TypeError("A superseding handoff must identify a newer package version.");
1255
- return value;
1256
- }
1257
-
1258
- // packages/design/lib/design/handoff-readiness.mjs
1259
- var CHECKS = Object.freeze([
1260
- "current-revision",
1261
- "selected-direction",
1262
- "design-specification",
1263
- "rendered-verification",
1264
- "review-freshness",
1265
- "review-dispositions",
1266
- "unresolved-blockers",
1267
- "approved-review-handoff"
1268
- ]);
1269
- var action2 = Object.freeze({
1270
- "current-revision": Object.freeze({ id: "render-design", label: "Render the current design" }),
1271
- "selected-direction": Object.freeze({
1272
- id: "select-direction",
1273
- label: "Choose one ready direction"
1274
- }),
1275
- "design-specification": Object.freeze({
1276
- id: "complete-design-specification",
1277
- label: "Complete the design specification"
1278
- }),
1279
- "rendered-verification": Object.freeze({
1280
- id: "verify-rendered-design",
1281
- label: "Verify the rendered design"
1282
- }),
1283
- "review-freshness": Object.freeze({
1284
- id: "refresh-review",
1285
- label: "Refresh review against the current design"
1286
- }),
1287
- "review-dispositions": Object.freeze({
1288
- id: "resolve-review-decisions",
1289
- label: "Record the remaining review decisions"
1290
- }),
1291
- "unresolved-blockers": Object.freeze({
1292
- id: "resolve-review-blockers",
1293
- label: "Resolve the blocking feedback"
1294
- }),
1295
- "approved-review-handoff": Object.freeze({
1296
- id: "approve-review-handoff",
1297
- label: "Prepare and approve the current review handoff"
1298
- })
1299
- });
1300
- var message = Object.freeze({
1301
- "current-revision": Object.freeze({
1302
- pass: "The current design has a completed render.",
1303
- blocked: "Render the design before preparing work for engineering."
1304
- }),
1305
- "selected-direction": Object.freeze({
1306
- pass: "One ready design direction is selected.",
1307
- blocked: "Choose one ready design direction before continuing.",
1308
- stale: "The selected direction changed after the review handoff was prepared."
1309
- }),
1310
- "design-specification": Object.freeze({
1311
- pass: "The design specification is complete for this revision.",
1312
- blocked: "Complete the design specification before continuing.",
1313
- stale: "The design specification belongs to an earlier revision."
1314
- }),
1315
- "rendered-verification": Object.freeze({
1316
- pass: "The rendered design is verified for this revision.",
1317
- blocked: "Complete rendered design verification before continuing.",
1318
- stale: "Rendered verification belongs to an earlier revision."
1319
- }),
1320
- "review-freshness": Object.freeze({
1321
- pass: "Review feedback is current for this revision.",
1322
- blocked: "Review feedback contains ambiguous identities or anchors.",
1323
- stale: "Review feedback belongs to an earlier revision."
1324
- }),
1325
- "review-dispositions": Object.freeze({
1326
- pass: "Every current review comment has a recorded outcome.",
1327
- attention: "Some non-blocking review comments still need an owner decision.",
1328
- blocked: "Review decisions are incomplete or ambiguous."
1329
- }),
1330
- "unresolved-blockers": Object.freeze({
1331
- pass: "No blocking feedback remains open.",
1332
- blocked: "Blocking feedback must be resolved before continuing.",
1333
- stale: "A prior decision must be reviewed against the current design."
1334
- }),
1335
- "approved-review-handoff": Object.freeze({
1336
- pass: "The current review handoff is approved.",
1337
- blocked: "Prepare and approve the review handoff before continuing.",
1338
- stale: "The approved review handoff no longer matches the current design."
1339
- })
1340
- });
1341
- var priority = Object.freeze({ pass: 0, attention: 1, blocked: 2, stale: 3 });
1342
- var digestPattern = /^(?:sha256:)?[a-f0-9]{64}$/u;
1343
- var normalizeDigest = (value, label) => {
1344
- if (typeof value !== "string" || !digestPattern.test(value))
1345
- throw new TypeError(`${label} must be a lowercase SHA-256 value.`);
1346
- return value.startsWith("sha256:") ? value : `sha256:${value}`;
1347
- };
1348
- var optionalDigest = (value, label) => value === void 0 || value === null ? void 0 : normalizeDigest(value, label);
1349
- var plainClone = (value) => value === void 0 ? void 0 : JSON.parse(canonicalizeJson(value));
1350
- var logicalPath = (value, fallback, label) => {
1351
- const result = value ?? fallback;
1352
- if (!isDesignHandoffRelativePath(result) || /[?#%]/u.test(result))
1353
- throw new TypeError(`${label} must be a repository-relative logical path.`);
1354
- return result;
1355
- };
1356
- var evidenceDigest = (value) => `sha256:${sha256Hex(canonicalizeJson(value))}`;
1357
- function ensureUnique(items, select, label) {
1358
- const values = items.map(select);
1359
- if (new Set(values).size !== values.length) throw new TypeError(`Duplicate ${label}.`);
1360
- }
1361
- function evidence(id2, kind, path, value, { revision, anchor: anchor2 } = {}) {
1362
- return {
1363
- id: id2,
1364
- kind,
1365
- path,
1366
- ...revision ? { revision: normalizeDigest(revision, `${id2} revision`) } : {},
1367
- digest: optionalDigest(value?.digest, `${id2} integrity`) ?? evidenceDigest(value),
1368
- ...anchor2 ? { anchor: anchor2 } : {}
1369
- };
1370
- }
1371
- function checked(id2, status, evidenceRefs = []) {
1372
- return {
1373
- id: id2,
1374
- status,
1375
- message: message[id2][status],
1376
- evidenceRefs,
1377
- ...status === "pass" ? {} : { recoveryAction: action2[id2] }
1378
- };
1379
- }
1380
- function selectedDirection(document, studioState) {
1381
- const selected = studioState?.selectedVariant ?? document?.selectedVariant ?? null;
1382
- const variants = Array.isArray(document?.variants) ? document.variants : [];
1383
- ensureUnique(variants, (item) => item?.id, "design direction identity");
1384
- const matches = variants.filter((item) => item?.id === selected && item?.status === "ready");
1385
- return { selected, ready: matches.length === 1 };
1386
- }
1387
- function normalizedPins(review, revision) {
1388
- const pins = Array.isArray(review?.pins) ? review.pins.map((pin) => ({ ...pin })) : [];
1389
- ensureUnique(
1390
- pins,
1391
- (pin) => `${pin.revisionId ?? pin.reviewId ?? ""}:${pin.id ?? ""}`,
1392
- "review comment identity"
1393
- );
1394
- for (const pin of pins) {
1395
- if (typeof pin.id !== "string" || !pin.id)
1396
- throw new TypeError("Review comments require stable identities.");
1397
- if (pin.elementId && !pin.screenId)
1398
- throw new TypeError("An element review anchor must identify its screen.");
1399
- if (pin.anchorCount !== void 0 && pin.anchorCount !== 1)
1400
- throw new TypeError("Review comments must identify exactly one anchor.");
1401
- }
1402
- return pins.sort(
1403
- (left, right) => `${left.revisionId ?? left.reviewId}:${left.id}`.localeCompare(
1404
- `${right.revisionId ?? right.reviewId}:${right.id}`
1405
- )
1406
- ).map((pin) => ({
1407
- ...pin,
1408
- current: !pin.stale && (!revision || !pin.revisionId || normalizeDigest(pin.revisionId, "review revision") === revision)
1409
- }));
1410
- }
1411
- function reviewState(input, revision) {
1412
- if (!input) return { pins: [], stale: false, ambiguous: false };
1413
- const pins = normalizedPins(input, revision);
1414
- const recordedRevision = optionalDigest(input.revision, "review revision");
1415
- return {
1416
- pins,
1417
- stale: input.current === false || recordedRevision !== void 0 && recordedRevision !== revision || pins.some((pin) => !pin.current),
1418
- ambiguous: input.ambiguous === true
1419
- };
1420
- }
1421
- function handoffState(handoff, designId, revision, selectedVariant) {
1422
- if (!handoff) return "blocked";
1423
- if (handoff.status !== "approved" || !handoff.approval || handoff.approval.contentHash !== handoff.contentHash)
1424
- return "blocked";
1425
- const basisRevision = optionalDigest(handoff.basis?.sourceRevision, "review handoff revision");
1426
- if (handoff.current === false || handoff.basis?.designId !== designId || basisRevision !== revision || handoff.basis?.selectedVariant !== selectedVariant)
1427
- return "stale";
1428
- return "pass";
1429
- }
1430
- function compileDesignHandoffReadiness(input) {
1431
- if (input === null || input === void 0) return designHandoffReadinessAbsence();
1432
- const source = plainClone(input);
1433
- const document = source.document;
1434
- if (!document || document.kind !== "openplanr-design-document" || !["1.0.0", "1.1.0"].includes(document.schemaVersion) || typeof document.id !== "string" || !document.id)
1435
- throw new TypeError("Readiness requires one supported design document.");
1436
- const revision = source.sourceRevision === null || source.sourceRevision === void 0 ? null : normalizeDigest(source.sourceRevision, "design revision");
1437
- const direction = selectedDirection(document, source.studioState);
1438
- const evidenceItems = [];
1439
- if (revision)
1440
- evidenceItems.push(
1441
- evidence(
1442
- "design-revision",
1443
- "design-revision",
1444
- logicalPath(source.documentPath, "design-document.json", "design document path"),
1445
- document,
1446
- { revision }
1447
- )
1448
- );
1449
- const directionEvidence = direction.selected && revision ? evidence(
1450
- "selected-direction",
1451
- "selected-direction",
1452
- logicalPath(source.studioStatePath, ".design/studio-state.json", "Studio state path"),
1453
- { selectedVariant: direction.selected },
1454
- { revision, anchor: { section: direction.selected } }
1455
- ) : null;
1456
- if (directionEvidence) evidenceItems.push(directionEvidence);
1457
- const specification = source.specification;
1458
- if (specification)
1459
- evidenceItems.push(
1460
- evidence(
1461
- "design-specification",
1462
- "design-specification",
1463
- logicalPath(specification.path, "design-spec.md", "design specification path"),
1464
- specification,
1465
- { revision: specification.revision }
1466
- )
1467
- );
1468
- const verification = source.verification;
1469
- if (verification)
1470
- evidenceItems.push(
1471
- evidence(
1472
- "rendered-verification",
1473
- "rendered-verification",
1474
- logicalPath(verification.path, ".design/verification/current.json", "verification path"),
1475
- verification,
1476
- { revision: verification.revision }
1477
- )
1478
- );
1479
- const review = reviewState(source.review, revision);
1480
- if (source.review)
1481
- evidenceItems.push(
1482
- evidence(
1483
- "review-feedback",
1484
- "review-feedback",
1485
- logicalPath(source.review.path, ".design/review.json", "review feedback path"),
1486
- source.review,
1487
- { revision: source.review.revision }
1488
- )
1489
- );
1490
- const handoff = source.reviewHandoff;
1491
- if (handoff)
1492
- evidenceItems.push(
1493
- evidence(
1494
- "review-handoff",
1495
- "review-handoff",
1496
- logicalPath(handoff.path, "review-handoff.json", "review handoff path"),
1497
- handoff,
1498
- { revision: handoff.basis?.sourceRevision }
1499
- )
1500
- );
1501
- const checks = [];
1502
- checks.push(
1503
- checked("current-revision", revision ? "pass" : "blocked", revision ? ["design-revision"] : [])
1504
- );
1505
- const handoffDirection = handoff?.basis?.selectedVariant;
1506
- const directionStatus = !direction.ready ? "blocked" : handoffDirection && handoffDirection !== direction.selected ? "stale" : "pass";
1507
- checks.push(
1508
- checked("selected-direction", directionStatus, directionEvidence ? ["selected-direction"] : [])
1509
- );
1510
- let specificationStatus = "blocked";
1511
- if (specification?.complete === true) {
1512
- const specificationRevision = optionalDigest(
1513
- specification.revision,
1514
- "design specification revision"
1515
- );
1516
- specificationStatus = revision && specificationRevision && specificationRevision !== revision ? "stale" : "pass";
1517
- }
1518
- checks.push(
1519
- checked(
1520
- "design-specification",
1521
- specificationStatus,
1522
- specification ? ["design-specification"] : []
1523
- )
1524
- );
1525
- let verificationStatus = "blocked";
1526
- if (verification) {
1527
- const verificationRevision = optionalDigest(
1528
- verification.revision,
1529
- "rendered verification revision"
1530
- );
1531
- if (revision && verificationRevision && verificationRevision !== revision)
1532
- verificationStatus = "stale";
1533
- else if (verification.status === "verified") verificationStatus = "pass";
1534
- }
1535
- checks.push(
1536
- checked(
1537
- "rendered-verification",
1538
- verificationStatus,
1539
- verification ? ["rendered-verification"] : []
1540
- )
1541
- );
1542
- const reviewRefs = source.review ? ["review-feedback"] : [];
1543
- const freshnessStatus = review.ambiguous ? "blocked" : review.stale ? "stale" : "pass";
1544
- checks.push(checked("review-freshness", freshnessStatus, reviewRefs));
1545
- const undecided = review.pins.filter(
1546
- (pin) => pin.current && !["accepted", "deferred", "rejected"].includes(pin.disposition)
1547
- );
1548
- const invalidDisposition = review.pins.some(
1549
- (pin) => pin.disposition && !["accepted", "deferred", "rejected"].includes(pin.disposition)
1550
- );
1551
- const dispositionStatus = invalidDisposition || review.ambiguous ? "blocked" : undecided.length ? "attention" : "pass";
1552
- checks.push(checked("review-dispositions", dispositionStatus, reviewRefs));
1553
- const openBlockers = review.pins.filter(
1554
- (pin) => pin.current && ["blocker", "change-request"].includes(pin.category) && !["accepted", "deferred", "rejected"].includes(pin.disposition)
1555
- );
1556
- const staleAccepted = review.pins.some((pin) => !pin.current && pin.disposition === "accepted");
1557
- const blockerStatus = staleAccepted ? "stale" : openBlockers.length ? "blocked" : "pass";
1558
- checks.push(checked("unresolved-blockers", blockerStatus, reviewRefs));
1559
- const approvalStatus = handoffState(handoff, document.id, revision, direction.selected);
1560
- checks.push(
1561
- checked("approved-review-handoff", approvalStatus, handoff ? ["review-handoff"] : [])
1562
- );
1563
- if (checks.map((item) => item.id).join("\n") !== CHECKS.join("\n"))
1564
- throw new TypeError("Readiness checks are not in canonical order.");
1565
- const worst = checks.reduce(
1566
- (current, item) => priority[item.status] > priority[current] ? item.status : current,
1567
- "pass"
1568
- );
1569
- const status = worst === "pass" ? "ready" : worst;
1570
- const blockers = checks.filter((item) => ["blocked", "stale"].includes(item.status)).map((item) => item.id);
1571
- const nextActions = checks.filter((item) => item.status !== "pass").map((item) => item.recoveryAction);
1572
- return assertDesignHandoffReadiness({
1573
- kind: "openplanr-design-handoff-readiness",
1574
- schemaVersion: "1.0.0",
1575
- scope: "design-originated",
1576
- authority: "none",
1577
- designId: document.id,
1578
- sourceRevision: revision,
1579
- selectedVariant: direction.selected,
1580
- status,
1581
- continuation: { action: "prepare-plan", available: ["ready", "attention"].includes(status) },
1582
- checks,
1583
- evidence: evidenceItems.sort((left, right) => left.id.localeCompare(right.id)),
1584
- blockers,
1585
- nextActions
1586
- });
1587
- }
1588
- function designHandoffReadinessAbsence(reason = "not-computed") {
1589
- return assertDesignHandoffReadiness({
1590
- kind: "openplanr-design-handoff-readiness-absence",
1591
- schemaVersion: "1.0.0",
1592
- status: "absent",
1593
- reason,
1594
- message: "No design handoff readiness has been prepared.",
1595
- nextAction: {
1596
- id: "inspect-design",
1597
- label: "Open the design when you want to prepare a handoff"
1598
- }
1599
- });
1600
- }
1601
- function designHandoffReadinessDigest(value) {
1602
- assertDesignHandoffReadiness(value);
1603
- return `sha256:${sha256Hex(canonicalizeJson(value))}`;
1604
- }
1605
-
1606
- // packages/design/lib/design/handoff-resolution.mjs
1607
- var OUTCOMES = /* @__PURE__ */ new Set(["accepted", "open", "blocking", "deferred", "declined"]);
1608
- var CATEGORIES = /* @__PURE__ */ new Set(["question", "suggestion", "change-request", "blocker"]);
1609
- var DISPOSITIONS = /* @__PURE__ */ new Set(["accepted", "deferred", "rejected", "declined"]);
1610
- var MAX_COMMENTS = 1e4;
1611
- var MAX_ISSUES = 1e4;
1612
- var digestPattern2 = /^[a-f0-9]{64}$/u;
1613
- var revisionOf = (pin) => pin.revisionId ?? pin.reviewId;
1614
- var keyOf = (pin) => `${revisionOf(pin)}:${pin.id}`;
1615
- var compare = (left, right) => left.localeCompare(right, "en");
1616
- var clone3 = (value) => {
1617
- assertPlainData(value, "Review resolution data");
1618
- return JSON.parse(canonicalizeJson(value));
1619
- };
1620
- function issue(code, severity, message2, { pinId, revisionId, recoveryAction } = {}) {
1621
- return {
1622
- code,
1623
- severity,
1624
- message: message2,
1625
- ...revisionId ? { revisionId } : {},
1626
- ...pinId ? { pinId } : {},
1627
- recoveryAction: recoveryAction ?? {
1628
- id: "refresh-review-resolution",
1629
- label: "Refresh review decisions"
1630
- }
1631
- };
1632
- }
1633
- function validatePin(pin) {
1634
- if (!pin || typeof pin !== "object" || Array.isArray(pin))
1635
- throw new TypeError("Every review comment must be an object.");
1636
- if (typeof pin.id !== "string" || !pin.id || pin.id.length > 160)
1637
- throw new TypeError("Every review comment requires a stable identity.");
1638
- const revisionId = revisionOf(pin);
1639
- if (typeof revisionId !== "string" || !revisionId || revisionId.length > 160)
1640
- throw new TypeError("Every review comment requires its original revision identity.");
1641
- if (typeof pin.reviewOf !== "string" || !digestPattern2.test(pin.reviewOf))
1642
- throw new TypeError("Every review comment requires its original review basis.");
1643
- if (pin.screenId !== void 0 && (typeof pin.screenId !== "string" || !pin.screenId))
1644
- throw new TypeError("Review screen references must be stable identities.");
1645
- if (pin.elementId !== void 0 && (typeof pin.elementId !== "string" || !pin.elementId || !pin.screenId))
1646
- throw new TypeError("Review element references require a stable screen identity.");
1647
- }
1648
- function scopedMetadata(metadata2, pin, duplicatePinIds, diagnostics) {
1649
- const revisionId = revisionOf(pin);
1650
- const scoped = metadata2.byRevision?.[revisionId] ?? {};
1651
- let category = scoped.categories?.[pin.id];
1652
- let disposition = scoped.dispositions?.[pin.id];
1653
- if (category === void 0 && Object.hasOwn(metadata2.categories ?? {}, pin.id)) {
1654
- if (duplicatePinIds.has(pin.id))
1655
- diagnostics.push(
1656
- issue(
1657
- "AMBIGUOUS_LEGACY_CATEGORY",
1658
- "blocked",
1659
- "A legacy category cannot be matched to one original revision.",
1660
- { pinId: pin.id, revisionId }
1661
- )
1662
- );
1663
- else category = metadata2.categories[pin.id];
1664
- }
1665
- if (disposition === void 0 && Object.hasOwn(metadata2.dispositions ?? {}, pin.id)) {
1666
- if (duplicatePinIds.has(pin.id))
1667
- diagnostics.push(
1668
- issue(
1669
- "AMBIGUOUS_LEGACY_DISPOSITION",
1670
- "blocked",
1671
- "A legacy owner decision cannot be matched to one original revision.",
1672
- { pinId: pin.id, revisionId }
1673
- )
1674
- );
1675
- else disposition = metadata2.dispositions[pin.id];
1676
- }
1677
- if (category !== void 0 && !CATEGORIES.has(category)) {
1678
- diagnostics.push(
1679
- issue("UNKNOWN_CATEGORY", "blocked", "The comment category is not supported.", {
1680
- pinId: pin.id,
1681
- revisionId
1682
- })
1683
- );
1684
- category = void 0;
1685
- }
1686
- const dispositionValue = typeof disposition === "string" ? disposition : disposition?.disposition;
1687
- if (dispositionValue !== void 0 && !DISPOSITIONS.has(dispositionValue)) {
1688
- diagnostics.push(
1689
- issue("UNKNOWN_DISPOSITION", "blocked", "The owner decision is not supported.", {
1690
- pinId: pin.id,
1691
- revisionId
1692
- })
1693
- );
1694
- disposition = void 0;
1695
- }
1696
- return {
1697
- category,
1698
- disposition,
1699
- dispositionValue: typeof disposition === "string" ? disposition : disposition?.disposition
1700
- };
1701
- }
1702
- function unknownMetadata(metadata2, known, diagnostics) {
1703
- for (const [revisionId, value] of Object.entries(metadata2.byRevision ?? {}).sort(
1704
- ([left], [right]) => compare(left, right)
1705
- )) {
1706
- for (const field of ["categories", "dispositions"]) {
1707
- for (const pinId of Object.keys(value?.[field] ?? {}).sort(compare)) {
1708
- if (!known.has(`${revisionId}:${pinId}`))
1709
- diagnostics.push(
1710
- issue(
1711
- "UNKNOWN_COMMENT_METADATA",
1712
- "blocked",
1713
- "Review metadata targets a comment that is not present in the recorded review history.",
1714
- { revisionId, pinId }
1715
- )
1716
- );
1717
- }
1718
- }
1719
- }
1720
- }
1721
- function compileDesignHandoffResolution(input) {
1722
- const source = clone3(input ?? {});
1723
- const pins = Array.isArray(source.pins) ? source.pins : [];
1724
- if (pins.length > MAX_COMMENTS)
1725
- throw new RangeError("Review resolution exceeds the comment limit.");
1726
- const metadata2 = source.metadata && typeof source.metadata === "object" && !Array.isArray(source.metadata) ? source.metadata : {};
1727
- const diagnostics = [];
1728
- const counts = /* @__PURE__ */ new Map();
1729
- for (const pin of pins) {
1730
- validatePin(pin);
1731
- counts.set(pin.id, (counts.get(pin.id) ?? 0) + 1);
1732
- }
1733
- const duplicatePinIds = new Set([...counts].filter(([, count]) => count > 1).map(([id2]) => id2));
1734
- const known = /* @__PURE__ */ new Set();
1735
- for (const pin of pins) {
1736
- const key = keyOf(pin);
1737
- if (known.has(key)) throw new TypeError(`Duplicate review comment identity: ${key}.`);
1738
- known.add(key);
1739
- }
1740
- unknownMetadata(metadata2, known, diagnostics);
1741
- const items = [...pins].sort((left, right) => compare(keyOf(left), keyOf(right))).map((pin) => {
1742
- const revisionId = revisionOf(pin);
1743
- const current = pin.stale !== true && (!source.currentReviewOf || pin.reviewOf === source.currentReviewOf);
1744
- const resolved = scopedMetadata(metadata2, pin, duplicatePinIds, diagnostics);
1745
- let outcome;
1746
- if (resolved.dispositionValue === "accepted") outcome = "accepted";
1747
- else if (resolved.dispositionValue === "deferred") outcome = "deferred";
1748
- else if (["rejected", "declined"].includes(resolved.dispositionValue)) outcome = "declined";
1749
- else if (["blocker", "change-request"].includes(resolved.category)) outcome = "blocking";
1750
- else outcome = "open";
1751
- if (!OUTCOMES.has(outcome)) throw new Error("Review resolution produced an invalid outcome.");
1752
- if (!current && outcome === "accepted")
1753
- diagnostics.push(
1754
- issue(
1755
- "STALE_ACCEPTED_DECISION",
1756
- "stale",
1757
- "An accepted change belongs to an earlier design revision and must be reviewed again.",
1758
- {
1759
- pinId: pin.id,
1760
- revisionId,
1761
- recoveryAction: {
1762
- id: "review-stale-decision",
1763
- label: "Review this decision against the current design"
1764
- }
1765
- }
1766
- )
1767
- );
1768
- if (current && outcome === "blocking")
1769
- diagnostics.push(
1770
- issue(
1771
- "UNRESOLVED_BLOCKING_COMMENT",
1772
- "blocked",
1773
- "A blocking comment still needs an owner decision.",
1774
- {
1775
- pinId: pin.id,
1776
- revisionId,
1777
- recoveryAction: {
1778
- id: "resolve-blocking-comment",
1779
- label: "Record the owner decision"
1780
- }
1781
- }
1782
- )
1783
- );
1784
- return {
1785
- id: keyOf(pin),
1786
- pinId: pin.id,
1787
- reviewId: pin.reviewId,
1788
- revisionId,
1789
- reviewOf: pin.reviewOf,
1790
- current,
1791
- category: resolved.category ?? "question",
1792
- outcome,
1793
- implementationScope: current && outcome === "accepted",
1794
- anchor: pin.elementId ? { screenId: pin.screenId, elementId: pin.elementId } : pin.screenId ? { screenId: pin.screenId } : pin.anchor?.planrId ? { planrId: pin.anchor.planrId } : { artifactId: pin.artifactId },
1795
- source: {
1796
- text: pin.comment,
1797
- author: clone3(pin.author),
1798
- status: pin.status,
1799
- ...resolved.disposition && typeof resolved.disposition === "object" ? { decision: clone3(resolved.disposition) } : {}
1800
- }
1801
- };
1802
- });
1803
- if (source.historyComplete === false)
1804
- diagnostics.push(
1805
- issue("INCOMPLETE_REVIEW_HISTORY", "blocked", "The complete review history is unavailable.", {
1806
- recoveryAction: {
1807
- id: "restore-review-history",
1808
- label: "Restore the complete review history"
1809
- }
1810
- })
1811
- );
1812
- if (source.synchronizationPending === true)
1813
- diagnostics.push(
1814
- issue(
1815
- "SYNCHRONIZATION_PENDING",
1816
- "blocked",
1817
- "A review decision is still waiting to synchronize.",
1818
- {
1819
- recoveryAction: {
1820
- id: "retry-review-sync",
1821
- label: "Retry review synchronization"
1822
- }
1823
- }
1824
- )
1825
- );
1826
- for (const value of (source.synchronizationIssues ?? []).slice(0, MAX_ISSUES))
1827
- diagnostics.push(
1828
- issue(
1829
- "UNTRUSTED_HOSTED_FEEDBACK",
1830
- "blocked",
1831
- value?.reason || "Hosted feedback could not be validated.",
1832
- {
1833
- pinId: value?.pinId,
1834
- revisionId: value?.revisionId,
1835
- recoveryAction: {
1836
- id: "inspect-review-sync",
1837
- label: "Inspect the rejected hosted feedback"
1838
- }
1839
- }
1840
- )
1841
- );
1842
- if ((source.synchronizationIssues ?? []).length > MAX_ISSUES)
1843
- throw new RangeError("Review resolution exceeds the synchronization issue limit.");
1844
- diagnostics.sort(
1845
- (left, right) => compare(
1846
- `${left.code}:${left.revisionId ?? ""}:${left.pinId ?? ""}:${left.message}`,
1847
- `${right.code}:${right.revisionId ?? ""}:${right.pinId ?? ""}:${right.message}`
1848
- )
1849
- );
1850
- const severity = new Set(diagnostics.map((value) => value.severity));
1851
- const status = severity.has("stale") ? "stale" : severity.has("blocked") ? "blocked" : items.some((item) => item.outcome === "open") ? "attention" : "ready";
1852
- return {
1853
- kind: "openplanr-design-handoff-resolution",
1854
- schemaVersion: "1.0.0",
1855
- currentReviewOf: source.currentReviewOf ?? null,
1856
- status,
1857
- complete: source.historyComplete !== false && !["blocked", "stale"].includes(status),
1858
- items,
1859
- implementationScope: items.filter((item) => item.implementationScope).map((item) => item.id),
1860
- diagnostics
1861
- };
1862
- }
1863
- function canApproveDesignHandoffResolution(value) {
1864
- return Boolean(value?.complete && ["ready", "attention"].includes(value.status));
1865
- }
1866
-
1867
- // packages/design/lib/design/handoff-reader.mjs
1868
- var sections = ["agreedChanges", "openQuestions", "deferred", "rejected"];
1869
- var metadataPath = (current) => join3(current.root, ".design/review-metadata.json");
1870
- var revisionOf2 = (pin) => pin.revisionId ?? pin.reviewId;
1871
- var pinKey = (pin) => `${revisionOf2(pin)}:${pin.id}`;
1872
- function metadata(current, feedback) {
1873
- const local = readJson(metadataPath(current), { version: 0, byRevision: {} });
1874
- const byRevision = structuredClone(feedback.shared?.metadataByRevision ?? {});
1875
- for (const [revision, value] of Object.entries(local.byRevision ?? {})) {
1876
- const remote = byRevision[revision] ?? {};
1877
- byRevision[revision] = {
1878
- categories: { ...remote.categories, ...value.categories },
1879
- dispositions: { ...remote.dispositions, ...value.dispositions }
1880
- };
1881
- }
1882
- const counts = /* @__PURE__ */ new Map();
1883
- for (const pin of feedback.pins) counts.set(pin.id, (counts.get(pin.id) ?? 0) + 1);
1884
- const categories = {}, dispositions = {};
1885
- for (const pin of feedback.pins) {
1886
- const value = byRevision[revisionOf2(pin)];
1887
- if (counts.get(pin.id) === 1 && value) {
1888
- if (Object.hasOwn(value.categories ?? {}, pin.id))
1889
- Object.defineProperty(categories, pin.id, {
1890
- value: value.categories[pin.id],
1891
- enumerable: true
1892
- });
1893
- if (Object.hasOwn(value.dispositions ?? {}, pin.id))
1894
- Object.defineProperty(dispositions, pin.id, {
1895
- value: value.dispositions[pin.id],
1896
- enumerable: true
1897
- });
1898
- }
1899
- if (counts.get(pin.id) === 1 && !Object.hasOwn(categories, pin.id) && Object.hasOwn(local.categories ?? {}, pin.id))
1900
- Object.defineProperty(categories, pin.id, {
1901
- value: local.categories[pin.id],
1902
- enumerable: true
1903
- });
1904
- if (counts.get(pin.id) === 1 && !Object.hasOwn(dispositions, pin.id) && Object.hasOwn(local.dispositions ?? {}, pin.id))
1905
- Object.defineProperty(dispositions, pin.id, {
1906
- value: local.dispositions[pin.id],
1907
- enumerable: true
1908
- });
1909
- }
1910
- return {
1911
- version: local.version,
1912
- categories,
1913
- dispositions,
1914
- byRevision,
1915
- legacy: {
1916
- categories: structuredClone(local.categories ?? {}),
1917
- dispositions: structuredClone(local.dispositions ?? {})
1918
- }
1919
- };
1920
- }
1921
- function findPin(pins, id2, revision) {
1922
- const candidates = pins.filter(
1923
- (pin) => pin.id === id2 && (!revision || revisionOf2(pin) === revision)
1924
- );
1925
- if (candidates.length !== 1)
1926
- throw new Error(
1927
- "The comment identity is missing or ambiguous. Include its original revisionId."
1928
- );
1929
- return candidates[0];
1930
- }
1931
- function resolutionFor(value, shareStatus) {
1932
- return compileDesignHandoffResolution({
1933
- currentReviewOf: value.basis.reviewOf,
1934
- pins: value.feedback.pins,
1935
- metadata: {
1936
- byRevision: value.metadata.byRevision,
1937
- categories: value.metadata.legacy.categories,
1938
- dispositions: value.metadata.legacy.dispositions
1939
- },
1940
- historyComplete: !value.feedback.shared?.issues?.length,
1941
- synchronizationPending: Boolean(shareStatus?.pendingReviewMetadata),
1942
- synchronizationIssues: value.feedback.shared?.issues ?? []
1943
- });
1944
- }
1945
- function snapshot(file, env, shareOptions = {}) {
1946
- const current = currentDesign(file, shareOptions), feedback = readDesignFeedback(file, env, shareOptions), meta = metadata(current, feedback);
1947
- const reviewContext = current.reviewContext ?? emptyReviewContext(current.document);
1948
- const basis = {
1949
- designId: current.document.id,
1950
- sourceRevision: current.revision,
1951
- contextDigest: current.contextDigest ?? reviewDigest(reviewContext),
1952
- reviewOf: digestArtifactEnvelope(current.envelope),
1953
- selectedVariant: feedback.state.selectedVariant ?? current.document.selectedVariant,
1954
- feedbackDigest: reviewDigest({
1955
- pins: feedback.pins,
1956
- metadata: {
1957
- byRevision: meta.byRevision,
1958
- categories: meta.categories,
1959
- dispositions: meta.dispositions
1960
- },
1961
- overall: (feedback.ledger?.reviews ?? []).map((entry) => ({
1962
- reviewId: entry.review.reviewId,
1963
- reviewOf: entry.review.reviewOf,
1964
- overall: entry.review.overall
1965
- })),
1966
- directions: feedback.shared?.directions ?? []
1967
- }),
1968
- verificationDigest: reviewDigest(current.verification),
1969
- feedbackWatermark: Math.max(
1970
- 0,
1971
- ...(feedback.shared?.events ?? []).map((event) => event.sequence ?? 0)
1972
- )
1973
- };
1974
- let shareStatus = null;
1975
- try {
1976
- shareStatus = getDesignShareStatus(file, { env, ...shareOptions });
1977
- } catch (error) {
1978
- if (error.code === "E_DESIGN_PUBLICATION_PENDING") throw error;
1979
- }
1980
- const value = { current, feedback, metadata: meta, reviewContext, basis };
1981
- return { ...value, resolution: resolutionFor(value, shareStatus), shareStatus };
1982
- }
1983
- function readDesignExperience(file, { env = process.env } = {}) {
1984
- const value = snapshot(file, env);
1985
- return {
1986
- ok: true,
1987
- capabilities: { owner: true, revisions: true, handoff: true },
1988
- revision: value.current.revision,
1989
- reviewContext: value.reviewContext,
1990
- contextDigest: value.basis.contextDigest,
1991
- fingerprints: value.current.fingerprints ?? [],
1992
- metadata: value.metadata,
1993
- loadingHistory: false
1994
- };
1995
- }
1996
- function readDesignHandoff(file, { env = process.env, ...shareOptions } = {}) {
1997
- const value = snapshot(file, env, shareOptions);
1998
- const path = join3(dirname3(designSpecPath(value.current.root)), "review-handoff.json");
1999
- const draft = readJson(path, null);
2000
- if (draft) {
2001
- assertDraft(draft);
2002
- const markdownPath = path.replace(/\.json$/u, ".md");
2003
- if (!existsSync3(markdownPath) || readFileSync3(markdownPath, "utf8") !== draft.markdown)
2004
- throw new Error(
2005
- "The handoff Markdown differs from its approved JSON. Rebuild the handoff projection before using it in Plan."
2006
- );
2007
- }
2008
- return {
2009
- ok: true,
2010
- path,
2011
- revision: value.current.revision,
2012
- draft,
2013
- current: Boolean(draft && reviewDigest(draft.basis) === reviewDigest(value.basis)),
2014
- metadata: value.metadata,
2015
- feedback: { pins: value.feedback.pins },
2016
- basis: value.basis,
2017
- resolution: value.resolution
2018
- };
2019
- }
2020
- function readDesignHandoffReadiness(file, { env = process.env, ...shareOptions } = {}) {
2021
- const value = snapshot(file, env, shareOptions);
2022
- const path = join3(dirname3(designSpecPath(value.current.root)), "review-handoff.json");
2023
- const handoff = readJson(path, null);
2024
- if (handoff) assertDraft(handoff);
2025
- const outcomes = new Map(value.resolution.items.map((item) => [item.id, item]));
2026
- const pins = value.feedback.pins.map((pin) => {
2027
- const resolved = outcomes.get(pinKey(pin));
2028
- const disposition = resolved?.outcome === "accepted" ? "accepted" : resolved?.outcome === "deferred" ? "deferred" : resolved?.outcome === "declined" ? "rejected" : void 0;
2029
- return {
2030
- id: pin.id,
2031
- ...pin.screenId ? { screenId: pin.screenId } : {},
2032
- ...pin.anchor?.planrId ? { elementId: pin.anchor.planrId } : {},
2033
- category: resolved?.category,
2034
- ...disposition ? { disposition } : {},
2035
- stale: Boolean(pin.stale)
2036
- };
2037
- });
2038
- const specificationPath = designSpecPath(value.current.root);
2039
- const specification = existsSync3(specificationPath) ? {
2040
- path: "design-spec.md",
2041
- revision: value.current.revision,
2042
- digest: `sha256:${hash(readFileSync3(specificationPath))}`,
2043
- complete: true
2044
- } : void 0;
2045
- const studioState = readJson(join3(value.current.root, ".design/studio-state.json"), {
2046
- state: {}
2047
- }).state;
2048
- const readiness = compileDesignHandoffReadiness({
2049
- document: value.current.document,
2050
- documentPath: "design-document.json",
2051
- sourceRevision: value.current.revision,
2052
- studioState,
2053
- studioStatePath: ".design/studio-state.json",
2054
- specification,
2055
- verification: { path: ".design/verification/current.json", ...value.current.verification },
2056
- review: {
2057
- path: ".design/review.json",
2058
- revision: value.current.revision,
2059
- current: pins.every((pin) => !pin.stale),
2060
- pins
2061
- },
2062
- reviewHandoff: handoff ? {
2063
- ...handoff,
2064
- path: "review-handoff.json",
2065
- digest: `sha256:${handoff.contentHash}`,
2066
- current: reviewDigest(handoff.basis) === reviewDigest(value.basis)
2067
- } : void 0
2068
- });
2069
- return { ok: true, readiness, digest: designHandoffReadinessDigest(readiness) };
2070
- }
2071
- function assertDraft(draft) {
2072
- assertReviewExperience(draft, DESIGN_HANDOFF_SCHEMA);
2073
- const expected = reviewDigest({
2074
- title: draft.title,
2075
- reviewNotes: draft.reviewNotes,
2076
- basis: draft.basis,
2077
- content: draft.content,
2078
- affectedScreens: draft.affectedScreens ?? [],
2079
- verificationGaps: draft.verificationGaps ?? []
2080
- });
2081
- if (draft.contentHash !== expected || draft.status === "approved" && draft.approval?.contentHash !== expected)
2082
- throw new Error(
2083
- "The handoff content does not match its approval digest. Refine it through the handoff utility."
2084
- );
2085
- if (draft.markdown !== renderMarkdown(draft, draft.title))
2086
- throw new Error("The handoff Markdown does not match its approved content.");
2087
- return draft;
2088
- }
2089
-
2090
- // packages/design/lib/design/handoff.mjs
2091
- import { existsSync as existsSync4, writeFileSync as writeFileSync3 } from "node:fs";
2092
- import { dirname as dirname4, join as join4 } from "node:path";
2093
- var conflict2 = (message2) => Object.assign(new Error(message2), { statusCode: 409 });
2094
- function sourceItem(pin, shareUrl) {
2095
- const source = pin.revisionId ? `${shareUrl ?? ""}#revision=${encodeURIComponent(pin.revisionId)}&pin=${encodeURIComponent(pin.id)}` : `#review=${encodeURIComponent(pin.reviewId)}&pin=${encodeURIComponent(pin.id)}`;
2096
- return {
2097
- pinId: pin.id,
2098
- ...pin.screenId ? { screenId: pin.screenId } : {},
2099
- reviewId: pin.reviewId,
2100
- ...pin.revisionId ? { revisionId: pin.revisionId } : {},
2101
- text: pin.comment,
2102
- author: pin.author.name,
2103
- reviewOf: pin.reviewOf,
2104
- stale: Boolean(pin.stale),
2105
- source
2106
- };
2107
- }
2108
- function contentFromFeedback(value, shareUrl) {
2109
- const content = { summary: "", agreedChanges: [], openQuestions: [], deferred: [], rejected: [] };
2110
- const pins = new Map(value.feedback.pins.map((pin) => [pinKey(pin), pin]));
2111
- for (const resolved of value.resolution.items) {
2112
- const pin = pins.get(resolved.id);
2113
- const item = sourceItem(pin, shareUrl);
2114
- if (resolved.outcome === "accepted") content.agreedChanges.push(item);
2115
- else if (resolved.outcome === "deferred") content.deferred.push(item);
2116
- else if (resolved.outcome === "declined") content.rejected.push(item);
2117
- else content.openQuestions.push(item);
2118
- }
2119
- return content;
2120
- }
2121
- function enrichContent(content, value, shareUrl) {
2122
- assertReviewExperience(content, DESIGN_HANDOFF_CONTENT_SCHEMA);
2123
- const seen = /* @__PURE__ */ new Set();
2124
- const enriched = { summary: content.summary };
2125
- for (const key of sections)
2126
- enriched[key] = content[key].map((item) => {
2127
- const pin = findPin(value.feedback.pins, item.pinId, item.revisionId ?? item.reviewId);
2128
- if (seen.has(pinKey(pin)))
2129
- throw new Error("Handoff items must cite distinct recorded comments.");
2130
- seen.add(pinKey(pin));
2131
- const resolved = value.resolution.items.find((itemValue) => itemValue.id === pinKey(pin));
2132
- const expected = key === "agreedChanges" ? ["accepted"] : key === "deferred" ? ["deferred"] : key === "rejected" ? ["declined"] : ["open", "blocking"];
2133
- if (!resolved || !expected.includes(resolved.outcome))
2134
- throw new Error(
2135
- "Record the owner disposition before moving a comment into this handoff section."
2136
- );
2137
- const refinement = item.refinement ?? (item.text !== pin.comment ? item.text : void 0);
2138
- return { ...sourceItem(pin, shareUrl), ...refinement !== void 0 ? { refinement } : {} };
2139
- });
2140
- for (const pin of value.feedback.pins)
2141
- if (!seen.has(pinKey(pin)))
2142
- throw new Error(
2143
- `Keep every recorded review comment in the handoff; ${pinKey(pin)} is missing.`
2144
- );
2145
- return enriched;
2146
- }
2147
- function normalizedLocalMetadata(local, pins) {
2148
- const byRevision = structuredClone(local.byRevision ?? {});
2149
- const counts = /* @__PURE__ */ new Map();
2150
- for (const pin of pins) counts.set(pin.id, (counts.get(pin.id) ?? 0) + 1);
2151
- for (const field of ["categories", "dispositions"]) {
2152
- for (const [pinId, item] of Object.entries(local[field] ?? {})) {
2153
- if (counts.get(pinId) !== 1) continue;
2154
- const pin = pins.find((value) => value.id === pinId);
2155
- const revision = revisionOf2(pin);
2156
- const scoped = byRevision[revision] ?? { categories: {}, dispositions: {} };
2157
- byRevision[revision] = { ...scoped, [field]: { ...scoped[field], [pinId]: item } };
2158
- }
2159
- }
2160
- return { version: local.version ?? 0, byRevision };
2161
- }
2162
- async function preserveReviewErrors(path, action3) {
2163
- let failure, result;
2164
- await withArtifactReviewLock(path, async () => {
2165
- try {
2166
- result = await action3();
2167
- } catch (error) {
2168
- failure = error;
2169
- }
2170
- });
2171
- if (failure) throw failure;
2172
- return result;
2173
- }
2174
- async function updateDesignHandoff(file, input, { env = process.env, ...shareOptions } = {}) {
2175
- if (!input || !["draft", "update", "approve", "category", "disposition"].includes(input.action))
2176
- throw new Error("Unknown design handoff action.");
2177
- const initial = currentDesign(file);
2178
- const unlockRender = await acquireStartLock(join4(initial.root, ".design/render.lock"));
2179
- let outgoing;
2180
- try {
2181
- const unlock = await acquireStartLock(join4(initial.root, ".design/handoff.lock"));
2182
- try {
2183
- await preserveReviewErrors(designReviewPath(file, env), async () => {
2184
- const value = snapshot(file, env, shareOptions);
2185
- if (input.revision !== value.current.revision)
2186
- throw conflict2("The design changed. Refresh the review before updating its handoff.");
2187
- if (["category", "disposition"].includes(input.action)) {
2188
- if (input.version !== value.metadata.version)
2189
- throw conflict2("Review organization changed in another window. Reload before saving.");
2190
- const pin = findPin(value.feedback.pins, input.pinId, input.revisionId ?? input.reviewId);
2191
- if (!pin) throw new Error("The comment is no longer available.");
2192
- const choices = input.action === "category" ? ["question", "suggestion", "change-request", "blocker"] : ["accepted", "deferred", "rejected"];
2193
- if (!choices.includes(input[input.action])) throw new Error(`Invalid ${input.action}.`);
2194
- if (typeof (input.reason ?? "") !== "string" || (input.reason ?? "").length > 16384)
2195
- throw new Error("Disposition reason is too long.");
2196
- if (pin.revisionId) assertDesignShareAvailable({ env, ...shareOptions });
2197
- const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
2198
- const local = normalizedLocalMetadata(
2199
- readJson(metadataPath(value.current), { version: 0, byRevision: {} }),
2200
- value.feedback.pins
2201
- );
2202
- const revision = revisionOf2(pin);
2203
- const scoped = local.byRevision?.[revision] ?? { categories: {}, dispositions: {} };
2204
- const valueForRevision = { ...scoped };
2205
- if (input.action === "category")
2206
- valueForRevision.categories = { ...scoped.categories, [pin.id]: input.category };
2207
- else
2208
- valueForRevision.dispositions = {
2209
- ...scoped.dispositions,
2210
- [pin.id]: {
2211
- disposition: input.disposition,
2212
- reason: input.reason ?? "",
2213
- updatedAt,
2214
- author: "Design owner"
2215
- }
2216
- };
2217
- const next = {
2218
- version: value.metadata.version + 1,
2219
- byRevision: { ...local.byRevision, [revision]: valueForRevision }
2220
- };
2221
- atomicJson(metadataPath(value.current), next);
2222
- if (pin.revisionId)
2223
- outgoing = {
2224
- revisionId: pin.revisionId,
2225
- payload: {
2226
- schemaVersion: input.category === "change-request" ? "1.1.0" : "1.0.0",
2227
- kind: input.action,
2228
- author: "Design owner",
2229
- reviewOf: pin.reviewOf,
2230
- pinId: pin.id,
2231
- [input.action]: input[input.action],
2232
- ...input.action === "disposition" ? { reason: input.reason ?? "" } : {},
2233
- updatedAt
2234
- }
2235
- };
2236
- return;
2237
- }
2238
- const path = join4(dirname4(designSpecPath(value.current.root)), "review-handoff.json");
2239
- const previous = readJson(path, null);
2240
- if (previous) assertDraft(previous);
2241
- if (input.version !== (previous?.version ?? 0))
2242
- throw conflict2("The handoff changed in another window. Reload before saving.");
2243
- let shareUrl;
2244
- try {
2245
- shareUrl = getDesignShareStatus(file, { env, ...shareOptions }).url;
2246
- } catch {
2247
- }
2248
- if (input.action === "approve") {
2249
- if (!previous || input.contentHash !== previous.contentHash || reviewDigest(previous.basis) !== reviewDigest(value.basis))
2250
- throw conflict2(
2251
- "The handoff is out of date. Rebuild and review the current draft before approving."
2252
- );
2253
- if (!canApproveDesignHandoffResolution(value.resolution)) {
2254
- const diagnostic = value.resolution.diagnostics[0];
2255
- throw conflict2(
2256
- diagnostic?.message ?? "Resolve the blocking review decisions before approving this handoff."
2257
- );
2258
- }
2259
- if (!previous.content.summary.trim())
2260
- throw new Error("Write or refine the handoff summary before approving it.");
2261
- const approved = {
2262
- ...previous,
2263
- version: previous.version + 1,
2264
- status: "approved",
2265
- approval: { contentHash: previous.contentHash, at: (/* @__PURE__ */ new Date()).toISOString() }
2266
- };
2267
- approved.markdown = renderMarkdown(approved, value.current.document.title);
2268
- assertReviewExperience(approved, DESIGN_HANDOFF_SCHEMA);
2269
- const archive = join4(
2270
- value.current.root,
2271
- ".design/handoff-approvals",
2272
- `${approved.contentHash}.json`
2273
- );
2274
- if (!existsSync4(archive)) atomicJson(archive, approved);
2275
- atomicJson(path, approved);
2276
- writeFileSync3(path.replace(/\.json$/u, ".md"), approved.markdown);
2277
- return;
2278
- }
2279
- const content = input.action === "draft" ? contentFromFeedback(value, shareUrl) : enrichContent(input.content, value, shareUrl);
2280
- if (input.action === "update" && (!previous || reviewDigest(previous.basis) !== reviewDigest(value.basis)))
2281
- throw conflict2("The review changed. Rebuild the draft before refining it.");
2282
- const affectedScreens = [
2283
- ...new Set(
2284
- sections.flatMap((key) => content[key].map((item) => item.screenId).filter(Boolean))
2285
- )
2286
- ];
2287
- const verificationGaps = value.current.verification.status === "verified" ? [] : [`Rendered design verification: ${value.current.verification.status}.`];
2288
- for (const issue2 of value.current.verification.issues ?? [])
2289
- if (issue2.message && verificationGaps.length < 256) verificationGaps.push(issue2.message);
2290
- const reviewNotes = (value.feedback.ledger?.reviews ?? []).filter((entry) => entry.review.overall?.trim()).map((entry) => ({ reviewId: entry.review.reviewId, text: entry.review.overall }));
2291
- const title2 = value.current.document.title;
2292
- const draft = {
2293
- title: title2,
2294
- reviewNotes,
2295
- kind: "openplanr-design-review-handoff",
2296
- schemaVersion: "1.0.0",
2297
- version: (previous?.version ?? 0) + 1,
2298
- status: "draft",
2299
- basis: value.basis,
2300
- content,
2301
- affectedScreens,
2302
- verificationGaps,
2303
- contentHash: reviewDigest({
2304
- title: title2,
2305
- reviewNotes,
2306
- basis: value.basis,
2307
- content,
2308
- affectedScreens,
2309
- verificationGaps
2310
- }),
2311
- markdown: ""
2312
- };
2313
- draft.markdown = renderMarkdown(draft, value.current.document.title);
2314
- assertReviewExperience(draft, DESIGN_HANDOFF_SCHEMA);
2315
- atomicJson(path, draft);
2316
- writeFileSync3(path.replace(/\.json$/u, ".md"), draft.markdown);
2317
- });
2318
- } finally {
2319
- unlock();
2320
- }
2321
- } finally {
2322
- unlockRender();
2323
- }
2324
- let synchronization;
2325
- if (outgoing) {
2326
- try {
2327
- synchronization = await publishDesignReviewMetadata(file, outgoing.payload, {
2328
- revisionId: outgoing.revisionId,
2329
- env,
2330
- ...shareOptions
2331
- });
2332
- } catch (error) {
2333
- synchronization = {
2334
- pending: false,
2335
- error: error.message,
2336
- ...error.code ? { code: error.code } : {}
2337
- };
2338
- }
2339
- }
2340
- return {
2341
- ...readDesignHandoff(file, { env, ...shareOptions }),
2342
- ...synchronization ? { synchronization } : {}
2343
- };
2344
- }
2345
-
2346
- export {
2347
- PLANNING_FOLDER,
2348
- CLI_COMMAND,
2349
- createReviewLedger,
2350
- mergeReviewLedger,
2351
- effectiveReviewDecision,
2352
- ARTIFACT_REVIEW_MAX_STATE_BYTES,
2353
- normalizeArtifactReview,
2354
- readArtifactReviewState,
2355
- writeArtifactReviewState,
2356
- withArtifactReviewLock,
2357
- exportArtifactReview,
2358
- resolveArtifactReviewDestination,
2359
- decodeArtifactReviewSources,
2360
- designReviewKey,
2361
- designReviewPath,
2362
- readDesignFeedback,
2363
- isDesignHandoffRelativePath,
2364
- designImplementationHandoffDigest,
2365
- assertDesignImplementationHandoff,
2366
- readDesignExperience,
2367
- readDesignHandoff,
2368
- readDesignHandoffReadiness,
2369
- updateDesignHandoff
2370
- };