opendevbrowser 0.0.32 → 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 (246) hide show
  1. package/README.md +1 -1
  2. package/dist/{accessibility-snapshot-XOP66CSK.js → accessibility-snapshot-JSPFVWZ6.js} +8 -8
  3. package/dist/{active-window-E3WFOQGX.js → active-window-2OB2MSCR.js} +8 -8
  4. package/dist/{annotate-MAE7ZJOZ.js → annotate-VDZBZBKZ.js} +7 -7
  5. package/dist/{attr-M3PFDJ7Q.js → attr-7XIO4MCH.js} +7 -7
  6. package/dist/browser/canvas-manager.d.ts.map +1 -1
  7. package/dist/canvas/guidance.d.ts +7 -0
  8. package/dist/canvas/guidance.d.ts.map +1 -1
  9. package/dist/canvas/repair-examples.d.ts +45 -0
  10. package/dist/canvas/repair-examples.d.ts.map +1 -0
  11. package/dist/{canvas-3AJVL5I5.js → canvas-N4PAA274.js} +22 -7
  12. package/dist/canvas-N4PAA274.js.map +1 -0
  13. package/dist/{capture-desktop-VJGEETMJ.js → capture-desktop-T5YO3EBI.js} +8 -8
  14. package/dist/{capture-window-W5UFSFQL.js → capture-window-UKEUBWKH.js} +8 -8
  15. package/dist/{check-4IR3UJVW.js → check-PQB6KKMN.js} +7 -7
  16. package/dist/{checked-PKNY7724.js → checked-RNZIMCU6.js} +7 -7
  17. package/dist/{chunk-AKIAGFOE.js → chunk-27W46IKI.js} +15 -7
  18. package/dist/chunk-27W46IKI.js.map +1 -0
  19. package/dist/{chunk-WHQZBUNY.js → chunk-3WLCWHIV.js} +2 -2
  20. package/dist/{chunk-WHQZBUNY.js.map → chunk-3WLCWHIV.js.map} +1 -1
  21. package/dist/{chunk-PIFHXKV4.js → chunk-52ZIOWVU.js} +2 -2
  22. package/dist/{chunk-HBK56JST.js → chunk-EOX6U6Q4.js} +46 -18
  23. package/dist/chunk-EOX6U6Q4.js.map +1 -0
  24. package/dist/{chunk-RO3SMXF3.js → chunk-FBKPDILE.js} +2574 -173
  25. package/dist/chunk-FBKPDILE.js.map +1 -0
  26. package/dist/{chunk-AWQ37HSC.js → chunk-FDBUB7BM.js} +2 -2
  27. package/dist/{chunk-ZOVMMQO6.js → chunk-HMRANSDX.js} +4 -4
  28. package/dist/chunk-HMRANSDX.js.map +1 -0
  29. package/dist/{chunk-2X4JFMKJ.js → chunk-IBIHDGTZ.js} +4 -4
  30. package/dist/chunk-IBIHDGTZ.js.map +1 -0
  31. package/dist/{chunk-BUXFIY2P.js → chunk-JROW6ZNN.js} +2 -2
  32. package/dist/{chunk-XDLJE3RJ.js → chunk-MJF67OTH.js} +2 -2
  33. package/dist/{chunk-P5K3ZIPI.js → chunk-YRRRUGSQ.js} +2 -2
  34. package/dist/{chunk-37VSRUW4.js → chunk-ZGCTC5YM.js} +39 -7
  35. package/dist/chunk-ZGCTC5YM.js.map +1 -0
  36. package/dist/cli/commands/canvas.d.ts +12 -0
  37. package/dist/cli/commands/canvas.d.ts.map +1 -1
  38. package/dist/cli/daemon-mismatch.d.ts +6 -0
  39. package/dist/cli/daemon-mismatch.d.ts.map +1 -1
  40. package/dist/cli/help.d.ts.map +1 -1
  41. package/dist/cli/index.js +77 -77
  42. package/dist/cli/index.js.map +1 -1
  43. package/dist/cli/utils/workflow-message.d.ts +1 -1
  44. package/dist/cli/utils/workflow-message.d.ts.map +1 -1
  45. package/dist/{click-HLNXU4I5.js → click-U7ZFKSB4.js} +7 -7
  46. package/dist/{clone-component-QIKN5PIM.js → clone-component-SWYAORTU.js} +7 -7
  47. package/dist/{clone-page-5C7DTGZT.js → clone-page-WJ6UJOJG.js} +7 -7
  48. package/dist/{close-PCRZHX7F.js → close-NAVIHZ2T.js} +7 -7
  49. package/dist/{close-WTXB3EDD.js → close-VKIGIKVT.js} +7 -7
  50. package/dist/{connect-6C2IG55I.js → connect-XVG2MOZL.js} +7 -7
  51. package/dist/{console-poll-VJXCZR3F.js → console-poll-XI5BZPL7.js} +7 -7
  52. package/dist/{cookie-import-5OEDFB6U.js → cookie-import-QELKE7TK.js} +7 -7
  53. package/dist/{cookie-list-44UNJJ6D.js → cookie-list-QDA6KWIY.js} +7 -7
  54. package/dist/{daemon-CIKGBWEB.js → daemon-CA4UIIZQ.js} +6 -6
  55. package/dist/daemon-fingerprint.json +1 -1
  56. package/dist/{debug-trace-snapshot-RGXAPGWB.js → debug-trace-snapshot-AT4GAO57.js} +7 -7
  57. package/dist/{dialog-S64MJUM2.js → dialog-O3V2IBFH.js} +7 -7
  58. package/dist/{disconnect-MTIELIM7.js → disconnect-NAX5TPTG.js} +7 -7
  59. package/dist/{enabled-KF2L7LW4.js → enabled-VT4FJXDX.js} +7 -7
  60. package/dist/{goto-ULWINUAZ.js → goto-GBJG5NC4.js} +7 -7
  61. package/dist/guidance/context.d.ts +44 -0
  62. package/dist/guidance/context.d.ts.map +1 -0
  63. package/dist/guidance/index.d.ts +7 -0
  64. package/dist/guidance/index.d.ts.map +1 -0
  65. package/dist/guidance/readiness.d.ts +7 -0
  66. package/dist/guidance/readiness.d.ts.map +1 -0
  67. package/dist/guidance/recipes/generic.d.ts +3 -0
  68. package/dist/guidance/recipes/generic.d.ts.map +1 -0
  69. package/dist/guidance/recipes/pinterest.d.ts +5 -0
  70. package/dist/guidance/recipes/pinterest.d.ts.map +1 -0
  71. package/dist/guidance/recipes/site-recipe-types.d.ts +2 -0
  72. package/dist/guidance/recipes/site-recipe-types.d.ts.map +1 -0
  73. package/dist/guidance/recipes/site-registry.d.ts +5 -0
  74. package/dist/guidance/recipes/site-registry.d.ts.map +1 -0
  75. package/dist/guidance/renderers.d.ts +22 -0
  76. package/dist/guidance/renderers.d.ts.map +1 -0
  77. package/dist/guidance/router.d.ts +8 -0
  78. package/dist/guidance/router.d.ts.map +1 -0
  79. package/dist/guidance/types.d.ts +139 -0
  80. package/dist/guidance/types.d.ts.map +1 -0
  81. package/dist/{help-IG5S5RJD.js → help-SUI4H77K.js} +6 -5
  82. package/dist/help-SUI4H77K.js.map +1 -0
  83. package/dist/{hover-NOCOTR6N.js → hover-476ZNQZE.js} +7 -7
  84. package/dist/{html-LXSYP6BT.js → html-5C4TXOV3.js} +7 -7
  85. package/dist/index.js +11 -11
  86. package/dist/{inspector-62EPCLYB.js → inspector-73ARPCIV.js} +8 -8
  87. package/dist/{inspector-audit-T2IF67RJ.js → inspector-audit-QT6QY7KS.js} +9 -9
  88. package/dist/{inspector-plan-KQS6LRMW.js → inspector-plan-JRNSGN2Z.js} +9 -9
  89. package/dist/inspiredesign/contract.d.ts +2 -0
  90. package/dist/inspiredesign/contract.d.ts.map +1 -1
  91. package/dist/inspiredesign/handoff.d.ts +2 -2
  92. package/dist/inspiredesign/meta-prompt.d.ts +1 -1
  93. package/dist/inspiredesign/meta-prompt.d.ts.map +1 -1
  94. package/dist/inspiredesign/reference-pattern-board.d.ts +17 -1
  95. package/dist/inspiredesign/reference-pattern-board.d.ts.map +1 -1
  96. package/dist/{inspiredesign-DB6CHYN3.js → inspiredesign-IPVZDLSQ.js} +9 -9
  97. package/dist/{launch-B5ES6FVS.js → launch-B35YDRQC.js} +7 -7
  98. package/dist/{list-XM4BP5GM.js → list-JV55JVGB.js} +7 -7
  99. package/dist/{list-TIZVR6RO.js → list-YETWKTKY.js} +7 -7
  100. package/dist/{macro-resolve-TTQZVFIW.js → macro-resolve-DQK4B3W3.js} +8 -8
  101. package/dist/{network-poll-NNSY4W63.js → network-poll-4GWHCJXI.js} +7 -7
  102. package/dist/{new-E6VNAC2A.js → new-XDCQPIEG.js} +7 -7
  103. package/dist/{open-F55XKMKB.js → open-GIM3ZCSV.js} +7 -7
  104. package/dist/opendevbrowser.js +11 -11
  105. package/dist/{perf-RE7JE6CP.js → perf-26VBXDPI.js} +7 -7
  106. package/dist/{pointer-down-BCBPC5FJ.js → pointer-down-O3VSNAXW.js} +7 -7
  107. package/dist/{pointer-drag-QK7KGF7W.js → pointer-drag-WQ5QGE6J.js} +7 -7
  108. package/dist/{pointer-move-VFAZQAXA.js → pointer-move-4N4D7JY2.js} +7 -7
  109. package/dist/{pointer-up-FA5WE6LS.js → pointer-up-CQC4NPDX.js} +7 -7
  110. package/dist/{press-TNRHNDSW.js → press-XGJD45CU.js} +7 -7
  111. package/dist/{product-video-UEANMZ2U.js → product-video-HD4ZOUI7.js} +9 -9
  112. package/dist/providers/browser-native-discovery.d.ts +23 -0
  113. package/dist/providers/browser-native-discovery.d.ts.map +1 -0
  114. package/dist/providers/renderer.d.ts +2 -0
  115. package/dist/providers/renderer.d.ts.map +1 -1
  116. package/dist/providers/workflow-handoff.d.ts +3 -0
  117. package/dist/providers/workflow-handoff.d.ts.map +1 -1
  118. package/dist/providers/workflows.d.ts.map +1 -1
  119. package/dist/{providers-AMCNWZUL.js → providers-KKNPJSQK.js} +4 -4
  120. package/dist/public-surface/generated-manifest.d.ts +3 -3
  121. package/dist/public-surface/generated-manifest.d.ts.map +1 -1
  122. package/dist/public-surface/source.d.ts +2 -2
  123. package/dist/public-surface/source.d.ts.map +1 -1
  124. package/dist/{research-YFY7WJSZ.js → research-VUWWEQ4R.js} +9 -9
  125. package/dist/{review-NHOPLAT7.js → review-LZ3TA7U7.js} +7 -7
  126. package/dist/{review-desktop-OFWPDYGD.js → review-desktop-LAO7U7T3.js} +7 -7
  127. package/dist/{rpc-TVVQPUOL.js → rpc-HKNIVFGC.js} +7 -7
  128. package/dist/{run-OCBEZRDW.js → run-SHCF53FO.js} +5 -5
  129. package/dist/{screencast-start-GTSDA33J.js → screencast-start-JHMQZVWJ.js} +7 -7
  130. package/dist/{screencast-stop-FYBUIXAA.js → screencast-stop-RWQTWWQS.js} +7 -7
  131. package/dist/{screenshot-OEYRT3SP.js → screenshot-QHFYO6PB.js} +7 -7
  132. package/dist/{scroll-35OFEFC5.js → scroll-L3FTMAV4.js} +7 -7
  133. package/dist/{scroll-into-view-UQ5RAWIX.js → scroll-into-view-JVDHX4WU.js} +7 -7
  134. package/dist/{select-K56QELVZ.js → select-X4BO7GTB.js} +7 -7
  135. package/dist/{serve-5UJ3VMWC.js → serve-JIMIBCNO.js} +6 -6
  136. package/dist/{shopping-FJG7XB4Q.js → shopping-EGSDP2GL.js} +9 -9
  137. package/dist/{snapshot-W7RKVZEI.js → snapshot-QGJ7RDNV.js} +7 -7
  138. package/dist/{status-KHYCLGUD.js → status-CKGPNYIH.js} +7 -7
  139. package/dist/{status-R4EV4TWO.js → status-LEBY2X7N.js} +8 -8
  140. package/dist/{status-capabilities-XD3RGLKF.js → status-capabilities-6QTWNGKM.js} +8 -8
  141. package/dist/{text-TANLFZ4O.js → text-VUZU7D3L.js} +7 -7
  142. package/dist/{type-Y2Y7LX7Y.js → type-N5SURP74.js} +7 -7
  143. package/dist/{uncheck-6REVUUB2.js → uncheck-JFMK3SSY.js} +7 -7
  144. package/dist/{upload-GGZC5UQP.js → upload-KFUYLL7M.js} +7 -7
  145. package/dist/{use-B4Q7CFG2.js → use-CNMPP2ED.js} +7 -7
  146. package/dist/{value-DHOHO55D.js → value-J335MPZE.js} +7 -7
  147. package/dist/{visible-S5BTWYNH.js → visible-YQZWWPBZ.js} +7 -7
  148. package/dist/{wait-WV6NZUKL.js → wait-IC7YJJPJ.js} +7 -7
  149. package/dist/{windows-GKE36DJQ.js → windows-AGVQ3KX3.js} +8 -8
  150. package/extension/manifest.json +1 -1
  151. package/package.json +1 -1
  152. package/skills/opendevbrowser-best-practices/SKILL.md +8 -2
  153. package/skills/opendevbrowser-best-practices/artifacts/canvas-governance-playbook.md +4 -4
  154. package/skills/opendevbrowser-best-practices/scripts/odb-workflow.sh +7 -0
  155. package/skills/opendevbrowser-best-practices/scripts/validate-skill-assets.sh +6 -0
  156. package/skills/opendevbrowser-design-agent/SKILL.md +8 -6
  157. package/skills/opendevbrowser-design-agent/artifacts/design-workflows.md +4 -3
  158. package/skills/opendevbrowser-design-agent/artifacts/research-harvest-workflow.md +28 -4
  159. package/skills/opendevbrowser-design-agent/assets/templates/reference-pattern-board.v1.json +1 -0
  160. package/skills/opendevbrowser-design-agent/scripts/design-workflow.sh +5 -2
  161. package/skills/opendevbrowser-design-agent/scripts/validate-skill-assets.sh +8 -2
  162. package/skills/opendevbrowser-motion-design/SKILL.md +1 -1
  163. package/skills/opendevbrowser-motion-design/scripts/validate-skill-assets.sh +1 -0
  164. package/dist/canvas-3AJVL5I5.js.map +0 -1
  165. package/dist/chunk-2X4JFMKJ.js.map +0 -1
  166. package/dist/chunk-37VSRUW4.js.map +0 -1
  167. package/dist/chunk-AKIAGFOE.js.map +0 -1
  168. package/dist/chunk-HBK56JST.js.map +0 -1
  169. package/dist/chunk-RO3SMXF3.js.map +0 -1
  170. package/dist/chunk-ZOVMMQO6.js.map +0 -1
  171. package/dist/help-IG5S5RJD.js.map +0 -1
  172. /package/dist/{accessibility-snapshot-XOP66CSK.js.map → accessibility-snapshot-JSPFVWZ6.js.map} +0 -0
  173. /package/dist/{active-window-E3WFOQGX.js.map → active-window-2OB2MSCR.js.map} +0 -0
  174. /package/dist/{annotate-MAE7ZJOZ.js.map → annotate-VDZBZBKZ.js.map} +0 -0
  175. /package/dist/{attr-M3PFDJ7Q.js.map → attr-7XIO4MCH.js.map} +0 -0
  176. /package/dist/{capture-desktop-VJGEETMJ.js.map → capture-desktop-T5YO3EBI.js.map} +0 -0
  177. /package/dist/{capture-window-W5UFSFQL.js.map → capture-window-UKEUBWKH.js.map} +0 -0
  178. /package/dist/{check-4IR3UJVW.js.map → check-PQB6KKMN.js.map} +0 -0
  179. /package/dist/{checked-PKNY7724.js.map → checked-RNZIMCU6.js.map} +0 -0
  180. /package/dist/{chunk-PIFHXKV4.js.map → chunk-52ZIOWVU.js.map} +0 -0
  181. /package/dist/{chunk-AWQ37HSC.js.map → chunk-FDBUB7BM.js.map} +0 -0
  182. /package/dist/{chunk-BUXFIY2P.js.map → chunk-JROW6ZNN.js.map} +0 -0
  183. /package/dist/{chunk-XDLJE3RJ.js.map → chunk-MJF67OTH.js.map} +0 -0
  184. /package/dist/{chunk-P5K3ZIPI.js.map → chunk-YRRRUGSQ.js.map} +0 -0
  185. /package/dist/{click-HLNXU4I5.js.map → click-U7ZFKSB4.js.map} +0 -0
  186. /package/dist/{clone-component-QIKN5PIM.js.map → clone-component-SWYAORTU.js.map} +0 -0
  187. /package/dist/{clone-page-5C7DTGZT.js.map → clone-page-WJ6UJOJG.js.map} +0 -0
  188. /package/dist/{close-PCRZHX7F.js.map → close-NAVIHZ2T.js.map} +0 -0
  189. /package/dist/{close-WTXB3EDD.js.map → close-VKIGIKVT.js.map} +0 -0
  190. /package/dist/{connect-6C2IG55I.js.map → connect-XVG2MOZL.js.map} +0 -0
  191. /package/dist/{console-poll-VJXCZR3F.js.map → console-poll-XI5BZPL7.js.map} +0 -0
  192. /package/dist/{cookie-import-5OEDFB6U.js.map → cookie-import-QELKE7TK.js.map} +0 -0
  193. /package/dist/{cookie-list-44UNJJ6D.js.map → cookie-list-QDA6KWIY.js.map} +0 -0
  194. /package/dist/{daemon-CIKGBWEB.js.map → daemon-CA4UIIZQ.js.map} +0 -0
  195. /package/dist/{debug-trace-snapshot-RGXAPGWB.js.map → debug-trace-snapshot-AT4GAO57.js.map} +0 -0
  196. /package/dist/{dialog-S64MJUM2.js.map → dialog-O3V2IBFH.js.map} +0 -0
  197. /package/dist/{disconnect-MTIELIM7.js.map → disconnect-NAX5TPTG.js.map} +0 -0
  198. /package/dist/{enabled-KF2L7LW4.js.map → enabled-VT4FJXDX.js.map} +0 -0
  199. /package/dist/{goto-ULWINUAZ.js.map → goto-GBJG5NC4.js.map} +0 -0
  200. /package/dist/{hover-NOCOTR6N.js.map → hover-476ZNQZE.js.map} +0 -0
  201. /package/dist/{html-LXSYP6BT.js.map → html-5C4TXOV3.js.map} +0 -0
  202. /package/dist/{inspector-62EPCLYB.js.map → inspector-73ARPCIV.js.map} +0 -0
  203. /package/dist/{inspector-audit-T2IF67RJ.js.map → inspector-audit-QT6QY7KS.js.map} +0 -0
  204. /package/dist/{inspector-plan-KQS6LRMW.js.map → inspector-plan-JRNSGN2Z.js.map} +0 -0
  205. /package/dist/{inspiredesign-DB6CHYN3.js.map → inspiredesign-IPVZDLSQ.js.map} +0 -0
  206. /package/dist/{launch-B5ES6FVS.js.map → launch-B35YDRQC.js.map} +0 -0
  207. /package/dist/{list-XM4BP5GM.js.map → list-JV55JVGB.js.map} +0 -0
  208. /package/dist/{list-TIZVR6RO.js.map → list-YETWKTKY.js.map} +0 -0
  209. /package/dist/{macro-resolve-TTQZVFIW.js.map → macro-resolve-DQK4B3W3.js.map} +0 -0
  210. /package/dist/{network-poll-NNSY4W63.js.map → network-poll-4GWHCJXI.js.map} +0 -0
  211. /package/dist/{new-E6VNAC2A.js.map → new-XDCQPIEG.js.map} +0 -0
  212. /package/dist/{open-F55XKMKB.js.map → open-GIM3ZCSV.js.map} +0 -0
  213. /package/dist/{perf-RE7JE6CP.js.map → perf-26VBXDPI.js.map} +0 -0
  214. /package/dist/{pointer-down-BCBPC5FJ.js.map → pointer-down-O3VSNAXW.js.map} +0 -0
  215. /package/dist/{pointer-drag-QK7KGF7W.js.map → pointer-drag-WQ5QGE6J.js.map} +0 -0
  216. /package/dist/{pointer-move-VFAZQAXA.js.map → pointer-move-4N4D7JY2.js.map} +0 -0
  217. /package/dist/{pointer-up-FA5WE6LS.js.map → pointer-up-CQC4NPDX.js.map} +0 -0
  218. /package/dist/{press-TNRHNDSW.js.map → press-XGJD45CU.js.map} +0 -0
  219. /package/dist/{product-video-UEANMZ2U.js.map → product-video-HD4ZOUI7.js.map} +0 -0
  220. /package/dist/{providers-AMCNWZUL.js.map → providers-KKNPJSQK.js.map} +0 -0
  221. /package/dist/{research-YFY7WJSZ.js.map → research-VUWWEQ4R.js.map} +0 -0
  222. /package/dist/{review-NHOPLAT7.js.map → review-LZ3TA7U7.js.map} +0 -0
  223. /package/dist/{review-desktop-OFWPDYGD.js.map → review-desktop-LAO7U7T3.js.map} +0 -0
  224. /package/dist/{rpc-TVVQPUOL.js.map → rpc-HKNIVFGC.js.map} +0 -0
  225. /package/dist/{run-OCBEZRDW.js.map → run-SHCF53FO.js.map} +0 -0
  226. /package/dist/{screencast-start-GTSDA33J.js.map → screencast-start-JHMQZVWJ.js.map} +0 -0
  227. /package/dist/{screencast-stop-FYBUIXAA.js.map → screencast-stop-RWQTWWQS.js.map} +0 -0
  228. /package/dist/{screenshot-OEYRT3SP.js.map → screenshot-QHFYO6PB.js.map} +0 -0
  229. /package/dist/{scroll-35OFEFC5.js.map → scroll-L3FTMAV4.js.map} +0 -0
  230. /package/dist/{scroll-into-view-UQ5RAWIX.js.map → scroll-into-view-JVDHX4WU.js.map} +0 -0
  231. /package/dist/{select-K56QELVZ.js.map → select-X4BO7GTB.js.map} +0 -0
  232. /package/dist/{serve-5UJ3VMWC.js.map → serve-JIMIBCNO.js.map} +0 -0
  233. /package/dist/{shopping-FJG7XB4Q.js.map → shopping-EGSDP2GL.js.map} +0 -0
  234. /package/dist/{snapshot-W7RKVZEI.js.map → snapshot-QGJ7RDNV.js.map} +0 -0
  235. /package/dist/{status-KHYCLGUD.js.map → status-CKGPNYIH.js.map} +0 -0
  236. /package/dist/{status-R4EV4TWO.js.map → status-LEBY2X7N.js.map} +0 -0
  237. /package/dist/{status-capabilities-XD3RGLKF.js.map → status-capabilities-6QTWNGKM.js.map} +0 -0
  238. /package/dist/{text-TANLFZ4O.js.map → text-VUZU7D3L.js.map} +0 -0
  239. /package/dist/{type-Y2Y7LX7Y.js.map → type-N5SURP74.js.map} +0 -0
  240. /package/dist/{uncheck-6REVUUB2.js.map → uncheck-JFMK3SSY.js.map} +0 -0
  241. /package/dist/{upload-GGZC5UQP.js.map → upload-KFUYLL7M.js.map} +0 -0
  242. /package/dist/{use-B4Q7CFG2.js.map → use-CNMPP2ED.js.map} +0 -0
  243. /package/dist/{value-DHOHO55D.js.map → value-J335MPZE.js.map} +0 -0
  244. /package/dist/{visible-S5BTWYNH.js.map → visible-YQZWWPBZ.js.map} +0 -0
  245. /package/dist/{wait-WV6NZUKL.js.map → wait-IC7YJJPJ.js.map} +0 -0
  246. /package/dist/{windows-GKE36DJQ.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-2X4JFMKJ.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,
@@ -11192,6 +11192,155 @@ var expandInspiredesignBrief = (brief, preferredFormatId) => {
11192
11192
  };
11193
11193
  };
