opendevbrowser 0.0.31 → 0.0.33

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 (336) hide show
  1. package/README.md +18 -5
  2. package/dist/{accessibility-snapshot-CQ4ZKWKC.js → accessibility-snapshot-JSPFVWZ6.js} +12 -12
  3. package/dist/{active-window-TD5HYJ72.js → active-window-2OB2MSCR.js} +12 -12
  4. package/dist/{annotate-VTLFS2XV.js → annotate-VDZBZBKZ.js} +11 -11
  5. package/dist/{artifacts-KJ6RNDO2.js → artifacts-JHDUUJGQ.js} +2 -2
  6. package/dist/{attr-BCI5KYCW.js → attr-7XIO4MCH.js} +11 -11
  7. package/dist/browser/canvas-manager.d.ts.map +1 -1
  8. package/dist/canvas/guidance.d.ts +7 -0
  9. package/dist/canvas/guidance.d.ts.map +1 -1
  10. package/dist/canvas/repair-examples.d.ts +45 -0
  11. package/dist/canvas/repair-examples.d.ts.map +1 -0
  12. package/dist/{canvas-5DFEEOKM.js → canvas-N4PAA274.js} +26 -11
  13. package/dist/canvas-N4PAA274.js.map +1 -0
  14. package/dist/{capture-desktop-HFTTWY4Z.js → capture-desktop-T5YO3EBI.js} +12 -12
  15. package/dist/{capture-window-X63XPIFF.js → capture-window-UKEUBWKH.js} +12 -12
  16. package/dist/{check-LWAUY7GC.js → check-PQB6KKMN.js} +11 -11
  17. package/dist/{checked-ZSOUKVYT.js → checked-RNZIMCU6.js} +11 -11
  18. package/dist/{chunk-6B5WAQV7.js → chunk-27W46IKI.js} +42 -11
  19. package/dist/chunk-27W46IKI.js.map +1 -0
  20. package/dist/{chunk-WHQZBUNY.js → chunk-3WLCWHIV.js} +2 -2
  21. package/dist/{chunk-WHQZBUNY.js.map → chunk-3WLCWHIV.js.map} +1 -1
  22. package/dist/{chunk-PPUWQKIC.js → chunk-52ZIOWVU.js} +4 -4
  23. package/dist/{chunk-IPE7TF2P.js → chunk-7BNU6DFI.js} +8 -5
  24. package/dist/chunk-7BNU6DFI.js.map +1 -0
  25. package/dist/{chunk-3ILXPKSJ.js → chunk-BUVYTJZR.js} +2 -1
  26. package/dist/chunk-BUVYTJZR.js.map +1 -0
  27. package/dist/{chunk-QOMWCRE3.js → chunk-EOX6U6Q4.js} +47 -19
  28. package/dist/chunk-EOX6U6Q4.js.map +1 -0
  29. package/dist/{chunk-4BEJVZRK.js → chunk-FBKPDILE.js} +3625 -289
  30. package/dist/chunk-FBKPDILE.js.map +1 -0
  31. package/dist/{chunk-2I3YS3DV.js → chunk-FDBUB7BM.js} +7 -3
  32. package/dist/chunk-FDBUB7BM.js.map +1 -0
  33. package/dist/{chunk-COAOWH3G.js → chunk-HMRANSDX.js} +120 -28
  34. package/dist/chunk-HMRANSDX.js.map +1 -0
  35. package/dist/{chunk-KZ2IXVQT.js → chunk-IBIHDGTZ.js} +40 -5
  36. package/dist/chunk-IBIHDGTZ.js.map +1 -0
  37. package/dist/{chunk-T4GMCW6Z.js → chunk-J3KYGJRQ.js} +3 -3
  38. package/dist/{chunk-AHEWXOKY.js → chunk-JROW6ZNN.js} +4 -4
  39. package/dist/{chunk-6PVZ2ABC.js → chunk-L3YNUGYF.js} +2 -2
  40. package/dist/{chunk-MD655IPO.js → chunk-MJF67OTH.js} +11 -4
  41. package/dist/chunk-MJF67OTH.js.map +1 -0
  42. package/dist/{chunk-JZXD6FWR.js → chunk-NURQB55J.js} +2 -2
  43. package/dist/{chunk-STGGGVYT.js → chunk-QMHKAFYX.js} +2 -2
  44. package/dist/{chunk-RPXWUCQQ.js → chunk-SKFB5ICF.js} +2 -2
  45. package/dist/{chunk-2SIMIPLY.js → chunk-W6YPVNDX.js} +3 -3
  46. package/dist/{chunk-GQJ5S3BL.js → chunk-YRRRUGSQ.js} +3 -3
  47. package/dist/{chunk-37VSRUW4.js → chunk-ZGCTC5YM.js} +39 -7
  48. package/dist/chunk-ZGCTC5YM.js.map +1 -0
  49. package/dist/{chunk-KDSNXS6N.js → chunk-ZMNEWS7A.js} +2 -2
  50. package/dist/cli/args.d.ts.map +1 -1
  51. package/dist/cli/commands/canvas.d.ts +12 -0
  52. package/dist/cli/commands/canvas.d.ts.map +1 -1
  53. package/dist/cli/commands/daemon.d.ts +19 -2
  54. package/dist/cli/commands/daemon.d.ts.map +1 -1
  55. package/dist/cli/commands/inspiredesign.d.ts +6 -1
  56. package/dist/cli/commands/inspiredesign.d.ts.map +1 -1
  57. package/dist/cli/commands/serve.d.ts +12 -3
  58. package/dist/cli/commands/serve.d.ts.map +1 -1
  59. package/dist/cli/commands/status.d.ts.map +1 -1
  60. package/dist/cli/commands/types.d.ts +1 -0
  61. package/dist/cli/commands/types.d.ts.map +1 -1
  62. package/dist/cli/daemon-client.d.ts.map +1 -1
  63. package/dist/cli/daemon-commands.d.ts.map +1 -1
  64. package/dist/cli/daemon-mismatch.d.ts +15 -0
  65. package/dist/cli/daemon-mismatch.d.ts.map +1 -0
  66. package/dist/cli/daemon.d.ts.map +1 -1
  67. package/dist/cli/errors.d.ts +4 -2
  68. package/dist/cli/errors.d.ts.map +1 -1
  69. package/dist/cli/help.d.ts.map +1 -1
  70. package/dist/cli/index.js +91 -90
  71. package/dist/cli/index.js.map +1 -1
  72. package/dist/cli/installers/postinstall-skill-sync.js +2 -2
  73. package/dist/cli/utils/workflow-message.d.ts +1 -1
  74. package/dist/cli/utils/workflow-message.d.ts.map +1 -1
  75. package/dist/{click-2AILSEIZ.js → click-U7ZFKSB4.js} +11 -11
  76. package/dist/{clone-component-TPJS3PEG.js → clone-component-SWYAORTU.js} +10 -10
  77. package/dist/{clone-page-LE74CIFC.js → clone-page-WJ6UJOJG.js} +10 -10
  78. package/dist/{close-HN4YI47K.js → close-NAVIHZ2T.js} +10 -10
  79. package/dist/{close-WFERRHX6.js → close-VKIGIKVT.js} +10 -10
  80. package/dist/{connect-RWBV2UCQ.js → connect-XVG2MOZL.js} +11 -11
  81. package/dist/{console-poll-PP4YYPDF.js → console-poll-XI5BZPL7.js} +11 -11
  82. package/dist/{cookie-import-6IP776FC.js → cookie-import-QELKE7TK.js} +10 -10
  83. package/dist/{cookie-list-O2KG6DPU.js → cookie-list-QDA6KWIY.js} +10 -10
  84. package/dist/{daemon-2BSAZXLT.js → daemon-CA4UIIZQ.js} +26 -13
  85. package/dist/daemon-CA4UIIZQ.js.map +1 -0
  86. package/dist/daemon-fingerprint.json +1 -1
  87. package/dist/{debug-trace-snapshot-F3BDVZXS.js → debug-trace-snapshot-AT4GAO57.js} +11 -11
  88. package/dist/{dialog-6JQYUWMQ.js → dialog-O3V2IBFH.js} +11 -11
  89. package/dist/{disconnect-763TP7GH.js → disconnect-NAX5TPTG.js} +10 -10
  90. package/dist/{enabled-DLYQFNIP.js → enabled-VT4FJXDX.js} +11 -11
  91. package/dist/{goto-S346TJJH.js → goto-GBJG5NC4.js} +11 -11
  92. package/dist/guidance/context.d.ts +44 -0
  93. package/dist/guidance/context.d.ts.map +1 -0
  94. package/dist/guidance/index.d.ts +7 -0
  95. package/dist/guidance/index.d.ts.map +1 -0
  96. package/dist/guidance/readiness.d.ts +7 -0
  97. package/dist/guidance/readiness.d.ts.map +1 -0
  98. package/dist/guidance/recipes/generic.d.ts +3 -0
  99. package/dist/guidance/recipes/generic.d.ts.map +1 -0
  100. package/dist/guidance/recipes/pinterest.d.ts +5 -0
  101. package/dist/guidance/recipes/pinterest.d.ts.map +1 -0
  102. package/dist/guidance/recipes/site-recipe-types.d.ts +2 -0
  103. package/dist/guidance/recipes/site-recipe-types.d.ts.map +1 -0
  104. package/dist/guidance/recipes/site-registry.d.ts +5 -0
  105. package/dist/guidance/recipes/site-registry.d.ts.map +1 -0
  106. package/dist/guidance/renderers.d.ts +22 -0
  107. package/dist/guidance/renderers.d.ts.map +1 -0
  108. package/dist/guidance/router.d.ts +8 -0
  109. package/dist/guidance/router.d.ts.map +1 -0
  110. package/dist/guidance/types.d.ts +139 -0
  111. package/dist/guidance/types.d.ts.map +1 -0
  112. package/dist/{help-U7KBQME6.js → help-SUI4H77K.js} +14 -9
  113. package/dist/help-SUI4H77K.js.map +1 -0
  114. package/dist/{hover-6JVJFGO7.js → hover-476ZNQZE.js} +11 -11
  115. package/dist/{html-EVOSPBIT.js → html-5C4TXOV3.js} +11 -11
  116. package/dist/index.d.ts.map +1 -1
  117. package/dist/index.js +47 -18
  118. package/dist/index.js.map +1 -1
  119. package/dist/{inspector-H57BVUJP.js → inspector-73ARPCIV.js} +13 -13
  120. package/dist/{inspector-audit-NQBAJWC7.js → inspector-audit-QT6QY7KS.js} +15 -15
  121. package/dist/{inspector-plan-ZDIQVND3.js → inspector-plan-JRNSGN2Z.js} +13 -13
  122. package/dist/inspiredesign/capture.d.ts +4 -0
  123. package/dist/inspiredesign/capture.d.ts.map +1 -1
  124. package/dist/inspiredesign/contract.d.ts +24 -0
  125. package/dist/inspiredesign/contract.d.ts.map +1 -1
  126. package/dist/inspiredesign/handoff.d.ts +9 -3
  127. package/dist/inspiredesign/handoff.d.ts.map +1 -1
  128. package/dist/inspiredesign/meta-prompt.d.ts +9 -0
  129. package/dist/inspiredesign/meta-prompt.d.ts.map +1 -0
  130. package/dist/inspiredesign/reference-discovery.d.ts +29 -0
  131. package/dist/inspiredesign/reference-discovery.d.ts.map +1 -0
  132. package/dist/inspiredesign/reference-pattern-board.d.ts +38 -1
  133. package/dist/inspiredesign/reference-pattern-board.d.ts.map +1 -1
  134. package/dist/inspiredesign/visual-evidence.d.ts +46 -0
  135. package/dist/inspiredesign/visual-evidence.d.ts.map +1 -0
  136. package/dist/inspiredesign/visual-policy.d.ts +17 -0
  137. package/dist/inspiredesign/visual-policy.d.ts.map +1 -0
  138. package/dist/{inspiredesign-IEUL4PX3.js → inspiredesign-IPVZDLSQ.js} +73 -21
  139. package/dist/inspiredesign-IPVZDLSQ.js.map +1 -0
  140. package/dist/{launch-EK66VQPF.js → launch-B35YDRQC.js} +11 -11
  141. package/dist/{list-ADZAQ2IU.js → list-JV55JVGB.js} +10 -10
  142. package/dist/{list-KKUKN467.js → list-YETWKTKY.js} +10 -10
  143. package/dist/{macro-resolve-6DOQJ7CA.js → macro-resolve-DQK4B3W3.js} +12 -12
  144. package/dist/{native-UPLVQ2SG.js → native-J2DFLOLP.js} +3 -3
  145. package/dist/{network-poll-NUL4PDPY.js → network-poll-4GWHCJXI.js} +11 -11
  146. package/dist/{new-5NKYPEFT.js → new-XDCQPIEG.js} +10 -10
  147. package/dist/{open-NR3BPLXV.js → open-GIM3ZCSV.js} +10 -10
  148. package/dist/opendevbrowser.d.ts.map +1 -1
  149. package/dist/opendevbrowser.js +47 -18
  150. package/dist/opendevbrowser.js.map +1 -1
  151. package/dist/{perf-HJ36ZI6H.js → perf-26VBXDPI.js} +11 -11
  152. package/dist/{pointer-down-IYTTQWXZ.js → pointer-down-O3VSNAXW.js} +12 -12
  153. package/dist/{pointer-drag-A2YC5PWI.js → pointer-drag-WQ5QGE6J.js} +12 -12
  154. package/dist/{pointer-move-W5K5FUI4.js → pointer-move-4N4D7JY2.js} +12 -12
  155. package/dist/{pointer-up-6GWVO64Y.js → pointer-up-CQC4NPDX.js} +12 -12
  156. package/dist/{press-A3V5WB3S.js → press-XGJD45CU.js} +11 -11
  157. package/dist/{product-video-52REKWF3.js → product-video-HD4ZOUI7.js} +13 -13
  158. package/dist/providers/browser-native-discovery.d.ts +23 -0
  159. package/dist/providers/browser-native-discovery.d.ts.map +1 -0
  160. package/dist/providers/renderer.d.ts +9 -1
  161. package/dist/providers/renderer.d.ts.map +1 -1
  162. package/dist/providers/workflow-handoff.d.ts +4 -0
  163. package/dist/providers/workflow-handoff.d.ts.map +1 -1
  164. package/dist/providers/workflows.d.ts +45 -3
  165. package/dist/providers/workflows.d.ts.map +1 -1
  166. package/dist/{providers-IMFYMMHQ.js → providers-KKNPJSQK.js} +4 -4
  167. package/dist/public-surface/generated-manifest.d.ts +14 -5
  168. package/dist/public-surface/generated-manifest.d.ts.map +1 -1
  169. package/dist/public-surface/source.d.ts +7 -7
  170. package/dist/public-surface/source.d.ts.map +1 -1
  171. package/dist/{research-WB6BBCDD.js → research-VUWWEQ4R.js} +13 -13
  172. package/dist/{review-BGWVY4RA.js → review-LZ3TA7U7.js} +12 -12
  173. package/dist/{review-desktop-LEORC5VS.js → review-desktop-LAO7U7T3.js} +12 -12
  174. package/dist/{rpc-4TSKSFGC.js → rpc-HKNIVFGC.js} +11 -11
  175. package/dist/{run-3NBLVWXD.js → run-SHCF53FO.js} +9 -9
  176. package/dist/{screencast-start-UZVIT3IN.js → screencast-start-JHMQZVWJ.js} +11 -11
  177. package/dist/{screencast-stop-NOSJSIUO.js → screencast-stop-RWQTWWQS.js} +11 -11
  178. package/dist/{screenshot-LARG4JQG.js → screenshot-QHFYO6PB.js} +11 -11
  179. package/dist/{scroll-VNFMV6TW.js → scroll-L3FTMAV4.js} +11 -11
  180. package/dist/{scroll-into-view-VYRT3JPT.js → scroll-into-view-JVDHX4WU.js} +11 -11
  181. package/dist/{select-KJTUZDVO.js → select-X4BO7GTB.js} +11 -11
  182. package/dist/{serve-EV7K4HKR.js → serve-JIMIBCNO.js} +49 -25
  183. package/dist/serve-JIMIBCNO.js.map +1 -0
  184. package/dist/{shopping-DTXHVQ2X.js → shopping-EGSDP2GL.js} +13 -13
  185. package/dist/{skill-lifecycle-5UAZGKSN.js → skill-lifecycle-OWZYBPFS.js} +3 -3
  186. package/dist/skills/bundled-skill-directories.d.ts.map +1 -1
  187. package/dist/skills/skill-loader.js +2 -2
  188. package/dist/{skills-NSXDX6YM.js → skills-KHMRNOE4.js} +3 -3
  189. package/dist/{snapshot-3XQMCMRJ.js → snapshot-QGJ7RDNV.js} +11 -11
  190. package/dist/{status-YUMDP5KY.js → status-CKGPNYIH.js} +21 -13
  191. package/dist/status-CKGPNYIH.js.map +1 -0
  192. package/dist/{status-OXSYA5XD.js → status-LEBY2X7N.js} +12 -12
  193. package/dist/{status-capabilities-P4KDSE2Y.js → status-capabilities-6QTWNGKM.js} +12 -12
  194. package/dist/{text-V3B7UVIH.js → text-VUZU7D3L.js} +11 -11
  195. package/dist/tools/inspiredesign_run.d.ts.map +1 -1
  196. package/dist/{type-IYBN3ZLR.js → type-N5SURP74.js} +11 -11
  197. package/dist/{uncheck-SG737EGI.js → uncheck-JFMK3SSY.js} +11 -11
  198. package/dist/{uninstall-KYKGJAX7.js → uninstall-FW5ORBIN.js} +3 -3
  199. package/dist/{update-skill-modes-BVX7IVMW.js → update-skill-modes-3ULKJK3Y.js} +3 -3
  200. package/dist/{upload-KH6ZABJA.js → upload-KFUYLL7M.js} +11 -11
  201. package/dist/{use-7YDKO3U4.js → use-CNMPP2ED.js} +10 -10
  202. package/dist/{value-RZBWSKKM.js → value-J335MPZE.js} +11 -11
  203. package/dist/{visible-BSFTAKXR.js → visible-YQZWWPBZ.js} +11 -11
  204. package/dist/{wait-TMTEAYOP.js → wait-IC7YJJPJ.js} +11 -11
  205. package/dist/{windows-HIZ23OHS.js → windows-AGVQ3KX3.js} +12 -12
  206. package/extension/manifest.json +1 -1
  207. package/package.json +1 -1
  208. package/skills/AGENTS.md +2 -1
  209. package/skills/opendevbrowser-best-practices/SKILL.md +16 -3
  210. package/skills/opendevbrowser-best-practices/artifacts/canvas-governance-playbook.md +4 -4
  211. package/skills/opendevbrowser-best-practices/artifacts/skill-runtime-surface-matrix.md +4 -3
  212. package/skills/opendevbrowser-best-practices/assets/templates/mode-flag-matrix.json +7 -0
  213. package/skills/opendevbrowser-best-practices/assets/templates/skill-runtime-pack-matrix.json +49 -3
  214. package/skills/opendevbrowser-best-practices/scripts/odb-workflow.sh +31 -2
  215. package/skills/opendevbrowser-best-practices/scripts/validate-skill-assets.sh +7 -0
  216. package/skills/opendevbrowser-design-agent/SKILL.md +11 -6
  217. package/skills/opendevbrowser-design-agent/artifacts/design-workflows.md +4 -3
  218. package/skills/opendevbrowser-design-agent/artifacts/research-harvest-workflow.md +110 -41
  219. package/skills/opendevbrowser-design-agent/artifacts/scroll-reveal-surface-planning.md +2 -0
  220. package/skills/opendevbrowser-design-agent/assets/templates/reference-pattern-board.v1.json +21 -5
  221. package/skills/opendevbrowser-design-agent/scripts/design-workflow.sh +5 -2
  222. package/skills/opendevbrowser-design-agent/scripts/validate-skill-assets.sh +8 -2
  223. package/skills/opendevbrowser-motion-design/SKILL.md +129 -0
  224. package/skills/opendevbrowser-motion-design/artifacts/accessibility-reduced-motion.md +37 -0
  225. package/skills/opendevbrowser-motion-design/artifacts/device-breakpoint-posture.md +40 -0
  226. package/skills/opendevbrowser-motion-design/artifacts/motion-anti-patterns.md +29 -0
  227. package/skills/opendevbrowser-motion-design/artifacts/motion-pattern-catalog.md +430 -0
  228. package/skills/opendevbrowser-motion-design/artifacts/motion-release-gate.md +28 -0
  229. package/skills/opendevbrowser-motion-design/artifacts/motion-terminology.md +46 -0
  230. package/skills/opendevbrowser-motion-design/artifacts/open-dev-browser-motion-evidence.md +48 -0
  231. package/skills/opendevbrowser-motion-design/artifacts/performance-frame-budget.md +38 -0
  232. package/skills/opendevbrowser-motion-design/artifacts/platform-framework-guide.md +166 -0
  233. package/skills/opendevbrowser-motion-design/assets/templates/motion-audit-report.v1.md +70 -0
  234. package/skills/opendevbrowser-motion-design/assets/templates/motion-contract.v1.json +79 -0
  235. package/skills/opendevbrowser-motion-design/assets/templates/motion-release-gate.v1.json +18 -0
  236. package/skills/opendevbrowser-motion-design/assets/templates/motion-viewport-matrix.v1.json +76 -0
  237. package/skills/opendevbrowser-motion-design/scripts/motion-workflow.sh +163 -0
  238. package/skills/opendevbrowser-motion-design/scripts/validate-skill-assets.sh +375 -0
  239. package/dist/canvas-5DFEEOKM.js.map +0 -1
  240. package/dist/chunk-2I3YS3DV.js.map +0 -1
  241. package/dist/chunk-37VSRUW4.js.map +0 -1
  242. package/dist/chunk-3ILXPKSJ.js.map +0 -1
  243. package/dist/chunk-4BEJVZRK.js.map +0 -1
  244. package/dist/chunk-6B5WAQV7.js.map +0 -1
  245. package/dist/chunk-COAOWH3G.js.map +0 -1
  246. package/dist/chunk-IPE7TF2P.js.map +0 -1
  247. package/dist/chunk-KZ2IXVQT.js.map +0 -1
  248. package/dist/chunk-MD655IPO.js.map +0 -1
  249. package/dist/chunk-QOMWCRE3.js.map +0 -1
  250. package/dist/daemon-2BSAZXLT.js.map +0 -1
  251. package/dist/help-U7KBQME6.js.map +0 -1
  252. package/dist/inspiredesign-IEUL4PX3.js.map +0 -1
  253. package/dist/serve-EV7K4HKR.js.map +0 -1
  254. package/dist/status-YUMDP5KY.js.map +0 -1
  255. /package/dist/{accessibility-snapshot-CQ4ZKWKC.js.map → accessibility-snapshot-JSPFVWZ6.js.map} +0 -0
  256. /package/dist/{active-window-TD5HYJ72.js.map → active-window-2OB2MSCR.js.map} +0 -0
  257. /package/dist/{annotate-VTLFS2XV.js.map → annotate-VDZBZBKZ.js.map} +0 -0
  258. /package/dist/{artifacts-KJ6RNDO2.js.map → artifacts-JHDUUJGQ.js.map} +0 -0
  259. /package/dist/{attr-BCI5KYCW.js.map → attr-7XIO4MCH.js.map} +0 -0
  260. /package/dist/{capture-desktop-HFTTWY4Z.js.map → capture-desktop-T5YO3EBI.js.map} +0 -0
  261. /package/dist/{capture-window-X63XPIFF.js.map → capture-window-UKEUBWKH.js.map} +0 -0
  262. /package/dist/{check-LWAUY7GC.js.map → check-PQB6KKMN.js.map} +0 -0
  263. /package/dist/{checked-ZSOUKVYT.js.map → checked-RNZIMCU6.js.map} +0 -0
  264. /package/dist/{chunk-PPUWQKIC.js.map → chunk-52ZIOWVU.js.map} +0 -0
  265. /package/dist/{chunk-T4GMCW6Z.js.map → chunk-J3KYGJRQ.js.map} +0 -0
  266. /package/dist/{chunk-AHEWXOKY.js.map → chunk-JROW6ZNN.js.map} +0 -0
  267. /package/dist/{chunk-6PVZ2ABC.js.map → chunk-L3YNUGYF.js.map} +0 -0
  268. /package/dist/{chunk-JZXD6FWR.js.map → chunk-NURQB55J.js.map} +0 -0
  269. /package/dist/{chunk-STGGGVYT.js.map → chunk-QMHKAFYX.js.map} +0 -0
  270. /package/dist/{chunk-RPXWUCQQ.js.map → chunk-SKFB5ICF.js.map} +0 -0
  271. /package/dist/{chunk-2SIMIPLY.js.map → chunk-W6YPVNDX.js.map} +0 -0
  272. /package/dist/{chunk-GQJ5S3BL.js.map → chunk-YRRRUGSQ.js.map} +0 -0
  273. /package/dist/{chunk-KDSNXS6N.js.map → chunk-ZMNEWS7A.js.map} +0 -0
  274. /package/dist/{click-2AILSEIZ.js.map → click-U7ZFKSB4.js.map} +0 -0
  275. /package/dist/{clone-component-TPJS3PEG.js.map → clone-component-SWYAORTU.js.map} +0 -0
  276. /package/dist/{clone-page-LE74CIFC.js.map → clone-page-WJ6UJOJG.js.map} +0 -0
  277. /package/dist/{close-HN4YI47K.js.map → close-NAVIHZ2T.js.map} +0 -0
  278. /package/dist/{close-WFERRHX6.js.map → close-VKIGIKVT.js.map} +0 -0
  279. /package/dist/{connect-RWBV2UCQ.js.map → connect-XVG2MOZL.js.map} +0 -0
  280. /package/dist/{console-poll-PP4YYPDF.js.map → console-poll-XI5BZPL7.js.map} +0 -0
  281. /package/dist/{cookie-import-6IP776FC.js.map → cookie-import-QELKE7TK.js.map} +0 -0
  282. /package/dist/{cookie-list-O2KG6DPU.js.map → cookie-list-QDA6KWIY.js.map} +0 -0
  283. /package/dist/{debug-trace-snapshot-F3BDVZXS.js.map → debug-trace-snapshot-AT4GAO57.js.map} +0 -0
  284. /package/dist/{dialog-6JQYUWMQ.js.map → dialog-O3V2IBFH.js.map} +0 -0
  285. /package/dist/{disconnect-763TP7GH.js.map → disconnect-NAX5TPTG.js.map} +0 -0
  286. /package/dist/{enabled-DLYQFNIP.js.map → enabled-VT4FJXDX.js.map} +0 -0
  287. /package/dist/{goto-S346TJJH.js.map → goto-GBJG5NC4.js.map} +0 -0
  288. /package/dist/{hover-6JVJFGO7.js.map → hover-476ZNQZE.js.map} +0 -0
  289. /package/dist/{html-EVOSPBIT.js.map → html-5C4TXOV3.js.map} +0 -0
  290. /package/dist/{inspector-H57BVUJP.js.map → inspector-73ARPCIV.js.map} +0 -0
  291. /package/dist/{inspector-audit-NQBAJWC7.js.map → inspector-audit-QT6QY7KS.js.map} +0 -0
  292. /package/dist/{inspector-plan-ZDIQVND3.js.map → inspector-plan-JRNSGN2Z.js.map} +0 -0
  293. /package/dist/{launch-EK66VQPF.js.map → launch-B35YDRQC.js.map} +0 -0
  294. /package/dist/{list-ADZAQ2IU.js.map → list-JV55JVGB.js.map} +0 -0
  295. /package/dist/{list-KKUKN467.js.map → list-YETWKTKY.js.map} +0 -0
  296. /package/dist/{macro-resolve-6DOQJ7CA.js.map → macro-resolve-DQK4B3W3.js.map} +0 -0
  297. /package/dist/{native-UPLVQ2SG.js.map → native-J2DFLOLP.js.map} +0 -0
  298. /package/dist/{network-poll-NUL4PDPY.js.map → network-poll-4GWHCJXI.js.map} +0 -0
  299. /package/dist/{new-5NKYPEFT.js.map → new-XDCQPIEG.js.map} +0 -0
  300. /package/dist/{open-NR3BPLXV.js.map → open-GIM3ZCSV.js.map} +0 -0
  301. /package/dist/{perf-HJ36ZI6H.js.map → perf-26VBXDPI.js.map} +0 -0
  302. /package/dist/{pointer-down-IYTTQWXZ.js.map → pointer-down-O3VSNAXW.js.map} +0 -0
  303. /package/dist/{pointer-drag-A2YC5PWI.js.map → pointer-drag-WQ5QGE6J.js.map} +0 -0
  304. /package/dist/{pointer-move-W5K5FUI4.js.map → pointer-move-4N4D7JY2.js.map} +0 -0
  305. /package/dist/{pointer-up-6GWVO64Y.js.map → pointer-up-CQC4NPDX.js.map} +0 -0
  306. /package/dist/{press-A3V5WB3S.js.map → press-XGJD45CU.js.map} +0 -0
  307. /package/dist/{product-video-52REKWF3.js.map → product-video-HD4ZOUI7.js.map} +0 -0
  308. /package/dist/{providers-IMFYMMHQ.js.map → providers-KKNPJSQK.js.map} +0 -0
  309. /package/dist/{research-WB6BBCDD.js.map → research-VUWWEQ4R.js.map} +0 -0
  310. /package/dist/{review-BGWVY4RA.js.map → review-LZ3TA7U7.js.map} +0 -0
  311. /package/dist/{review-desktop-LEORC5VS.js.map → review-desktop-LAO7U7T3.js.map} +0 -0
  312. /package/dist/{rpc-4TSKSFGC.js.map → rpc-HKNIVFGC.js.map} +0 -0
  313. /package/dist/{run-3NBLVWXD.js.map → run-SHCF53FO.js.map} +0 -0
  314. /package/dist/{screencast-start-UZVIT3IN.js.map → screencast-start-JHMQZVWJ.js.map} +0 -0
  315. /package/dist/{screencast-stop-NOSJSIUO.js.map → screencast-stop-RWQTWWQS.js.map} +0 -0
  316. /package/dist/{screenshot-LARG4JQG.js.map → screenshot-QHFYO6PB.js.map} +0 -0
  317. /package/dist/{scroll-VNFMV6TW.js.map → scroll-L3FTMAV4.js.map} +0 -0
  318. /package/dist/{scroll-into-view-VYRT3JPT.js.map → scroll-into-view-JVDHX4WU.js.map} +0 -0
  319. /package/dist/{select-KJTUZDVO.js.map → select-X4BO7GTB.js.map} +0 -0
  320. /package/dist/{shopping-DTXHVQ2X.js.map → shopping-EGSDP2GL.js.map} +0 -0
  321. /package/dist/{skill-lifecycle-5UAZGKSN.js.map → skill-lifecycle-OWZYBPFS.js.map} +0 -0
  322. /package/dist/{skills-NSXDX6YM.js.map → skills-KHMRNOE4.js.map} +0 -0
  323. /package/dist/{snapshot-3XQMCMRJ.js.map → snapshot-QGJ7RDNV.js.map} +0 -0
  324. /package/dist/{status-OXSYA5XD.js.map → status-LEBY2X7N.js.map} +0 -0
  325. /package/dist/{status-capabilities-P4KDSE2Y.js.map → status-capabilities-6QTWNGKM.js.map} +0 -0
  326. /package/dist/{text-V3B7UVIH.js.map → text-VUZU7D3L.js.map} +0 -0
  327. /package/dist/{type-IYBN3ZLR.js.map → type-N5SURP74.js.map} +0 -0
  328. /package/dist/{uncheck-SG737EGI.js.map → uncheck-JFMK3SSY.js.map} +0 -0
  329. /package/dist/{uninstall-KYKGJAX7.js.map → uninstall-FW5ORBIN.js.map} +0 -0
  330. /package/dist/{update-skill-modes-BVX7IVMW.js.map → update-skill-modes-3ULKJK3Y.js.map} +0 -0
  331. /package/dist/{upload-KH6ZABJA.js.map → upload-KFUYLL7M.js.map} +0 -0
  332. /package/dist/{use-7YDKO3U4.js.map → use-CNMPP2ED.js.map} +0 -0
  333. /package/dist/{value-RZBWSKKM.js.map → value-J335MPZE.js.map} +0 -0
  334. /package/dist/{visible-BSFTAKXR.js.map → visible-YQZWWPBZ.js.map} +0 -0
  335. /package/dist/{wait-TMTEAYOP.js.map → wait-IC7YJJPJ.js.map} +0 -0
  336. /package/dist/{windows-HIZ23OHS.js.map → windows-AGVQ3KX3.js.map} +0 -0
@@ -10,7 +10,7 @@ import {
10
10
  INSPIREDESIGN_HANDOFF_RECOMMENDED_SKILLS,
11
11
  buildInspiredesignFollowthroughSummary,
12
12
  buildInspiredesignNextStep
13
- } from "./chunk-KZ2IXVQT.js";
13
+ } from "./chunk-IBIHDGTZ.js";
14
14
  import {
15
15
  applyPromptGuard,
16
16
  applyProviderIssueHint,
@@ -22,7 +22,7 @@ import {
22
22
  readProviderIssueHintFromRecord,
23
23
  redactSensitive,
24
24
  summarizePrimaryProviderIssue
25
- } from "./chunk-WHQZBUNY.js";
25
+ } from "./chunk-3WLCWHIV.js";
26
26
  import {
27
27
  ProviderRuntimeError,
28
28
  createProviderError,
@@ -1968,7 +1968,7 @@ var executeStep = async (args) => {
1968
1968
  });
1969
1969
  await args.handle.pointerMove(args.sessionId, point.x, point.y, args.targetId, 12);
1970
1970
  await args.handle.pointerDown(args.sessionId, point.x, point.y, args.targetId, "left", 1);
1971
- await new Promise((resolve) => setTimeout(resolve, Math.max(250, args.step.holdMs ?? DEFAULT_HOLD_MS2)));
1971
+ await new Promise((resolve2) => setTimeout(resolve2, Math.max(250, args.step.holdMs ?? DEFAULT_HOLD_MS2)));
1972
1972
  await args.handle.pointerUp(args.sessionId, point.x, point.y, args.targetId, "left", 1);
1973
1973
  return;
1974
1974
  }
@@ -3685,8 +3685,8 @@ var CrawlWorkerPool = class {
3685
3685
  }
3686
3686
  const taskId = this.nextTaskId;
3687
3687
  this.nextTaskId += 1;