11194
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
+
11195
11344
  // src/inspiredesign/reference-pattern-board.ts
11196
11345
  var SIGNAL_LIMIT = 5;
11197
11346
  var SIGNAL_CLIP = 180;
@@ -11204,7 +11353,11 @@ var SCORE_CLONE = 8;
11204
11353
  var SCORE_DOM = 8;
11205
11354
  var SCORE_PUBLIC_LANDING = 6;
11206
11355
  var SCORE_SIGNAL_CAP = 12;
11356
+ var SCORE_INTENT_MISMATCH_PENALTY = 55;
11357
+ var SCORE_PINTEREST_CHROME_METADATA_PENALTY = 35;
11207
11358
  var MAX_REFERENCE_SCORE = 100;
11359
+ var MIN_READY_REFERENCE_SCORE = 50;
11360
+ var MIN_READY_REFERENCE_CONFIDENCE = 0.5;
11208
11361
  var ADVANCED_MOTION_FIELDS = [
11209
11362
  "Advisory shader-style gradients: specify effect type, uniforms, static fallback, and reduced-motion replacement as design language only.",
11210
11363
  "Advisory WebGL-style depth cues: describe layered depth, camera-like parallax, and spatial hierarchy without requiring WebGL runtime.",
@@ -11235,6 +11388,15 @@ var DIAGNOSTIC_TEXT_MARKERS = [
11235
11388
  "challenge page",
11236
11389
  "access denied",
11237
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",
11238
11400
  "javascript required",
11239
11401
  "javascript is required",
11240
11402
  "captcha",
@@ -11244,6 +11406,31 @@ var DIAGNOSTIC_TEXT_MARKERS = [
11244
11406
  "complete the verification",
11245
11407
  "blocked reference"
11246
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
+ ];
11247
11434
  var INTERFACE_CHROME_TEXT_MARKERS = [
11248
11435
  "your profile",
11249
11436
  "your boards",
@@ -11300,14 +11487,53 @@ var isDiagnosticText = (value) => {
11300
11487
  const lower = value.toLowerCase();
11301
11488
  return DIAGNOSTIC_TEXT_MARKERS.some((marker) => lower.includes(marker));
11302
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
+ };
11303
11527
  var isInterfaceChromeText = (value) => {
11304
11528
  const lower = value.toLowerCase();
11305
- 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") || 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")) {
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")) {
11306
11532
  return true;
11307
11533
  }
11308
- const markerCount = INTERFACE_CHROME_TEXT_MARKERS.filter((marker) => lower.includes(marker)).length;
11309
11534
  return markerCount >= 3 || lower.includes("pin card") && lower.includes("your profile");
11310
11535
  };
11536
+ var countActionRefs = (value) => (value.match(/\[r\d+\]\s+(?:link|button|combobox|textbox|option)\s+/gi) ?? []).length;
11311
11537
  var hasPublicLandingSignal = (value) => {
11312
11538
  const lower = value.toLowerCase();
11313
11539
  const strongCount = PUBLIC_LANDING_TEXT_MARKERS.filter((marker) => lower.includes(marker)).length;
@@ -11337,13 +11563,56 @@ var getInspiredesignReferenceSignals = (reference) => {
11337
11563
  var hasCleanSignal = (value) => {
11338
11564
  if (!value || isCodeOrCssPreview(value)) return false;
11339
11565
  const text = cleanEvidenceText(value);
11340
- return text.length > 0 && !isCodeOrCssPreview(text) && !isDiagnosticText(text) && !isInterfaceChromeText(text);
11566
+ return text.length > 0 && !isCodeOrCssPreview(text) && !isDiagnosticText(text) && !isDiagnosticPageText(text) && !isInterfaceChromeText(text);
11341
11567
  };
11342
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);
11343
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");
11344
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
+ }
11345
11614
  if (reference.captureStatus === "captured" && hasUsableCaptureEvidence(reference)) return true;
11346
- return reference.fetchStatus === "captured" && (hasCleanSignal(reference.title) || hasCleanSignal(reference.excerpt));
11615
+ return reference.fetchStatus === "captured" && diagnosticReasons.length === 0 && (hasCleanSignal(reference.title) || hasCleanSignal(reference.excerpt));
11347
11616
  };
11348
11617
  var firstSignal = (reference) => {
11349
11618
  const preferred = [
@@ -11414,25 +11683,34 @@ var appendSourceDetail = (patterns, primarySignal) => {
11414
11683
  };
11415
11684
  var deriveCapturedVia = (reference) => {
11416
11685
  const methods = [];
11686
+ const diagnosticReasons = referenceDiagnosticReasons(reference);
11687
+ const hasPinterestVisualMetadata = hasPinterestVisualMetadataEvidence(reference, diagnosticReasons);
11417
11688
  if (reference.fetchStatus === "captured") methods.push("fetch");
11418
- if (reference.capture?.snapshot?.content.trim()) methods.push("snapshot");
11689
+ if (hasCleanSignal(reference.capture?.snapshot?.content)) methods.push("snapshot");
11419
11690
  if (hasUsableCloneCreativeEvidence(reference)) {
11420
11691
  methods.push("clone");
11421
11692
  }
11422
- if (reference.capture?.dom?.outerHTML.trim()) methods.push("dom");
11423
- if (reference.capture?.visual?.status === "captured") methods.push("visual");
11693
+ if (hasCleanSignal(textFromHtml(reference.capture?.dom?.outerHTML))) methods.push("dom");
11694
+ if (reference.capture?.visual?.status === "captured" && (hasUsableCaptureEvidence(reference) || hasPinterestVisualMetadata)) methods.push("visual");
11424
11695
  return methods;
11425
11696
  };
11426
11697
  var scoreReference = (reference, signals, isPublicLanding) => {
11427
11698
  let score = 0;
11699
+ const diagnosticReasons = referenceDiagnosticReasons(reference);
11700
+ const hasPinterestVisualMetadata = hasPinterestVisualMetadataEvidence(reference, diagnosticReasons);
11428
11701
  if (reference.fetchStatus === "captured") score += SCORE_FETCH_CAPTURED;
11429
- if (reference.captureStatus === "captured") score += SCORE_CAPTURE_CAPTURED;
11430
- if (reference.capture?.visual?.status === "captured") score += SCORE_VISUAL_CAPTURED;
11431
- if (reference.capture?.snapshot?.content.trim()) score += SCORE_SNAPSHOT;
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;
11432
11707
  if (hasUsableCloneCreativeEvidence(reference)) score += SCORE_CLONE;
11433
- if (reference.capture?.dom?.outerHTML.trim()) score += SCORE_DOM;
11708
+ if (hasCleanSignal(textFromHtml(reference.capture?.dom?.outerHTML))) score += SCORE_DOM;
11434
11709
  if (isPublicLanding) score += SCORE_PUBLIC_LANDING;
11435
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
+ }
11436
11714
  return Math.min(MAX_REFERENCE_SCORE, score);
11437
11715
  };
11438
11716
  var confidenceFromScore = (score) => Number((score / MAX_REFERENCE_SCORE).toFixed(2));
@@ -11485,13 +11763,68 @@ var boardEvidenceText = (board) => board.references.map((reference) => [
11485
11763
  ...reference.patternsToBorrow
11486
11764
  ].join(" ")).join(" ").toLowerCase();
11487
11765
  var hasEvidenceCue = (text, matches) => matches.some((match) => text.includes(match));
11488
- 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) => {
11489
11820
  const signals = getInspiredesignReferenceSignals(reference);
11490
11821
  const primarySignal = firstSignal(reference);
11491
11822
  const patterns = appendSourceDetail(derivePatternSummaries(signals, primarySignal), primarySignal);
11492
11823
  const isPublicLanding = signals.some(hasPublicLandingSignal);
11493
11824
  const capturedVia = deriveCapturedVia(reference);
11494
- const score = scoreReference(reference, signals, isPublicLanding);
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);
11495
11828
  return {
11496
11829
  id: reference.id,
11497
11830
  score,
@@ -11500,7 +11833,8 @@ var deriveReferenceEntry = (reference, format) => {
11500
11833
  url: reference.url,
11501
11834
  surfaceType: isPublicLanding ? "public landing page" : format.archetype,
11502
11835
  capturedVia,
11503
- selectionReason: selectionReasonForScore(score, capturedVia),
11836
+ intentMatched,
11837
+ selectionReason: intentMatched ? selectionReasonForScore(score, capturedVia) : `${selectionReasonForScore(score, capturedVia)} Intent overlap with the brief is weak, so the score was downgraded.`,
11504
11838
  visualStrengths: deriveVisualStrengths(reference, patterns),
11505
11839
  visualRisks: deriveVisualRisks(reference),
11506
11840
  layoutRecipe: patterns.join("; "),
@@ -11518,6 +11852,13 @@ var sortReferenceEntries = (entries) => entries.slice().sort((left, right) => ri
11518
11852
  ...entry
11519
11853
  }));