3688
- return new Promise((resolve, reject) => {
3689
- this.queue.push({ id: taskId, input, resolve, reject });
3688
+ return new Promise((resolve2, reject) => {
3689
+ this.queue.push({ id: taskId, input, resolve: resolve2, reject });
3690
3690
  this.dispatch();
3691
3691
  });
3692
3692
  }
@@ -9086,7 +9086,10 @@ var isWorkflowResumeEnvelope = (value) => isJsonRecord(value) && isWorkflowKind(
9086
9086
  var isWorkflowResumePayload = (value) => isJsonRecord(value) && isWorkflowResumeEnvelope(value.workflow);
9087
9087
 
9088
9088
  // src/providers/workflows.ts
9089
- import { createHash as createHash7 } from "crypto";
9089
+ import { createHash as createHash8 } from "crypto";
9090
+ import { mkdtemp as mkdtemp2, readFile, rm as rm2 } from "fs/promises";
9091
+ import { tmpdir as tmpdir2 } from "os";
9092
+ import { join as join3, resolve } from "path";
9090
9093
 
9091
9094
  // src/providers/workflow-output-root.ts
9092
9095
  import { join as join2 } from "path";
@@ -9282,7 +9285,7 @@ var enrichResearchRecords = (records, timebox, now = /* @__PURE__ */ new Date())
9282
9285
  };
9283
9286
 
9284
9287
  // src/inspiredesign/contract.ts
9285
- import { createHash as createHash3 } from "crypto";
9288
+ import { createHash as createHash4 } from "crypto";
9286
9289
 
9287
9290
  // skills/opendevbrowser-design-agent/assets/templates/canvas-generation-plan.design.v1.json
9288
9291
  var canvas_generation_plan_design_v1_default = {
@@ -11189,10 +11192,172 @@ var expandInspiredesignBrief = (brief, preferredFormatId) => {
11189
11192
  };
11190
11193
  };
11191
11194
 
11195
+ // src/guidance/recipes/pinterest.ts
11196
+ var pinterestGuidance = {
11197
+ id: "inspiredesign.harvest.browser_native_site_search.pinterest",
11198
+ recipeType: "site_navigation",
11199
+ workflow: "inspiredesign",
11200
+ severity: "warning",
11201
+ readiness: "needs_recovery",
11202
+ reasonCode: "pinterest_browser_native_recovery",
11203
+ primaryAction: {
11204
+ id: "pinterest_browser_native_discovery",
11205
+ label: "Use Pinterest browser-native discovery",
11206
+ summary: "Use a user-authorized signed-in Pinterest browser session when required, search Pinterest naturally, collect visual pins or boards, and reject full login walls, challenges, empty grids, and search-shell pages."
11207
+ },
11208
+ commands: [{
11209
+ id: "pinterest-authenticated-harvest",
11210
+ label: "Run an authenticated Pinterest harvest",
11211
+ command: 'npx opendevbrowser inspiredesign harvest --brief "Digital photography studio landing page" --query "cinematic photography studio landing page inspiration" --provider social/pinterest --max-references 5 --visual-evidence required --browser-mode extension --use-cookies --cookie-policy required --challenge-automation-mode browser_with_helper --mode json --output-format json'
11212
+ }],
11213
+ paramsExamples: [{
11214
+ id: "pinterest-harvest-input",
11215
+ label: "Pinterest discovery input",
11216
+ params: {
11217
+ provider: "social/pinterest",
11218
+ browserMode: "extension",
11219
+ useCookies: true,
11220
+ cookiePolicy: "required",
11221
+ visualEvidence: "required"
11222
+ }
11223
+ }],
11224
+ fieldExamples: [],
11225
+ artifactInputs: [
11226
+ { path: "ranked-references.json", purpose: "Confirm accepted URLs are pins, boards, or idea pages with actual visual grids.", required: true },
11227
+ { path: "visual-evidence.json", purpose: "Reject login, challenge, empty-grid, and search-shell screenshots.", required: true }
11228
+ ],
11229
+ validationChecks: [
11230
+ { id: "pinterest-hosts", description: "Accepted URLs stay on Pinterest hosts.", assertion: 'acceptedUrls.every(url => { const host = new URL(url).hostname; return host === "pinterest.com" || host.endsWith(".pinterest.com"); })' },
11231
+ { id: "pinterest-visual-grid", description: "Screenshots show usable visual grids, pins, boards, or idea pages, not blocked UI." }
11232
+ ],
11233
+ fallbackPolicy: {
11234
+ allowed: false,
11235
+ requiresUserConfirmation: true,
11236
+ reason: "Do not switch a Pinterest-scoped request to unrelated web providers without user confirmation."
11237
+ },
11238
+ doNotProceedIf: [
11239
+ "Pinterest is logged out when cookies are required or protected by a challenge",
11240
+ "The signed-in Pinterest session was not explicitly authorized by the user",
11241
+ "Captured page is only a search shell, login wall, or empty grid",
11242
+ "No ranked Pinterest references remain after scoring"
11243
+ ]
11244
+ };
11245
+ var PINTEREST_PIN_ID_PATTERN = /^\d+$/;
11246
+ var RESERVED_PINTEREST_BOARD_PATHS = /* @__PURE__ */ new Set([
11247
+ "about",
11248
+ "board",
11249
+ "business",
11250
+ "create",
11251
+ "explore",
11252
+ "ideas",
11253
+ "login",
11254
+ "messages",
11255
+ "notifications",
11256
+ "pin",
11257
+ "search",
11258
+ "settings",
11259
+ "shopping",
11260
+ "today"
11261
+ ]);
11262
+ var RESERVED_PINTEREST_IDEA_PATHS = /* @__PURE__ */ new Set(["create", "edit", "search"]);
11263
+ var RESERVED_PINTEREST_PROFILE_TABS = /* @__PURE__ */ new Set([
11264
+ "activity",
11265
+ "comments",
11266
+ "created",
11267
+ "followers",
11268
+ "following",
11269
+ "likes",
11270
+ "pins",
11271
+ "saved",
11272
+ "tried"
11273
+ ]);
11274
+ var isAllowedPinterestReferenceHost = (hostname) => hostname === "pinterest.com" || hostname === "www.pinterest.com" || /^[a-z]{2}\.pinterest\.com$/.test(hostname);
11275
+ var normalizePinterestReferenceUrl = (value) => {
11276
+ const trimmed = value.trim();
11277
+ const absolute = trimmed.startsWith("/") ? `https://www.pinterest.com${trimmed}` : trimmed;
11278
+ try {
11279
+ const url = new URL(absolute);
11280
+ if (url.protocol !== "https:" && url.protocol !== "http:") return null;
11281
+ url.protocol = "https:";
11282
+ const hostname = url.hostname.toLowerCase();
11283
+ if (!isAllowedPinterestReferenceHost(hostname)) return null;
11284
+ const pathSegments = url.pathname.split("/").filter(Boolean);
11285
+ const isPin = pathSegments[0] === "pin" && pathSegments.length === 2 && PINTEREST_PIN_ID_PATTERN.test(pathSegments[1] ?? "");
11286
+ const isIdea = pathSegments[0] === "ideas" && pathSegments.length >= 3 && !RESERVED_PINTEREST_IDEA_PATHS.has(pathSegments[1] ?? "") && PINTEREST_PIN_ID_PATTERN.test(pathSegments[pathSegments.length - 1] ?? "");
11287
+ const isBoard = pathSegments.length === 2 && !RESERVED_PINTEREST_BOARD_PATHS.has(pathSegments[0] ?? "") && !RESERVED_PINTEREST_PROFILE_TABS.has(pathSegments[1] ?? "") && pathSegments.every((segment) => !segment.startsWith("_"));
11288
+ if (!isPin && !isIdea && !isBoard) return null;
11289
+ url.hash = "";
11290
+ url.search = "";
11291
+ return url.toString();
11292
+ } catch {
11293
+ return null;
11294
+ }
11295
+ };
11296
+ var extractPinterestUrlsFromText = (value) => {
11297
+ const candidates = value.match(/(?:https?:\/\/(?:(?:www|[a-z]{2})\.)?pinterest\.com\/(?:pin\/[a-zA-Z0-9_-]+|ideas\/[a-zA-Z0-9/_-]+|[a-zA-Z0-9_-]+\/[a-zA-Z0-9_-]+)|(?<![A-Za-z0-9.])\/(?:pin\/[a-zA-Z0-9_-]+|ideas\/[a-zA-Z0-9/_-]+|[a-zA-Z0-9_-]+\/[a-zA-Z0-9_-]+))\/?/g) ?? [];
11298
+ return candidates.map(normalizePinterestReferenceUrl).filter((url) => url !== null);
11299
+ };
11300
+ var buildPinterestSearchUrl = (query) => {
11301
+ const params = new URLSearchParams({ q: query });
11302
+ return `https://www.pinterest.com/search/pins/?${params.toString()}`;
11303
+ };
11304
+ var extractPinterestReferenceUrls = (candidate) => {
11305
+ return [
11306
+ normalizePinterestReferenceUrl(candidate.url ?? ""),
11307
+ ...(candidate.links ?? []).map(normalizePinterestReferenceUrl),
11308
+ ...extractPinterestUrlsFromText(candidate.content ?? ""),
11309
+ ...extractPinterestUrlsFromText(candidate.html ?? "")
11310
+ ].filter((url) => url !== null);
11311
+ };
11312
+ var pinterestSiteRecipe = {
11313
+ id: "social/pinterest",
11314
+ providerIds: ["social/pinterest", "pinterest"],
11315
+ hostnames: ["pinterest.com", "www.pinterest.com", "uk.pinterest.com"],
11316
+ authMode: "authenticated_preferred",
11317
+ navigationSteps: [
11318
+ { id: "open", instruction: "Open Pinterest in the requested browser mode." },
11319
+ { id: "verify-session", instruction: "Verify the page is logged in before searching when cookies are required." },
11320
+ { id: "search", instruction: "Use the Pinterest search box with the brief-specific visual query." },
11321
+ { id: "scroll", instruction: "Scroll enough to collect varied pins, boards, and idea pages." },
11322
+ { id: "collect", instruction: "Collect candidate URLs only from visual result pages." }
11323
+ ],
11324
+ badStates: [
11325
+ { id: "login", markers: ["log in", "sign up", "continue with"], reasonCode: "auth_required", recoveryAction: "Use extension mode with a user-authorized logged-in Pinterest session." },
11326
+ { id: "challenge", markers: ["captcha", "verification", "challenge"], reasonCode: "challenge_detected", recoveryAction: "Resolve the browser challenge before rerunning harvest." },
11327
+ { id: "search-shell", markers: ["pin card", "your profile", "when autocomplete results are available"], reasonCode: "env_limited", recoveryAction: "Open a concrete pin, board, or idea page before capture." }
11328
+ ],
11329
+ evidenceRequirements: [
11330
+ { id: "visual-grid", description: "Candidate shows visual design material, not only Pinterest chrome.", validation: "Screenshot contains pins, boards, or idea page content." },
11331
+ { id: "on-brief", description: "Candidate matches the design brief surface and style intent.", validation: "Reference signals overlap the brief target and are not generic marketplace chrome." }
11332
+ ],
11333
+ recoverySteps: [
11334
+ { id: "authenticate", instruction: "Use extension mode and cookies only from a user-authorized signed-in Pinterest tab." },
11335
+ { id: "explicit-url", instruction: "If search is blocked, provide explicit Pinterest pin, board, or idea page URLs." }
11336
+ ],
11337
+ browserNativeDiscovery: {
11338
+ buildSearchUrl: buildPinterestSearchUrl,
11339
+ extractReferenceUrls: extractPinterestReferenceUrls
11340
+ },
11341
+ guidance: pinterestGuidance
11342
+ };
11343
+
11192
11344
  // src/inspiredesign/reference-pattern-board.ts
11193
11345
  var SIGNAL_LIMIT = 5;
11194
11346
  var SIGNAL_CLIP = 180;
11195
11347
  var PATTERN_LIMIT = 6;
11348
+ var SCORE_FETCH_CAPTURED = 20;
11349
+ var SCORE_CAPTURE_CAPTURED = 20;
11350
+ var SCORE_VISUAL_CAPTURED = 30;
11351
+ var SCORE_SNAPSHOT = 10;
11352
+ var SCORE_CLONE = 8;
11353
+ var SCORE_DOM = 8;
11354
+ var SCORE_PUBLIC_LANDING = 6;
11355
+ var SCORE_SIGNAL_CAP = 12;
11356
+ var SCORE_INTENT_MISMATCH_PENALTY = 55;
11357
+ var SCORE_PINTEREST_CHROME_METADATA_PENALTY = 35;
11358
+ var MAX_REFERENCE_SCORE = 100;
11359
+ var MIN_READY_REFERENCE_SCORE = 50;
11360
+ var MIN_READY_REFERENCE_CONFIDENCE = 0.5;
11196
11361
  var ADVANCED_MOTION_FIELDS = [
11197
11362
  "Advisory shader-style gradients: specify effect type, uniforms, static fallback, and reduced-motion replacement as design language only.",
11198
11363
  "Advisory WebGL-style depth cues: describe layered depth, camera-like parallax, and spatial hierarchy without requiring WebGL runtime.",
@@ -11211,7 +11376,7 @@ var textFromHtml = (html) => {
11211
11376
  var stripActionRefs = (value) => value.replace(/\[r\d+\]\s+(?:link|button|combobox|textbox|option)\s+/gi, "").replace(/\[r\d+\]\s+/gi, "").replace(/\bvalue=/gi, "");
11212
11377
  var isCodeOrCssPreview = (value) => {
11213
11378
  const lower = value.toLowerCase();
11214
- return lower.includes("dangerouslysetinnerhtml") || lower.includes("opendevbrowser-root") || lower.includes("align-content:") || lower.startsWith("import ") || /^[.#][a-z0-9_-]+\s*\{/.test(lower) || lower.includes("{") && /[a-z-]+:\s*[^;]+;/.test(lower);
11379
+ return lower.includes("dangerouslysetinnerhtml") || lower.includes("opendevbrowser-root") || lower.includes("--gestalt-") || lower.includes("align-content:") || lower.startsWith(":root") || lower.startsWith("import ") || /^[.#][a-z0-9_-]+\s*\{/.test(lower) || lower.includes("{") && /[a-z-]+:\s*[^;]+;/.test(lower);
11215
11380
  };
11216
11381
  var cleanEvidenceText = (value) => {
11217
11382
  return trimText(stripActionRefs(value).replace(/[{};]/g, " "));
@@ -11223,6 +11388,15 @@ var DIAGNOSTIC_TEXT_MARKERS = [
11223
11388
  "challenge page",
11224
11389
  "access denied",
11225
11390
  "browser capture unavailable",
11391
+ "404",
11392
+ "page not found",
11393
+ "not found",
11394
+ "unavailable page",
11395
+ "accept all cookies",
11396
+ "cookie consent",
11397
+ "cookie preferences",
11398
+ "privacy settings",
11399
+ "consent modal",
11226
11400
  "javascript required",
11227
11401
  "javascript is required",
11228
11402
  "captcha",
@@ -11232,6 +11406,48 @@ var DIAGNOSTIC_TEXT_MARKERS = [
11232
11406
  "complete the verification",
11233
11407
  "blocked reference"
11234
11408
  ];
11409
+ var SEARCH_OR_LISTING_SHELL_MARKERS = [
11410
+ "search results for",
11411
+ "related searches",
11412
+ "sort by",
11413
+ "filter by"
11414
+ ];
11415
+ var MARKETPLACE_CHROME_MARKERS = [
11416
+ "add to cart",
11417
+ "marketplace",
11418
+ "envato",
11419
+ "etsy",
11420
+ "template kits"
11421
+ ];
11422
+ var HARD_DIAGNOSTIC_PAGE_MARKERS = [
11423
+ "404",
11424
+ "page not found",
11425
+ "this page is unavailable",
11426
+ "accept all cookies",
11427
+ "manage cookies",
11428
+ "cookie consent",
11429
+ "sign in to continue",
11430
+ "log in to continue",
11431
+ "captcha",
11432
+ "verification challenge"
11433
+ ];
11434
+ var INTERFACE_CHROME_TEXT_MARKERS = [
11435
+ "your profile",
11436
+ "your boards",
11437
+ "remove search input",
11438
+ "settings & support",
11439
+ "pin card",
11440
+ "voice search",
11441
+ "lens",
11442
+ "back to home page",
11443
+ "toggle mobile menu",
11444
+ "facebook",
11445
+ "instagram",
11446
+ "updates",
11447
+ "messages",
11448
+ "when autocomplete results are available",
11449
+ "touch device users"
11450
+ ];
11235
11451
  var PUBLIC_LANDING_TEXT_MARKERS = [
11236
11452
  "church",
11237
11453
  "landing page",
@@ -11271,6 +11487,53 @@ var isDiagnosticText = (value) => {
11271
11487
  const lower = value.toLowerCase();
11272
11488
  return DIAGNOSTIC_TEXT_MARKERS.some((marker) => lower.includes(marker));
11273
11489
  };
11490
+ var diagnosticPageReasons = (value) => {
11491
+ const lower = value.toLowerCase();
11492
+ const reasons = [];
11493
+ if (["404", "page not found", "this page is unavailable"].some((marker) => lower.includes(marker))) {
11494
+ reasons.push("unavailable_page");
11495
+ }
11496
+ if (["accept all cookies", "manage cookies", "cookie consent", "privacy settings", "enable cookies"].some((marker) => lower.includes(marker))) {
11497
+ reasons.push("cookie_or_consent_modal");
11498
+ }
11499
+ if ([
11500
+ "sign in to continue",
11501
+ "log in to continue",
11502
+ "authentication required",
11503
+ "access denied",
11504
+ "captcha",
11505
+ "verification challenge",
11506
+ "complete the verification"
11507
+ ].some((marker) => lower.includes(marker))) {
11508
+ reasons.push("login_or_challenge_state");
11509
+ }
11510
+ const searchShellCount = SEARCH_OR_LISTING_SHELL_MARKERS.filter((marker) => lower.includes(marker)).length;
11511
+ if (searchShellCount >= 2 || lower.includes("search results for") || lower.includes("related searches")) {
11512
+ reasons.push("search_or_listing_shell");
11513
+ }
11514
+ const marketplaceChromeCount = MARKETPLACE_CHROME_MARKERS.filter((marker) => lower.includes(marker)).length;
11515
+ if (marketplaceChromeCount >= 2 || (lower.includes("envato") || lower.includes("etsy")) && (lower.includes("template kits") || searchShellCount > 0)) {
11516
+ reasons.push("marketplace_or_template_chrome");
11517
+ }
11518
+ if (isInterfaceChromeText(value)) {
11519
+ reasons.push("interface_chrome_shell");
11520
+ }
11521
+ return [...new Set(reasons)];
11522
+ };
11523
+ var isDiagnosticPageText = (value) => {
11524
+ const lower = value.toLowerCase();
11525
+ return HARD_DIAGNOSTIC_PAGE_MARKERS.some((marker) => lower.includes(marker)) || diagnosticPageReasons(value).length > 0;
11526
+ };
11527
+ var isInterfaceChromeText = (value) => {
11528
+ const lower = value.toLowerCase();
11529
+ const actionRefCount = countActionRefs(value);
11530
+ const markerCount = INTERFACE_CHROME_TEXT_MARKERS.filter((marker) => lower.includes(marker)).length;
11531
+ if (lower === "your profile" || lower === "adobe, inc." || lower === "dribbble: the community for graphic design" || /^https?:\/\/\S+$/.test(lower) || lower.includes("when autocomplete results are available") && lower.includes("touch device users") || actionRefCount >= 3 && markerCount >= 2 || lower.includes("get 20%") && lower.includes("dribbble: the community for graphic design") || lower.includes("our free wordpress themes are downloaded") && lower.includes("get them now")) {
11532
+ return true;
11533
+ }
11534
+ return markerCount >= 3 || lower.includes("pin card") && lower.includes("your profile");
11535
+ };
11536
+ var countActionRefs = (value) => (value.match(/\[r\d+\]\s+(?:link|button|combobox|textbox|option)\s+/gi) ?? []).length;
11274
11537
  var hasPublicLandingSignal = (value) => {
11275
11538
  const lower = value.toLowerCase();
11276
11539
  const strongCount = PUBLIC_LANDING_TEXT_MARKERS.filter((marker) => lower.includes(marker)).length;
@@ -11281,7 +11544,7 @@ var hasPublicLandingSignal = (value) => {
11281
11544
  var pushSignal = (signals, value) => {
11282
11545
  if (!value || isCodeOrCssPreview(value)) return;
11283
11546
  const text = cleanEvidenceText(value);
11284
- if (isCodeOrCssPreview(text) || isDiagnosticText(text)) return;
11547
+ if (isCodeOrCssPreview(text) || isDiagnosticText(text) || isInterfaceChromeText(text)) return;
11285
11548
  if (text.length > 0 && !signals.includes(text)) {
11286
11549
  signals.push(text);
11287
11550
  }
@@ -11300,13 +11563,56 @@ var getInspiredesignReferenceSignals = (reference) => {
11300
11563
  var hasCleanSignal = (value) => {
11301
11564
  if (!value || isCodeOrCssPreview(value)) return false;
11302
11565
  const text = cleanEvidenceText(value);
11303
- return text.length > 0 && !isCodeOrCssPreview(text) && !isDiagnosticText(text);
11566
+ return text.length > 0 && !isCodeOrCssPreview(text) && !isDiagnosticText(text) && !isDiagnosticPageText(text) && !isInterfaceChromeText(text);
11304
11567
  };
11305
11568
  var hasUsableCloneCreativeEvidence = (reference) => hasCleanSignal(reference.capture?.clone?.componentPreview);
11569
+ var hasUsableRecoveredCreativeEvidence = (reference) => hasUsableCloneCreativeEvidence(reference) || hasCleanSignal(textFromHtml(reference.capture?.dom?.outerHTML));
11570
+ var isPinterestVisualReferenceUrl = (value) => normalizePinterestReferenceUrl(value) !== null;
11571
+ var pinterestHostnameFromUrl = (value) => {
11572
+ try {
11573
+ return new URL(value).hostname.toLowerCase();
11574
+ } catch {
11575
+ return null;
11576
+ }
11577
+ };
11578
+ var isPinterestOwnedReferenceUrl = (value) => {
11579
+ const hostname = pinterestHostnameFromUrl(value);
11580
+ return hostname !== null && (hostname === "pinterest.com" || hostname.endsWith(".pinterest.com"));
11581
+ };
11582
+ var isUnapprovedPinterestReferenceUrl = (value) => {
11583
+ const hostname = pinterestHostnameFromUrl(value);
11584
+ return hostname !== null && isPinterestOwnedReferenceUrl(value) && !isAllowedPinterestReferenceHost(hostname);
11585
+ };
11586
+ var hasCleanMetadataValue = (value) => typeof value === "string" && countActionRefs(value) < 3 && hasCleanSignal(value);
11587
+ var hasCleanMetadataSignal = (reference) => hasCleanMetadataValue(reference.title) || hasCleanMetadataValue(reference.excerpt) || hasCleanMetadataValue(reference.capture?.title);
11588
+ var hasOnlySoftPinterestChromeDiagnostics = (reasons) => reasons.every((reason) => reason === "interface_chrome_shell");
11589
+ var hasPinterestVisualMetadataEvidence = (reference, diagnosticReasons) => isPinterestVisualReferenceUrl(reference.url) && reference.captureStatus === "captured" && reference.capture?.visual?.status === "captured" && hasCleanMetadataSignal(reference) && hasOnlySoftPinterestChromeDiagnostics(diagnosticReasons);
11306
11590
  var hasUsableCaptureEvidence = (reference) => hasCleanSignal(reference.capture?.snapshot?.content) || hasUsableCloneCreativeEvidence(reference) || hasCleanSignal(textFromHtml(reference.capture?.dom?.outerHTML));
11591
+ var referenceDiagnosticReasons = (reference) => {
11592
+ const text = [
11593
+ reference.title,
11594
+ reference.excerpt,
11595
+ reference.capture?.title,
11596
+ reference.capture?.snapshot?.content,
11597
+ textFromHtml(reference.capture?.clone?.componentPreview),
11598
+ reference.capture?.clone?.cssPreview,
11599
+ textFromHtml(reference.capture?.dom?.outerHTML),
11600
+ reference.capture?.visual?.failure,
11601
+ ...reference.capture?.visual?.warnings ?? []
11602
+ ].filter((value) => typeof value === "string" && value.trim().length > 0).join(" ");
11603
+ return diagnosticPageReasons(text);
11604
+ };
11605
+ var hasBlockingDiagnosticReason = (reasons) => reasons.some((reason) => reason !== "login_or_challenge_state");
11307
11606
  var hasInspiredesignUsableReferenceEvidence = (reference) => {
11607
+ if (isUnapprovedPinterestReferenceUrl(reference.url)) return false;
11608
+ const diagnosticReasons = referenceDiagnosticReasons(reference);
11609
+ if (hasPinterestVisualMetadataEvidence(reference, diagnosticReasons)) return true;
11610
+ if (hasBlockingDiagnosticReason(diagnosticReasons)) return false;
11611
+ if (diagnosticReasons.includes("login_or_challenge_state") && !hasUsableRecoveredCreativeEvidence(reference)) {
11612
+ return false;
11613
+ }
11308
11614
  if (reference.captureStatus === "captured" && hasUsableCaptureEvidence(reference)) return true;
11309
- return reference.fetchStatus === "captured" && (hasCleanSignal(reference.title) || hasCleanSignal(reference.excerpt));
11615
+ return reference.fetchStatus === "captured" && diagnosticReasons.length === 0 && (hasCleanSignal(reference.title) || hasCleanSignal(reference.excerpt));
11310
11616
  };
11311
11617
  var firstSignal = (reference) => {
11312
11618
  const preferred = [
@@ -11316,9 +11622,16 @@ var firstSignal = (reference) => {
11316
11622
  textFromHtml(reference.capture?.dom?.outerHTML),
11317
11623
  reference.excerpt,
11318
11624
  reference.title
11319
- ].map((value) => value ? cleanEvidenceText(value) : "").find((value) => value.length > 0 && !isCodeOrCssPreview(value) && !isDiagnosticText(value));
11625
+ ].map((value) => value ? cleanEvidenceText(value) : "").find((value) => value.length > 0 && !isCodeOrCssPreview(value) && !isDiagnosticText(value) && !isInterfaceChromeText(value));
11320
11626
  return preferred ? clipText(preferred, SIGNAL_CLIP) : reference.url;
11321
11627
  };
11628
+ var displayNameForReference = (reference, primarySignal) => {
11629
+ const title = reference.title ? cleanEvidenceText(reference.title) : "";
11630
+ if (title && !isDiagnosticText(title) && !isInterfaceChromeText(title)) {
11631
+ return clipText(title, SIGNAL_CLIP);
11632
+ }
11633
+ return primarySignal !== reference.url ? primarySignal : reference.url;
11634
+ };
11322
11635
  var REFERENCE_PATTERN_RULES = [
11323
11636
  {
11324
11637
  summary: "location-first church discovery with regional pathways",
@@ -11370,14 +11683,64 @@ var appendSourceDetail = (patterns, primarySignal) => {
11370
11683
  };
11371
11684
  var deriveCapturedVia = (reference) => {
11372
11685
  const methods = [];
11686
+ const diagnosticReasons = referenceDiagnosticReasons(reference);
11687
+ const hasPinterestVisualMetadata = hasPinterestVisualMetadataEvidence(reference, diagnosticReasons);
11373
11688
  if (reference.fetchStatus === "captured") methods.push("fetch");
11374
- if (reference.capture?.snapshot?.content.trim()) methods.push("snapshot");
11689
+ if (hasCleanSignal(reference.capture?.snapshot?.content)) methods.push("snapshot");
11375
11690
  if (hasUsableCloneCreativeEvidence(reference)) {
11376
11691
  methods.push("clone");
11377
11692
  }
11378
- if (reference.capture?.dom?.outerHTML.trim()) methods.push("dom");
11693
+ if (hasCleanSignal(textFromHtml(reference.capture?.dom?.outerHTML))) methods.push("dom");
11694
+ if (reference.capture?.visual?.status === "captured" && (hasUsableCaptureEvidence(reference) || hasPinterestVisualMetadata)) methods.push("visual");
11379
11695
  return methods;
11380
11696
  };
11697
+ var scoreReference = (reference, signals, isPublicLanding) => {
11698
+ let score = 0;
11699
+ const diagnosticReasons = referenceDiagnosticReasons(reference);
11700
+ const hasPinterestVisualMetadata = hasPinterestVisualMetadataEvidence(reference, diagnosticReasons);
11701
+ if (reference.fetchStatus === "captured") score += SCORE_FETCH_CAPTURED;
11702
+ if (reference.captureStatus === "captured" && (hasUsableCaptureEvidence(reference) || hasPinterestVisualMetadata)) {
11703
+ score += SCORE_CAPTURE_CAPTURED;
11704
+ }
11705
+ if (reference.capture?.visual?.status === "captured" && (hasUsableCaptureEvidence(reference) || hasPinterestVisualMetadata)) score += SCORE_VISUAL_CAPTURED;
11706
+ if (hasCleanSignal(reference.capture?.snapshot?.content)) score += SCORE_SNAPSHOT;
11707
+ if (hasUsableCloneCreativeEvidence(reference)) score += SCORE_CLONE;
11708
+ if (hasCleanSignal(textFromHtml(reference.capture?.dom?.outerHTML))) score += SCORE_DOM;
11709
+ if (isPublicLanding) score += SCORE_PUBLIC_LANDING;
11710
+ score += Math.min(SCORE_SIGNAL_CAP, signals.length * 2);
11711
+ if (hasPinterestVisualMetadata && diagnosticReasons.includes("interface_chrome_shell")) {
11712
+ score -= SCORE_PINTEREST_CHROME_METADATA_PENALTY;
11713
+ }
11714
+ return Math.min(MAX_REFERENCE_SCORE, score);
11715
+ };
11716
+ var confidenceFromScore = (score) => Number((score / MAX_REFERENCE_SCORE).toFixed(2));
11717
+ var deriveVisualStrengths = (reference, patterns) => {
11718
+ const strengths = [
11719
+ ...reference.capture?.visual?.status === "captured" ? ["Screenshot artifact is available for direct visual inspection."] : [],
11720
+ ...reference.capture?.snapshot?.content.trim() ? ["Snapshot text confirms visible hierarchy and interaction targets."] : [],
11721
+ ...hasUsableCloneCreativeEvidence(reference) ? ["Clone preview exposes reusable component and styling cues."] : [],
11722
+ ...patterns.slice(0, 2).map((pattern) => `Reusable visual cue: ${pattern}.`)
11723
+ ];
11724
+ return strengths.slice(0, PATTERN_LIMIT);
11725
+ };
11726
+ var deriveVisualRisks = (reference) => {
11727
+ const risks = [
11728
+ ...reference.capture?.visual?.status !== "captured" ? ["No finalized screenshot artifact, so visual claims must stay conservative."] : [],
11729
+ ...reference.capture?.visual?.status === "failed" && reference.capture.visual.failure ? [`Screenshot failure: ${reference.capture.visual.failure}.`] : [],
11730
+ ...(reference.capture?.visual?.warnings ?? []).map((warning) => `Screenshot warning: ${warning}.`),
11731
+ ...reference.fetchStatus !== "captured" ? ["Fetch evidence failed or was skipped, so use browser capture cautiously."] : []
11732
+ ];
11733
+ return risks.length > 0 ? risks.slice(0, PATTERN_LIMIT) : ["No major visual evidence risk detected in the captured reference."];
11734
+ };
11735
+ var selectionReasonForScore = (score, capturedVia) => {
11736
+ if (capturedVia.includes("visual")) {
11737
+ return `Ranked for screenshot-backed visual evidence plus ${capturedVia.join(", ")} capture.`;
11738
+ }
11739
+ if (score >= 50) {
11740
+ return `Ranked for strong text and structural evidence from ${capturedVia.join(", ") || "reference metadata"}.`;
11741
+ }
11742
+ return "Ranked for limited but usable reference cues.";
11743
+ };
11381
11744
  var deriveComponentFamilies = (format, patterns, isPublicLanding) => {
11382
11745
  const base = isPublicLanding ? "hero composition, proof bands, narrative pathways, service or story sections, conversion CTA, and footer" : format.componentGrammar;
11383
11746
  return [base, ...patterns.slice(0, 3)];
@@ -11400,17 +11763,80 @@ var boardEvidenceText = (board) => board.references.map((reference) => [
11400
11763
  ...reference.patternsToBorrow
11401
11764
  ].join(" ")).join(" ").toLowerCase();
11402
11765
  var hasEvidenceCue = (text, matches) => matches.some((match) => text.includes(match));
11403
- var deriveReferenceEntry = (reference, format) => {
11766
+ var INTENT_STOP_WORDS = /* @__PURE__ */ new Set([
11767
+ "and",
11768
+ "cinematic",
11769
+ "dark",
11770
+ "digital",
11771
+ "for",
11772
+ "from",
11773
+ "landing",
11774
+ "light",
11775
+ "microinteractions",
11776
+ "motion",
11777
+ "page",
11778
+ "parallax",
11779
+ "premium",
11780
+ "reveal",
11781
+ "site",
11782
+ "scroll",
11783
+ "theme",
11784
+ "with",
11785
+ "design",
11786
+ "website"
11787
+ ]);
11788
+ var tokenizeIntent = (value) => (value.toLowerCase().match(/[a-z0-9][a-z0-9-]{2,}/g) ?? []).filter((token) => !INTENT_STOP_WORDS.has(token));
11789
+ var formatIntentTokens = (format) => [
11790
+ ...format.keywords,
11791
+ ...format.businessFocus,
11792
+ ...format.bestFor,
11793
+ ...format.focusAreas ?? [],
11794
+ format.archetype,
11795
+ format.layoutArchetype,
11796
+ format.surfaceTreatment,
11797
+ format.motionGrammar,
11798
+ format.paletteIntent
11799
+ ].flatMap(tokenizeIntent);
11800
+ var intentTokenVariants = (token) => {
11801
+ if (token === "photo" || token === "photos" || token === "photography" || token === "photographer" || token === "photographic") {
11802
+ return ["photo", "photos", "photography", "photographer", "photographic"];
11803
+ }
11804
+ return [token];
11805
+ };
11806
+ var countMatchedIntentTokens = (signals, intentTokens) => {
11807
+ const evidenceTokens = new Set(signals.flatMap(tokenizeIntent));
11808
+ return intentTokens.filter((token) => intentTokenVariants(token).some((variant) => evidenceTokens.has(variant))).length;
11809
+ };
11810
+ var hasBriefIntentMatch = (signals, format, briefText) => {
11811
+ const briefTokens = tokenizeIntent(briefText);
11812
+ const hasBriefIntentTokens = briefTokens.length > 0;
11813
+ const intentTokens = [...new Set(hasBriefIntentTokens ? briefTokens : formatIntentTokens(format))];
11814
+ if (intentTokens.length === 0) return true;
11815
+ const matchCount = countMatchedIntentTokens(signals, intentTokens);
11816
+ if (!hasBriefIntentTokens) return matchCount > 0;
11817
+ return matchCount >= Math.min(2, intentTokens.length);
11818
+ };
11819
+ var deriveReferenceEntry = (reference, format, briefText) => {
11404
11820
  const signals = getInspiredesignReferenceSignals(reference);
11405
11821
  const primarySignal = firstSignal(reference);
11406
11822
  const patterns = appendSourceDetail(derivePatternSummaries(signals, primarySignal), primarySignal);
11407
11823
  const isPublicLanding = signals.some(hasPublicLandingSignal);
11824
+ const capturedVia = deriveCapturedVia(reference);
11825
+ const intentMatched = hasBriefIntentMatch(signals, format, briefText);
11826
+ const rawScore = scoreReference(reference, signals, isPublicLanding);
11827
+ const score = intentMatched ? rawScore : Math.max(0, rawScore - SCORE_INTENT_MISMATCH_PENALTY);
11408
11828
  return {
11409
11829
  id: reference.id,
11410
- name: reference.title ?? reference.url,
11830
+ score,
11831
+ confidence: confidenceFromScore(score),
11832
+ name: displayNameForReference(reference, primarySignal),
11411
11833
  url: reference.url,
11412
11834
  surfaceType: isPublicLanding ? "public landing page" : format.archetype,
11413
- capturedVia: deriveCapturedVia(reference),
11835
+ capturedVia,
11836
+ intentMatched,
11837
+ selectionReason: intentMatched ? selectionReasonForScore(score, capturedVia) : `${selectionReasonForScore(score, capturedVia)} Intent overlap with the brief is weak, so the score was downgraded.`,
11838
+ visualStrengths: deriveVisualStrengths(reference, patterns),
11839
+ visualRisks: deriveVisualRisks(reference),
11414
11840
  layoutRecipe: patterns.join("; "),
11415
11841
  contentHierarchy: patterns.slice(0, 4),
11416
11842
  componentFamilies: deriveComponentFamilies(format, patterns, isPublicLanding),
@@ -11421,16 +11847,104 @@ var deriveReferenceEntry = (reference, format) => {
11421
11847
  whyItWorks: reference.captureStatus === "captured" ? "Captured reference evidence provides reusable hierarchy, rhythm, and component cues." : "Available reference text provides directional content and hierarchy cues."
11422
11848
  };
11423
11849
  };
11424
- var buildInspiredesignReferencePatternBoard = (briefId, format, references) => {
11425
- const entries = references.filter(hasInspiredesignUsableReferenceEvidence).map((reference) => deriveReferenceEntry(reference, format));
11426
- const sharedStrengths = entries.flatMap((entry) => entry.patternsToBorrow).slice(0, 6);
11427
- const targetSurface = entries.some((entry) => entry.surfaceType === "public landing page") ? "reference-led public landing page" : format.layoutArchetype;
11850
+ var sortReferenceEntries = (entries) => entries.slice().sort((left, right) => right.score - left.score || left.id.localeCompare(right.id) || left.url.localeCompare(right.url)).map((entry, index) => ({
11851
+ rank: index + 1,
11852
+ ...entry
11853
+ }));
11854
+ var rejectionReasonForReference = (reference) => {
11855
+ if (isUnapprovedPinterestReferenceUrl(reference.url)) {
11856
+ return "Pinterest reference host is not approved for creative synthesis.";
11857
+ }
11858
+ const diagnosticReasons = referenceDiagnosticReasons(reference);
11859
+ if (diagnosticReasons.length > 0) {
11860
+ return `Reference evidence is diagnostic-only: ${diagnosticReasons.join(", ")}.`;
11861
+ }
11862
+ if (reference.fetchStatus === "failed" && reference.captureStatus === "failed") {
11863
+ return "Fetch and capture did not produce usable creative evidence.";
11864
+ }
11865
+ if (reference.captureStatus === "failed") {
11866
+ return "Capture did not produce usable creative evidence.";
11867
+ }
11868
+ if (reference.fetchStatus === "failed") {
11869
+ return "Fetch did not produce usable creative evidence.";
11870
+ }
11871
+ return "Reference evidence was diagnostic, empty, or too weak for creative synthesis.";
11872
+ };
11873
+ var buildRejectedReferences = (references) => references.filter((reference) => !hasInspiredesignUsableReferenceEvidence(reference)).map((reference) => ({
11874
+ id: reference.id,
11875
+ url: reference.url,
11876
+ reason: rejectionReasonForReference(reference),
11877
+ fetchStatus: reference.fetchStatus,
11878
+ captureStatus: reference.captureStatus
11879
+ }));
11880
+ var buildQualitySummary = (references, rankedEntries, rejectedReferences) => {
11881
+ const diagnosticOnlyReasons = [...new Set(references.flatMap(referenceDiagnosticReasons))];
11882
+ const rankedIds = new Set(rankedEntries.map((entry) => entry.id));
11883
+ const rankedReferences = references.filter((reference) => rankedIds.has(reference.id));
11884
+ const failedCaptureCount = rankedReferences.filter((reference) => reference.captureStatus === "failed").length;
11885
+ const missingScreenshotCount = rankedReferences.filter((reference) => reference.capture?.visual?.status !== "captured").length;
11886
+ const topReference = rankedEntries[0];
11887
+ return {
11888
+ rankedReferenceCount: rankedEntries.length,
11889
+ rejectedReferenceCount: rejectedReferences.length,
11890
+ failedCaptureCount,
11891
+ missingScreenshotCount,
11892
+ diagnosticOnlyReasons,
11893
+ ...topReference ? {
11894
+ topReferenceScore: topReference.score,
11895
+ topReferenceConfidence: topReference.confidence,
11896
+ topReferenceIntentMatched: topReference.intentMatched
11897
+ } : {}
11898
+ };
11899
+ };
11900
+ var summarizeInspiredesignReferenceQuality = (board) => ({ ...board.qualitySummary });
11901
+ var isInspiredesignReadyReference = (reference) => reference.intentMatched && reference.score >= MIN_READY_REFERENCE_SCORE && reference.confidence >= MIN_READY_REFERENCE_CONFIDENCE;
11902
+ var isInspiredesignDesignReference = (reference) => !isPinterestOwnedReferenceUrl(reference.url) || isPinterestVisualReferenceUrl(reference.url) && isInspiredesignReadyReference(reference);
11903
+ var buildInspiredesignDesignReferencePatternBoard = (board, designVectors) => {
11904
+ const references = board.references.filter(isInspiredesignDesignReference);
11905
+ const notReadyCount = board.references.length - references.length;
11906
+ const topReference = references[0];
11907
+ const missingScreenshotCount = references.filter((reference) => !reference.capturedVia.includes("visual")).length;
11908
+ const qualitySummary = {
11909
+ rankedReferenceCount: references.length,
11910
+ rejectedReferenceCount: board.rejectedReferences.length + notReadyCount,
11911
+ failedCaptureCount: 0,
11912
+ missingScreenshotCount,
11913
+ diagnosticOnlyReasons: [...board.qualitySummary.diagnosticOnlyReasons],
11914
+ ...topReference ? {
11915
+ topReferenceScore: topReference.score,
11916
+ topReferenceConfidence: topReference.confidence,
11917
+ topReferenceIntentMatched: topReference.intentMatched
11918
+ } : {}
11919
+ };
11920
+ return {
11921
+ ...board,
11922
+ targetSurface: designVectors.surfaceIntent,
11923
+ qualitySummary,
11924
+ references,
11925
+ rejectedReferences: [],
11926
+ synthesis: {
11927
+ dominantDirection: designVectors.directionLabel,
11928
+ sharedStrengths: [...designVectors.patternsToBorrow],
11929
+ sharedFailuresToAvoid: [...designVectors.patternsToReject],
11930
+ contractDeltas: references.length > 0 ? [...board.synthesis.contractDeltas] : ["No ready reference evidence is available; keep implementation anchored to the source brief."]
11931
+ }
11932
+ };
11933
+ };
11934
+ var buildInspiredesignReferencePatternBoard = (briefId, format, references, briefText = "") => {
11935
+ const entries = references.filter(hasInspiredesignUsableReferenceEvidence).map((reference) => deriveReferenceEntry(reference, format, briefText));
11936
+ const rankedEntries = sortReferenceEntries(entries);
11937
+ const rejectedReferences = buildRejectedReferences(references);
11938
+ const sharedStrengths = rankedEntries.flatMap((entry) => entry.patternsToBorrow).slice(0, 6);
11939
+ const targetSurface = rankedEntries.some((entry) => entry.surfaceType === "public landing page") ? "reference-led public landing page" : format.layoutArchetype;
11428
11940
  return {
11429
11941
  briefId,
11430
11942
  targetSurface,
11431
- references: entries,
11943
+ qualitySummary: buildQualitySummary(references, rankedEntries, rejectedReferences),
11944
+ references: rankedEntries,
11945
+ rejectedReferences,
11432
11946
  synthesis: {
11433
- dominantDirection: entries[0]?.layoutRecipe ?? format.archetype,
11947
+ dominantDirection: rankedEntries[0]?.layoutRecipe ?? format.archetype,
11434
11948
  sharedStrengths,
11435
11949
  sharedFailuresToAvoid: [...format.antiPatterns],
11436
11950
  contractDeltas: [
@@ -11534,13 +12048,16 @@ var buildSectionArchitecture = (format, board) => {
11534
12048
  ];
11535
12049
  };
11536
12050
  var buildInspiredesignDesignVectors = (format, board) => {
11537
- const influence = board.synthesis.sharedStrengths.length > 0 ? board.synthesis.sharedStrengths : [format.archetype];
11538
- const publicLandingEvidence = hasBoardPublicLandingEvidence(board);
12051
+ const designReferences = board.references.filter(isInspiredesignDesignReference);
12052
+ const designStrengths = designReferences.flatMap((entry) => entry.patternsToBorrow).slice(0, 6);
12053
+ const influence = designStrengths.length > 0 ? designStrengths : [format.archetype];
12054
+ const designBoard = { ...board, references: designReferences };
12055
+ const publicLandingEvidence = hasBoardPublicLandingEvidence(designBoard);
11539
12056
  const surfaceIntent = publicLandingEvidence ? "reference-led public landing page" : format.archetype;
11540
- const compositionModel = publicLandingEvidence ? ["full-bleed hero with narrative section cadence", ...board.references.map((entry) => entry.layoutRecipe)] : [format.layoutArchetype, ...board.references.map((entry) => entry.layoutRecipe)];
12057
+ const compositionModel = publicLandingEvidence ? ["full-bleed hero with narrative section cadence", ...designReferences.map((entry) => entry.layoutRecipe)] : [format.layoutArchetype, ...designReferences.map((entry) => entry.layoutRecipe)];
11541
12058
  return {
11542
- sourcePriority: board.references.length > 0 ? "reference-evidence-first" : "brief-only",
11543
- directionLabel: board.synthesis.dominantDirection,
12059
+ sourcePriority: designReferences.length > 0 ? "reference-evidence-first" : "brief-only",
12060
+ directionLabel: designReferences[0]?.layoutRecipe ?? format.archetype,
11544
12061
  surfaceIntent,
11545
12062
  compositionModel: compositionModel.slice(0, 5),
11546
12063
  premiumPosture: [
@@ -11554,21 +12071,198 @@ var buildInspiredesignDesignVectors = (format, board) => {
11554
12071
  "Respect reduced-motion preference with static hierarchy preserved.",
11555
12072
  format.motionGrammar
11556
12073
  ],
11557
- sectionArchitecture: buildSectionArchitecture(format, board),
12074
+ sectionArchitecture: buildSectionArchitecture(format, designBoard),
11558
12075
  typographyPosture: [format.typographySystem],
11559
- imageryPosture: buildImageryPosture(format, board),
11560
- interactionDensity: buildInteractionDensity(format, board),
11561
- interactionMoments: buildInteractionMoments(format, board),
11562
- materialEffects: buildMaterialEffects(board),
12076
+ imageryPosture: buildImageryPosture(format, designBoard),
12077
+ interactionDensity: buildInteractionDensity(format, designBoard),
12078
+ interactionMoments: buildInteractionMoments(format, designBoard),
12079
+ materialEffects: buildMaterialEffects(designBoard),
11563
12080
  advancedMotionAdvisory: [...ADVANCED_MOTION_FIELDS],
11564
12081
  referenceInfluence: influence,
11565
- patternsToBorrow: board.references.flatMap((entry) => entry.patternsToBorrow).slice(0, 8),
11566
- patternsToReject: board.references.flatMap((entry) => entry.patternsToReject).slice(0, 8),
12082
+ patternsToBorrow: designReferences.flatMap((entry) => entry.patternsToBorrow).slice(0, 8),
12083
+ patternsToReject: designReferences.flatMap((entry) => entry.patternsToReject).slice(0, 8),
11567
12084
  guardrails: [...format.guardrails],
11568
12085
  antiPatterns: [...format.antiPatterns]
11569
12086
  };
11570
12087
  };
11571
12088
 
12089
+ // src/inspiredesign/meta-prompt.ts
12090
+ var formatList = (items) => items.length > 0 ? items.map((item) => `- ${item}`).join("\n") : "- No evidence-backed item available.";
12091
+ var formatRankedReferences = (references) => {
12092
+ if (references.length === 0) {
12093
+ return "- No ready references were ranked. Work from the brief and note missing evidence.";
12094
+ }
12095
+ return references.map((reference) => [
12096
+ `### Rank ${reference.rank}: ${reference.name}`,
12097
+ `- URL: ${reference.url}`,
12098
+ `- Score: ${reference.score}`,
12099
+ `- Confidence: ${reference.confidence.toFixed(2)}`,
12100
+ `- Selection reason: ${reference.selectionReason}`,
12101
+ `- Borrow: ${reference.patternsToBorrow.join("; ")}`,
12102
+ `- Reject: ${reference.patternsToReject.join("; ")}`,
12103
+ `- Visual strengths: ${reference.visualStrengths.join("; ")}`,
12104
+ `- Visual risks: ${reference.visualRisks.join("; ")}`
12105
+ ].join("\n")).join("\n\n");
12106
+ };
12107
+ var formatRejectedReferences = (board, notReadyReferences) => {
12108
+ const lines = [
12109
+ ...board.rejectedReferences.length > 0 ? [`- ${board.rejectedReferences.length} reference(s) were rejected as diagnostic-only or unavailable.`] : [],
12110
+ ...notReadyReferences.length > 0 ? [`- ${notReadyReferences.length} ranked reference(s) were not ready for creative synthesis due to score, confidence, or brief-intent mismatch.`] : []
12111
+ ];
12112
+ return lines.length > 0 ? lines.join("\n") : "- No references were rejected from the creative synthesis.";
12113
+ };
12114
+ var buildInspiredesignMetaPrompt = (input) => {
12115
+ const designReferences = input.referencePatternBoard.references.filter(isInspiredesignDesignReference);
12116
+ const notReadyReferences = input.referencePatternBoard.references.filter(
12117
+ (reference) => !isInspiredesignDesignReference(reference)
12118
+ );
12119
+ return [
12120
+ "# InspireDesign Meta Prompt",
12121
+ "",
12122
+ "Use this prompt to generate a fresh design direction from evidence without copying any reference brand, asset, layout, or proprietary expression.",
12123
+ "",
12124
+ "## Source Brief",
12125
+ input.brief,
12126
+ "",
12127
+ "## Prompt Format",
12128
+ `- Format: ${input.briefExpansion.format.label}`,
12129
+ `- Target surface: ${input.designVectors.surfaceIntent}`,
12130
+ `- Dominant direction: ${input.designVectors.directionLabel}`,
12131
+ "",
12132
+ "## Ranked References",
12133
+ formatRankedReferences(designReferences),
12134
+ "",
12135
+ "## Rejected References",
12136
+ formatRejectedReferences(input.referencePatternBoard, notReadyReferences),
12137
+ "",
12138
+ "## Borrow Guidance",
12139
+ formatList(input.designVectors.patternsToBorrow),
12140
+ "",
12141
+ "## Reject Guidance",
12142
+ formatList([
12143
+ ...input.designVectors.patternsToReject,
12144
+ "Do not copy logos, screenshots, protected brand assets, page structure, copy, or trade dress from references."
12145
+ ]),
12146
+ "",
12147
+ "## Motion Posture",
12148
+ formatList([
12149
+ ...input.designVectors.motionPosture,
12150
+ ...input.designVectors.interactionMoments,
12151
+ ...input.designVectors.advancedMotionAdvisory
12152
+ ]),
12153
+ "",
12154
+ "## Accessibility Constraints",
12155
+ formatList([
12156
+ "Keyboard navigation must reach every interactive element.",
12157
+ "Focus states must be visible in every theme and viewport.",
12158
+ "Respect prefers-reduced-motion with a static hierarchy-preserving alternative.",
12159
+ "Validate contrast for text, controls, overlays, and disabled states."
12160
+ ]),
12161
+ "",
12162
+ "## Validation Gates",
12163
+ formatList([
12164
+ "Read visual-evidence.json, screenshot-index.json, ranked-references.json, and evidence.json before implementation.",
12165
+ "Confirm screenshot paths exist before making visual claims.",
12166
+ "Verify desktop and mobile layouts with real browser screenshots.",
12167
+ "Run reduced-motion, keyboard, focus, and contrast checks before shipping.",
12168
+ "Keep production code generation outside the harvest output."
12169
+ ])
12170
+ ].join("\n");
12171
+ };
12172
+
12173
+ // src/inspiredesign/visual-evidence.ts
12174
+ import { createHash as createHash3 } from "crypto";
12175
+ var INSPIREDESIGN_VISUAL_EVIDENCE_MODES = ["off", "auto", "required"];
12176
+ var INSPIREDESIGN_VISUAL_EVIDENCE_KINDS = ["viewport", "full_page"];
12177
+ var SAFE_REFERENCE_ID_PATTERN = /[^a-z0-9._-]+/gi;
12178
+ var MAX_VISUAL_REFERENCE_ID_LENGTH = 96;
12179
+ var MAX_VISUAL_WARNING_LENGTH = 160;
12180
+ var MAX_VISUAL_FAILURE_LENGTH = 240;
12181
+ var UNSAFE_VISUAL_TEXT_PATTERN = /(?:\/(?:Users|private|tmp|var|Volumes)\/|[A-Za-z]:\\|\\|data:image|;base64|base64,|[A-Za-z0-9+/]{80,}={0,2})/i;
12182
+ var DOT_ONLY_PATH_SEGMENT_PATTERN = /^\.+$/;
12183
+ var SHA256_HEX_PATTERN = /^[a-f0-9]{64}$/i;
12184
+ var VISUAL_ARTIFACT_PATH_PATTERN = /^visual-evidence\/([A-Za-z0-9._-]+)\/(?:viewport|full_page)\.png$/;
12185
+ var FALLBACK_VISUAL_CAPTURED_AT = "1970-01-01T00:00:00.000Z";
12186
+ var isInspiredesignVisualEvidenceMode = (value) => typeof value === "string" && INSPIREDESIGN_VISUAL_EVIDENCE_MODES.includes(value);
12187
+ var isInspiredesignVisualEvidenceKind = (value) => typeof value === "string" && INSPIREDESIGN_VISUAL_EVIDENCE_KINDS.includes(value);
12188
+ var sanitizeInspiredesignVisualReferenceId = (referenceId) => {
12189
+ const sanitized = referenceId.trim().replace(SAFE_REFERENCE_ID_PATTERN, "-").replace(/^-+|-+$/g, "");
12190
+ if (!sanitized || DOT_ONLY_PATH_SEGMENT_PATTERN.test(sanitized)) return "reference";
12191
+ const truncated = sanitized.slice(0, MAX_VISUAL_REFERENCE_ID_LENGTH);
12192
+ return DOT_ONLY_PATH_SEGMENT_PATTERN.test(truncated) ? "reference" : truncated;
12193
+ };
12194
+ var buildVisualEvidenceArtifactPath = (referenceId, kind) => `visual-evidence/${sanitizeInspiredesignVisualReferenceId(referenceId)}/${kind}.png`;
12195
+ var hashVisualEvidenceBuffer = (buffer) => createHash3("sha256").update(buffer).digest("hex");
12196
+ var sanitizeVisualEvidenceText = (value, maxLength) => {
12197
+ if (typeof value !== "string") return void 0;
12198
+ const trimmed = value.trim();
12199
+ if (!trimmed || UNSAFE_VISUAL_TEXT_PATTERN.test(trimmed)) return void 0;
12200
+ return trimmed.slice(0, maxLength);
12201
+ };
12202
+ var sanitizeVisualEvidencePath = (value) => {
12203
+ if (typeof value !== "string") return void 0;
12204
+ const trimmed = value.trim();
12205
+ const match = VISUAL_ARTIFACT_PATH_PATTERN.exec(trimmed);
12206
+ const referenceSegment = match?.[1];
12207
+ if (!referenceSegment || DOT_ONLY_PATH_SEGMENT_PATTERN.test(referenceSegment)) return void 0;
12208
+ return trimmed;
12209
+ };
12210
+ var sanitizeVisualEvidenceSha256 = (value) => {
12211
+ if (typeof value !== "string") return void 0;
12212
+ const trimmed = value.trim();
12213
+ return SHA256_HEX_PATTERN.test(trimmed) ? trimmed.toLowerCase() : void 0;
12214
+ };
12215
+ var sanitizeVisualEvidenceBytes = (value) => typeof value === "number" && Number.isFinite(value) && Number.isInteger(value) && value >= 0 ? value : void 0;
12216
+ var sanitizeVisualEvidenceCapturedAt = (value) => {
12217
+ if (typeof value !== "string") return FALLBACK_VISUAL_CAPTURED_AT;
12218
+ const trimmed = value.trim();
12219
+ if (!trimmed || UNSAFE_VISUAL_TEXT_PATTERN.test(trimmed)) return FALLBACK_VISUAL_CAPTURED_AT;
12220
+ const timestamp = Date.parse(trimmed);
12221
+ if (!Number.isFinite(timestamp)) return FALLBACK_VISUAL_CAPTURED_AT;
12222
+ return new Date(timestamp).toISOString();
12223
+ };
12224
+ var normalizeVisualEvidenceViewport = (value) => {
12225
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
12226
+ const record = value;
12227
+ const viewport = {};
12228
+ if (typeof record.width === "number" && Number.isFinite(record.width)) {
12229
+ viewport.width = record.width;
12230
+ }
12231
+ if (typeof record.height === "number" && Number.isFinite(record.height)) {
12232
+ viewport.height = record.height;
12233
+ }
12234
+ if (typeof record.deviceScaleFactor === "number" && Number.isFinite(record.deviceScaleFactor)) {
12235
+ viewport.deviceScaleFactor = record.deviceScaleFactor;
12236
+ }
12237
+ return Object.keys(viewport).length > 0 ? viewport : void 0;
12238
+ };
12239
+ var normalizeVisualEvidenceWarnings = (value) => {
12240
+ if (!Array.isArray(value)) return [];
12241
+ return value.map((warning) => sanitizeVisualEvidenceText(warning, MAX_VISUAL_WARNING_LENGTH)).filter((warning) => Boolean(warning));
12242
+ };
12243
+ var persistInspiredesignVisualEvidence = (metadata, options = {}) => {
12244
+ const runtimeMetadata = metadata;
12245
+ const persistedMetadata = metadata;
12246
+ const path2 = metadata.status === "captured" ? sanitizeVisualEvidencePath(options.artifactPath) ?? sanitizeVisualEvidencePath(persistedMetadata.path) ?? sanitizeVisualEvidencePath(runtimeMetadata.artifactPath) : void 0;
12247
+ const sha256 = sanitizeVisualEvidenceSha256(options.sha256) ?? sanitizeVisualEvidenceSha256(persistedMetadata.sha256);
12248
+ const bytes = sanitizeVisualEvidenceBytes(options.bytes) ?? sanitizeVisualEvidenceBytes(persistedMetadata.bytes);
12249
+ const capturedAt = sanitizeVisualEvidenceCapturedAt(metadata.capturedAt);
12250
+ const viewport = normalizeVisualEvidenceViewport(metadata.viewport);
12251
+ const failure = sanitizeVisualEvidenceText(metadata.failure, MAX_VISUAL_FAILURE_LENGTH);
12252
+ return {
12253
+ status: metadata.status,
12254
+ kind: isInspiredesignVisualEvidenceKind(metadata.kind) ? metadata.kind : "viewport",
12255
+ fullPage: metadata.fullPage === true,
12256
+ capturedAt,
12257
+ ...path2 ? { path: path2 } : {},
12258
+ ...sha256 ? { sha256 } : {},
12259
+ ...bytes !== void 0 ? { bytes } : {},
12260
+ ...viewport ? { viewport } : {},
12261
+ warnings: normalizeVisualEvidenceWarnings(metadata.warnings),
12262
+ ...failure ? { failure } : {}
12263
+ };
12264
+ };
12265
+
11572
12266
  // src/inspiredesign/contract.ts
11573
12267
  var INSPIREDESIGN_CAPTURE_ATTEMPT_KEYS = ["snapshot", "clone", "dom"];
11574
12268
  var MALFORMED_CAPTURE_ATTEMPT_DETAIL = "Capture attempt metadata missing or malformed.";
@@ -11662,7 +12356,8 @@ var normalizeInspiredesignCaptureEvidence = (capture) => {
11662
12356
  ...capture.title ? { title: capture.title } : {},
11663
12357
  ...hasUsableInspiredesignSnapshot(capture) && capture.snapshot ? { snapshot: capture.snapshot } : {},
11664
12358
  ...hasUsableInspiredesignDom(capture) && capture.dom ? { dom: capture.dom } : {},
11665
- ...hasUsableInspiredesignClone(capture) && capture.clone ? { clone: capture.clone } : {}
12359
+ ...hasUsableInspiredesignClone(capture) && capture.clone ? { clone: capture.clone } : {},
12360
+ ...capture.visual ? { visual: persistInspiredesignVisualEvidence(capture.visual) } : {}
11666
12361
  };
11667
12362
  const attempts = reconcileInspiredesignCaptureAttempts(
11668
12363
  normalizedBase,
@@ -11920,13 +12615,16 @@ var buildReferenceSynthesis = (references) => {
11920
12615
  };
11921
12616
  };
11922
12617
  var renderReferenceFirstAdvancedBrief = (briefExpansion, board, vectors, references) => {
11923
- if (board.references.length === 0) {
12618
+ if (board.references.length === 0 || vectors.sourcePriority !== "reference-evidence-first") {
11924
12619
  if (references.length > 0) {
11925
12620
  return [
11926
12621
  "Reference evidence unavailable:",
11927
- "URL references were attempted, but no usable creative evidence was captured. Treat this as a capture gap, not a design direction.",
12622
+ "URL references were attempted, but no ready-quality creative evidence was captured. Treat this as a capture or intent gap, not a design direction.",
11928
12623
  "",
11929
- formatBulletList2(references.map((reference) => renderUnavailableReference(reference))),
12624
+ formatBulletList2([
12625
+ `${references.length} attempted reference(s) are retained in diagnostic artifacts only.`,
12626
+ "Do not use rejected or not-ready reference URLs, names, screenshots, or metadata as creative direction."
12627
+ ]),
11930
12628
  "",
11931
12629
  briefExpansion.advancedBrief
11932
12630
  ].join("\n");
@@ -12013,13 +12711,9 @@ var renderEvidenceDerivedAdvancedBrief = (briefExpansion, format) => [
12013
12711
  "Best fit use cases:",
12014
12712
  formatBulletList2(format.bestFor)
12015
12713
  ].join("\n");
12016
- var renderUnavailableReference = (reference) => {
12017
- const reason = reference.fetchFailure ?? reference.captureFailure ?? "no usable creative evidence captured";
12018
- return `${reference.url}: fetch=${reference.fetchStatus}, capture=${reference.captureStatus}, reason=${clipText2(reason, 160)}`;
12019
- };
12020
12714
  var cloneTemplate = (value) => structuredClone(value);
12021
12715
  var referenceFingerprint = (value) => {
12022
- return createHash3("sha256").update(value).digest("hex").slice(0, 12);
12716
+ return createHash4("sha256").update(value).digest("hex").slice(0, 12);
12023
12717
  };
12024
12718
  var summarizeBrief = (brief) => {
12025
12719
  const normalized = trimText2(brief);
@@ -12543,6 +13237,10 @@ var buildBriefExpansionMetadata = (briefExpansion) => ({
12543
13237
  var buildRequiredReferenceArtifacts = (includePrototypeGuidance) => {
12544
13238
  const files = [
12545
13239
  INSPIREDESIGN_HANDOFF_FILES.evidence,
13240
+ INSPIREDESIGN_HANDOFF_FILES.visualEvidence,
13241
+ INSPIREDESIGN_HANDOFF_FILES.screenshotIndex,
13242
+ INSPIREDESIGN_HANDOFF_FILES.rankedReferences,
13243
+ INSPIREDESIGN_HANDOFF_FILES.metaPrompt,
12546
13244
  INSPIREDESIGN_HANDOFF_FILES.advancedBrief,
12547
13245
  INSPIREDESIGN_HANDOFF_FILES.designMarkdown,
12548
13246
  INSPIREDESIGN_HANDOFF_FILES.generationPlan,
@@ -12585,15 +13283,14 @@ var buildFollowthrough = ({
12585
13283
  });
12586
13284
  var buildDesignContract = ({
12587
13285
  brief,
12588
- urls,
12589
- references,
13286
+ designReferences,
12590
13287
  plan,
12591
13288
  format
12592
13289
  }) => ({
12593
- intent: buildIntentBlock(brief, urls, references, format),
13290
+ intent: buildIntentBlock(brief, designReferences.map((reference) => reference.url), designReferences, format),
12594
13291
  generationPlan: toCanvasGenerationPlan(plan),
12595
13292
  designLanguage: buildDesignLanguageBlock(plan.visualDirection.profile, format),
12596
- contentModel: buildContentModelBlock(brief, references.filter(hasInspiredesignUsableReferenceEvidence)),
13293
+ contentModel: buildContentModelBlock(brief, designReferences),
12597
13294
  layoutSystem: buildLayoutSystemBlock(plan, format),
12598
13295
  typographySystem: buildTypographySystemBlock(format),
12599
13296
  colorSystem: buildColorSystemBlock(plan.visualDirection.profile, format),
@@ -12665,6 +13362,7 @@ var buildImplementationPlan = ({
12665
13362
  profile,
12666
13363
  format,
12667
13364
  references,
13365
+ attemptedReferenceCount,
12668
13366
  synthesis,
12669
13367
  designVectors
12670
13368
  }) => ({
@@ -12702,7 +13400,7 @@ var buildImplementationPlan = ({
12702
13400
  "Avoid horizontal scrolling for primary content."
12703
13401
  ],
12704
13402
  risksAndAmbiguities: [
12705
- references.length === 0 ? "No live references were supplied, so visual cues are derived entirely from the written brief." : synthesis.lines.length > 0 ? "Live references were reduced into reusable patterns; unique brand assets should still be recreated, not copied." : "Reference URLs were attempted, but no usable creative evidence was captured; keep implementation anchored to the source brief and selected prompt format.",
13403
+ attemptedReferenceCount === 0 ? "No live references were supplied, so visual cues are derived entirely from the written brief." : synthesis.lines.length > 0 ? "Live references were reduced into reusable patterns; unique brand assets should still be recreated, not copied." : "Reference URLs were attempted, but no usable creative evidence was captured; keep implementation anchored to the source brief and selected prompt format.",
12706
13404
  "Any missing interaction states must be validated during visual QA.",
12707
13405
  "Capture desktop and mobile browser proof before handoff, including reduced-motion behavior and primary CTA visibility."
12708
13406
  ],
@@ -12957,11 +13655,11 @@ var renderPrototypeGuidance = (profile, synthesis, designVectors, targetAnalysis
12957
13655
  "- first prototype should include vs omit: include shell, primary hero or decision section, CTA group, proof or detail sections, section patterns named in the design vectors, final CTA, and footer; omit analytics, app-shell widgets, empty card grids, and any section not supported by the brief or reference evidence."
12958
13656
  ].join("\n");
12959
13657
  };
12960
- var renderDeliverablesSummary = (includePrototypeGuidance) => {
13658
+ var renderDeliverablesSummary = (includePrototypeGuidance, canvasContinuationReady) => {
12961
13659
  const deliverables = [
12962
13660
  "Structured `designContract` JSON aligned to canvas governance",
12963
13661
  "Valid `generationPlan` JSON aligned to the canvas generation plan contract",
12964
- "Ready-to-fill `canvasPlanRequest` JSON for `canvas.plan.set`",
13662
+ canvasContinuationReady ? "Ready-to-fill `canvasPlanRequest` JSON for `canvas.plan.set`" : "Diagnostic `canvasPlanRequest` preview; do not submit to Canvas until next-step guidance is ready",
12965
13663
  "Design-agent handoff JSON with contract scope, skill nudges, and richer implementation context",
12966
13664
  "Human-readable `design.md` design specification",
12967
13665
  "Engineering implementation plan in JSON and Markdown"
@@ -12994,9 +13692,30 @@ var buildEvidencePayload = ({
12994
13692
  referenceCount: references.length,
12995
13693
  references: references.map((reference) => toReferenceEvidenceJson(reference)),
12996
13694
  referencePatternBoard,
13695
+ rankedReferences: referencePatternBoard.references,
12997
13696
  designVectors,
12998
- targetAnalysis
13697
+ targetAnalysis,
13698
+ visualEvidence: buildVisualEvidencePayload(references),
13699
+ screenshotIndex: buildScreenshotIndex(references)
12999
13700
  });
13701
+ var buildVisualEvidencePayload = (references) => references.flatMap((reference) => {
13702
+ const visual = normalizeInspiredesignCaptureEvidence(reference.capture)?.visual;
13703
+ return visual ? [{
13704
+ referenceId: reference.id,
13705
+ url: reference.url,
13706
+ visual: persistInspiredesignVisualEvidence(visual)
13707
+ }] : [];
13708
+ });
13709
+ var buildScreenshotIndex = (references) => buildVisualEvidencePayload(references).filter((entry) => entry.visual.status === "captured" && typeof entry.visual.path === "string" && typeof entry.visual.sha256 === "string" && typeof entry.visual.bytes === "number").map((entry) => ({
13710
+ referenceId: entry.referenceId,
13711
+ url: entry.url,
13712
+ path: entry.visual.path,
13713
+ sha256: entry.visual.sha256,
13714
+ bytes: entry.visual.bytes,
13715
+ kind: entry.visual.kind,
13716
+ fullPage: entry.visual.fullPage,
13717
+ capturedAt: entry.visual.capturedAt
13718
+ }));
13000
13719
  var toCaptureEvidenceJson = (reference) => {
13001
13720
  const normalized = normalizeInspiredesignCaptureEvidence(reference.capture);
13002
13721
  if (!normalized) return null;
@@ -13004,6 +13723,7 @@ var toCaptureEvidenceJson = (reference) => {
13004
13723
  return {
13005
13724
  ...normalized.title ? { title: normalized.title } : {},
13006
13725
  ...signals.length > 0 ? { signals } : {},
13726
+ ...normalized.visual ? { visual: normalized.visual } : {},
13007
13727
  ...normalized.attempts ? { attempts: normalized.attempts } : {}
13008
13728
  };
13009
13729
  };
@@ -13028,19 +13748,25 @@ var buildInspiredesignPacket = (input) => {
13028
13748
  title: reference.title ? trimText2(reference.title) : void 0,
13029
13749
  excerpt: reference.excerpt ? trimText2(reference.excerpt) : void 0
13030
13750
  }));
13031
- const usableReferences = references.filter(hasInspiredesignUsableReferenceEvidence);
13032
- const synthesis = buildReferenceSynthesis(usableReferences);
13751
+ const referenceEvidenceRequired = input.referenceEvidenceRequired ?? (urls.length > 0 || references.length > 0);
13033
13752
  const referencePatternBoard = buildInspiredesignReferencePatternBoard(
13034
13753
  referenceFingerprint(brief),
13035
13754
  selectedFormat,
13036
- references
13755
+ references,
13756
+ brief
13037
13757
  );
13758
+ const readyReferenceIds = new Set(
13759
+ referencePatternBoard.references.filter(isInspiredesignDesignReference).map((reference) => reference.id)
13760
+ );
13761
+ const usableReferences = references.filter(hasInspiredesignUsableReferenceEvidence).filter((reference) => readyReferenceIds.has(reference.id));
13762
+ const synthesis = buildReferenceSynthesis(usableReferences);
13038
13763
  const designVectors = buildInspiredesignDesignVectors(selectedFormat, referencePatternBoard);
13764
+ const designReferencePatternBoard = buildInspiredesignDesignReferencePatternBoard(referencePatternBoard, designVectors);
13039
13765
  const effectiveFormat = buildEvidenceDerivedFormat(selectedFormat, designVectors);
13040
13766
  const targetAnalysis = buildTargetAnalysis(
13041
13767
  brief,
13042
13768
  effectiveFormat,
13043
- references,
13769
+ usableReferences,
13044
13770
  synthesis,
13045
13771
  designVectors
13046
13772
  );
@@ -13049,9 +13775,15 @@ var buildInspiredesignPacket = (input) => {
13049
13775
  advancedBrief: isReferenceFirstPublicLanding(designVectors) ? renderEvidenceDerivedAdvancedBrief(input.briefExpansion, effectiveFormat) : input.briefExpansion.advancedBrief,
13050
13776
  format: effectiveFormat
13051
13777
  };
13778
+ const metaPromptMarkdown = buildInspiredesignMetaPrompt({
13779
+ brief,
13780
+ briefExpansion: effectiveBriefExpansion,
13781
+ referencePatternBoard,
13782
+ designVectors
13783
+ });
13052
13784
  const advancedBriefMarkdown = renderReferenceFirstAdvancedBrief(
13053
13785
  effectiveBriefExpansion,
13054
- referencePatternBoard,
13786
+ designReferencePatternBoard,
13055
13787
  designVectors,
13056
13788
  references
13057
13789
  );
@@ -13059,7 +13791,7 @@ var buildInspiredesignPacket = (input) => {
13059
13791
  brief,
13060
13792
  format: effectiveFormat,
13061
13793
  synthesis,
13062
- referencePatternBoard,
13794
+ referencePatternBoard: designReferencePatternBoard,
13063
13795
  designVectors,
13064
13796
  targetAnalysis
13065
13797
  });
@@ -13067,8 +13799,7 @@ var buildInspiredesignPacket = (input) => {
13067
13799
  const canvasPlanRequest = buildCanvasPlanRequest(brief, generationPlan);
13068
13800
  const designContract = buildDesignContract({
13069
13801
  brief,
13070
- urls,
13071
- references,
13802
+ designReferences: usableReferences,
13072
13803
  plan: generationPlan,
13073
13804
  format: effectiveFormat
13074
13805
  });
@@ -13077,14 +13808,15 @@ var buildInspiredesignPacket = (input) => {
13077
13808
  briefExpansion: effectiveBriefExpansion,
13078
13809
  synthesis,
13079
13810
  includePrototypeGuidance,
13080
- referencePatternBoard,
13811
+ referencePatternBoard: designReferencePatternBoard,
13081
13812
  designVectors,
13082
13813
  targetAnalysis
13083
13814
  });
13084
13815
  const implementationPlan = buildImplementationPlan({
13085
13816
  profile,
13086
13817
  format: effectiveFormat,
13087
- references,
13818
+ references: usableReferences,
13819
+ attemptedReferenceCount: references.length,
13088
13820
  synthesis,
13089
13821
  designVectors
13090
13822
  });
@@ -13115,7 +13847,7 @@ var buildInspiredesignPacket = (input) => {
13115
13847
  "",
13116
13848
  "## 3.2 Reference Pattern Board",
13117
13849
  "",
13118
- formatBulletList2(referencePatternBoard.synthesis.sharedStrengths.length > 0 ? referencePatternBoard.synthesis.sharedStrengths : ["No live reference cues were captured."]),
13850
+ formatBulletList2(designVectors.patternsToBorrow.length > 0 ? designVectors.patternsToBorrow : ["No live reference cues were captured."]),
13119
13851
  "",
13120
13852
  "## 3.3 Design Vectors",
13121
13853
  "",
@@ -13154,8 +13886,13 @@ var buildInspiredesignPacket = (input) => {
13154
13886
  "",
13155
13887
  "# 7. Deliverables Summary",
13156
13888
  "",
13157
- renderDeliverablesSummary(Boolean(input.includePrototypeGuidance))
13889
+ renderDeliverablesSummary(
13890
+ Boolean(input.includePrototypeGuidance),
13891
+ !referenceEvidenceRequired || designReferencePatternBoard.references.length > 0
13892
+ )
13158
13893
  ].join("\n");
13894
+ const visualEvidence = buildVisualEvidencePayload(references);
13895
+ const screenshotIndex = buildScreenshotIndex(references);
13159
13896
  return {
13160
13897
  advancedBriefMarkdown,
13161
13898
  designContract,
@@ -13166,89 +13903,1291 @@ var buildInspiredesignPacket = (input) => {
13166
13903
  implementationPlan,
13167
13904
  implementationPlanMarkdown,
13168
13905
  prototypeGuidanceMarkdown,
13906
+ visualEvidence,
13907
+ screenshotIndex,
13908
+ rankedReferences: designReferencePatternBoard.references,
13909
+ metaPromptMarkdown,
13169
13910
  evidence: buildEvidencePayload({
13170
13911
  brief,
13171
13912
  briefExpansion: effectiveBriefExpansion,
13172
13913
  advancedBriefMarkdown,
13173
13914
  urls,
13174
13915
  references,
13175
- referencePatternBoard,
13916
+ referencePatternBoard: designReferencePatternBoard,
13176
13917
  designVectors,
13177
13918
  targetAnalysis
13178
13919
  })
13179
13920
  };
13180
13921
  };
13181
13922
 
13182
- // src/providers/workflow-handoff.ts
13183
- var PRODUCT_VIDEO_BRIEF_HELPER_PATH = "./skills/opendevbrowser-product-presentation-asset/scripts/render-video-brief.sh";
13184
- var PRODUCT_VIDEO_BRIEF_HELPER_COMMAND = `${PRODUCT_VIDEO_BRIEF_HELPER_PATH} <pack>/manifest.json`;
13185
- var createSuccessHandoff = (followthroughSummary, suggestedNextAction, suggestedSteps) => ({
13186
- followthroughSummary,
13187
- suggestedNextAction,
13188
- suggestedSteps
13189
- });
13190
- var cliExample = (command, args = "") => `npx opendevbrowser ${command}${args ? ` ${args}` : ""}`;
13191
- var quoteCliValue = (value) => JSON.stringify(value);
13192
- var GATED_PROVIDER_REASON_CODES = /* @__PURE__ */ new Set([
13193
- "auth_required",
13194
- "token_required",
13195
- "challenge_detected"
13196
- ]);
13197
- var buildResearchRerunCommand = (input, options = {}) => {
13198
- const browserMode = options.browserMode ?? input.browserMode ?? "managed";
13199
- const useCookies = options.useCookies ? " --use-cookies" : "";
13200
- const challengeMode = options.challengeAutomationMode ? ` --challenge-automation-mode ${options.challengeAutomationMode}` : "";
13201
- return cliExample(
13202
- "research run",
13203
- `--topic ${quoteCliValue(input.topic)} --days 14 --sources web,community --browser-mode ${browserMode}${useCookies}${challengeMode} --mode json --output-format json`
13204
- );
13923
+ // src/guidance/renderers.ts
13924
+ var toJsonValue2 = (value) => {
13925
+ return structuredClone(value);
13205
13926
  };
13206
- var isJsonRecord3 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
13207
- var readFailureReasonCode = (failure) => {
13208
- return failure.error.reasonCode ?? normalizeProviderReasonCode({
13209
- code: failure.error.code,
13210
- message: failure.error.message,
13211
- details: failure.error.details
13212
- }) ?? null;
13927
+ var renderWorkflowGuidance = (guidance) => {
13928
+ return toJsonValue2(guidance);
13213
13929
  };
13214
- var readDiagnosticReasonCode = (diagnostic) => {
13215
- const reasonCode = diagnostic.reasonCode ?? diagnostic.browserFallbackReasonCode;
13216
- return isProviderReasonCode(reasonCode) && GATED_PROVIDER_REASON_CODES.has(reasonCode) ? reasonCode : null;
13930
+ var renderWorkflowCompatibility = (guidance, fallbackSummary) => {
13931
+ const commandSteps = guidance.commands.map((entry) => ({
13932
+ reason: entry.label,
13933
+ command: entry.command
13934
+ }));
13935
+ const artifactSteps = guidance.artifactInputs.map((entry) => ({
13936
+ reason: `${entry.required ? "Required" : "Optional"}: ${entry.path}. ${entry.purpose}`
13937
+ }));
13938
+ const validationSteps = guidance.validationChecks.map((entry) => ({
13939
+ reason: entry.assertion ? `${entry.description} Assertion: ${entry.assertion}` : entry.description,
13940
+ ...entry.command ? { command: entry.command } : {}
13941
+ }));
13942
+ return {
13943
+ followthroughSummary: fallbackSummary ?? guidance.primaryAction.summary,
13944
+ suggestedNextAction: guidance.primaryAction.summary,
13945
+ suggestedSteps: [...commandSteps, ...artifactSteps, ...validationSteps]
13946
+ };
13217
13947
  };
13218
- var cookieDiagnosticShowsAvailableCookies = (diagnostic) => {
13219
- return diagnostic.available === true || typeof diagnostic.loaded === "number" && diagnostic.loaded > 0 || typeof diagnostic.injected === "number" && diagnostic.injected > 0 || typeof diagnostic.verifiedCount === "number" && diagnostic.verifiedCount > 0;
13948
+
13949
+ // src/guidance/readiness.ts
13950
+ var MIN_READY_REFERENCE_SCORE2 = 50;
13951
+ var MIN_READY_REFERENCE_CONFIDENCE2 = 0.5;
13952
+ var hasProviderBlocker = (context) => {
13953
+ if (context.providerUnavailable === true) return true;
13954
+ return context.reasonCode === "provider_unavailable" || context.reasonCode === "auth_required";
13955
+ };
13956
+ var hasDiagnosticOnlyEvidence = (context) => {
13957
+ const reasons = context.evidence?.diagnosticOnlyReasons ?? [];
13958
+ if (reasons.length === 0) return false;
13959
+ return (context.evidence?.rankedReferenceCount ?? 0) === 0;
13960
+ };
13961
+ var hasNoReferences = (context) => {
13962
+ return context.evidence?.referenceEvidenceRequired !== false && (context.evidence?.referenceCount ?? 0) === 0;
13963
+ };
13964
+ var hasNoRankedReferences = (context) => {
13965
+ const referenceCount = context.evidence?.referenceCount ?? 0;
13966
+ if (referenceCount === 0) return false;
13967
+ return (context.evidence?.rankedReferenceCount ?? 0) === 0;
13968
+ };
13969
+ var hasRequiredCaptureFailure = (context) => {
13970
+ if (context.evidence?.visualEvidenceRequired !== true) return false;
13971
+ return (context.evidence.failedCaptureCount ?? 0) > 0 || (context.evidence.missingScreenshotCount ?? 0) > 0;
13972
+ };
13973
+ var hasWeakTopReference = (context) => {
13974
+ const rankedCount = context.evidence?.rankedReferenceCount ?? 0;
13975
+ if (rankedCount === 0) return false;
13976
+ const score = context.evidence?.topReferenceScore ?? 0;
13977
+ const confidence = context.evidence?.topReferenceConfidence ?? 0;
13978
+ return score < MIN_READY_REFERENCE_SCORE2 || confidence < MIN_READY_REFERENCE_CONFIDENCE2;
13979
+ };
13980
+ var hasOffBriefTopReference = (context) => {
13981
+ const rankedCount = context.evidence?.rankedReferenceCount ?? 0;
13982
+ return rankedCount > 0 && context.evidence?.topReferenceIntentMatched === false;
13983
+ };
13984
+ var classifyGuidanceReadiness = (context) => {
13985
+ if (context.reasonCode === "missing_input" || context.reasonCode === "missing_params") return "needs_input";
13986
+ if (context.reasonCode === "daemon_fingerprint_mismatch") return "blocked";
13987
+ if (hasProviderBlocker(context)) return "blocked";
13988
+ if (hasDiagnosticOnlyEvidence(context)) return "diagnostic_only";
13989
+ if (hasNoReferences(context)) return "needs_recovery";
13990
+ if (hasNoRankedReferences(context)) return "needs_recovery";
13991
+ if (hasRequiredCaptureFailure(context)) return "needs_recovery";
13992
+ if (hasOffBriefTopReference(context)) return "needs_recovery";
13993
+ if (hasWeakTopReference(context)) return "needs_recovery";
13994
+ return "ready";
13220
13995
  };
13221
- var addProviderSignal = (signal, provider, reasonCode) => {
13222
- if (provider) signal.providers.push(provider);
13223
- if (reasonCode) signal.reasonCodes.push(reasonCode);
13996
+
13997
+ // src/canvas/repair-examples.ts
13998
+ var EXAMPLE_MAX_INTERACTION_LATENCY_MS = 150;
13999
+ var MAX_ISSUE_FIELD_EXAMPLES = 8;
14000
+ var EXAMPLE_CANVAS_GENERATION_PLAN = {
14001
+ targetOutcome: {
14002
+ mode: "high-fi-live-edit",
14003
+ summary: "Produce an evidence-backed, responsive landing page iteration."
14004
+ },
14005
+ visualDirection: {
14006
+ profile: "cinematic-minimal",
14007
+ themeStrategy: "single-theme"
14008
+ },
14009
+ layoutStrategy: {
14010
+ approach: "hero-led composition with clear content sections",
14011
+ navigationModel: "global-header"
14012
+ },
14013
+ contentStrategy: {
14014
+ source: "design brief, harvested references, and current project content"
14015
+ },
14016
+ componentStrategy: {
14017
+ mode: "reuse existing components before creating new primitives",
14018
+ interactionStates: ["default", "hover", "focus", "disabled"]
14019
+ },
14020
+ motionPosture: {
14021
+ level: "subtle",
14022
+ reducedMotion: "respect-user-preference"
14023
+ },
14024
+ responsivePosture: {
14025
+ primaryViewport: "desktop",
14026
+ requiredViewports: ["desktop", "tablet", "mobile"]
14027
+ },
14028
+ accessibilityPosture: {
14029
+ target: "WCAG_2_2_AA",
14030
+ keyboardNavigation: "full"
14031
+ },
14032
+ validationTargets: {
14033
+ blockOn: ["contrast-failure", "missing-intent", "missing-design-language"],
14034
+ requiredThemes: ["light"],
14035
+ browserValidation: "required",
14036
+ maxInteractionLatencyMs: EXAMPLE_MAX_INTERACTION_LATENCY_MS
14037
+ },
14038
+ interactionMoments: ["primary CTA hover", "keyboard focus ring", "mobile navigation open"],
14039
+ materialEffects: ["soft depth on primary surfaces"],
14040
+ designVectors: {
14041
+ density: "editorial",
14042
+ imagery: "dominant first-viewport visual plane"
14043
+ }
13224
14044
  };
13225
- var readFailureCookieDiagnostics = (failure) => {
13226
- const candidate = failure.error.details?.cookieDiagnostics;
13227
- return isJsonRecord3(candidate) ? candidate : null;
14045
+ var exampleIds = {
14046
+ canvasSessionId: "canvas-session-from-session-open",
14047
+ leaseId: "lease-from-session-open",
14048
+ documentId: "document-from-session-open"
13228
14049
  };
13229
- var emptyResearchGatedProviderSignal = () => ({
13230
- providers: [],
13231
- reasonCodes: [],
13232
- useCookies: false
13233
- });
13234
- var normalizeResearchGatedProviderSignal = (signal) => {
13235
- return signal.providers.length > 0 || signal.reasonCodes.length > 0 ? {
13236
- providers: [...new Set(signal.providers)].sort(),
13237
- reasonCodes: [...new Set(signal.reasonCodes)].sort(),
13238
- useCookies: signal.useCookies
13239
- } : null;
14050
+ var stringifyReceived = (value) => {
14051
+ if (typeof value === "string") return value;
14052
+ try {
14053
+ return JSON.stringify(value);
14054
+ } catch {
14055
+ return String(value);
14056
+ }
13240
14057
  };
13241
- var mergeResearchGatedProviderSignals = (signals) => {
13242
- const merged = emptyResearchGatedProviderSignal();
13243
- for (const signal of signals) {
13244
- merged.providers.push(...signal.providers);
13245
- merged.reasonCodes.push(...signal.reasonCodes);
13246
- merged.useCookies = merged.useCookies || signal.useCookies;
14058
+ var toExpectedString = (value) => {
14059
+ if (Array.isArray(value)) return value.join(" | ");
14060
+ return value;
14061
+ };
14062
+ var commandForReason = (reasonCode, blockedCommand) => {
14063
+ const retryCommand = blockedCommand && blockedCommand !== "canvas.session.attach" ? blockedCommand : "canvas.plan.set";
14064
+ if (reasonCode === "missing_canvas_session_id") return ["canvas.session.open", retryCommand];
14065
+ if (reasonCode === "missing_lease_id") return ["canvas.session.attach", retryCommand];
14066
+ if (reasonCode === "missing_document_id") return ["canvas.document.load"];
14067
+ if (reasonCode === "governance_missing") return ["canvas.document.patch", "canvas.preview.render", "canvas.document.save"];
14068
+ return ["canvas.plan.set", "canvas.plan.get"];
14069
+ };
14070
+ var titleForReason = (reasonCode) => {
14071
+ if (reasonCode === "missing_canvas_session_id") return "Open a Canvas session before running this command.";
14072
+ if (reasonCode === "missing_lease_id") return "Attach to the Canvas session and include the active leaseId.";
14073
+ if (reasonCode === "missing_document_id") return "Load a Canvas document by documentId or repoPath before continuing.";
14074
+ if (reasonCode === "governance_missing") return "Patch missing governance blocks before mutation, preview, or save.";
14075
+ if (reasonCode === "plan_required") return "Submit a valid generationPlan before mutating the Canvas document.";
14076
+ return "Repair generationPlan and resubmit canvas.plan.set.";
14077
+ };
14078
+ var labelForCommand = (command) => {
14079
+ switch (command) {
14080
+ case "canvas.session.open":
14081
+ return "Open a Canvas session";
14082
+ case "canvas.session.attach":
14083
+ return "Attach or reclaim a Canvas lease";
14084
+ case "canvas.document.load":
14085
+ return "Load the target Canvas document";
14086
+ case "canvas.document.patch":
14087
+ return "Patch missing governance";
14088
+ case "canvas.plan.get":
14089
+ return "Inspect the current plan status";
14090
+ case "canvas.plan.set":
14091
+ return "Submit a valid generationPlan";
14092
+ default:
14093
+ return command.startsWith("canvas.") ? `Retry ${command}` : "Submit a valid generationPlan";
13247
14094
  }
13248
- return merged;
13249
14095
  };
13250
- var detectResearchFailureSignals = (failures) => {
13251
- const signal = emptyResearchGatedProviderSignal();
14096
+ var shellSingleQuote = (value) => `'${value.replaceAll("'", `'"'"'`)}'`;
14097
+ var inlineParamsFlag = (params) => ` --params ${shellSingleQuote(JSON.stringify(params))}`;
14098
+ var buildCanvasSessionParamsExample = () => ({
14099
+ canvasSessionId: exampleIds.canvasSessionId,
14100
+ leaseId: exampleIds.leaseId
14101
+ });
14102
+ var cliForCommand = (command) => {
14103
+ switch (command) {
14104
+ case "canvas.session.open":
14105
+ return "npx opendevbrowser canvas --command canvas.session.open --output-format json";
14106
+ case "canvas.session.attach":
14107
+ return `npx opendevbrowser canvas --command canvas.session.attach${inlineParamsFlag(buildAttachParamsExample())} --output-format json`;
14108
+ case "canvas.document.load":
14109
+ return `npx opendevbrowser canvas --command canvas.document.load${inlineParamsFlag(buildDocumentLoadParamsExample())} --output-format json`;
14110
+ case "canvas.document.patch":
14111
+ return `npx opendevbrowser canvas --command canvas.document.patch${inlineParamsFlag(buildCanvasGovernancePatchParamsExample())} --output-format json`;
14112
+ case "canvas.plan.get":
14113
+ return `npx opendevbrowser canvas --command canvas.plan.get${inlineParamsFlag(buildCanvasSessionParamsExample())} --output-format json`;
14114
+ case "canvas.plan.set":
14115
+ return `npx opendevbrowser canvas --command canvas.plan.set${inlineParamsFlag(buildCanvasPlanSetParamsExample())} --output-format json`;
14116
+ default:
14117
+ if (command.startsWith("canvas.")) {
14118
+ return `npx opendevbrowser canvas --command ${command}${inlineParamsFlag(buildCanvasSessionParamsExample())} --output-format json`;
14119
+ }
14120
+ return `npx opendevbrowser canvas --command canvas.plan.set${inlineParamsFlag(buildCanvasPlanSetParamsExample())} --output-format json`;
14121
+ }
14122
+ };
14123
+ var commandExamples = (reasonCode, blockedCommand) => {
14124
+ const commands = commandForReason(reasonCode, blockedCommand);
14125
+ return commands.map((command) => ({
14126
+ id: command.replaceAll(".", "-"),
14127
+ label: labelForCommand(command),
14128
+ command: cliForCommand(command)
14129
+ }));
14130
+ };
14131
+ var buildCanvasPlanSetParamsExample = () => ({
14132
+ canvasSessionId: exampleIds.canvasSessionId,
14133
+ leaseId: exampleIds.leaseId,
14134
+ generationPlan: EXAMPLE_CANVAS_GENERATION_PLAN
14135
+ });
14136
+ var buildCanvasGovernancePatchParamsExample = () => ({
14137
+ canvasSessionId: exampleIds.canvasSessionId,
14138
+ leaseId: exampleIds.leaseId,
14139
+ baseRevision: 1,
14140
+ patches: [{
14141
+ op: "governance.update",
14142
+ block: "intent",
14143
+ changes: {
14144
+ summary: "Create an evidence-backed landing page iteration for the current brief.",
14145
+ audience: "Primary product or service buyers",
14146
+ task: "Understand the offer and take the primary conversion action",
14147
+ successCriteria: [
14148
+ "Hero communicates the brand and offer without relying on navigation text",
14149
+ "Primary CTA is visible and keyboard reachable",
14150
+ "Desktop, tablet, and mobile layouts preserve content hierarchy"
14151
+ ]
14152
+ }
14153
+ }]
14154
+ });
14155
+ var buildDocumentLoadParamsExample = () => ({
14156
+ canvasSessionId: exampleIds.canvasSessionId,
14157
+ leaseId: exampleIds.leaseId,
14158
+ documentId: exampleIds.documentId
14159
+ });
14160
+ var buildAttachParamsExample = () => ({
14161
+ canvasSessionId: exampleIds.canvasSessionId,
14162
+ attachMode: "lease_reclaim"
14163
+ });
14164
+ var issuePriority = (issue) => {
14165
+ if (issue.code === "invalid_value") return 0;
14166
+ if (issue.code === "invalid_type") return 1;
14167
+ return 2;
14168
+ };
14169
+ var issueFieldExamples = (issues) => {
14170
+ const prioritizedIssues = [...issues].sort((left, right) => issuePriority(left) - issuePriority(right));
14171
+ return prioritizedIssues.slice(0, MAX_ISSUE_FIELD_EXAMPLES).map((issue) => ({
14172
+ path: `generationPlan.${issue.path}`,
14173
+ description: issue.message,
14174
+ example: readExampleForIssuePath(issue.path),
14175
+ ...issue.expected ? { expected: toExpectedString(issue.expected) } : {},
14176
+ ...typeof issue.received !== "undefined" ? { received: stringifyReceived(issue.received) } : {}
14177
+ }));
14178
+ };
14179
+ var readExampleForIssuePath = (path2) => {
14180
+ const segments = path2.split(".");
14181
+ let current = EXAMPLE_CANVAS_GENERATION_PLAN;
14182
+ for (const segment of segments) {
14183
+ if (!current || typeof current !== "object" || Array.isArray(current)) return "<valid value>";
14184
+ current = current[segment] ?? "<valid value>";
14185
+ }
14186
+ return current;
14187
+ };
14188
+ var normalizeGenerationPlanPath = (path2) => {
14189
+ const trimmed = path2.trim();
14190
+ return trimmed.startsWith("generationPlan.") ? trimmed.slice("generationPlan.".length) : trimmed;
14191
+ };
14192
+ var missingFieldExamples = (missingFields) => missingFields.map(normalizeGenerationPlanPath).filter((path2) => path2.length > 0).slice(0, MAX_ISSUE_FIELD_EXAMPLES).map((path2) => ({
14193
+ path: `generationPlan.${path2}`,
14194
+ description: `Provide generationPlan.${path2} before retrying canvas.plan.set.`,
14195
+ example: readExampleForIssuePath(path2),
14196
+ expected: "valid Canvas generation plan field"
14197
+ }));
14198
+ var baseFieldExamples = (reasonCode) => {
14199
+ if (reasonCode === "missing_canvas_session_id") {
14200
+ return [{
14201
+ path: "canvasSessionId",
14202
+ description: "Use the canvasSessionId returned by canvas.session.open.",
14203
+ example: exampleIds.canvasSessionId,
14204
+ expected: "non-empty string"
14205
+ }];
14206
+ }
14207
+ if (reasonCode === "missing_lease_id") {
14208
+ return [{
14209
+ path: "leaseId",
14210
+ description: "Use the active leaseId returned by canvas.session.open or canvas.session.attach.",
14211
+ example: exampleIds.leaseId,
14212
+ expected: "non-empty string"
14213
+ }];
14214
+ }
14215
+ if (reasonCode === "missing_document_id") {
14216
+ return [{
14217
+ path: "documentId",
14218
+ description: "Use documentId when loading a persisted Canvas document. Use repoPath instead when loading by file path.",
14219
+ example: exampleIds.documentId,
14220
+ expected: "non-empty string"
14221
+ }];
14222
+ }
14223
+ return [{
14224
+ path: "designGovernance.intent",
14225
+ description: "Patch intent before save or downstream handoff when governance warnings report missing intent.",
14226
+ example: {
14227
+ summary: "Create an evidence-backed landing page iteration for the current brief.",
14228
+ audience: "Primary product or service buyers",
14229
+ task: "Understand the offer and take the primary conversion action"
14230
+ }
14231
+ }];
14232
+ };
14233
+ var chooseFieldExamples = (reasonCode, issues, missingFields) => {
14234
+ const issueExamples = issueFieldExamples(issues);
14235
+ if (issueExamples.length > 0) return issueExamples;
14236
+ const missingExamples = missingFieldExamples(missingFields);
14237
+ if (missingExamples.length > 0) return missingExamples;
14238
+ return baseFieldExamples(reasonCode);
14239
+ };
14240
+ var paramsForCommand = (command) => {
14241
+ switch (command) {
14242
+ case "canvas.session.attach":
14243
+ return buildAttachParamsExample();
14244
+ case "canvas.document.load":
14245
+ return buildDocumentLoadParamsExample();
14246
+ case "canvas.document.patch":
14247
+ return buildCanvasGovernancePatchParamsExample();
14248
+ case "canvas.plan.get":
14249
+ return buildCanvasSessionParamsExample();
14250
+ case "canvas.plan.set":
14251
+ return buildCanvasPlanSetParamsExample();
14252
+ default:
14253
+ return command.startsWith("canvas.") ? buildCanvasSessionParamsExample() : null;
14254
+ }
14255
+ };
14256
+ var paramsExamples = (reasonCode, blockedCommand) => {
14257
+ const examples = [];
14258
+ if (reasonCode === "missing_lease_id") {
14259
+ examples.push({
14260
+ id: "canvas-attach-request",
14261
+ label: "Attach or reclaim a session lease",
14262
+ command: "canvas.session.attach",
14263
+ params: buildAttachParamsExample()
14264
+ });
14265
+ const blockedParams = blockedCommand ? paramsForCommand(blockedCommand) : null;
14266
+ if (blockedCommand && blockedCommand !== "canvas.session.attach" && blockedParams) {
14267
+ examples.push({
14268
+ id: `${blockedCommand.replaceAll(".", "-")}-request`,
14269
+ label: `Valid ${blockedCommand} params after lease recovery`,
14270
+ command: blockedCommand,
14271
+ params: blockedParams
14272
+ });
14273
+ return examples;
14274
+ }
14275
+ }
14276
+ if (reasonCode === "missing_document_id") {
14277
+ examples.push({
14278
+ id: "canvas-document-load-request",
14279
+ label: "Load a document by id",
14280
+ command: "canvas.document.load",
14281
+ params: buildDocumentLoadParamsExample()
14282
+ });
14283
+ return examples;
14284
+ }
14285
+ examples.push({
14286
+ id: "canvas-plan-set-request",
14287
+ label: "Valid canvas.plan.set params",
14288
+ command: "canvas.plan.set",
14289
+ params: buildCanvasPlanSetParamsExample()
14290
+ });
14291
+ if (reasonCode === "governance_missing") {
14292
+ examples.push({
14293
+ id: "canvas-governance-intent-patch",
14294
+ label: "Patch missing intent governance",
14295
+ command: "canvas.document.patch",
14296
+ params: buildCanvasGovernancePatchParamsExample()
14297
+ });
14298
+ }
14299
+ return examples;
14300
+ };
14301
+ var validationChecks = (reasonCode) => {
14302
+ const checks = [{
14303
+ id: "session-opened",
14304
+ description: "canvas.session.open or canvas.session.attach returns active ids before command retry.",
14305
+ assertion: 'typeof canvasSessionId === "string" && typeof leaseId === "string"'
14306
+ }];
14307
+ if (reasonCode !== "missing_document_id") {
14308
+ checks.push({
14309
+ id: "plan-valid",
14310
+ description: "generationPlan passes Canvas validation.",
14311
+ assertion: "validateGenerationPlan(generationPlan).ok === true"
14312
+ });
14313
+ } else {
14314
+ checks.push({
14315
+ id: "document-target-selected",
14316
+ description: "documentId or repoPath is present before loading a Canvas document.",
14317
+ assertion: 'typeof documentId === "string" || typeof repoPath === "string"'
14318
+ });
14319
+ }
14320
+ if (reasonCode === "governance_missing") {
14321
+ checks.push({
14322
+ id: "intent-present",
14323
+ description: "intent governance block is present after canvas.document.patch.",
14324
+ assertion: "designGovernance.intent is present"
14325
+ });
14326
+ }
14327
+ return checks;
14328
+ };
14329
+ var doNotProceedIf = (reasonCode) => {
14330
+ const blockers = [
14331
+ "canvasSessionId is missing or stale",
14332
+ "leaseId is missing or no longer active"
14333
+ ];
14334
+ if (reasonCode !== "missing_document_id") {
14335
+ blockers.push("generationPlan validation still reports missing or invalid fields");
14336
+ } else {
14337
+ blockers.push("documentId and repoPath are both missing");
14338
+ }
14339
+ if (reasonCode === "governance_missing") {
14340
+ blockers.push("intent or other required governance blocks are still missing");
14341
+ }
14342
+ return blockers;
14343
+ };
14344
+ var buildCanvasRepairGuidance = (input) => {
14345
+ const fields = chooseFieldExamples(input.reasonCode, input.issues ?? [], input.missingFields ?? []);
14346
+ const readiness = input.reasonCode === "governance_missing" ? "needs_recovery" : "needs_input";
14347
+ const severity = input.reasonCode === "governance_missing" ? "warning" : "blocked";
14348
+ return {
14349
+ id: `canvas.${input.reasonCode}`,
14350
+ recipeType: "schema_repair",
14351
+ workflow: "canvas",
14352
+ severity,
14353
+ readiness,
14354
+ reasonCode: input.reasonCode,
14355
+ primaryAction: {
14356
+ id: "repair_canvas_request",
14357
+ label: "Repair Canvas command params",
14358
+ summary: input.message ?? titleForReason(input.reasonCode)
14359
+ },
14360
+ commands: commandExamples(input.reasonCode, input.blockedCommand),
14361
+ paramsExamples: paramsExamples(input.reasonCode, input.blockedCommand),
14362
+ fieldExamples: fields,
14363
+ artifactInputs: [],
14364
+ validationChecks: validationChecks(input.reasonCode),
14365
+ fallbackPolicy: {
14366
+ allowed: false,
14367
+ requiresUserConfirmation: true,
14368
+ reason: "Do not skip Canvas validation or governance gates. Repair the typed command payload first."
14369
+ },
14370
+ doNotProceedIf: doNotProceedIf(input.reasonCode)
14371
+ };
14372
+ };
14373
+ var buildCanvasRepairEnvelope = (input) => {
14374
+ const guidance = buildCanvasRepairGuidance(input);
14375
+ const recommendedNextCommands = commandForReason(input.reasonCode, input.blockedCommand);
14376
+ const message = input.message ?? guidance.primaryAction.summary;
14377
+ const guidancePayload = {
14378
+ recommendedNextCommands,
14379
+ reason: message,
14380
+ nextStepGuidance: renderWorkflowGuidance(guidance),
14381
+ paramsExamples: guidance.paramsExamples,
14382
+ fieldExamples: guidance.fieldExamples,
14383
+ validationChecks: guidance.validationChecks,
14384
+ doNotProceedIf: guidance.doNotProceedIf
14385
+ };
14386
+ return {
14387
+ code: input.reasonCode,
14388
+ message,
14389
+ recommendedNextCommands,
14390
+ guidance: guidancePayload,
14391
+ nextStepGuidance: guidancePayload.nextStepGuidance,
14392
+ paramsExamples: guidancePayload.paramsExamples,
14393
+ fieldExamples: guidancePayload.fieldExamples,
14394
+ validationChecks: guidancePayload.validationChecks,
14395
+ doNotProceedIf: guidancePayload.doNotProceedIf
14396
+ };
14397
+ };
14398
+ var missingIdentifierReasonCode = (field) => {
14399
+ if (field === "canvasSessionId") return "missing_canvas_session_id";
14400
+ if (field === "leaseId") return "missing_lease_id";
14401
+ return "missing_document_id";
14402
+ };
14403
+ var SESSION_REQUIRED_COMMANDS = /* @__PURE__ */ new Set([
14404
+ "canvas.session.attach",
14405
+ "canvas.session.status",
14406
+ "canvas.session.close",
14407
+ "canvas.capabilities.get",
14408
+ "canvas.plan.set",
14409
+ "canvas.plan.get",
14410
+ "canvas.document.load",
14411
+ "canvas.document.import",
14412
+ "canvas.document.patch",
14413
+ "canvas.history.undo",
14414
+ "canvas.history.redo",
14415
+ "canvas.document.save",
14416
+ "canvas.document.export",
14417
+ "canvas.inventory.list",
14418
+ "canvas.inventory.insert",
14419
+ "canvas.starter.apply",
14420
+ "canvas.tab.open",
14421
+ "canvas.tab.close",
14422
+ "canvas.overlay.mount",
14423
+ "canvas.overlay.unmount",
14424
+ "canvas.overlay.select",
14425
+ "canvas.preview.render",
14426
+ "canvas.preview.refresh",
14427
+ "canvas.feedback.poll",
14428
+ "canvas.feedback.subscribe",
14429
+ "canvas.feedback.next",
14430
+ "canvas.feedback.unsubscribe",
14431
+ "canvas.code.bind",
14432
+ "canvas.code.unbind",
14433
+ "canvas.code.pull",
14434
+ "canvas.code.push",
14435
+ "canvas.code.status",
14436
+ "canvas.code.resolve"
14437
+ ]);
14438
+ var requiresCanvasSessionId = (command) => SESSION_REQUIRED_COMMANDS.has(command);
14439
+ var LEASE_REQUIRED_COMMANDS = /* @__PURE__ */ new Set([
14440
+ "canvas.session.close",
14441
+ "canvas.plan.set",
14442
+ "canvas.plan.get",
14443
+ "canvas.document.load",
14444
+ "canvas.document.import",
14445
+ "canvas.document.patch",
14446
+ "canvas.history.undo",
14447
+ "canvas.history.redo",
14448
+ "canvas.document.save",
14449
+ "canvas.document.export",
14450
+ "canvas.inventory.insert",
14451
+ "canvas.starter.apply",
14452
+ "canvas.tab.open",
14453
+ "canvas.tab.close",
14454
+ "canvas.overlay.mount",
14455
+ "canvas.overlay.unmount",
14456
+ "canvas.overlay.select",
14457
+ "canvas.preview.render",
14458
+ "canvas.preview.refresh",
14459
+ "canvas.code.bind",
14460
+ "canvas.code.unbind",
14461
+ "canvas.code.pull",
14462
+ "canvas.code.push",
14463
+ "canvas.code.resolve"
14464
+ ]);
14465
+ var requiresLeaseId = (command) => LEASE_REQUIRED_COMMANDS.has(command);
14466
+ var missingString = (params, field) => {
14467
+ const value = params[field];
14468
+ return typeof value !== "string" || value.trim().length === 0;
14469
+ };
14470
+ var buildCanvasCommandValidationEnvelope = (command, params) => {
14471
+ if (requiresCanvasSessionId(command) && missingString(params, "canvasSessionId")) {
14472
+ return buildCanvasMissingIdentifierEnvelope("canvasSessionId", command);
14473
+ }
14474
+ if (requiresLeaseId(command) && missingString(params, "leaseId")) {
14475
+ return buildCanvasMissingIdentifierEnvelope("leaseId", command);
14476
+ }
14477
+ const repoPath = params.repoPath;
14478
+ const hasRepoPath = typeof repoPath === "string" && repoPath.trim().length > 0;
14479
+ if (command === "canvas.document.load" && missingString(params, "documentId") && !hasRepoPath) {
14480
+ return buildCanvasMissingIdentifierEnvelope("documentId", command);
14481
+ }
14482
+ return null;
14483
+ };
14484
+ var buildCanvasMissingIdentifierEnvelope = (field, blockedCommand) => {
14485
+ const reasonCode = missingIdentifierReasonCode(field);
14486
+ return buildCanvasRepairEnvelope({
14487
+ reasonCode,
14488
+ ...blockedCommand ? { blockedCommand } : {},
14489
+ message: `Missing ${field}. ${titleForReason(reasonCode)}`
14490
+ });
14491
+ };
14492
+
14493
+ // src/guidance/recipes/generic.ts
14494
+ var quote = (value) => JSON.stringify(value);
14495
+ var DAEMON_STATUS_PREFLIGHT_COMMAND = "opendevbrowser status --daemon --output-format json";
14496
+ var DAEMON_FINGERPRINT_CURRENT_ASSERTION = "data.fingerprintCurrent === true";
14497
+ var DEFAULT_INSPIREDESIGN_BRIEF = "Digital photography studio landing page";
14498
+ var DEFAULT_INSPIREDESIGN_QUERY = "cinematic photography studio landing page inspiration";
14499
+ var DEFAULT_RESEARCH_TOPIC = "browser automation provider recovery";
14500
+ var DEFAULT_PROVIDER = "provider diagnostics";
14501
+ var isCanvasGenerationPlanIssue = (value) => {
14502
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
14503
+ const record = value;
14504
+ return typeof record.path === "string" && typeof record.message === "string" && typeof record.code === "string";
14505
+ };
14506
+ var canvasGenerationPlanIssues = (value) => Array.isArray(value) ? value.filter(isCanvasGenerationPlanIssue) : [];
14507
+ var isPinterestProvider = (provider) => provider === "social/pinterest" || provider === "pinterest";
14508
+ var isPinterestOnlyContext = (context) => {
14509
+ const providers = context.requestedProviders ?? [];
14510
+ return providers.length === 0 || providers.every(isPinterestProvider);
14511
+ };
14512
+ var selectedInspiredesignProvider = (context) => {
14513
+ const providers = context.requestedProviders ?? [];
14514
+ const nonPinterestProvider = providers.find((provider) => !isPinterestProvider(provider));
14515
+ if (!isPinterestOnlyContext(context) && nonPinterestProvider) return nonPinterestProvider;
14516
+ return providers[0] ?? context.siteRecipeId ?? "web/default";
14517
+ };
14518
+ var selectedProviderIsPinterest = (context) => isPinterestProvider(selectedInspiredesignProvider(context));
14519
+ var isPinterestScopedRecovery = (context) => context.siteRecipeId === "social/pinterest" && isPinterestOnlyContext(context);
14520
+ var inspiredesignBrowserMode = (context) => selectedProviderIsPinterest(context) ? "extension" : context.browserMode ?? "managed";
14521
+ var inspiredesignCookieFlags = (context) => {
14522
+ if (selectedProviderIsPinterest(context)) return " --use-cookies --cookie-policy required";
14523
+ return context.useCookies === true ? " --use-cookies" : "";
14524
+ };
14525
+ var inspiredesignHarvestCommand = (context) => {
14526
+ const brief = typeof context.details?.brief === "string" ? context.details.brief : DEFAULT_INSPIREDESIGN_BRIEF;
14527
+ const query = context.query ?? DEFAULT_INSPIREDESIGN_QUERY;
14528
+ const provider = selectedInspiredesignProvider(context);
14529
+ const browserMode = inspiredesignBrowserMode(context);
14530
+ const cookieFlags = inspiredesignCookieFlags(context);
14531
+ return {
14532
+ id: "inspiredesign-harvest-rerun",
14533
+ label: "Rerun Inspired Design harvest with explicit evidence settings",
14534
+ command: `npx opendevbrowser inspiredesign harvest --brief ${quote(brief)} --query ${quote(query)} --provider ${provider} --max-references 5 --visual-evidence required --browser-mode ${browserMode}${cookieFlags} --challenge-automation-mode browser_with_helper --mode json --output-format json`
14535
+ };
14536
+ };
14537
+ var canvasSessionOpenCommand = {
14538
+ id: "canvas-session-open",
14539
+ label: "Open a Canvas session before submitting the plan",
14540
+ command: "npx opendevbrowser canvas --command canvas.session.open --output-format json"
14541
+ };
14542
+ var canvasPlanSetCommand = {
14543
+ id: "canvas-plan-set",
14544
+ label: "Submit the generated Canvas plan request after filling ids",
14545
+ command: "npx opendevbrowser canvas --command canvas.plan.set --params-file ./canvas-plan.request.json --output-format json"
14546
+ };
14547
+ var defaultFallbackPolicy = {
14548
+ allowed: false,
14549
+ requiresUserConfirmation: true,
14550
+ reason: "Do not widen provider or source scope without user confirmation."
14551
+ };
14552
+ var inspiredesignArtifacts = [
14553
+ { path: "advanced-brief.md", purpose: "Review the reference-first brief before design or implementation.", required: true },
14554
+ { path: "ranked-references.json", purpose: "Verify ranked evidence quality and rejected diagnostics.", required: true },
14555
+ { path: "visual-evidence.json", purpose: "Confirm screenshot metadata and warnings.", required: true },
14556
+ { path: "screenshot-index.json", purpose: "Confirm screenshot artifact paths exist before visual claims.", required: true }
14557
+ ];
14558
+ var requiresInspiredesignReferenceEvidence = (context) => context.evidence?.referenceEvidenceRequired !== false;
14559
+ var notReadyInspiredesignReasonCode = (context) => context.evidence?.topReferenceIntentMatched === false ? "off_brief_reference" : "weak_reference";
14560
+ var notReadyInspiredesignSummary = (reasonCode) => reasonCode === "off_brief_reference" ? "The workflow requested a design-ready handoff, but the top ranked reference is off brief for Canvas continuation." : "The workflow requested a design-ready handoff, but the evidence does not meet the ready threshold for Canvas continuation.";
14561
+ var buildReadyInspiredesignGuidance = (context, readiness) => {
14562
+ if (readiness !== "ready") {
14563
+ const reasonCode = notReadyInspiredesignReasonCode(context);
14564
+ return buildEvidenceRecoveryGuidance(
14565
+ context,
14566
+ readiness,
14567
+ reasonCode,
14568
+ reasonCode === "off_brief_reference" ? "Replace off-brief reference evidence" : "Strengthen reference evidence before Canvas",
14569
+ notReadyInspiredesignSummary(reasonCode)
14570
+ );
14571
+ }
14572
+ const referenceEvidenceRequired = requiresInspiredesignReferenceEvidence(context);
14573
+ const artifactInputs = referenceEvidenceRequired ? [...inspiredesignArtifacts, { path: "canvas-plan.request.json", purpose: "Runtime request body for canvas.plan.set.", required: true }] : [
14574
+ { path: "advanced-brief.md", purpose: "Review the brief-expanded design direction before Canvas.", required: true },
14575
+ { path: "design-contract.json", purpose: "Use the brief-derived Canvas governance contract.", required: true },
14576
+ { path: "canvas-plan.request.json", purpose: "Runtime request body for canvas.plan.set.", required: true }
14577
+ ];
14578
+ const validationChecks2 = referenceEvidenceRequired ? [{
14579
+ id: "plan-accepted",
14580
+ description: "canvas.plan.set returns planStatus=accepted before document mutation.",
14581
+ assertion: 'planStatus === "accepted"'
14582
+ }] : [{
14583
+ id: "brief-contract-accepted",
14584
+ description: "canvas.plan.set accepts the generated brief-only generationPlan before document mutation.",
14585
+ assertion: 'planStatus === "accepted"'
14586
+ }];
14587
+ const doNotProceedIf2 = referenceEvidenceRequired ? [
14588
+ "rankedReferences is empty",
14589
+ "screenshot paths are missing when visual evidence was required",
14590
+ "planStatus is not accepted"
14591
+ ] : [
14592
+ "advanced-brief.md or design-contract.json is missing",
14593
+ "planStatus is not accepted"
14594
+ ];
14595
+ return {
14596
+ id: "inspiredesign.canvas_ready_handoff",
14597
+ recipeType: "artifact_handoff",
14598
+ workflow: "inspiredesign",
14599
+ severity: "info",
14600
+ readiness,
14601
+ reasonCode: "design_ready",
14602
+ primaryAction: {
14603
+ id: "continue_in_canvas",
14604
+ label: "Continue in Canvas",
14605
+ summary: "Read the generated artifacts, open a Canvas session, fill canvas-plan.request.json ids, then submit canvas.plan.set."
14606
+ },
14607
+ commands: [canvasSessionOpenCommand, canvasPlanSetCommand],
14608
+ paramsExamples: [{
14609
+ id: "canvas-plan-request-ids",
14610
+ label: "Canvas plan request id placeholders to fill",
14611
+ command: "canvas.plan.set",
14612
+ params: {
14613
+ canvasSessionId: "<canvasSessionId from canvas.session.open>",
14614
+ leaseId: "<leaseId from canvas.session.open>",
14615
+ generationPlan: "<keep generated generationPlan object unchanged>"
14616
+ }
14617
+ }],
14618
+ fieldExamples: [{
14619
+ path: "intent",
14620
+ description: "Patch emitted governance blocks from design-contract.json after plan acceptance.",
14621
+ example: { audience: "Primary user", task: "Complete the design goal", successCriteria: ["Evidence-backed design direction is implemented"] }
14622
+ }],
14623
+ artifactInputs,
14624
+ validationChecks: validationChecks2,
14625
+ fallbackPolicy: {
14626
+ allowed: true,
14627
+ requiresUserConfirmation: false,
14628
+ reason: referenceEvidenceRequired ? "Canvas continuation is allowed because ranked reference evidence is ready." : "Canvas continuation is allowed because this brief-only run did not require reference evidence."
14629
+ },
14630
+ doNotProceedIf: doNotProceedIf2
14631
+ };
14632
+ };
14633
+ var buildDaemonFingerprintMismatchGuidance = (readiness) => ({
14634
+ id: "daemon.fingerprint_mismatch",
14635
+ recipeType: "workflow_entry",
14636
+ workflow: "daemon",
14637
+ severity: "blocked",
14638
+ readiness,
14639
+ reasonCode: "daemon_fingerprint_mismatch",
14640
+ primaryAction: {
14641
+ id: "verify_daemon_fingerprint",
14642
+ label: "Verify daemon fingerprint",
14643
+ summary: "Run the daemon status preflight and continue only when the running daemon matches the current opendevbrowser build."
14644
+ },
14645
+ commands: [{
14646
+ id: "daemon-status-preflight",
14647
+ label: "Check daemon fingerprint freshness",
14648
+ command: DAEMON_STATUS_PREFLIGHT_COMMAND
14649
+ }],
14650
+ paramsExamples: [],
14651
+ fieldExamples: [{
14652
+ path: "data.fingerprintCurrent",
14653
+ description: "The daemon status response must report the current build fingerprint.",
14654
+ example: true,
14655
+ expected: "true"
14656
+ }],
14657
+ artifactInputs: [],
14658
+ validationChecks: [{
14659
+ id: "fingerprint-current",
14660
+ description: "Daemon status confirms the binary and daemon fingerprint match.",
14661
+ assertion: DAEMON_FINGERPRINT_CURRENT_ASSERTION,
14662
+ command: DAEMON_STATUS_PREFLIGHT_COMMAND
14663
+ }],
14664
+ fallbackPolicy: {
14665
+ allowed: true,
14666
+ requiresUserConfirmation: false,
14667
+ reason: "Use the matching binary, restart the daemon from the current install, or isolate config, cache, daemon port, and relay port."
14668
+ },
14669
+ doNotProceedIf: [
14670
+ "data.fingerprintCurrent is false or missing",
14671
+ "the daemon is still running a different opendevbrowser build"
14672
+ ]
14673
+ });
14674
+ var buildResearchGatedProviderGuidance = (context, readiness) => {
14675
+ const topic = typeof context.details?.topic === "string" ? context.details.topic : DEFAULT_RESEARCH_TOPIC;
14676
+ const browserMode = context.browserMode ?? "extension";
14677
+ const cookieFlag = context.useCookies === true ? " --use-cookies" : "";
14678
+ const providers = context.requestedProviders?.length ? context.requestedProviders.join(", ") : "gated providers";
14679
+ return {
14680
+ id: "research.gated_provider_recovery",
14681
+ recipeType: "evidence_recovery",
14682
+ workflow: "research",
14683
+ severity: "warning",
14684
+ readiness,
14685
+ reasonCode: "gated_provider",
14686
+ primaryAction: {
14687
+ id: "recover_gated_provider_evidence",
14688
+ label: "Recover gated provider evidence",
14689
+ summary: `Inspect gated-provider diagnostics for ${providers}, then rerun research with a user-authorized signed-in browser session before publishing claims.`
14690
+ },
14691
+ commands: [{
14692
+ id: "research-gated-provider-rerun",
14693
+ label: "Rerun research with browser-scoped provider recovery",
14694
+ command: `npx opendevbrowser research run --topic ${quote(topic)} --days 14 --sources web,community --browser-mode ${browserMode}${cookieFlag} --challenge-automation-mode browser_with_helper --mode json --output-format json`
14695
+ }],
14696
+ paramsExamples: [{
14697
+ id: "research-gated-provider-input",
14698
+ label: "Research gated-provider retry input",
14699
+ params: {
14700
+ topic,
14701
+ browserMode,
14702
+ useCookies: context.useCookies === true,
14703
+ challengeAutomationMode: "browser_with_helper",
14704
+ providers
14705
+ }
14706
+ }],
14707
+ fieldExamples: [{
14708
+ path: "meta.failures[].error.reasonCode",
14709
+ description: "Gated provider failures should identify auth or challenge reason codes before retry.",
14710
+ example: "auth_required"
14711
+ }],
14712
+ artifactInputs: [
14713
+ { path: "records.json", purpose: "Confirm destination records support claims.", required: true },
14714
+ { path: "context.json", purpose: "Inspect source and timebox context.", required: true },
14715
+ { path: "meta.json", purpose: "Review failures, cookie diagnostics, and challenge orchestration metadata.", required: true },
14716
+ { path: "report.md", purpose: "Publish only claims supported by accepted records.", required: true }
14717
+ ],
14718
+ validationChecks: [
14719
+ { id: "signed-in-session", description: "Provider auth or challenge state has been resolved in the browser session." },
14720
+ { id: "records-supported", description: "Final claims are supported by destination records, not SERP snippets." }
14721
+ ],
14722
+ fallbackPolicy: {
14723
+ allowed: false,
14724
+ requiresUserConfirmation: true,
14725
+ reason: "Do not switch sources or publish unsupported claims without user approval."
14726
+ },
14727
+ doNotProceedIf: [
14728
+ "gated provider failures remain unresolved",
14729
+ "records.json lacks destination evidence for the claim",
14730
+ "cookie or challenge recovery has not been user-authorized"
14731
+ ]
14732
+ };
14733
+ };
14734
+ var buildProviderWorkflowGuidance = (context, readiness) => {
14735
+ const providers = context.requestedProviders?.join(", ") || DEFAULT_PROVIDER;
14736
+ const reasonCode = context.reasonCode ?? "provider_recovery";
14737
+ return {
14738
+ id: `provider.${reasonCode}`,
14739
+ recipeType: "evidence_recovery",
14740
+ workflow: "provider",
14741
+ severity: readiness === "blocked" ? "blocked" : "warning",
14742
+ readiness,
14743
+ reasonCode,
14744
+ primaryAction: {
14745
+ id: "inspect_provider_diagnostics",
14746
+ label: "Inspect provider diagnostics",
14747
+ summary: "Use the typed failure details to resolve auth, challenge, availability, or evidence-quality blockers before widening provider scope."
14748
+ },
14749
+ commands: [{
14750
+ id: "provider-diagnostic-rerun",
14751
+ label: "Show executable workflow help before rerunning",
14752
+ command: "npx opendevbrowser help"
14753
+ }],
14754
+ paramsExamples: [{
14755
+ id: "provider-recovery-input",
14756
+ label: "Provider recovery input",
14757
+ params: {
14758
+ providers,
14759
+ reasonCode,
14760
+ browserMode: context.browserMode ?? "extension",
14761
+ useCookies: context.useCookies === true
14762
+ }
14763
+ }],
14764
+ fieldExamples: [{
14765
+ path: "meta.failures[].error.reasonCode",
14766
+ description: "Use the provider reason code to choose auth, challenge, availability, or evidence recovery.",
14767
+ example: reasonCode
14768
+ }],
14769
+ artifactInputs: [
14770
+ { path: "meta.json", purpose: "Inspect provider diagnostics and reason codes.", required: true },
14771
+ { path: "records.json", purpose: "Confirm accepted destination records before using results.", required: true }
14772
+ ],
14773
+ validationChecks: [{
14774
+ id: "provider-evidence-ready",
14775
+ description: "At least one accepted record supports the workflow output before proceeding."
14776
+ }],
14777
+ fallbackPolicy: defaultFallbackPolicy,
14778
+ doNotProceedIf: [
14779
+ "provider failure reason codes remain unresolved",
14780
+ "accepted records are empty",
14781
+ "the requested provider scope would be widened without user confirmation"
14782
+ ]
14783
+ };
14784
+ };
14785
+ var buildCliValidationGuidance = (context, readiness) => {
14786
+ const reasonCode = context.reasonCode ?? "validation_error";
14787
+ return {
14788
+ id: `cli.${reasonCode}`,
14789
+ recipeType: "schema_repair",
14790
+ workflow: "cli",
14791
+ severity: "blocked",
14792
+ readiness,
14793
+ reasonCode,
14794
+ primaryAction: {
14795
+ id: "repair_cli_arguments",
14796
+ label: "Repair CLI arguments",
14797
+ summary: "Use the command help and typed error details to rerun with valid flags, params, and output mode."
14798
+ },
14799
+ commands: [{
14800
+ id: "cli-help",
14801
+ label: "Show command help",
14802
+ command: "npx opendevbrowser help"
14803
+ }],
14804
+ paramsExamples: [{
14805
+ id: "cli-validation-input",
14806
+ label: "CLI validation retry",
14807
+ params: {
14808
+ reasonCode,
14809
+ outputFormat: "json"
14810
+ }
14811
+ }],
14812
+ fieldExamples: [{
14813
+ path: "error.reasonCode",
14814
+ description: "The reason code identifies which CLI argument or params field must be repaired.",
14815
+ example: reasonCode
14816
+ }],
14817
+ artifactInputs: [],
14818
+ validationChecks: [{
14819
+ id: "json-output",
14820
+ description: "Rerun the command with --output-format json and verify the response has no validation errors."
14821
+ }],
14822
+ fallbackPolicy: {
14823
+ allowed: true,
14824
+ requiresUserConfirmation: false,
14825
+ reason: "Help output and typed examples are the supported recovery path for invalid CLI input."
14826
+ },
14827
+ doNotProceedIf: [
14828
+ "the command still returns validation errors",
14829
+ "required params are missing or empty"
14830
+ ]
14831
+ };
14832
+ };
14833
+ var buildEvidenceRecoveryGuidance = (context, readiness, reasonCode, actionLabel, actionSummary) => ({
14834
+ id: `inspiredesign.harvest.${reasonCode}`,
14835
+ recipeType: "evidence_recovery",
14836
+ workflow: "inspiredesign",
14837
+ severity: readiness === "blocked" ? "blocked" : "warning",
14838
+ readiness,
14839
+ reasonCode,
14840
+ primaryAction: {
14841
+ id: "recover_reference_evidence",
14842
+ label: actionLabel,
14843
+ summary: actionSummary
14844
+ },
14845
+ commands: [inspiredesignHarvestCommand(context)],
14846
+ paramsExamples: [{
14847
+ id: "explicit-reference-url-recovery",
14848
+ label: "Use explicit high-quality visual references when provider discovery is blocked",
14849
+ params: {
14850
+ brief: typeof context.details?.brief === "string" ? context.details.brief : DEFAULT_INSPIREDESIGN_BRIEF,
14851
+ urls: ["https://example.com/usable-reference"],
14852
+ visualEvidence: "required",
14853
+ browserMode: inspiredesignBrowserMode(context),
14854
+ ...selectedProviderIsPinterest(context) ? { useCookies: true, cookiePolicy: "required" } : {}
14855
+ }
14856
+ }],
14857
+ fieldExamples: [],
14858
+ artifactInputs: inspiredesignArtifacts.map((artifact) => ({ ...artifact, required: false })),
14859
+ validationChecks: [
14860
+ { id: "ranked-reference-count", description: "At least one ranked reference is present.", assertion: "rankedReferences.length > 0" },
14861
+ { id: "reference-score", description: "The top reference score meets the ready threshold.", assertion: "topReferenceScore >= 50" },
14862
+ { id: "reference-intent", description: "The top ranked reference overlaps the requested brief intent.", assertion: "topReferenceIntentMatched === true" },
14863
+ { id: "visual-artifact", description: "Required visual evidence has finalized screenshot paths.", assertion: "missingScreenshotCount === 0" }
14864
+ ],
14865
+ fallbackPolicy: defaultFallbackPolicy,
14866
+ doNotProceedIf: [
14867
+ "reference_count is 0",
14868
+ "rankedReferences is empty",
14869
+ "top ranked reference is diagnostic-only or off brief",
14870
+ "required visual evidence is missing or failed"
14871
+ ]
14872
+ });
14873
+ var genericGuidanceRecipes = [
14874
+ {
14875
+ id: "provider.generic_recovery",
14876
+ recipeType: "evidence_recovery",
14877
+ workflow: "provider",
14878
+ priority: 130,
14879
+ reasonCode: "provider_recovery",
14880
+ matches: (context) => context.workflow === "provider",
14881
+ build: buildProviderWorkflowGuidance
14882
+ },
14883
+ {
14884
+ id: "cli.validation_recovery",
14885
+ recipeType: "schema_repair",
14886
+ workflow: "cli",
14887
+ priority: 125,
14888
+ reasonCode: "validation_error",
14889
+ matches: (context) => context.workflow === "cli",
14890
+ build: buildCliValidationGuidance
14891
+ },
14892
+ {
14893
+ id: "daemon.fingerprint_mismatch",
14894
+ recipeType: "workflow_entry",
14895
+ workflow: "daemon",
14896
+ priority: 120,
14897
+ reasonCode: "daemon_fingerprint_mismatch",
14898
+ matches: (context) => context.workflow === "daemon" && context.reasonCode === "daemon_fingerprint_mismatch",
14899
+ build: (_context, readiness) => buildDaemonFingerprintMismatchGuidance(readiness)
14900
+ },
14901
+ {
14902
+ id: "research.gated_provider",
14903
+ recipeType: "evidence_recovery",
14904
+ workflow: "research",
14905
+ priority: 110,
14906
+ reasonCode: "gated_provider",
14907
+ matches: (context) => context.workflow === "research" && context.reasonCode === "gated_provider",
14908
+ build: buildResearchGatedProviderGuidance
14909
+ },
14910
+ {
14911
+ id: "canvas.generation_plan_invalid",
14912
+ recipeType: "schema_repair",
14913
+ workflow: "canvas",
14914
+ priority: 100,
14915
+ reasonCode: "generation_plan_invalid",
14916
+ matches: (context) => context.workflow === "canvas" && context.reasonCode === "generation_plan_invalid",
14917
+ build: (context) => buildCanvasRepairGuidance({
14918
+ reasonCode: "generation_plan_invalid",
14919
+ missingFields: Array.isArray(context.details?.missingFields) ? context.details.missingFields.filter((field) => typeof field === "string") : [],
14920
+ issues: canvasGenerationPlanIssues(context.details?.issues)
14921
+ })
14922
+ },
14923
+ {
14924
+ id: "canvas.plan_required",
14925
+ recipeType: "schema_repair",
14926
+ workflow: "canvas",
14927
+ priority: 90,
14928
+ reasonCode: "plan_required",
14929
+ matches: (context) => context.workflow === "canvas" && context.reasonCode === "plan_required",
14930
+ build: () => buildCanvasRepairGuidance({ reasonCode: "plan_required" })
14931
+ },
14932
+ {
14933
+ id: "canvas.governance_missing",
14934
+ recipeType: "schema_repair",
14935
+ workflow: "canvas",
14936
+ priority: 80,
14937
+ reasonCode: "governance_missing",
14938
+ matches: (context) => context.workflow === "canvas" && context.reasonCode === "governance_missing",
14939
+ build: () => buildCanvasRepairGuidance({ reasonCode: "governance_missing" })
14940
+ },
14941
+ {
14942
+ id: "canvas.missing_canvas_session_id",
14943
+ recipeType: "schema_repair",
14944
+ workflow: "canvas",
14945
+ priority: 70,
14946
+ reasonCode: "missing_canvas_session_id",
14947
+ matches: (context) => context.workflow === "canvas" && context.reasonCode === "missing_canvas_session_id",
14948
+ build: () => buildCanvasRepairGuidance({ reasonCode: "missing_canvas_session_id" })
14949
+ },
14950
+ {
14951
+ id: "canvas.missing_lease_id",
14952
+ recipeType: "schema_repair",
14953
+ workflow: "canvas",
14954
+ priority: 60,
14955
+ reasonCode: "missing_lease_id",
14956
+ matches: (context) => context.workflow === "canvas" && context.reasonCode === "missing_lease_id",
14957
+ build: () => buildCanvasRepairGuidance({ reasonCode: "missing_lease_id" })
14958
+ },
14959
+ {
14960
+ id: "canvas.missing_document_id",
14961
+ recipeType: "schema_repair",
14962
+ workflow: "canvas",
14963
+ priority: 50,
14964
+ reasonCode: "missing_document_id",
14965
+ matches: (context) => context.workflow === "canvas" && context.reasonCode === "missing_document_id",
14966
+ build: () => buildCanvasRepairGuidance({ reasonCode: "missing_document_id" })
14967
+ },
14968
+ {
14969
+ id: "inspiredesign.pinterest.browser_native_recovery",
14970
+ recipeType: "site_navigation",
14971
+ workflow: "inspiredesign",
14972
+ priority: 100,
14973
+ reasonCode: "pinterest_browser_native_recovery",
14974
+ matches: (context) => context.workflow === "inspiredesign" && isPinterestScopedRecovery(context) && context.reasonCode !== "design_ready",
14975
+ build: (context, readiness) => buildEvidenceRecoveryGuidance(
14976
+ context,
14977
+ readiness,
14978
+ "pinterest_browser_native_recovery",
14979
+ "Recover Pinterest evidence in an authenticated browser session",
14980
+ "Use the Pinterest browser-native recipe to verify login, search the brief on Pinterest, collect usable pins or boards, and reject login, challenge, empty-grid, and search-shell pages before Canvas."
14981
+ )
14982
+ },
14983
+ {
14984
+ id: "inspiredesign.provider_unavailable",
14985
+ recipeType: "evidence_recovery",
14986
+ workflow: "inspiredesign",
14987
+ priority: 90,
14988
+ reasonCode: "provider_unavailable",
14989
+ matches: (context) => context.workflow === "inspiredesign" && context.reasonCode === "provider_unavailable",
14990
+ build: (context, readiness) => buildEvidenceRecoveryGuidance(
14991
+ context,
14992
+ readiness,
14993
+ "provider_unavailable",
14994
+ "Recover provider evidence",
14995
+ "Resolve the requested provider lane or supply explicit usable reference URLs before continuing to Canvas."
14996
+ )
14997
+ },
14998
+ {
14999
+ id: "inspiredesign.diagnostic_only",
15000
+ recipeType: "quality_gate",
15001
+ workflow: "inspiredesign",
15002
+ priority: 80,
15003
+ reasonCode: "diagnostic_only",
15004
+ matches: (context) => context.workflow === "inspiredesign" && context.reasonCode === "diagnostic_only",
15005
+ build: (context, readiness) => buildEvidenceRecoveryGuidance(
15006
+ context,
15007
+ readiness,
15008
+ "diagnostic_only",
15009
+ "Replace diagnostic references",
15010
+ "The harvest captured diagnostic or blocked pages. Replace them with usable creative references before Canvas."
15011
+ )
15012
+ },
15013
+ {
15014
+ id: "inspiredesign.zero_references",
15015
+ recipeType: "evidence_recovery",
15016
+ workflow: "inspiredesign",
15017
+ priority: 70,
15018
+ reasonCode: "zero_references",
15019
+ matches: (context) => context.workflow === "inspiredesign" && context.reasonCode === "zero_references",
15020
+ build: (context, readiness) => buildEvidenceRecoveryGuidance(
15021
+ context,
15022
+ readiness,
15023
+ "zero_references",
15024
+ "Collect reference evidence",
15025
+ "The harvest produced no references. Run source-specific discovery or provide explicit URLs before Canvas."
15026
+ )
15027
+ },
15028
+ {
15029
+ id: "inspiredesign.failed_capture",
15030
+ recipeType: "evidence_recovery",
15031
+ workflow: "inspiredesign",
15032
+ priority: 60,
15033
+ reasonCode: "failed_capture",
15034
+ matches: (context) => context.workflow === "inspiredesign" && context.reasonCode === "failed_capture",
15035
+ build: (context, readiness) => buildEvidenceRecoveryGuidance(
15036
+ context,
15037
+ readiness,
15038
+ "failed_capture",
15039
+ "Retry capture with a usable browser session",
15040
+ "Deep capture or required visual evidence failed. Restore session state or use explicit references with capturable pages."
15041
+ )
15042
+ },
15043
+ {
15044
+ id: "inspiredesign.zero_ranked_references",
15045
+ recipeType: "evidence_recovery",
15046
+ workflow: "inspiredesign",
15047
+ priority: 55,
15048
+ reasonCode: "zero_ranked_references",
15049
+ matches: (context) => context.workflow === "inspiredesign" && context.reasonCode === "zero_ranked_references",
15050
+ build: (context, readiness) => buildEvidenceRecoveryGuidance(
15051
+ context,
15052
+ readiness,
15053
+ "zero_ranked_references",
15054
+ "Replace rejected reference evidence",
15055
+ "The harvest captured references, but none survived scoring. Replace rejected, off-brief, blocked, or diagnostic pages before Canvas."
15056
+ )
15057
+ },
15058
+ {
15059
+ id: "inspiredesign.off_brief_reference",
15060
+ recipeType: "quality_gate",
15061
+ workflow: "inspiredesign",
15062
+ priority: 52,
15063
+ reasonCode: "off_brief_reference",
15064
+ matches: (context) => context.workflow === "inspiredesign" && context.reasonCode === "off_brief_reference",
15065
+ build: (context, readiness) => buildEvidenceRecoveryGuidance(
15066
+ context,
15067
+ readiness,
15068
+ "off_brief_reference",
15069
+ "Replace off-brief reference evidence",
15070
+ "The top ranked reference is captured, but its signals do not overlap the requested brief. Replace it with on-brief references before Canvas."
15071
+ )
15072
+ },
15073
+ {
15074
+ id: "inspiredesign.weak_reference",
15075
+ recipeType: "quality_gate",
15076
+ workflow: "inspiredesign",
15077
+ priority: 50,
15078
+ reasonCode: "weak_reference",
15079
+ matches: (context) => context.workflow === "inspiredesign" && context.reasonCode === "weak_reference",
15080
+ build: (context, readiness) => buildEvidenceRecoveryGuidance(
15081
+ context,
15082
+ readiness,
15083
+ "weak_reference",
15084
+ "Strengthen weak reference evidence",
15085
+ "The harvest has ranked references, but their score or confidence is too weak for Canvas-first design handoff."
15086
+ )
15087
+ },
15088
+ {
15089
+ id: "inspiredesign.ready",
15090
+ recipeType: "artifact_handoff",
15091
+ workflow: "inspiredesign",
15092
+ priority: 1,
15093
+ reasonCode: "design_ready",
15094
+ matches: (context) => context.workflow === "inspiredesign" && context.reasonCode === "design_ready",
15095
+ build: buildReadyInspiredesignGuidance
15096
+ }
15097
+ ];
15098
+
15099
+ // src/guidance/router.ts
15100
+ var byPriority = (left, right) => {
15101
+ return right.priority - left.priority || left.id.localeCompare(right.id);
15102
+ };
15103
+ var GuidanceRouter = class {
15104
+ recipes;
15105
+ constructor(recipes = genericGuidanceRecipes) {
15106
+ this.recipes = recipes.slice().sort(byPriority);
15107
+ }
15108
+ route(context) {
15109
+ const readiness = classifyGuidanceReadiness(context);
15110
+ const recipe = this.recipes.find((candidate) => candidate.matches(context));
15111
+ if (!recipe) {
15112
+ throw new Error(`No guidance recipe matched workflow ${context.workflow}.`);
15113
+ }
15114
+ return recipe.build(context, readiness);
15115
+ }
15116
+ };
15117
+ var routeNextStepGuidance = (context) => {
15118
+ return new GuidanceRouter().route(context);
15119
+ };
15120
+
15121
+ // src/providers/workflow-handoff.ts
15122
+ var PRODUCT_VIDEO_BRIEF_HELPER_PATH = "./skills/opendevbrowser-product-presentation-asset/scripts/render-video-brief.sh";
15123
+ var PRODUCT_VIDEO_BRIEF_HELPER_COMMAND = `${PRODUCT_VIDEO_BRIEF_HELPER_PATH} <pack>/manifest.json`;
15124
+ var createSuccessHandoff = (followthroughSummary, suggestedNextAction, suggestedSteps) => ({
15125
+ followthroughSummary,
15126
+ suggestedNextAction,
15127
+ suggestedSteps
15128
+ });
15129
+ var cliExample = (command, args) => `npx opendevbrowser ${command} ${args}`;
15130
+ var quoteCliValue = (value) => JSON.stringify(value);
15131
+ var GATED_PROVIDER_REASON_CODES = /* @__PURE__ */ new Set([
15132
+ "auth_required",
15133
+ "token_required",
15134
+ "challenge_detected"
15135
+ ]);
15136
+ var buildResearchRerunCommand = (input, options = {}) => {
15137
+ const browserMode = options.browserMode ?? input.browserMode ?? "managed";
15138
+ const useCookies = options.useCookies ? " --use-cookies" : "";
15139
+ const challengeMode = options.challengeAutomationMode ? ` --challenge-automation-mode ${options.challengeAutomationMode}` : "";
15140
+ return cliExample(
15141
+ "research run",
15142
+ `--topic ${quoteCliValue(input.topic)} --days 14 --sources web,community --browser-mode ${browserMode}${useCookies}${challengeMode} --mode json --output-format json`
15143
+ );
15144
+ };
15145
+ var isJsonRecord3 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
15146
+ var readFailureReasonCode = (failure) => {
15147
+ return failure.error.reasonCode ?? normalizeProviderReasonCode({
15148
+ code: failure.error.code,
15149
+ message: failure.error.message,
15150
+ details: failure.error.details
15151
+ }) ?? null;
15152
+ };
15153
+ var readDiagnosticReasonCode = (diagnostic) => {
15154
+ const reasonCode = diagnostic.reasonCode ?? diagnostic.browserFallbackReasonCode;
15155
+ return isProviderReasonCode(reasonCode) && GATED_PROVIDER_REASON_CODES.has(reasonCode) ? reasonCode : null;
15156
+ };
15157
+ var cookieDiagnosticShowsAvailableCookies = (diagnostic) => {
15158
+ return diagnostic.available === true || typeof diagnostic.loaded === "number" && diagnostic.loaded > 0 || typeof diagnostic.injected === "number" && diagnostic.injected > 0 || typeof diagnostic.verifiedCount === "number" && diagnostic.verifiedCount > 0;
15159
+ };
15160
+ var addProviderSignal = (signal, provider, reasonCode) => {
15161
+ if (provider) signal.providers.push(provider);
15162
+ if (reasonCode) signal.reasonCodes.push(reasonCode);
15163
+ };
15164
+ var readFailureCookieDiagnostics = (failure) => {
15165
+ const candidate = failure.error.details?.cookieDiagnostics;
15166
+ return isJsonRecord3(candidate) ? candidate : null;
15167
+ };
15168
+ var emptyResearchGatedProviderSignal = () => ({
15169
+ providers: [],
15170
+ reasonCodes: [],
15171
+ useCookies: false
15172
+ });
15173
+ var normalizeResearchGatedProviderSignal = (signal) => {
15174
+ return signal.providers.length > 0 || signal.reasonCodes.length > 0 ? {
15175
+ providers: [...new Set(signal.providers)].sort(),
15176
+ reasonCodes: [...new Set(signal.reasonCodes)].sort(),
15177
+ useCookies: signal.useCookies
15178
+ } : null;
15179
+ };
15180
+ var mergeResearchGatedProviderSignals = (signals) => {
15181
+ const merged = emptyResearchGatedProviderSignal();
15182
+ for (const signal of signals) {
15183
+ merged.providers.push(...signal.providers);
15184
+ merged.reasonCodes.push(...signal.reasonCodes);
15185
+ merged.useCookies = merged.useCookies || signal.useCookies;
15186
+ }
15187
+ return merged;
15188
+ };
15189
+ var detectResearchFailureSignals = (failures) => {
15190
+ const signal = emptyResearchGatedProviderSignal();
13252
15191
  for (const failure of failures) {
13253
15192
  const reasonCode = readFailureReasonCode(failure);
13254
15193
  const isGatedFailure = Boolean(reasonCode && GATED_PROVIDER_REASON_CODES.has(reasonCode));
@@ -13317,6 +15256,10 @@ var buildProductVideoRerunCommand = (input = {}) => {
13317
15256
  `${target}${providerHint}${screenshots}${allImages}${includeCopy}${browserMode} --use-cookies --challenge-automation-mode browser_with_helper --output-format json`
13318
15257
  );
13319
15258
  };
15259
+ var extractPrimaryConstraintSentence = (summary) => {
15260
+ const match = /^Primary constraint:\s+(.+?\.)\s/.exec(summary);
15261
+ return match?.[1] ?? null;
15262
+ };
13320
15263
  var buildMacroResolveArgs = (input, options) => {
13321
15264
  const defaultProvider = input.defaultProvider ? ` --default-provider ${input.defaultProvider}` : "";
13322
15265
  const execute = options?.execute ? " --execute" : "";
@@ -13324,7 +15267,7 @@ var buildMacroResolveArgs = (input, options) => {
13324
15267
  const useCookies = options?.useCookies ? " --use-cookies" : "";
13325
15268
  const challenge = options?.challengeAutomationMode ? ` --challenge-automation-mode ${options.challengeAutomationMode}` : "";
13326
15269
  const cookiePolicy = options?.cookiePolicyOverride ? ` --cookie-policy ${options.cookiePolicyOverride}` : "";
13327
- const outputFormat = options?.includeOutputFormat === false ? "" : " --output-format json";
15270
+ const outputFormat = " --output-format json";
13328
15271
  return `--expression ${quoteCliValue(input.expression)}${defaultProvider}${execute}${browserMode}${useCookies}${cookiePolicy}${challenge}${outputFormat}`;
13329
15272
  };
13330
15273
  var buildMacroPreviewCommand = (input) => cliExample("macro-resolve", buildMacroResolveArgs(input));
@@ -13338,7 +15281,7 @@ var buildResearchGatedSuccessHandoff = (input, signal) => {
13338
15281
  const recoveryCommand = buildResearchRecoveryRerunCommand(input, signal);
13339
15282
  const providers = signal.providers.length > 0 ? signal.providers.join(", ") : "gated providers";
13340
15283
  const cookieNote = signal.useCookies ? " The command includes --use-cookies because cookie diagnostics show available cookies." : " Add --use-cookies only when legitimate provider cookies are available.";
13341
- return createSuccessHandoff(
15284
+ const handoff = createSuccessHandoff(
13342
15285
  `Review ranked records, artifact metadata, and gated-provider diagnostics for ${providers} before publishing claims.`,
13343
15286
  `Open the returned artifact path, inspect records.json, context.json, meta.json, and report.md, then rerun ${recoveryCommand} only with a user-authorized signed-in relay session.${cookieNote}`,
13344
15287
  [
@@ -13350,6 +15293,21 @@ var buildResearchGatedSuccessHandoff = (input, signal) => {
13350
15293
  { reason: "Keep SERPs discovery-only and publish only claims supported by destination records that passed review." }
13351
15294
  ]
13352
15295
  );
15296
+ const guidance = routeNextStepGuidance({
15297
+ workflow: "research",
15298
+ reasonCode: "gated_provider",
15299
+ requestedProviders: signal.providers,
15300
+ browserMode: "extension",
15301
+ useCookies: signal.useCookies,
15302
+ details: {
15303
+ topic: input.topic,
15304
+ reasonCodes: signal.reasonCodes
15305
+ }
15306
+ });
15307
+ return {
15308
+ ...handoff,
15309
+ nextStepGuidance: renderWorkflowGuidance(guidance)
15310
+ };
13353
15311
  };
13354
15312
  var buildResearchDefaultSuccessHandoff = (input) => {
13355
15313
  const rerunCommand = buildResearchRerunCommand(input);
@@ -13438,26 +15396,43 @@ var buildMacroResolveSuccessHandoff = (input) => {
13438
15396
  ]
13439
15397
  );
13440
15398
  };
13441
- var buildInspiredesignSuccessHandoff = (input) => createSuccessHandoff(
13442
- input.summary,
13443
- input.nextStep,
13444
- [
13445
- { reason: INSPIREDESIGN_HANDOFF_GUIDANCE.reviewAdvancedBrief },
13446
- {
13447
- reason: "Load the baseline workflow runbook before implementation.",
13448
- command: input.commandExamples.loadBestPractices
13449
- },
13450
- {
13451
- reason: "Load the Canvas contract lane before patching.",
13452
- command: input.commandExamples.loadDesignAgent
13453
- },
13454
- {
13455
- reason: INSPIREDESIGN_HANDOFF_GUIDANCE.prepareCanvasPlanRequest,
13456
- command: input.commandExamples.continueInCanvas
13457
- },
13458
- { reason: input.deepCaptureRecommendation }
13459
- ]
13460
- );
15399
+ var buildInspiredesignSuccessHandoff = (input) => {
15400
+ if (input.nextStepGuidance && input.nextStepGuidance.readiness !== "ready") {
15401
+ const primaryConstraint = extractPrimaryConstraintSentence(input.summary);
15402
+ const summary = primaryConstraint ? `Primary constraint: ${primaryConstraint} ${input.nextStepGuidance.primaryAction.summary}` : void 0;
15403
+ const compatibility = renderWorkflowCompatibility(input.nextStepGuidance, summary);
15404
+ return {
15405
+ ...compatibility,
15406
+ nextStepGuidance: renderWorkflowGuidance(input.nextStepGuidance)
15407
+ };
15408
+ }
15409
+ const handoff = createSuccessHandoff(
15410
+ input.summary,
15411
+ input.nextStep,
15412
+ [
15413
+ { reason: INSPIREDESIGN_HANDOFF_GUIDANCE.reviewAdvancedBrief },
15414
+ {
15415
+ reason: "Load the baseline workflow runbook before implementation.",
15416
+ command: input.commandExamples.loadBestPractices
15417
+ },
15418
+ {
15419
+ reason: "Load the Canvas contract lane before patching.",
15420
+ command: input.commandExamples.loadDesignAgent
15421
+ },
15422
+ {
15423
+ reason: "Load the motion-design lane before translating visual evidence into animation, timing, or reduced-motion behavior.",
15424
+ command: input.commandExamples.loadMotionDesign
15425
+ },
15426
+ { reason: INSPIREDESIGN_HANDOFF_GUIDANCE.visualArtifactRecommendation },
15427
+ {
15428
+ reason: INSPIREDESIGN_HANDOFF_GUIDANCE.prepareCanvasPlanRequest,
15429
+ command: input.commandExamples.continueInCanvas
15430
+ },
15431
+ { reason: input.deepCaptureRecommendation }
15432
+ ]
15433
+ );
15434
+ return input.nextStepGuidance ? { ...handoff, nextStepGuidance: renderWorkflowGuidance(input.nextStepGuidance) } : handoff;
15435
+ };
13461
15436
 
13462
15437
  // src/providers/renderer.ts
13463
15438
  var toCurrency = (value) => `$${value.toFixed(2)}`;
@@ -13562,6 +15537,33 @@ var researchFailureMessage = (content) => boundedInlineText({
13562
15537
  limit: RESEARCH_REPORT_LIMITS.failureMessageCharacters,
13563
15538
  target: "meta.json"
13564
15539
  });
15540
+ var CANVAS_CONTINUATION_BLOCKED_COMMAND = "Unavailable until nextStepGuidance.readiness is ready.";
15541
+ var canContinueInspiredesignInCanvas = (guidance) => guidance?.readiness === "ready";
15542
+ var blockInspiredesignCanvasArtifactGuide = (handoff, recoverySummary) => ({
15543
+ ...handoff.artifactGuide,
15544
+ [INSPIREDESIGN_HANDOFF_FILES.canvasPlanRequest]: {
15545
+ ...handoff.artifactGuide[INSPIREDESIGN_HANDOFF_FILES.canvasPlanRequest],
15546
+ purpose: "Diagnostic Canvas request preview only until nextStepGuidance.readiness is ready.",
15547
+ howToUse: [
15548
+ recoverySummary,
15549
+ "Do not submit this payload to Canvas until usable ranked references pass the readiness checks."
15550
+ ],
15551
+ mustNot: [
15552
+ "Do not submit canvas.plan.set while nextStepGuidance.readiness is not ready.",
15553
+ "Do not treat rejected or not-ready references as Canvas design direction."
15554
+ ]
15555
+ }
15556
+ });
15557
+ var buildMissingInspiredesignGuidanceHandoff = () => {
15558
+ const summary = "Canvas continuation unavailable until nextStepGuidance.readiness is ready.";
15559
+ return {
15560
+ followthroughSummary: summary,
15561
+ suggestedNextAction: summary,
15562
+ suggestedSteps: [{
15563
+ reason: "Inspect the workflow output for nextStepGuidance before using Canvas artifacts."
15564
+ }]
15565
+ };
15566
+ };
13565
15567
  var limitedCount = (total, limit) => Math.min(total, limit);
13566
15568
  var omissionLine = (args) => {
13567
15569
  const omitted = args.total - limitedCount(args.total, args.limit);
@@ -13986,6 +15988,19 @@ var renderShopping = (args) => {
13986
15988
  var renderInspiredesign = (args) => {
13987
15989
  const captureAttemptReport = inspiredesignCaptureAttemptReportFromMeta(args.meta);
13988
15990
  const captureAttemptSummary = inspiredesignCaptureAttemptSummaryFromMeta(args.meta);
15991
+ const visualEvidence = args.visualEvidence ?? [];
15992
+ const screenshotIndex = args.screenshotIndex ?? [];
15993
+ const rankedReferences = args.rankedReferences ?? [];
15994
+ const rankedReferencesArtifact = args.referencePatternBoard ? {
15995
+ qualitySummary: args.referencePatternBoard.qualitySummary,
15996
+ references: args.referencePatternBoard.references,
15997
+ rejectedReferences: args.referencePatternBoard.rejectedReferences,
15998
+ synthesis: args.referencePatternBoard.synthesis
15999
+ } : {
16000
+ references: rankedReferences,
16001
+ rejectedReferences: []
16002
+ };
16003
+ const metaPromptMarkdown = args.metaPromptMarkdown ?? "";
13989
16004
  const summary = buildInspiredesignSummary({
13990
16005
  brief: args.brief,
13991
16006
  referenceCount: args.urls.length,
@@ -13993,40 +16008,69 @@ var renderInspiredesign = (args) => {
13993
16008
  meta: args.meta
13994
16009
  });
13995
16010
  const followthroughSummary = prependPrimaryConstraint(args.designAgentHandoff.summary, args.meta);
16011
+ const canContinueInCanvas = canContinueInspiredesignInCanvas(args.nextStepGuidance);
16012
+ const prototypeGuidanceMarkdown = canContinueInCanvas ? args.prototypeGuidanceMarkdown : null;
16013
+ const commandExamples2 = {
16014
+ ...args.designAgentHandoff.commandExamples,
16015
+ continueInCanvas: canContinueInCanvas ? args.designAgentHandoff.commandExamples.continueInCanvas : CANVAS_CONTINUATION_BLOCKED_COMMAND
16016
+ };
16017
+ const renderedWorkflowHandoff = buildInspiredesignSuccessHandoff({
16018
+ summary: followthroughSummary,
16019
+ nextStep: args.designAgentHandoff.nextStep,
16020
+ commandExamples: commandExamples2,
16021
+ deepCaptureRecommendation: args.designAgentHandoff.deepCaptureRecommendation,
16022
+ ...args.nextStepGuidance ? { nextStepGuidance: args.nextStepGuidance } : {}
16023
+ });
16024
+ const handoff = args.nextStepGuidance ? renderedWorkflowHandoff : buildMissingInspiredesignGuidanceHandoff();
16025
+ const blockedCanvasArtifactGuide = canContinueInCanvas ? args.designAgentHandoff.artifactGuide : blockInspiredesignCanvasArtifactGuide(args.designAgentHandoff, handoff.suggestedNextAction);
16026
+ const renderedDesignAgentHandoff = {
16027
+ ...args.designAgentHandoff,
16028
+ ...handoff,
16029
+ summary: handoff.followthroughSummary,
16030
+ nextStep: handoff.suggestedNextAction,
16031
+ artifactGuide: blockedCanvasArtifactGuide,
16032
+ commandExamples: commandExamples2
16033
+ };
13996
16034
  const contextPayload = {
13997
16035
  brief: args.brief,
13998
16036
  advancedBriefMarkdown: args.advancedBriefMarkdown,
13999
16037
  urls: args.urls,
14000
16038
  designContract: args.designContract,
14001
16039
  canvasPlanRequest: args.canvasPlanRequest,
14002
- designAgentHandoff: args.designAgentHandoff,
16040
+ designAgentHandoff: renderedDesignAgentHandoff,
16041
+ ...args.nextStepGuidance ? { nextStepGuidance: args.nextStepGuidance } : {},
14003
16042
  generationPlan: args.generationPlan,
14004
16043
  implementationPlan: args.implementationPlan,
14005
16044
  designMarkdown: args.designMarkdown,
14006
16045
  implementationPlanMarkdown: args.implementationPlanMarkdown,
14007
- prototypeGuidanceMarkdown: args.prototypeGuidanceMarkdown,
16046
+ prototypeGuidanceMarkdown,
14008
16047
  evidence: args.evidence,
16048
+ visualEvidence,
16049
+ screenshotIndex,
16050
+ rankedReferences,
16051
+ metaPromptMarkdown,
14009
16052
  meta: args.meta
14010
16053
  };
14011
- const handoff = buildInspiredesignSuccessHandoff({
14012
- summary: followthroughSummary,
14013
- nextStep: args.designAgentHandoff.nextStep,
14014
- commandExamples: args.designAgentHandoff.commandExamples,
14015
- deepCaptureRecommendation: args.designAgentHandoff.deepCaptureRecommendation
14016
- });
14017
16054
  const files = [
14018
16055
  { path: INSPIREDESIGN_HANDOFF_FILES.designMarkdown, content: args.designMarkdown },
14019
16056
  { path: INSPIREDESIGN_HANDOFF_FILES.advancedBrief, content: args.advancedBriefMarkdown },
14020
16057
  { path: INSPIREDESIGN_HANDOFF_FILES.designContract, content: args.designContract },
14021
16058
  { path: INSPIREDESIGN_HANDOFF_FILES.canvasPlanRequest, content: args.canvasPlanRequest },
14022
- { path: INSPIREDESIGN_HANDOFF_FILES.designAgentHandoff, content: args.designAgentHandoff },
16059
+ {
16060
+ path: INSPIREDESIGN_HANDOFF_FILES.designAgentHandoff,
16061
+ content: renderedDesignAgentHandoff
16062
+ },
14023
16063
  { path: INSPIREDESIGN_HANDOFF_FILES.generationPlan, content: args.generationPlan },
14024
16064
  { path: INSPIREDESIGN_HANDOFF_FILES.implementationPlanMarkdown, content: args.implementationPlanMarkdown },
14025
16065
  { path: INSPIREDESIGN_HANDOFF_FILES.implementationPlan, content: args.implementationPlan },
14026
- { path: INSPIREDESIGN_HANDOFF_FILES.evidence, content: args.evidence }
16066
+ { path: INSPIREDESIGN_HANDOFF_FILES.evidence, content: args.evidence },
16067
+ { path: INSPIREDESIGN_HANDOFF_FILES.visualEvidence, content: { visualEvidence } },
16068
+ { path: INSPIREDESIGN_HANDOFF_FILES.screenshotIndex, content: { screenshots: screenshotIndex } },
16069
+ { path: INSPIREDESIGN_HANDOFF_FILES.rankedReferences, content: rankedReferencesArtifact },
16070
+ { path: INSPIREDESIGN_HANDOFF_FILES.metaPrompt, content: metaPromptMarkdown }
14027
16071
  ];
14028
- if (args.prototypeGuidanceMarkdown) {
14029
- files.push({ path: INSPIREDESIGN_HANDOFF_FILES.prototypeGuidance, content: args.prototypeGuidanceMarkdown });
16072
+ if (prototypeGuidanceMarkdown) {
16073
+ files.push({ path: INSPIREDESIGN_HANDOFF_FILES.prototypeGuidance, content: prototypeGuidanceMarkdown });
14030
16074
  }
14031
16075
  const captureAttemptFields = {
14032
16076
  ...captureAttemptSummary ? { captureAttemptSummary } : {},
@@ -14052,12 +16096,17 @@ var renderInspiredesign = (args) => {
14052
16096
  advancedBriefMarkdown: args.advancedBriefMarkdown,
14053
16097
  urls: args.urls,
14054
16098
  canvasPlanRequest: args.canvasPlanRequest,
14055
- designAgentHandoff: args.designAgentHandoff,
16099
+ designAgentHandoff: renderedDesignAgentHandoff,
16100
+ ...args.nextStepGuidance ? { nextStepGuidance: args.nextStepGuidance } : {},
14056
16101
  designContract: args.designContract,
14057
16102
  generationPlan: args.generationPlan,
14058
16103
  implementationPlan: args.implementationPlan,
14059
- prototypeGuidanceMarkdown: args.prototypeGuidanceMarkdown,
16104
+ prototypeGuidanceMarkdown,
14060
16105
  evidence: args.evidence,
16106
+ visualEvidence,
16107
+ screenshotIndex,
16108
+ rankedReferences,
16109
+ metaPromptMarkdown,
14061
16110
  ...handoff,
14062
16111
  ...captureAttemptFields,
14063
16112
  meta: args.meta
@@ -14071,7 +16120,7 @@ var renderInspiredesign = (args) => {
14071
16120
  mode: args.mode,
14072
16121
  markdown: args.designMarkdown,
14073
16122
  implementationPlanMarkdown: args.implementationPlanMarkdown,
14074
- prototypeGuidanceMarkdown: args.prototypeGuidanceMarkdown,
16123
+ prototypeGuidanceMarkdown,
14075
16124
  ...handoff,
14076
16125
  ...captureAttemptFields,
14077
16126
  meta: args.meta
@@ -14102,6 +16151,271 @@ var renderInspiredesign = (args) => {
14102
16151
  };
14103
16152
  };
14104
16153
 
16154
+ // src/guidance/recipes/site-registry.ts
16155
+ var freezeRecipeValue = (value) => {
16156
+ if (value === null || typeof value !== "object" || Object.isFrozen(value)) return value;
16157
+ for (const child of Object.values(value)) {
16158
+ freezeRecipeValue(child);
16159
+ }
16160
+ return Object.freeze(value);
16161
+ };
16162
+ var SITE_RECIPES = [freezeRecipeValue(pinterestSiteRecipe)];
16163
+ var normalizeHostname = (hostname) => hostname.toLowerCase().replace(/^www\./, "");
16164
+ var resolveSiteRecipeForProvider = (providerId) => {
16165
+ return SITE_RECIPES.find((recipe) => recipe.providerIds.includes(providerId));
16166
+ };
16167
+ var resolveSiteRecipeForUrl = (url) => {
16168
+ let hostname;
16169
+ try {
16170
+ hostname = new URL(url).hostname.toLowerCase();
16171
+ } catch {
16172
+ return void 0;
16173
+ }
16174
+ return SITE_RECIPES.find((recipe) => {
16175
+ if (recipe.id === "social/pinterest") {
16176
+ return isAllowedPinterestReferenceHost(hostname);
16177
+ }
16178
+ const normalizedHost = normalizeHostname(hostname);
16179
+ return recipe.hostnames.some((candidate) => {
16180
+ const normalized = normalizeHostname(candidate);
16181
+ return normalizedHost === normalized || normalizedHost.endsWith(`.${normalized}`);
16182
+ });
16183
+ });
16184
+ };
16185
+
16186
+ // src/guidance/context.ts
16187
+ var HARD_PROVIDER_FAILURE_REASON_CODES = /* @__PURE__ */ new Set([
16188
+ "auth_required",
16189
+ "challenge_detected",
16190
+ "policy_blocked",
16191
+ "rate_limited",
16192
+ "token_required"
16193
+ ]);
16194
+ var normalizeComparableUrl = (value) => {
16195
+ try {
16196
+ const url = new URL(value);
16197
+ url.protocol = "https:";
16198
+ url.hostname = url.hostname.toLowerCase().replace(/^www\./, "");
16199
+ url.hash = "";
16200
+ url.search = "";
16201
+ return url.toString();
16202
+ } catch {
16203
+ return null;
16204
+ }
16205
+ };
16206
+ var hasAcceptedUserSuppliedSiteRecipeReferenceUrl = (source) => {
16207
+ if (source.metrics.referenceCount === 0 || source.quality.rankedReferenceCount === 0) return false;
16208
+ const rankedReferenceUrls = new Set((source.quality.rankedReferenceUrls ?? []).map(normalizeComparableUrl).filter((url) => typeof url === "string"));
16209
+ if (rankedReferenceUrls.size === 0) return false;
16210
+ const requestedSiteRecipeIds = new Set(source.requestedProviders.map((providerId) => resolveSiteRecipeForProvider(providerId)?.id).filter((recipeId) => typeof recipeId === "string"));
16211
+ return (source.urls ?? []).some((url) => {
16212
+ const recipeId = resolveSiteRecipeForUrl(url)?.id;
16213
+ if (!recipeId) return false;
16214
+ if (requestedSiteRecipeIds.size > 0 && !requestedSiteRecipeIds.has(recipeId)) return false;
16215
+ const normalizedUrl = normalizeComparableUrl(url);
16216
+ return normalizedUrl !== null && rankedReferenceUrls.has(normalizedUrl);
16217
+ });
16218
+ };
16219
+ var hasHardProviderFailureSignal = (source) => !hasAcceptedUserSuppliedSiteRecipeReferenceUrl(source) && (source.discovery.hardFailureReasonCodes ?? []).some((reasonCode) => HARD_PROVIDER_FAILURE_REASON_CODES.has(reasonCode)) || (source.primaryConstraint?.reasonCode ? HARD_PROVIDER_FAILURE_REASON_CODES.has(source.primaryConstraint.reasonCode) : false);
16220
+ var hasProviderUnavailableSignal = (source) => {
16221
+ if (hasHardProviderFailureSignal(source)) return true;
16222
+ if (source.metrics.referenceCount > 0 && source.quality.rankedReferenceCount > 0) return false;
16223
+ if (source.discovery.requested && source.discovery.acceptedUrls.length === 0 && source.discovery.failures > 0) return true;
16224
+ if (source.discovery.failure && source.discovery.acceptedUrls.length === 0) return true;
16225
+ return source.primaryConstraint?.reasonCode === "auth_required";
16226
+ };
16227
+ var hasWeakTopReference2 = (source) => {
16228
+ if (source.quality.rankedReferenceCount === 0) return false;
16229
+ const score = source.quality.topReferenceScore ?? 0;
16230
+ const confidence = source.quality.topReferenceConfidence ?? 0;
16231
+ return score < 50 || confidence < 0.5;
16232
+ };
16233
+ var reasonCodeForInspiredesign = (source) => {
16234
+ if (hasProviderUnavailableSignal(source)) return "provider_unavailable";
16235
+ if (source.quality.diagnosticOnlyReasons.length > 0 && source.quality.rankedReferenceCount === 0) return "diagnostic_only";
16236
+ if (source.metrics.referenceCount === 0 && source.metrics.referenceEvidenceRequired !== false) return "zero_references";
16237
+ if (source.metrics.referenceCount > 0 && source.quality.rankedReferenceCount === 0) return "zero_ranked_references";
16238
+ if (source.metrics.visualEvidenceRequired && (source.metrics.failedCaptureCount > 0 || source.quality.missingScreenshotCount > 0)) {
16239
+ return "failed_capture";
16240
+ }
16241
+ if (source.quality.topReferenceIntentMatched === false) return "off_brief_reference";
16242
+ if (hasWeakTopReference2(source)) return "weak_reference";
16243
+ return "design_ready";
16244
+ };
16245
+ var resolveInspiredesignSiteRecipe = (source) => {
16246
+ const providerRecipe = source.requestedProviders.map((providerId) => resolveSiteRecipeForProvider(providerId)).find((recipe) => recipe !== void 0);
16247
+ if (providerRecipe) return providerRecipe.id;
16248
+ const urlRecipe = (source.urls ?? []).map((url) => resolveSiteRecipeForUrl(url)).find((recipe) => recipe !== void 0);
16249
+ return urlRecipe?.id;
16250
+ };
16251
+ var createInspiredesignGuidanceContext = (source) => {
16252
+ const siteRecipeId = resolveInspiredesignSiteRecipe(source);
16253
+ return {
16254
+ workflow: "inspiredesign",
16255
+ reasonCode: reasonCodeForInspiredesign(source),
16256
+ requestedProviders: source.requestedProviders,
16257
+ ...siteRecipeId ? { siteRecipeId } : {},
16258
+ ...source.query ? { query: source.query } : {},
16259
+ ...source.browserMode ? { browserMode: source.browserMode } : {},
16260
+ ...source.cookiePolicy ? { cookiePolicy: source.cookiePolicy } : {},
16261
+ ...typeof source.useCookies === "boolean" ? { useCookies: source.useCookies } : {},
16262
+ providerUnavailable: hasProviderUnavailableSignal(source),
16263
+ evidence: {
16264
+ referenceCount: source.metrics.referenceCount,
16265
+ referenceEvidenceRequired: source.metrics.referenceEvidenceRequired,
16266
+ failedCaptureCount: source.metrics.failedCaptureCount,
16267
+ visualEvidenceRequired: source.metrics.visualEvidenceRequired,
16268
+ rankedReferenceCount: source.quality.rankedReferenceCount,
16269
+ rejectedReferenceCount: source.quality.rejectedReferenceCount,
16270
+ missingScreenshotCount: source.quality.missingScreenshotCount,
16271
+ diagnosticOnlyReasons: source.quality.diagnosticOnlyReasons,
16272
+ ...typeof source.quality.topReferenceScore === "number" ? { topReferenceScore: source.quality.topReferenceScore } : {},
16273
+ ...typeof source.quality.topReferenceConfidence === "number" ? { topReferenceConfidence: source.quality.topReferenceConfidence } : {},
16274
+ ...typeof source.quality.topReferenceIntentMatched === "boolean" ? { topReferenceIntentMatched: source.quality.topReferenceIntentMatched } : {}
16275
+ },
16276
+ details: {
16277
+ brief: source.brief,
16278
+ discoveryFailure: source.discovery.failure ?? "",
16279
+ hardFailureReasonCodes: source.discovery.hardFailureReasonCodes ?? [],
16280
+ primaryConstraintSummary: source.primaryConstraint?.summary ?? ""
16281
+ }
16282
+ };
16283
+ };
16284
+
16285
+ // src/inspiredesign/reference-discovery.ts
16286
+ var normalizeHttpUrl = (value) => {
16287
+ try {
16288
+ const url = new URL(value);
16289
+ if (url.protocol !== "http:" && url.protocol !== "https:") return null;
16290
+ url.hash = "";
16291
+ if (url.pathname === "/" && !/^https?:\/\/[^/]+\/[^?#]/i.test(value)) {
16292
+ return `${url.origin}${url.search}`;
16293
+ }
16294
+ return url.toString();
16295
+ } catch (error) {
16296
+ void error;
16297
+ return null;
16298
+ }
16299
+ };
16300
+ var extractInspiredesignDiscoveryUrl = (record) => {
16301
+ if (typeof record.url !== "string") return null;
16302
+ const trimmed = record.url.trim();
16303
+ if (!trimmed) return null;
16304
+ return normalizeHttpUrl(trimmed);
16305
+ };
16306
+ var normalizeInspiredesignDiscoveryRecords = (records) => {
16307
+ const seen = /* @__PURE__ */ new Set();
16308
+ const accepted = [];
16309
+ const rejected = [];
16310
+ records.forEach((record, index) => {
16311
+ const rawUrl = typeof record.url === "string" ? record.url.trim() : void 0;
16312
+ const url = extractInspiredesignDiscoveryUrl(record);
16313
+ const base = {
16314
+ ...record.title ? { title: record.title } : {},
16315
+ source: record.source,
16316
+ provider: record.provider,
16317
+ rank: index + 1
16318
+ };
16319
+ if (!rawUrl) {
16320
+ rejected.push({ ...base, status: "rejected", reason: "missing_url" });
16321
+ return;
16322
+ }
16323
+ if (!url) {
16324
+ rejected.push({ ...base, status: "rejected", reason: "invalid_url", rawUrl });
16325
+ return;
16326
+ }
16327
+ if (seen.has(url)) {
16328
+ rejected.push({ ...base, status: "rejected", reason: "duplicate_url", rawUrl });
16329
+ return;
16330
+ }
16331
+ seen.add(url);
16332
+ accepted.push({ ...base, status: "accepted", url });
16333
+ });
16334
+ return { accepted, rejected };
16335
+ };
16336
+ var mergeInspiredesignReferenceUrls = (explicitUrls, discoveredUrls, maxReferences) => {
16337
+ const merged = [];
16338
+ const seen = /* @__PURE__ */ new Set();
16339
+ for (const url of [...explicitUrls, ...discoveredUrls]) {
16340
+ const normalized = normalizeHttpUrl(url.trim());
16341
+ if (!normalized || seen.has(normalized)) continue;
16342
+ seen.add(normalized);
16343
+ merged.push(normalized);
16344
+ if (merged.length >= maxReferences) return merged;
16345
+ }
16346
+ return merged;
16347
+ };
16348
+ var normalizeInspiredesignProviders = (providers) => {
16349
+ const normalized = (providers ?? []).map((provider) => provider.trim()).filter((provider) => provider.length > 0);
16350
+ return [...new Set(normalized)];
16351
+ };
16352
+
16353
+ // src/inspiredesign/visual-policy.ts
16354
+ var VISUAL_BLOCKER_REASONS = /* @__PURE__ */ new Set([
16355
+ "policy_blocked",
16356
+ "auth_required",
16357
+ "challenge_detected",
16358
+ "rate_limited"
16359
+ ]);
16360
+ var toVisualPolicyReason = (reasonCode) => {
16361
+ if (!VISUAL_BLOCKER_REASONS.has(reasonCode)) return null;
16362
+ if (reasonCode === "policy_blocked" || reasonCode === "auth_required" || reasonCode === "challenge_detected" || reasonCode === "rate_limited") {
16363
+ return reasonCode;
16364
+ }
16365
+ return null;
16366
+ };
16367
+ var blockerFromFailures = (failures) => {
16368
+ for (const failure of failures ?? []) {
16369
+ const reasonCode = failure.error.reasonCode;
16370
+ if (!reasonCode) continue;
16371
+ const blocker = toVisualPolicyReason(reasonCode);
16372
+ if (blocker) return blocker;
16373
+ }
16374
+ return null;
16375
+ };
16376
+ var blockerFromTopLevelError = (error) => {
16377
+ if (!error?.reasonCode) return null;
16378
+ return toVisualPolicyReason(error.reasonCode);
16379
+ };
16380
+ var messageForBlocker = (reason) => {
16381
+ switch (reason) {
16382
+ case "policy_blocked":
16383
+ return "Visual capture skipped because provider policy blocked the reference.";
16384
+ case "auth_required":
16385
+ return "Visual capture skipped because authenticated access is unresolved.";
16386
+ case "challenge_detected":
16387
+ return "Visual capture skipped because a challenge was detected.";
16388
+ case "rate_limited":
16389
+ return "Visual capture skipped because the provider is rate limited.";
16390
+ case "visual_evidence_off":
16391
+ return "Visual evidence is disabled for this run.";
16392
+ case "visual_capture_allowed":
16393
+ return "Visual capture is allowed for this reference.";
16394
+ }
16395
+ };
16396
+ var decideInspiredesignVisualCapturePolicy = (input) => {
16397
+ if (input.visualEvidence === "off") {
16398
+ return {
16399
+ status: "skipped",
16400
+ reason: "visual_evidence_off",
16401
+ message: messageForBlocker("visual_evidence_off")
16402
+ };
16403
+ }
16404
+ const blocker = input.hasUsableRecords === true ? null : blockerFromFailures(input.failures) ?? blockerFromTopLevelError(input.topLevelError);
16405
+ if (blocker) {
16406
+ return {
16407
+ status: "skipped",
16408
+ reason: blocker,
16409
+ message: messageForBlocker(blocker)
16410
+ };
16411
+ }
16412
+ return {
16413
+ status: "allowed",
16414
+ reason: "visual_capture_allowed",
16415
+ message: messageForBlocker("visual_capture_allowed")
16416
+ };
16417
+ };
16418
+
14105
16419
  // src/canvas/types.ts
14106
16420
  var CANVAS_SCHEMA_VERSION = "1.0.0";
14107
16421
  var CANVAS_SESSION_MODES = ["low-fi-wireframe", "high-fi-live-edit", "dual-track", "document-only"];
@@ -14230,7 +16544,7 @@ var CANVAS_VALIDATION_TARGET_BLOCK_ON_CODES = [
14230
16544
  var CANVAS_PUBLIC_WARNING_CLASSES = CANVAS_VALIDATION_TARGET_BLOCK_ON_CODES;
14231
16545
 
14232
16546
  // src/providers/shopping-postprocess.ts
14233
- import { createHash as createHash4 } from "crypto";
16547
+ import { createHash as createHash5 } from "crypto";
14234
16548
  var LOOKS_LIKE_URL_RE = /^https?:\/\/\S+$/i;
14235
16549
  var PRICE_TOKEN_RE = /((?:US\$|CA\$|C\$|USD|CAD|EUR|GBP|[$€£]))\s*([0-9]{1,4}(?:[.,][0-9]{3})*(?:[.,][0-9]{1,2})?)/gi;
14236
16550
  var CONTEXTUAL_PRICE_TOKEN_RE = /(?:connect to any carrier later|starting at|starts at|starting from|from|buy now for|buy for)\s*((?:US\$|CA\$|C\$|USD|CAD|EUR|GBP|[$€£]))\s*([0-9]{1,4}(?:[.,][0-9]{3})*(?:[.,][0-9]{1,2})?)/gi;
@@ -14316,7 +16630,7 @@ var REGION_CURRENCY_BY_REGION = {
14316
16630
  uk: "GBP",
14317
16631
  eu: "EUR"
14318
16632
  };
14319
- var hash = (value) => createHash4("sha1").update(value).digest("hex").slice(0, 16);
16633
+ var hash = (value) => createHash5("sha1").update(value).digest("hex").slice(0, 16);
14320
16634
  var normalizePlainText = (value) => {
14321
16635
  if (!value) return "";
14322
16636
  return extractText(value).replace(/[\u0000-\u001F\u007F-\u009F]+/g, " ").replace(/\s+/g, " ").trim();
@@ -14681,7 +16995,7 @@ var withOfferFilterDiagnosticDetails = (details, offerFilterDiagnostic) => {
14681
16995
  };
14682
16996
  };
14683
16997
  var inferShoppingNoOfferFailure = (providerId, query, records, offerFilterDiagnostic) => {
14684
- const issuePriority = (issue) => ({
16998
+ const issuePriority2 = (issue) => ({
14685
16999
  token_required: 3,
14686
17000
  auth_required: 3,
14687
17001
  challenge_detected: 2
@@ -14696,7 +17010,7 @@ var inferShoppingNoOfferFailure = (providerId, query, records, offerFilterDiagno
14696
17010
  ...title ? { title } : {},
14697
17011
  ...typeof record.attributes.providerShell === "string" && record.attributes.providerShell.trim().length > 0 ? { providerShell: record.attributes.providerShell.trim() } : {}
14698
17012
  }];
14699
- }).sort((left, right) => issuePriority(right.hint) - issuePriority(left.hint))[0] ?? null;
17013
+ }).sort((left, right) => issuePriority2(right.hint) - issuePriority2(left.hint))[0] ?? null;
14700
17014
  if (primaryRecordIssue) {
14701
17015
  const reasonCode = primaryRecordIssue.hint.reasonCode;
14702
17016
  return {
@@ -14945,7 +17259,7 @@ var compileShoppingWorkflow = (input, options = {}) => {
14945
17259
  };
14946
17260
 
14947
17261
  // src/providers/shopping-compiler.ts
14948
- import { createHash as createHash5 } from "crypto";
17262
+ import { createHash as createHash6 } from "crypto";
14949
17263
  var DEFAULT_SHOPPING_SEARCH_LIMIT = 8;
14950
17264
  var SHOPPING_FETCH_RECOVERY_LIMIT = 2;
14951
17265
  var SEARCH_INDEX_RETRIEVAL_PATHS = /* @__PURE__ */ new Set(["shopping:search:index", "shopping:search:link"]);
@@ -14962,7 +17276,7 @@ var emptyCheckpointState = () => ({
14962
17276
  step_results_by_id: {}
14963
17277
  });
14964
17278
  var createShoppingSearchStepId = (providerId) => `search:${providerId}`;
14965
- var createShoppingFetchStepId = (providerId, url) => `fetch:${providerId}:${createHash5("sha1").update(canonicalizeUrl(url)).digest("hex").slice(0, 16)}`;
17279
+ var createShoppingFetchStepId = (providerId, url) => `fetch:${providerId}:${createHash6("sha1").update(canonicalizeUrl(url)).digest("hex").slice(0, 16)}`;
14966
17280
  var serializeShoppingCheckpointState = (state) => ({
14967
17281
  completed_step_ids: [...state.completed_step_ids],
14968
17282
  step_results_by_id: state.step_results_by_id
@@ -15448,7 +17762,7 @@ var compileProductVideoExecutionPlan = (args) => {
15448
17762
  };
15449
17763
 
15450
17764
  // src/providers/research-compiler.ts
15451
- import { createHash as createHash6 } from "crypto";
17765
+ import { createHash as createHash7 } from "crypto";
15452
17766
  var RESEARCH_AUTO_SOURCES = ["web", "community", "social"];
15453
17767
  var RESEARCH_ALL_SOURCES = [...RESEARCH_AUTO_SOURCES];
15454
17768
  var DEFAULT_RESEARCH_SEARCH_LIMIT = 10;
@@ -15474,7 +17788,7 @@ var toProviderSource = (providerId) => {
15474
17788
  return null;
15475
17789
  };
15476
17790
  var createResearchSearchStepId = (source) => `search:${source}`;
15477
- var createResearchFetchStepId = (url) => `fetch:web:${createHash6("sha1").update(canonicalizeUrl(url)).digest("hex").slice(0, 16)}`;
17791
+ var createResearchFetchStepId = (url) => `fetch:web:${createHash7("sha1").update(canonicalizeUrl(url)).digest("hex").slice(0, 16)}`;
15478
17792
  var serializeResearchCheckpointState = (state) => ({
15479
17793
  completed_step_ids: [...state.completed_step_ids],
15480
17794
  step_results_by_id: state.step_results_by_id
@@ -15842,9 +18156,310 @@ var executeResearchWorkflowPlan = async (runtime, plan, options) => {
15842
18156
  var hasInspiredesignUrls = (urls) => {
15843
18157
  return Array.isArray(urls) && urls.some((url) => url.trim().length > 0);
15844
18158
  };
15845
- function resolveInspiredesignCaptureMode(requested, urls) {
15846
- return hasInspiredesignUrls(urls) ? "deep" : requested ?? "off";
15847
- }
18159
+ function resolveInspiredesignCaptureMode(requested, urls) {
18160
+ return hasInspiredesignUrls(urls) ? "deep" : requested ?? "off";
18161
+ }
18162
+
18163
+ // src/providers/browser-native-discovery.ts
18164
+ var HARD_FAILURE_REASON_CODES = /* @__PURE__ */ new Set([
18165
+ "auth_required",
18166
+ "challenge_detected",
18167
+ "policy_blocked",
18168
+ "rate_limited",
18169
+ "token_required"
18170
+ ]);
18171
+ var sourceForRecipe = (recipe) => {
18172
+ return recipe.id.startsWith("social/") ? "social" : "web";
18173
+ };
18174
+ var needsAuthenticatedBrowser = (input) => {
18175
+ if (input.recipe.authMode === "public") return false;
18176
+ if (input.cookiePolicy === "required") return true;
18177
+ return input.recipe.authMode === "authenticated";
18178
+ };
18179
+ var hasAuthenticatedBrowser = (input) => {
18180
+ return input.browserMode === "extension" && input.useCookies === true;
18181
+ };
18182
+ var htmlFromRecord = (record) => {
18183
+ const html = record.attributes.html;
18184
+ return typeof html === "string" ? html : "";
18185
+ };
18186
+ var linksFromRecord = (record) => {
18187
+ const links = record.attributes.links;
18188
+ return Array.isArray(links) ? links.filter((link) => typeof link === "string") : [];
18189
+ };
18190
+ var badStateTextForRecord = (record) => {
18191
+ return [
18192
+ record.url ?? "",
18193
+ record.title ?? "",
18194
+ record.content ?? "",
18195
+ htmlFromRecord(record)
18196
+ ].join(" ").toLowerCase();
18197
+ };
18198
+ var normalizeBadStateReasonCode = (state) => {
18199
+ return isProviderReasonCode(state.reasonCode) ? state.reasonCode : "env_limited";
18200
+ };
18201
+ var shouldMatchBadState = (state, mode) => {
18202
+ if (mode === "hard_blocker") return state.id === "challenge";
18203
+ return mode === "all" || state.id !== "search-shell";
18204
+ };
18205
+ var findBadState = (recipe, records, mode) => {
18206
+ for (const record of records) {
18207
+ const text = badStateTextForRecord(record);
18208
+ const state = recipe.badStates.find((candidate) => shouldMatchBadState(candidate, mode) && candidate.markers.some((marker) => text.includes(marker.toLowerCase())));
18209
+ if (state) {
18210
+ return {
18211
+ state,
18212
+ reasonCode: normalizeBadStateReasonCode(state)
18213
+ };
18214
+ }
18215
+ }
18216
+ return void 0;
18217
+ };
18218
+ var findHardFailure = (failures) => failures.find((failure) => {
18219
+ const reasonCode = failure.error.reasonCode ?? failure.error.details?.reasonCode;
18220
+ return typeof reasonCode === "string" && isProviderReasonCode(reasonCode) && HARD_FAILURE_REASON_CODES.has(reasonCode);
18221
+ });
18222
+ var reasonCodeForFailure = (failure) => {
18223
+ const reasonCode = failure.error.reasonCode ?? failure.error.details?.reasonCode;
18224
+ return typeof reasonCode === "string" && isProviderReasonCode(reasonCode) ? reasonCode : void 0;
18225
+ };
18226
+ var buildBadStateResult = (input, source, searchUrl, fetchedRecordCount, badState) => ({
18227
+ records: [],
18228
+ failures: [{
18229
+ provider: input.recipe.id,
18230
+ source,
18231
+ error: createProviderError(
18232
+ providerErrorCodeFromReasonCode(badState.reasonCode),
18233
+ badState.state.recoveryAction,
18234
+ {
18235
+ retryable: true,
18236
+ reasonCode: badState.reasonCode,
18237
+ provider: input.recipe.id,
18238
+ source,
18239
+ details: {
18240
+ siteRecipeId: input.recipe.id,
18241
+ query: input.query,
18242
+ searchUrl,
18243
+ badStateId: badState.state.id
18244
+ }
18245
+ }
18246
+ )
18247
+ }],
18248
+ diagnostics: {
18249
+ siteRecipeId: input.recipe.id,
18250
+ attempted: true,
18251
+ reason: badState.reasonCode,
18252
+ searchUrl,
18253
+ fetchedRecordCount,
18254
+ badStateId: badState.state.id,
18255
+ recoveryAction: badState.state.recoveryAction
18256
+ }
18257
+ });
18258
+ var buildHardFailureResult = (input, source, searchUrl, fetchedRecordCount, failure) => ({
18259
+ records: [],
18260
+ failures: [failure],
18261
+ diagnostics: {
18262
+ siteRecipeId: input.recipe.id,
18263
+ attempted: true,
18264
+ reason: reasonCodeForFailure(failure) ?? "challenge_detected",
18265
+ searchUrl,
18266
+ fetchedRecordCount,
18267
+ recoveryAction: failure.error.message
18268
+ }
18269
+ });
18270
+ var extractRecipeReferenceUrls = (input, records, maxReferences) => {
18271
+ const extractor = input.recipe.browserNativeDiscovery?.extractReferenceUrls;
18272
+ if (!extractor) return [];
18273
+ const urls = [];
18274
+ const seen = /* @__PURE__ */ new Set();
18275
+ const pushUrl = (url) => {
18276
+ if (!url || seen.has(url)) return;
18277
+ seen.add(url);
18278
+ urls.push(url);
18279
+ };
18280
+ for (const record of records) {
18281
+ extractor({
18282
+ url: record.url ?? void 0,
18283
+ content: record.content ?? void 0,
18284
+ html: typeof record.attributes.html === "string" ? record.attributes.html : void 0,
18285
+ links: linksFromRecord(record)
18286
+ }).forEach(pushUrl);
18287
+ if (urls.length >= maxReferences) break;
18288
+ }
18289
+ return urls.slice(0, maxReferences);
18290
+ };
18291
+ var buildRecipeReferenceRecord = (input, url, index) => {
18292
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
18293
+ return {
18294
+ id: `${input.recipe.id}:reference:${index + 1}:${timestamp}`,
18295
+ source: sourceForRecipe(input.recipe),
18296
+ provider: input.recipe.id,
18297
+ url,
18298
+ title: `Site visual reference ${index + 1} for ${input.query}`,
18299
+ content: input.recipe.navigationSteps.map((step) => step.instruction).join(" "),
18300
+ timestamp,
18301
+ confidence: 0.72,
18302
+ attributes: {
18303
+ siteRecipeId: input.recipe.id,
18304
+ discoveryMode: "browser_native_extracted_reference",
18305
+ authMode: input.recipe.authMode,
18306
+ maxReferences: input.maxReferences,
18307
+ validationChecks: input.recipe.evidenceRequirements.map((entry) => entry.validation)
18308
+ }
18309
+ };
18310
+ };
18311
+ var runBrowserNativeDiscovery = async (input) => {
18312
+ const source = sourceForRecipe(input.recipe);
18313
+ const searchUrl = input.recipe.browserNativeDiscovery?.buildSearchUrl(input.query);
18314
+ if (!searchUrl) {
18315
+ return {
18316
+ records: [],
18317
+ failures: [{
18318
+ provider: input.recipe.id,
18319
+ source,
18320
+ error: createProviderError(
18321
+ "unavailable",
18322
+ `Site recipe ${input.recipe.id} does not define browser-native discovery.`,
18323
+ {
18324
+ retryable: false,
18325
+ reasonCode: "env_limited",
18326
+ provider: input.recipe.id,
18327
+ source,
18328
+ details: {
18329
+ siteRecipeId: input.recipe.id,
18330
+ query: input.query
18331
+ }
18332
+ }
18333
+ )
18334
+ }],
18335
+ diagnostics: {
18336
+ siteRecipeId: input.recipe.id,
18337
+ attempted: false,
18338
+ reason: "unsupported_site_recipe"
18339
+ }
18340
+ };
18341
+ }
18342
+ if (needsAuthenticatedBrowser(input) && !hasAuthenticatedBrowser(input)) {
18343
+ return {
18344
+ records: [],
18345
+ failures: [{
18346
+ provider: input.recipe.id,
18347
+ source,
18348
+ error: createProviderError(
18349
+ "auth",
18350
+ `${input.recipe.id} requires an authenticated browser session before search results are visible.`,
18351
+ {
18352
+ retryable: true,
18353
+ reasonCode: "auth_required",
18354
+ provider: input.recipe.id,
18355
+ source,
18356
+ details: {
18357
+ siteRecipeId: input.recipe.id,
18358
+ query: input.query,
18359
+ requiredBrowserMode: "extension",
18360
+ requiredCookies: true
18361
+ }
18362
+ }
18363
+ )
18364
+ }],
18365
+ diagnostics: {
18366
+ siteRecipeId: input.recipe.id,
18367
+ attempted: false,
18368
+ reason: "auth_required",
18369
+ recoverySteps: input.recipe.recoverySteps.map((step) => step.instruction)
18370
+ }
18371
+ };
18372
+ }
18373
+ if (!input.fetchSearchPage) {
18374
+ return {
18375
+ records: [],
18376
+ failures: [{
18377
+ provider: input.recipe.id,
18378
+ source,
18379
+ error: createProviderError(
18380
+ "unavailable",
18381
+ `${input.recipe.id} browser-native discovery requires a browser-backed fetch executor for the search page.`,
18382
+ {
18383
+ retryable: true,
18384
+ reasonCode: "env_limited",
18385
+ provider: input.recipe.id,
18386
+ source,
18387
+ details: {
18388
+ siteRecipeId: input.recipe.id,
18389
+ query: input.query,
18390
+ searchUrl
18391
+ }
18392
+ }
18393
+ )
18394
+ }],
18395
+ diagnostics: {
18396
+ siteRecipeId: input.recipe.id,
18397
+ attempted: false,
18398
+ reason: "fetch_executor_missing",
18399
+ searchUrl
18400
+ }
18401
+ };
18402
+ }
18403
+ const fetched = await input.fetchSearchPage(searchUrl);
18404
+ const hardFailure = findHardFailure(fetched.failures);
18405
+ if (hardFailure) {
18406
+ return buildHardFailureResult(input, source, searchUrl, fetched.records.length, hardFailure);
18407
+ }
18408
+ const preExtractionMode = needsAuthenticatedBrowser(input) ? "pre_extraction" : "hard_blocker";
18409
+ const hardBlocker = findBadState(input.recipe, fetched.records, preExtractionMode);
18410
+ if (hardBlocker) {
18411
+ return buildBadStateResult(input, source, searchUrl, fetched.records.length, hardBlocker);
18412
+ }
18413
+ const extractedUrls = extractRecipeReferenceUrls(input, fetched.records, input.maxReferences);
18414
+ if (extractedUrls.length === 0) {
18415
+ const shellState = fetched.failures.length === 0 ? findBadState(input.recipe, fetched.records, "all") : void 0;
18416
+ if (shellState) {
18417
+ return buildBadStateResult(input, source, searchUrl, fetched.records.length, shellState);
18418
+ }
18419
+ return {
18420
+ records: [],
18421
+ failures: fetched.failures.length > 0 ? fetched.failures : [{
18422
+ provider: input.recipe.id,
18423
+ source,
18424
+ error: createProviderError(
18425
+ "unavailable",
18426
+ fetched.errorMessage ?? `${input.recipe.id} search did not expose recipe-approved URLs that can be used as references.`,
18427
+ {
18428
+ retryable: true,
18429
+ reasonCode: "env_limited",
18430
+ provider: input.recipe.id,
18431
+ source,
18432
+ details: {
18433
+ siteRecipeId: input.recipe.id,
18434
+ query: input.query,
18435
+ searchUrl
18436
+ }
18437
+ }
18438
+ )
18439
+ }],
18440
+ diagnostics: {
18441
+ siteRecipeId: input.recipe.id,
18442
+ attempted: true,
18443
+ reason: "no_reference_urls_extracted",
18444
+ searchUrl,
18445
+ fetchedRecordCount: fetched.records.length
18446
+ }
18447
+ };
18448
+ }
18449
+ return {
18450
+ records: extractedUrls.map((url, index) => buildRecipeReferenceRecord(input, url, index)),
18451
+ failures: [],
18452
+ diagnostics: {
18453
+ siteRecipeId: input.recipe.id,
18454
+ attempted: true,
18455
+ reason: "reference_urls_extracted",
18456
+ searchUrl,
18457
+ navigationSteps: input.recipe.navigationSteps.map((step) => step.instruction),
18458
+ badStates: input.recipe.badStates.map((state) => state.id),
18459
+ extractedUrlCount: extractedUrls.length
18460
+ }
18461
+ };
18462
+ };
15848
18463
 
15849
18464
  // src/providers/workflows.ts
15850
18465
  var SIGNAL_WINDOW = 50;
@@ -16105,7 +18720,15 @@ var withPrimaryConstraintMeta = (meta, failures) => {
16105
18720
  var withCamelCasePrimaryConstraintMeta = withPrimaryConstraintMeta;
16106
18721
  var readPrimaryConstraintGuidance = (constraint) => {
16107
18722
  const guidance = constraint.guidance;
16108
- return guidance && typeof guidance === "object" && !Array.isArray(guidance) ? guidance : void 0;
18723
+ if (!guidance || typeof guidance !== "object" || Array.isArray(guidance)) return void 0;
18724
+ const record = guidance;
18725
+ if (typeof record.reason !== "string") return void 0;
18726
+ if (!Array.isArray(record.recommendedNextCommands)) return void 0;
18727
+ if (!record.recommendedNextCommands.every((command) => typeof command === "string")) return void 0;
18728
+ return {
18729
+ reason: record.reason,
18730
+ recommendedNextCommands: record.recommendedNextCommands
18731
+ };
16109
18732
  };
16110
18733
  var withPrimaryConstraintSummaryOverride = (meta, summary, guidance) => {
16111
18734
  const currentPrimaryConstraint = meta.primaryConstraint;
@@ -16396,6 +19019,9 @@ var workflowTestUtils = {
16396
19019
  redactRawCapture: (record) => redactRawCapture(record),
16397
19020
  toProviderSource: (providerId) => toProviderSource2(providerId),
16398
19021
  resolveShoppingProviderIdForUrl: (url) => resolveShoppingProviderIdForUrl(url),
19022
+ resolveShoppingSourceForUrl: (url) => resolveShoppingSourceForUrl(url),
19023
+ resolveProductCopy: (record, productUrl, refreshedDescription, featureList) => resolveProductCopy(record, productUrl, refreshedDescription, featureList),
19024
+ getRequiredProductVideoExecutionStep: (steps, stepId) => getRequiredProductVideoExecutionStep(steps, stepId),
16399
19025
  normalizeProductVideoProviderHint: (productUrl, providerHint, fallbackProvider) => normalizeProductVideoProviderHint(productUrl, providerHint, fallbackProvider),
16400
19026
  hasTranscriptSuccess: (record) => hasTranscriptSuccess(record),
16401
19027
  sanitizeFeatureList: (values) => sanitizeFeatureList(values),
@@ -16407,7 +19033,15 @@ var workflowTestUtils = {
16407
19033
  fetchBinary: (url, timeoutMs) => fetchBinary(url, timeoutMs),
16408
19034
  rankResearchRecords: (records) => rankResearchRecords(records),
16409
19035
  isValidHttpUrl: (url) => isValidHttpUrl3(url),
16410
- buildWorkflowResumePayload: (kind, input) => buildWorkflowResumePayload(kind, input)
19036
+ buildWorkflowResumePayload: (kind, input) => buildWorkflowResumePayload(kind, input),
19037
+ withPrimaryConstraintSummaryOverride: (meta, summary, guidance) => withPrimaryConstraintSummaryOverride(meta, summary, guidance),
19038
+ withReasonCodeDistributionMeta: (meta, reasonCodeDistribution) => withReasonCodeDistributionMeta(meta, reasonCodeDistribution),
19039
+ incrementReasonCodeDistribution: (reasonCodeDistribution, reasonCode, count) => incrementReasonCodeDistribution(reasonCodeDistribution, reasonCode, count),
19040
+ summarizeShoppingOfferFilterConstraint: (args) => summarizeShoppingOfferFilterConstraint(args),
19041
+ parseInspiredesignEnvelopeInput: (input) => parseInspiredesignEnvelopeInput(input),
19042
+ failureFromInspiredesignDiscoveryError: (workflowInput, error) => failureFromInspiredesignDiscoveryError(workflowInput, error),
19043
+ failureFromInspiredesignFetchError: (result) => failureFromInspiredesignFetchError(result),
19044
+ extractProductBrandFromTitle: (title, productUrl) => extractProductBrandFromTitle(title, productUrl)
16411
19045
  };
16412
19046
  var PRODUCT_ASSET_FETCH_TIMEOUT_MS = 15e3;
16413
19047
  var RESEARCH_PROVIDER_STEP_TIMEOUT_MS = 3e4;
@@ -16459,7 +19093,7 @@ var rankResearchRecords = (records) => {
16459
19093
  return left.id.localeCompare(right.id);
16460
19094
  });
16461
19095
  };
16462
- var hash2 = (value) => createHash7("sha1").update(value).digest("hex").slice(0, 16);
19096
+ var hash2 = (value) => createHash8("sha1").update(value).digest("hex").slice(0, 16);
16463
19097
  var RESEARCH_ALWAYS_SANITIZED_PATHS = /* @__PURE__ */ new Set([
16464
19098
  "community:search:index",
16465
19099
  "community:search:url",
@@ -16655,8 +19289,17 @@ var INSPIREDESIGN_RENDER_MODES = /* @__PURE__ */ new Set(["compact", "json", "md
16655
19289
  var INSPIREDESIGN_CAPTURE_MODES = /* @__PURE__ */ new Set(["off", "deep"]);
16656
19290
  var INSPIREDESIGN_COOKIE_POLICIES = /* @__PURE__ */ new Set(["off", "auto", "required"]);
16657
19291
  var WORKFLOW_BROWSER_MODES = /* @__PURE__ */ new Set(["auto", "extension", "managed"]);
19292
+ var INSPIREDESIGN_DEFAULT_MAX_REFERENCES = 5;
19293
+ var INSPIREDESIGN_MAX_REFERENCES_LIMIT = 10;
16658
19294
  var isJsonRecord7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
16659
19295
  var INSPIREDESIGN_CAPTURE_UNAVAILABLE_FAILURE = "Deep capture requested, but browser capture is unavailable in this execution lane.";
19296
+ var REQUIRED_VISUAL_EVIDENCE_MISSING_FAILURE = "Required visual evidence was not captured.";
19297
+ var INSPIREDESIGN_VISUAL_POLICY_BLOCKER_REASONS = /* @__PURE__ */ new Set([
19298
+ "policy_blocked",
19299
+ "auth_required",
19300
+ "challenge_detected",
19301
+ "rate_limited"
19302
+ ]);
16660
19303
  var isCanvasVisualDirectionProfile = (value) => {
16661
19304
  return CANVAS_VISUAL_DIRECTION_PROFILES.includes(value);
16662
19305
  };
@@ -16670,6 +19313,11 @@ var serializeInspiredesignBriefExpansion = (expansion) => structuredClone(expans
16670
19313
  var serializeInspiredesignRunInput = (input) => ({
16671
19314
  brief: input.brief,
16672
19315
  briefExpansion: serializeInspiredesignBriefExpansion(input.briefExpansion),
19316
+ ...input.harvest === true ? { harvest: true } : {},
19317
+ ...input.query ? { query: input.query } : {},
19318
+ ...input.providers.length > 0 ? { providers: input.providers } : {},
19319
+ ...input.referenceLimit !== void 0 ? { maxReferences: input.maxReferences } : {},
19320
+ visualEvidence: input.visualEvidence,
16673
19321
  urls: input.urls,
16674
19322
  captureMode: input.captureMode,
16675
19323
  mode: input.mode,
@@ -16745,6 +19393,11 @@ var parseInspiredesignEnvelopeInput = (input) => {
16745
19393
  return {
16746
19394
  brief: typeof input.brief === "string" ? input.brief : "",
16747
19395
  mode: typeof input.mode === "string" && INSPIREDESIGN_RENDER_MODES.has(input.mode) ? input.mode : "compact",
19396
+ ...typeof input.harvest === "boolean" ? { harvest: input.harvest } : {},
19397
+ ...typeof input.query === "string" && input.query.trim().length > 0 ? { query: input.query.trim() } : {},
19398
+ ...Array.isArray(input.providers) ? { providers: input.providers.filter((provider) => typeof provider === "string") } : {},
19399
+ ...typeof input.maxReferences === "number" ? { maxReferences: input.maxReferences } : {},
19400
+ ...isInspiredesignVisualEvidenceMode(input.visualEvidence) ? { visualEvidence: input.visualEvidence } : {},
16748
19401
  ...briefExpansion ? { briefExpansion } : {},
16749
19402
  ...Array.isArray(input.urls) ? { urls: input.urls.filter((url) => typeof url === "string") } : {},
16750
19403
  ...typeof input.captureMode === "string" && INSPIREDESIGN_CAPTURE_MODES.has(input.captureMode) ? { captureMode: input.captureMode } : {},
@@ -16767,6 +19420,24 @@ var normalizeInspiredesignUrls = (urls) => {
16767
19420
  }
16768
19421
  return [...new Set(normalized.map((url) => canonicalizeUrl(url)))];
16769
19422
  };
19423
+ var normalizeInspiredesignMaxReferences = (value, fallbackCount) => {
19424
+ if (typeof value === "undefined") {
19425
+ return Math.max(1, Math.min(Math.max(fallbackCount, 1), INSPIREDESIGN_MAX_REFERENCES_LIMIT));
19426
+ }
19427
+ if (!Number.isInteger(value) || value < 1 || value > INSPIREDESIGN_MAX_REFERENCES_LIMIT) {
19428
+ throw new Error("Inspiredesign workflow maxReferences must be an integer from 1 to 10.");
19429
+ }
19430
+ return value;
19431
+ };
19432
+ var normalizeInspiredesignVisualEvidenceMode = (value, harvest) => {
19433
+ if (typeof value === "undefined") {
19434
+ return harvest === true ? "required" : "off";
19435
+ }
19436
+ if (!isInspiredesignVisualEvidenceMode(value)) {
19437
+ throw new Error("Inspiredesign workflow visualEvidence must be one of off, auto, or required.");
19438
+ }
19439
+ return value;
19440
+ };
16770
19441
  var hasValidInspiredesignBriefRoute = (route) => {
16771
19442
  return isCanvasVisualDirectionProfile(route.profile) && isCanvasThemeStrategy(route.themeStrategy) && isCanvasNavigationModel(route.navigationModel);
16772
19443
  };
@@ -16788,6 +19459,23 @@ var normalizeInspiredesignInput = (input) => {
16788
19459
  throw new Error("Inspiredesign workflow requires a non-empty brief.");
16789
19460
  }
16790
19461
  const urls = normalizeInspiredesignUrls(input.urls);
19462
+ const query = typeof input.query === "string" && input.query.trim().length > 0 ? input.query.trim() : void 0;
19463
+ const providers = normalizeInspiredesignProviders(input.providers);
19464
+ const hasExplicitMaxReferences = typeof input.maxReferences !== "undefined";
19465
+ if (query && input.harvest !== true) {
19466
+ throw new Error("Inspiredesign workflow query is only supported when harvest is true.");
19467
+ }
19468
+ if (providers.length > 0 && !query) {
19469
+ throw new Error("Inspiredesign workflow providers require query.");
19470
+ }
19471
+ if (input.harvest === true && !query && urls.length === 0) {
19472
+ throw new Error("Inspiredesign harvest requires query or URL references.");
19473
+ }
19474
+ const visualEvidence = normalizeInspiredesignVisualEvidenceMode(
19475
+ input.visualEvidence,
19476
+ input.harvest
19477
+ );
19478
+ const maxReferencesFallback = query || input.harvest === true ? INSPIREDESIGN_DEFAULT_MAX_REFERENCES : urls.length;
16791
19479
  const normalizedBrief = normalizeInspiredesignBriefText(brief);
16792
19480
  const preferredFormatId = shouldReuseInspiredesignBriefExpansion(input.briefExpansion, normalizedBrief) ? input.briefExpansion.format.id : void 0;
16793
19481
  const briefExpansion = expandInspiredesignBrief(brief, preferredFormatId);
@@ -16795,9 +19483,14 @@ var normalizeInspiredesignInput = (input) => {
16795
19483
  ...input,
16796
19484
  brief,
16797
19485
  briefExpansion,
19486
+ ...query ? { query } : {},
19487
+ providers,
19488
+ maxReferences: normalizeInspiredesignMaxReferences(input.maxReferences, maxReferencesFallback),
19489
+ ...query || input.harvest === true || hasExplicitMaxReferences ? { referenceLimit: normalizeInspiredesignMaxReferences(input.maxReferences, maxReferencesFallback) } : {},
19490
+ visualEvidence,
16798
19491
  urls,
16799
19492
  captureMode: resolveInspiredesignCaptureMode(input.captureMode, urls),
16800
- mode: input.mode ?? "compact"
19493
+ mode: input.mode ?? (input.harvest === true ? "path" : "compact")
16801
19494
  };
16802
19495
  };
16803
19496
  var isInspiredesignWorkflowEnvelopeInput = (input) => {
@@ -16845,10 +19538,11 @@ var buildInspiredesignStepEnvelope = (workflowInput, trace, stepIndex, url) => b
16845
19538
  trace
16846
19539
  }
16847
19540
  );
16848
- var buildInspiredesignFetchOptions = (workflowInput, envelope, timeoutMs) => withWorkflowResumeEnvelopeIntent(
19541
+ var buildInspiredesignFetchOptionsWithScope = (workflowInput, envelope, providerScope, timeoutMs) => withWorkflowResumeEnvelopeIntent(
16849
19542
  withBrowserModeOverride(
16850
19543
  withChallengeAutomationOverride(
16851
19544
  withCookieOverrides({
19545
+ ...providerScope,
16852
19546
  ...typeof timeoutMs === "number" ? { timeoutMs } : {}
16853
19547
  }, workflowInput),
16854
19548
  workflowInput
@@ -16858,6 +19552,252 @@ var buildInspiredesignFetchOptions = (workflowInput, envelope, timeoutMs) => wit
16858
19552
  "workflow.inspiredesign",
16859
19553
  envelope
16860
19554
  );
19555
+ var buildInspiredesignFetchOptions = (workflowInput, envelope, timeoutMs) => {
19556
+ const siteRecipeProviderIds = new Set(
19557
+ workflowInput.providers.filter((providerId) => resolveSiteRecipeForProvider(providerId) !== void 0)
19558
+ );
19559
+ const standardProviderIds = workflowInput.providers.filter((providerId) => !siteRecipeProviderIds.has(providerId));
19560
+ let providerScope = {};
19561
+ if (workflowInput.providers.length > 0 && standardProviderIds.length === 0) {
19562
+ providerScope = { source: "web" };
19563
+ } else if (standardProviderIds.length > 0) {
19564
+ providerScope = { providerIds: standardProviderIds };
19565
+ }
19566
+ return buildInspiredesignFetchOptionsWithScope(workflowInput, envelope, providerScope, timeoutMs);
19567
+ };
19568
+ var buildInspiredesignSiteRecipeFetchOptions = (workflowInput, envelope, timeoutMs) => buildInspiredesignFetchOptionsWithScope(
19569
+ workflowInput,
19570
+ envelope,
19571
+ { source: "web" },
19572
+ timeoutMs
19573
+ );
19574
+ var buildInspiredesignReferenceFetchOptions = (workflowInput, envelope, url, timeoutMs) => resolveSiteRecipeForUrl(url) ? buildInspiredesignSiteRecipeFetchOptions(workflowInput, envelope, timeoutMs) : buildInspiredesignFetchOptions(workflowInput, envelope, timeoutMs);
19575
+ var emptyInspiredesignDiscoveryDiagnostics = (workflowInput, searchAvailable, failure) => ({
19576
+ requested: Boolean(workflowInput.query),
19577
+ searchAvailable,
19578
+ ...workflowInput.query ? { query: workflowInput.query } : {},
19579
+ providers: workflowInput.providers,
19580
+ acceptedUrls: [],
19581
+ rejected: [],
19582
+ failures: [],
19583
+ ...failure ? { failure } : {}
19584
+ });
19585
+ var providerFromInspiredesignDiscoveryFailure = (workflowInput, error) => {
19586
+ const provider = error.provider ?? workflowInput.providers[0];
19587
+ const source = error.source ?? (provider ? toProviderSource2(provider) : null);
19588
+ return provider && source ? { provider, source } : void 0;
19589
+ };
19590
+ var failureFromInspiredesignDiscoveryError = (workflowInput, error) => {
19591
+ if (!error) return [];
19592
+ const provider = providerFromInspiredesignDiscoveryFailure(workflowInput, error);
19593
+ if (!provider) return [];
19594
+ return [{
19595
+ provider: provider.provider,
19596
+ source: provider.source,
19597
+ error
19598
+ }];
19599
+ };
19600
+ var providerFromInspiredesignFetchFailure = (result) => {
19601
+ const provider = result.error?.provider ?? result.providerOrder[0];
19602
+ const source = result.error?.source ?? (provider ? toProviderSource2(provider) : null);
19603
+ return provider && source ? { provider, source } : void 0;
19604
+ };
19605
+ var failureFromInspiredesignFetchError = (result) => {
19606
+ if (!result.error || result.failures.length > 0) return [];
19607
+ const provider = providerFromInspiredesignFetchFailure(result);
19608
+ if (!provider) return [];
19609
+ return [{
19610
+ provider: provider.provider,
19611
+ source: provider.source,
19612
+ error: result.error
19613
+ }];
19614
+ };
19615
+ var normalizeSiteRecipeFetchFailures = (siteRecipe, failures) => {
19616
+ const source = toProviderSource2(siteRecipe.id) ?? "web";
19617
+ return failures.map((failure) => ({
19618
+ provider: siteRecipe.id,
19619
+ source,
19620
+ error: {
19621
+ ...failure.error,
19622
+ provider: siteRecipe.id,
19623
+ source,
19624
+ details: {
19625
+ ...failure.error.details ?? {},
19626
+ upstreamProvider: failure.provider,
19627
+ upstreamSource: failure.source
19628
+ }
19629
+ }
19630
+ }));
19631
+ };
19632
+ var appendNextUniqueDiscoveryCandidate = (queue, cursor, seen, accepted) => {
19633
+ let nextCursor = cursor;
19634
+ while (nextCursor < queue.length) {
19635
+ const candidate = queue[nextCursor];
19636
+ nextCursor += 1;
19637
+ if (!candidate || seen.has(candidate.url)) continue;
19638
+ seen.add(candidate.url);
19639
+ accepted.push(candidate);
19640
+ return nextCursor;
19641
+ }
19642
+ return nextCursor;
19643
+ };
19644
+ var capMixedInspiredesignDiscovery = (siteDiscovery, standardDiscovery, maxReferences) => {
19645
+ const accepted = [];
19646
+ const seen = /* @__PURE__ */ new Set();
19647
+ let siteCursor = 0;
19648
+ let standardCursor = 0;
19649
+ while (accepted.length < maxReferences && (siteCursor < siteDiscovery.accepted.length || standardCursor < standardDiscovery.accepted.length)) {
19650
+ siteCursor = appendNextUniqueDiscoveryCandidate(siteDiscovery.accepted, siteCursor, seen, accepted);
19651
+ if (accepted.length >= maxReferences) break;
19652
+ standardCursor = appendNextUniqueDiscoveryCandidate(standardDiscovery.accepted, standardCursor, seen, accepted);
19653
+ }
19654
+ return {
19655
+ accepted,
19656
+ rejected: [...siteDiscovery.rejected, ...standardDiscovery.rejected]
19657
+ };
19658
+ };
19659
+ var discoverInspiredesignReferences = async (runtime, workflowInput, envelope, timeoutMs) => {
19660
+ if (!workflowInput.query) {
19661
+ return emptyInspiredesignDiscoveryDiagnostics(workflowInput, typeof runtime.search === "function");
19662
+ }
19663
+ const query = workflowInput.query;
19664
+ const siteRecipe = workflowInput.providers.map((providerId) => resolveSiteRecipeForProvider(providerId)).find((recipe) => recipe !== void 0);
19665
+ const siteRecipeProviderIds = new Set(
19666
+ workflowInput.providers.filter((providerId) => resolveSiteRecipeForProvider(providerId) !== void 0)
19667
+ );
19668
+ const standardProviderIds = workflowInput.providers.filter((providerId) => !siteRecipeProviderIds.has(providerId));
19669
+ if (siteRecipe) {
19670
+ const runSiteRecipeDiscovery = async () => runBrowserNativeDiscovery({
19671
+ recipe: siteRecipe,
19672
+ query,
19673
+ maxReferences: workflowInput.referenceLimit ?? workflowInput.maxReferences,
19674
+ ...workflowInput.browserMode ? { browserMode: workflowInput.browserMode } : {},
19675
+ ...typeof workflowInput.useCookies === "boolean" ? { useCookies: workflowInput.useCookies } : {},
19676
+ ...workflowInput.cookiePolicyOverride ? { cookiePolicy: workflowInput.cookiePolicyOverride } : {},
19677
+ fetchSearchPage: async (url) => {
19678
+ const result = normalizeInspiredesignFetchResult(await runtime.fetch(
19679
+ { url },
19680
+ buildInspiredesignSiteRecipeFetchOptions(workflowInput, envelope, timeoutMs)
19681
+ ));
19682
+ const failures = result.failures.length > 0 ? result.failures : failureFromInspiredesignFetchError(result);
19683
+ return {
19684
+ records: result.records,
19685
+ failures: normalizeSiteRecipeFetchFailures(siteRecipe, failures),
19686
+ ...result.error?.message ? { errorMessage: result.error.message } : {}
19687
+ };
19688
+ }
19689
+ });
19690
+ if (standardProviderIds.length > 0 && typeof runtime.search === "function") {
19691
+ try {
19692
+ const searchResult2 = await runtime.search(
19693
+ {
19694
+ query,
19695
+ limit: workflowInput.maxReferences
19696
+ },
19697
+ {
19698
+ ...buildInspiredesignFetchOptions(workflowInput, envelope, timeoutMs),
19699
+ providerIds: standardProviderIds
19700
+ }
19701
+ );
19702
+ const searchFailures = searchResult2.failures.length > 0 ? searchResult2.failures : failureFromInspiredesignDiscoveryError({ ...workflowInput, providers: standardProviderIds }, searchResult2.error);
19703
+ const discovery3 = normalizeInspiredesignDiscoveryRecords(searchResult2.records);
19704
+ const siteResult2 = await runSiteRecipeDiscovery();
19705
+ const siteDiscovery = normalizeInspiredesignDiscoveryRecords(siteResult2.records);
19706
+ const combinedDiscovery = capMixedInspiredesignDiscovery(
19707
+ siteDiscovery,
19708
+ discovery3,
19709
+ workflowInput.referenceLimit ?? workflowInput.maxReferences
19710
+ );
19711
+ const failures = [...searchFailures, ...siteResult2.failures];
19712
+ return {
19713
+ requested: true,
19714
+ searchAvailable: true,
19715
+ query,
19716
+ providers: workflowInput.providers,
19717
+ acceptedUrls: combinedDiscovery.accepted.map((candidate) => candidate.url),
19718
+ rejected: combinedDiscovery.rejected,
19719
+ failures,
19720
+ ...failures[0]?.error.message ? { failure: failures[0].error.message } : {},
19721
+ siteRecipeId: siteRecipe.id,
19722
+ browserNativeDiagnostics: {
19723
+ ...siteResult2.diagnostics,
19724
+ standardAcceptedCount: discovery3.accepted.length,
19725
+ standardRejectedCount: discovery3.rejected.length,
19726
+ siteAcceptedCount: siteDiscovery.accepted.length,
19727
+ cappedAcceptedCount: combinedDiscovery.accepted.length
19728
+ }
19729
+ };
19730
+ } catch (error) {
19731
+ const siteResult2 = await runSiteRecipeDiscovery();
19732
+ const discovery3 = normalizeInspiredesignDiscoveryRecords(siteResult2.records);
19733
+ return {
19734
+ requested: true,
19735
+ searchAvailable: true,
19736
+ query,
19737
+ providers: workflowInput.providers,
19738
+ acceptedUrls: discovery3.accepted.map((candidate) => candidate.url),
19739
+ rejected: discovery3.rejected,
19740
+ failures: siteResult2.failures,
19741
+ failure: error instanceof Error ? error.message : "Reference discovery failed.",
19742
+ siteRecipeId: siteRecipe.id,
19743
+ browserNativeDiagnostics: siteResult2.diagnostics
19744
+ };
19745
+ }
19746
+ }
19747
+ const siteResult = await runSiteRecipeDiscovery();
19748
+ const discovery2 = normalizeInspiredesignDiscoveryRecords(siteResult.records);
19749
+ return {
19750
+ requested: true,
19751
+ searchAvailable: true,
19752
+ query,
19753
+ providers: workflowInput.providers,
19754
+ acceptedUrls: discovery2.accepted.map((candidate) => candidate.url),
19755
+ rejected: discovery2.rejected,
19756
+ failures: siteResult.failures,
19757
+ ...siteResult.failures[0]?.error.message ? { failure: siteResult.failures[0].error.message } : {},
19758
+ siteRecipeId: siteRecipe.id,
19759
+ browserNativeDiagnostics: siteResult.diagnostics
19760
+ };
19761
+ }
19762
+ if (typeof runtime.search !== "function") {
19763
+ return emptyInspiredesignDiscoveryDiagnostics(
19764
+ workflowInput,
19765
+ false,
19766
+ "Reference discovery requested, but provider search is unavailable in this execution lane."
19767
+ );
19768
+ }
19769
+ let searchResult;
19770
+ try {
19771
+ searchResult = await runtime.search(
19772
+ {
19773
+ query: workflowInput.query,
19774
+ limit: workflowInput.maxReferences
19775
+ },
19776
+ {
19777
+ ...buildInspiredesignFetchOptions(workflowInput, envelope, timeoutMs),
19778
+ ...workflowInput.providers.length > 0 ? { providerIds: workflowInput.providers } : {}
19779
+ }
19780
+ );
19781
+ } catch (error) {
19782
+ return emptyInspiredesignDiscoveryDiagnostics(
19783
+ workflowInput,
19784
+ true,
19785
+ error instanceof Error ? error.message : "Reference discovery failed."
19786
+ );
19787
+ }
19788
+ const discovery = normalizeInspiredesignDiscoveryRecords(searchResult.records);
19789
+ const discoveryFailures = searchResult.failures.length > 0 ? searchResult.failures : failureFromInspiredesignDiscoveryError(workflowInput, searchResult.error);
19790
+ return {
19791
+ requested: true,
19792
+ searchAvailable: true,
19793
+ query: workflowInput.query,
19794
+ providers: workflowInput.providers,
19795
+ acceptedUrls: discovery.accepted.map((candidate) => candidate.url),
19796
+ rejected: discovery.rejected,
19797
+ failures: discoveryFailures,
19798
+ ...searchResult.error?.message ? { failure: searchResult.error.message } : {}
19799
+ };
19800
+ };
16861
19801
  var buildEmptyInspiredesignCaptureAttemptCounts = () => ({
16862
19802
  snapshot: { captured: 0, failed: 0, skipped: 0 },
16863
19803
  clone: { captured: 0, failed: 0, skipped: 0 },
@@ -16870,6 +19810,78 @@ var buildUnavailableInspiredesignCaptureEvidence = () => ({
16870
19810
  dom: { status: "skipped", detail: INSPIREDESIGN_CAPTURE_UNAVAILABLE_FAILURE }
16871
19811
  }
16872
19812
  });
19813
+ var getInspiredesignReferenceId = (url) => createHash8("sha256").update(url).digest("hex").slice(0, 12);
19814
+ var buildVisualPolicyMetadata = (decision) => {
19815
+ if (decision.status === "allowed") return void 0;
19816
+ return {
19817
+ status: decision.status,
19818
+ kind: "viewport",
19819
+ fullPage: false,
19820
+ capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
19821
+ warnings: [`policy:${decision.reason}`],
19822
+ failure: decision.message
19823
+ };
19824
+ };
19825
+ var mergeCaptureVisualEvidence = (capture, visual) => {
19826
+ if (!visual) return capture;
19827
+ return {
19828
+ ...capture ?? {},
19829
+ visual
19830
+ };
19831
+ };
19832
+ var isVisualPolicyBlockerDecision = (decision) => INSPIREDESIGN_VISUAL_POLICY_BLOCKER_REASONS.has(decision.reason);
19833
+ var buildMissingRequiredVisualEvidence = (failure, _visualPlan) => ({
19834
+ status: "failed",
19835
+ kind: "viewport",
19836
+ fullPage: false,
19837
+ capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
19838
+ warnings: ["required_visual_evidence_missing"],
19839
+ failure
19840
+ });
19841
+ var getRequiredVisualEvidenceFailure = (workflowInput, visualPlan, capture) => {
19842
+ if (workflowInput.visualEvidence !== "required" || visualPlan.policy.status !== "allowed") return void 0;
19843
+ const visual = normalizeInspiredesignCaptureEvidence(capture)?.visual;
19844
+ if (!visual) return REQUIRED_VISUAL_EVIDENCE_MISSING_FAILURE;
19845
+ if (visual.status === "captured") return void 0;
19846
+ return visual.failure ?? REQUIRED_VISUAL_EVIDENCE_MISSING_FAILURE;
19847
+ };
19848
+ var addRequiredVisualEvidenceFailure = (capture, visualPlan, failure) => {
19849
+ const visual = normalizeInspiredesignCaptureEvidence(capture)?.visual;
19850
+ if (visual) return capture;
19851
+ return mergeCaptureVisualEvidence(capture, buildMissingRequiredVisualEvidence(failure, visualPlan));
19852
+ };
19853
+ var VISUAL_TEMP_PATH_MISMATCH_FAILURE = "Visual evidence temp path did not match the workflow capture plan.";
19854
+ var VISUAL_KIND_MISMATCH_FAILURE = "Visual evidence kind did not match the workflow capture contract.";
19855
+ var hasTrustedVisualTempPath = (visual, visualPlan) => {
19856
+ if (visual.status === "captured" && !visual.tempPath) return false;
19857
+ if (!visual.tempPath) return true;
19858
+ if (!visualPlan.tempPath) return false;
19859
+ return resolve(visual.tempPath) === resolve(visualPlan.tempPath);
19860
+ };
19861
+ var hasTrustedVisualKind = (visual) => isInspiredesignVisualEvidenceKind(visual.kind);
19862
+ var readRuntimeVisualWarnings = (visual) => {
19863
+ const warnings = visual.warnings;
19864
+ return Array.isArray(warnings) ? warnings.filter((warning) => typeof warning === "string") : [];
19865
+ };
19866
+ var failMismatchedVisualTempPath = (visual, failure = VISUAL_TEMP_PATH_MISMATCH_FAILURE, warning = "visual_temp_path_mismatch") => ({
19867
+ status: "failed",
19868
+ kind: hasTrustedVisualKind(visual) ? visual.kind : "viewport",
19869
+ fullPage: visual.fullPage,
19870
+ capturedAt: visual.capturedAt,
19871
+ warnings: [...readRuntimeVisualWarnings(visual), warning],
19872
+ failure
19873
+ });
19874
+ var trustRuntimeVisualEvidence = (visual, visualPlan) => {
19875
+ if (!visual) return void 0;
19876
+ if (!hasTrustedVisualKind(visual)) {
19877
+ return failMismatchedVisualTempPath(
19878
+ visual,
19879
+ VISUAL_KIND_MISMATCH_FAILURE,
19880
+ "visual_kind_mismatch"
19881
+ );
19882
+ }
19883
+ return hasTrustedVisualTempPath(visual, visualPlan) ? visual : failMismatchedVisualTempPath(visual);
19884
+ };
16873
19885
  var PRE_ARTIFACT_CAPTURE_SKIP_MESSAGE = "Skipped after deep capture failed before artifact capture started.";
16874
19886
  var buildFailedInspiredesignCaptureEvidence = (detail) => ({
16875
19887
  attempts: {
@@ -16904,41 +19916,74 @@ var summarizeInspiredesignCaptureAttempts = (references) => {
16904
19916
  summary: formatInspiredesignCaptureAttemptSummary({ worked, didNotWork })
16905
19917
  };
16906
19918
  };
16907
- var captureInspiredesignReference = async (url, captureMode, workflowInput, captureReference, timeoutMs) => {
19919
+ var captureInspiredesignReference = async (url, captureMode, workflowInput, captureReference, visualPlan, timeoutMs) => {
19920
+ const visualPolicyMetadata = buildVisualPolicyMetadata(visualPlan.policy);
16908
19921
  if (captureMode === "off") {
16909
- return { captureStatus: "off" };
19922
+ return visualPolicyMetadata ? { captureStatus: "off", capture: { visual: visualPolicyMetadata } } : { captureStatus: "off" };
19923
+ }
19924
+ if (visualPolicyMetadata && isVisualPolicyBlockerDecision(visualPlan.policy)) {
19925
+ const captureStatus = visualPlan.policy.status === "failed" ? "failed" : "off";
19926
+ return {
19927
+ captureStatus,
19928
+ ...captureStatus === "failed" ? { captureFailure: visualPlan.policy.message } : {},
19929
+ capture: { visual: visualPolicyMetadata }
19930
+ };
16910
19931
  }
16911
19932
  if (!captureReference) {
19933
+ const visualFailureMetadata = visualPolicyMetadata ?? (workflowInput.visualEvidence === "required" && visualPlan.policy.status === "allowed" ? buildMissingRequiredVisualEvidence(INSPIREDESIGN_CAPTURE_UNAVAILABLE_FAILURE, visualPlan) : void 0);
16912
19934
  return {
16913
19935
  captureStatus: "failed",
16914
19936
  captureFailure: INSPIREDESIGN_CAPTURE_UNAVAILABLE_FAILURE,
16915
- capture: buildUnavailableInspiredesignCaptureEvidence()
19937
+ capture: mergeCaptureVisualEvidence(
19938
+ buildUnavailableInspiredesignCaptureEvidence(),
19939
+ visualFailureMetadata
19940
+ )
16916
19941
  };
16917
19942
  }
16918
19943
  try {
16919
- const capture = normalizeInspiredesignCaptureEvidence(await captureReference(url, {
19944
+ const rawCapture = await captureReference(url, {
16920
19945
  timeoutMs,
16921
19946
  useCookies: workflowInput.useCookies,
16922
19947
  challengeAutomationMode: workflowInput.challengeAutomationMode,
16923
- cookiePolicyOverride: workflowInput.cookiePolicyOverride
16924
- }));
19948
+ cookiePolicyOverride: workflowInput.cookiePolicyOverride,
19949
+ visualEvidence: visualPlan.policy.status === "allowed" ? workflowInput.visualEvidence : "off",
19950
+ visualEvidencePath: visualPlan.policy.status === "allowed" ? visualPlan.tempPath : void 0
19951
+ });
19952
+ const capture = normalizeInspiredesignCaptureEvidence(rawCapture);
19953
+ const runtimeVisual = rawCapture?.visual;
19954
+ const trustedRuntimeVisual = trustRuntimeVisualEvidence(runtimeVisual, visualPlan);
19955
+ const captureWithRuntimeVisual = trustedRuntimeVisual ? mergeCaptureVisualEvidence(capture, trustedRuntimeVisual) : capture;
19956
+ const captureWithVisualPolicy = trustedRuntimeVisual ? captureWithRuntimeVisual : mergeCaptureVisualEvidence(captureWithRuntimeVisual, visualPolicyMetadata);
19957
+ const requiredVisualFailure = getRequiredVisualEvidenceFailure(workflowInput, visualPlan, captureWithVisualPolicy);
19958
+ const captureWithRequiredVisual = requiredVisualFailure ? addRequiredVisualEvidenceFailure(captureWithVisualPolicy, visualPlan, requiredVisualFailure) : captureWithVisualPolicy;
16925
19959
  if (!hasInspiredesignCaptureArtifacts(capture)) {
16926
19960
  return {
16927
19961
  captureStatus: "failed",
16928
19962
  captureFailure: "Deep capture did not return usable snapshot, DOM, or clone evidence.",
16929
- ...capture ? { capture } : {}
19963
+ ...captureWithRequiredVisual ? { capture: captureWithRequiredVisual } : {}
19964
+ };
19965
+ }
19966
+ if (requiredVisualFailure) {
19967
+ return {
19968
+ captureStatus: "failed",
19969
+ captureFailure: requiredVisualFailure,
19970
+ ...captureWithRequiredVisual ? { capture: captureWithRequiredVisual } : {}
16930
19971
  };
16931
19972
  }
16932
19973
  return {
16933
19974
  captureStatus: "captured",
16934
- ...capture ? { capture } : {}
19975
+ ...captureWithRequiredVisual ? { capture: captureWithRequiredVisual } : {}
16935
19976
  };
16936
19977
  } catch (error) {
16937
19978
  const captureFailure = error instanceof Error && error.message.trim() ? error.message : "Deep capture failed.";
19979
+ const visualFailureMetadata = visualPolicyMetadata ?? (workflowInput.visualEvidence === "required" && visualPlan.policy.status === "allowed" ? buildMissingRequiredVisualEvidence(captureFailure, visualPlan) : void 0);
16938
19980
  return {
16939
19981
  captureStatus: "failed",
16940
19982
  captureFailure,
16941
- capture: buildFailedInspiredesignCaptureEvidence(captureFailure)
19983
+ capture: mergeCaptureVisualEvidence(
19984
+ buildFailedInspiredesignCaptureEvidence(captureFailure),
19985
+ visualFailureMetadata
19986
+ )
16942
19987
  };
16943
19988
  }
16944
19989
  };
@@ -16983,7 +20028,11 @@ var toInspiredesignIssueFailure = (record, hint) => {
16983
20028
  };
16984
20029
  var normalizeInspiredesignFetchResult = (result) => {
16985
20030
  if (result.records.length === 0) {
16986
- return result;
20031
+ const synthesizedFailures = failureFromInspiredesignFetchError(result);
20032
+ return synthesizedFailures.length > 0 ? {
20033
+ ...result,
20034
+ failures: synthesizedFailures
20035
+ } : result;
16987
20036
  }
16988
20037
  const usableRecords = [];
16989
20038
  const unusableRecords = [];
@@ -17043,12 +20092,14 @@ var summarizeInspiredesignRecoveredFetches = (references) => references.filter(i
17043
20092
  }));
17044
20093
  var buildInspiredesignReference = (url, result, capture) => {
17045
20094
  const primary = getInspiredesignPrimaryRecord(result, url);
17046
- const normalizedCapture = normalizeInspiredesignCaptureEvidence(capture.capture);
20095
+ const baseCapture = normalizeInspiredesignCaptureEvidence(capture.capture);
20096
+ const runtimeVisual = capture.capture?.visual;
20097
+ const normalizedCapture = runtimeVisual?.tempPath ? mergeCaptureVisualEvidence(baseCapture, runtimeVisual) : baseCapture;
17047
20098
  const title = normalizePlainText(primary?.title) || titleFromInspiredesignCapture(normalizedCapture);
17048
20099
  const excerpt = excerptFromInspiredesignRecord(primary) ?? excerptFromInspiredesignCapture(normalizedCapture);
17049
20100
  const fetchStatus = result.records.length > 0 ? "captured" : "failed";
17050
20101
  return {
17051
- id: createHash7("sha256").update(url).digest("hex").slice(0, 12),
20102
+ id: getInspiredesignReferenceId(url),
17052
20103
  url,
17053
20104
  ...title ? { title } : {},
17054
20105
  ...excerpt ? { excerpt } : {},
@@ -17059,6 +20110,102 @@ var buildInspiredesignReference = (url, result, capture) => {
17059
20110
  ...normalizedCapture ? { capture: normalizedCapture } : {}
17060
20111
  };
17061
20112
  };
20113
+ var failReferenceForRequiredVisualEvidence = (reference, failure, visualEvidence, shouldFail = true) => {
20114
+ if (visualEvidence !== "required" || !shouldFail) return reference;
20115
+ return {
20116
+ ...reference,
20117
+ captureStatus: "failed",
20118
+ captureFailure: reference.captureFailure ?? failure
20119
+ };
20120
+ };
20121
+ var isPolicySkippedVisualEvidence = (visual) => visual.status === "skipped" && visual.warnings.some((warning) => warning.startsWith("policy:"));
20122
+ var finalizeInspiredesignReferenceVisual = async (reference, visualEvidence) => {
20123
+ const visual = reference.capture?.visual;
20124
+ if (!visual) {
20125
+ return { reference };
20126
+ }
20127
+ const runtimeVisual = visual;
20128
+ if (visual.status !== "captured" || !runtimeVisual.tempPath) {
20129
+ const persisted = persistInspiredesignVisualEvidence(visual);
20130
+ const referenceWithPersistedVisual = {
20131
+ ...reference,
20132
+ capture: mergeCaptureVisualEvidence(reference.capture, persisted)
20133
+ };
20134
+ return {
20135
+ reference: failReferenceForRequiredVisualEvidence(
20136
+ referenceWithPersistedVisual,
20137
+ persisted.failure ?? REQUIRED_VISUAL_EVIDENCE_MISSING_FAILURE,
20138
+ visualEvidence,
20139
+ !isPolicySkippedVisualEvidence(persisted)
20140
+ )
20141
+ };
20142
+ }
20143
+ const artifactPath = buildVisualEvidenceArtifactPath(reference.id, visual.kind);
20144
+ try {
20145
+ const buffer = await readFile(runtimeVisual.tempPath);
20146
+ if (buffer.byteLength === 0) {
20147
+ throw new Error("Visual evidence screenshot file was empty.");
20148
+ }
20149
+ const persisted = persistInspiredesignVisualEvidence(visual, {
20150
+ artifactPath,
20151
+ sha256: hashVisualEvidenceBuffer(buffer),
20152
+ bytes: buffer.byteLength
20153
+ });
20154
+ return {
20155
+ reference: {
20156
+ ...reference,
20157
+ capture: mergeCaptureVisualEvidence(reference.capture, persisted)
20158
+ },
20159
+ file: {
20160
+ path: artifactPath,
20161
+ content: buffer
20162
+ }
20163
+ };
20164
+ } catch (error) {
20165
+ const errorMessage = error instanceof Error ? error.message.trim() : "";
20166
+ const failure = errorMessage === "Visual evidence screenshot file was empty." ? errorMessage : "Visual evidence screenshot file was unavailable.";
20167
+ const persisted = persistInspiredesignVisualEvidence({
20168
+ ...visual,
20169
+ status: "failed",
20170
+ warnings: [...readRuntimeVisualWarnings(runtimeVisual), "finalize_failed"],
20171
+ failure
20172
+ });
20173
+ const referenceWithPersistedVisual = {
20174
+ ...reference,
20175
+ capture: mergeCaptureVisualEvidence(reference.capture, persisted)
20176
+ };
20177
+ return {
20178
+ reference: failReferenceForRequiredVisualEvidence(referenceWithPersistedVisual, failure, visualEvidence)
20179
+ };
20180
+ }
20181
+ };
20182
+ var finalizeInspiredesignVisualArtifacts = async (references, visualEvidence) => {
20183
+ const finalized = await Promise.all(
20184
+ references.map((reference) => finalizeInspiredesignReferenceVisual(reference, visualEvidence))
20185
+ );
20186
+ return {
20187
+ references: finalized.map((entry) => entry.reference),
20188
+ files: finalized.map((entry) => entry.file).filter((file) => Boolean(file))
20189
+ };
20190
+ };
20191
+ var buildInspiredesignVisualCapturePlan = (url, workflowInput, result, visualEvidenceTempDir) => {
20192
+ const referenceId = getInspiredesignReferenceId(url);
20193
+ const policy = decideInspiredesignVisualCapturePolicy({
20194
+ visualEvidence: workflowInput.visualEvidence,
20195
+ failures: result.failures,
20196
+ topLevelError: result.error,
20197
+ cookiePolicy: workflowInput.cookiePolicyOverride,
20198
+ hasUsableRecords: result.records.length > 0
20199
+ });
20200
+ if (policy.status !== "allowed" || !visualEvidenceTempDir) {
20201
+ return { policy, referenceId };
20202
+ }
20203
+ return {
20204
+ policy,
20205
+ referenceId,
20206
+ tempPath: join3(visualEvidenceTempDir, `${referenceId}-viewport.png`)
20207
+ };
20208
+ };
17062
20209
  var summarizeInspiredesignCaptureConstraint = (references) => {
17063
20210
  const failedReferences = references.filter((reference) => reference.captureStatus === "failed");
17064
20211
  if (failedReferences.length === 0) {
@@ -17084,14 +20231,100 @@ var summarizeInspiredesignCaptureConstraint = (references) => {
17084
20231
  var summarizeInspiredesignFetchConstraint = (references) => {
17085
20232
  return references.find((reference) => reference.fetchStatus === "failed" && !isInspiredesignFetchRecovered(reference) && typeof reference.fetchFailure === "string" && reference.fetchFailure.trim().length > 0)?.fetchFailure;
17086
20233
  };
17087
- var buildInspiredesignMeta = (runtime, workflowInput, references, failures, followthrough) => {
20234
+ var hasSurvivingInspiredesignReference = (references) => references.some((reference) => reference.fetchStatus === "captured" || reference.captureStatus === "captured");
20235
+ var INSPIREDESIGN_HARD_DISCOVERY_REASON_CODES = /* @__PURE__ */ new Set([
20236
+ "auth_required",
20237
+ "challenge_detected",
20238
+ "policy_blocked",
20239
+ "rate_limited",
20240
+ "token_required"
20241
+ ]);
20242
+ var readInspiredesignFailureReasonCode = (failure) => {
20243
+ const reasonCode = failure.error.reasonCode ?? failure.error.details?.reasonCode;
20244
+ return typeof reasonCode === "string" && INSPIREDESIGN_HARD_DISCOVERY_REASON_CODES.has(reasonCode) ? reasonCode : void 0;
20245
+ };
20246
+ var hardInspiredesignDiscoveryReasonCodes = (discovery) => {
20247
+ const reasonCodes = discovery.failures.map(readInspiredesignFailureReasonCode).filter((reasonCode) => reasonCode !== void 0);
20248
+ return [...new Set(reasonCodes)];
20249
+ };
20250
+ var hardInspiredesignMetaReasonCodes = (meta) => {
20251
+ const distribution = meta.reasonCodeDistribution;
20252
+ if (!distribution || typeof distribution !== "object" || Array.isArray(distribution)) return [];
20253
+ return Object.keys(distribution).filter((reasonCode) => INSPIREDESIGN_HARD_DISCOVERY_REASON_CODES.has(reasonCode));
20254
+ };
20255
+ var hardInspiredesignGuidanceReasonCodes = (discovery, meta) => [
20256
+ .../* @__PURE__ */ new Set([
20257
+ ...hardInspiredesignDiscoveryReasonCodes(discovery),
20258
+ ...hardInspiredesignMetaReasonCodes(meta)
20259
+ ])
20260
+ ];
20261
+ var selectInspiredesignPrimaryConstraintFailures = (failures, references, discovery) => {
20262
+ if (!hasSurvivingInspiredesignReference(references)) return failures;
20263
+ if (discovery.failures.length === 0) return failures;
20264
+ return failures.slice(discovery.failures.length);
20265
+ };
20266
+ var readMetaPrimaryConstraint = (meta) => {
20267
+ const value = meta.primaryConstraint;
20268
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
20269
+ const record = value;
20270
+ const primaryConstraint = {
20271
+ ...typeof record.reasonCode === "string" ? { reasonCode: record.reasonCode } : {},
20272
+ ...typeof record.summary === "string" ? { summary: record.summary } : {}
20273
+ };
20274
+ return Object.keys(primaryConstraint).length > 0 ? primaryConstraint : void 0;
20275
+ };
20276
+ var isInspiredesignReferenceEvidenceRequired = (workflowInput) => workflowInput.harvest === true || workflowInput.urls.length > 0 || workflowInput.providers.length > 0 || typeof workflowInput.query === "string" || workflowInput.visualEvidence === "required";
20277
+ var buildInspiredesignGuidanceSource = (workflowInput, discovery, meta, referencePatternBoard) => {
20278
+ const quality = summarizeInspiredesignReferenceQuality(referencePatternBoard);
20279
+ const primaryConstraint = readMetaPrimaryConstraint(meta);
20280
+ return {
20281
+ brief: workflowInput.brief,
20282
+ ...workflowInput.query ? { query: workflowInput.query } : {},
20283
+ urls: workflowInput.urls,
20284
+ requestedProviders: workflowInput.providers,
20285
+ ...workflowInput.browserMode ? { browserMode: workflowInput.browserMode } : {},
20286
+ ...workflowInput.cookiePolicyOverride ? { cookiePolicy: workflowInput.cookiePolicyOverride } : {},
20287
+ ...typeof workflowInput.useCookies === "boolean" ? { useCookies: workflowInput.useCookies } : {},
20288
+ discovery: {
20289
+ requested: discovery.requested,
20290
+ acceptedUrls: discovery.acceptedUrls,
20291
+ failures: discovery.failures.length,
20292
+ ...discovery.failure ? { failure: discovery.failure } : {},
20293
+ hardFailureReasonCodes: hardInspiredesignGuidanceReasonCodes(discovery, meta)
20294
+ },
20295
+ metrics: {
20296
+ referenceCount: quality.rankedReferenceCount + quality.rejectedReferenceCount,
20297
+ referenceEvidenceRequired: isInspiredesignReferenceEvidenceRequired(workflowInput),
20298
+ failedCaptureCount: quality.failedCaptureCount,
20299
+ visualEvidenceRequired: workflowInput.visualEvidence === "required"
20300
+ },
20301
+ quality: {
20302
+ rankedReferenceCount: quality.rankedReferenceCount,
20303
+ rankedReferenceUrls: referencePatternBoard.references.map((reference) => reference.url),
20304
+ rejectedReferenceCount: quality.rejectedReferenceCount,
20305
+ missingScreenshotCount: quality.missingScreenshotCount,
20306
+ diagnosticOnlyReasons: quality.diagnosticOnlyReasons,
20307
+ ...typeof quality.topReferenceScore === "number" ? { topReferenceScore: quality.topReferenceScore } : {},
20308
+ ...typeof quality.topReferenceConfidence === "number" ? { topReferenceConfidence: quality.topReferenceConfidence } : {},
20309
+ ...typeof quality.topReferenceIntentMatched === "boolean" ? { topReferenceIntentMatched: quality.topReferenceIntentMatched } : {}
20310
+ },
20311
+ ...primaryConstraint ? { primaryConstraint } : {}
20312
+ };
20313
+ };
20314
+ var buildInspiredesignMeta = (runtime, workflowInput, references, failures, followthrough, discovery) => {
17088
20315
  const failedCaptures = references.filter((reference) => reference.captureStatus === "failed");
17089
20316
  const captureAttemptReport = summarizeInspiredesignCaptureAttempts(references);
17090
20317
  const recoveredFetches = summarizeInspiredesignRecoveredFetches(references);
20318
+ const hasSurvivingReference = hasSurvivingInspiredesignReference(references);
20319
+ const primaryConstraintFailures = selectInspiredesignPrimaryConstraintFailures(failures, references, discovery);
17091
20320
  let reasonCodeDistribution = summarizeReasonCodeDistribution(failures);
17092
20321
  let meta = withCamelCasePrimaryConstraintMeta(withReasonCodeDistributionMeta({
17093
20322
  selection: {
17094
20323
  urls: workflowInput.urls,
20324
+ ...workflowInput.query ? { query: workflowInput.query } : {},
20325
+ ...workflowInput.providers.length > 0 ? { providers: workflowInput.providers } : {},
20326
+ ...workflowInput.referenceLimit !== void 0 ? { max_references: workflowInput.referenceLimit } : {},
20327
+ ...workflowInput.visualEvidence !== "off" ? { visual_evidence: workflowInput.visualEvidence } : {},
17095
20328
  capture_mode: workflowInput.captureMode,
17096
20329
  ...workflowInput.browserMode ? { requested_browser_mode: workflowInput.browserMode } : {},
17097
20330
  include_prototype_guidance: Boolean(workflowInput.includePrototypeGuidance)
@@ -17109,7 +20342,7 @@ var buildInspiredesignMeta = (runtime, workflowInput, references, failures, foll
17109
20342
  ...captureAttemptReport ? { capture_attempts: captureAttemptReport.counts } : {}
17110
20343
  },
17111
20344
  alerts: buildWorkflowAlerts(runtime, failures)
17112
- }, reasonCodeDistribution), failures);
20345
+ }, reasonCodeDistribution), primaryConstraintFailures);
17113
20346
  if (!meta.primaryConstraint) {
17114
20347
  const fetchConstraint = summarizeInspiredesignFetchConstraint(references);
17115
20348
  if (fetchConstraint) {
@@ -17119,6 +20352,16 @@ var buildInspiredesignMeta = (runtime, workflowInput, references, failures, foll
17119
20352
  };
17120
20353
  }
17121
20354
  }
20355
+ if (!hasSurvivingReference && !meta.primaryConstraint && !meta.primaryConstraintSummary) {
20356
+ const discoveryConstraint = summarizeInspiredesignDiscoveryConstraint(discovery);
20357
+ if (discoveryConstraint) {
20358
+ meta = withPrimaryConstraintSummaryOverride(
20359
+ meta,
20360
+ discoveryConstraint.summary,
20361
+ discoveryConstraint.guidance
20362
+ );
20363
+ }
20364
+ }
17122
20365
  if (!meta.primaryConstraint && !meta.primaryConstraintSummary) {
17123
20366
  const captureConstraint = summarizeInspiredesignCaptureConstraint(references);
17124
20367
  if (captureConstraint) {
@@ -17143,9 +20386,31 @@ var buildInspiredesignMeta = (runtime, workflowInput, references, failures, foll
17143
20386
  } : {},
17144
20387
  recommendedSkills: followthrough.recommendedSkills,
17145
20388
  deepCaptureRecommendation: followthrough.deepCaptureRecommendation,
20389
+ discovery,
17146
20390
  contractScope: followthrough.contractScope
17147
20391
  };
17148
20392
  };
20393
+ var buildInspiredesignDiscoveryGuidance = (discovery) => ({
20394
+ reason: discovery.failure ?? "Reference discovery did not produce usable design references.",
20395
+ recommendedNextCommands: [
20396
+ "Rerun inspiredesign harvest with explicit --url references from usable inspiration pages.",
20397
+ "Retry provider discovery in a lane with provider search support and any required authenticated browser session."
20398
+ ]
20399
+ });
20400
+ var summarizeInspiredesignDiscoveryConstraint = (discovery) => {
20401
+ if (!discovery.requested || discovery.acceptedUrls.length > 0) return void 0;
20402
+ const queryDetail = discovery.query ? ` for query "${discovery.query}"` : "";
20403
+ const summary = discovery.failure ?? `Reference discovery returned no usable references${queryDetail}.`;
20404
+ return {
20405
+ summary,
20406
+ guidance: buildInspiredesignDiscoveryGuidance(discovery)
20407
+ };
20408
+ };
20409
+ var buildInspiredesignGuidanceFollowthroughSummary = (_followthrough, meta, nextStepGuidance) => {
20410
+ const primaryConstraintSummary = typeof meta.primaryConstraintSummary === "string" ? meta.primaryConstraintSummary.trim() : "";
20411
+ const fallbackSummary = primaryConstraintSummary ? `Primary constraint: ${primaryConstraintSummary} ${nextStepGuidance.primaryAction.summary}` : void 0;
20412
+ return renderWorkflowCompatibility(nextStepGuidance, fallbackSummary).followthroughSummary;
20413
+ };
17149
20414
  var inferBrandFromContent = (content, productUrl) => {
17150
20415
  const normalized = normalizePlainText(content);
17151
20416
  if (!normalized) return void 0;
@@ -17617,6 +20882,15 @@ var resolveShoppingSourceForUrl = (url) => {
17617
20882
  return "web";
17618
20883
  }
17619
20884
  };
20885
+ var getRequiredProductVideoExecutionStep = (steps, stepId) => {
20886
+ const step = steps.find(
20887
+ (candidate) => candidate.id === stepId
20888
+ );
20889
+ if (!step) {
20890
+ throw new Error(`Product-video workflow plan is missing required step ${stepId}.`);
20891
+ }
20892
+ return step;
20893
+ };
17620
20894
  var RESEARCH_REJECTED_CANDIDATE_LIMIT = 25;
17621
20895
  var isResearchPrivacyPreferenceShell = (content) => {
17622
20896
  const matchIndex = content.slice(0, 400).search(RESEARCH_PRIVACY_PREFERENCE_SHELL_RE);
@@ -17909,8 +21183,9 @@ var runResearchWorkflow = async (runtime, input) => {
17909
21183
  challengeOrchestration
17910
21184
  });
17911
21185
  const responseMeta = withFollowthroughMeta(meta, handoff);
21186
+ const renderMode = workflowInput.mode ?? "compact";
17912
21187
  const rendered = renderResearch({
17913
- mode: workflowInput.mode,
21188
+ mode: renderMode,
17914
21189
  topic: plan.compiled.topic,
17915
21190
  records: ranked,
17916
21191
  meta: responseMeta
@@ -17921,7 +21196,7 @@ var runResearchWorkflow = async (runtime, input) => {
17921
21196
  ttlHours: workflowInput.ttlHours,
17922
21197
  files: rendered.files
17923
21198
  });
17924
- if (workflowInput.mode === "path") {
21199
+ if (renderMode === "path") {
17925
21200
  return {
17926
21201
  ...rendered.response,
17927
21202
  ...handoff,
@@ -18135,102 +21410,169 @@ var runShoppingWorkflow = async (runtime, input) => {
18135
21410
  var runInspiredesignWorkflow = async (runtime, input, options = {}) => {
18136
21411
  const { envelope, workflowInput: rawWorkflowInput } = buildInspiredesignEnvelope(input);
18137
21412
  const artifactRoot = resolveWorkflowArtifactRoot(rawWorkflowInput.outputDir);
18138
- const workflowInput = { ...rawWorkflowInput, outputDir: artifactRoot };
21413
+ let workflowInput = { ...rawWorkflowInput, outputDir: artifactRoot };
18139
21414
  const remainingTimeoutMs = createRemainingTimeoutResolver(workflowInput.timeoutMs);
18140
- let trace = appendWorkflowTrace(envelope.trace ?? [], "compile", "compile_started", {
18141
- kind: "inspiredesign"
18142
- });
18143
- trace = appendWorkflowTrace(trace, "compile", "compile_completed", {
18144
- kind: "inspiredesign",
18145
- urlCount: workflowInput.urls.length,
18146
- captureMode: workflowInput.captureMode
18147
- });
18148
- const references = [];
18149
- const failures = [];
18150
- for (const [index, url] of workflowInput.urls.entries()) {
18151
- const stepTrace = appendWorkflowTrace(trace, "execute", "reference_started", {
18152
- stepIndex: index,
18153
- url
21415
+ const visualEvidenceTempDir = workflowInput.visualEvidence !== "off" ? await mkdtemp2(join3(tmpdir2(), "inspiredesign-visual-")) : void 0;
21416
+ try {
21417
+ const discovery = await discoverInspiredesignReferences(
21418
+ runtime,
21419
+ workflowInput,
21420
+ envelope,
21421
+ workflowInput.query ? remainingTimeoutMs() : void 0
21422
+ );
21423
+ workflowInput = {
21424
+ ...workflowInput,
21425
+ urls: mergeInspiredesignReferenceUrls(
21426
+ workflowInput.urls,
21427
+ discovery.acceptedUrls,
21428
+ workflowInput.referenceLimit ?? workflowInput.urls.length + discovery.acceptedUrls.length
21429
+ ),
21430
+ captureMode: resolveInspiredesignCaptureMode(workflowInput.captureMode, [
21431
+ ...workflowInput.urls,
21432
+ ...discovery.acceptedUrls
21433
+ ])
21434
+ };
21435
+ let trace = appendWorkflowTrace(envelope.trace ?? [], "compile", "compile_started", {
21436
+ kind: "inspiredesign"
21437
+ });
21438
+ trace = appendWorkflowTrace(trace, "compile", "compile_completed", {
21439
+ kind: "inspiredesign",
21440
+ urlCount: workflowInput.urls.length,
21441
+ captureMode: workflowInput.captureMode
18154
21442
  });
18155
- const fetchTimeoutMs = remainingTimeoutMs();
18156
- const fetchResult = await runtime.fetch(
18157
- { url },
18158
- buildInspiredesignFetchOptions(
21443
+ const references = [];
21444
+ const failures = [...discovery.failures];
21445
+ for (const [index, url] of workflowInput.urls.entries()) {
21446
+ const stepTrace = appendWorkflowTrace(trace, "execute", "reference_started", {
21447
+ stepIndex: index,
21448
+ url
21449
+ });
21450
+ const fetchTimeoutMs = remainingTimeoutMs();
21451
+ const fetchResult = await runtime.fetch(
21452
+ { url },
21453
+ buildInspiredesignReferenceFetchOptions(
21454
+ workflowInput,
21455
+ buildInspiredesignStepEnvelope(workflowInput, stepTrace, index, url),
21456
+ url,
21457
+ fetchTimeoutMs
21458
+ )
21459
+ );
21460
+ const result = normalizeInspiredesignFetchResult(fetchResult);
21461
+ observeWorkflowSignals(runtime, result);
21462
+ const captureTimeoutMs = remainingTimeoutMs();
21463
+ const visualPlan = buildInspiredesignVisualCapturePlan(
21464
+ url,
18159
21465
  workflowInput,
18160
- buildInspiredesignStepEnvelope(workflowInput, stepTrace, index, url),
18161
- fetchTimeoutMs
18162
- )
18163
- );
18164
- const result = normalizeInspiredesignFetchResult(fetchResult);
18165
- observeWorkflowSignals(runtime, result);
18166
- const captureTimeoutMs = remainingTimeoutMs();
18167
- const capture = await captureInspiredesignReference(
18168
- url,
18169
- workflowInput.captureMode,
21466
+ result,
21467
+ visualEvidenceTempDir
21468
+ );
21469
+ const capture = await captureInspiredesignReference(
21470
+ url,
21471
+ workflowInput.captureMode,
21472
+ workflowInput,
21473
+ options.captureReference,
21474
+ visualPlan,
21475
+ captureTimeoutMs
21476
+ );
21477
+ const reference = buildInspiredesignReference(url, result, capture);
21478
+ references.push(reference);
21479
+ if (reference.fetchStatus === "failed" && !isInspiredesignFetchRecovered(reference)) {
21480
+ const fetchFailures = result.failures.length > 0 ? result.failures : failureFromInspiredesignFetchError(result);
21481
+ const siteRecipe = resolveSiteRecipeForUrl(url);
21482
+ failures.push(...siteRecipe ? normalizeSiteRecipeFetchFailures(siteRecipe, fetchFailures) : fetchFailures);
21483
+ }
21484
+ trace = appendWorkflowTrace(stepTrace, "execute", "reference_completed", {
21485
+ stepIndex: index,
21486
+ url,
21487
+ fetchStatus: result.records.length > 0 ? "captured" : "failed",
21488
+ captureStatus: capture.captureStatus
21489
+ });
21490
+ }
21491
+ const visualCollation = await finalizeInspiredesignVisualArtifacts(references, workflowInput.visualEvidence);
21492
+ const packet = buildInspiredesignPacket({
21493
+ brief: workflowInput.brief,
21494
+ briefExpansion: workflowInput.briefExpansion,
21495
+ urls: workflowInput.urls,
21496
+ references: visualCollation.references,
21497
+ includePrototypeGuidance: workflowInput.includePrototypeGuidance,
21498
+ referenceEvidenceRequired: isInspiredesignReferenceEvidenceRequired(workflowInput)
21499
+ });
21500
+ const meta = buildInspiredesignMeta(
21501
+ runtime,
18170
21502
  workflowInput,
18171
- options.captureReference,
18172
- captureTimeoutMs
21503
+ visualCollation.references,
21504
+ failures,
21505
+ packet.followthrough,
21506
+ discovery
18173
21507
  );
18174
- const reference = buildInspiredesignReference(url, result, capture);
18175
- references.push(reference);
18176
- if (reference.fetchStatus === "failed" && !isInspiredesignFetchRecovered(reference)) {
18177
- failures.push(...result.failures);
18178
- }
18179
- trace = appendWorkflowTrace(stepTrace, "execute", "reference_completed", {
18180
- stepIndex: index,
18181
- url,
18182
- fetchStatus: result.records.length > 0 ? "captured" : "failed",
18183
- captureStatus: capture.captureStatus
21508
+ const nextStepGuidance = routeNextStepGuidance(createInspiredesignGuidanceContext(
21509
+ buildInspiredesignGuidanceSource(
21510
+ workflowInput,
21511
+ discovery,
21512
+ meta,
21513
+ packet.generationPlan.referencePatternBoard
21514
+ )
21515
+ ));
21516
+ const metaWithGuidance = {
21517
+ ...meta,
21518
+ followthroughSummary: nextStepGuidance.readiness === "ready" ? meta.followthroughSummary : buildInspiredesignGuidanceFollowthroughSummary(
21519
+ packet.followthrough,
21520
+ meta,
21521
+ nextStepGuidance
21522
+ ),
21523
+ nextStepGuidance
21524
+ };
21525
+ const rendered = renderInspiredesign({
21526
+ mode: workflowInput.mode,
21527
+ brief: workflowInput.brief,
21528
+ advancedBriefMarkdown: packet.advancedBriefMarkdown,
21529
+ urls: workflowInput.urls,
21530
+ designContract: packet.designContract,
21531
+ canvasPlanRequest: packet.canvasPlanRequest,
21532
+ designAgentHandoff: packet.followthrough,
21533
+ generationPlan: packet.generationPlan,
21534
+ implementationPlan: packet.implementationPlan,
21535
+ designMarkdown: packet.designMarkdown,
21536
+ implementationPlanMarkdown: packet.implementationPlanMarkdown,
21537
+ prototypeGuidanceMarkdown: packet.prototypeGuidanceMarkdown,
21538
+ evidence: packet.evidence,
21539
+ visualEvidence: packet.visualEvidence,
21540
+ screenshotIndex: packet.screenshotIndex,
21541
+ rankedReferences: packet.rankedReferences,
21542
+ referencePatternBoard: packet.generationPlan.referencePatternBoard,
21543
+ metaPromptMarkdown: packet.metaPromptMarkdown,
21544
+ nextStepGuidance,
21545
+ meta: metaWithGuidance
18184
21546
  });
18185
- }
18186
- const packet = buildInspiredesignPacket({
18187
- brief: workflowInput.brief,
18188
- briefExpansion: workflowInput.briefExpansion,
18189
- urls: workflowInput.urls,
18190
- references,
18191
- includePrototypeGuidance: workflowInput.includePrototypeGuidance
18192
- });
18193
- const meta = buildInspiredesignMeta(runtime, workflowInput, references, failures, packet.followthrough);
18194
- const rendered = renderInspiredesign({
18195
- mode: workflowInput.mode,
18196
- brief: workflowInput.brief,
18197
- advancedBriefMarkdown: packet.advancedBriefMarkdown,
18198
- urls: workflowInput.urls,
18199
- designContract: packet.designContract,
18200
- canvasPlanRequest: packet.canvasPlanRequest,
18201
- designAgentHandoff: packet.followthrough,
18202
- generationPlan: packet.generationPlan,
18203
- implementationPlan: packet.implementationPlan,
18204
- designMarkdown: packet.designMarkdown,
18205
- implementationPlanMarkdown: packet.implementationPlanMarkdown,
18206
- prototypeGuidanceMarkdown: packet.prototypeGuidanceMarkdown,
18207
- evidence: packet.evidence,
18208
- meta
18209
- });
18210
- const bundle = await createArtifactBundle({
18211
- namespace: "inspiredesign",
18212
- outputDir: artifactRoot,
18213
- ttlHours: workflowInput.ttlHours,
18214
- files: rendered.files
18215
- });
18216
- if (workflowInput.mode === "path") {
21547
+ const bundle = await createArtifactBundle({
21548
+ namespace: "inspiredesign",
21549
+ outputDir: artifactRoot,
21550
+ ttlHours: workflowInput.ttlHours,
21551
+ files: [...rendered.files, ...visualCollation.files]
21552
+ });
21553
+ if (workflowInput.mode === "path") {
21554
+ return {
21555
+ ...rendered.response,
21556
+ artifact_path: bundle.basePath,
21557
+ meta: {
21558
+ ...metaWithGuidance,
21559
+ artifact_manifest: bundle.manifest
21560
+ }
21561
+ };
21562
+ }
18217
21563
  return {
18218
21564
  ...rendered.response,
18219
21565
  artifact_path: bundle.basePath,
18220
21566
  meta: {
18221
- ...meta,
21567
+ ...metaWithGuidance,
18222
21568
  artifact_manifest: bundle.manifest
18223
21569
  }
18224
21570
  };
18225
- }
18226
- return {
18227
- ...rendered.response,
18228
- artifact_path: bundle.basePath,
18229
- meta: {
18230
- ...meta,
18231
- artifact_manifest: bundle.manifest
21571
+ } finally {
21572
+ if (visualEvidenceTempDir) {
21573
+ await rm2(visualEvidenceTempDir, { recursive: true, force: true }).catch(() => void 0);
18232
21574
  }
18233
- };
21575
+ }
18234
21576
  };
18235
21577
  var runProductVideoWorkflow = async (runtime, input, options = {}) => {
18236
21578
  const envelope = isWorkflowResumeEnvelope(input) ? input : buildWorkflowResumeEnvelope("product_video", input);
@@ -18294,15 +21636,7 @@ var runProductVideoWorkflow = async (runtime, input, options = {}) => {
18294
21636
  ...updates,
18295
21637
  completed_step_ids: checkpointState2.completed_step_ids.includes(stepId) ? checkpointState2.completed_step_ids : [...checkpointState2.completed_step_ids, stepId]
18296
21638
  });
18297
- const getRequiredProductVideoStep = (stepId) => {
18298
- const step = plan.plan.steps.find(
18299
- (candidate) => candidate.id === stepId
18300
- );
18301
- if (!step) {
18302
- throw new Error(`Product-video workflow plan is missing required step ${stepId}.`);
18303
- }
18304
- return step;
18305
- };
21639
+ const getRequiredProductVideoStep = (stepId) => getRequiredProductVideoExecutionStep(plan.plan.steps, stepId);
18306
21640
  let checkpointState = {
18307
21641
  ...plan.checkpointState,
18308
21642
  completed_step_ids: [...plan.checkpointState.completed_step_ids]
@@ -18732,10 +22066,10 @@ var Semaphore = class {
18732
22066
  this.active += 1;
18733
22067
  return;
18734
22068
  }
18735
- await new Promise((resolve) => {
22069
+ await new Promise((resolve2) => {
18736
22070
  this.queue.push(() => {
18737
22071
  this.active += 1;
18738
- resolve();
22072
+ resolve2();
18739
22073
  });
18740
22074
  });
18741
22075
  }
@@ -21036,6 +24370,8 @@ export {
21036
24370
  CANVAS_BROWSER_VALIDATION_MODES,
21037
24371
  CANVAS_VALIDATION_TARGET_BLOCK_ON_CODES,
21038
24372
  CANVAS_PUBLIC_WARNING_CLASSES,
24373
+ buildCanvasRepairEnvelope,
24374
+ buildCanvasCommandValidationEnvelope,
21039
24375
  createTraceContext,
21040
24376
  clampConfidence,
21041
24377
  createStableRecordId,
@@ -21085,4 +24421,4 @@ export {
21085
24421
  createProviderRuntime,
21086
24422
  createDefaultRuntime
21087
24423
  };
21088
- //# sourceMappingURL=chunk-4BEJVZRK.js.map
24424
+ //# sourceMappingURL=chunk-FBKPDILE.js.map