11520
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
+ }
11521
11862
  if (reference.fetchStatus === "failed" && reference.captureStatus === "failed") {
11522
11863
  return "Fetch and capture did not produce usable creative evidence.";
11523
11864
  }
@@ -11536,16 +11877,72 @@ var buildRejectedReferences = (references) => references.filter((reference) => !
11536
11877
  fetchStatus: reference.fetchStatus,
11537
11878
  captureStatus: reference.captureStatus
11538
11879
  }));
11539
- var buildInspiredesignReferencePatternBoard = (briefId, format, references) => {
11540
- const entries = references.filter(hasInspiredesignUsableReferenceEvidence).map((reference) => deriveReferenceEntry(reference, format));
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));
11541
11936
  const rankedEntries = sortReferenceEntries(entries);
11937
+ const rejectedReferences = buildRejectedReferences(references);
11542
11938
  const sharedStrengths = rankedEntries.flatMap((entry) => entry.patternsToBorrow).slice(0, 6);
11543
11939
  const targetSurface = rankedEntries.some((entry) => entry.surfaceType === "public landing page") ? "reference-led public landing page" : format.layoutArchetype;
11544
11940
  return {
11545
11941
  briefId,
11546
11942
  targetSurface,
11943
+ qualitySummary: buildQualitySummary(references, rankedEntries, rejectedReferences),
11547
11944
  references: rankedEntries,
11548
- rejectedReferences: buildRejectedReferences(references),
11945
+ rejectedReferences,
11549
11946
  synthesis: {
11550
11947
  dominantDirection: rankedEntries[0]?.layoutRecipe ?? format.archetype,
11551
11948
  sharedStrengths,
@@ -11651,13 +12048,16 @@ var buildSectionArchitecture = (format, board) => {
11651
12048
  ];
11652
12049
  };
11653
12050
  var buildInspiredesignDesignVectors = (format, board) => {
11654
- const influence = board.synthesis.sharedStrengths.length > 0 ? board.synthesis.sharedStrengths : [format.archetype];
11655
- 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);
11656
12056
  const surfaceIntent = publicLandingEvidence ? "reference-led public landing page" : format.archetype;
11657
- 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)];
11658
12058
  return {
11659
- sourcePriority: board.references.length > 0 ? "reference-evidence-first" : "brief-only",
11660
- directionLabel: board.synthesis.dominantDirection,
12059
+ sourcePriority: designReferences.length > 0 ? "reference-evidence-first" : "brief-only",
12060
+ directionLabel: designReferences[0]?.layoutRecipe ?? format.archetype,
11661
12061
  surfaceIntent,
11662
12062
  compositionModel: compositionModel.slice(0, 5),
11663
12063
  premiumPosture: [
@@ -11671,16 +12071,16 @@ var buildInspiredesignDesignVectors = (format, board) => {
11671
12071
  "Respect reduced-motion preference with static hierarchy preserved.",
11672
12072
  format.motionGrammar
11673
12073
  ],
11674
- sectionArchitecture: buildSectionArchitecture(format, board),
12074
+ sectionArchitecture: buildSectionArchitecture(format, designBoard),
11675
12075
  typographyPosture: [format.typographySystem],
11676
- imageryPosture: buildImageryPosture(format, board),
11677
- interactionDensity: buildInteractionDensity(format, board),
11678
- interactionMoments: buildInteractionMoments(format, board),
11679
- materialEffects: buildMaterialEffects(board),
12076
+ imageryPosture: buildImageryPosture(format, designBoard),
12077
+ interactionDensity: buildInteractionDensity(format, designBoard),
12078
+ interactionMoments: buildInteractionMoments(format, designBoard),
12079
+ materialEffects: buildMaterialEffects(designBoard),
11680
12080
  advancedMotionAdvisory: [...ADVANCED_MOTION_FIELDS],
11681
12081
  referenceInfluence: influence,
11682
- patternsToBorrow: board.references.flatMap((entry) => entry.patternsToBorrow).slice(0, 8),
11683
- 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),
11684
12084
  guardrails: [...format.guardrails],
11685
12085
  antiPatterns: [...format.antiPatterns]
11686
12086
  };
@@ -11688,11 +12088,11 @@ var buildInspiredesignDesignVectors = (format, board) => {
11688
12088
 
11689
12089
  // src/inspiredesign/meta-prompt.ts
11690
12090
  var formatList = (items) => items.length > 0 ? items.map((item) => `- ${item}`).join("\n") : "- No evidence-backed item available.";
11691
- var formatRankedReferences = (board) => {
11692
- if (board.references.length === 0) {
11693
- return "- No usable references were ranked. Work from the brief and note missing evidence.";
12091
+ var formatRankedReferences = (references) => {
12092
+ if (references.length === 0) {
12093
+ return "- No ready references were ranked. Work from the brief and note missing evidence.";
11694
12094
  }
11695
- return board.references.map((reference) => [
12095
+ return references.map((reference) => [
11696
12096
  `### Rank ${reference.rank}: ${reference.name}`,
11697
12097
  `- URL: ${reference.url}`,
11698
12098
  `- Score: ${reference.score}`,
@@ -11704,64 +12104,71 @@ var formatRankedReferences = (board) => {
11704
12104
  `- Visual risks: ${reference.visualRisks.join("; ")}`
11705
12105
  ].join("\n")).join("\n\n");
11706
12106
  };
11707
- var formatRejectedReferences = (board) => {
11708
- if (board.rejectedReferences.length === 0) {
11709
- return "- No references were rejected from the creative synthesis.";
11710
- }
11711
- return board.rejectedReferences.map((reference) => `- ${reference.url}: ${reference.reason} (fetch=${reference.fetchStatus}, capture=${reference.captureStatus})`).join("\n");
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");
11712
12171
  };
11713
- var buildInspiredesignMetaPrompt = (input) => [
11714
- "# InspireDesign Meta Prompt",
11715
- "",
11716
- "Use this prompt to generate a fresh design direction from evidence without copying any reference brand, asset, layout, or proprietary expression.",
11717
- "",
11718
- "## Source Brief",
11719
- input.brief,
11720
- "",
11721
- "## Prompt Format",
11722
- `- Format: ${input.briefExpansion.format.label}`,
11723
- `- Target surface: ${input.referencePatternBoard.targetSurface}`,
11724
- `- Dominant direction: ${input.referencePatternBoard.synthesis.dominantDirection}`,
11725
- "",
11726
- "## Ranked References",
11727
- formatRankedReferences(input.referencePatternBoard),
11728
- "",
11729
- "## Rejected References",
11730
- formatRejectedReferences(input.referencePatternBoard),
11731
- "",
11732
- "## Borrow Guidance",
11733
- formatList(input.designVectors.patternsToBorrow),
11734
- "",
11735
- "## Reject Guidance",
11736
- formatList([
11737
- ...input.designVectors.patternsToReject,
11738
- "Do not copy logos, screenshots, protected brand assets, page structure, copy, or trade dress from references."
11739
- ]),
11740
- "",
11741
- "## Motion Posture",
11742
- formatList([
11743
- ...input.designVectors.motionPosture,
11744
- ...input.designVectors.interactionMoments,
11745
- ...input.designVectors.advancedMotionAdvisory
11746
- ]),
11747
- "",
11748
- "## Accessibility Constraints",
11749
- formatList([
11750
- "Keyboard navigation must reach every interactive element.",
11751
- "Focus states must be visible in every theme and viewport.",
11752
- "Respect prefers-reduced-motion with a static hierarchy-preserving alternative.",
11753
- "Validate contrast for text, controls, overlays, and disabled states."
11754
- ]),
11755
- "",
11756
- "## Validation Gates",
11757
- formatList([
11758
- "Read visual-evidence.json, screenshot-index.json, ranked-references.json, and evidence.json before implementation.",
11759
- "Confirm screenshot paths exist before making visual claims.",
11760
- "Verify desktop and mobile layouts with real browser screenshots.",
11761
- "Run reduced-motion, keyboard, focus, and contrast checks before shipping.",
11762
- "Keep production code generation outside the harvest output."
11763
- ])
11764
- ].join("\n");
11765
12172
 
11766
12173
  // src/inspiredesign/visual-evidence.ts
11767
12174
  import { createHash as createHash3 } from "crypto";
@@ -12208,13 +12615,16 @@ var buildReferenceSynthesis = (references) => {
12208
12615
  };
12209
12616
  };
12210
12617
  var renderReferenceFirstAdvancedBrief = (briefExpansion, board, vectors, references) => {
12211
- if (board.references.length === 0) {
12618
+ if (board.references.length === 0 || vectors.sourcePriority !== "reference-evidence-first") {
12212
12619
  if (references.length > 0) {
12213
12620
  return [
12214
12621
  "Reference evidence unavailable:",
12215
- "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.",
12216
12623
  "",
12217
- 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
+ ]),
12218
12628
  "",
12219
12629
  briefExpansion.advancedBrief
12220
12630
  ].join("\n");
@@ -12301,10 +12711,6 @@ var renderEvidenceDerivedAdvancedBrief = (briefExpansion, format) => [
12301
12711
  "Best fit use cases:",
12302
12712
  formatBulletList2(format.bestFor)
12303
12713
  ].join("\n");
12304
- var renderUnavailableReference = (reference) => {
12305
- const reason = reference.fetchFailure ?? reference.captureFailure ?? "no usable creative evidence captured";
12306
- return `${reference.url}: fetch=${reference.fetchStatus}, capture=${reference.captureStatus}, reason=${clipText2(reason, 160)}`;
12307
- };
12308
12714
  var cloneTemplate = (value) => structuredClone(value);
12309
12715
  var referenceFingerprint = (value) => {
12310
12716
  return createHash4("sha256").update(value).digest("hex").slice(0, 12);
@@ -12877,15 +13283,14 @@ var buildFollowthrough = ({
12877
13283
  });
12878
13284
  var buildDesignContract = ({
12879
13285
  brief,
12880
- urls,
12881
- references,
13286
+ designReferences,
12882
13287
  plan,
12883
13288
  format
12884
13289
  }) => ({
12885
- intent: buildIntentBlock(brief, urls, references, format),
13290
+ intent: buildIntentBlock(brief, designReferences.map((reference) => reference.url), designReferences, format),
12886
13291
  generationPlan: toCanvasGenerationPlan(plan),
12887
13292
  designLanguage: buildDesignLanguageBlock(plan.visualDirection.profile, format),
12888
- contentModel: buildContentModelBlock(brief, references.filter(hasInspiredesignUsableReferenceEvidence)),
13293
+ contentModel: buildContentModelBlock(brief, designReferences),
12889
13294
  layoutSystem: buildLayoutSystemBlock(plan, format),
12890
13295
  typographySystem: buildTypographySystemBlock(format),
12891
13296
  colorSystem: buildColorSystemBlock(plan.visualDirection.profile, format),
@@ -12957,6 +13362,7 @@ var buildImplementationPlan = ({
12957
13362
  profile,
12958
13363
  format,
12959
13364
  references,
13365
+ attemptedReferenceCount,
12960
13366
  synthesis,
12961
13367
  designVectors
12962
13368
  }) => ({
@@ -12994,7 +13400,7 @@ var buildImplementationPlan = ({
12994
13400
  "Avoid horizontal scrolling for primary content."
12995
13401
  ],
12996
13402
  risksAndAmbiguities: [
12997
- 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.",
12998
13404
  "Any missing interaction states must be validated during visual QA.",
12999
13405
  "Capture desktop and mobile browser proof before handoff, including reduced-motion behavior and primary CTA visibility."
13000
13406
  ],
@@ -13249,11 +13655,11 @@ var renderPrototypeGuidance = (profile, synthesis, designVectors, targetAnalysis
13249
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."
13250
13656
  ].join("\n");
13251
13657
  };
13252
- var renderDeliverablesSummary = (includePrototypeGuidance) => {
13658
+ var renderDeliverablesSummary = (includePrototypeGuidance, canvasContinuationReady) => {
13253
13659
  const deliverables = [
13254
13660
  "Structured `designContract` JSON aligned to canvas governance",
13255
13661
  "Valid `generationPlan` JSON aligned to the canvas generation plan contract",
13256
- "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",
13257
13663
  "Design-agent handoff JSON with contract scope, skill nudges, and richer implementation context",
13258
13664
  "Human-readable `design.md` design specification",
13259
13665
  "Engineering implementation plan in JSON and Markdown"
@@ -13342,19 +13748,25 @@ var buildInspiredesignPacket = (input) => {
13342
13748
  title: reference.title ? trimText2(reference.title) : void 0,
13343
13749
  excerpt: reference.excerpt ? trimText2(reference.excerpt) : void 0
13344
13750
  }));
13345
- const usableReferences = references.filter(hasInspiredesignUsableReferenceEvidence);
13346
- const synthesis = buildReferenceSynthesis(usableReferences);
13751
+ const referenceEvidenceRequired = input.referenceEvidenceRequired ?? (urls.length > 0 || references.length > 0);
13347
13752
  const referencePatternBoard = buildInspiredesignReferencePatternBoard(
13348
13753
  referenceFingerprint(brief),
13349
13754
  selectedFormat,
13350
- references
13755
+ references,
13756
+ brief
13351
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);
13352
13763
  const designVectors = buildInspiredesignDesignVectors(selectedFormat, referencePatternBoard);
13764
+ const designReferencePatternBoard = buildInspiredesignDesignReferencePatternBoard(referencePatternBoard, designVectors);
13353
13765
  const effectiveFormat = buildEvidenceDerivedFormat(selectedFormat, designVectors);
13354
13766
  const targetAnalysis = buildTargetAnalysis(
13355
13767
  brief,
13356
13768
  effectiveFormat,
13357
- references,
13769
+ usableReferences,
13358
13770
  synthesis,
13359
13771
  designVectors
13360
13772
  );
@@ -13371,7 +13783,7 @@ var buildInspiredesignPacket = (input) => {
13371
13783
  });
13372
13784
  const advancedBriefMarkdown = renderReferenceFirstAdvancedBrief(
13373
13785
  effectiveBriefExpansion,
13374
- referencePatternBoard,
13786
+ designReferencePatternBoard,
13375
13787
  designVectors,
13376
13788
  references
13377
13789
  );
@@ -13379,7 +13791,7 @@ var buildInspiredesignPacket = (input) => {
13379
13791
  brief,
13380
13792
  format: effectiveFormat,
13381
13793
  synthesis,
13382
- referencePatternBoard,
13794
+ referencePatternBoard: designReferencePatternBoard,
13383
13795
  designVectors,
13384
13796
  targetAnalysis
13385
13797
  });
@@ -13387,8 +13799,7 @@ var buildInspiredesignPacket = (input) => {
13387
13799
  const canvasPlanRequest = buildCanvasPlanRequest(brief, generationPlan);
13388
13800
  const designContract = buildDesignContract({
13389
13801
  brief,
13390
- urls,
13391
- references,
13802
+ designReferences: usableReferences,
13392
13803
  plan: generationPlan,
13393
13804
  format: effectiveFormat
13394
13805
  });
@@ -13397,14 +13808,15 @@ var buildInspiredesignPacket = (input) => {
13397
13808
  briefExpansion: effectiveBriefExpansion,
13398
13809
  synthesis,
13399
13810
  includePrototypeGuidance,
13400
- referencePatternBoard,
13811
+ referencePatternBoard: designReferencePatternBoard,
13401
13812
  designVectors,
13402
13813
  targetAnalysis
13403
13814
  });
13404
13815
  const implementationPlan = buildImplementationPlan({
13405
13816
  profile,
13406
13817
  format: effectiveFormat,
13407
- references,
13818
+ references: usableReferences,
13819
+ attemptedReferenceCount: references.length,
13408
13820
  synthesis,
13409
13821
  designVectors
13410
13822
  });
@@ -13435,7 +13847,7 @@ var buildInspiredesignPacket = (input) => {
13435
13847
  "",
13436
13848
  "## 3.2 Reference Pattern Board",
13437
13849
  "",
13438
- 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."]),
13439
13851
  "",
13440
13852
  "## 3.3 Design Vectors",
13441
13853
  "",
@@ -13474,7 +13886,10 @@ var buildInspiredesignPacket = (input) => {
13474
13886
  "",
13475
13887
  "# 7. Deliverables Summary",
13476
13888
  "",
13477
- renderDeliverablesSummary(Boolean(input.includePrototypeGuidance))
13889
+ renderDeliverablesSummary(
13890
+ Boolean(input.includePrototypeGuidance),
13891
+ !referenceEvidenceRequired || designReferencePatternBoard.references.length > 0
13892
+ )
13478
13893
  ].join("\n");
13479
13894
  const visualEvidence = buildVisualEvidencePayload(references);
13480
13895
  const screenshotIndex = buildScreenshotIndex(references);
@@ -13490,7 +13905,7 @@ var buildInspiredesignPacket = (input) => {
13490
13905
  prototypeGuidanceMarkdown,
13491
13906
  visualEvidence,
13492
13907
  screenshotIndex,
13493
- rankedReferences: referencePatternBoard.references,
13908
+ rankedReferences: designReferencePatternBoard.references,
13494
13909
  metaPromptMarkdown,
13495
13910
  evidence: buildEvidencePayload({
13496
13911
  brief,
@@ -13498,13 +13913,1211 @@ var buildInspiredesignPacket = (input) => {
13498
13913
  advancedBriefMarkdown,
13499
13914
  urls,
13500
13915
  references,
13501
- referencePatternBoard,
13916
+ referencePatternBoard: designReferencePatternBoard,
13502
13917
  designVectors,
13503
13918
  targetAnalysis
13504
13919
  })
13505
13920
  };
13506
13921
  };
13507
13922
 
13923
+ // src/guidance/renderers.ts
13924
+ var toJsonValue2 = (value) => {
13925
+ return structuredClone(value);
13926
+ };
13927
+ var renderWorkflowGuidance = (guidance) => {
13928
+ return toJsonValue2(guidance);
13929
+ };
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
+ };
13947
+ };
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";
13995
+ };
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
+ }
14044
+ };
14045
+ var exampleIds = {
14046
+ canvasSessionId: "canvas-session-from-session-open",
14047
+ leaseId: "lease-from-session-open",
14048
+ documentId: "document-from-session-open"
14049
+ };
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
+ }
14057
+ };
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";
14094
+ }
14095
+ };
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
+
13508
15121
  // src/providers/workflow-handoff.ts
13509
15122
  var PRODUCT_VIDEO_BRIEF_HELPER_PATH = "./skills/opendevbrowser-product-presentation-asset/scripts/render-video-brief.sh";
13510
15123
  var PRODUCT_VIDEO_BRIEF_HELPER_COMMAND = `${PRODUCT_VIDEO_BRIEF_HELPER_PATH} <pack>/manifest.json`;
@@ -13513,7 +15126,7 @@ var createSuccessHandoff = (followthroughSummary, suggestedNextAction, suggested
13513
15126
  suggestedNextAction,
13514
15127
  suggestedSteps
13515
15128
  });
13516
- var cliExample = (command, args = "") => `npx opendevbrowser ${command}${args ? ` ${args}` : ""}`;
15129
+ var cliExample = (command, args) => `npx opendevbrowser ${command} ${args}`;
13517
15130
  var quoteCliValue = (value) => JSON.stringify(value);
13518
15131
  var GATED_PROVIDER_REASON_CODES = /* @__PURE__ */ new Set([
13519
15132
  "auth_required",
@@ -13643,6 +15256,10 @@ var buildProductVideoRerunCommand = (input = {}) => {
13643
15256
  `${target}${providerHint}${screenshots}${allImages}${includeCopy}${browserMode} --use-cookies --challenge-automation-mode browser_with_helper --output-format json`
13644
15257
  );
13645
15258
  };
15259
+ var extractPrimaryConstraintSentence = (summary) => {
15260
+ const match = /^Primary constraint:\s+(.+?\.)\s/.exec(summary);
15261
+ return match?.[1] ?? null;
15262
+ };
13646
15263
  var buildMacroResolveArgs = (input, options) => {
13647
15264
  const defaultProvider = input.defaultProvider ? ` --default-provider ${input.defaultProvider}` : "";
13648
15265
  const execute = options?.execute ? " --execute" : "";
@@ -13650,7 +15267,7 @@ var buildMacroResolveArgs = (input, options) => {
13650
15267
  const useCookies = options?.useCookies ? " --use-cookies" : "";
13651
15268
  const challenge = options?.challengeAutomationMode ? ` --challenge-automation-mode ${options.challengeAutomationMode}` : "";
13652
15269
  const cookiePolicy = options?.cookiePolicyOverride ? ` --cookie-policy ${options.cookiePolicyOverride}` : "";
13653
- const outputFormat = options?.includeOutputFormat === false ? "" : " --output-format json";
15270
+ const outputFormat = " --output-format json";
13654
15271
  return `--expression ${quoteCliValue(input.expression)}${defaultProvider}${execute}${browserMode}${useCookies}${cookiePolicy}${challenge}${outputFormat}`;
13655
15272
  };
13656
15273
  var buildMacroPreviewCommand = (input) => cliExample("macro-resolve", buildMacroResolveArgs(input));
@@ -13664,7 +15281,7 @@ var buildResearchGatedSuccessHandoff = (input, signal) => {
13664
15281
  const recoveryCommand = buildResearchRecoveryRerunCommand(input, signal);
13665
15282
  const providers = signal.providers.length > 0 ? signal.providers.join(", ") : "gated providers";
13666
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.";
13667
- return createSuccessHandoff(
15284
+ const handoff = createSuccessHandoff(
13668
15285
  `Review ranked records, artifact metadata, and gated-provider diagnostics for ${providers} before publishing claims.`,
13669
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}`,
13670
15287
  [
@@ -13676,6 +15293,21 @@ var buildResearchGatedSuccessHandoff = (input, signal) => {
13676
15293
  { reason: "Keep SERPs discovery-only and publish only claims supported by destination records that passed review." }
13677
15294
  ]
13678
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
+ };
13679
15311
  };
13680
15312
  var buildResearchDefaultSuccessHandoff = (input) => {
13681
15313
  const rerunCommand = buildResearchRerunCommand(input);
@@ -13764,31 +15396,43 @@ var buildMacroResolveSuccessHandoff = (input) => {
13764
15396
  ]
13765
15397
  );
13766
15398
  };
13767
- var buildInspiredesignSuccessHandoff = (input) => createSuccessHandoff(
13768
- input.summary,
13769
- input.nextStep,
13770
- [
13771
- { reason: INSPIREDESIGN_HANDOFF_GUIDANCE.reviewAdvancedBrief },
13772
- {
13773
- reason: "Load the baseline workflow runbook before implementation.",
13774
- command: input.commandExamples.loadBestPractices
13775
- },
13776
- {
13777
- reason: "Load the Canvas contract lane before patching.",
13778
- command: input.commandExamples.loadDesignAgent
13779
- },
13780
- {
13781
- reason: "Load the motion-design lane before translating visual evidence into animation, timing, or reduced-motion behavior.",
13782
- command: input.commandExamples.loadMotionDesign
13783
- },
13784
- { reason: INSPIREDESIGN_HANDOFF_GUIDANCE.visualArtifactRecommendation },
13785
- {
13786
- reason: INSPIREDESIGN_HANDOFF_GUIDANCE.prepareCanvasPlanRequest,
13787
- command: input.commandExamples.continueInCanvas
13788
- },
13789
- { reason: input.deepCaptureRecommendation }
13790
- ]
13791
- );
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
+ };
13792
15436
 
13793
15437
  // src/providers/renderer.ts
13794
15438
  var toCurrency = (value) => `$${value.toFixed(2)}`;
@@ -13893,6 +15537,33 @@ var researchFailureMessage = (content) => boundedInlineText({
13893
15537
  limit: RESEARCH_REPORT_LIMITS.failureMessageCharacters,
13894
15538
  target: "meta.json"
13895
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
+ };
13896
15567
  var limitedCount = (total, limit) => Math.min(total, limit);
13897
15568
  var omissionLine = (args) => {
13898
15569
  const omitted = args.total - limitedCount(args.total, args.limit);
@@ -14321,6 +15992,7 @@ var renderInspiredesign = (args) => {
14321
15992
  const screenshotIndex = args.screenshotIndex ?? [];
14322
15993
  const rankedReferences = args.rankedReferences ?? [];
14323
15994
  const rankedReferencesArtifact = args.referencePatternBoard ? {
15995
+ qualitySummary: args.referencePatternBoard.qualitySummary,
14324
15996
  references: args.referencePatternBoard.references,
14325
15997
  rejectedReferences: args.referencePatternBoard.rejectedReferences,
14326
15998
  synthesis: args.referencePatternBoard.synthesis
@@ -14336,18 +16008,42 @@ var renderInspiredesign = (args) => {
14336
16008
  meta: args.meta
14337
16009
  });
14338
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
+ };
14339
16034
  const contextPayload = {
14340
16035
  brief: args.brief,
14341
16036
  advancedBriefMarkdown: args.advancedBriefMarkdown,
14342
16037
  urls: args.urls,
14343
16038
  designContract: args.designContract,
14344
16039
  canvasPlanRequest: args.canvasPlanRequest,
14345
- designAgentHandoff: args.designAgentHandoff,
16040
+ designAgentHandoff: renderedDesignAgentHandoff,
16041
+ ...args.nextStepGuidance ? { nextStepGuidance: args.nextStepGuidance } : {},
14346
16042
  generationPlan: args.generationPlan,
14347
16043
  implementationPlan: args.implementationPlan,
14348
16044
  designMarkdown: args.designMarkdown,
14349
16045
  implementationPlanMarkdown: args.implementationPlanMarkdown,
14350
- prototypeGuidanceMarkdown: args.prototypeGuidanceMarkdown,
16046
+ prototypeGuidanceMarkdown,
14351
16047
  evidence: args.evidence,
14352
16048
  visualEvidence,
14353
16049
  screenshotIndex,
@@ -14355,18 +16051,15 @@ var renderInspiredesign = (args) => {
14355
16051
  metaPromptMarkdown,
14356
16052
  meta: args.meta
14357
16053
  };
14358
- const handoff = buildInspiredesignSuccessHandoff({
14359
- summary: followthroughSummary,
14360
- nextStep: args.designAgentHandoff.nextStep,
14361
- commandExamples: args.designAgentHandoff.commandExamples,
14362
- deepCaptureRecommendation: args.designAgentHandoff.deepCaptureRecommendation
14363
- });
14364
16054
  const files = [
14365
16055
  { path: INSPIREDESIGN_HANDOFF_FILES.designMarkdown, content: args.designMarkdown },
14366
16056
  { path: INSPIREDESIGN_HANDOFF_FILES.advancedBrief, content: args.advancedBriefMarkdown },
14367
16057
  { path: INSPIREDESIGN_HANDOFF_FILES.designContract, content: args.designContract },
14368
16058
  { path: INSPIREDESIGN_HANDOFF_FILES.canvasPlanRequest, content: args.canvasPlanRequest },
14369
- { path: INSPIREDESIGN_HANDOFF_FILES.designAgentHandoff, content: args.designAgentHandoff },
16059
+ {
16060
+ path: INSPIREDESIGN_HANDOFF_FILES.designAgentHandoff,
16061
+ content: renderedDesignAgentHandoff
16062
+ },
14370
16063
  { path: INSPIREDESIGN_HANDOFF_FILES.generationPlan, content: args.generationPlan },
14371
16064
  { path: INSPIREDESIGN_HANDOFF_FILES.implementationPlanMarkdown, content: args.implementationPlanMarkdown },
14372
16065
  { path: INSPIREDESIGN_HANDOFF_FILES.implementationPlan, content: args.implementationPlan },
@@ -14376,8 +16069,8 @@ var renderInspiredesign = (args) => {
14376
16069
  { path: INSPIREDESIGN_HANDOFF_FILES.rankedReferences, content: rankedReferencesArtifact },
14377
16070
  { path: INSPIREDESIGN_HANDOFF_FILES.metaPrompt, content: metaPromptMarkdown }
14378
16071
  ];
14379
- if (args.prototypeGuidanceMarkdown) {
14380
- files.push({ path: INSPIREDESIGN_HANDOFF_FILES.prototypeGuidance, content: args.prototypeGuidanceMarkdown });
16072
+ if (prototypeGuidanceMarkdown) {
16073
+ files.push({ path: INSPIREDESIGN_HANDOFF_FILES.prototypeGuidance, content: prototypeGuidanceMarkdown });
14381
16074
  }
14382
16075
  const captureAttemptFields = {
14383
16076
  ...captureAttemptSummary ? { captureAttemptSummary } : {},
@@ -14403,11 +16096,12 @@ var renderInspiredesign = (args) => {
14403
16096
  advancedBriefMarkdown: args.advancedBriefMarkdown,
14404
16097
  urls: args.urls,
14405
16098
  canvasPlanRequest: args.canvasPlanRequest,
14406
- designAgentHandoff: args.designAgentHandoff,
16099
+ designAgentHandoff: renderedDesignAgentHandoff,
16100
+ ...args.nextStepGuidance ? { nextStepGuidance: args.nextStepGuidance } : {},
14407
16101
  designContract: args.designContract,
14408
16102
  generationPlan: args.generationPlan,
14409
16103
  implementationPlan: args.implementationPlan,
14410
- prototypeGuidanceMarkdown: args.prototypeGuidanceMarkdown,
16104
+ prototypeGuidanceMarkdown,
14411
16105
  evidence: args.evidence,
14412
16106
  visualEvidence,
14413
16107
  screenshotIndex,
@@ -14426,7 +16120,7 @@ var renderInspiredesign = (args) => {
14426
16120
  mode: args.mode,
14427
16121
  markdown: args.designMarkdown,
14428
16122
  implementationPlanMarkdown: args.implementationPlanMarkdown,
14429
- prototypeGuidanceMarkdown: args.prototypeGuidanceMarkdown,
16123
+ prototypeGuidanceMarkdown,
14430
16124
  ...handoff,
14431
16125
  ...captureAttemptFields,
14432
16126
  meta: args.meta
@@ -14457,6 +16151,137 @@ var renderInspiredesign = (args) => {
14457
16151
  };
14458
16152
  };
14459
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
+
14460
16285
  // src/inspiredesign/reference-discovery.ts
14461
16286
  var normalizeHttpUrl = (value) => {
14462
16287
  try {
@@ -15170,7 +16995,7 @@ var withOfferFilterDiagnosticDetails = (details, offerFilterDiagnostic) => {
15170
16995
  };
15171
16996
  };
15172
16997
  var inferShoppingNoOfferFailure = (providerId, query, records, offerFilterDiagnostic) => {
15173
- const issuePriority = (issue) => ({
16998
+ const issuePriority2 = (issue) => ({
15174
16999
  token_required: 3,
15175
17000
  auth_required: 3,
15176
17001
  challenge_detected: 2
@@ -15185,7 +17010,7 @@ var inferShoppingNoOfferFailure = (providerId, query, records, offerFilterDiagno
15185
17010
  ...title ? { title } : {},
15186
17011
  ...typeof record.attributes.providerShell === "string" && record.attributes.providerShell.trim().length > 0 ? { providerShell: record.attributes.providerShell.trim() } : {}
15187
17012
  }];
15188
- }).sort((left, right) => issuePriority(right.hint) - issuePriority(left.hint))[0] ?? null;
17013
+ }).sort((left, right) => issuePriority2(right.hint) - issuePriority2(left.hint))[0] ?? null;
15189
17014
  if (primaryRecordIssue) {
15190
17015
  const reasonCode = primaryRecordIssue.hint.reasonCode;
15191
17016
  return {
@@ -16335,6 +18160,307 @@ function resolveInspiredesignCaptureMode(requested, urls) {
16335
18160
  return hasInspiredesignUrls(urls) ? "deep" : requested ?? "off";
16336
18161
  }
16337
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
+ };
18463
+
16338
18464
  // src/providers/workflows.ts
16339
18465
  var SIGNAL_WINDOW = 50;
16340
18466
  var RECOVERY_WINDOWS_REQUIRED = 2;
@@ -16594,7 +18720,15 @@ var withPrimaryConstraintMeta = (meta, failures) => {
16594
18720
  var withCamelCasePrimaryConstraintMeta = withPrimaryConstraintMeta;
16595
18721
  var readPrimaryConstraintGuidance = (constraint) => {
16596
18722
  const guidance = constraint.guidance;
16597
- 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
+ };
16598
18732
  };
16599
18733
  var withPrimaryConstraintSummaryOverride = (meta, summary, guidance) => {
16600
18734
  const currentPrimaryConstraint = meta.primaryConstraint;
@@ -17404,10 +19538,11 @@ var buildInspiredesignStepEnvelope = (workflowInput, trace, stepIndex, url) => b
17404
19538
  trace
17405
19539
  }
17406
19540
  );
17407
- var buildInspiredesignFetchOptions = (workflowInput, envelope, timeoutMs) => withWorkflowResumeEnvelopeIntent(
19541
+ var buildInspiredesignFetchOptionsWithScope = (workflowInput, envelope, providerScope, timeoutMs) => withWorkflowResumeEnvelopeIntent(
17408
19542
  withBrowserModeOverride(
17409
19543
  withChallengeAutomationOverride(
17410
19544
  withCookieOverrides({
19545
+ ...providerScope,
17411
19546
  ...typeof timeoutMs === "number" ? { timeoutMs } : {}
17412
19547
  }, workflowInput),
17413
19548
  workflowInput
@@ -17417,6 +19552,26 @@ var buildInspiredesignFetchOptions = (workflowInput, envelope, timeoutMs) => wit
17417
19552
  "workflow.inspiredesign",
17418
19553
  envelope
17419
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);
17420
19575
  var emptyInspiredesignDiscoveryDiagnostics = (workflowInput, searchAvailable, failure) => ({
17421
19576
  requested: Boolean(workflowInput.query),
17422
19577
  searchAvailable,
@@ -17457,10 +19612,153 @@ var failureFromInspiredesignFetchError = (result) => {
17457
19612
  error: result.error
17458
19613
  }];
17459
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
+ };
17460
19659
  var discoverInspiredesignReferences = async (runtime, workflowInput, envelope, timeoutMs) => {
17461
19660
  if (!workflowInput.query) {
17462
19661
  return emptyInspiredesignDiscoveryDiagnostics(workflowInput, typeof runtime.search === "function");
17463
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
+ }
17464
19762
  if (typeof runtime.search !== "function") {
17465
19763
  return emptyInspiredesignDiscoveryDiagnostics(
17466
19764
  workflowInput,
@@ -17934,11 +20232,85 @@ var summarizeInspiredesignFetchConstraint = (references) => {
17934
20232
  return references.find((reference) => reference.fetchStatus === "failed" && !isInspiredesignFetchRecovered(reference) && typeof reference.fetchFailure === "string" && reference.fetchFailure.trim().length > 0)?.fetchFailure;
17935
20233
  };
17936
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
+ ];
17937
20261
  var selectInspiredesignPrimaryConstraintFailures = (failures, references, discovery) => {
17938
20262
  if (!hasSurvivingInspiredesignReference(references)) return failures;
17939
20263
  if (discovery.failures.length === 0) return failures;
17940
20264
  return failures.slice(discovery.failures.length);
17941
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
+ };
17942
20314
  var buildInspiredesignMeta = (runtime, workflowInput, references, failures, followthrough, discovery) => {
17943
20315
  const failedCaptures = references.filter((reference) => reference.captureStatus === "failed");
17944
20316
  const captureAttemptReport = summarizeInspiredesignCaptureAttempts(references);
@@ -18034,6 +20406,11 @@ var summarizeInspiredesignDiscoveryConstraint = (discovery) => {
18034
20406
  guidance: buildInspiredesignDiscoveryGuidance(discovery)
18035
20407
  };
18036
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
+ };
18037
20414
  var inferBrandFromContent = (content, productUrl) => {
18038
20415
  const normalized = normalizePlainText(content);
18039
20416
  if (!normalized) return void 0;
@@ -19073,9 +21450,10 @@ var runInspiredesignWorkflow = async (runtime, input, options = {}) => {
19073
21450
  const fetchTimeoutMs = remainingTimeoutMs();
19074
21451
  const fetchResult = await runtime.fetch(
19075
21452
  { url },
19076
- buildInspiredesignFetchOptions(
21453
+ buildInspiredesignReferenceFetchOptions(
19077
21454
  workflowInput,
19078
21455
  buildInspiredesignStepEnvelope(workflowInput, stepTrace, index, url),
21456
+ url,
19079
21457
  fetchTimeoutMs
19080
21458
  )
19081
21459
  );
@@ -19099,7 +21477,9 @@ var runInspiredesignWorkflow = async (runtime, input, options = {}) => {
19099
21477
  const reference = buildInspiredesignReference(url, result, capture);
19100
21478
  references.push(reference);
19101
21479
  if (reference.fetchStatus === "failed" && !isInspiredesignFetchRecovered(reference)) {
19102
- failures.push(...result.failures);
21480
+ const fetchFailures = result.failures.length > 0 ? result.failures : failureFromInspiredesignFetchError(result);
21481
+ const siteRecipe = resolveSiteRecipeForUrl(url);
21482
+ failures.push(...siteRecipe ? normalizeSiteRecipeFetchFailures(siteRecipe, fetchFailures) : fetchFailures);
19103
21483
  }
19104
21484
  trace = appendWorkflowTrace(stepTrace, "execute", "reference_completed", {
19105
21485
  stepIndex: index,
@@ -19114,7 +21494,8 @@ var runInspiredesignWorkflow = async (runtime, input, options = {}) => {
19114
21494
  briefExpansion: workflowInput.briefExpansion,
19115
21495
  urls: workflowInput.urls,
19116
21496
  references: visualCollation.references,
19117
- includePrototypeGuidance: workflowInput.includePrototypeGuidance
21497
+ includePrototypeGuidance: workflowInput.includePrototypeGuidance,
21498
+ referenceEvidenceRequired: isInspiredesignReferenceEvidenceRequired(workflowInput)
19118
21499
  });
19119
21500
  const meta = buildInspiredesignMeta(
19120
21501
  runtime,
@@ -19124,6 +21505,23 @@ var runInspiredesignWorkflow = async (runtime, input, options = {}) => {
19124
21505
  packet.followthrough,
19125
21506
  discovery
19126
21507
  );
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
+ };
19127
21525
  const rendered = renderInspiredesign({
19128
21526
  mode: workflowInput.mode,
19129
21527
  brief: workflowInput.brief,
@@ -19143,7 +21541,8 @@ var runInspiredesignWorkflow = async (runtime, input, options = {}) => {
19143
21541
  rankedReferences: packet.rankedReferences,
19144
21542
  referencePatternBoard: packet.generationPlan.referencePatternBoard,
19145
21543
  metaPromptMarkdown: packet.metaPromptMarkdown,
19146
- meta
21544
+ nextStepGuidance,
21545
+ meta: metaWithGuidance
19147
21546
  });
19148
21547
  const bundle = await createArtifactBundle({
19149
21548
  namespace: "inspiredesign",
@@ -19156,7 +21555,7 @@ var runInspiredesignWorkflow = async (runtime, input, options = {}) => {
19156
21555
  ...rendered.response,
19157
21556
  artifact_path: bundle.basePath,
19158
21557
  meta: {
19159
- ...meta,
21558
+ ...metaWithGuidance,
19160
21559
  artifact_manifest: bundle.manifest
19161
21560
  }
19162
21561
  };
@@ -19165,7 +21564,7 @@ var runInspiredesignWorkflow = async (runtime, input, options = {}) => {
19165
21564
  ...rendered.response,
19166
21565
  artifact_path: bundle.basePath,
19167
21566
  meta: {
19168
- ...meta,
21567
+ ...metaWithGuidance,
19169
21568
  artifact_manifest: bundle.manifest
19170
21569
  }
19171
21570
  };
@@ -21971,6 +24370,8 @@ export {
21971
24370
  CANVAS_BROWSER_VALIDATION_MODES,
21972
24371
  CANVAS_VALIDATION_TARGET_BLOCK_ON_CODES,
21973
24372
  CANVAS_PUBLIC_WARNING_CLASSES,
24373
+ buildCanvasRepairEnvelope,
24374
+ buildCanvasCommandValidationEnvelope,
21974
24375
  createTraceContext,
21975
24376
  clampConfidence,
21976
24377
  createStableRecordId,
@@ -22020,4 +24421,4 @@ export {
22020
24421
  createProviderRuntime,
22021
24422
  createDefaultRuntime
22022
24423
  };
22023
- //# sourceMappingURL=chunk-RO3SMXF3.js.map
24424
+ //# sourceMappingURL=chunk-FBKPDILE.js.map