@koda-sl/baker-cli 0.570.0 → 0.571.0-dev.6a3439a0a
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.
- package/README.md +1 -1
- package/dist/account-EXGRZIXS.js +82 -0
- package/dist/account-JVDP5ERG.js +82 -0
- package/dist/account-reads-Z467VAL4.js +219 -0
- package/dist/account-users-342OZALE.js +64 -0
- package/dist/account-writes-KEXINJ5D.js +68 -0
- package/dist/accounts-QESGQJGZ.js +713 -0
- package/dist/accounts-QR6OQ3GC.js +119 -0
- package/dist/accounts-UWC2TT6R.js +80 -0
- package/dist/actions-NT3HXFFA.js +55 -0
- package/dist/activecampaign-EYRHDSXY.js +938 -0
- package/dist/ad-group-writes-SVR4RCKB.js +172 -0
- package/dist/ad-groups-C726HUXS.js +70 -0
- package/dist/ad-writes-RWJIWGEL.js +176 -0
- package/dist/add-EPOHDTUO.js +305 -0
- package/dist/add-NSW26HIM.js +107 -0
- package/dist/ads-3KK7VQPU.js +79 -0
- package/dist/ads-EWZGIC4T.js +48 -0
- package/dist/advertisers-AHOWL3YL.js +123 -0
- package/dist/analytics-7H6NDVUQ.js +447 -0
- package/dist/analytics-GFFXCMLV.js +2437 -0
- package/dist/animate-GTUI7XX4.js +480 -0
- package/dist/assign-SDPPWP3Q.js +80 -0
- package/dist/audience-size-LKDDHKED.js +76 -0
- package/dist/audiences-6L43K2T2.js +280 -0
- package/dist/audit-TSZIQTUB.js +154 -0
- package/dist/autocomplete-5BSAOAMZ.js +114 -0
- package/dist/avatars-S6RRD7M3.js +38 -0
- package/dist/bid-pricing-5KUAINH4.js +103 -0
- package/dist/brand-KFK2MQWW.js +22 -0
- package/dist/brief-6DV2PKAU.js +543 -0
- package/dist/campaign-groups-5RPZPDNW.js +99 -0
- package/dist/campaign-writes-FUIGN5OR.js +176 -0
- package/dist/campaign-writes-XMYBEVZF.js +168 -0
- package/dist/campaigns-5A3IE735.js +111 -0
- package/dist/campaigns-JNP3VDZK.js +113 -0
- package/dist/campaigns-N2SWSBYT.js +78 -0
- package/dist/canvas-CHFNQTLY.js +46 -0
- package/dist/capabilities-2W3SRZ2I.js +147 -0
- package/dist/catalog-6BER3SF7.js +66 -0
- package/dist/catalogs-G5NOKL4L.js +130 -0
- package/dist/changes-AS4RVEAL.js +167 -0
- package/dist/chatgpt-O6EEAYLF.js +47 -0
- package/dist/chats-4JLWMUAC.js +584 -0
- package/dist/check-BOKLY5WG.js +107 -0
- package/dist/chunk-3KUNRKNV.js +430 -0
- package/dist/chunk-3UNMVVSI.js +917 -0
- package/dist/chunk-3UNMVVSI.js.map +1 -0
- package/dist/chunk-4INBMXUS.js +930 -0
- package/dist/chunk-5NMKNHJI.js +46 -0
- package/dist/chunk-6D7WTUF3.js +98 -0
- package/dist/chunk-6DSPB6YA.js +7904 -0
- package/dist/chunk-6DSPB6YA.js.map +1 -0
- package/dist/chunk-6FQ7CJEX.js +57 -0
- package/dist/chunk-6OIKNJ7G.js +26 -0
- package/dist/chunk-6OZDN2FI.js +19 -0
- package/dist/chunk-75OGTGC4.js +89 -0
- package/dist/chunk-AXLKR3E4.js +66 -0
- package/dist/chunk-BEZEZHQ6.js +455 -0
- package/dist/chunk-BMK4F4CU.js +169 -0
- package/dist/chunk-C52Q3L4C.js +51 -0
- package/dist/chunk-CST52ZME.js +142 -0
- package/dist/chunk-CUTTTFAU.js +783 -0
- package/dist/chunk-D32EWSMB.js +150 -0
- package/dist/chunk-DW3H2XQA.js +91 -0
- package/dist/chunk-EAA273XW.js +2250 -0
- package/dist/chunk-EAA273XW.js.map +1 -0
- package/dist/chunk-EM5R3BYC.js +131 -0
- package/dist/chunk-EMR5KGNY.js +685 -0
- package/dist/chunk-EONUZOJV.js +962 -0
- package/dist/chunk-F3CZFUXZ.js +3187 -0
- package/dist/chunk-F3CZFUXZ.js.map +1 -0
- package/dist/chunk-GRX3JXSR.js +843 -0
- package/dist/chunk-H4RHZJ65.js +207 -0
- package/dist/chunk-HFIHXIYY.js +547 -0
- package/dist/chunk-HOA74TOS.js +249 -0
- package/dist/chunk-HQDNDKNR.js +5471 -0
- package/dist/chunk-HXSYWXLH.js +709 -0
- package/dist/chunk-I3QLWGKS.js +64 -0
- package/dist/chunk-IMS53EQU.js +4277 -0
- package/dist/chunk-IMS53EQU.js.map +1 -0
- package/dist/chunk-J4AWNWKN.js +1919 -0
- package/dist/chunk-JAK5VDSG.js +103 -0
- package/dist/chunk-JGSEHX2Q.js +3107 -0
- package/dist/chunk-JGSEHX2Q.js.map +1 -0
- package/dist/chunk-JLAFNORO.js +285 -0
- package/dist/chunk-KG5VNPKU.js +91 -0
- package/dist/chunk-KJHG2DWS.js +170 -0
- package/dist/chunk-LAMSUL26.js +1518 -0
- package/dist/chunk-LLTHDEM2.js +479 -0
- package/dist/chunk-M5PZ6QQB.js +312 -0
- package/dist/chunk-MFGUR5OD.js +334 -0
- package/dist/chunk-MZLPOYCC.js +10058 -0
- package/dist/chunk-MZLPOYCC.js.map +1 -0
- package/dist/chunk-NOCBNING.js +638 -0
- package/dist/chunk-NWLK5RPA.js +197 -0
- package/dist/chunk-PR5OPERY.js +167 -0
- package/dist/chunk-QGAUDVMR.js +148 -0
- package/dist/chunk-QRRAMUKV.js +468 -0
- package/dist/chunk-QZ4YHQLW.js +63 -0
- package/dist/chunk-RGLTITIH.js +494 -0
- package/dist/chunk-RIVQ4PQQ.js +225 -0
- package/dist/chunk-RLLPY62L.js +163 -0
- package/dist/chunk-RQHXWPET.js +61 -0
- package/dist/chunk-RULW4627.js +23 -0
- package/dist/chunk-S4RCF3YT.js +156 -0
- package/dist/chunk-SIKCVWM3.js +76 -0
- package/dist/chunk-TCLJRWST.js +831 -0
- package/dist/chunk-UVUY6FLV.js +1254 -0
- package/dist/chunk-V4HS5JRL.js +1320 -0
- package/dist/chunk-WTOBG3YL.js +392 -0
- package/dist/chunk-WYMX3F47.js +399 -0
- package/dist/chunk-WZXMZFVB.js +238 -0
- package/dist/chunk-X5YHMGAT.js +224 -0
- package/dist/chunk-X7USE7IA.js +24026 -0
- package/dist/chunk-X7USE7IA.js.map +1 -0
- package/dist/chunk-XA7JN7YE.js +297 -0
- package/dist/chunk-XHAGX4J4.js +604 -0
- package/dist/chunk-XY7W6MQN.js +274 -0
- package/dist/chunk-YAINUFSC.js +203 -0
- package/dist/chunk-Z5BG47PO.js +5752 -0
- package/dist/chunk-Z5BG47PO.js.map +1 -0
- package/dist/chunk-Z7ICQKC2.js +344 -0
- package/dist/chunk-ZBXV2KOQ.js +220 -0
- package/dist/chunk-ZMNRSTNV.js +454 -0
- package/dist/claim-L4WLCVUL.js +200 -0
- package/dist/cli.js +32 -32
- package/dist/companies-HW46BRQG.js +198 -0
- package/dist/company-KCIDE7SL.js +308 -0
- package/dist/complete-JXM25FVW.js +84 -0
- package/dist/connect-7TX7AAM5.js +45 -0
- package/dist/conversation-YIDUB6GL.js +96 -0
- package/dist/conversion-report-33SG7SHU.js +127 -0
- package/dist/conversion-upload-command-N3OMLLF2.js +439 -0
- package/dist/conversion-writes-XGGTBML5.js +122 -0
- package/dist/conversions-F4OZYUCT.js +140 -0
- package/dist/conversions-PPP4QK7U.js +78 -0
- package/dist/create-6EAKNERA.js +239 -0
- package/dist/create-772LZHZR.js +218 -0
- package/dist/create-FDNMIVFX.js +62 -0
- package/dist/create-X2QM7GA7.js +135 -0
- package/dist/creatives-K2AAW6EL.js +58 -0
- package/dist/creatives-SNYN4KIM.js +229 -0
- package/dist/credentials-KZZVBO42.js +290 -0
- package/dist/critique-G5QXRHPF.js +1451 -0
- package/dist/critique-PUHOJI7V.js +232 -0
- package/dist/crm-4LZZVT4N.js +229 -0
- package/dist/crm-M6NXDU5B.js +323 -0
- package/dist/currency-HK2ZW2VW.js +88 -0
- package/dist/customers-V5NT4W7X.js +65 -0
- package/dist/delete-GQIKNO53.js +57 -0
- package/dist/delete-LFZIPQEO.js +69 -0
- package/dist/delete-YOEI63OT.js +67 -0
- package/dist/demographics-CEQ74O74.js +141 -0
- package/dist/discard-5GDF3TP3.js +69 -0
- package/dist/discover-Q5PAOIQQ.js +172 -0
- package/dist/domain-PKOUPHHF.js +101 -0
- package/dist/download-2WNTN7JQ.js +172 -0
- package/dist/draft-CF4XNJG5.js +578 -0
- package/dist/draft-F4CVSL2I.js +332 -0
- package/dist/draft-L2NXCIYT.js +315 -0
- package/dist/draft-RZCTAOI2.js +374 -0
- package/dist/draft-UEVBUNKV.js +220 -0
- package/dist/engine/index.js +8 -8
- package/dist/experiments-DWC6L72S.js +236 -0
- package/dist/extract-6HJXSOZW.js +143 -0
- package/dist/facets-TBOXGYJT.js +117 -0
- package/dist/feedback-MSMFYAEY.js +114 -0
- package/dist/feedback-WAC6S42V.js +115 -0
- package/dist/feedback-record-XRQ2R2WD.js +269 -0
- package/dist/fetch-LGX7B3IC.js +204 -0
- package/dist/fit-RVWPRBNO.js +65 -0
- package/dist/flows-LA6EYMLS.js +340 -0
- package/dist/fonts-WRC34VSV.js +39 -0
- package/dist/forecast-6VHRGBJG.js +121 -0
- package/dist/forecast-OVKXBLJB.js +169 -0
- package/dist/funnel-U3GQIGND.js +397 -0
- package/dist/generate-Y4NJEYIH.js +263 -0
- package/dist/get-AHI247JG.js +82 -0
- package/dist/get-PF3HGECD.js +62 -0
- package/dist/google-BMUJKAUO.js +3300 -0
- package/dist/google-ZVAIFXQZ.js +163 -0
- package/dist/google-ads-6Z7P3SCD.js +198 -0
- package/dist/history-4QUV45ZJ.js +102 -0
- package/dist/history-PD7FCTDD.js +153 -0
- package/dist/history-VKRYKQ4C.js +69 -0
- package/dist/hubspot-WEFAFKVJ.js +814 -0
- package/dist/ideas-SMSEXKIA.js +45 -0
- package/dist/images-KAT4BPYV.js +92 -0
- package/dist/ingest-IHKTSJ4H.js +28 -0
- package/dist/ingest-TOHQ6MZA.js +131 -0
- package/dist/insights-3IPSEBYW.js +132 -0
- package/dist/inspect-5MZBPDYS.js +192 -0
- package/dist/intent-ZM4K623V.js +95 -0
- package/dist/keyword-gap-FAAF2I6V.js +130 -0
- package/dist/keyword-metrics-EXNJRJBY.js +200 -0
- package/dist/keywords-for-site-5LW77QWF.js +131 -0
- package/dist/landing-ZH4SD3DW.js +28 -0
- package/dist/languages-ZGDTERIQ.js +40 -0
- package/dist/leads-736RILZN.js +115 -0
- package/dist/learn-BESXWXEN.js +207 -0
- package/dist/line-item-writes-FA72DHNQ.js +211 -0
- package/dist/line-items-XVYE3IYT.js +107 -0
- package/dist/link-6FPKFVC3.js +67 -0
- package/dist/linkedin-TE6P4RYN.js +1344 -0
- package/dist/linkedin-person-TZJ6VEXE.js +139 -0
- package/dist/list-4R5EMKUQ.js +154 -0
- package/dist/list-MN2FPF3T.js +306 -0
- package/dist/list-ORO4WDF4.js +67 -0
- package/dist/locations-A65MFB7Q.js +69 -0
- package/dist/locations-WN6B3IJK.js +40 -0
- package/dist/log-ABBZLPRU.js +95 -0
- package/dist/make-QAFKU6WO.js +1367 -0
- package/dist/map-52P35OKE.js +445 -0
- package/dist/mcp-PZ3VBIF4.js +729 -0
- package/dist/media-sources-TT374PLN.js +35 -0
- package/dist/members-CF6VG6ZW.js +47 -0
- package/dist/metrics-3U3ZO2RF.js +152 -0
- package/dist/models-VOSJJFO2.js +155 -0
- package/dist/normalize-4LZCLMTQ.js +144 -0
- package/dist/options-6IRL7CL6.js +125 -0
- package/dist/organization-WMLLJE66.js +949 -0
- package/dist/performance-A7CYFBW2.js +5565 -0
- package/dist/performance-HYSTXLTS.js +27 -0
- package/dist/pixels-U6UA662G.js +62 -0
- package/dist/preview-76ZP2QA3.js +101 -0
- package/dist/promoted-tweet-writes-I5G4IDL5.js +183 -0
- package/dist/promoted-tweets-X5XNO7IT.js +119 -0
- package/dist/publish-S2Z4EF4H.js +350 -0
- package/dist/query-SAQADBM2.js +62 -0
- package/dist/reddit-S2L5WDY7.js +29 -0
- package/dist/refresh-K2YTJSH3.js +97 -0
- package/dist/release-FX76IIVN.js +63 -0
- package/dist/relevant-pages-KTSODNNW.js +99 -0
- package/dist/remove-LOVWPLDO.js +53 -0
- package/dist/reopen-DXV2Y6Z3.js +66 -0
- package/dist/rerun-TFQCRRFK.js +97 -0
- package/dist/research-7PGDAKC7.js +265 -0
- package/dist/research-HY5PSUCC.js +75 -0
- package/dist/reset-MEHUQJA4.js +57 -0
- package/dist/reset-Y5VZJRDQ.js +57 -0
- package/dist/resolve-FAVABEJW.js +124 -0
- package/dist/retry-5IY4MNDW.js +65 -0
- package/dist/retry-OMJ3C3AX.js +63 -0
- package/dist/revenue-S4KFZCOI.js +91 -0
- package/dist/rules-66IGR2KA.js +99 -0
- package/dist/rules-add-G7YGOYZJ.js +465 -0
- package/dist/run-LJVBH3JS.js +72 -0
- package/dist/run-XJBWDWN6.js +69 -0
- package/dist/scaffold-ad-GNMCB3QY.js +1513 -0
- package/dist/scaffold-static-ad-QIWKWURL.js +1013 -0
- package/dist/scaffold-static-ad-QIWKWURL.js.map +1 -0
- package/dist/scaffold-video-G6G2NPUF.js +885 -0
- package/dist/schedule-OX5XHXLH.js +64 -0
- package/dist/scheduled-agents-A5ZFQB5X.js +55 -0
- package/dist/schema-NTGHAPR2.js +135 -0
- package/dist/search-WCXQBMMM.js +177 -0
- package/dist/select-5ZD7FVBT.js +110 -0
- package/dist/set-prompt-NGCVMQIQ.js +199 -0
- package/dist/setup-links-4HCSF55G.js +144 -0
- package/dist/shopify-GDR5WGHH.js +4009 -0
- package/dist/site-B7LT6KAO.js +180 -0
- package/dist/sources-6DPUEROC.js +30 -0
- package/dist/sources-OSUXCLID.js +457 -0
- package/dist/stale-YKFKPPOH.js +90 -0
- package/dist/status-KIC3P5JV.js +65 -0
- package/dist/stock-VWFUFRYV.js +212 -0
- package/dist/studio-XLC37YGX.js +49 -0
- package/dist/sync-QBW4XH2H.js +57 -0
- package/dist/sync-definition-4KMJK46H.js +70 -0
- package/dist/tags-4F5UBPYG.js +227 -0
- package/dist/tags-4O5FPEEY.js +26 -0
- package/dist/tags-7RKKCQ4X.js +23 -0
- package/dist/tags-CB4MWI3A.js +23 -0
- package/dist/tags-QZJIP4LJ.js +23 -0
- package/dist/targeting-criteria-65UU7EYD.js +113 -0
- package/dist/targets-T742OPQI.js +106 -0
- package/dist/testimonials-HKJJXONO.js +32 -0
- package/dist/themes-Q6LVMEMF.js +95 -0
- package/dist/top-companies-T6AMU4C6.js +111 -0
- package/dist/transcript-DOUYMZAP.js +165 -0
- package/dist/translate-WKOXFZTQ.js +603 -0
- package/dist/triggers-EYY4GSUL.js +144 -0
- package/dist/unlink-JNM4WRZK.js +70 -0
- package/dist/unstage-QF4JT5YP.js +88 -0
- package/dist/update-6V3RBRIE.js +101 -0
- package/dist/update-J4DURR4K.js +192 -0
- package/dist/update-J7Y6LZC5.js +155 -0
- package/dist/update-MQ4NYIU6.js +66 -0
- package/dist/upload-CEIYYPID.js +137 -0
- package/dist/url-options-6WC2XQKB.js +131 -0
- package/dist/url-params-OVBIP6UA.js +101 -0
- package/dist/validate-UHXI2ESE.js +135 -0
- package/dist/videos-Z72RXCRB.js +41 -0
- package/dist/viewer-check-655BZRML.js +83 -0
- package/dist/web-4QN6QB7L.js +173 -0
- package/dist/winning-ads-2J2RIOLR.js +86 -0
- package/dist/write-commands-V7B4FBMX.js +1524 -0
- package/dist/x-7KXNCWTJ.js +47 -0
- package/package.json +1 -1
- package/dist/account-52WDLW4Z.js +0 -82
- package/dist/account-7KZ7MHMN.js +0 -82
- package/dist/account-reads-RXF37O4N.js +0 -219
- package/dist/account-users-NUI3ILRE.js +0 -64
- package/dist/account-writes-3BJSUM2V.js +0 -68
- package/dist/accounts-FLKNFDIE.js +0 -713
- package/dist/accounts-I2ZLR76R.js +0 -80
- package/dist/accounts-ZV4IXOF5.js +0 -119
- package/dist/actions-IR47GVZ6.js +0 -55
- package/dist/activecampaign-MNJYIWJL.js +0 -938
- package/dist/ad-group-writes-KU4QMQZP.js +0 -172
- package/dist/ad-groups-NMW2G32A.js +0 -70
- package/dist/ad-writes-7NOFTOM4.js +0 -176
- package/dist/add-4I25INAO.js +0 -107
- package/dist/add-QMTD6EGI.js +0 -305
- package/dist/ads-BT2DF3XN.js +0 -48
- package/dist/ads-P4Z3MLKS.js +0 -79
- package/dist/advertisers-LOIXTTGP.js +0 -123
- package/dist/analytics-6AHC3J4L.js +0 -447
- package/dist/analytics-NL2KGDLK.js +0 -2437
- package/dist/animate-VX7E7KJE.js +0 -480
- package/dist/assign-NKHIHVGI.js +0 -80
- package/dist/audience-size-WEOM6XIL.js +0 -76
- package/dist/audiences-P3SPTAJT.js +0 -280
- package/dist/audit-4RIBJ7BR.js +0 -154
- package/dist/autocomplete-FMTJDXTL.js +0 -114
- package/dist/avatars-LY5SFMWO.js +0 -38
- package/dist/bid-pricing-MQ7WLV5U.js +0 -103
- package/dist/brand-LR5IXW3W.js +0 -22
- package/dist/brief-4DSXIX3F.js +0 -543
- package/dist/campaign-groups-EZYLKMO2.js +0 -99
- package/dist/campaign-writes-P5XPFTRK.js +0 -176
- package/dist/campaign-writes-UMENYMKO.js +0 -168
- package/dist/campaigns-PP2DQMJE.js +0 -113
- package/dist/campaigns-SWZJVE2T.js +0 -78
- package/dist/campaigns-TAFDM242.js +0 -111
- package/dist/canvas-RKR3ZB4E.js +0 -46
- package/dist/capabilities-45RZ6E6W.js +0 -147
- package/dist/catalog-TOHUVBEU.js +0 -66
- package/dist/catalogs-V7PTEJBO.js +0 -130
- package/dist/changes-5OW3UYMF.js +0 -167
- package/dist/chatgpt-JBMYNVJB.js +0 -47
- package/dist/chats-VOLBYA3R.js +0 -584
- package/dist/check-4DI73QX4.js +0 -107
- package/dist/chunk-22RM3UOO.js +0 -63
- package/dist/chunk-2N7TB346.js +0 -5368
- package/dist/chunk-2N7TB346.js.map +0 -1
- package/dist/chunk-2Q7K4F4H.js +0 -7899
- package/dist/chunk-2Q7K4F4H.js.map +0 -1
- package/dist/chunk-2TS2ITSG.js +0 -392
- package/dist/chunk-2YXTXSYG.js +0 -454
- package/dist/chunk-2Z6PFHD2.js +0 -91
- package/dist/chunk-47VWQ7FQ.js +0 -843
- package/dist/chunk-4QFMRL6O.js +0 -455
- package/dist/chunk-5OC6VUDZ.js +0 -930
- package/dist/chunk-5VXEH72O.js +0 -249
- package/dist/chunk-B4BITHOD.js +0 -2235
- package/dist/chunk-B4BITHOD.js.map +0 -1
- package/dist/chunk-BFAPSFS7.js +0 -1518
- package/dist/chunk-BMMXYR7A.js +0 -238
- package/dist/chunk-BNEWJXKU.js +0 -638
- package/dist/chunk-BXTIG5JL.js +0 -66
- package/dist/chunk-C7KV5O5J.js +0 -274
- package/dist/chunk-CDPX6WAL.js +0 -207
- package/dist/chunk-COOJKEJE.js +0 -312
- package/dist/chunk-CTJWMZPL.js +0 -430
- package/dist/chunk-D5HD46VV.js +0 -163
- package/dist/chunk-EGICPBDY.js +0 -1920
- package/dist/chunk-EGICPBDY.js.map +0 -1
- package/dist/chunk-EKOMZH2S.js +0 -685
- package/dist/chunk-ELC42LJJ.js +0 -8954
- package/dist/chunk-ELC42LJJ.js.map +0 -1
- package/dist/chunk-G4FU6VC5.js +0 -23
- package/dist/chunk-H3RCEM6L.js +0 -61
- package/dist/chunk-H7LKYGLJ.js +0 -24026
- package/dist/chunk-H7LKYGLJ.js.map +0 -1
- package/dist/chunk-HI4SKWNW.js +0 -709
- package/dist/chunk-HM4NWA72.js +0 -5471
- package/dist/chunk-I33FO2ON.js +0 -170
- package/dist/chunk-IAE24RKD.js +0 -604
- package/dist/chunk-IGCS3X4F.js +0 -150
- package/dist/chunk-IJ6WA2JW.js +0 -148
- package/dist/chunk-ITIUWJGQ.js +0 -131
- package/dist/chunk-J4BJLHLQ.js +0 -3510
- package/dist/chunk-J4BJLHLQ.js.map +0 -1
- package/dist/chunk-JAC6JVCI.js +0 -26
- package/dist/chunk-JCDCIQMA.js +0 -479
- package/dist/chunk-JGK2FDZW.js +0 -1919
- package/dist/chunk-JSOOLOHP.js +0 -468
- package/dist/chunk-JT3UUBID.js +0 -142
- package/dist/chunk-KUI74TNG.js +0 -169
- package/dist/chunk-LAOCXV6Z.js +0 -98
- package/dist/chunk-LQACNCAV.js +0 -334
- package/dist/chunk-MC5F2L64.js +0 -962
- package/dist/chunk-MCJ5I5LR.js +0 -3187
- package/dist/chunk-MCJ5I5LR.js.map +0 -1
- package/dist/chunk-MKG57P2E.js +0 -783
- package/dist/chunk-MZPS46OR.js +0 -76
- package/dist/chunk-O2ECZKXP.js +0 -197
- package/dist/chunk-OJZKY5UM.js +0 -46
- package/dist/chunk-P4UCSXNA.js +0 -156
- package/dist/chunk-QLO4RNHU.js +0 -51
- package/dist/chunk-QSS34JWZ.js +0 -224
- package/dist/chunk-QVHZTCB5.js +0 -1254
- package/dist/chunk-RVIBHENP.js +0 -344
- package/dist/chunk-TEJOILEY.js +0 -203
- package/dist/chunk-TEQEZAJI.js +0 -1320
- package/dist/chunk-TNI7CN4L.js +0 -547
- package/dist/chunk-TPJ34LXX.js +0 -220
- package/dist/chunk-U6AWJIFP.js +0 -225
- package/dist/chunk-V5ODOBBI.js +0 -399
- package/dist/chunk-VAURJ4QJ.js +0 -89
- package/dist/chunk-VAV5CCDD.js +0 -167
- package/dist/chunk-VWHUO3AP.js +0 -103
- package/dist/chunk-W3TZPHZO.js +0 -285
- package/dist/chunk-WZATC4O5.js +0 -297
- package/dist/chunk-X25XRSDP.js +0 -57
- package/dist/chunk-XGG72YRO.js +0 -91
- package/dist/chunk-XHWHBGKX.js +0 -4277
- package/dist/chunk-XHWHBGKX.js.map +0 -1
- package/dist/chunk-XWAOECD2.js +0 -831
- package/dist/chunk-YDALLZNS.js +0 -494
- package/dist/chunk-Z3RGBLVJ.js +0 -64
- package/dist/chunk-Z5JWFNG4.js +0 -19
- package/dist/claim-3UMAFZEM.js +0 -200
- package/dist/companies-RL5A26AT.js +0 -198
- package/dist/company-DJ44F5C6.js +0 -308
- package/dist/complete-PGNIP3LN.js +0 -84
- package/dist/connect-ROARWN63.js +0 -45
- package/dist/conversation-GDFMJL7X.js +0 -96
- package/dist/conversion-report-2FREFML5.js +0 -127
- package/dist/conversion-upload-command-G7LLWHSK.js +0 -439
- package/dist/conversion-writes-JZIJSQ7T.js +0 -122
- package/dist/conversions-2IFWDQKK.js +0 -140
- package/dist/conversions-Q5EBTEXA.js +0 -78
- package/dist/create-B5DIYK5D.js +0 -218
- package/dist/create-BRCSXXFO.js +0 -239
- package/dist/create-PXAUL6FF.js +0 -62
- package/dist/create-R6CMATVY.js +0 -135
- package/dist/creatives-D6O6Z46U.js +0 -229
- package/dist/creatives-XNVWQWFF.js +0 -58
- package/dist/credentials-CLJO7WWY.js +0 -290
- package/dist/critique-MBMKW6SL.js +0 -1451
- package/dist/critique-OUJDTVMI.js +0 -232
- package/dist/crm-H5ITJ2RC.js +0 -229
- package/dist/crm-JJHYRABB.js +0 -323
- package/dist/currency-EFDQYW5B.js +0 -88
- package/dist/customers-C5YXAVXI.js +0 -65
- package/dist/delete-3GYCQK6B.js +0 -57
- package/dist/delete-NBUDIGSD.js +0 -69
- package/dist/delete-WZ3KVVX5.js +0 -67
- package/dist/demographics-O7AJW7DO.js +0 -141
- package/dist/discard-RMVZAX2J.js +0 -69
- package/dist/discover-BPUUWRBP.js +0 -172
- package/dist/domain-J3ZMBOHS.js +0 -101
- package/dist/download-ZVOGLTFB.js +0 -172
- package/dist/draft-6PJD3MCW.js +0 -374
- package/dist/draft-GCOCG4PO.js +0 -315
- package/dist/draft-Q4PEFBJB.js +0 -578
- package/dist/draft-TPR3DH5N.js +0 -220
- package/dist/draft-ZPGGWU7E.js +0 -332
- package/dist/experiments-MM4BYHRH.js +0 -236
- package/dist/extract-JMY6YRPW.js +0 -143
- package/dist/facets-B5AZAU2C.js +0 -117
- package/dist/feedback-2EVDGTEN.js +0 -115
- package/dist/feedback-4MCMOMVN.js +0 -114
- package/dist/feedback-record-DL7UEU2H.js +0 -269
- package/dist/fetch-JDNFK476.js +0 -204
- package/dist/fit-DKVH5BDW.js +0 -65
- package/dist/flows-LURTZICL.js +0 -340
- package/dist/fonts-HUXFDDAE.js +0 -39
- package/dist/forecast-ITLKAFHM.js +0 -169
- package/dist/forecast-UHTW4Y7Q.js +0 -121
- package/dist/funnel-QM7WFFMD.js +0 -397
- package/dist/generate-KAWRRYTT.js +0 -263
- package/dist/get-237TYJZT.js +0 -82
- package/dist/get-FWPR2YPC.js +0 -62
- package/dist/google-DTSLO3PT.js +0 -163
- package/dist/google-JY7KDAFC.js +0 -3300
- package/dist/google-ads-RZOQQDQN.js +0 -198
- package/dist/history-H7S7XRBX.js +0 -153
- package/dist/history-XL52537O.js +0 -102
- package/dist/history-YQSYXBJH.js +0 -69
- package/dist/hubspot-2DSISSUI.js +0 -814
- package/dist/ideas-2XBFQJ56.js +0 -45
- package/dist/images-VFRQ32G5.js +0 -92
- package/dist/ingest-4RPLN54K.js +0 -28
- package/dist/ingest-TPVH44VI.js +0 -131
- package/dist/insights-UVCFOB3N.js +0 -132
- package/dist/inspect-VD3GVXDU.js +0 -192
- package/dist/intent-F5NTOSQC.js +0 -95
- package/dist/keyword-gap-EB5QATYN.js +0 -130
- package/dist/keyword-metrics-PW2DDIJW.js +0 -200
- package/dist/keywords-for-site-JEPABY6E.js +0 -131
- package/dist/landing-4N6YSB4L.js +0 -28
- package/dist/languages-4S26FJDP.js +0 -40
- package/dist/leads-R5OZJQHW.js +0 -115
- package/dist/learn-AQ2FRFB7.js +0 -207
- package/dist/line-item-writes-LGO7HIJJ.js +0 -211
- package/dist/line-items-AAZVKQ7E.js +0 -107
- package/dist/link-7IGHVARH.js +0 -67
- package/dist/linkedin-UB2CW4KP.js +0 -1344
- package/dist/linkedin-person-D6U2ZAUW.js +0 -139
- package/dist/list-P44QRX2O.js +0 -154
- package/dist/list-UMJACDTQ.js +0 -67
- package/dist/list-VZKUHY4Y.js +0 -306
- package/dist/locations-UWBQLHXW.js +0 -40
- package/dist/locations-WXGOI3VV.js +0 -69
- package/dist/log-6ZKMUTYS.js +0 -95
- package/dist/make-5CEIJRBC.js +0 -1367
- package/dist/map-ZL4MQVJZ.js +0 -445
- package/dist/mcp-GSRYLRD4.js +0 -729
- package/dist/media-sources-VSPVHLYN.js +0 -35
- package/dist/members-L6SXP6GC.js +0 -47
- package/dist/metrics-4AFEEDVP.js +0 -152
- package/dist/models-2ZEM64H5.js +0 -155
- package/dist/normalize-GK7DH7ZP.js +0 -144
- package/dist/options-FDAAHG7C.js +0 -125
- package/dist/organization-K2FTFAAO.js +0 -949
- package/dist/performance-N3UROH7Z.js +0 -5565
- package/dist/performance-RG2HR46T.js +0 -27
- package/dist/pixels-HEI5WVAO.js +0 -62
- package/dist/preview-NVWIEUHF.js +0 -101
- package/dist/promoted-tweet-writes-7QZRFDOM.js +0 -183
- package/dist/promoted-tweets-V555Y7DN.js +0 -119
- package/dist/publish-5KR6YLA6.js +0 -350
- package/dist/query-K7MYBRTS.js +0 -62
- package/dist/reddit-XPQ7YAJW.js +0 -29
- package/dist/refresh-XFHEBSDU.js +0 -97
- package/dist/release-3ECEF26P.js +0 -63
- package/dist/relevant-pages-XYQKVX3U.js +0 -99
- package/dist/remove-OCTUC3RB.js +0 -53
- package/dist/reopen-JRI3TYD4.js +0 -66
- package/dist/rerun-HWWYCDT2.js +0 -97
- package/dist/research-ODPU62BA.js +0 -265
- package/dist/research-TG5CBTYP.js +0 -75
- package/dist/reset-J2NLNITD.js +0 -57
- package/dist/reset-SRU7YJUR.js +0 -57
- package/dist/resolve-KHMMUGB2.js +0 -124
- package/dist/retry-VLH4AO7F.js +0 -65
- package/dist/retry-WP7LWKZF.js +0 -63
- package/dist/revenue-EEIS2AV5.js +0 -91
- package/dist/rules-TTUGQAEB.js +0 -99
- package/dist/rules-add-AIXUAZXG.js +0 -465
- package/dist/run-AQTACLY6.js +0 -69
- package/dist/run-YA6IWQAJ.js +0 -72
- package/dist/scaffold-ad-IYNFJPT7.js +0 -1513
- package/dist/scaffold-static-ad-SPYKSAJR.js +0 -1012
- package/dist/scaffold-static-ad-SPYKSAJR.js.map +0 -1
- package/dist/scaffold-video-BUN27PKS.js +0 -885
- package/dist/schedule-EH2MOC5C.js +0 -64
- package/dist/scheduled-agents-DTAEP25E.js +0 -55
- package/dist/schema-7B4MVVAS.js +0 -135
- package/dist/search-ZZWIJRXJ.js +0 -177
- package/dist/select-LWZRF7KV.js +0 -110
- package/dist/set-prompt-YKDH6FYK.js +0 -199
- package/dist/setup-links-OE6PC2YQ.js +0 -144
- package/dist/shopify-CCPLZI2H.js +0 -4009
- package/dist/site-FW5BBLYG.js +0 -180
- package/dist/sources-WPHMWBEK.js +0 -30
- package/dist/sources-X77TGJ52.js +0 -457
- package/dist/stale-SPCDL73V.js +0 -90
- package/dist/status-FLETGJ2A.js +0 -65
- package/dist/stock-5AOSQH52.js +0 -212
- package/dist/studio-4EV5S7PR.js +0 -49
- package/dist/sync-363VKXU3.js +0 -57
- package/dist/sync-definition-ZDE5L644.js +0 -70
- package/dist/tags-6MN3AWKN.js +0 -23
- package/dist/tags-VOKUNEIW.js +0 -227
- package/dist/tags-Y6MNMIEA.js +0 -23
- package/dist/tags-YHAC3NVY.js +0 -23
- package/dist/tags-ZCQMJ5YH.js +0 -26
- package/dist/targeting-criteria-ECQFHQF3.js +0 -113
- package/dist/targets-U2JHTB5U.js +0 -106
- package/dist/testimonials-IDVLMXDT.js +0 -32
- package/dist/themes-QMR5TWTI.js +0 -95
- package/dist/top-companies-CBI4O3ZB.js +0 -111
- package/dist/transcript-IIRFTFRW.js +0 -165
- package/dist/translate-N6QW4FZB.js +0 -603
- package/dist/triggers-Q3KRAMA3.js +0 -144
- package/dist/unlink-7RVQXKAR.js +0 -70
- package/dist/unstage-3LPHNZKR.js +0 -88
- package/dist/update-AL3LBHGK.js +0 -192
- package/dist/update-AWR7EHGA.js +0 -155
- package/dist/update-LNSSLZXG.js +0 -66
- package/dist/update-YBTFH5MN.js +0 -101
- package/dist/upload-45GCGMA5.js +0 -137
- package/dist/url-options-AHJPR5VY.js +0 -131
- package/dist/url-params-U6ZM4LL2.js +0 -101
- package/dist/validate-S325RXPH.js +0 -135
- package/dist/videos-NW2UP342.js +0 -41
- package/dist/viewer-check-IDXFRRCO.js +0 -83
- package/dist/web-VMPKMBKA.js +0 -173
- package/dist/winning-ads-7UJXCWFH.js +0 -86
- package/dist/write-commands-R42DQEW6.js +0 -1524
- package/dist/x-UGTUOCVR.js +0 -47
- /package/dist/{account-7KZ7MHMN.js.map → account-EXGRZIXS.js.map} +0 -0
- /package/dist/{account-52WDLW4Z.js.map → account-JVDP5ERG.js.map} +0 -0
- /package/dist/{account-reads-RXF37O4N.js.map → account-reads-Z467VAL4.js.map} +0 -0
- /package/dist/{account-users-NUI3ILRE.js.map → account-users-342OZALE.js.map} +0 -0
- /package/dist/{account-writes-3BJSUM2V.js.map → account-writes-KEXINJ5D.js.map} +0 -0
- /package/dist/{accounts-FLKNFDIE.js.map → accounts-QESGQJGZ.js.map} +0 -0
- /package/dist/{accounts-ZV4IXOF5.js.map → accounts-QR6OQ3GC.js.map} +0 -0
- /package/dist/{accounts-I2ZLR76R.js.map → accounts-UWC2TT6R.js.map} +0 -0
- /package/dist/{actions-IR47GVZ6.js.map → actions-NT3HXFFA.js.map} +0 -0
- /package/dist/{activecampaign-MNJYIWJL.js.map → activecampaign-EYRHDSXY.js.map} +0 -0
- /package/dist/{ad-group-writes-KU4QMQZP.js.map → ad-group-writes-SVR4RCKB.js.map} +0 -0
- /package/dist/{ad-groups-NMW2G32A.js.map → ad-groups-C726HUXS.js.map} +0 -0
- /package/dist/{ad-writes-7NOFTOM4.js.map → ad-writes-RWJIWGEL.js.map} +0 -0
- /package/dist/{add-QMTD6EGI.js.map → add-EPOHDTUO.js.map} +0 -0
- /package/dist/{add-4I25INAO.js.map → add-NSW26HIM.js.map} +0 -0
- /package/dist/{ads-P4Z3MLKS.js.map → ads-3KK7VQPU.js.map} +0 -0
- /package/dist/{ads-BT2DF3XN.js.map → ads-EWZGIC4T.js.map} +0 -0
- /package/dist/{advertisers-LOIXTTGP.js.map → advertisers-AHOWL3YL.js.map} +0 -0
- /package/dist/{analytics-6AHC3J4L.js.map → analytics-7H6NDVUQ.js.map} +0 -0
- /package/dist/{analytics-NL2KGDLK.js.map → analytics-GFFXCMLV.js.map} +0 -0
- /package/dist/{animate-VX7E7KJE.js.map → animate-GTUI7XX4.js.map} +0 -0
- /package/dist/{assign-NKHIHVGI.js.map → assign-SDPPWP3Q.js.map} +0 -0
- /package/dist/{audience-size-WEOM6XIL.js.map → audience-size-LKDDHKED.js.map} +0 -0
- /package/dist/{audiences-P3SPTAJT.js.map → audiences-6L43K2T2.js.map} +0 -0
- /package/dist/{audit-4RIBJ7BR.js.map → audit-TSZIQTUB.js.map} +0 -0
- /package/dist/{autocomplete-FMTJDXTL.js.map → autocomplete-5BSAOAMZ.js.map} +0 -0
- /package/dist/{avatars-LY5SFMWO.js.map → avatars-S6RRD7M3.js.map} +0 -0
- /package/dist/{bid-pricing-MQ7WLV5U.js.map → bid-pricing-5KUAINH4.js.map} +0 -0
- /package/dist/{brand-LR5IXW3W.js.map → brand-KFK2MQWW.js.map} +0 -0
- /package/dist/{brief-4DSXIX3F.js.map → brief-6DV2PKAU.js.map} +0 -0
- /package/dist/{campaign-groups-EZYLKMO2.js.map → campaign-groups-5RPZPDNW.js.map} +0 -0
- /package/dist/{campaign-writes-P5XPFTRK.js.map → campaign-writes-FUIGN5OR.js.map} +0 -0
- /package/dist/{campaign-writes-UMENYMKO.js.map → campaign-writes-XMYBEVZF.js.map} +0 -0
- /package/dist/{campaigns-TAFDM242.js.map → campaigns-5A3IE735.js.map} +0 -0
- /package/dist/{campaigns-PP2DQMJE.js.map → campaigns-JNP3VDZK.js.map} +0 -0
- /package/dist/{campaigns-SWZJVE2T.js.map → campaigns-N2SWSBYT.js.map} +0 -0
- /package/dist/{canvas-RKR3ZB4E.js.map → canvas-CHFNQTLY.js.map} +0 -0
- /package/dist/{capabilities-45RZ6E6W.js.map → capabilities-2W3SRZ2I.js.map} +0 -0
- /package/dist/{catalog-TOHUVBEU.js.map → catalog-6BER3SF7.js.map} +0 -0
- /package/dist/{catalogs-V7PTEJBO.js.map → catalogs-G5NOKL4L.js.map} +0 -0
- /package/dist/{changes-5OW3UYMF.js.map → changes-AS4RVEAL.js.map} +0 -0
- /package/dist/{chatgpt-JBMYNVJB.js.map → chatgpt-O6EEAYLF.js.map} +0 -0
- /package/dist/{chats-VOLBYA3R.js.map → chats-4JLWMUAC.js.map} +0 -0
- /package/dist/{check-4DI73QX4.js.map → check-BOKLY5WG.js.map} +0 -0
- /package/dist/{chunk-CTJWMZPL.js.map → chunk-3KUNRKNV.js.map} +0 -0
- /package/dist/{chunk-5OC6VUDZ.js.map → chunk-4INBMXUS.js.map} +0 -0
- /package/dist/{chunk-OJZKY5UM.js.map → chunk-5NMKNHJI.js.map} +0 -0
- /package/dist/{chunk-LAOCXV6Z.js.map → chunk-6D7WTUF3.js.map} +0 -0
- /package/dist/{chunk-X25XRSDP.js.map → chunk-6FQ7CJEX.js.map} +0 -0
- /package/dist/{chunk-JAC6JVCI.js.map → chunk-6OIKNJ7G.js.map} +0 -0
- /package/dist/{chunk-Z5JWFNG4.js.map → chunk-6OZDN2FI.js.map} +0 -0
- /package/dist/{chunk-VAURJ4QJ.js.map → chunk-75OGTGC4.js.map} +0 -0
- /package/dist/{chunk-BXTIG5JL.js.map → chunk-AXLKR3E4.js.map} +0 -0
- /package/dist/{chunk-4QFMRL6O.js.map → chunk-BEZEZHQ6.js.map} +0 -0
- /package/dist/{chunk-KUI74TNG.js.map → chunk-BMK4F4CU.js.map} +0 -0
- /package/dist/{chunk-QLO4RNHU.js.map → chunk-C52Q3L4C.js.map} +0 -0
- /package/dist/{chunk-JT3UUBID.js.map → chunk-CST52ZME.js.map} +0 -0
- /package/dist/{chunk-MKG57P2E.js.map → chunk-CUTTTFAU.js.map} +0 -0
- /package/dist/{chunk-IGCS3X4F.js.map → chunk-D32EWSMB.js.map} +0 -0
- /package/dist/{chunk-XGG72YRO.js.map → chunk-DW3H2XQA.js.map} +0 -0
- /package/dist/{chunk-ITIUWJGQ.js.map → chunk-EM5R3BYC.js.map} +0 -0
- /package/dist/{chunk-EKOMZH2S.js.map → chunk-EMR5KGNY.js.map} +0 -0
- /package/dist/{chunk-MC5F2L64.js.map → chunk-EONUZOJV.js.map} +0 -0
- /package/dist/{chunk-47VWQ7FQ.js.map → chunk-GRX3JXSR.js.map} +0 -0
- /package/dist/{chunk-CDPX6WAL.js.map → chunk-H4RHZJ65.js.map} +0 -0
- /package/dist/{chunk-TNI7CN4L.js.map → chunk-HFIHXIYY.js.map} +0 -0
- /package/dist/{chunk-5VXEH72O.js.map → chunk-HOA74TOS.js.map} +0 -0
- /package/dist/{chunk-HM4NWA72.js.map → chunk-HQDNDKNR.js.map} +0 -0
- /package/dist/{chunk-HI4SKWNW.js.map → chunk-HXSYWXLH.js.map} +0 -0
- /package/dist/{chunk-Z3RGBLVJ.js.map → chunk-I3QLWGKS.js.map} +0 -0
- /package/dist/{chunk-JGK2FDZW.js.map → chunk-J4AWNWKN.js.map} +0 -0
- /package/dist/{chunk-VWHUO3AP.js.map → chunk-JAK5VDSG.js.map} +0 -0
- /package/dist/{chunk-W3TZPHZO.js.map → chunk-JLAFNORO.js.map} +0 -0
- /package/dist/{chunk-2Z6PFHD2.js.map → chunk-KG5VNPKU.js.map} +0 -0
- /package/dist/{chunk-I33FO2ON.js.map → chunk-KJHG2DWS.js.map} +0 -0
- /package/dist/{chunk-BFAPSFS7.js.map → chunk-LAMSUL26.js.map} +0 -0
- /package/dist/{chunk-JCDCIQMA.js.map → chunk-LLTHDEM2.js.map} +0 -0
- /package/dist/{chunk-COOJKEJE.js.map → chunk-M5PZ6QQB.js.map} +0 -0
- /package/dist/{chunk-LQACNCAV.js.map → chunk-MFGUR5OD.js.map} +0 -0
- /package/dist/{chunk-BNEWJXKU.js.map → chunk-NOCBNING.js.map} +0 -0
- /package/dist/{chunk-O2ECZKXP.js.map → chunk-NWLK5RPA.js.map} +0 -0
- /package/dist/{chunk-VAV5CCDD.js.map → chunk-PR5OPERY.js.map} +0 -0
- /package/dist/{chunk-IJ6WA2JW.js.map → chunk-QGAUDVMR.js.map} +0 -0
- /package/dist/{chunk-JSOOLOHP.js.map → chunk-QRRAMUKV.js.map} +0 -0
- /package/dist/{chunk-22RM3UOO.js.map → chunk-QZ4YHQLW.js.map} +0 -0
- /package/dist/{chunk-YDALLZNS.js.map → chunk-RGLTITIH.js.map} +0 -0
- /package/dist/{chunk-U6AWJIFP.js.map → chunk-RIVQ4PQQ.js.map} +0 -0
- /package/dist/{chunk-D5HD46VV.js.map → chunk-RLLPY62L.js.map} +0 -0
- /package/dist/{chunk-H3RCEM6L.js.map → chunk-RQHXWPET.js.map} +0 -0
- /package/dist/{chunk-G4FU6VC5.js.map → chunk-RULW4627.js.map} +0 -0
- /package/dist/{chunk-P4UCSXNA.js.map → chunk-S4RCF3YT.js.map} +0 -0
- /package/dist/{chunk-MZPS46OR.js.map → chunk-SIKCVWM3.js.map} +0 -0
- /package/dist/{chunk-XWAOECD2.js.map → chunk-TCLJRWST.js.map} +0 -0
- /package/dist/{chunk-QVHZTCB5.js.map → chunk-UVUY6FLV.js.map} +0 -0
- /package/dist/{chunk-TEQEZAJI.js.map → chunk-V4HS5JRL.js.map} +0 -0
- /package/dist/{chunk-2TS2ITSG.js.map → chunk-WTOBG3YL.js.map} +0 -0
- /package/dist/{chunk-V5ODOBBI.js.map → chunk-WYMX3F47.js.map} +0 -0
- /package/dist/{chunk-BMMXYR7A.js.map → chunk-WZXMZFVB.js.map} +0 -0
- /package/dist/{chunk-QSS34JWZ.js.map → chunk-X5YHMGAT.js.map} +0 -0
- /package/dist/{chunk-WZATC4O5.js.map → chunk-XA7JN7YE.js.map} +0 -0
- /package/dist/{chunk-IAE24RKD.js.map → chunk-XHAGX4J4.js.map} +0 -0
- /package/dist/{chunk-C7KV5O5J.js.map → chunk-XY7W6MQN.js.map} +0 -0
- /package/dist/{chunk-TEJOILEY.js.map → chunk-YAINUFSC.js.map} +0 -0
- /package/dist/{chunk-RVIBHENP.js.map → chunk-Z7ICQKC2.js.map} +0 -0
- /package/dist/{chunk-TPJ34LXX.js.map → chunk-ZBXV2KOQ.js.map} +0 -0
- /package/dist/{chunk-2YXTXSYG.js.map → chunk-ZMNRSTNV.js.map} +0 -0
- /package/dist/{claim-3UMAFZEM.js.map → claim-L4WLCVUL.js.map} +0 -0
- /package/dist/{companies-RL5A26AT.js.map → companies-HW46BRQG.js.map} +0 -0
- /package/dist/{company-DJ44F5C6.js.map → company-KCIDE7SL.js.map} +0 -0
- /package/dist/{complete-PGNIP3LN.js.map → complete-JXM25FVW.js.map} +0 -0
- /package/dist/{connect-ROARWN63.js.map → connect-7TX7AAM5.js.map} +0 -0
- /package/dist/{conversation-GDFMJL7X.js.map → conversation-YIDUB6GL.js.map} +0 -0
- /package/dist/{conversion-report-2FREFML5.js.map → conversion-report-33SG7SHU.js.map} +0 -0
- /package/dist/{conversion-upload-command-G7LLWHSK.js.map → conversion-upload-command-N3OMLLF2.js.map} +0 -0
- /package/dist/{conversion-writes-JZIJSQ7T.js.map → conversion-writes-XGGTBML5.js.map} +0 -0
- /package/dist/{conversions-2IFWDQKK.js.map → conversions-F4OZYUCT.js.map} +0 -0
- /package/dist/{conversions-Q5EBTEXA.js.map → conversions-PPP4QK7U.js.map} +0 -0
- /package/dist/{create-BRCSXXFO.js.map → create-6EAKNERA.js.map} +0 -0
- /package/dist/{create-B5DIYK5D.js.map → create-772LZHZR.js.map} +0 -0
- /package/dist/{create-PXAUL6FF.js.map → create-FDNMIVFX.js.map} +0 -0
- /package/dist/{create-R6CMATVY.js.map → create-X2QM7GA7.js.map} +0 -0
- /package/dist/{creatives-XNVWQWFF.js.map → creatives-K2AAW6EL.js.map} +0 -0
- /package/dist/{creatives-D6O6Z46U.js.map → creatives-SNYN4KIM.js.map} +0 -0
- /package/dist/{credentials-CLJO7WWY.js.map → credentials-KZZVBO42.js.map} +0 -0
- /package/dist/{critique-MBMKW6SL.js.map → critique-G5QXRHPF.js.map} +0 -0
- /package/dist/{critique-OUJDTVMI.js.map → critique-PUHOJI7V.js.map} +0 -0
- /package/dist/{crm-H5ITJ2RC.js.map → crm-4LZZVT4N.js.map} +0 -0
- /package/dist/{crm-JJHYRABB.js.map → crm-M6NXDU5B.js.map} +0 -0
- /package/dist/{currency-EFDQYW5B.js.map → currency-HK2ZW2VW.js.map} +0 -0
- /package/dist/{customers-C5YXAVXI.js.map → customers-V5NT4W7X.js.map} +0 -0
- /package/dist/{delete-3GYCQK6B.js.map → delete-GQIKNO53.js.map} +0 -0
- /package/dist/{delete-NBUDIGSD.js.map → delete-LFZIPQEO.js.map} +0 -0
- /package/dist/{delete-WZ3KVVX5.js.map → delete-YOEI63OT.js.map} +0 -0
- /package/dist/{demographics-O7AJW7DO.js.map → demographics-CEQ74O74.js.map} +0 -0
- /package/dist/{discard-RMVZAX2J.js.map → discard-5GDF3TP3.js.map} +0 -0
- /package/dist/{discover-BPUUWRBP.js.map → discover-Q5PAOIQQ.js.map} +0 -0
- /package/dist/{domain-J3ZMBOHS.js.map → domain-PKOUPHHF.js.map} +0 -0
- /package/dist/{download-ZVOGLTFB.js.map → download-2WNTN7JQ.js.map} +0 -0
- /package/dist/{draft-Q4PEFBJB.js.map → draft-CF4XNJG5.js.map} +0 -0
- /package/dist/{draft-ZPGGWU7E.js.map → draft-F4CVSL2I.js.map} +0 -0
- /package/dist/{draft-GCOCG4PO.js.map → draft-L2NXCIYT.js.map} +0 -0
- /package/dist/{draft-6PJD3MCW.js.map → draft-RZCTAOI2.js.map} +0 -0
- /package/dist/{draft-TPR3DH5N.js.map → draft-UEVBUNKV.js.map} +0 -0
- /package/dist/{experiments-MM4BYHRH.js.map → experiments-DWC6L72S.js.map} +0 -0
- /package/dist/{extract-JMY6YRPW.js.map → extract-6HJXSOZW.js.map} +0 -0
- /package/dist/{facets-B5AZAU2C.js.map → facets-TBOXGYJT.js.map} +0 -0
- /package/dist/{feedback-4MCMOMVN.js.map → feedback-MSMFYAEY.js.map} +0 -0
- /package/dist/{feedback-2EVDGTEN.js.map → feedback-WAC6S42V.js.map} +0 -0
- /package/dist/{feedback-record-DL7UEU2H.js.map → feedback-record-XRQ2R2WD.js.map} +0 -0
- /package/dist/{fetch-JDNFK476.js.map → fetch-LGX7B3IC.js.map} +0 -0
- /package/dist/{fit-DKVH5BDW.js.map → fit-RVWPRBNO.js.map} +0 -0
- /package/dist/{flows-LURTZICL.js.map → flows-LA6EYMLS.js.map} +0 -0
- /package/dist/{fonts-HUXFDDAE.js.map → fonts-WRC34VSV.js.map} +0 -0
- /package/dist/{forecast-UHTW4Y7Q.js.map → forecast-6VHRGBJG.js.map} +0 -0
- /package/dist/{forecast-ITLKAFHM.js.map → forecast-OVKXBLJB.js.map} +0 -0
- /package/dist/{funnel-QM7WFFMD.js.map → funnel-U3GQIGND.js.map} +0 -0
- /package/dist/{generate-KAWRRYTT.js.map → generate-Y4NJEYIH.js.map} +0 -0
- /package/dist/{get-237TYJZT.js.map → get-AHI247JG.js.map} +0 -0
- /package/dist/{get-FWPR2YPC.js.map → get-PF3HGECD.js.map} +0 -0
- /package/dist/{google-JY7KDAFC.js.map → google-BMUJKAUO.js.map} +0 -0
- /package/dist/{google-DTSLO3PT.js.map → google-ZVAIFXQZ.js.map} +0 -0
- /package/dist/{google-ads-RZOQQDQN.js.map → google-ads-6Z7P3SCD.js.map} +0 -0
- /package/dist/{history-XL52537O.js.map → history-4QUV45ZJ.js.map} +0 -0
- /package/dist/{history-H7S7XRBX.js.map → history-PD7FCTDD.js.map} +0 -0
- /package/dist/{history-YQSYXBJH.js.map → history-VKRYKQ4C.js.map} +0 -0
- /package/dist/{hubspot-2DSISSUI.js.map → hubspot-WEFAFKVJ.js.map} +0 -0
- /package/dist/{ideas-2XBFQJ56.js.map → ideas-SMSEXKIA.js.map} +0 -0
- /package/dist/{images-VFRQ32G5.js.map → images-KAT4BPYV.js.map} +0 -0
- /package/dist/{ingest-4RPLN54K.js.map → ingest-IHKTSJ4H.js.map} +0 -0
- /package/dist/{ingest-TPVH44VI.js.map → ingest-TOHQ6MZA.js.map} +0 -0
- /package/dist/{insights-UVCFOB3N.js.map → insights-3IPSEBYW.js.map} +0 -0
- /package/dist/{inspect-VD3GVXDU.js.map → inspect-5MZBPDYS.js.map} +0 -0
- /package/dist/{intent-F5NTOSQC.js.map → intent-ZM4K623V.js.map} +0 -0
- /package/dist/{keyword-gap-EB5QATYN.js.map → keyword-gap-FAAF2I6V.js.map} +0 -0
- /package/dist/{keyword-metrics-PW2DDIJW.js.map → keyword-metrics-EXNJRJBY.js.map} +0 -0
- /package/dist/{keywords-for-site-JEPABY6E.js.map → keywords-for-site-5LW77QWF.js.map} +0 -0
- /package/dist/{landing-4N6YSB4L.js.map → landing-ZH4SD3DW.js.map} +0 -0
- /package/dist/{languages-4S26FJDP.js.map → languages-ZGDTERIQ.js.map} +0 -0
- /package/dist/{leads-R5OZJQHW.js.map → leads-736RILZN.js.map} +0 -0
- /package/dist/{learn-AQ2FRFB7.js.map → learn-BESXWXEN.js.map} +0 -0
- /package/dist/{line-item-writes-LGO7HIJJ.js.map → line-item-writes-FA72DHNQ.js.map} +0 -0
- /package/dist/{line-items-AAZVKQ7E.js.map → line-items-XVYE3IYT.js.map} +0 -0
- /package/dist/{link-7IGHVARH.js.map → link-6FPKFVC3.js.map} +0 -0
- /package/dist/{linkedin-UB2CW4KP.js.map → linkedin-TE6P4RYN.js.map} +0 -0
- /package/dist/{linkedin-person-D6U2ZAUW.js.map → linkedin-person-TZJ6VEXE.js.map} +0 -0
- /package/dist/{list-P44QRX2O.js.map → list-4R5EMKUQ.js.map} +0 -0
- /package/dist/{list-VZKUHY4Y.js.map → list-MN2FPF3T.js.map} +0 -0
- /package/dist/{list-UMJACDTQ.js.map → list-ORO4WDF4.js.map} +0 -0
- /package/dist/{locations-WXGOI3VV.js.map → locations-A65MFB7Q.js.map} +0 -0
- /package/dist/{locations-UWBQLHXW.js.map → locations-WN6B3IJK.js.map} +0 -0
- /package/dist/{log-6ZKMUTYS.js.map → log-ABBZLPRU.js.map} +0 -0
- /package/dist/{make-5CEIJRBC.js.map → make-QAFKU6WO.js.map} +0 -0
- /package/dist/{map-ZL4MQVJZ.js.map → map-52P35OKE.js.map} +0 -0
- /package/dist/{mcp-GSRYLRD4.js.map → mcp-PZ3VBIF4.js.map} +0 -0
- /package/dist/{media-sources-VSPVHLYN.js.map → media-sources-TT374PLN.js.map} +0 -0
- /package/dist/{members-L6SXP6GC.js.map → members-CF6VG6ZW.js.map} +0 -0
- /package/dist/{metrics-4AFEEDVP.js.map → metrics-3U3ZO2RF.js.map} +0 -0
- /package/dist/{models-2ZEM64H5.js.map → models-VOSJJFO2.js.map} +0 -0
- /package/dist/{normalize-GK7DH7ZP.js.map → normalize-4LZCLMTQ.js.map} +0 -0
- /package/dist/{options-FDAAHG7C.js.map → options-6IRL7CL6.js.map} +0 -0
- /package/dist/{organization-K2FTFAAO.js.map → organization-WMLLJE66.js.map} +0 -0
- /package/dist/{performance-N3UROH7Z.js.map → performance-A7CYFBW2.js.map} +0 -0
- /package/dist/{performance-RG2HR46T.js.map → performance-HYSTXLTS.js.map} +0 -0
- /package/dist/{pixels-HEI5WVAO.js.map → pixels-U6UA662G.js.map} +0 -0
- /package/dist/{preview-NVWIEUHF.js.map → preview-76ZP2QA3.js.map} +0 -0
- /package/dist/{promoted-tweet-writes-7QZRFDOM.js.map → promoted-tweet-writes-I5G4IDL5.js.map} +0 -0
- /package/dist/{promoted-tweets-V555Y7DN.js.map → promoted-tweets-X5XNO7IT.js.map} +0 -0
- /package/dist/{publish-5KR6YLA6.js.map → publish-S2Z4EF4H.js.map} +0 -0
- /package/dist/{query-K7MYBRTS.js.map → query-SAQADBM2.js.map} +0 -0
- /package/dist/{reddit-XPQ7YAJW.js.map → reddit-S2L5WDY7.js.map} +0 -0
- /package/dist/{refresh-XFHEBSDU.js.map → refresh-K2YTJSH3.js.map} +0 -0
- /package/dist/{release-3ECEF26P.js.map → release-FX76IIVN.js.map} +0 -0
- /package/dist/{relevant-pages-XYQKVX3U.js.map → relevant-pages-KTSODNNW.js.map} +0 -0
- /package/dist/{remove-OCTUC3RB.js.map → remove-LOVWPLDO.js.map} +0 -0
- /package/dist/{reopen-JRI3TYD4.js.map → reopen-DXV2Y6Z3.js.map} +0 -0
- /package/dist/{rerun-HWWYCDT2.js.map → rerun-TFQCRRFK.js.map} +0 -0
- /package/dist/{research-ODPU62BA.js.map → research-7PGDAKC7.js.map} +0 -0
- /package/dist/{research-TG5CBTYP.js.map → research-HY5PSUCC.js.map} +0 -0
- /package/dist/{reset-SRU7YJUR.js.map → reset-MEHUQJA4.js.map} +0 -0
- /package/dist/{reset-J2NLNITD.js.map → reset-Y5VZJRDQ.js.map} +0 -0
- /package/dist/{resolve-KHMMUGB2.js.map → resolve-FAVABEJW.js.map} +0 -0
- /package/dist/{retry-VLH4AO7F.js.map → retry-5IY4MNDW.js.map} +0 -0
- /package/dist/{retry-WP7LWKZF.js.map → retry-OMJ3C3AX.js.map} +0 -0
- /package/dist/{revenue-EEIS2AV5.js.map → revenue-S4KFZCOI.js.map} +0 -0
- /package/dist/{rules-TTUGQAEB.js.map → rules-66IGR2KA.js.map} +0 -0
- /package/dist/{rules-add-AIXUAZXG.js.map → rules-add-G7YGOYZJ.js.map} +0 -0
- /package/dist/{run-YA6IWQAJ.js.map → run-LJVBH3JS.js.map} +0 -0
- /package/dist/{run-AQTACLY6.js.map → run-XJBWDWN6.js.map} +0 -0
- /package/dist/{scaffold-ad-IYNFJPT7.js.map → scaffold-ad-GNMCB3QY.js.map} +0 -0
- /package/dist/{scaffold-video-BUN27PKS.js.map → scaffold-video-G6G2NPUF.js.map} +0 -0
- /package/dist/{schedule-EH2MOC5C.js.map → schedule-OX5XHXLH.js.map} +0 -0
- /package/dist/{scheduled-agents-DTAEP25E.js.map → scheduled-agents-A5ZFQB5X.js.map} +0 -0
- /package/dist/{schema-7B4MVVAS.js.map → schema-NTGHAPR2.js.map} +0 -0
- /package/dist/{search-ZZWIJRXJ.js.map → search-WCXQBMMM.js.map} +0 -0
- /package/dist/{select-LWZRF7KV.js.map → select-5ZD7FVBT.js.map} +0 -0
- /package/dist/{set-prompt-YKDH6FYK.js.map → set-prompt-NGCVMQIQ.js.map} +0 -0
- /package/dist/{setup-links-OE6PC2YQ.js.map → setup-links-4HCSF55G.js.map} +0 -0
- /package/dist/{shopify-CCPLZI2H.js.map → shopify-GDR5WGHH.js.map} +0 -0
- /package/dist/{site-FW5BBLYG.js.map → site-B7LT6KAO.js.map} +0 -0
- /package/dist/{sources-WPHMWBEK.js.map → sources-6DPUEROC.js.map} +0 -0
- /package/dist/{sources-X77TGJ52.js.map → sources-OSUXCLID.js.map} +0 -0
- /package/dist/{stale-SPCDL73V.js.map → stale-YKFKPPOH.js.map} +0 -0
- /package/dist/{status-FLETGJ2A.js.map → status-KIC3P5JV.js.map} +0 -0
- /package/dist/{stock-5AOSQH52.js.map → stock-VWFUFRYV.js.map} +0 -0
- /package/dist/{studio-4EV5S7PR.js.map → studio-XLC37YGX.js.map} +0 -0
- /package/dist/{sync-363VKXU3.js.map → sync-QBW4XH2H.js.map} +0 -0
- /package/dist/{sync-definition-ZDE5L644.js.map → sync-definition-4KMJK46H.js.map} +0 -0
- /package/dist/{tags-VOKUNEIW.js.map → tags-4F5UBPYG.js.map} +0 -0
- /package/dist/{tags-ZCQMJ5YH.js.map → tags-4O5FPEEY.js.map} +0 -0
- /package/dist/{tags-YHAC3NVY.js.map → tags-7RKKCQ4X.js.map} +0 -0
- /package/dist/{tags-6MN3AWKN.js.map → tags-CB4MWI3A.js.map} +0 -0
- /package/dist/{tags-Y6MNMIEA.js.map → tags-QZJIP4LJ.js.map} +0 -0
- /package/dist/{targeting-criteria-ECQFHQF3.js.map → targeting-criteria-65UU7EYD.js.map} +0 -0
- /package/dist/{targets-U2JHTB5U.js.map → targets-T742OPQI.js.map} +0 -0
- /package/dist/{testimonials-IDVLMXDT.js.map → testimonials-HKJJXONO.js.map} +0 -0
- /package/dist/{themes-QMR5TWTI.js.map → themes-Q6LVMEMF.js.map} +0 -0
- /package/dist/{top-companies-CBI4O3ZB.js.map → top-companies-T6AMU4C6.js.map} +0 -0
- /package/dist/{transcript-IIRFTFRW.js.map → transcript-DOUYMZAP.js.map} +0 -0
- /package/dist/{translate-N6QW4FZB.js.map → translate-WKOXFZTQ.js.map} +0 -0
- /package/dist/{triggers-Q3KRAMA3.js.map → triggers-EYY4GSUL.js.map} +0 -0
- /package/dist/{unlink-7RVQXKAR.js.map → unlink-JNM4WRZK.js.map} +0 -0
- /package/dist/{unstage-3LPHNZKR.js.map → unstage-QF4JT5YP.js.map} +0 -0
- /package/dist/{update-YBTFH5MN.js.map → update-6V3RBRIE.js.map} +0 -0
- /package/dist/{update-AL3LBHGK.js.map → update-J4DURR4K.js.map} +0 -0
- /package/dist/{update-AWR7EHGA.js.map → update-J7Y6LZC5.js.map} +0 -0
- /package/dist/{update-LNSSLZXG.js.map → update-MQ4NYIU6.js.map} +0 -0
- /package/dist/{upload-45GCGMA5.js.map → upload-CEIYYPID.js.map} +0 -0
- /package/dist/{url-options-AHJPR5VY.js.map → url-options-6WC2XQKB.js.map} +0 -0
- /package/dist/{url-params-U6ZM4LL2.js.map → url-params-OVBIP6UA.js.map} +0 -0
- /package/dist/{validate-S325RXPH.js.map → validate-UHXI2ESE.js.map} +0 -0
- /package/dist/{videos-NW2UP342.js.map → videos-Z72RXCRB.js.map} +0 -0
- /package/dist/{viewer-check-IDXFRRCO.js.map → viewer-check-655BZRML.js.map} +0 -0
- /package/dist/{web-VMPKMBKA.js.map → web-4QN6QB7L.js.map} +0 -0
- /package/dist/{winning-ads-7UJXCWFH.js.map → winning-ads-2J2RIOLR.js.map} +0 -0
- /package/dist/{write-commands-R42DQEW6.js.map → write-commands-V7B4FBMX.js.map} +0 -0
- /package/dist/{x-UGTUOCVR.js.map → x-7KXNCWTJ.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/engine/scaffold/static-logo-briefs.ts","../src/language.ts","../src/engine/scaffold/static-series.ts","../src/engine/scaffold/static-render-briefs.ts","../src/engine/scaffold/static-adapt-briefs.ts","../src/engine/scaffold/static-delivery.ts","../src/engine/scaffold/static-format-briefs.ts","../src/engine/scaffold/static-shape-route.ts","../src/engine/lib/image-model-router.ts","../src/engine/scaffold/staticAd.ts","../src/engine/scaffold/castAvatar.ts","../src/engine/scaffold/static-upgrade.ts","../src/commands/canvas/creative-definition.ts","../src/engine/scaffold/static-fonts.ts","../src/engine/scaffold/static-brand.ts","../src/engine/scaffold/static-native-graph.ts","../src/commands/canvas/logo-file.ts","../src/commands/canvas/static-copy-projection.ts","../src/engine/scaffold/static-named-people.ts","../src/engine/scaffold/static-proof.ts","../src/engine/scaffold/video/aspect.ts","../src/engine/scaffold/video/elements.ts","../src/engine/scaffold/video/ids.ts","../src/engine/scaffold/video/routing.ts","../src/engine/scaffold/video/overlay-html.ts","../src/engine/scaffold/lib/html.ts","../src/engine/scaffold/video/timing.ts","../src/engine/scaffold/video/projections.ts","../src/engine/scaffold/video/report.ts","../src/engine/scaffold/lib/language.ts","../src/engine/scaffold/video/assembly.ts","../src/engine/scaffold/video/audio.ts","../src/engine/scaffold/video/guide.ts","../src/engine/scaffold/video/meta.ts","../src/engine/scaffold/lib/scene-role.ts","../src/engine/scaffold/video/routes/surface-still.ts","../src/engine/scaffold/video/routes/graphic-plate.ts","../src/engine/scaffold/video/dialogue/speakers.ts","../src/engine/scaffold/video/dialogue/phrases.ts","../src/engine/scaffold/video/ffmpeg-args.ts","../src/engine/scaffold/video/dialogue/voices.ts","../src/engine/scaffold/video/routes/brand-card.ts","../src/engine/scaffold/lib/shoot-modes.ts","../src/engine/scaffold/video/prompts/frame.ts","../src/engine/scaffold/video/frames.ts","../src/engine/scaffold/video/model-params.ts","../src/engine/scaffold/video/prompts/clip.ts","../src/engine/scaffold/video/dialogue/numbers.ts","../src/engine/scaffold/video/routes/clip.ts","../src/engine/scaffold/video/timeline-env.ts","../src/engine/scaffold/video/routes/composite.ts","../src/engine/scaffold/video/routes/phrase-slice.ts","../src/engine/scaffold/video/routes/screen-still.ts","../src/engine/scaffold/video/routes/still-hold.ts","../src/engine/scaffold/video/timeline.ts","../src/engine/scaffold/video/todo.ts","../src/engine/scaffold/video.ts","../src/engine/nodes/local/lib/caption-groups.ts","../src/engine/scaffold/video/speech-reading.ts","../src/commands/canvas/scene-files.ts","../src/commands/canvas/scene-projection.ts","../src/commands/canvas/source-version.ts","../src/engine/nodes/local/lib/jev-cache.ts","../src/engine/scaffold/video/dialogue/voice-gender.ts","../src/commands/creatives/cast-decision.ts","../src/commands/creatives/thinking.ts","../src/engine/creative-context/anchor.ts","../src/commands/canvas/style-projection.ts","../src/commands/canvas/prepare-canvas.ts","../src/commands/canvas/placeholders.ts","../src/commands/canvas/interface-words.ts","../src/commands/canvas/claim-check.ts","../src/engine/scaffold/ad-claims.ts","../src/commands/canvas/native-projection.ts","../src/commands/canvas/promote-canvas-outputs.ts","../src/commands/creatives/cast-roster.ts","../src/commands/canvas/idea-gate.ts","../src/commands/canvas/keep-gate.ts","../src/commands/canvas/copy-language.ts","../src/commands/canvas/definition-sizes.ts","../src/engine/scaffold/static-replan.ts"],"sourcesContent":["/**\n * The logo placed from its file (`static_logo`), as the briefs and the composites are told it from\n * prompt.json on every run: each composite learns where the concept puts the logo and the ad's\n * copy (its check finds the headline among it), each size's words where its slot goes, and each\n * render that lays a size out (the variants, each re-laid-out size) to draw no logo and keep the\n * slot its composite will place the file in. Pure.\n */\nimport { blockingArea } from \"./platform-safe-area.ts\";\nimport type { AdSpec } from \"./static-ad-spec.ts\";\nimport {\n designerSpots,\n LOGO_POSITIONS,\n type LogoPosition,\n logoSlotLine,\n placedLogoPosition,\n type Span,\n spanOf,\n} from \"./static-logo.ts\";\nimport { deliveredSize } from \"./static-sizes.ts\";\n\ntype Node = {\n id?: unknown;\n type?: unknown;\n params?: Record<string, unknown>;\n inputs?: Record<string, unknown>;\n tags?: { role?: unknown };\n};\n\n/** The shape a slot is planned with when the composite names none: a wordmark. */\nconst DEFAULT_ASPECT = 3;\n\nconst positionOf = (v: unknown): LogoPosition | undefined =>\n (LOGO_POSITIONS as readonly unknown[]).includes(v) ? (v as LogoPosition) : undefined;\n\n/**\n * The line a render that lays out `format` (drawn at ratio `drawn`, then filled to it) is told when\n * that size's composite plans its own slot: draw no logo, keep the slot plain. Null when no\n * composite places the logo on that size, or it is placed in the slot a size's words chose.\n */\nexport function logoSlotLineFor(nodes: readonly Node[], format: string, drawn: string): string | null {\n const planned = plannedSlot(nodes, format);\n return planned ? logoSlotLine(planned.clear, planned.position, { drawn, format }) : null;\n}\n\n/**\n * The slot `format`'s composite plans for the logo, with its clear space, as fractions of the\n * delivered size: what the renders keep plain and the variant checks hold them to. Null when no\n * composite places the logo on that size, or it takes the slot a size's words chose.\n */\nexport function logoSlotSpanFor(nodes: readonly Node[], format: string): Span | null {\n return plannedSlot(nodes, format)?.clear ?? null;\n}\n\nfunction plannedSlot(nodes: readonly Node[], format: string): { clear: Span; position: LogoPosition } | null {\n const composite = nodes.find((n) => n.type === \"static_logo\" && n.params?.format === format);\n if (!composite || composite.inputs?.slot !== undefined) return null;\n const aspect = typeof composite.params?.aspect === \"number\" ? composite.params.aspect : DEFAULT_ASPECT;\n const position = positionOf(composite.params?.position) ?? \"top_left\";\n const raw = composite.params?.placements;\n const placements = Array.isArray(raw) && raw.every((p) => typeof p === \"string\") ? (raw as string[]) : undefined;\n const size = deliveredSize(format);\n // Nothing is known of the picture yet: the place the composite tries first (`chooseLogoSpot` on an empty scene).\n const slot = designerSpots(size, blockingArea(format, placements), { aspect, position })[0];\n return slot ? { clear: spanOf(slot.clear, size), position: slot.position } : null;\n}\n\n/**\n * The colours a logo file inked in the text colour (`currentColor`) is drawn in, in the brand's\n * order: its accent (a wordmark's colour, Zernio's coral), its ink, then white for a dark ground.\n * The composite takes the first that reads on the ground under the slot. Pure.\n */\nfunction logoInks(brand: AdSpec[\"brand\"]): string[] {\n const hex = (v: unknown) => (typeof v === \"string\" && /^#[0-9a-fA-F]{6}$/.test(v) ? v.toUpperCase() : null);\n return [...new Set([hex(brand?.accent), hex(brand?.ink), \"#FFFFFF\"].filter((v): v is string => v !== null))];\n}\n\n/**\n * The brand's colours a plate behind the logo may take when no plain ground holds it, its ground and\n * ink first, then its accent, button and palette. The composite picks the one the logo file stands out from most. Pure.\n */\nfunction logoPlates(brand: AdSpec[\"brand\"]): string[] {\n const hex = (v: unknown) => (typeof v === \"string\" && /^#[0-9a-fA-F]{6}$/.test(v) ? v.toUpperCase() : null);\n const colours = [brand?.ground, brand?.ink, brand?.accent, brand?.cta, ...(brand?.palette ?? [])].map(hex);\n return [...new Set(colours.filter((v): v is string => v !== null))];\n}\n\n/** A brief's zones with the logo out of them: it is placed on the size afterwards, in its own slot. */\nexport function withoutLogoInZones(paragraph: string): string {\n return paragraph.replace(\"every word, the logo and the button sit\", \"every word and the button sit\");\n}\n\n/**\n * Tell each composite (`static_logo`) where the concept puts the logo and the ad's copy, the\n * brand's name and the words its logo prints as role `logo`; and each size's words call\n * (`static_format` with a `logo_slot`) the same position. Returns how many nodes changed.\n */\nexport function projectLogoPlacement(nodes: Node[], spec: Pick<AdSpec, \"copy\" | \"brand\" | \"logo_position\">): number {\n const position = placedLogoPosition(spec.logo_position);\n const inks = logoInks(spec.brand);\n const plates = logoPlates(spec.brand);\n const logoWords = [...new Set([...(spec.brand?.name ? [spec.brand.name] : []), ...(spec.brand?.lockup ?? [])])];\n const copy = [\n ...spec.copy.map((l) => ({ text: l.text, ...(l.role ? { role: l.role } : {}) })),\n ...logoWords.map((text) => ({ text, role: \"logo\" })),\n ];\n let changed = 0;\n for (const n of nodes) {\n const before = JSON.stringify(n.params);\n if (n.type === \"static_logo\") {\n const params: Record<string, unknown> = { ...n.params, position, inks, plates };\n if (copy.length > 0) params.copy = copy;\n else delete params.copy;\n n.params = params;\n } else if (n.type === \"static_format\" && n.params?.logo_slot && typeof n.params.logo_slot === \"object\") {\n n.params = { ...n.params, logo_slot: { ...(n.params.logo_slot as Record<string, unknown>), position } };\n } else continue;\n if (JSON.stringify(n.params) !== before) changed++;\n }\n return changed;\n}\n","/**\n * A language an ad is written in, as a BCP-47 tag: parsed with `Intl`, never by hand. The tag is\n * stored canonical (`es-MX`, `pt-BR`), as ad specs hold it, and compared without case; only where\n * it names something, the translation's creative (`<ad>-es-mx`), is it lowercase.\n */\n\nconst NAMES = new Intl.DisplayNames([\"en\"], { type: \"language\", fallback: \"none\" });\n\n/** The canonical tag of `code` (\"pt-br\" → \"pt-BR\"); null when it names no language. Pure. */\nexport function languageTag(code: string): string | null {\n try {\n const [canonical] = Intl.getCanonicalLocales(code.trim());\n if (!canonical || NAMES.of(canonical) === undefined) return null;\n return canonical;\n } catch {\n return null;\n }\n}\n\n/** Whether two tags name the same language and country (\"es-mx\" and \"es-MX\" do; \"es\" and \"es-MX\" do not). Pure. */\nexport function sameTag(a: string, b: string): boolean {\n return a.toLowerCase() === b.toLowerCase();\n}\n\n/** The tag as it names a creative: lowercase (\"es-MX\" → \"es-mx\"). Pure. */\nexport function tagSlug(tag: string): string {\n return tag.toLowerCase();\n}\n\n/** A language's English name (\"es\" → \"Spanish\", \"pt-br\" → \"Brazilian Portuguese\"); null for a code that names none. Pure. */\nexport function languageName(code: string): string | null {\n try {\n const [canonical] = Intl.getCanonicalLocales(code.trim());\n return canonical ? (NAMES.of(canonical) ?? null) : null;\n } catch {\n return null;\n }\n}\n\nconst REGIONS = new Intl.DisplayNames([\"en\"], { type: \"region\", fallback: \"none\" });\n\n/** The country a tag names (\"es-MX\" → { code: \"MX\", name: \"Mexico\" }); null for a tag with none. Pure. */\nexport function languageRegion(code: string): { code: string; name: string } | null {\n try {\n const region = new Intl.Locale(code.trim()).region;\n const name = region ? REGIONS.of(region) : undefined;\n return region && name ? { code: region, name } : null;\n } catch {\n return null;\n }\n}\n","/**\n * A series is one finished ad repeated with other words: the lead ad is designed once, and every\n * other ad of the series is the lead's picture with only its lines changed (`seriesMemberAd`).\n * Here: which of the lead's lines each of this ad's lines replaces, said as the edit's instruction.\n *\n * Pure.\n */\nimport { languageName } from \"../../language.ts\";\n\ntype Line = { text: string; role?: string; position?: string };\n\n/**\n * The edit that turns the lead's words into this ad's, line by line in the lead's order: a line of\n * this ad replaces the lead's line of the same role (else the next one left, in order, so the\n * layout stays the lead's), a line both share is kept, a lead line with nothing to replace it is\n * removed, and a line of this ad left over is added. The model edits one line in place far better\n * than it re-sets a whole block of type.\n */\nexport function seriesWordsInstruction(\n leadCopy: readonly Line[],\n copy: readonly Line[],\n opts: { language?: string } = {},\n): string {\n const pairs = pairLines(leadCopy, copy);\n const said = leadCopy.map((from, i) => {\n const to = pairs.get(i);\n if (!to) return `Remove \"${from.text}\" and give its space to the background.`;\n return to.text === from.text ? `Keep \"${from.text}\" as it is.` : `Replace \"${from.text}\" with \"${to.text}\"`;\n });\n const paired = new Set(pairs.values());\n const added = copy\n .filter((line) => !paired.has(line))\n .map(\n (line) =>\n `Add \"${line.text}\"${line.position ? ` ${line.position}` : \"\"}, in the lettering of the ad's other lines.`,\n );\n const language = opts.language ? languageName(opts.language) : null;\n const lettering = language ? [`The new words are in ${language}: set every accent and mark exactly as written`] : [];\n return [...lettering, ...said, ...added].map(endSentence).join(\" \");\n}\n\n/** Each lead line's replacement, by index: the same words, else the same role, else the next line left, in order. */\nfunction pairLines(leadCopy: readonly Line[], copy: readonly Line[]): Map<number, Line> {\n const pairs = new Map<number, Line>();\n const free = [...copy];\n const take = (match: (line: Line) => boolean): Line | undefined => {\n const at = free.findIndex(match);\n return at < 0 ? undefined : free.splice(at, 1)[0];\n };\n leadCopy.forEach((from, i) => {\n const same =\n take((line) => line.text === from.text) ?? (from.role ? take((line) => line.role === from.role) : undefined);\n if (same) pairs.set(i, same);\n });\n leadCopy.forEach((_from, i) => {\n if (pairs.has(i)) return;\n const next = take(() => true);\n if (next) pairs.set(i, next);\n });\n return pairs;\n}\n\nfunction endSentence(text: string): string {\n return /[.!?]\"?$/.test(text) ? text : `${text}.`;\n}\n","/**\n * A static ad canvas's render prompts, compiled from its `prompt.json`.\n *\n * Every render node of a static ad (the candidate takes, the re-lays, the judge) carries the\n * brief `static-brief.ts` compiles from the ad spec, never the spec itself: the model, the\n * cache key and the dashboard all see the prompt that renders. The scaffold writes them and\n * `prepareCanvas` projects them again on every run (`syncStaticAdBrief`), so an edit to\n * prompt.json reaches exactly the nodes it changes. A canvas scaffolded before the compiler\n * (its prompt inlining the blueprint, the source ad among its references) is upgraded in place\n * by the same projection on its next run.\n *\n * Pure: canvas + prompt.json content in, nodes rewritten in place.\n */\n\nimport type { CreativeRule } from \"../creative-rules/schema.ts\";\nimport { GPT_IMAGE_25_PROFILE, imageProfileFor } from \"../lib/prompt-profiles.ts\";\nimport { type StaticChecks, staticChecksOf } from \"../nodes/local/lib/variant-prefilter.ts\";\nimport {\n type AdReference,\n type AdSpec,\n readAdSpec,\n referenceNodeId,\n seesReferenceStructure,\n withRenderedLettering,\n} from \"./static-ad-spec.ts\";\nimport { adaptPlan, trimmedRenderBand } from \"./static-adapt.ts\";\nimport { type BriefImages, type BriefJob, compileStaticBrief, judgeBrief, type PlannedBand } from \"./static-brief.ts\";\nimport { COPY_DIRECTIVE_HEADER, replaceCopyDirective, specimenText, textFidelityDirective } from \"./static-copy.ts\";\nimport { logoSlotLineFor, logoSlotSpanFor } from \"./static-logo-briefs.ts\";\nimport { seriesWordsInstruction } from \"./static-series.ts\";\nimport { MASTER_SHAPES, type MasterShape, planStaticFormats } from \"./static-sizes.ts\";\nimport {\n isPlateCanvas,\n LOGO_COMPOSITE_ROLE,\n SERIES_LEAD_ROLE,\n STATIC_ADAPT_ROLE,\n STATIC_VARIANT_CALL_ROLE,\n STATIC_VARIANTS_ROLE,\n staticMasterFormat,\n VARIANT_PREFILTER_ROLE,\n} from \"./static-topology.ts\";\n\n/** The tag on the `prompt` ingest that says this canvas is a static ad (tags never enter the cache key). */\nexport const STATIC_AD_ROLE = \"static_ad_blueprint\";\n/** The tag on the ingest of the brand's real logo file, whatever id the element pass gave it. */\nexport const BRAND_LOGO_ROLE = \"brand_logo\";\n/** The tag on the ingest of the same logo in another colour (`logo-dark.svg` beside `logo-light.svg`): the composite picks the one that reads. */\nexport const BRAND_LOGO_COLOURWAY_ROLE = \"brand_logo_colourway\";\n/** The tag a pre-topology canvas put on one of its takes (upgraded by `upgradeStaticCanvas`). */\nexport const STATIC_CANDIDATE_ROLE = \"static_candidate\";\n/** The tag a pre-topology canvas put on a re-lay of the chosen ad (upgraded by `upgradeStaticCanvas`). */\nexport const STATIC_RELAY_ROLE = \"static_relay\";\n\nexport type StaticCanvasNode = {\n id: string;\n type: string;\n params?: Record<string, unknown>;\n inputs?: Record<string, unknown>;\n tags?: { role?: string; region?: number };\n};\n\nfunction nodesOf(canvas: unknown): StaticCanvasNode[] {\n const nodes = (canvas as { nodes?: unknown } | null)?.nodes;\n return Array.isArray(nodes) ? (nodes as StaticCanvasNode[]) : [];\n}\n\nconst refId = (ref: unknown): string | undefined =>\n typeof ref === \"string\" ? ref.match(/^\\$ref:([a-z][a-z0-9_]*)\\./)?.[1] : undefined;\n\n/** Whether a canvas is a static ad whose renders compile from prompt.json. */\nexport function isStaticBriefCanvas(canvas: unknown): boolean {\n return isStaticCanvas(nodesOf(canvas));\n}\n\nfunction isStaticCanvas(nodes: StaticCanvasNode[]): boolean {\n if (nodes.some((n) => n.id === \"prompt\" && n.type === \"ingest\" && n.tags?.role === STATIC_AD_ROLE)) return true;\n // Scaffolded before the prompt ingest was tagged: its renders carry the copy block.\n return nodes.some(\n (n) =>\n n.type === \"image_generate\" &&\n typeof n.params?.prompt === \"string\" &&\n n.params.prompt.includes(COPY_DIRECTIVE_HEADER),\n );\n}\n\ntype Render = { node: StaticCanvasNode; job: Exclude<BriefJob, \"fix\">; variant: number; format: string };\n\n/** The lead ad a series ad replaces the words of (`metadata.series`, written by `seriesMemberAd`); null on any other ad. */\nexport type SeriesOf = {\n lead: string;\n run_id: string;\n copy: Array<{ text: string; role?: string }>;\n /** A translation of the lead: the language its words are in. */\n language?: string;\n};\n\n/** The language a translation's words are in, for `seriesWordsInstruction`. */\nexport function wordsLanguage(series: SeriesOf): { language?: string } {\n return typeof series.language === \"string\" ? { language: series.language } : {};\n}\n\nexport function seriesOf(canvas: unknown): SeriesOf | null {\n const series = (canvas as { metadata?: { series?: unknown } } | null)?.metadata?.series as\n | Partial<SeriesOf>\n | undefined;\n return series && typeof series.lead === \"string\" && Array.isArray(series.copy) ? (series as SeriesOf) : null;\n}\n\n/** The job one node does, read off its tag (or, on an older canvas, its id); null when it is not a static render. */\nfunction renderOf(node: StaticCanvasNode, lead: string | undefined): Render | null {\n if (node.type !== \"image_generate\") return null;\n return variantRenderOf(node, lead) ?? legacyRenderOf(node, lead);\n}\n\n/** The variants: one request each on its own direction, or (a single variant, or one `n` request on an older canvas) variant 0's. */\nfunction variantRenderOf(node: StaticCanvasNode, lead: string | undefined): Render | null {\n if (node.tags?.role === STATIC_VARIANTS_ROLE) return { node, job: \"generate\", variant: 0, format: lead ?? \"9:16\" };\n if (node.tags?.role !== STATIC_VARIANT_CALL_ROLE) return null;\n return { node, job: \"generate\", variant: node.tags.region ?? 0, format: lead ?? \"9:16\" };\n}\n\n/** A take or a re-lay of a canvas scaffolded before the one-picture graph (`upgradeStaticCanvas` replaces them). */\nfunction legacyRenderOf(node: StaticCanvasNode, lead: string | undefined): Render | null {\n const take = node.id.match(/^ad(?:_([a-c]))?$/);\n if (node.tags?.role === STATIC_CANDIDATE_ROLE || take) {\n const letter = take?.[1];\n const variant = node.tags?.region ?? (letter ? letter.charCodeAt(0) - 97 : 0);\n return { node, job: \"generate\", variant, format: lead ?? String(node.params?.aspect_ratio ?? \"9:16\") };\n }\n const relay = node.id.match(/^ad_(\\d+)x(\\d+)$/);\n if (node.tags?.role !== STATIC_RELAY_ROLE && !relay) return null;\n const format = relay ? `${relay[1]}:${relay[2]}` : String(node.params?.aspect_ratio ?? \"4:5\");\n return { node, job: \"relay\", variant: 0, format };\n}\n\n/** The render nodes, with the job each does. */\nfunction staticRenders(nodes: StaticCanvasNode[]): Render[] {\n const lead = renderFormat(nodes);\n return nodes.flatMap((node) => {\n const render = renderOf(node, lead);\n return render ? [render] : [];\n });\n}\n\n/** The format the ad is rendered for: the master's, else (an older canvas) the first delivered format. */\nfunction renderFormat(nodes: StaticCanvasNode[]): string | undefined {\n const master = staticMasterFormat({ nodes });\n if (master) return master;\n const labels = nodes.find((n) => n.id === \"final\" && n.type === \"collect\")?.params?.labels;\n return Array.isArray(labels) && typeof labels[0] === \"string\" ? labels[0] : undefined;\n}\n\n/** The ad set's placements the canvas's sizes were planned with (kept on the prefilter), for the brief's safe area. */\nfunction plannedPlacements(nodes: StaticCanvasNode[]): { placements?: string[] } {\n const placements = nodes.find((n) => n.tags?.role === VARIANT_PREFILTER_ROLE)?.params?.placements;\n return Array.isArray(placements) && placements.every((p) => typeof p === \"string\") ? { placements } : {};\n}\n\n/**\n * The content band the canvas's sizes were planned with (`planStaticFormats` over the formats,\n * master shape and placements kept on the prefilter), when `format` is its master: the one\n * region a render at the master must keep every word in, so every cut keeps it too.\n */\nfunction plannedBand(nodes: StaticCanvasNode[], format: string, model: string): { band?: PlannedBand } {\n const params = nodes.find((n) => n.tags?.role === VARIANT_PREFILTER_ROLE)?.params;\n const formats = params?.formats;\n if (!Array.isArray(formats) || formats.length === 0 || !formats.every((f) => typeof f === \"string\")) return {};\n const shape = MASTER_SHAPES.find((s) => s === params?.master_shape);\n const plan = planStaticFormats(model, formats, {\n ...(shape ? { masterShape: shape as MasterShape } : {}),\n ...plannedPlacements(nodes),\n // A canvas made before platforms named its lead records none: its master is re-planned as it was.\n ...(typeof params?.lead === \"string\" ? { lead: params.lead } : {}),\n });\n if (plan.master.format !== format) return {};\n // Re-laid out, no size is cut from the master: its own safe area holds, widened by whatever\n // the fill to its format trims off the render (GPT renders a 4:5 at 3:4).\n if (plan.masterShape === \"relayout\") {\n const band = trimmedRenderBand(adaptPlan(model, format, plan.placements));\n return band ? { band } : {};\n }\n return { band: { area: plan.band, cut: plan.sizes.some((s) => s.from === \"crop\") } };\n}\n\n/** An element slot the spec does not name, given a role from what its node is. */\nfunction unnamedReference(id: string, taken: AdReference[]): AdReference {\n const [prefix, role] = /person|avatar/.test(id)\n ? ([\"PERSON\", \"identity\"] as const)\n : /_sheet$|animal|dog|cat|pet|hero/.test(id)\n ? ([\"ANIMAL\", \"identity\"] as const)\n : /product|package|bottle|box/.test(id)\n ? ([\"PRODUCT\", \"product\"] as const)\n : ([\"PROP\", \"prop\"] as const);\n let n = 1;\n while (taken.some((r) => r.id === `${prefix}_${n}`)) n++;\n return {\n id: `${prefix}_${n}`,\n role,\n slot: id.replace(/_sheet$/, \"\"),\n what: `the ${role === \"identity\" ? \"subject\" : role === \"product\" ? \"product\" : \"object\"} in this picture`,\n };\n}\n\n/**\n * The spec reference an element slot fills: the one naming its slot, else one the spec describes\n * without a picture (a blueprint's product) of the same kind, else a new role-based one. Added to\n * `references` (in place) when it is not there yet.\n */\nfunction referenceFor(id: string, references: AdReference[]): AdReference {\n const slot = id.replace(/_sheet$/, \"\");\n const named = references.find((r) => r.slot === slot || r.slot === id || referenceNodeId(r) === id);\n if (named) return named;\n const fresh = unnamedReference(id, references);\n const kind = (r: AdReference) => r.id.split(\"_\")[0];\n const waiting = references.findIndex((r) => !r.slot && r.role === fresh.role && kind(r) === kind(fresh));\n if (waiting < 0) {\n references.push(fresh);\n return fresh;\n }\n const adopted = { ...(references[waiting] as AdReference), slot };\n references[waiting] = adopted;\n return adopted;\n}\n\n/**\n * What each picture wired into a render is, for the compiler: the ad being re-laid or\n * corrected, the logo, the type specimen, the source ad, or the spec reference whose slot it\n * is (an element the spec does not name gets a role-based one). Returns the spec with those\n * additions and the pictures keyed as the compiler reads them.\n */\nexport function bindBriefImages(\n nodes: StaticCanvasNode[],\n reference: unknown,\n spec: AdSpec,\n): { spec: AdSpec; images: BriefImages } {\n const byId = new Map(nodes.map((n) => [n.id, n] as const));\n const refs: Record<string, string> = {};\n const images: BriefImages = { refs };\n const references = [...spec.references];\n const list = Array.isArray(reference) ? reference : reference === undefined ? [] : [reference];\n for (const ref of list) {\n const id = refId(ref);\n if (!id || typeof ref !== \"string\") continue;\n const kind = pictureKind(id, byId.get(id));\n if (kind !== \"element\") {\n images[kind] = ref;\n continue;\n }\n refs[referenceFor(id, references).id] = ref;\n }\n return { spec: { ...spec, references }, images };\n}\n\n/** What a wired picture is, by the node it comes from. */\nfunction pictureKind(\n id: string,\n target: StaticCanvasNode | undefined,\n): \"layout\" | \"base\" | \"logo\" | \"type\" | \"element\" {\n if (id === \"original\") return \"layout\";\n // A picture made in the graph: a render, a pick, or the variant the checks framed (a grown version's).\n const made = [\"image_generate\", \"image_select\", \"static_prefilter\", \"collect\"];\n if (id === \"previous\" || made.includes(String(target?.type))) return \"base\";\n if (target?.tags?.role === SERIES_LEAD_ROLE) return \"base\";\n if (target?.tags?.role === BRAND_LOGO_ROLE) return \"logo\";\n return target?.type === \"font_specimen\" ? \"type\" : \"element\";\n}\n\n/** Rewrite one render node to its compiled brief. Returns whether anything changed. */\nfunction applyBrief(node: StaticCanvasNode, prompt: string, reference: string[]): boolean {\n const before = JSON.stringify([node.params?.prompt, node.inputs]);\n node.params = { ...node.params, prompt };\n const inputs: Record<string, unknown> = { ...node.inputs };\n delete inputs.blueprint;\n if (reference.length > 0) inputs.reference = reference;\n else delete inputs.reference;\n node.inputs = inputs;\n return JSON.stringify([node.params.prompt, node.inputs]) !== before;\n}\n\nconst profileOf = (node: StaticCanvasNode) => imageProfileFor(String(node.params?.model ?? \"\")) ?? GPT_IMAGE_25_PROFILE;\n\n/**\n * Built on the reference's concept, a first render sees the reference for its structure (C5) when\n * what won is the whole ad or its layout (`seesReferenceStructure`).\n */\nfunction structureRef(nodes: StaticCanvasNode[], spec: AdSpec): string | undefined {\n return seesReferenceStructure(spec) && nodes.some((n) => n.id === \"original\" && n.type === \"ingest\")\n ? \"$ref:original.asset\"\n : undefined;\n}\n\n/** The pictures a render is wired to, the reference's structure added to a first render. */\nfunction referencesOf(render: { node: StaticCanvasNode; job: string }, structure: string | undefined): unknown[] {\n const wired = render.node.inputs?.reference;\n const list: unknown[] = Array.isArray(wired) ? wired : wired === undefined ? [] : [wired];\n return render.job === \"generate\" && structure && !list.includes(structure) ? [...list, structure] : list;\n}\n\n/**\n * Compile every render of a static canvas from its prompt.json, in place: each take, each\n * re-lay, the judge's criteria and the type specimen's text. Returns how many nodes changed\n * (0 for a canvas that is not a static ad, and for one already up to date). Throws when an\n * ad spec in prompt.json is invalid: the caller stops before anything bills.\n */\nexport function projectStaticBriefs(\n canvas: unknown,\n promptJson: unknown,\n /** The company's rules this ad is held to: the ones a picture can keep reach every take and the judge. */\n rules: readonly CreativeRule[] = [],\n): number {\n const nodes = nodesOf(canvas);\n if (!isStaticCanvas(nodes)) return 0;\n const spec = readAdSpec(promptJson);\n const series = seriesOf(canvas);\n // On the plate shape a variant is a picture without the ad's words (`projectFormatBriefs`): only\n // the judge's criteria come from the ad's brief here.\n const plate = isPlateCanvas(canvas);\n const all = staticRenders(nodes);\n // An ad of a series renders the lead's picture with its words replaced: its variant is that edit.\n const renders = (plate ? [] : all).map((r) =>\n series && r.job === \"generate\" ? { ...r, job: \"series\" as const } : r,\n );\n let changed = 0;\n let judgeFrom: string | undefined;\n const structure = structureRef(nodes, spec);\n const judged = plate ? all.find((r) => r.job === \"generate\") : undefined;\n if (judged) {\n const bound = bindBriefImages(nodes, referencesOf(judged, structure), spec);\n // Read as the picture is briefed (`projectFormatBriefs`): it carries no designed words, so neither the\n // logo file nor the type specimen, whichever order the two are compiled in.\n const { logo: _logo, type: _type, base: _base, ...images } = bound.images;\n judgeFrom = compileStaticBrief(bound.spec, undefined, judged.format, undefined, profileOf(judged.node), {\n job: \"generate\",\n images,\n ...plannedPlacements(nodes),\n }).prompt;\n }\n for (const render of renders) {\n const bound = bindBriefImages(nodes, referencesOf(render, structure), spec);\n const profile = profileOf(render.node);\n const compile = (variant: number) =>\n compileStaticBrief(bound.spec, undefined, render.format, undefined, profile, {\n job: render.job,\n variant,\n ...(series && render.job === \"series\"\n ? { instruction: seriesWordsInstruction(series.copy, spec.copy, wordsLanguage(series)) }\n : {}),\n images: bound.images,\n ...(rules.length > 0 ? { rules } : {}),\n ...plannedPlacements(nodes),\n ...(render.job === \"generate\"\n ? plannedBand(nodes, render.format, String(render.node.params?.model ?? \"\"))\n : {}),\n });\n const brief = compile(render.variant);\n // The logo file is placed on the size afterwards: the render draws none and keeps its slot plain.\n const slot = logoSlotLineFor(nodes, render.format, String(render.node.params?.aspect_ratio ?? render.format));\n if (\n applyBrief(\n render.node,\n slot ? `${brief.prompt}\\n\\n${slot}` : brief.prompt,\n brief.references.map((r) => r.ref),\n )\n )\n changed++;\n if (render.job === \"generate\") judgeFrom ??= compile(0).prompt;\n }\n if (judgeFrom) changed += projectJudges(nodes, spec, judgeFrom, rules);\n changed += projectHandWrittenCopy(nodes, spec, new Set(all.map((r) => r.node)));\n return changed + projectSpecimens(nodes, spec) + projectAdaptCopy(nodes, spec) + projectPlacementCopy(nodes, spec);\n}\n\n/**\n * The steps that place a size clear of an interface (`static_safe_fit`, `static_place`) are told\n * the ad's copy and the role of each line, and the brand's name and the words its logo prints\n * (role `logo`), so they move the ad for its own words and logo, never for what the scene prints\n * (`must-show.ts`). Returns how many nodes changed.\n */\nexport function projectPlacementCopy(nodes: StaticCanvasNode[], spec: Pick<AdSpec, \"copy\" | \"brand\">): number {\n // The brand's name and the words its logo prints count as the logo, as the review counts them.\n const logoWords = [...new Set([...(spec.brand?.name ? [spec.brand.name] : []), ...(spec.brand?.lockup ?? [])])];\n const copy = [\n ...spec.copy.map((l) => ({ text: l.text, ...(l.role ? { role: l.role } : {}) })),\n ...logoWords.map((text) => ({ text, role: \"logo\" })),\n ];\n let changed = 0;\n for (const step of nodes.filter((n) => n.type === \"static_safe_fit\" || n.type === \"static_place\")) {\n const before = JSON.stringify(step.params?.copy);\n const params: Record<string, unknown> = { ...step.params };\n if (copy.length > 0) params.copy = copy;\n else delete params.copy;\n step.params = params;\n if (JSON.stringify(params.copy) !== before) changed++;\n }\n return changed;\n}\n\n/**\n * The reframe of the master is told the exact words it must keep, each once, so a size it\n * adapts cannot drift from the master's copy (the model reads them off the picture otherwise).\n */\nfunction projectAdaptCopy(nodes: StaticCanvasNode[], spec: AdSpec): number {\n const copy = spec.copy.map((l) => l.text);\n let changed = 0;\n for (const adapt of nodes.filter((n) => n.type === \"image_aspect_adapt\" && n.tags?.role === STATIC_ADAPT_ROLE)) {\n const before = JSON.stringify(adapt.params?.copy);\n const params: Record<string, unknown> = { ...adapt.params };\n if (copy.length > 0) params.copy = copy;\n else delete params.copy;\n adapt.params = params;\n if (JSON.stringify(params.copy) !== before) changed++;\n }\n return changed;\n}\n\n/**\n * What the variant checks read of the spec. A logo is checked for only when the model draws it from\n * its file: without one none is drawn (never a stand-in), and a logo file placed on every size\n * afterwards is drawn by no variant, whose master instead keeps its slot plain (`logo_slot`).\n */\nfunction variantChecks(nodes: StaticCanvasNode[], spec: AdSpec): StaticChecks | null {\n const checks = staticChecksOf(spec);\n if (!checks) return null;\n const placed = nodes.some((n) => n.tags?.role === LOGO_COMPOSITE_ROLE);\n const master = staticMasterFormat({ nodes });\n const slot = placed && master ? logoSlotSpanFor(nodes, master) : null;\n return {\n ...checks,\n logo: checks.logo && !placed && nodes.some((n) => n.tags?.role === BRAND_LOGO_ROLE),\n ...(slot ? { logo_slot: slot } : {}),\n };\n}\n\n/** The judge's criteria (on the prefilter, or an older graph's judge node): the brief the takes render from, the brand and the viewer; no temperature. */\nfunction projectJudges(\n nodes: StaticCanvasNode[],\n spec: AdSpec,\n brief: string,\n rules: readonly CreativeRule[] = [],\n): number {\n const criteria = judgeBrief(brief, {\n ...(spec.brand?.name ? { brand: spec.brand.name } : {}),\n ...(spec.viewer?.who ? { viewer: spec.viewer.who } : {}),\n mechanisms: spec.mechanism.map((m) => m.device),\n rules,\n });\n let changed = 0;\n // The prefilter asks the judge on a tie (the current graph has no judge node), and reads only\n // what its checks need of prompt.json, so a note-only edit changes no step (E3).\n const checks = variantChecks(nodes, spec);\n for (const prefilter of nodes.filter((n) => n.tags?.role === VARIANT_PREFILTER_ROLE)) {\n const before = JSON.stringify([prefilter.params, prefilter.inputs]);\n const params: Record<string, unknown> = { ...prefilter.params, ...(checks ? { checks } : {}) };\n if (params.judge_model) params.judge_prompt = criteria;\n prefilter.params = params;\n if (checks && prefilter.inputs && \"spec\" in prefilter.inputs) {\n const { spec: _spec, ...rest } = prefilter.inputs;\n prefilter.inputs = rest;\n }\n if (JSON.stringify([prefilter.params, prefilter.inputs]) !== before) changed++;\n }\n for (const pick of nodes.filter((n) => n.type === \"image_select\")) {\n const before = JSON.stringify([pick.params, pick.inputs]);\n const params: Record<string, unknown> = { ...pick.params, prompt: criteria };\n // Gemini 3 wants its default temperature (prompting-google-gemini-image.md §7).\n delete params.temperature;\n pick.params = params;\n const inputs: Record<string, unknown> = { ...pick.inputs };\n delete inputs.blueprint;\n pick.inputs = inputs;\n if (JSON.stringify([pick.params, pick.inputs]) !== before) changed++;\n }\n return changed;\n}\n\n/**\n * A render written by hand (not one of the scaffold's) keeps its own prompt; only its copy\n * block is re-read from prompt.json, as it always was.\n */\nfunction projectHandWrittenCopy(nodes: StaticCanvasNode[], spec: AdSpec, compiled: Set<StaticCanvasNode>): number {\n const directive = textFidelityDirective(\n spec.copy.map((l) => l.text),\n nodes.some((n) => n.type === \"font_specimen\"),\n );\n let changed = 0;\n for (const node of nodes) {\n const current = node.params?.prompt;\n if (node.type !== \"image_generate\" || compiled.has(node) || typeof current !== \"string\") continue;\n const next = replaceCopyDirective(current, directive);\n if (next === current) continue;\n node.params = { ...node.params, prompt: next };\n changed++;\n }\n return changed;\n}\n\n/** The type specimen shows the lines set in the brand's face (every line when none is). */\nfunction projectSpecimens(nodes: StaticCanvasNode[], spec: AdSpec): number {\n const designed = withRenderedLettering(spec)\n .copy.filter((l) => l.lettering === \"designed\")\n .map((l) => l.text);\n const text = specimenText(designed.length > 0 ? designed : spec.copy.map((l) => l.text));\n let changed = 0;\n for (const specimen of nodes.filter((n) => n.type === \"font_specimen\")) {\n const current = specimen.params?.text;\n if ((typeof current === \"string\" && current.includes(\"{{\")) || current === text) continue;\n specimen.params = { ...specimen.params, text };\n changed++;\n }\n return changed;\n}\n\n/**\n * The ids of the nodes whose prompt is compiled from prompt.json on every run (the takes,\n * the re-lays, the judge): a prompt set on one of them by hand would be overwritten.\n */\nexport function compiledPromptNodeIds(canvas: unknown): Set<string> {\n const nodes = nodesOf(canvas);\n if (!isStaticCanvas(nodes)) return new Set();\n return new Set([\n ...staticRenders(nodes).map((r) => r.node.id),\n ...nodes.filter((n) => n.type === \"image_select\").map((n) => n.id),\n ]);\n}\n\n/**\n * The correction render that replaces the takes on `--fix`: the template take's model and\n * params, `previous` first among its pictures (the source ad dropped), and a brief that\n * changes only what the instruction says.\n */\nexport function fixBriefNode(\n canvas: unknown,\n template: StaticCanvasNode,\n promptJson: unknown,\n opts: {\n instruction: string;\n previous: string;\n format?: string;\n drop?: ReadonlySet<string>;\n /** What the person rejected in earlier versions of this ad, in their words (`readCaseFile`). */\n rejected?: readonly string[];\n /** The company's rules this ad is held to (`compileStaticBrief`). */\n rules?: readonly CreativeRule[];\n },\n): StaticCanvasNode {\n const nodes = nodesOf(canvas);\n const spec = readAdSpec(promptJson);\n const templateRefs = template.inputs?.reference;\n // A series ad is corrected from its own picture: the lead's it was made from is no longer one to copy.\n const leads = new Set(nodes.filter((n) => n.tags?.role === SERIES_LEAD_ROLE).map((n) => n.id));\n const kept = (Array.isArray(templateRefs) ? templateRefs : []).filter(\n (r): r is string =>\n typeof r === \"string\" && refId(r) !== \"original\" && !opts.drop?.has(refId(r) ?? \"\") && !leads.has(refId(r) ?? \"\"),\n );\n const bound = bindBriefImages(nodes, [opts.previous, ...kept], spec);\n const format = opts.format ?? renderFormat(nodes) ?? \"9:16\";\n const brief = compileStaticBrief(bound.spec, undefined, format, undefined, profileOf(template), {\n job: \"fix\",\n instruction: opts.instruction,\n ...(opts.rejected && opts.rejected.length > 0 ? { rejected: opts.rejected } : {}),\n ...(opts.rules && opts.rules.length > 0 ? { rules: opts.rules } : {}),\n images: bound.images,\n ...plannedPlacements(nodes),\n ...plannedBand(nodes, format, String(template.params?.model ?? \"\")),\n });\n const inputs: Record<string, unknown> = { ...template.inputs, reference: brief.references.map((r) => r.ref) };\n delete inputs.blueprint;\n return { ...template, id: \"ad\", inputs, params: { ...template.params, prompt: brief.prompt } };\n}\n","/**\n * The briefs of a static ad's re-laid-out sizes (`static_adapt_format`), compiled from\n * prompt.json on every run, the way `projectStaticBriefs` compiles the variants': each size\n * is handed the chosen ad, the logo file the model draws and the brief for its own frame\n * (`adaptBrief`). Its own module so the render graph (`static-topology.ts`) can read the\n * adapt plan without importing the brief projection.\n */\nimport { imageProfileFor } from \"../lib/prompt-profiles.ts\";\nimport { type AdSpec, readAdSpec } from \"./static-ad-spec.ts\";\nimport { adaptBrief, adaptPlan, STATIC_ADAPT_FORMAT_ROLE } from \"./static-adapt.ts\";\nimport { compileStaticBrief } from \"./static-brief.ts\";\nimport { logoSlotLineFor, withoutLogoInZones } from \"./static-logo-briefs.ts\";\nimport {\n BRAND_LOGO_ROLE,\n bindBriefImages,\n type SeriesOf,\n type StaticCanvasNode,\n seriesOf,\n wordsLanguage,\n} from \"./static-render-briefs.ts\";\nimport { seriesWordsInstruction } from \"./static-series.ts\";\nimport {\n formatSlug,\n LOGO_COMPOSITE_ROLE,\n SERIES_LEAD_ROLE,\n STATIC_VARIANT_CALL_ROLE,\n STATIC_VARIANTS_ROLE,\n} from \"./static-topology.ts\";\n\ntype Node = {\n id?: unknown;\n type?: unknown;\n params?: Record<string, unknown>;\n inputs?: Record<string, unknown>;\n tags?: { role?: unknown };\n};\n\n/** `adapt_9x16` → `9:16`, `adapt_1_91x1` → `1.91:1`: the format a re-lay node's id names. */\nexport function formatOfAdaptId(id: string): string | null {\n const m = id.match(/^adapt_(\\d+(?:_\\d+)?)x(\\d+(?:_\\d+)?)$/);\n return m ? `${m[1]?.replace(\"_\", \".\")}:${m[2]?.replace(\"_\", \".\")}` : null;\n}\n\n/** The re-lay nodes of a canvas, each with the format it delivers. */\nexport function adaptNodes(canvas: unknown): Array<{ node: Node & { id: string }; format: string }> {\n const nodes = (canvas as { nodes?: unknown } | null)?.nodes;\n if (!Array.isArray(nodes)) return [];\n return (nodes as Node[]).flatMap((node) => {\n if (node?.type !== \"image_generate\" || node.tags?.role !== STATIC_ADAPT_FORMAT_ROLE || typeof node.id !== \"string\")\n return [];\n const format = formatOfAdaptId(node.id);\n return format ? [{ node: node as Node & { id: string }, format }] : [];\n });\n}\n\n/**\n * Compile each re-laid-out size's brief from prompt.json, in place: the chosen ad first, the\n * logo file the model draws (when the spec shows a logo), the format's own frame and safe\n * area for the canvas's planned placements. Returns how many nodes changed.\n */\nexport function projectAdaptBriefs(canvas: unknown, promptJson: unknown): number {\n const adapts = adaptNodes(canvas);\n if (adapts.length === 0) return 0;\n const nodes = (canvas as { nodes: Node[] }).nodes;\n const { spec, refs } = ownPictures(nodes, readAdSpec(promptJson));\n const logo = drawnLogo(nodes);\n const placements = plannedPlacements(nodes);\n const series = seriesOf(canvas);\n let changed = 0;\n for (const { node, format } of adapts) {\n const model = String(node.params?.model ?? \"\");\n const profile = imageProfileFor(model);\n if (!profile) continue;\n const leadSize = series ? leadSizeRef(nodes, format) : undefined;\n const brief =\n series && leadSize\n ? seriesSizeBrief(spec, profile, { series, format, base: leadSize, logo, placements })\n : relayBrief(spec, profile, { model, format, placements, logo, refs });\n const reference = brief.references.map((r) => r.ref);\n const prompt = withLogoSlot(brief.prompt, nodes, format, node.params?.aspect_ratio);\n if (node.params?.prompt === prompt && JSON.stringify(node.inputs?.reference) === JSON.stringify(reference))\n continue;\n node.params = { ...node.params, prompt };\n node.inputs = { ...node.inputs, reference };\n changed++;\n }\n return changed;\n}\n\n/**\n * The product and the people (or animal) the variants were made from, by the spec's reference\n * id: every size is handed them, so the label and the faces stay the ones in the pictures. The\n * final comparison's re-laid sizes redrew a bottle's label and changed a man's face (BENCH.md § \"Final\").\n */\nfunction ownPictures(nodes: Node[], spec: AdSpec): { spec: AdSpec; refs: Record<string, string> } {\n const variant = nodes.find((n) => n.tags?.role === STATIC_VARIANT_CALL_ROLE || n.tags?.role === STATIC_VARIANTS_ROLE);\n if (!variant) return { spec, refs: {} };\n const bound = bindBriefImages(nodes as StaticCanvasNode[], variant.inputs?.reference, spec);\n const kept = new Set(bound.spec.references.filter((r) => r.role !== \"prop\").map((r) => r.id));\n const refs = Object.fromEntries(Object.entries(bound.images.refs ?? {}).filter(([id]) => kept.has(id)));\n return { spec: bound.spec, refs };\n}\n\n/** One size re-laid out from the chosen picture for its own frame. */\nfunction relayBrief(\n spec: AdSpec,\n profile: NonNullable<ReturnType<typeof imageProfileFor>>,\n opts: {\n model: string;\n format: string;\n placements: string[] | undefined;\n logo: string | undefined;\n refs: Record<string, string>;\n },\n) {\n return adaptBrief(spec, profile, {\n plan: adaptPlan(opts.model, opts.format, opts.placements),\n images: { base: MASTER_REF, ...(opts.logo ? { logo: opts.logo } : {}), refs: opts.refs },\n });\n}\n\n/** A re-lay's brief with the slot its size's logo composite places the file in kept plain, and no logo drawn. */\nfunction withLogoSlot(prompt: string, nodes: Node[], format: string, drawn: unknown): string {\n const slot = logoSlotLineFor(nodes, format, typeof drawn === \"string\" ? drawn : format);\n return slot ? `${withoutLogoInZones(prompt)}\\n\\n${slot}` : prompt;\n}\n\n/** The lead's own picture of `format`, on an ad of a series that has it (`lead_ad_9x16`). */\nfunction leadSizeRef(nodes: Node[], format: string): string | undefined {\n const id = `lead_ad_${formatSlug(format)}`;\n return nodes.some((n) => n.id === id && n.tags?.role === SERIES_LEAD_ROLE) ? `$ref:${id}.asset` : undefined;\n}\n\n/**\n * One size of an ad of a series: the lead's own picture of that size with the same words replaced\n * as on this ad's picture. The lead's size was already laid out for its frame, so nothing is\n * re-laid: each ad of the series keeps the lead's layout in every size.\n */\nfunction seriesSizeBrief(\n spec: AdSpec,\n profile: NonNullable<ReturnType<typeof imageProfileFor>>,\n opts: { series: SeriesOf; format: string; base: string; logo: string | undefined; placements: string[] | undefined },\n) {\n return compileStaticBrief(spec, undefined, opts.format, undefined, profile, {\n job: \"series\",\n instruction: seriesWordsInstruction(opts.series.copy, spec.copy, wordsLanguage(opts.series)),\n images: { base: opts.base, ...(opts.logo ? { logo: opts.logo } : {}) },\n ...(opts.placements ? { placements: opts.placements } : {}),\n });\n}\n\n/** What every re-laid-out size is made from: the chosen picture at the master's pixels. */\nconst MASTER_REF = \"$ref:master.image\";\n\n/** The brand's logo file as the re-lays are handed it: none when the canvas composites it on every size instead. */\nfunction drawnLogo(nodes: Node[]): string | undefined {\n if (nodes.some((n) => n.tags?.role === LOGO_COMPOSITE_ROLE)) return undefined;\n const logo = nodes.find((n) => n.type === \"ingest\" && n.tags?.role === BRAND_LOGO_ROLE);\n return typeof logo?.id === \"string\" ? `$ref:${logo.id}.asset` : undefined;\n}\n\n/** The ad set's placements the canvas's sizes were planned with (kept on the prefilter). */\nexport function plannedPlacements(nodes: Node[]): string[] | undefined {\n const placements = nodes.find((n) => n.type === \"static_prefilter\")?.params?.placements;\n return Array.isArray(placements) && placements.every((p) => typeof p === \"string\") ? placements : undefined;\n}\n","/**\n * Where a static ad runs, and the sizes that follow from it.\n *\n * The platforms an ad runs in decide its sizes (`@baker/canvas-contract` `deliveryPlan`): Meta\n * 4:5 + 9:16, LinkedIn 1:1, TikTok 9:16. This module turns the platforms named (by a flag, the\n * idea, the creative's `_definition.md`, or the ad set it targets) into that plan, and refuses\n * when nothing names one rather than defaulting to Meta. Pure.\n */\nimport { AD_PLACEMENTS, AD_PLATFORMS, deliveryPlan } from \"@baker/canvas-contract\";\nimport { parseDocument } from \"yaml\";\n\n/** The sizes a static ad is made in and where they run: what the scaffold builds the canvas from. */\nexport type StaticDelivery = {\n /** The platforms (or placement ids) named, the main one first. */\n platforms: string[];\n /** The size designed first; every other size is re-laid out from it. */\n lead: string;\n /** Every delivered ratio, lead first. */\n formats: string[];\n /** The placements those sizes serve: each keeps clear of their interfaces. */\n placements: string[];\n /** Fixed-pixel banners the platforms require, never made from the picture. */\n banners: string[];\n};\n\n/** The delivery of these platforms (or exactly the sizes `asked`), ignoring any name or size it refuses. */\nexport function staticDeliveryOf(platforms: readonly string[], asked?: readonly string[]): StaticDelivery {\n const plan = deliveryPlan(platforms, asked);\n return {\n platforms: platforms.map((p) => p.trim().toLowerCase()).filter((p) => p && !plan.unknown.includes(p)),\n lead: plan.lead,\n formats: plan.formats.map((f) => f.format),\n placements: plan.placements,\n banners: plan.banners.map((b) => b.format),\n };\n}\n\n/** What a `_definition.md` says about where its ad runs. */\nexport type DefinitionDelivery = { platforms?: string[]; platform?: string; formats?: string[]; targetAdSet?: string };\n\n/**\n * Read where a `_definition.md` says its ad runs. Null when it has no readable front matter\n * (none, or invalid YAML mid-edit): nothing is planned from half a file.\n */\nexport function parseDefinitionDelivery(raw: string): DefinitionDelivery | null {\n const match = raw.match(/^---\\r?\\n([\\s\\S]*?\\r?\\n)?---/);\n if (!match) return null;\n const doc = parseDocument(match[1] ?? \"\");\n if (doc.errors.length > 0) return null;\n const data = (doc.toJS() ?? {}) as Record<string, unknown>;\n const list = (value: unknown) =>\n Array.isArray(value)\n ? value.filter((v): v is string => typeof v === \"string\" && v.trim() !== \"\").map((v) => v.trim())\n : [];\n const text = (value: unknown) =>\n typeof value === \"string\" || typeof value === \"number\" ? String(value).trim() || undefined : undefined;\n const platforms = list(data.platforms);\n const formats = list(data.formats);\n const platform = text(data.platform);\n const targetAdSet = text(data.targetAdSet);\n return {\n ...(platforms.length > 0 ? { platforms } : {}),\n ...(platform ? { platform } : {}),\n ...(formats.length > 0 ? { formats } : {}),\n ...(targetAdSet ? { targetAdSet } : {}),\n };\n}\n\nexport type DeliverySource = \"flag\" | \"idea\" | \"definition\" | \"legacy_definition\" | \"adset\";\n\n/** A delivery, where its platforms were read from, and what the agent should be told about it. */\nexport type ResolvedDelivery = StaticDelivery & { source: DeliverySource; notes: string[] };\n\nexport type DeliveryRefusal = {\n code: \"platform_required\" | \"invalid_platforms\" | \"invalid_formats\";\n message: string;\n fix: string;\n};\n\nexport type DeliveryInput = {\n /** `--platforms a,b`: where the ad runs, the main one first. */\n platformsFlag?: string;\n /** The retired `--platform <definition platform>`. */\n legacyPlatform?: string;\n /** The retired `--placements <preset>`. */\n legacyPlacements?: string;\n /** The retired `--aspect`: a size added when the platforms show it, never a narrowing. */\n aspect?: string;\n /** `--formats a,b`: exactly the sizes to deliver. */\n formatsFlag?: string;\n /** The idea's `platforms`. */\n idea?: readonly string[];\n definition?: DefinitionDelivery | null;\n /** The Meta ad set the ad is for (`--target-adset`). */\n targetAdSet?: string;\n /** The platforms of the ad accounts connected, named in the refusal's fix (never chosen from). */\n connected?: readonly string[];\n};\n\n/** A `_definition.md` platform (the collection's coarse enum) as the catalog's names. */\nconst DEFINITION_PLATFORM: Record<string, string[]> = {\n meta: [\"meta\"],\n google: [\"google_demandgen\"],\n linkedin: [\"linkedin\"],\n tiktok: [\"tiktok\"],\n youtube: [\"youtube\"],\n x: [\"x\"],\n other: [],\n};\n\n/** The retired `--placements` presets as the catalog's names. */\nconst LEGACY_PRESET: Record<string, string[]> = {\n meta_feed: [\"meta_feed\"],\n meta_feed_stories: [\"meta\"],\n meta_all: [\"meta\", \"meta_right_column\"],\n linkedin: [\"linkedin\"],\n google_search: [\"google_search\"],\n google_demandgen: [\"google_demandgen\"],\n tiktok: [\"tiktok\"],\n youtube: [\"youtube\"],\n};\n\nconst listOf = (flag: string | undefined) =>\n (flag ?? \"\")\n .split(\",\")\n .map((n) => n.trim())\n .filter(Boolean);\n\ntype FoundPlatforms = { platforms: string[]; source: DeliverySource; notes: string[] };\n\n/**\n * Where the ad runs, from the first thing that says so: `--platforms`, the retired `--platform`\n * and `--placements`, the definition's `platforms` (the creative's own record, chosen for it), the\n * idea, the definition's single legacy `platform`, the Meta ad set it targets. Nothing saying so\n * is a refusal, never a default: the sizes depend on it.\n */\nfunction platformsOf(input: DeliveryInput): FoundPlatforms | DeliveryRefusal | null {\n const flag = listOf(input.platformsFlag);\n if (flag.length > 0) return { platforms: flag, source: \"flag\", notes: [] };\n return retiredFlagPlatforms(input) ?? recordedPlatforms(input);\n}\n\n/** The retired `--platform` and `--placements`, mapped onto platforms with a note to use `--platforms`. */\nfunction retiredFlagPlatforms(input: DeliveryInput): FoundPlatforms | DeliveryRefusal | null {\n const legacy = input.legacyPlatform?.trim();\n const fromPlatform = legacy ? (DEFINITION_PLATFORM[legacy] ?? [legacy]) : [];\n if (fromPlatform.length > 0)\n return {\n platforms: fromPlatform,\n source: \"flag\",\n notes: [`--platform is retired: pass --platforms ${fromPlatform.join(\",\")}.`],\n };\n const preset = input.legacyPlacements?.trim();\n if (!preset) return null;\n if (preset === \"none\") {\n return {\n code: \"invalid_platforms\",\n message: \"--placements none is retired: one size is a placement or a size asked for, not a missing platform.\",\n fix: \"Name the placement (--platforms meta_stories for a 9:16 only), or the sizes (--platforms meta --formats 4:5).\",\n };\n }\n const mapped = LEGACY_PRESET[preset];\n if (!mapped) {\n return {\n code: \"invalid_platforms\",\n message: `--placements \"${preset}\" is no placement set.`,\n fix: `Pass --platforms instead (any of ${AD_PLATFORMS.join(\", \")}).`,\n };\n }\n return {\n platforms: mapped,\n source: \"flag\",\n notes: [`--placements is retired: pass --platforms ${mapped.join(\",\")}.`],\n };\n}\n\n/** What the definition, the idea or the ad set already say. */\nfunction recordedPlatforms(input: DeliveryInput): FoundPlatforms | null {\n const definition = input.definition;\n if (definition?.platforms && definition.platforms.length > 0)\n return { platforms: [...definition.platforms], source: \"definition\", notes: [] };\n if (input.idea && input.idea.length > 0) return { platforms: [...input.idea], source: \"idea\", notes: [] };\n const mapped = definition?.platform ? (DEFINITION_PLATFORM[definition.platform] ?? []) : [];\n if (mapped.length > 0) return { platforms: mapped, source: \"legacy_definition\", notes: [] };\n if (input.targetAdSet || definition?.targetAdSet) return { platforms: [\"meta\"], source: \"adset\", notes: [] };\n return null;\n}\n\n/** The refusal when nothing says where the ad runs. */\nexport function platformRequired(connected: readonly string[] = []): DeliveryRefusal {\n const accounts =\n connected.length > 0 ? ` Connected ad accounts: ${connected.join(\", \")} (choices to offer, not an answer).` : \"\";\n return {\n code: \"platform_required\",\n message:\n \"Nothing says where this ad runs, and its sizes depend on it (Meta 4:5 + 9:16, LinkedIn 1:1, TikTok 9:16).\",\n fix: `Take it from the person's request, the idea, or the ad set it is for, and pass --platforms linkedin (meta, tiktok, google_demandgen, …; several comma-separated, the main one first).${accounts} If none of them names a platform, ask the person once, for every ad at once; never assume one, even when only one ad account is connected.`,\n };\n}\n\n/** A catalog name (a platform, or a placement id) as the platform a definition records. */\nconst platformOfName = (name: string) => AD_PLACEMENTS.find((p) => p.id === name)?.platform ?? name;\n\n/**\n * The sizes the definition records, when it records them for these same platforms: a size asked\n * for once (a 4:5 alone, LinkedIn's 4:5) stays asked on every rebuild until `--formats` changes it.\n */\nfunction recordedFormats(platforms: readonly string[], definition: DefinitionDelivery | null | undefined) {\n const named = definition?.platforms;\n if (!named || !definition?.formats || definition.formats.length === 0) return undefined;\n const ours = new Set(platforms.map(platformOfName));\n const same = ours.size === new Set(named).size && named.every((p) => ours.has(p));\n if (!same) return undefined;\n return deliveryPlan(platforms, definition.formats).refused.length === 0 ? definition.formats : undefined;\n}\n\nconst sameSizes = (a: readonly string[], b: readonly string[]) =>\n a.length === b.length && a.every((f) => b.includes(f));\n\n/** The placements a narrower ask leaves cropped, said the way a person names them. */\nfunction croppedNote(formats: readonly string[], cropped: readonly string[]): string[] {\n if (cropped.length === 0) return [];\n const names = cropped.map((id) => AD_PLACEMENTS.find((p) => p.id === id)?.name ?? id);\n const placements = names.length > 1 ? `${names.slice(0, -1).join(\", \")} and ${names.at(-1)}` : names[0];\n return [`Only the sizes asked for are made (${formats.join(\", \")}): ${placements} will show a cropped picture.`];\n}\n\n/**\n * The sizes asked for other than the platforms' own: `--formats`, else the ones the definition\n * records, else the platforms' with a retired `--aspect` they show added; undefined for the\n * platforms' own. What it keeps or leaves out is said in `notes`.\n */\nfunction askedFormats(\n input: DeliveryInput,\n platforms: readonly string[],\n planned: readonly string[],\n notes: string[],\n): string[] | undefined {\n const asked = listOf(input.formatsFlag);\n if (asked.length > 0) return asked;\n const aspect = input.aspect?.trim();\n const recorded = aspect ? undefined : recordedFormats(platforms, input.definition);\n if (recorded && !sameSizes(recorded, planned)) {\n notes.push(`Keeps the sizes _definition.md records (${recorded.join(\", \")}); pass --formats to change them.`);\n return [...recorded];\n }\n if (!aspect || planned.includes(aspect)) return undefined;\n if (deliveryPlan(platforms, [aspect]).refused.length === 0) return [...planned, aspect];\n notes.push(`--aspect ${aspect} is not a size ${platforms.join(\", \")} shows, so it is left out.`);\n return undefined;\n}\n\n/**\n * Where a static ad runs and the sizes it is made in, resolved before anything is billed.\n * Pure: the caller reads the flags, the idea and the definition, and the connected accounts.\n */\nexport function resolveDelivery(\n input: DeliveryInput,\n): { ok: true; delivery: ResolvedDelivery } | { ok: false; error: DeliveryRefusal } {\n const found = platformsOf(input);\n if (found === null) return { ok: false, error: platformRequired(input.connected) };\n if (\"code\" in found) return { ok: false, error: found };\n const plan = deliveryPlan(found.platforms);\n if (plan.unknown.length > 0) {\n return {\n ok: false,\n error: {\n code: \"invalid_platforms\",\n message: `${plan.unknown.join(\", \")} is no platform here.`,\n fix: `Use any of: ${AD_PLATFORMS.join(\", \")} (or a placement id such as meta_stories).`,\n },\n };\n }\n if (plan.formats.length === 0) {\n return {\n ok: false,\n error: {\n code: \"invalid_platforms\",\n message: `${found.platforms.join(\",\")} requires only fixed-size banners (${plan.banners.map((b) => b.format).join(\", \")}), which are never made from the picture.`,\n fix: \"Add a platform with a feed or story size (meta, google_display, …).\",\n },\n };\n }\n const notes = [...found.notes];\n const formats = askedFormats(\n input,\n found.platforms,\n plan.formats.map((f) => f.format),\n notes,\n );\n const sized = formats ? deliveryPlan(found.platforms, formats) : plan;\n if (sized.refused.length > 0) {\n return {\n ok: false,\n error: {\n code: \"invalid_formats\",\n message: `${sized.refused.map((r) => r.why).join(\"; \")}.`,\n fix: `Ask only for sizes ${found.platforms.join(\", \")} shows: ${plan.formats.map((f) => f.format).join(\", \")} by default.`,\n },\n };\n }\n const delivered = staticDeliveryOf(found.platforms, formats);\n return {\n ok: true,\n delivery: {\n ...delivered,\n source: found.source,\n notes: [...notes, ...croppedNote(delivered.formats, sized.cropped)],\n },\n };\n}\n\n/** Meta's apps and surfaces, and \"Meta\" with an ads word after it or a place word before it (\"en Meta\", \"Meta Ads\"). */\nconst META_SURFACES =\n /\\b(?:facebook|instagram|insta|reels?|meta\\s+(?:ads?|ad sets?|campaigns?|business|advantage\\+?|feeds?|placements?))\\b/i;\n/**\n * Meta's apps as people abbreviate them (IG, FB), and \"Meta\" where an ad runs (\"en Meta\"). Never \"Stories\" alone: a\n * case study's \"Customer Stories\" names no platform, and Snapchat has Stories too (review, Oct 2026).\n */\nconst META_SHORT = /\\b(?:IG|FB)\\b|\\b(?:[Ee]n|[Oo]n|[Ii]n|[Ee]m|[Vv]ia|[Tt]hrough|[Aa]cross)\\s+Meta\\b/;\n/** What makes \"meta\" a goal in Spanish or Portuguese (\"su meta\", \"a meta do mês\"), said just before it. */\nconst GOAL_BEFORE =\n /\\b(?:la|una|nuestra|mi|tu|su|esta|esa|cada|otra|alcanzar|cumplir|lograr|a|uma|nossa|minha|sua|essa|bater|atingir)\\s+$/i;\n\n/**\n * Whether the words name Meta, the platform: one of its apps or surfaces, or \"Meta\" capitalised and\n * not said as a goal. Lowercase \"meta\" and \"Metas\" are the Spanish and Portuguese word for a goal\n * (review, Oct 2026: ideas naming no platform were built for Meta from \"su meta de ahorro\"). Pure.\n */\nfunction namesMeta(text: string): boolean {\n if (META_SURFACES.test(text) || META_SHORT.test(text)) return true;\n return [...text.matchAll(/\\bMeta\\b/g)].some((m) => !GOAL_BEFORE.test(text.slice(0, m.index)));\n}\n\n/** The words that name a platform where an ad runs (never Google: \"Google reviews\" is no campaign). */\nconst PLATFORM_WORDS: ReadonlyArray<[string, (text: string) => boolean]> = [\n [\"linkedin\", (t) => /\\blinked\\s?in\\b/i.test(t)],\n [\"meta\", namesMeta],\n [\"tiktok\", (t) => /\\btik\\s?tok\\b/i.test(t)],\n [\"youtube\", (t) => /\\byoutube\\b/i.test(t)],\n [\"pinterest\", (t) => /\\bpinterest\\b/i.test(t)],\n [\"snapchat\", (t) => /\\bsnapchat\\b/i.test(t)],\n [\"reddit\", (t) => /\\breddit\\b/i.test(t)],\n];\n\n/**\n * The platform an idea's own words name, when they name exactly one (\"decision makers scrolling\n * LinkedIn\"): an idea written before ideas carried `platforms` still says where its ads run.\n * Nothing when they name none or several. Pure.\n */\nexport function platformsNamedIn(text: string): string[] {\n const named = PLATFORM_WORDS.filter(([, names]) => names(text)).map(([platform]) => platform);\n return named.length === 1 ? named : [];\n}\n","/**\n * The briefs of a static ad on the `plate` master shape, compiled from prompt.json on every run:\n *\n * - each variant's picture (`plate_<i>`): the scene, its people and products, and the words the\n * scene itself prints (a chat on a phone, a label), never the ad's designed lines, logo or\n * button, so an edit of the copy or its language draws no picture again;\n * - each size's words (`static_format`: `lead_<i>`, `format_<size>`): the designed lines, the logo\n * and the button set on the picture, which stays as it is.\n *\n * Pure: canvas + prompt.json content in, nodes rewritten in place.\n */\nimport type { CreativeRule } from \"../creative-rules/schema.ts\";\nimport { briefRules, rulesBlock } from \"../creative-rules/select.ts\";\nimport { type ImageModelProfile, imageProfileFor } from \"../lib/prompt-profiles.ts\";\nimport { type AdSpec, readAdSpec, seesReferenceStructure, withRenderedLettering } from \"./static-ad-spec.ts\";\nimport { adaptBrief, adaptPlan } from \"./static-adapt.ts\";\nimport { plannedPlacements } from \"./static-adapt-briefs.ts\";\nimport { type BriefImages, type CompiledBrief, compileStaticBrief, quotedCopy, showsPeople } from \"./static-brief.ts\";\nimport { withoutLogoInZones } from \"./static-logo-briefs.ts\";\nimport type { PlateZones, ZoneSpan } from \"./static-plate.ts\";\nimport { BRAND_LOGO_ROLE, bindBriefImages, type StaticCanvasNode } from \"./static-render-briefs.ts\";\nimport { planStaticFormats } from \"./static-sizes.ts\";\nimport {\n isPlateCanvas,\n LOGO_COMPOSITE_ROLE,\n STATIC_VARIANT_CALL_ROLE,\n VARIANT_PREFILTER_ROLE,\n} from \"./static-topology.ts\";\n\n/** The company's rules the picture keeps: everything a render is told but the logo, which the picture never carries. */\nconst pictureRules = (rules: readonly CreativeRule[]) => rules.filter((r) => r.applies !== \"logo\");\n/** The company's rules a size's words keep: the logo's, which the words step places. */\nconst logoRules = (rules: readonly CreativeRule[]) => rules.filter((r) => r.applies === \"logo\");\n\nconst pct = (share: number): string => `${Math.round(Math.max(0, Math.min(1, share)) * 100)}%`;\nconst span = (s: ZoneSpan, axis: \"y\" | \"x\"): string =>\n axis === \"y\" ? `${pct(s.y0)} and ${pct(s.y1)} of the height` : `${pct(s.x0)} and ${pct(s.x1)} of the width`;\n\n/**\n * The spec as the picture draws it: the lines the scene prints, and none of the designed lines, the\n * logo, the button or the colours of what carries them (told the white of \"the bands behind the\n * headline\", a picture can draw the bands itself).\n */\nfunction pictureSpec(spec: AdSpec): AdSpec {\n const rendered = withRenderedLettering(spec);\n return {\n ...rendered,\n copy: rendered.copy.filter((l) => l.lettering === \"in_scene\"),\n colors: rendered.colors.filter((c) => !isWordsObject(c.object)),\n logo: false,\n };\n}\n\n/**\n * How much more of the model's word budget a picture's brief takes than an ad's: the scene is all it\n * draws, and a chat ad's own quoted lines cut its scene to \"Two frosted.\" at the ad's budget (dev, Oct 2026).\n */\nconst PLATE_ROOM = 1.3;\n\n/** What the picture is, said first: an ad's picture whose words come later. */\nconst PLATE_DELIVERABLE =\n \"Deliverable: the picture of an ad, with none of its designed words: its headline, lines, logo and button are set on it afterwards, so the picture carries none of them.\";\n\n/**\n * The zones every size is cut from: where what the ad shows stays, and the calm room the words\n * take. Named by what the ad has: a scene with no one in it is never told where people go.\n */\nfunction zonesLine(zones: PlateZones, spec: AdSpec): string {\n const people = showsPeople(spec);\n const what = people ? \"every person, face and product\" : \"everything the picture shows\";\n const photo = spec.scene.look === \"photo\";\n const calm = photo ? \"(a wall, the sky, a table top)\" : \"(the plain ground)\";\n const clear = people\n ? \"with no face and no product in it\"\n : photo\n ? \"with no product in it\"\n : \"with nothing drawn in it\";\n return `Zones: ${what} sits between ${span(zones.subjectCore, \"y\")} and between ${span(zones.subjectCore, \"x\")}, so every size cut from this picture keeps it whole. The words are set later between ${span(zones.wordsZone, \"y\")}: keep a calm, plain part of that band ${calm} ${clear}.`;\n}\n\n/** The designed things a layout ad is built of, as its scene names them: panels, cards, bubbles, posts, tables. */\nconst DESIGNED_ELEMENTS =\n /\\b(?:panels?|cards?|bubbles?|chats?|tables?|charts?|dashboards?|notifications?|posts?|mockups?|messages?|interfaces?|ui)\\b/i;\n\n/**\n * A designed ad's picture is its layout: the panels, cards and bubbles it is built of are drawn in\n * it with their own words, and only the ad's headline, lines, logo and button come later. Null for\n * a scene built of no designed elements, or a photo that keeps no reference's layout. Pure.\n */\nfunction designedLine(spec: AdSpec): string | null {\n const designed = spec.scene.look === \"designed\" || seesReferenceStructure(spec);\n if (!designed || !DESIGNED_ELEMENTS.test(`${spec.scene.description} ${spec.scene.layout ?? \"\"}`)) return null;\n return \"Designed layout: its panels, cards, bubbles and posts are part of this picture, drawn as the scene describes them and holding only the words quoted for them; the ad's headline, its other lines, its logo and its button are set on it afterwards, so their places stay plain.\";\n}\n\n/**\n * Who the picture shows, said outright: the people cast, else those a photo's scene names, else\n * nobody. Dev, Oct 2026: a chat ad's picture, told nothing, drew two strangers at laptops.\n */\nfunction peopleLine(spec: AdSpec): string {\n const cast = spec.references.filter((r) => r.id.startsWith(\"PERSON_\")).map((r) => r.id);\n if (cast.length > 0) {\n return `People: only ${cast.join(\" and \")}, each once and as the scene shows them; no other person, face, hand or body anywhere.`;\n }\n if (showsPeople(spec)) return \"People: only those the scene names, each once; no other person, face or hand.\";\n return \"People: none. No person, face, hand or body anywhere in the picture.\";\n}\n\n/**\n * The brief of one variant's picture: the ad's generate brief for the picture's shape, from the\n * spec without its designed lines (`pictureSpec`), told it carries no designed words and where its\n * people and the words go (`zones`). The same for any designed copy. Pure.\n */\nexport function plateBrief(\n spec: AdSpec,\n profile: ImageModelProfile,\n opts: {\n ratio: string;\n zones: PlateZones;\n variant?: number;\n images?: BriefImages;\n placements?: readonly string[];\n /** The company's rules for its ads: the picture keeps all but the logo's. */\n rules?: readonly CreativeRule[];\n },\n): CompiledBrief {\n // The picture's brief carries the scene the ad's words used to hold up: more of it is the picture's.\n const roomy = {\n ...profile,\n brief: { ...profile.brief, wordBudget: Math.round(profile.brief.wordBudget * PLATE_ROOM) },\n };\n const compiled = compileStaticBrief(pictureSpec(spec), undefined, opts.ratio, undefined, roomy, {\n job: \"generate\",\n variant: opts.variant ?? 0,\n ...(opts.images ? { images: opts.images } : { images: { refs: {} } }),\n ...(opts.placements ? { placements: [...opts.placements] } : {}),\n ...(opts.rules ? { rules: pictureRules(opts.rules) } : {}),\n });\n const paragraphs = compiled.prompt.split(\"\\n\\n\");\n const [first = \"\", ...rest] = paragraphs;\n const lead = first.replace(/^Deliverable:[^\\n]*?\\.(?=\\s|$)/, PLATE_DELIVERABLE);\n const designed = designedLine(spec);\n const prompt = [\n lead.startsWith(\"Deliverable:\") ? lead : `${PLATE_DELIVERABLE}\\n${lead}`,\n ...(designed ? [designed] : []),\n ...rest,\n peopleLine(spec),\n zonesLine(opts.zones, spec),\n ]\n .join(\"\\n\\n\")\n .replace(\n \"Text: none; the picture is the ad.\",\n \"Text: none of the ad's own words; they are set on the picture afterwards.\",\n );\n return { ...compiled, prompt };\n}\n\n/** The spec as a size's words are set: the designed lines only (the scene's own words are the picture's). */\nfunction wordsSpec(spec: AdSpec): AdSpec {\n const rendered = withRenderedLettering(spec);\n return { ...rendered, copy: rendered.copy.filter((l) => l.lettering === \"designed\") };\n}\n\nconst WORDS_DELIVERABLE =\n \"Deliverable: Image 1 is the finished picture of this ad, with none of its words yet. Set the ad's designed words, logo and button on it, and nothing else. The picture stays exactly as it is: the same scene, people, products, light and framing, every pixel outside the words unchanged; add no person or object and move nothing. Only the type and what carries it (a card, band, highlight, pill or shadow, and a mark a line's look names beside it, such as a ✗ or a ✓) is added, and every word already in the picture (on a screen, a label, a sign) stays as it is. A band or card the words sit on is laid over the picture, covering what is under it: the picture is never shrunk, moved or cropped to make room for it. A line placed above or below the photo sits on a band laid over the photo, its words inside the zones, the picture behind it at its full size.\";\n\n/** The deliverable when the brand's logo file is placed on the size afterwards: the words model draws none. */\nconst WORDS_DELIVERABLE_LOGO_PLACED = WORDS_DELIVERABLE.replace(\n \"Set the ad's designed words, logo and button on it, and nothing else.\",\n \"Set the ad's designed words and button on it, and nothing else; draw no logo, wordmark or brand mark: the brand's own logo file is placed on it afterwards.\",\n);\n\n/** The deliverable when the ad has no logo (`logo: false`): the words model draws none, as it would paint the wordmark itself. */\nconst WORDS_DELIVERABLE_NO_LOGO = WORDS_DELIVERABLE.replace(\n \"Set the ad's designed words, logo and button on it, and nothing else.\",\n \"Set the ad's designed words and button on it, and nothing else; draw no logo or wordmark anywhere: this ad has none.\",\n);\n\n/** Which deliverable the words are told: the logo file placed afterwards, no logo at all, or the logo drawn with the words. */\nfunction deliverableOf(logoPlaced: boolean, logo: boolean): string {\n if (logoPlaced) return WORDS_DELIVERABLE_LOGO_PLACED;\n return logo ? WORDS_DELIVERABLE : WORDS_DELIVERABLE_NO_LOGO;\n}\n\n/** What the lead's size is handed to the other sizes as: the look of the words, never the picture. */\nconst STYLE_LINE = (n: number) =>\n `Image ${n} (STYLE): this ad at its first size. Set the words in the same typeface, colours, weights, hierarchy and the treatment under them (card, band, pill, shadow), laid out for this frame; its picture and its words are only a sample of the look.`;\n\n/** Paragraphs of the re-layout brief a size's words do not need: it reflows, re-scales or re-tells a picture that stays. */\nconst NOT_FOR_WORDS = /^(Real-world anatomy|Built on a proven|Scale:|The idea:|Idea:)/;\n\n/**\n * The brief of one size's words: the designed lines exactly, their hierarchy, the logo and the\n * typeface, inside the zones the size's placements leave clear on the frame the model draws (a\n * 3:4 holding a 4:5), on a picture that stays as it is. Every size but the lead follows the\n * lead's look (`STYLE`); the lead places its lines where the spec says. Pure.\n */\nexport function wordsBrief(\n spec: AdSpec,\n profile: ImageModelProfile,\n opts: {\n model: string;\n format: string;\n lead: boolean;\n /** The size is handed a finished size to follow (`STYLE`): every size but the lead, and every size of a series ad. */\n style?: boolean;\n placements?: readonly string[];\n images: { logo?: string; type?: string };\n /** The company's rules for its ads: the words keep the logo's. */\n rules?: readonly CreativeRule[];\n /** The brand's logo file is placed on the size afterwards (`static_logo`): no logo is drawn. */\n logoPlaced?: boolean;\n },\n): CompiledBrief {\n const styled = opts.style ?? !opts.lead;\n const words = wordsSpec(spec);\n const compiled = adaptBrief(words, profile, {\n plan: adaptPlan(opts.model, opts.format, opts.placements),\n // The words call draws the lines' treatment: their looks are what it is told, whole.\n looksWhole: true,\n ...(opts.rules ? { rules: logoRules(opts.rules) } : {}),\n images: {\n base: PICTURE_REF,\n ...(opts.images.logo ? { logo: opts.images.logo } : {}),\n ...(opts.images.type ? { type: opts.images.type } : {}),\n },\n });\n const references = [\n ...compiled.references.map((r) => (r.role === \"base\" ? { ...r, label: \"PICTURE\" } : r)),\n ...(opts.lead\n ? []\n : [{ index: compiled.references.length + 1, role: \"base\" as const, label: \"STYLE\", ref: STYLE_REF }]),\n ];\n const placed = opts.lead\n ? words.copy.flatMap((l) => (l.position ? [`\"${quotedCopy(l.text)}\": ${l.position}`] : []))\n : [];\n const paragraphs = compiled.prompt\n .split(\"\\n\\n\")\n .slice(1)\n .filter((p) => !NOT_FOR_WORDS.test(p))\n .map((p) =>\n p.startsWith(\"References:\")\n ? [\n p.replace(\n /^Image 1 \\(AD\\):.*$/m,\n \"Image 1 (PICTURE): the picture the words are set on; it stays exactly as it is.\",\n ),\n ...(styled ? [STYLE_LINE(compiled.references.length + 1)] : []),\n ].join(\"\\n\")\n : p.replace(\"they are the only words in the image\", \"they are the only words added\"),\n );\n const colour = wordsColour(spec);\n const prompt = [\n deliverableOf(opts.logoPlaced === true, spec.logo),\n ...(opts.logoPlaced ? paragraphs.map(withoutLogoInZones) : paragraphs),\n ...(colour ? [colour] : []),\n ...(placed.length > 0 ? [`Where each line sits: ${placed.join(\"; \")}.`] : []),\n ].join(\"\\n\\n\");\n return { ...compiled, prompt, references };\n}\n\n/** What in the spec's colours belongs to the words: the type, the button, its label, the logo, a card under them. */\nconst WORDS_OBJECT =\n /\\b(text|type|headline|subhead|line|copy|words?|cta|button|pill|label|logo|wordmark|card|badge|highlight|caption)\\b/i;\n\n/** Whether a colour the spec names belongs to the words (the type, the button, its label, the logo, a card under them). */\nexport function isWordsObject(object: string): boolean {\n return WORDS_OBJECT.test(object);\n}\n\n/** The colours the words are set in, as the spec ties them to the type and the button; null when it names none. */\nfunction wordsColour(spec: AdSpec): string | null {\n const uses = (spec.colors ?? []).filter((c) => isWordsObject(c.object));\n if (uses.length === 0) return null;\n return `Colour: ${uses.map((c) => `${c.object} in ${c.name}${c.hex ? ` (${c.hex})` : \"\"}`).join(\"; \")}.`;\n}\n\n/** Placeholders for the pictures a size node hands its words call itself (its cut, the lead's size). */\nconst PICTURE_REF = \"$ref:cut.image\";\nconst STYLE_REF = \"$ref:style.image\";\n\ntype Node = {\n id?: unknown;\n type?: unknown;\n params?: Record<string, unknown>;\n inputs?: Record<string, unknown>;\n tags?: { role?: unknown; region?: unknown };\n};\n\nfunction nodesOf(canvas: unknown): Node[] {\n const nodes = (canvas as { nodes?: unknown } | null)?.nodes;\n return Array.isArray(nodes) ? (nodes as Node[]) : [];\n}\n\nconst stringsOf = (v: unknown): string[] | undefined =>\n Array.isArray(v) && v.every((p) => typeof p === \"string\") ? (v as string[]) : undefined;\n\n/** The zones the canvas's pictures were planned with: re-planned from the prefilter's params, as `plannedBand` does. */\nfunction plannedZones(nodes: Node[], model: string): { zones: PlateZones; placements?: string[] } | null {\n const params = nodes.find((n) => n.tags?.role === VARIANT_PREFILTER_ROLE)?.params;\n const formats = stringsOf(params?.formats);\n if (!formats || formats.length === 0) return null;\n const placements = stringsOf(params?.placements);\n const plan = planStaticFormats(model, formats, {\n masterShape: \"plate\",\n ...(placements ? { placements } : {}),\n ...(typeof params?.lead === \"string\" ? { lead: params.lead } : {}),\n });\n return plan.plate ? { zones: plan.plate.zones, ...(placements ? { placements } : {}) } : null;\n}\n\n/** The ref of the canvas's ingest with `role` (the brand's logo file), or of its type specimen. */\nfunction pictureRef(nodes: Node[], match: (n: Node) => boolean, output: string): string | undefined {\n const found = nodes.find(match);\n return typeof found?.id === \"string\" ? `$ref:${found.id}.${output}` : undefined;\n}\n\nfunction changed(node: Node, next: { params: Record<string, unknown>; inputs: Record<string, unknown> }): boolean {\n const before = JSON.stringify([node.params, node.inputs]);\n node.params = next.params;\n node.inputs = next.inputs;\n return JSON.stringify([node.params, node.inputs]) !== before;\n}\n\n/** One variant's picture (`plate_<i>`) briefed from the spec, its references the spec's own pictures. Whether it changed. */\nfunction projectPlate(node: Node, nodes: Node[], spec: AdSpec, rules: readonly CreativeRule[]): boolean {\n const model = String(node.params?.model ?? \"\");\n const planned = plannedZones(nodes, model);\n const profile = imageProfileFor(model);\n if (!planned || !profile) return false;\n // Built on a proven ad as a whole or on its layout, the picture is shown that ad for its structure only.\n const wired = Array.isArray(node.inputs?.reference) ? (node.inputs.reference as unknown[]) : [];\n const structure =\n seesReferenceStructure(spec) && nodes.some((n) => n.id === \"original\" && n.type === \"ingest\")\n ? [\"$ref:original.asset\"].filter((r) => !wired.includes(r))\n : [];\n const bound = bindBriefImages(nodes as StaticCanvasNode[], [...wired, ...structure], spec);\n // The picture carries no designed words: neither the logo file nor the type specimen.\n const { logo: _logo, type: _type, base: _base, ...images } = bound.images;\n const brief = plateBrief(bound.spec, profile, {\n ratio: String(node.params?.aspect_ratio ?? \"9:16\"),\n zones: planned.zones,\n variant: typeof node.tags?.region === \"number\" ? node.tags.region : 0,\n images,\n ...(planned.placements ? { placements: planned.placements } : {}),\n rules,\n });\n const inputs: Record<string, unknown> = { ...node.inputs };\n const reference = brief.references.map((r) => r.ref);\n if (reference.length > 0) inputs.reference = reference;\n else delete inputs.reference;\n return changed(node, { params: { ...node.params, prompt: brief.prompt }, inputs });\n}\n\n/** What every size's words are told, the same for each size: the lines, the scene's own, the logo file and the type. */\ntype SizeWords = {\n spec: AdSpec;\n /** The brand's logo file is placed on every size afterwards: no words call draws it. */\n logoPlaced: boolean;\n copy: Array<{ text: string; role?: string }>;\n inScene: string[];\n logo?: string;\n type?: string;\n placements?: string[];\n rules: readonly CreativeRule[];\n};\n\nfunction sizeWords(nodes: Node[], spec: AdSpec, rules: readonly CreativeRule[]): SizeWords {\n const composited = nodes.some((n) => n.tags?.role === LOGO_COMPOSITE_ROLE);\n const logo =\n spec.logo && !composited\n ? pictureRef(nodes, (n) => n.type === \"ingest\" && n.tags?.role === BRAND_LOGO_ROLE, \"asset\")\n : undefined;\n const type = pictureRef(nodes, (n) => n.type === \"font_specimen\", \"image\");\n const placements = plannedPlacements(nodes);\n const rendered = withRenderedLettering(spec);\n // The brand's name and the words its logo prints count as the logo, as the review counts them.\n const logoWords = [...new Set([...(spec.brand?.name ? [spec.brand.name] : []), ...(spec.brand?.lockup ?? [])])];\n return {\n spec,\n logoPlaced: composited,\n copy: [\n ...rendered.copy\n .filter((l) => l.lettering === \"designed\")\n .map((l) => ({ text: l.text, ...(l.role ? { role: l.role } : {}) })),\n ...logoWords.map((text) => ({ text, role: \"logo\" })),\n ],\n inScene: rendered.copy.filter((l) => l.lettering === \"in_scene\").map((l) => l.text),\n ...(logo ? { logo } : {}),\n ...(type ? { type } : {}),\n ...(placements ? { placements } : {}),\n rules,\n };\n}\n\n/** The placements a size keeps clear of: its own, as planned, else the canvas's. */\nfunction placementsOf(node: Node, w: SizeWords): string[] | undefined {\n return stringsOf(node.params?.placements) ?? w.placements;\n}\n\n/** `value` under `key` of `record`, or the key gone when there is nothing to say. */\nfunction setOrDrop(record: Record<string, unknown>, key: string, value: unknown): void {\n if (value === undefined || (Array.isArray(value) && value.length === 0)) delete record[key];\n else record[key] = value;\n}\n\n/** One size node's words briefed from the spec, with its lines, the scene's lines, the logo file and the type. Whether it changed. */\nfunction projectSize(node: Node, w: SizeWords): boolean {\n const words = (node.params?.words ?? {}) as Record<string, unknown>;\n const model = String(words.model ?? \"\");\n const profile = imageProfileFor(model);\n const format = node.params?.format;\n if (!profile || typeof format !== \"string\") return false;\n const brief = wordsBrief(w.spec, profile, {\n model,\n format,\n lead: node.params?.lead === true,\n style: node.inputs?.style !== undefined,\n ...(placementsOf(node, w) ? { placements: placementsOf(node, w) } : {}),\n images: { ...(w.logo ? { logo: w.logo } : {}), ...(w.type ? { type: w.type } : {}) },\n rules: w.rules,\n ...(w.logoPlaced ? { logoPlaced: true } : {}),\n });\n const params: Record<string, unknown> = { ...node.params, words: { ...words, prompt: brief.prompt } };\n setOrDrop(params, \"copy\", w.copy);\n setOrDrop(params, \"in_scene\", w.inScene);\n const inputs: Record<string, unknown> = { ...node.inputs };\n setOrDrop(inputs, \"logo\", w.logo);\n setOrDrop(inputs, \"type\", w.type);\n return changed(node, { params, inputs });\n}\n\n/**\n * Compile a `plate` canvas's pictures and every size's words from prompt.json, in place: each\n * variant's picture (`plate_<i>`) with its references, and each size node's words brief, its\n * designed lines and the brand's (`copy`, the logo's words with role `logo`), the scene's own\n * lines (`in_scene`), the logo file the model draws and the type specimen. The company's `rules`\n * reach them as they reach the takes of an ad re-laid out: the picture's to each picture, the logo's\n * to each size's words. Returns how many nodes changed (0 for a canvas not on the plate shape).\n */\nexport function projectFormatBriefs(canvas: unknown, promptJson: unknown, rules: readonly CreativeRule[] = []): number {\n const nodes = nodesOf(canvas);\n if (!isPlateCanvas(canvas)) return 0;\n const spec = readAdSpec(promptJson);\n const plates = nodes.filter((n) => n.type === \"image_generate\" && n.tags?.role === STATIC_VARIANT_CALL_ROLE);\n const words = sizeWords(nodes, spec, rules);\n const sizes = nodes.filter((n) => n.type === \"static_format\");\n return (\n plates.filter((n) => projectPlate(n, nodes, spec, rules)).length + sizes.filter((n) => projectSize(n, words)).length\n );\n}\n\n/**\n * The correction of a static ad's picture (`edit_<n>` on the plate shape): Image 1 is the picture\n * without the ad's designed words; only what the instruction names changes (a colour, or the words\n * lettered in its scene), and it gains no other words. Every size's words are set again on the\n * corrected picture. Pure.\n */\nexport function plateFixPrompt(\n instruction: string,\n opts: { rejected?: readonly string[]; rules?: readonly CreativeRule[] } = {},\n): string {\n const change = instruction.trim().replace(/^Change only this:\\s*/i, \"\");\n const rejected =\n opts.rejected && opts.rejected.length > 0\n ? [`The person rejected these in earlier versions of this ad; none may come back: ${opts.rejected.join(\"; \")}.`]\n : [];\n const ruled = rulesBlock(\n briefRules(pictureRules(opts.rules ?? [])),\n \"The company's own rules for every ad it makes, each one kept in this picture:\",\n );\n return [\n `Edit: Image 1 is this ad's picture, without the words set over it. Change only this: ${change.replace(/\\.$/, \"\")}.`,\n \"Keep the rest of Image 1 exactly as it is: the same people and faces, the same products, the same place, light, colours and framing. Any other word already in the scene (on a screen, a label, a sign) stays as it is.\",\n ...rejected,\n \"Add no headline, no other words or letters, no logo and no button: the ad's designed words are set on the picture afterwards.\",\n ...(ruled ? [ruled] : []),\n ].join(\"\\n\\n\");\n}\n","/**\n * Which master shape a new static ad is scaffolded on, decided from its spec (ADR 0014).\n *\n * One picture (`plate`) won or tied on photo-led ads and lost on a designed one: on Permut's chat\n * comparison (dev, Oct 2026) the picture drew framed chat panels the words model re-laid twice, and\n * the 9:16's button sat under Stories' reply bar in a block code cannot move. A picture made of\n * designed elements (a chat, a screenshot, a table, a card of text) is the ad's layout itself, so it\n * is laid out again for each size (`relayout`). A picture of people, places and products is drawn whole\n * too (`PHOTO_LED_SHAPE`); the route still says which kind it read, for the reason it records.\n *\n * Read in order: the proven ad the render keeps for its structure (`concept.carry` whole ad or layout)\n * whose picture is designed elements; an in-scene line set on an interface (a chat bubble, a screen);\n * a scene that is an interface. Anything else is photo-led. Pure: the spec in, the shape and why out.\n */\nimport type { MasterShape } from \"./static-sizes.ts\";\n\nexport type ShapeRoute = { shape: Extract<MasterShape, \"plate\" | \"relayout\">; reason: string };\n\n/**\n * How a photo-led ad is made: drawn whole, like every other. On one picture (`plate`, ADR 0014) the\n * words came from a second call over a wordless picture and the logo was pasted on afterwards; in\n * production (Oct 2026) the ads read as stamped and lost the look the reference was chosen for, as\n * the ADR's own first comparison had found (re-laid out won 3-0). `--master-shape plate` still asks for it.\n * Tried and reverted three times (docs/marketing-intelligence.md § \"Tried and failed\"): do not flip\n * it without beating the drawn ad on production work.\n */\nconst PHOTO_LED_SHAPE = \"relayout\";\n\n/** Library containers (`staticFormatPatternSchema`) whose picture is designed elements, not a photo. */\nconst DESIGNED_PATTERNS = new Set([\n \"headline_card\",\n \"infographic\",\n \"chat_screenshot\",\n \"tweet_screenshot\",\n \"review_screenshot\",\n \"comparison_table\",\n \"list_card\",\n \"meme_template\",\n \"native_post_lookalike\",\n \"notes_app_screenshot\",\n \"founder_letter_textonly\",\n \"us_vs_them_grid\",\n \"benefit_callout_grid\",\n \"create_your_own_adventure_meme\",\n]);\n\n/** An interface named in a scene: a chat, a screenshot, a dashboard, a screen showing something, a table. */\nconst INTERFACE_SCENE =\n /\\b(?:chat(?:bot)?s?|screenshots?|interfaces?|dashboards?|app screens?|spreadsheets?|inbox|notifications?|(?:chat|message|speech) bubbles?|(?:comparison|pricing) tables?|tables? of|screens? (?:showing|displaying|with)|mock-?ups? of (?:an? |the )?(?:app|screen|website|phone|dashboard))\\b|\\bUI\\b/i;\n\n/** Where an in-scene line sits when it is lettered on an interface. */\nconst INTERFACE_SURFACE =\n /\\b(?:bubbles?|chat|screens?|app|notifications?|messages?|inbox|dashboard|tweet|review|(?:app|browser|chat|desktop) window|(?:social|linkedin|facebook|instagram|twitter|reddit) post)\\b/i;\n\n/** What a negation rules out (\"no screens\", \"without any app screens or notifications\"): its noun phrase, not the rest of the clause. */\nconst NEGATED_CLAUSE =\n /\\b(?:no|not|never|without)\\b(?:\\s+(?:any|an?|the))?(?:\\s+[\\w'-]+){0,2}(?:\\s+(?:or|nor|and)\\s+[\\w'-]+(?:\\s+[\\w'-]+)?)*/gi;\n\n/** A scene's words with what it rules out taken away: \"no dashboard\" names no interface. */\nconst affirmed = (scene: string) => scene.replace(NEGATED_CLAUSE, \" \");\n\ntype Loose = Record<string, unknown>;\nconst text = (v: unknown) => (typeof v === \"string\" ? v : \"\");\n\nfunction carriedPattern(spec: Loose): { pattern: string; carry: string } | null {\n const concept = spec.concept as Loose | undefined;\n if (!concept || concept.verdict === \"reject\") return null;\n const carry = text(concept.carry) || \"whole_ad\";\n if (carry !== \"whole_ad\" && carry !== \"layout\") return null;\n const pattern = text((spec.reference as Loose | undefined)?.format_pattern);\n return DESIGNED_PATTERNS.has(pattern) ? { pattern, carry } : null;\n}\n\nfunction interfaceLine(spec: Loose): string | null {\n const copy = Array.isArray(spec.copy) ? (spec.copy as Loose[]) : [];\n const line = copy.find(\n (l) => l?.lettering === \"in_scene\" && INTERFACE_SURFACE.test(`${text(l.on)} ${text(l.position)}`),\n );\n return line ? text(line.text) : null;\n}\n\n/** The shape a new static ad's spec routes to, and why, in a sentence the agent can repeat. Pure. */\nexport function staticShapeFor(spec: unknown): ShapeRoute {\n const loose = (spec && typeof spec === \"object\" ? spec : {}) as Loose;\n const carried = carriedPattern(loose);\n if (carried) {\n const kept = carried.carry === \"whole_ad\" ? \"the whole ad\" : \"its layout\";\n return {\n shape: \"relayout\",\n reason: `designed: it keeps ${kept} of a proven ${carried.pattern.replace(/_/g, \" \")} ad, whose picture is designed elements, so every size is laid out again`,\n };\n }\n const line = interfaceLine(loose);\n if (line) {\n return {\n shape: \"relayout\",\n reason: `interface: the picture carries interface lines (\"${line.slice(0, 60)}\"), so every size is laid out again`,\n };\n }\n const scene = loose.scene as Loose | undefined;\n const named = affirmed(`${text(scene?.description)} ${text(scene?.layout)}`).match(INTERFACE_SCENE)?.[0];\n if (named) {\n return {\n shape: \"relayout\",\n reason: `interface: the scene is an interface (\"${named}\"), so every size is laid out again`,\n };\n }\n return {\n shape: PHOTO_LED_SHAPE,\n reason: \"photo-led: the ad is drawn whole, logo and words included, and laid out again for each size\",\n };\n}\n\n/** The shape a scaffolded static canvas is on and why, as it records them; null for any other canvas. Pure. */\nexport function recordedShape(canvas: unknown): { shape: string; reason: string } | null {\n const holder = (canvas ?? {}) as { metadata?: Loose; nodes?: unknown };\n const nodes = Array.isArray(holder.nodes) ? (holder.nodes as Loose[]) : [];\n const prefilter = nodes.find((n) => (n.tags as Loose | undefined)?.role === \"variant_prefilter\");\n const shape = text((prefilter?.params as Loose | undefined)?.master_shape);\n const reason = text(holder.metadata?.master_shape_reason);\n return shape && reason ? { shape, reason } : null;\n}\n","/**\n * Which model does which image job, by the kind of concept: one table, read by every\n * static scaffold and the bench, so no call site pins a model id.\n *\n * A route changes here only for a model that has a profile (`prompt-profiles.ts`) and won its\n * class on the bench. E5 decides the reframe model.\n */\nimport {\n AD_DESCRIBE_MODEL,\n AD_IMAGE_MODEL,\n ASPECT_ADAPT_MODEL,\n PLATE_JUDGE_MODEL,\n REFERENCE_SHEET_MODEL,\n} from \"@baker/canvas-contract\";\n\n/** What kind of picture a concept is, as far as choosing its model goes. */\nexport const CONCEPT_CLASSES = [\"designed\", \"illustration\", \"photo\", \"photo_people\"] as const;\nexport type ConceptClass = (typeof CONCEPT_CLASSES)[number];\n\n/** The image jobs a static ad runs. */\nexport const IMAGE_JOBS = [\"generate\", \"fix\", \"reframe\", \"relayout\", \"identity_sheet\", \"judge\", \"describe\"] as const;\nexport type ImageJob = (typeof IMAGE_JOBS)[number];\n\nconst everyClass = (model: string): Record<ConceptClass, string> => ({\n designed: model,\n illustration: model,\n photo: model,\n photo_people: model,\n});\n\nconst ROUTES: Readonly<Record<ImageJob, Readonly<Record<ConceptClass, string>>>> = {\n // gpt-image-2.5 Sunburst in every class, Nano Banana Pro in none: on the same brief (182 paired\n // ads) Sunburst shipped 8.2% vs 6.0%, read its copy exactly in 72% vs 60% and drew an artifact\n // in 1% vs 15%; on photoreal people (9 ads) 11% vs 0% shippable, artifacts 0% vs 13%. On the\n // E7 gallery (30 rated pairs) the user picked Sunburst 68% of the time and the judge 72%.\n // Routes are chosen by results per job, never by price (the user: \"use the best one for what\n // it is\") (BENCH.md#E7).\n generate: everyClass(AD_IMAGE_MODEL),\n fix: everyClass(AD_IMAGE_MODEL),\n reframe: everyClass(ASPECT_ADAPT_MODEL),\n // Each size re-laid out from the chosen ad: gpt-image-2.5 Sunburst at max. In the E5 pilot\n // Nano Banana Pro set the ad as a card on a background and drew the layout guide's stripes\n // into it (BENCH.md § \"E5 — true per-format adaptation\").\n relayout: everyClass(AD_IMAGE_MODEL),\n identity_sheet: everyClass(REFERENCE_SHEET_MODEL),\n // Gemini Flash. Against the user's blind picks (E9, 20 pairs, the same rubric) Gemini Pro\n // agreed 55% vs Flash's 60%, so Pro bought nothing; the gain has to come from elsewhere\n // (BENCH.md § \"E9 — judge calibrated to the user\").\n judge: everyClass(PLATE_JUDGE_MODEL),\n describe: everyClass(AD_DESCRIBE_MODEL),\n};\n\n/** The model for one job on one kind of concept. Pure. */\nexport function pickImageModel(conceptClass: ConceptClass, job: ImageJob): string {\n return ROUTES[job][conceptClass];\n}\n","// Pure transform: an `image_describe` blueprint + an AI-selected list of the\n// image's MAIN identity elements → a runnable `baker-canvas/1` static-ad canvas.\n// No IO — the command layer runs the describe + element-selection passes, bakes\n// the blueprint to `prompt.json`, calls this, validates the result, and writes it.\n//\n// The image model designs the whole ad. Three days of production (Sept 2026) on the\n// other design, a text-free \"plate\" with the copy drawn over it by HTML that read the\n// picture's pixels for room, kept the ready rate flat at 40-43% whatever was patched:\n// the model paints an ad whether or not it is told to (cards, pills, wordmarks, whole\n// UI mocks with their words), and a second designer that cannot see the first collides\n// with it. So there is one designer. The model renders the finished ad from the\n// blueprint, with the copy quoted verbatim, the brand's typeface shown to it as a\n// specimen and the real logo file as a reference; three requests return three variants and a\n// judge keeps one; every size is made from that one picture (the lead size as it is, each\n// other size the chosen ad re-laid out for its frame by one request with the same words,\n// people, product and logo) (`static-sizes.ts`, `static-topology.ts`); the run then reads\n// every word back (static-review.ts) and refuses to call the ad ready when one is off.\n// No render reads the blueprint: each carries the brief `static-brief.ts` compiles from the\n// ad spec in prompt.json (`static-render-briefs.ts`), re-projected on every run.\n// Shares its shape with `video.ts` (tolerant schema, `[TODO]` markers, a `*Report`).\n\nimport { type AdFormatPlatform, imageGenerateAspectRatios, platformFormats } from \"@baker/canvas-contract\";\nimport { z } from \"zod\";\nimport type { CreativeRule } from \"../creative-rules/schema.ts\";\nimport { pickImageModel } from \"../lib/image-model-router.ts\";\nimport { GPT_IMAGE_25_PROFILE, imageProfileFor } from \"../lib/prompt-profiles.ts\";\nimport type { Canvas, NodeDecl } from \"../schema/canvas.ts\";\nimport { avatarsByPersona, avatarsLeftUncast, type CastAvatar, castAvatarsInOrder } from \"./castAvatar.ts\";\nimport { assignElementLabels, sanitizeId } from \"./lib/elements.ts\";\nimport { imageRenderParams } from \"./lib/image-params.ts\";\nimport {\n AD_SPEC_SCHEMA,\n type AdBrand,\n type AdReference,\n type AdSpec,\n AdSpecSchema,\n adSpecFromBlueprint,\n conceptClassOf,\n plainText,\n withRenderedLettering,\n} from \"./static-ad-spec.ts\";\nimport { formatOfAdaptId, projectAdaptBriefs } from \"./static-adapt-briefs.ts\";\nimport { copyStrings, inSceneText, specimenText, type WinningMechanism, winningMechanisms } from \"./static-copy.ts\";\nimport type { StaticDelivery } from \"./static-delivery.ts\";\nimport type { FontOrigin, ResolvedFont } from \"./static-fonts.ts\";\nimport { projectFormatBriefs } from \"./static-format-briefs.ts\";\nimport { projectLogoPlacement } from \"./static-logo-briefs.ts\";\nimport {\n BRAND_LOGO_COLOURWAY_ROLE,\n BRAND_LOGO_ROLE,\n fixBriefNode,\n projectStaticBriefs,\n STATIC_AD_ROLE,\n} from \"./static-render-briefs.ts\";\nimport { staticShapeFor } from \"./static-shape-route.ts\";\nimport { type MasterShape, planStaticFormats, type SizePlan, type StaticFormatPlan } from \"./static-sizes.ts\";\nimport {\n formatSlug,\n isPlateCanvas,\n LOGO_COMPOSITE_DEFAULT,\n nodesWithRole,\n RENDER_GRAPH_IDS,\n SERIES_LEAD_ROLE,\n STATIC_ADAPT_FORMAT_ROLE,\n STATIC_FIX_ROLE,\n STATIC_LEAD_ROLE,\n STATIC_MASTER_ROLE,\n STATIC_PICK_ROLE,\n STATIC_VARIANT_CALL_ROLE,\n STATIC_VARIANTS_ROLE,\n staticMasterFormat,\n staticRenderNodes,\n VARIANT_PREFILTER_ROLE,\n} from \"./static-topology.ts\";\n\n// Ratios at least one curated image model renders, read off the registry; the\n// blueprint's estimate is honored only when it lands in this set, else we default to\n// a vertical social format. The render model then snaps it to its own nearest shape.\nconst GEN_ASPECT_RATIOS = new Set(imageGenerateAspectRatios());\nconst DEFAULT_ASPECT_RATIO = \"9:16\";\n\n// The tier every render asks for; snapped down per model (Nano Banana 2 Lite is 1K).\nconst AD_IMAGE_SIZE = \"2K\";\n\n// --- Tolerant blueprint schema: only the fields the scaffold itself consumes. ---\nconst Blueprint = z\n .object({\n meta: z.object({ estimated_aspect_ratio: z.string().optional() }).loose().optional(),\n text_content: z.array(z.object({ text: z.string().optional() }).loose()).optional(),\n people: z.array(z.unknown()).optional(),\n fonts: z.array(z.unknown()).optional(),\n winning_mechanisms: z.array(z.unknown()).optional(),\n })\n .loose();\ntype StaticAdBlueprint = z.infer<typeof Blueprint>;\n\n/**\n * The parts of the describe contract a static ad is rebuilt from that the blueprint lacks.\n * Named rather than silently tolerated: without `winning_mechanisms` the rewrite keeps the\n * surface and loses what made the ad work, and without `fonts` the letterforms go with it.\n */\nfunction describeGaps(blueprint: StaticAdBlueprint): Array<\"fonts\" | \"winning_mechanisms\"> {\n const gaps: Array<\"fonts\" | \"winning_mechanisms\"> = [];\n if (!blueprint.fonts?.length) gaps.push(\"fonts\");\n if (winningMechanisms(blueprint).length === 0) gaps.push(\"winning_mechanisms\");\n return gaps;\n}\n\n// --- A main element chosen by the AI selection pass. ---\nconst MainElement = z\n .object({\n // logo | product | person | animal | badge | other\n type: z.string(),\n label: z.string().optional(),\n description: z.string().optional(),\n expression: z.string().nullable().optional(),\n reason: z.string().optional(),\n })\n .loose();\ntype MainElementT = z.infer<typeof MainElement>;\nconst MainElements = z.array(MainElement);\n\n// A static ad's selection never links two looks of one person, and it never sheets a\n// person, so a cast slot needs no telling that its picture is already a turnaround.\nconst STATIC_CASTING = { looks: false, markSheet: false };\n\n/**\n * Cast company Avatars into the person slots: the avatar that best matches `persona` (who the ad\n * is for) first, else in the order given; the first person gets the first, and so on. The slot takes the avatar's identity sheet as its picture and its\n * subject description as the words, so the render shows the brand's own cast. A person\n * left without an avatar keeps its TODO: casting nobody is how a canvas renders a stranger.\n */\nexport function castAvatarsOnStaticElements(\n elementsInput: unknown,\n avatars: readonly CastAvatar[],\n persona?: string,\n): MainElementT[] {\n return castAvatarsInOrder(MainElements.parse(elementsInput), avatarsByPersona(avatars, persona), STATIC_CASTING);\n}\n\n/**\n * An ad started from an idea, with the Avatars asked for cast: it has no reference to find people\n * in, so each Avatar is a person of its own, grounded on its sheet and written into the spec's\n * references beside the ones it had. Pure.\n */\nexport function castOnIdeaSpec(\n spec: AdSpec,\n avatars: readonly CastAvatar[],\n persona?: string,\n): { spec: AdSpec; elements: MainElementT[] } {\n const elements = castAvatarsOnStaticElements(\n avatars.map(() => ({ type: \"person\", label: \"PERSON\" })),\n avatars,\n persona,\n );\n const cast = staticAdSpec({}, elements).references.filter((r) => !spec.references.some((s) => s.slot === r.slot));\n return { spec: { ...spec, references: [...spec.references, ...cast] }, elements };\n}\n\n/**\n * The handles `castAvatarsOnStaticElements` had no person for, in the order given: read off the\n * cast elements, since a persona may cast them in another order than they were passed.\n */\nexport function staticAvatarsNotCast(castElements: unknown, handles: readonly string[]): string[] {\n const elements = MainElements.parse(castElements);\n if (!elements.some((el) => typeof el.cast_handle === \"string\")) {\n return avatarsLeftUncast(elements, handles, STATIC_CASTING);\n }\n return handles.filter((h) => !elements.some((el) => el.cast_handle === h));\n}\n\n/** The picture an element arrived with (a cast Avatar's sheet URL), if any. */\nfunction suppliedImage(el: MainElementT): string | undefined {\n const url = typeof el.source_image === \"string\" ? el.source_image.trim() : \"\";\n return /^https?:\\/\\//i.test(url) ? url : undefined;\n}\n\n/** Where a static ad's brand lives in the workspace, as paths relative to the canvas file. */\ntype StaticAdBrand = {\n /** The brand's logo file, placed on every size (or shown to the model). Only when the concept shows a logo; never generated. */\n logoPath?: string;\n /** The same logo in its other colours (`logoColourways`): the composite places the one that reads on the ground. */\n logoColourways?: string[];\n /** The logo's shape, width over height, measured off the file: the slot each size keeps for it. */\n logoAspect?: number;\n /** The brand's headline face: a font file, or the family the brand names as a web font. Shown to the model as a type specimen. */\n font?: ResolvedFont;\n};\n\nexport type StaticAdOpts = {\n /** image_generate model id (resolved from the registry by the command). */\n genModel: string;\n /** Source image the emitted `original` ingest reads (the record of the source; a first render sees it for its structure only when prompt.json keeps its concept) — a local path or, when `imageIsUrl`, a URL. */\n imagePath?: string;\n /** When true, `imagePath` is a URL and the `original` ingest uses `source: \"url\"`. */\n imageIsUrl?: boolean;\n /** Path the emitted `prompt` ingest reads (the baked blueprint). Default ./prompt.json */\n blueprintPath?: string;\n /** Override the aspect ratio; otherwise taken from the blueprint, else 9:16. */\n aspectRatio?: string;\n /**\n * A legacy placement preset (`meta_all`, …), for a canvas made without a platform: the sizes\n * then follow the preset, the reference's shape leading. `delivery` wins.\n */\n placements?: AdFormatPlatform;\n /** The brand's logo and typeface. */\n brand?: StaticAdBrand;\n /** Variants rendered and judged. Default 3; 1 skips the judge. */\n takes?: number;\n /** How the one master picture is shaped and the sizes made from it. Default: the one the spec's kind routes to (`staticShapeFor`). */\n masterShape?: MasterShape;\n /** The ad set's Meta placements (the viewer's), which narrow the safe areas; none = Advantage+, Reels included. */\n adPlacements?: readonly string[];\n /**\n * Where the ad runs and the sizes that follow (`static-delivery.ts`): its sizes exactly, lead\n * first and rendered first, each keeping clear of its placements' interface. Absent: a single\n * size (the reference's shape, or `aspectRatio`), or the legacy `placements` preset.\n */\n delivery?: StaticDelivery;\n /** Composite the brand's logo file on every size instead of having the model draw it. Default off (`LOGO_COMPOSITE_DEFAULT`): the model draws it from the file. */\n logoComposite?: boolean;\n /**\n * The ad spec the renders compile from (what prompt.json holds). Default: the one\n * `staticAdSpec` derives from the blueprint and the elements.\n */\n spec?: unknown;\n};\n\n/**\n * A typographic reference: it carries copy and pictures nothing (no subject, no person).\n * Reported so the agent knows the ad is its words on the brand's colours.\n */\nexport function isTextForward(input: unknown): boolean {\n const blueprint = input as { subjects?: unknown; people?: unknown } | null;\n const none = (v: unknown) => !Array.isArray(v) || v.length === 0;\n return none(blueprint?.subjects) && none(blueprint?.people) && copyStrings(input).length > 0;\n}\n\n/**\n * The logo is on the ad when the ad spec keeps it AND the brand has the real file. The reference\n * ad never decides: audited Sept 2026, whether our ad carried our logo followed whether the\n * reference showed its own.\n */\nfunction logoDrawn(spec: AdSpec, opts: StaticAdOpts): boolean {\n return Boolean(opts.brand?.logoPath) && spec.logo;\n}\n\n/** The ad spec a canvas compiles from: the one given, else the one the blueprint reads as, keeping the logo when the brand has one. */\nfunction specFor(input: unknown, elements: MainElementT[], opts: StaticAdOpts): AdSpec {\n return opts.spec === undefined\n ? staticAdSpec(input, elements, { logo: Boolean(opts.brand?.logoPath) })\n : AdSpecSchema.parse(opts.spec);\n}\n\n/** The shape a logo is planned with before its file is measured: a wordmark, three times as wide as tall. */\nconst LOGO_ASPECT = 3;\n\n/** Whether the logo file is composited on every size (else the model draws it from the file). */\nfunction logoComposited(opts: StaticAdOpts): boolean {\n return opts.logoComposite ?? LOGO_COMPOSITE_DEFAULT;\n}\n\n/** Candidates rendered at most: the three directions a brief can take (`static-brief.ts`). */\nconst MAX_TAKES = 3;\n\n/** A render's prompt before its brief is projected into it (never sent: the scaffold projects before it returns). */\nconst UNCOMPILED = \"compiled from prompt.json\";\n\nfunction ingestNode(id: string, path: string, expect: \"image\" | \"font\" | \"json\"): NodeDecl {\n return { id, type: \"ingest\", params: { source: \"path\", path, expect } };\n}\n\nfunction aspectRatio(blueprint: StaticAdBlueprint, opts: StaticAdOpts): string {\n const requested = opts.aspectRatio ?? blueprint.meta?.estimated_aspect_ratio;\n return requested && GEN_ASPECT_RATIOS.has(requested) ? requested : DEFAULT_ASPECT_RATIO;\n}\n\n/**\n * Every format this canvas delivers: where it runs decides them, lead first; else the legacy\n * preset's set with the requested ratio (the source's, or `--aspect`) leading when the set has\n * it; else just the requested ratio.\n */\nfunction outputFormats(blueprint: StaticAdBlueprint, opts: StaticAdOpts): string[] {\n const { delivery } = opts;\n if (delivery && delivery.formats.length === 0) {\n throw new Error(\n `--platforms ${delivery.platforms.join(\",\")} requires only fixed-size banners (${delivery.banners.join(\", \")}), which are never made from the picture: add a platform with a feed or story size (meta, google_display, …).`,\n );\n }\n if (delivery) return [...delivery.formats];\n const requested = aspectRatio(blueprint, opts);\n if (!opts.placements) return [requested];\n const formats = [...platformFormats(opts.placements)];\n return formats.includes(requested) ? [requested, ...formats.filter((f) => f !== requested)] : formats;\n}\n\n/**\n * The placements the safe areas keep clear of: the ad set's own when it was read (Meta's only, so\n * every other platform named keeps its own), else every placement the delivered sizes serve, else\n * none (Advantage+, Reels included).\n */\nfunction safePlacements(opts: StaticAdOpts): readonly string[] | undefined {\n const named = opts.delivery?.placements ?? [];\n if (opts.adPlacements) return [...new Set([...opts.adPlacements, ...named.filter((p) => !p.startsWith(\"meta_\"))])];\n return named.length > 0 ? [...new Set(named)] : undefined;\n}\n\n/**\n * The master shape a canvas is scaffolded on, and why: the one asked for (`--master-shape`), else the\n * one its spec's kind routes to (`staticShapeFor`: designed and interface ads are laid out again for\n * each size, photo-led ones cut from one picture).\n */\nexport function shapeRouteOf(opts: StaticAdOpts, spec: AdSpec): { shape: MasterShape; reason: string } {\n if (opts.masterShape) return { shape: opts.masterShape, reason: `chosen: --master-shape ${opts.masterShape}` };\n return staticShapeFor(spec);\n}\n\n/** How the sizes are planned: the master shape, the placements kept clear of, and the platform's lead. */\nfunction formatPlanOpts(opts: StaticAdOpts, masterShape: MasterShape) {\n const placements = safePlacements(opts);\n return {\n masterShape,\n ...(placements ? { placements } : {}),\n ...(opts.delivery ? { lead: opts.delivery.lead, platforms: opts.delivery.platforms } : {}),\n };\n}\n\ntype Slot = { ref: string; label: string; type: string };\n\ntype Built = { nodes: NodeDecl[] };\n\n/** Ids the spine and the brand nodes take, so no element slot collides with them. */\nconst RESERVED_IDS = [\"prompt\", \"original\", \"brand_logo\", \"font_headline\", \"type_specimen\", ...RENDER_GRAPH_IDS];\n\n/** Each element with its role-based label and the id of the ingest that holds its picture. */\nfunction elementSlots(elements: MainElementT[]): Array<{ el: MainElementT; label: string; id: string }> {\n const used = new Set(RESERVED_IDS);\n return assignElementLabels(elements, \"static\").map(({ el, label }, i) => {\n let id = sanitizeId(`el_${label}`, `el_${i}`);\n while (used.has(id)) id = `${id}_${i}`;\n used.add(id);\n return { el, label, id };\n });\n}\n\n/**\n * The pictures the ad grounds on: each person cast from the company's avatars (its identity\n * sheet), and the brand's logo. The reference ad's own people, products, animals and badges are\n * never slots to fill: they are the source's world (audited Sept 2026: they became required\n * [TODO] slots and 8 chats hand-edited canvas.json 64 times to get rid of them). A picture of our\n * own goes in prompt.json, on the reference that shows it (`image`), and every run wires it.\n * The brand's real logo file is wired whenever the ad spec keeps the logo (never a stand-in).\n */\nfunction elementNodes(\n elements: MainElementT[],\n opts: StaticAdOpts,\n drawLogo: boolean,\n): Built & { slots: Slot[]; logoRef: string | undefined; colourways: string[] } {\n const nodes: NodeDecl[] = [];\n const slots: Slot[] = [];\n elementSlots(elements).forEach(({ el, label, id }) => {\n const url = suppliedImage(el);\n if (el.type.toLowerCase() === \"logo\" || !url) return;\n nodes.push({ id, type: \"ingest\", params: { source: \"url\", url, expect: \"image\" } });\n slots.push({ ref: `$ref:${id}.asset`, label, type: el.type });\n });\n const logoPath = drawLogo ? opts.brand?.logoPath : undefined;\n if (!logoPath) return { nodes, slots, logoRef: undefined, colourways: [] };\n nodes.push({ ...ingestNode(\"brand_logo\", logoPath, \"image\"), tags: { role: BRAND_LOGO_ROLE } });\n // The composite measures the ground under its slot and places the colour of the logo that reads there.\n const colourways = logoComposited(opts) ? (opts.brand?.logoColourways ?? []) : [];\n colourways.forEach((file, i) => {\n nodes.push({ ...ingestNode(`brand_logo_${i + 2}`, file, \"image\"), tags: { role: BRAND_LOGO_COLOURWAY_ROLE } });\n });\n return {\n nodes,\n slots,\n logoRef: \"$ref:brand_logo.asset\",\n colourways: colourways.map((_, i) => `$ref:brand_logo_${i + 2}.asset`),\n };\n}\n\n/**\n * The brand's typeface, shown to the model as a specimen set on the ad's own copy: the\n * font file (or the web font file by URL) staged like any asset, then `font_specimen`\n * renders the letters the ad needs. `syncStaticAdBrief` keeps the specimen's text in\n * step with prompt.json.\n */\nfunction typeNodes(font: ResolvedFont | undefined, copy: string[]): Built & { ref: string | undefined } {\n if (!font) return { nodes: [], ref: undefined };\n const ingest: NodeDecl =\n \"path\" in font.slot\n ? ingestNode(\"font_headline\", font.slot.path, \"font\")\n : { id: \"font_headline\", type: \"ingest\", params: { source: \"url\", url: font.slot.url, expect: \"font\" } };\n return {\n nodes: [\n ingest,\n {\n id: \"type_specimen\",\n type: \"font_specimen\",\n inputs: { font: \"$ref:font_headline.asset\" },\n params: { text: specimenText(copy) },\n },\n ],\n ref: \"$ref:type_specimen.image\",\n };\n}\n\n/**\n * What every render asks the model for, besides the prompt and the shape: the size and the\n * quality step its profile asks for (`prompt-profiles.ts`), snapped to what the model has.\n */\nexport function renderParamsFor(genModel: string): Record<string, unknown> {\n const want = (imageProfileFor(genModel) ?? GPT_IMAGE_25_PROFILE).brief.params;\n return imageRenderParams(genModel, { size: want.imageSize ?? AD_IMAGE_SIZE, quality: want.quality ?? \"xhigh\" });\n}\n\n/** Candidates rendered: 1-3 (default 3). */\nfunction takesFor(opts: StaticAdOpts): number {\n return Math.max(1, Math.min(MAX_TAKES, opts.takes ?? MAX_TAKES));\n}\n\n/**\n * The render graph from the element slots: the variants (their prompts are the compiled\n * brief, projected by `scaffoldStaticAd` before it returns), the judge, the master and every\n * size. The source ad is not among the pictures: a competitor's image is the strongest\n * conditioning a render gets, and it came back as a near-copy (prompt-audit.md §4.3; bench E2\n * decides whether it ever returns, as a layout-only reference). The logo file goes to the\n * model, or is composited on every size, never both.\n */\nfunction renderGraph(args: {\n slots: Slot[];\n logoRef: string | undefined;\n /** The logo's other colourways, as refs: placed beside the file when one reads better on the ground. */\n colourways: string[];\n typeRef: string | undefined;\n opts: StaticAdOpts;\n plan: StaticFormatPlan;\n judgeModel: string;\n adaptModel: string;\n relayoutModel: string;\n}): NodeDecl[] {\n const { opts } = args;\n const composite = args.logoRef !== undefined && logoComposited(opts);\n return staticRenderNodes({\n genModel: opts.genModel,\n genParams: renderParamsFor(opts.genModel),\n takes: takesFor(opts),\n reference: [\n ...args.slots.map((s) => s.ref),\n ...(args.logoRef && !composite ? [args.logoRef] : []),\n ...(args.typeRef ? [args.typeRef] : []),\n ],\n specRef: \"$ref:prompt.asset\",\n judgeModel: args.judgeModel,\n adaptModel: args.adaptModel,\n relayoutModel: args.relayoutModel,\n ...(args.logoRef && !composite ? { logoRef: args.logoRef } : {}),\n plan: args.plan,\n ...(composite && args.logoRef\n ? { compositeLogo: { files: [args.logoRef, ...args.colourways], aspect: opts.brand?.logoAspect ?? LOGO_ASPECT } }\n : {}),\n prompt: UNCOMPILED,\n });\n}\n\n/** Who the face is, for a person reading the report: the family, and where it came from. */\nfunction fontLabel(font: ResolvedFont): string {\n const origin: Record<FontOrigin, string> = {\n brand_file: \"the brand's font file\",\n tokens: \"named in tokens.json, loaded as a web font\",\n brand_md: \"named in BRAND.md, loaded as a web font\",\n };\n const name =\n font.family ?? (\"path\" in font.slot ? (font.slot.path.split(\"/\").pop() ?? font.slot.path) : \"a web font\");\n return `${name} (${origin[font.origin]})`;\n}\n\n/** How the variants come back, in one clause. */\nfunction describeVariants(takes: number): string {\n const numbers = [\"No\", \"One\", \"Two\", \"Three\"];\n if (takes <= 1) return \"One finished ad is rendered (no judge)\";\n const n = numbers[takes] ?? String(takes);\n return `${n} variants of the finished ad are rendered in parallel, one request each, and a judge keeps one`;\n}\n\n/**\n * How every size is made from the one chosen picture, in one sentence: the scaffold's\n * description and report and an upgraded canvas's description all say it the same way.\n */\nexport function describeSizes(plan: StaticFormatPlan): string {\n if (plan.masterShape === \"plate\") return describePlateSizes(plan);\n const of = (from: SizePlan[\"from\"]) => plan.sizes.filter((s) => s.from === from).map((s) => s.format);\n const cuts = of(\"crop\");\n const adapted = of(\"adapt\");\n const relaid = of(\"relayout\");\n const cut =\n cuts.length > 0\n ? `; ${cuts.join(\" and \")} ${cuts.length === 1 ? \"is a cut\" : \"are cuts\"} of it that ${cuts.length === 1 ? \"keeps\" : \"keep\"} every word inside that size's safe area`\n : \"\";\n const adapt =\n adapted.length > 0\n ? `; ${adapted.join(\" and \")} ${adapted.length === 1 ? \"is\" : \"are\"} adapted from it by the reframe model (one billed request)`\n : \"\";\n const relayout =\n relaid.length > 0\n ? `; ${relaid.join(\" and \")} ${relaid.length === 1 ? \"is\" : \"are\"} the chosen ad re-laid out for that size's frame by the image model (one billed request per size): the same words, people, product and logo, re-scaled for the frame and never cut`\n : \"\";\n const closing = relaid.length > 0 ? \"\" : \" No size is rendered again.\";\n return `Every size is made from the chosen picture, rendered once at ${plan.master.format}${relayout}${cut}${adapt}.${closing}`;\n}\n\n/** `plate`: each variant's picture drawn without the ad's words, and every size cut from the chosen one. */\nfunction describePlateSizes(plan: StaticFormatPlan): string {\n const lead = plan.master.format;\n const others = plan.sizes.filter((s) => s.format !== lead);\n const tall = others.filter((s) => s.plate !== \"wide\").map((s) => s.format);\n const wide = others.filter((s) => s.plate === \"wide\").map((s) => s.format);\n const cut =\n tall.length > 0\n ? `; ${tall.join(\" and \")} ${tall.length === 1 ? \"is a cut\" : \"are cuts\"} of the chosen picture with ${tall.length === 1 ? \"its\" : \"their\"} own words set (one billed request per size)`\n : \"\";\n const widened =\n wide.length > 0\n ? `; ${wide.join(\" and \")} ${wide.length === 1 ? \"is\" : \"are\"} cut from the chosen picture extended sideways (its people and product kept pixel for pixel), with ${wide.length === 1 ? \"its\" : \"their\"} own words set`\n : \"\";\n return `Every size is cut from one picture and its words are set for that size: each variant's picture is drawn at ${plan.master.renderRatio} without the ad's words and the ${lead}'s words are set on it${cut}${widened}. Nothing in the picture is drawn twice.`;\n}\n\n/** What a run of this canvas actually does, in one paragraph: the report and the description share it. */\nfunction describeRun(args: {\n takes: number;\n logo: \"model\" | \"composite\" | null;\n font?: ResolvedFont;\n copy: number;\n inScene: number;\n plan: StaticFormatPlan;\n}): string {\n const text =\n args.copy === 0\n ? \" The ad has no copy: the picture is the ad.\"\n : args.font\n ? ` The copy is set by the model in ${fontLabel(args.font)}, shown to it as a specimen, and read back word for word by the review.`\n : \" The copy is set by the model (no brand typeface could be loaded) and read back word for word by the review.\";\n const scene = args.inScene > 0 ? ` ${args.inScene} line(s) are written on something in the scene.` : \"\";\n const mark =\n args.logo === \"composite\"\n ? \" The brand's logo file is placed on every size, inside its safe area; the model draws no logo.\"\n : args.logo === \"model\"\n ? \" The brand's logo file is given to the model to reproduce where the concept places it.\"\n : \" No logo is drawn: the concept has none, or the brand has no logo file (Meta shows the page name and picture on every ad).\";\n return `${describeVariants(args.takes)}. ${describeSizes(args.plan)}${text}${scene}${mark}`;\n}\n\n/**\n * Assemble a static-ad canvas: variants of the finished ad, one request each, a deterministic\n * prefilter and a judge, the\n * chosen picture at the master shape, and every delivered size made from it without another\n * generation (`static-topology.ts`).\n */\nexport function scaffoldStaticAd(input: unknown, elementsInput: unknown, opts: StaticAdOpts): Canvas {\n const blueprint = Blueprint.parse(input);\n const elements = MainElements.parse(elementsInput);\n const spec = specFor(input, elements, opts);\n const shape = shapeRouteOf(opts, spec);\n const plan = planStaticFormats(opts.genModel, outputFormats(blueprint, opts), formatPlanOpts(opts, shape.shape));\n const copy = copyStrings(blueprint);\n const drawLogo = logoDrawn(spec, opts);\n // As rendered: handwritten in-scene copy is set as designed type (`withRenderedLettering`).\n const designed = withRenderedLettering(spec)\n .copy.filter((l) => l.lettering === \"designed\")\n .map((l) => l.text);\n\n const spine: NodeDecl[] = [\n { ...ingestNode(\"prompt\", opts.blueprintPath ?? \"./prompt.json\", \"json\"), tags: { role: STATIC_AD_ROLE } },\n // An ad started from an idea (`baker creatives make` with no reference) has no source picture.\n ...(opts.imagePath\n ? [\n {\n id: \"original\",\n type: \"ingest\",\n params: opts.imageIsUrl\n ? { source: \"url\", url: opts.imagePath, expect: \"image\" }\n : { source: \"path\", path: opts.imagePath, expect: \"image\" },\n },\n ]\n : []),\n ];\n const els = elementNodes(elements, opts, drawLogo);\n // The type specimen serves the lines set as designed type; in-scene lettering keeps its own.\n const type = typeNodes(designed.length > 0 ? opts.brand?.font : undefined, designed);\n const conceptClass = conceptClassOf(spec);\n const render = renderGraph({\n slots: els.slots,\n logoRef: els.logoRef,\n colourways: els.colourways,\n typeRef: type.ref,\n opts,\n plan,\n judgeModel: pickImageModel(conceptClass, \"judge\"),\n adaptModel: pickImageModel(conceptClass, \"reframe\"),\n relayoutModel: pickImageModel(conceptClass, \"relayout\"),\n });\n\n const canvas: Canvas = {\n schema: \"baker-canvas/1\",\n metadata: {\n name: \"static ad reproduction\",\n description: `Scaffolded by \\`baker canvas scaffold-static-ad\\`. Edit \\`prompt.json\\` (the ad spec read from the source image) into the ad you want; every render prompt is compiled from it on every run, and every picture it names (\\`references[].image\\`, the brand's logo) is wired from it. Then \\`baker canvas run\\`. ${describeRun(\n {\n takes: takesFor(opts),\n logo: drawLogo ? (logoComposited(opts) ? \"composite\" : \"model\") : null,\n font: opts.brand?.font,\n copy: copy.length,\n inScene: inSceneText(blueprint).length,\n plan,\n },\n )}`,\n // A shape chosen on purpose stays chosen (`upgradeStaticCanvas`); why it is on its shape, chosen or routed.\n ...(opts.masterShape ? { master_shape: opts.masterShape } : {}),\n master_shape_reason: shape.reason,\n },\n nodes: [...spine, ...els.nodes, ...type.nodes, ...render],\n output: { node: \"final\", output: \"images\" },\n };\n // Where the logo goes first: every brief that keeps its slot plain plans it from there.\n projectLogoPlacement(canvas.nodes, spec);\n projectStaticBriefs(canvas, spec);\n projectAdaptBriefs(canvas, spec);\n projectFormatBriefs(canvas, spec);\n return canvas;\n}\n\n/** A blueprint entry, read loosely: the describe pass's shape is not a contract here. */\ntype Loose = Record<string, unknown>;\n\n/** The names of the source ad's advertiser and every brand it shows: none may reach a render of ours. */\nfunction sourceBrandNames(bp: Loose): string[] {\n const context = bp.source_context as Loose | undefined;\n const reference = bp.reference as Loose | undefined;\n const logos = Array.isArray(bp.brands_logos) ? (bp.brands_logos as Loose[]) : [];\n return [context?.advertiser_brand, reference?.advertiser, ...logos.map((l) => l?.brand_name)].filter(\n (n): n is string => typeof n === \"string\" && n.trim().length > 1,\n );\n}\n\n/**\n * The concept a new spec starts from: the fit made of the reference when there is one (it knows\n * what we have), else the describe pass's read of why it wins, every load-bearing element marked\n * missing until the agent names what of ours carries it (a run refuses it until then: a render\n * that kept \"the free AirPods\" of a Rippling ad would show AirPods we do not give). Nothing when\n * the read names no load-bearing element.\n */\nfunction conceptSeed(\n bp: Loose,\n fit: Pick<AdSpec, \"concept\" | \"brand_presence\" | \"recognition\"> | undefined,\n scrub: readonly string[],\n) {\n if (fit?.concept) {\n return {\n concept: fit.concept,\n ...(fit.brand_presence ? { brand_presence: fit.brand_presence } : {}),\n ...(fit.recognition ? { recognition: fit.recognition } : {}),\n };\n }\n const loadBearing = (Array.isArray(bp.load_bearing) ? (bp.load_bearing as Loose[]) : []).flatMap((l) => {\n const element = plainText(l?.element, scrub);\n const needed = plainText(l?.needs, scrub);\n const needs = needed ? { needs: needed } : {};\n return element ? [{ element, ...needs, have: \"missing\" as const }] : [];\n });\n if (loadBearing.length === 0) return {};\n const why = (bp.why_it_wins && typeof bp.why_it_wins === \"object\" ? bp.why_it_wins : {}) as Loose;\n const layers = Object.fromEntries(\n ([\"disguise\", \"voice\", \"trigger\", \"attention\", \"logic\"] as const).flatMap((k) =>\n plainText(why[k], scrub) ? [[k, plainText(why[k], scrub)]] : [],\n ),\n );\n return { concept: { why_it_wins: layers, load_bearing: loadBearing, verdict: \"adapt\" as const } };\n}\n\nconst REFERENCE_KIND: Record<string, AdReference[\"role\"]> = {\n person: \"identity\",\n animal: \"identity\",\n product: \"product\",\n};\n\n/**\n * The ad spec a new static ad starts from, written to prompt.json for the agent to rewrite:\n * the source ad's copy (each line marked lettered-in-scene or designed), its scene, its\n * mechanism, and one reference per element slot, labelled by role, with the slot that holds\n * its picture. The source's advertiser and every brand it shows are scrubbed from the text;\n * the source's own read stays as bookkeeping (`source`, `reference`), never compiled.\n */\nexport function staticAdSpec(\n blueprintInput: unknown,\n elementsInput: unknown,\n extras: {\n brand?: AdBrand | null;\n formats?: readonly string[];\n logo?: boolean;\n /** The fit made of the reference (`baker winning-ads fit`, `conceptFromFit`): seeds the concept. */\n fit?: Pick<AdSpec, \"concept\" | \"brand_presence\" | \"recognition\">;\n /** Where the ad runs (the ad set's countries, else COMPANY.md): written into the viewer. */\n market?: NonNullable<AdSpec[\"viewer\"]>[\"market\"];\n } = {},\n): AdSpec {\n const bp = (blueprintInput && typeof blueprintInput === \"object\" ? blueprintInput : {}) as Loose;\n const scrub = sourceBrandNames(bp);\n const base = adSpecFromBlueprint(bp, {\n scrub,\n ...(extras.fit?.brand_presence ? { presence: extras.fit.brand_presence } : {}),\n });\n // Only our own cast is a reference: the source's products are a competitor's, its people strangers.\n const references: AdReference[] = elementSlots(MainElements.parse(elementsInput)).flatMap(({ el, label, id }) => {\n const type = el.type.toLowerCase();\n if (type === \"logo\" || !suppliedImage(el)) return [];\n const described = [el.description, el.expression ? `with a ${el.expression} expression` : \"\"]\n .filter(Boolean)\n .join(\", \");\n const what = plainText(described, scrub) || `the ${type} in this picture`;\n const avatar = typeof el.cast_handle === \"string\" ? { avatar: el.cast_handle } : {};\n return [{ id: label, role: REFERENCE_KIND[type] ?? \"prop\", slot: id, what, ...avatar }];\n });\n const context = bp.source_context as Loose | undefined;\n const source = {\n ...(typeof context?.advertiser_brand === \"string\" ? { advertiser: context.advertiser_brand } : {}),\n ...(bp.audience !== undefined ? { audience: bp.audience } : {}),\n ...(bp.mechanism !== undefined ? { mechanism: bp.mechanism } : {}),\n };\n return AdSpecSchema.parse({\n ...base,\n schema: AD_SPEC_SCHEMA,\n references,\n ...(extras.brand ? { brand: extras.brand } : {}),\n ...(extras.formats ? { formats: [...extras.formats] } : {}),\n ...(extras.logo !== undefined ? { logo: extras.logo } : {}),\n ...conceptSeed(bp, extras.fit, scrub),\n ...(extras.market\n ? { viewer: { ...(base.viewer ?? { who: \"the people this ad is for\" }), market: extras.market } }\n : {}),\n ...(Object.keys(source).length > 0 ? { source } : {}),\n });\n}\n\n/**\n * The canvas re-rendered as a correction of a finished version: one render that takes the\n * previous ad as its first reference and changes only what `instruction` says, in place of\n * the variants, the prefilter and the judge. It feeds the master, so every size is made from\n * the corrected picture exactly as from a chosen one (each re-laid-out size renders again, its\n * input changed; nothing else renders). A correction is\n * a fresh render from a right prompt's own result, so a good version is kept rather than\n * re-rolled: the picture, the layout and the words the person already liked survive the fix.\n * `promptJson` is the content of prompt.json, which the correction's brief compiles from.\n *\n * Only for a version whose graph was never kept (a run recorded before graphs were): any other\n * version is corrected on top of its own graph instead, its variants and pick kept (`growFromVersion`).\n *\n * Pure: the scaffolded canvas in, the correction canvas out; nothing is written.\n */\nexport function fixStaticAd(\n input: unknown,\n opts: {\n instruction: string;\n previous: string;\n promptJson: unknown;\n rejected?: readonly string[];\n rules?: readonly CreativeRule[];\n },\n): Canvas {\n const canvas = input as Canvas;\n const stage = variantStage(canvas);\n // The previous ad is the picture to edit; the identity references (subjects, logo, type)\n // stay so the fix keeps them exact.\n const masterFormat = staticMasterFormat(canvas);\n const brief = fixBriefNode(canvas, stage.template as never, opts.promptJson, {\n instruction: opts.instruction,\n previous: \"$ref:previous.asset\",\n ...(opts.rejected ? { rejected: opts.rejected } : {}),\n ...(opts.rules ? { rules: opts.rules } : {}),\n ...(masterFormat ? { format: masterFormat } : {}),\n drop: stage.removed,\n }) as NodeDecl;\n const params: Record<string, unknown> = { ...brief.params };\n delete params.n;\n const fix: NodeDecl = { ...brief, id: \"fix\", params, tags: { role: STATIC_FIX_ROLE } };\n const previous: NodeDecl = {\n id: \"previous\",\n type: \"ingest\",\n params: { source: \"url\", url: opts.previous, expect: \"image\" },\n };\n return withMasterSource(canvas, stage, [previous, fix], \"$ref:fix.images#0\", {\n note: `This run corrects a finished version: ${opts.instruction.trim()}`,\n });\n}\n\n/**\n * The canvas re-run on a variant the person chose over the judge's pick: the chosen picture\n * (by the URL its run recorded) takes the place of the variants, the prefilter and the judge,\n * and feeds the master, so every size is made again from it; the only requests are the\n * re-laid-out sizes, whose input changed. The ingest\n * carries the judge's role, so the dashboard badges the chosen picture as this version's pick.\n * Only for a version whose graph was never kept (`growFromVersion` otherwise).\n *\n * Pure: the scaffolded canvas in, the re-derive canvas out; nothing is written.\n */\nexport function rederiveFromVariant(input: unknown, opts: { url: string }): Canvas {\n const canvas = input as Canvas;\n const stage = variantStage(canvas);\n const chosen: NodeDecl = {\n id: \"chosen\",\n type: \"ingest\",\n params: { source: \"url\", url: opts.url, expect: \"image\" },\n tags: { role: STATIC_PICK_ROLE },\n };\n const relaid = nodesWithRole(canvas, STATIC_ADAPT_FORMAT_ROLE).length;\n return withMasterSource(canvas, stage, [chosen], \"$ref:chosen.asset\", {\n note:\n relaid > 0\n ? `This run makes every size again from the variant the person chose; each other size is re-laid out from it (${relaid} ${relaid === 1 ? \"request\" : \"requests\"}).`\n : \"This run makes every size again from the variant the person chose; nothing is rendered.\",\n });\n}\n\n/** The lead ad's version a series ad is made from: its words and its finished pictures. */\nexport type SeriesLead = {\n slug: string;\n runId: string;\n /** The lead's words as that version drew them. */\n copy: Array<{ text: string; role?: string }>;\n /** The lead's chosen picture, at its master's shape. */\n picture: string;\n /** Each size the lead delivered, by format: a size re-laid out from it is edited from the lead's own. */\n sizes: Readonly<Record<string, string>>;\n /** The lead's design the ad's prompt.json was last given (`seriesDesignOf`), so an edit made on the ad itself is told apart. */\n design?: string;\n /** A lead on one picture: the picture its sizes are cut from (no words), every ad of the series cut from it too. */\n plate?: string;\n};\n\n/** The id of the ingest holding the lead's picture of one re-laid-out size: `lead_ad_9x16`. */\nexport function seriesLeadSizeId(format: string): string {\n return `lead_ad_${formatSlug(format)}`;\n}\n\n/**\n * The canvas of the next ad of a series, from the lead's canvas: one render takes the lead's\n * finished picture (`lead_ad`) and changes only its words, in place of the variants and the judge;\n * each re-laid-out size is the lead's own delivered size with the same words changed, so no size\n * is designed again and the series cannot drift. A size the lead did not deliver is re-laid out\n * from this ad's picture as usual; the cut sizes are cut from it as the lead's are. The reference\n * ad is dropped: the lead's picture already carries everything it gave. Its words come from this\n * ad's prompt.json; the lead's (`metadata.series.copy`) say which line each one replaces.\n *\n * `language` marks a translation of the lead: the edit names the language its words are in.\n *\n * Pure: the lead's scaffolded canvas in, the series ad's canvas out; nothing is written.\n */\nexport function seriesMemberAd(input: unknown, lead: SeriesLead, opts: { language?: string } = {}): Canvas {\n if (isPlateCanvas(input) && lead.plate)\n return plateSeriesMember(input as Canvas, { ...lead, plate: lead.plate }, opts);\n const canvas = withoutLeadPictures(input as Canvas);\n const stage = variantStage(canvas);\n const wired = stage.template.inputs?.reference;\n const kept = (Array.isArray(wired) ? wired : []).filter(\n (r): r is string => typeof r === \"string\" && !r.startsWith(\"$ref:original.\") && !stage.removed.has(refNode(r)),\n );\n const params: Record<string, unknown> = { ...stage.template.params };\n delete params.n;\n const leadAd = leadPicture(\"lead_ad\", lead.picture);\n const gen: NodeDecl = {\n id: \"gen\",\n type: \"image_generate\",\n inputs: { ...stage.template.inputs, reference: [`$ref:${leadAd.id}.asset`, ...kept] },\n params,\n tags: { role: STATIC_VARIANTS_ROLE },\n };\n const edited = withMasterSource(canvas, stage, [leadAd, gen], \"$ref:gen.images#0\", { note: \"\" });\n const nodes = edited.nodes\n .filter((n) => n.id !== \"original\")\n .flatMap((n) => {\n const format = n.tags?.role === STATIC_ADAPT_FORMAT_ROLE ? formatOfAdaptId(n.id) : null;\n const url = format ? lead.sizes[format] : undefined;\n if (!format || !url) return [n];\n const source = leadPicture(seriesLeadSizeId(format), url);\n const refs = Array.isArray(n.inputs?.reference) ? (n.inputs.reference as unknown[]) : [];\n const rest = refs.filter((r) => typeof r === \"string\" && refNode(r) !== stage.masterId);\n return [source, { ...n, inputs: { ...n.inputs, reference: [`$ref:${source.id}.asset`, ...rest] } }];\n });\n return {\n ...edited,\n metadata: {\n ...canvas.metadata,\n name: \"static ad of a series\",\n description: `The next ad of the series led by \\`${lead.slug}\\`: the lead's finished picture (\\`lead_ad\\`) with only its words changed to the copy in this ad's \\`prompt.json\\`, every other size the lead's own size with the same words changed. Edit only the copy in \\`prompt.json\\`, then \\`baker canvas run\\`. Change the lead to change the design of the whole series.`,\n series: {\n lead: lead.slug,\n run_id: lead.runId,\n copy: lead.copy.map((l) => ({ ...l })),\n ...(lead.design ? { design: lead.design } : {}),\n // A translation of the lead: its words are in this language, the lead's in another.\n ...(opts.language ? { language: opts.language } : {}),\n },\n },\n nodes,\n };\n}\n\n/** What every ad of a series carries in its metadata about its lead. */\nfunction seriesMetadata(lead: SeriesLead, opts: { language?: string }) {\n return {\n lead: lead.slug,\n run_id: lead.runId,\n copy: lead.copy.map((l) => ({ ...l })),\n ...(lead.design ? { design: lead.design } : {}),\n // A translation of the lead: its words are in this language, the lead's in another.\n ...(opts.language ? { language: opts.language } : {}),\n };\n}\n\n/**\n * The next ad of a series led by an ad on one picture: no picture is drawn. Every size is cut from\n * the lead's picture (`lead_plate`) with this ad's words set on it, in the look of the lead's own\n * size (`lead_ad`, `lead_ad_<size>`), so ten messages come out as one ad ten times, paying only\n * for the words. The lead's options, choice and corrections are gone; a lead that is itself an ad\n * of a series hands on its own pictures. Pure.\n */\nfunction plateSeriesMember(canvas: Canvas, lead: SeriesLead & { plate: string }, opts: { language?: string }): Canvas {\n const master = nodesWithRole(canvas, STATIC_MASTER_ROLE)[0];\n const leadSize = refNode(String(master?.inputs?.image ?? \"\"));\n const stage = new Set(\n [\n ...nodesWithRole(canvas, STATIC_VARIANT_CALL_ROLE),\n ...nodesWithRole(canvas, STATIC_LEAD_ROLE),\n ...nodesWithRole(canvas, STATIC_VARIANTS_ROLE),\n ...nodesWithRole(canvas, VARIANT_PREFILTER_ROLE),\n ...nodesWithRole(canvas, SERIES_LEAD_ROLE),\n ].map((n) => n.id),\n );\n const pictures: NodeDecl[] = [\n leadPicture(\"lead_plate\", lead.plate),\n leadPicture(\"lead_ad\", lead.picture),\n ...Object.entries(lead.sizes).map(([format, url]) => leadPicture(seriesLeadSizeId(format), url)),\n ];\n const own = new Set(pictures.map((p) => p.id));\n const plateRef = (ref: unknown) => typeof ref === \"string\" && !ref.startsWith(\"$ref:plate_wide.\");\n const nodes = canvas.nodes\n .filter((n) => !stage.has(n.id) && n.id !== \"original\")\n .map((n): NodeDecl => {\n if (n.type === \"static_plate\") return { ...n, inputs: { ...n.inputs, image: \"$ref:lead_plate.asset\" } };\n if (n.type !== \"static_format\") return n;\n const format = String(n.params?.format ?? \"\");\n const style = n.id === leadSize ? \"lead_ad\" : seriesLeadSizeId(format);\n const { previous: _previous, ...rest } = n.inputs ?? {};\n return {\n ...n,\n inputs: {\n ...rest,\n ...(plateRef(n.inputs?.plate) ? { plate: \"$ref:lead_plate.asset\" } : {}),\n ...(own.has(style) ? { style: `$ref:${style}.asset` } : {}),\n },\n };\n });\n const at = nodes.findIndex((n) => n.type === \"static_format\");\n return {\n ...canvas,\n metadata: {\n ...canvas.metadata,\n name: \"static ad of a series\",\n description: `The next ad of the series led by \\`${lead.slug}\\`: every size cut from the lead's picture (\\`lead_plate\\`) with this ad's own words, from its \\`prompt.json\\`, set in the look of the lead's own size; no picture is drawn. Edit only the copy in \\`prompt.json\\`, then \\`baker canvas run\\`. Change the lead to change the design of the whole series.`,\n series: seriesMetadata(lead, opts),\n },\n nodes: [...nodes.slice(0, at < 0 ? nodes.length : at), ...pictures, ...nodes.slice(at < 0 ? nodes.length : at)],\n };\n}\n\n/**\n * A lead that is itself an ad of a series (an angle ad leading its translations) has a canvas made\n * from its own lead's pictures: those are dropped, each size re-laid out from the master again, so\n * the next ad is made from this lead's pictures alone. A canvas with no lead picture is returned as is.\n */\nfunction withoutLeadPictures(canvas: Canvas): Canvas {\n const leads = new Set(canvas.nodes.filter((n) => n.tags?.role === SERIES_LEAD_ROLE).map((n) => n.id));\n if (leads.size === 0) return canvas;\n const master = nodesWithRole(canvas, STATIC_MASTER_ROLE)[0]?.id ?? \"master\";\n const nodes = canvas.nodes\n .filter((n) => !leads.has(n.id))\n .map((n) => {\n const refs = n.inputs?.reference;\n if (!Array.isArray(refs) || !refs.some((r) => typeof r === \"string\" && leads.has(refNode(r)))) return n;\n const relaid = n.tags?.role === STATIC_ADAPT_FORMAT_ROLE;\n const kept = refs.filter((r) => !(typeof r === \"string\" && leads.has(refNode(r))));\n return { ...n, inputs: { ...n.inputs, reference: relaid ? [`$ref:${master}.image`, ...kept] : kept } };\n });\n return { ...canvas, nodes };\n}\n\nfunction leadPicture(id: string, url: string): NodeDecl {\n return { id, type: \"ingest\", params: { source: \"url\", url, expect: \"image\" }, tags: { role: SERIES_LEAD_ROLE } };\n}\n\n/** The node a `$ref:` names. */\nfunction refNode(ref: string): string {\n return ref.match(/^\\$ref:([a-z][a-z0-9_]*)\\./)?.[1] ?? \"\";\n}\n\ntype VariantStage = { removed: Set<string>; template: NodeDecl; masterId: string; prefilterId?: string };\n\n/** The part of a static canvas that produces the chosen picture, and the master it feeds. */\nfunction variantStage(canvas: Canvas): VariantStage {\n const variants = nodesWithRole(canvas, STATIC_VARIANTS_ROLE);\n const calls = nodesWithRole(canvas, STATIC_VARIANT_CALL_ROLE);\n const template = [...variants, ...calls].find((n) => n.type === \"image_generate\");\n const master = nodesWithRole(canvas, STATIC_MASTER_ROLE)[0];\n if (!template || !master) throw new Error(\"not a static ad canvas: it renders no variants to correct\");\n // The prefilter stays when it feeds the master: it frames the one picture as it frames a variant.\n const masterInputs = JSON.stringify(master.inputs ?? {});\n const prefilter = nodesWithRole(canvas, VARIANT_PREFILTER_ROLE).find((n) => masterInputs.includes(`$ref:${n.id}.`));\n const removed = new Set(\n [\n ...variants,\n ...calls,\n ...nodesWithRole(canvas, VARIANT_PREFILTER_ROLE).filter((n) => n !== prefilter),\n ...nodesWithRole(canvas, STATIC_PICK_ROLE),\n ].map((n) => n.id),\n );\n return {\n removed,\n template: template as unknown as NodeDecl,\n masterId: master.id,\n ...(prefilter ? { prefilterId: prefilter.id } : {}),\n };\n}\n\n/** The canvas with its variant stage replaced by `source` nodes whose `ref` the master now reads. */\nfunction withMasterSource(\n canvas: Canvas,\n stage: VariantStage,\n source: NodeDecl[],\n ref: string,\n opts: { note: string },\n): Canvas {\n // A picture drawn at another shape than the master's is cut where its words stay whole (Dev, Oct\n // 2026: a correction cut about its centre lost the 4:5's headline and button): through the prefilter,\n // which reads them, never asking the judge about one picture.\n const kept = canvas.nodes\n .filter((n) => !stage.removed.has(n.id))\n .map((n) => {\n if (n.id === stage.prefilterId) {\n const { judge_model: _judge, judge_prompt: _prompt, ...params } = n.params ?? {};\n return { ...n, inputs: { ...n.inputs, images: [ref] }, params };\n }\n return n.id === stage.masterId && !stage.prefilterId ? { ...n, inputs: { ...n.inputs, image: ref } } : n;\n });\n const at = kept.findIndex((n) => n.id === (stage.prefilterId ?? stage.masterId));\n const description = `${canvas.metadata?.description ?? \"\"} ${opts.note}`;\n return {\n ...canvas,\n metadata: { ...canvas.metadata, description: description.trim() },\n nodes: [...kept.slice(0, at), ...source, ...kept.slice(at)],\n };\n}\n\ntype StaticAdReport = {\n element_count: number;\n elements: Array<{ label: string; type: string; description: string | null; asset_todo: string }>;\n /** One paragraph on what a run does: candidates, judge, text, logo, formats. */\n summary: string;\n /** The typeface shown to the model, or null when none could be loaded. */\n font: string | null;\n /** Whether the logo is given to the model, and why. */\n logo: { drawn: boolean; why: string };\n /** A reference that pictures nothing but copy: the ad is its words on the brand's colours. */\n text_forward: boolean;\n /** Lines written on something in the scene. */\n in_scene_text: string[];\n /** Always empty: the reference's living heroes are no longer slots to fuse into a sheet (kept for readers of the report). */\n actor_sheets: string[];\n /** The shape the variants render at (the model's nearest to the master's format). */\n aspect_ratio: string;\n /** The placement preset delivered, or null for a single format. */\n placements: AdFormatPlatform | null;\n /** The platforms the sizes came from, or null when they came from a preset. */\n platforms: string[] | null;\n /** The size designed first, or null when no platform named one. */\n lead: string | null;\n /** Fixed-pixel banners the platforms require that a re-laid-out picture cannot make (`728x90`): made apart. */\n banners: string[];\n /** Every delivered format, each exact. */\n output_formats: string[];\n /** The master and how each size is made from it (the master itself, a cut, or an adapt; never a re-render). */\n format_plan: StaticFormatPlan;\n /** How the sizes are made (`plate`: cut from one picture; `relayout`: laid out again), and why. */\n master_shape: { shape: MasterShape; reason: string };\n /** Variants rendered. */\n takes: number;\n /** Whether a judge picks between the variants (more than one). */\n judged: boolean;\n /** What makes the source ad work, to rebuild for our brand rather than lose in the rewrite. */\n winning_mechanisms: WinningMechanism[];\n /** Describe-contract keys the blueprint came back without. */\n describe_gaps: Array<\"fonts\" | \"winning_mechanisms\">;\n};\n\nfunction logoWhy(spec: AdSpec, opts: StaticAdOpts): string {\n if (!opts.brand?.logoPath) {\n return 'src/brand/logos/ has no real logo file, so none is drawn (never a stand-in). Add the file: every run wires it while prompt.json keeps `\"logo\": true`.';\n }\n if (!spec.logo) {\n return 'prompt.json has `\"logo\": false`, so none is drawn: Meta shows the page name and picture on every ad.';\n }\n return logoComposited(opts)\n ? `The brand logo ${opts.brand.logoPath} is placed on every size inside its safe area; the model draws none.`\n : `The brand logo ${opts.brand.logoPath} is given to the model as a reference to reproduce where the concept places it, never invented.`;\n}\n\n/** Human-facing checklist the command prints — the real assets to supply before running. */\nexport function staticAdReport(input: unknown, elementsInput: unknown, opts: StaticAdOpts): StaticAdReport {\n const blueprint = Blueprint.parse(input);\n const elements = MainElements.parse(elementsInput);\n const spec = specFor(input, elements, opts);\n const shape = shapeRouteOf(opts, spec);\n const plan = planStaticFormats(opts.genModel, outputFormats(blueprint, opts), formatPlanOpts(opts, shape.shape));\n const drawLogo = logoDrawn(spec, opts);\n const takes = takesFor(opts);\n const inScene = inSceneText(blueprint).map((t) => t.text);\n return {\n element_count: elements.length,\n elements: assignElementLabels(elements, \"static\").map(({ el, label }) => ({\n label,\n type: el.type,\n description: el.description ?? null,\n asset_todo: suppliedImage(el)\n ? \"none: cast from a company Avatar's identity sheet\"\n : el.type.toLowerCase() === \"person\"\n ? \"description-only casting: prefer a suitable ready company Avatar via --avatar, including for a single ad\"\n : el.type.toLowerCase() === \"logo\"\n ? drawLogo\n ? `none: the brand's own logo ${opts.brand?.logoPath} is given to the model, never the reference's`\n : \"none: no logo is drawn (the logo is optional)\"\n : \"none: described in words, never the reference's own; to show ours, add a reference with its `image` in prompt.json\",\n })),\n summary: describeRun({\n takes,\n logo: drawLogo ? (logoComposited(opts) ? \"composite\" : \"model\") : null,\n font: opts.brand?.font,\n copy: copyStrings(blueprint).length,\n inScene: inScene.length,\n plan,\n }),\n font: opts.brand?.font ? fontLabel(opts.brand.font) : null,\n logo: { drawn: drawLogo, why: logoWhy(spec, opts) },\n text_forward: isTextForward(blueprint),\n in_scene_text: inScene,\n actor_sheets: [],\n aspect_ratio: plan.master.renderRatio,\n placements: opts.placements ?? null,\n platforms: opts.delivery ? [...opts.delivery.platforms] : null,\n lead: opts.delivery?.lead ?? null,\n banners: opts.delivery ? [...opts.delivery.banners] : [],\n output_formats: plan.sizes.map((f) => f.format),\n format_plan: plan,\n master_shape: shape,\n takes,\n judged: takes > 1,\n winning_mechanisms: winningMechanisms(blueprint),\n describe_gaps: describeGaps(blueprint),\n };\n}\n","/** A company Avatar resolved for casting: the identity sheet a slot grounds on, and the words it is described with. */\nexport type CastAvatar = { sheetUrl: string; subjectDescription?: string; handle?: string };\n\n/**\n * The fields a deconstruct records about who a person IS (not what they do or wear in\n * this ad). They describe the source ad's person, so a cast Avatar replaces them.\n */\nconst SOURCE_IDENTITY_FIELDS = [\n \"perceived_age_band\",\n \"perceived_gender_presentation\",\n \"perceived_ethnicity_or_skin_tone\",\n \"hair\",\n \"facial_hair\",\n \"build_body_type\",\n \"distinguishing_features\",\n] as const;\n\n/**\n * Rewrite a blueprint's person entry for the Avatar cast in their place: the Avatar's\n * words, verbatim, and none of the source person's face or body. That entry reaches the\n * render as the target blueprint, and a sheet and words that describe two people render\n * a third. In place — callers pass their own clone.\n */\nexport function recastPersonEntry(entry: Record<string, unknown>, avatarDescription: string): void {\n for (const field of SOURCE_IDENTITY_FIELDS) delete entry[field];\n entry.description = avatarDescription;\n}\n\ntype CastableElement = { type: string; label?: string; same_as?: string | null };\n\n/**\n * How a scaffold casts: whether a `same_as` look of a cast person is that person too (a\n * video's recurring cast can change clothes; a static ad's selection never links looks),\n * and whether the slot is told its picture is already a turnaround (a video builds a sheet\n * from any other picture, so it must be told; a static ad never sheets a person).\n */\ntype CastingRules = { looks: boolean; markSheet: boolean };\n\nconst castsSlot = (el: CastableElement, rules: CastingRules): boolean =>\n el.type.toLowerCase() === \"person\" && !(rules.looks && el.same_as);\n\n/**\n * Cast company Avatars into the person slots, in order: the first person gets the first\n * avatar, and so on. The slot takes the avatar's identity sheet as its picture and its\n * subject description as the words, so the render shows the brand's own cast. With `looks`,\n * a `same_as` look of a cast person grounds on that person's sheet too — it is the same face\n * in other clothes. A person left without an avatar keeps its TODO: casting nobody is how a\n * canvas renders a stranger.\n */\nexport function castAvatarsInOrder<T extends CastableElement>(\n elements: readonly T[],\n avatars: readonly CastAvatar[],\n rules: CastingRules,\n): T[] {\n const sheet = (avatar: CastAvatar) => ({\n source_image: avatar.sheetUrl,\n ...(avatar.handle ? { cast_handle: avatar.handle } : {}),\n ...(rules.markSheet ? { source_is_sheet: true } : {}),\n });\n const byLabel = new Map<string, CastAvatar>();\n let next = 0;\n const cast = elements.map((el) => {\n const avatar = castsSlot(el, rules) ? avatars[next] : undefined;\n if (!avatar) return el;\n next += 1;\n if (el.label) byLabel.set(el.label, avatar);\n const description = avatar.subjectDescription?.trim();\n return { ...el, ...(description ? { description } : {}), ...sheet(avatar) };\n });\n if (!rules.looks) return cast;\n return cast.map((el) => {\n const avatar = el.same_as ? byLabel.get(el.same_as) : undefined;\n return avatar ? { ...el, ...sheet(avatar) } : el;\n });\n}\n\n/**\n * The avatar handles `castAvatarsInOrder` had no person for, in the order given. A\n * selection can hold fewer people than were cast — a one-scene presenter the video\n * selection drops as non-recurring, a second handle on a one-person ad — and an uncast\n * avatar must be said, not assumed.\n */\nexport function avatarsLeftUncast(\n elements: readonly CastableElement[],\n handles: readonly string[],\n rules: CastingRules,\n): string[] {\n return handles.slice(elements.filter((el) => castsSlot(el, rules)).length);\n}\n\n/** A text's words that carry meaning, folded: accents off, short words out. */\nfunction meaningWords(text: string): Set<string> {\n return new Set(\n text\n .normalize(\"NFD\")\n .replace(/\\p{M}/gu, \"\")\n .toLowerCase()\n .split(/[^\\p{L}\\p{N}]+/u)\n .filter((w) => w.length >= 4 || /^\\d{2}$/.test(w))\n .map((w) => (w.length > 5 ? w.slice(0, 5) : w)),\n );\n}\n\n/**\n * The avatars in the order they should be cast for `persona` (who the ad is for, in words):\n * the best match first, by the words their descriptions share with it (D2: casting followed the\n * order the handles were passed in, not who the ad is for); a tie keeps the given order. Pure.\n */\nexport function avatarsByPersona<T extends CastAvatar>(avatars: readonly T[], persona: string | undefined): T[] {\n if (!persona?.trim()) return [...avatars];\n const wanted = meaningWords(persona);\n const score = (avatar: T) => [...meaningWords(avatar.subjectDescription ?? \"\")].filter((w) => wanted.has(w)).length;\n return avatars\n .map((avatar, index) => ({ avatar, index, score: score(avatar) }))\n .sort((a, b) => b.score - a.score || a.index - b.index)\n .map(({ avatar }) => avatar);\n}\n","/**\n * A static ad scaffolded before the one-picture topology, upgraded in place on its next\n * render.\n *\n * The old graph rendered up to three takes (`ad_a`/`ad_b`/`ad_c`, or `ad`), judged them\n * (`pick`), then re-generated every other format from the winner (`ad_4x5`, `ad_9x16`) and\n * centre-cropped a shape the model lacked (`fit_4x5`). The upgrade keeps everything the\n * creative owns (prompt.json, the source ad, every element slot, sheet, logo and type\n * specimen, the generation model and its request params, the judge's model, the delivered\n * formats and their order) and swaps the render part for the graph `static-topology.ts`\n * builds: one request per variant, prefilter, judge, master, and sizes made from it.\n *\n * A canvas already on the current graph but scaffolded before the safe fit gets only that:\n * a `static_safe_fit` node after each 9:16 an interface covers, every other node kept, so\n * nothing upstream renders again.\n *\n * A one-picture graph planned with a retired master shape (the band master: a square master\n * whose scene was extended into the 9:16 and pasted back, the 4:5 cut from that) is rebuilt\n * the same way. Only a dev deployment that ran this branch's CLI can hold one.\n *\n * It runs in `prepareCanvas` before the brief projection, so the upgraded graph is what is\n * written, fingerprinted (a `v2:` fingerprint, which never reads as stale against the bare\n * one the old render recorded) and rendered. Run records of the old graph are untouched and\n * stay readable: every reader finds nodes by role and falls back to the old ids.\n *\n * Pure: canvas in, canvas out.\n */\nimport { pickImageModel } from \"../lib/image-model-router.ts\";\nimport type { NodeDecl } from \"../schema/canvas.ts\";\nimport {\n BRAND_LOGO_ROLE,\n isStaticBriefCanvas,\n STATIC_AD_ROLE,\n STATIC_CANDIDATE_ROLE,\n STATIC_RELAY_ROLE,\n seriesOf,\n} from \"./static-render-briefs.ts\";\nimport { staticShapeFor } from \"./static-shape-route.ts\";\nimport { MASTER_SHAPES, type MasterShape, planStaticFormats } from \"./static-sizes.ts\";\nimport {\n type CompositeLogo,\n formatSlug,\n isPlateCanvas,\n LOGO_COMPOSITE_ROLE,\n STATIC_ADAPT_FORMAT_ROLE,\n STATIC_ADAPT_ROLE,\n STATIC_FORMAT_ROLE,\n STATIC_LEAD_ROLE,\n STATIC_MASTER_ROLE,\n STATIC_PICK_ROLE,\n STATIC_PLACE_ROLE,\n STATIC_PLATE_ROLE,\n STATIC_SAFE_FIT_ROLE,\n STATIC_SIZE_ROLE,\n STATIC_VARIANT_CALL_ROLE,\n STATIC_VARIANTS_ROLE,\n safeFitNode,\n staticRenderNodes,\n VARIANT_PREFILTER_ROLE,\n} from \"./static-topology.ts\";\nimport { describeSizes, renderParamsFor } from \"./staticAd.ts\";\n\ntype Node = {\n id: string;\n type: string;\n params?: Record<string, unknown>;\n inputs?: Record<string, unknown>;\n tags?: { role?: string };\n};\n\nconst TAKE_ID = /^ad(?:_[a-c])?$/;\nconst RELAY_ID = /^ad_(\\d+)x(\\d+)$/;\nconst FIT_ID = /^fit_(\\d+)x(\\d+)$/;\nconst SIZE_ID = /^(?:size|safe|logo)_([0-9_]+x[0-9_]+)$/;\nconst RATIO = /^\\d+(?:\\.\\d+)?:\\d+$/;\nconst REF_ID = /\\$ref:([a-z][a-z0-9_]*)\\.[a-z_]+(?:#\\d+)?/g;\n\n/** A placeholder prompt: the brief projection compiles the real one right after. */\nconst UNCOMPILED = \"compiled from prompt.json\";\n\n/** Request params a take carried that are the model's own, not the shape (its picture size included), the count or the prompt. */\nfunction carriedParams(take: Node): Record<string, unknown> {\n const { prompt: _p, aspect_ratio: _a, n: _n, model: _m, image_size: _s, ...rest } = take.params ?? {};\n return rest;\n}\n\nfunction refsOf(value: unknown): string[] {\n const list = Array.isArray(value) ? value : value === undefined ? [] : [value];\n return list.filter((r): r is string => typeof r === \"string\");\n}\n\n/** How a sentence of the old description said the run was made, to be replaced by the new one. */\nconst OLD_RUN_SENTENCE =\n /(?:One|Two|Three) finished ads? (?:is|are) rendered[^.]*?(?:\\.|; (?:the other (?:\\d+ )?formats? (?:is|are) the chosen ad re-laid by the model\\.))/;\n/** How a one-picture graph's description said its sizes were made (`describeSizes`), to be replaced by the new one. */\nconst SIZES_SENTENCE =\n /Every size is made from the chosen picture, rendered once at [\\s\\S]*?\\.(?=\\s|$)(?: No size is rendered again\\.)?|Every size is cut from one picture and its words are set [\\s\\S]*? Nothing in the picture is drawn twice\\./;\n\n/** The roles of the band-master graph's extended tallest size: the frame, the extend request, the paste-back. */\nconst EXTENDED_ROLES = [\"static_extend_frame\", \"static_extend\", \"static_pasteback\"];\n/** Every role of the render part of a topology graph: what the upgrade replaces. */\nconst RENDER_ROLES = new Set([\n STATIC_VARIANTS_ROLE,\n STATIC_VARIANT_CALL_ROLE,\n VARIANT_PREFILTER_ROLE,\n STATIC_PICK_ROLE,\n STATIC_MASTER_ROLE,\n STATIC_SIZE_ROLE,\n STATIC_ADAPT_ROLE,\n STATIC_ADAPT_FORMAT_ROLE,\n STATIC_SAFE_FIT_ROLE,\n STATIC_PLACE_ROLE,\n LOGO_COMPOSITE_ROLE,\n STATIC_LEAD_ROLE,\n STATIC_FORMAT_ROLE,\n STATIC_PLATE_ROLE,\n ...EXTENDED_ROLES,\n]);\n\n/** What the old graph carried that the new one is built from. */\nexport type OldGraph = {\n /** The render whose model, params and pictures the variants keep. */\n template: Node;\n takes: number;\n removed: Node[];\n judgeModel?: string;\n placements?: string[];\n /** The size its platform designs first and the platforms the sizes were planned for, as the prefilter kept them. */\n lead?: string;\n platforms?: string[];\n compositeLogo?: CompositeLogo;\n /** The sentence of the old description that said how the run was made. */\n sentence: RegExp;\n};\n\n/** What the run says an upgraded static ad now makes, by the shape it was rebuilt on. Pure. */\nexport function upgradeNote(canvas: unknown): string {\n const kept = \"(prompt.json, assets and history unchanged)\";\n return isPlateCanvas(canvas)\n ? `[upgrade] this static ad now makes all its sizes from one picture: every size is cut from one picture drawn without its words, one request per variant, and each size's words set for it ${kept}`\n : `[upgrade] this static ad now makes all its sizes from one picture: one request per variant, a judge, then the pick delivered at the lead size and every other size re-laid out from it ${kept}`;\n}\n\n/**\n * The shape an existing static ad is rebuilt on, when its graph must be rebuilt: none for an ad of\n * a series (made from its lead's picture, on its lead's shape); else the one asked for, else the one\n * it was scaffolded on by choice, else the re-laid-out shape every static ad was made on before one\n * picture (ADR 0014). A run never moves an existing creative onto one picture by itself (owner, Oct\n * 2026): only an explicit ask (`--master-shape plate`) or making the creative again does.\n */\nfunction shapeToKeep(canvas: unknown, asked: MasterShape | undefined): MasterShape | undefined {\n if (seriesOf(canvas)) return undefined;\n const chosen = (canvas as { metadata?: { master_shape?: unknown } } | null)?.metadata?.master_shape;\n return asked ?? MASTER_SHAPES.find((s) => s === chosen) ?? \"relayout\";\n}\n\n/**\n * The new graph for an old static canvas, and whether anything changed. Two older graphs\n * upgrade: the takes-and-re-lays graph (v1), and a one-picture graph whose master shape is\n * retired (the band master: the square extended into the 9:16 and pasted back). A canvas\n * already on the current graph, a hand-built one and anything that is not a static ad come\n * back as given.\n */\nexport function upgradeStaticCanvas(\n input: unknown,\n opts: { masterShape?: MasterShape } = {},\n): { canvas: unknown; upgraded: boolean } {\n const holder = input as { nodes?: unknown; metadata?: { description?: unknown } } | null;\n if (!holder || !Array.isArray(holder.nodes) || !isStaticBriefCanvas(holder))\n return { canvas: input, upgraded: false };\n const nodes = holder.nodes as Node[];\n const target = shapeToKeep(holder, opts.masterShape) ?? \"relayout\";\n const old = v1Graph(nodes) ?? retiredShapeGraph(nodes, shapeToKeep(holder, opts.masterShape));\n // Sizes cut from one picture set their words inside the band themselves: no judge node, no safe fit.\n if (!old && isPlateCanvas(holder)) return { canvas: input, upgraded: false };\n if (!old) {\n const unjudged = withoutJudgeNode(holder, nodes);\n const fitted = withSafeFit(unjudged.canvas as { nodes?: unknown }, (unjudged.canvas as { nodes: Node[] }).nodes);\n return { canvas: fitted.canvas, upgraded: unjudged.upgraded || fitted.upgraded };\n }\n const formats = deliveredFormats(nodes, old);\n const genModel = String(old.template.params?.model ?? \"\");\n const plan = planStaticFormats(genModel, formats, {\n masterShape: target,\n ...(old.placements ? { placements: old.placements } : {}),\n ...(old.lead ? { lead: old.lead } : {}),\n ...(old.platforms ? { platforms: old.platforms } : {}),\n });\n return { canvas: rebuildRenderPart(holder, old, plan), upgraded: true };\n}\n\n/**\n * A canvas not yet rendered, moved onto the shape its spec now routes to (`staticShapeFor`), with\n * the reason recorded: `baker creatives make` scaffolds on a proven ad before its fit answers, and\n * the concept seeded after decides what the ad keeps of it. A shape chosen (`--master-shape`), an ad\n * of a series and a graph with no render part are left as they are. Call it only before a first\n * render: a rendered creative stays on its shape (`shapeToKeep`). Pure.\n */\nexport function reroutedOnSpec(input: unknown, spec: unknown): { canvas: unknown; rerouted: boolean } {\n const holder = input as { nodes?: unknown; metadata?: Record<string, unknown> } | null;\n if (!holder || !isStaticBriefCanvas(holder) || seriesOf(holder) || holder.metadata?.master_shape !== undefined)\n return { canvas: input, rerouted: false };\n const old = renderGraph(holder);\n const route = staticShapeFor(spec);\n const prefilter = (holder.nodes as Node[]).find((n) => n.tags?.role === VARIANT_PREFILTER_ROLE);\n if (!old || prefilter?.params?.master_shape === route.shape) return { canvas: input, rerouted: false };\n const plan = planStaticFormats(\n String(old.template.params?.model ?? \"\"),\n deliveredFormats(holder.nodes as Node[], old),\n {\n masterShape: route.shape,\n ...(old.placements ? { placements: old.placements } : {}),\n ...(old.lead ? { lead: old.lead } : {}),\n ...(old.platforms ? { platforms: old.platforms } : {}),\n },\n );\n const rebuilt = rebuildRenderPart(holder, old, plan) as { metadata?: Record<string, unknown> };\n return {\n canvas: { ...rebuilt, metadata: { ...rebuilt.metadata, master_shape_reason: route.reason } },\n rerouted: true,\n };\n}\n\n/** The formats a graph delivers, as its final collect labels them (else the render's own shape). */\nfunction deliveredFormats(nodes: Node[], old: OldGraph): string[] {\n const labels = nodes.find((n) => n.type === \"collect\" && n.id === \"final\")?.params?.labels;\n return Array.isArray(labels) && labels.length > 0 && labels.every((l) => typeof l === \"string\" && RATIO.test(l))\n ? (labels as string[])\n : [String(old.template.params?.aspect_ratio ?? \"9:16\")];\n}\n\n/**\n * The graph with its render part (`old.removed`) replaced by the one `plan` makes: everything\n * else the creative owns is kept, and anything hand-added that read a removed node reads what\n * replaced it. The variants keep their model, params, pictures and count, the judge its model.\n */\nexport function rebuildRenderPart(\n holder: { nodes?: unknown; metadata?: { description?: unknown } },\n old: OldGraph,\n plan: ReturnType<typeof planStaticFormats>,\n): unknown {\n const nodes = holder.nodes as Node[];\n const removed = new Set(old.removed.map((n) => n.id));\n const formats = deliveredFormats(nodes, old);\n const genModel = String(old.template.params?.model ?? \"\");\n const promptIngest = nodes.find((n) => n.type === \"ingest\" && (n.tags?.role === STATIC_AD_ROLE || n.id === \"prompt\"));\n const reference = refsOf(old.template.inputs?.reference).filter((r) => {\n const id = r.match(/^\\$ref:([a-z][a-z0-9_]*)\\./)?.[1];\n return id !== undefined && id !== \"original\" && !removed.has(id);\n });\n const built = staticRenderNodes({\n genModel,\n genParams: { ...renderParamsFor(genModel), ...carriedParams(old.template) },\n takes: old.takes,\n reference,\n specRef: `$ref:${promptIngest?.id ?? \"prompt\"}.asset`,\n judgeModel: old.judgeModel ?? pickImageModel(\"designed\", \"judge\"),\n adaptModel: pickImageModel(\"designed\", \"reframe\"),\n relayoutModel: pickImageModel(\"designed\", \"relayout\"),\n ...logoOf(nodes, reference),\n ...(old.compositeLogo ? { compositeLogo: old.compositeLogo } : {}),\n plan,\n prompt: UNCOMPILED,\n });\n\n // Anything hand-added that read an old render now reads what replaced it: the chosen\n // picture for a take, the judge or the master; the size for a re-lay, a crop or the\n // extended picture.\n const sizeRef = (format: string | undefined) => {\n const size = plan.sizes.find((s) => s.format === format);\n if (!size || size.format === plan.master.format || size.from === \"master\") return \"$ref:master.image\";\n return `$ref:${size.from === \"plate\" ? \"format\" : \"size\"}_${formatSlug(size.format)}.image`;\n };\n const extended = extendedFormat(nodes, formats);\n const replacement = (id: string): string => {\n const shaped = id.match(RELAY_ID) ?? id.match(FIT_ID);\n if (shaped) return sizeRef(`${shaped[1]}:${shaped[2]}`);\n const slug = id.match(SIZE_ID)?.[1];\n if (slug) return sizeRef(formats.find((f) => formatSlug(f) === slug));\n const node = nodes.find((n) => n.id === id);\n return node?.tags?.role && EXTENDED_ROLES.includes(node.tags.role) ? sizeRef(extended) : \"$ref:master.image\";\n };\n const rewire = (node: Node): Node => {\n if (!node.inputs) return node;\n const text = JSON.stringify(node.inputs);\n const next = text.replace(REF_ID, (ref, id: string) => (removed.has(id) && id !== \"final\" ? replacement(id) : ref));\n return next === text ? node : { ...node, inputs: JSON.parse(next) as Record<string, unknown> };\n };\n\n const firstRemoved = nodes.findIndex((n) => removed.has(n.id));\n const kept = nodes.filter((n) => !removed.has(n.id)).map(rewire);\n const at = nodes.slice(0, firstRemoved).filter((n) => !removed.has(n.id)).length;\n const description = holder.metadata?.description;\n const canvas = {\n ...holder,\n ...(typeof description === \"string\"\n ? { metadata: { ...holder.metadata, description: upgradedDescription(description, old, plan) } }\n : {}),\n nodes: [...kept.slice(0, at), ...(built as unknown as Node[]), ...kept.slice(at)] as unknown as NodeDecl[],\n };\n return canvas;\n}\n\n/**\n * A current graph scaffolded with its judge node (`pick`, reading the prefilter's variants):\n * the node goes, everything that read it reads the prefilter's chosen picture, and the prefilter\n * takes the judge's model, asking it only on a real tie (bench, Sept 2026: it decided 5 of 59\n * runs). Every other node is kept as it is.\n */\nfunction withoutJudgeNode(holder: { nodes?: unknown }, nodes: Node[]): { canvas: unknown; upgraded: boolean } {\n const prefilter = nodes.find((n) => n.tags?.role === VARIANT_PREFILTER_ROLE);\n const pick = nodes.find(\n (n) =>\n n.type === \"image_select\" &&\n n.tags?.role === STATIC_PICK_ROLE &&\n n.inputs?.images === `$ref:${prefilter?.id}.images`,\n );\n if (!prefilter || !pick) return { canvas: holder, upgraded: false };\n const chosen = `$ref:${prefilter.id}.image`;\n const takes = nodes.filter((n) => n.type === \"image_generate\" && n.tags?.role === STATIC_VARIANT_CALL_ROLE).length;\n const judge = typeof pick.params?.model === \"string\" && takes > 1 ? { judge_model: pick.params.model } : {};\n const next = nodes.flatMap((n): Node[] => {\n if (n.id === pick.id) return [];\n if (n.id === prefilter.id) return [{ ...n, params: { ...n.params, ...judge } }];\n if (!n.inputs) return [n];\n const text = JSON.stringify(n.inputs);\n const rewired = text.replace(new RegExp(`\\\\$ref:${pick.id}\\\\.images(?:#0)?`, \"g\"), chosen);\n return [rewired === text ? n : { ...n, inputs: JSON.parse(rewired) as Record<string, unknown> }];\n });\n return { canvas: { ...holder, nodes: next }, upgraded: true };\n}\n\n/**\n * A current graph without the safe fit, given one after each 9:16 Reels or Stories covers:\n * between the size (or the master, or what the logo composite reads) and its reader. Every\n * other node is kept as it is, so their cached outputs still hold.\n */\nfunction withSafeFit(holder: { nodes?: unknown }, nodes: Node[]): { canvas: unknown; upgraded: boolean } {\n const prefilter = nodes.find((n) => n.tags?.role === VARIANT_PREFILTER_ROLE);\n const final = nodes.find((n) => n.type === \"collect\" && n.id === \"final\");\n const labels = final?.params?.labels;\n const images = final?.inputs?.images;\n if (\n !prefilter ||\n nodes.some((n) => n.tags?.role === STATIC_SAFE_FIT_ROLE) ||\n !Array.isArray(labels) ||\n !Array.isArray(images)\n )\n return { canvas: holder, upgraded: false };\n const raw = prefilter.params?.placements;\n const placements = Array.isArray(raw) && raw.every((p) => typeof p === \"string\") ? (raw as string[]) : undefined;\n let next = [...nodes];\n const byId = (id: string | undefined) => next.find((n) => n.id === id);\n const idOf = (ref: unknown) => (typeof ref === \"string\" ? ref.match(/^\\$ref:([a-z][a-z0-9_]*)\\./)?.[1] : undefined);\n labels.forEach((format, i) => {\n if (typeof format !== \"string\") return;\n // What the final (or the logo composite before it) reads for this format.\n const composite = byId(idOf(images[i]));\n const reader = composite?.tags?.role === LOGO_COMPOSITE_ROLE ? composite : undefined;\n const source = reader ? reader.inputs?.image : images[i];\n const fit = typeof source === \"string\" ? safeFitNode(format, source, placements) : null;\n const from = next.findIndex((n) => n.id === idOf(source));\n if (!fit || from < 0 || byId(fit.id)) return;\n const fitRef = `$ref:${fit.id}.image`;\n next = next.map((n) => {\n if (reader && n.id === reader.id) return { ...n, inputs: { ...n.inputs, image: fitRef } };\n const read = n.inputs?.images;\n if (!reader && n.id === \"final\" && n.type === \"collect\" && Array.isArray(read))\n return { ...n, inputs: { ...n.inputs, images: read.map((r, j) => (j === i ? fitRef : r)) } };\n return n;\n });\n next.splice(from + 1, 0, fit as unknown as Node);\n });\n if (next.length === nodes.length) return { canvas: holder, upgraded: false };\n return { canvas: { ...holder, nodes: next }, upgraded: true };\n}\n\n/** The takes-and-re-lays graph (v1): up to three takes, a judge, re-lays and centred crops. */\nfunction v1Graph(nodes: Node[]): OldGraph | null {\n const takes = nodes.filter(\n (n) => n.type === \"image_generate\" && (n.tags?.role === STATIC_CANDIDATE_ROLE || TAKE_ID.test(n.id)),\n );\n const first = takes[0];\n if (!first) return null;\n const relays = nodes.filter(\n (n) => n.type === \"image_generate\" && (n.tags?.role === STATIC_RELAY_ROLE || RELAY_ID.test(n.id)),\n );\n const pick = nodes.find((n) => n.type === \"image_select\" && n.id === \"pick\");\n const fits = nodes.filter((n) => n.type === \"imagemagick\" && FIT_ID.test(n.id));\n const final = nodes.find((n) => n.type === \"collect\" && n.id === \"final\");\n return {\n template: first,\n takes: Math.min(3, takes.length),\n removed: [...takes, ...relays, ...(pick ? [pick] : []), ...fits, ...(final ? [final] : [])],\n ...(typeof pick?.params?.model === \"string\" ? { judgeModel: pick.params.model } : {}),\n sentence: OLD_RUN_SENTENCE,\n };\n}\n\n/**\n * A one-picture graph planned with a master shape that no longer exists (`band_master`), or\n * carrying its extended-size nodes, or not yet on the `plate` shape when that is the `target`:\n * the whole render part is rebuilt on the target shape, keeping the variants' model, params,\n * pictures and count, the judge, the ad set's placements, its lead and platforms and a\n * composited logo. A plate graph is never rebuilt back, and no graph is moved onto one unless that is the `target` asked for.\n */\nfunction retiredShapeGraph(nodes: Node[], target: MasterShape | undefined): OldGraph | null {\n const prefilter = nodes.find((n) => n.tags?.role === VARIANT_PREFILTER_ROLE);\n const shape = prefilter?.params?.master_shape;\n const plate = isPlateCanvas({ nodes });\n const retired =\n (typeof shape === \"string\" && !(MASTER_SHAPES as readonly string[]).includes(shape)) ||\n nodes.some((n) => n.tags?.role !== undefined && EXTENDED_ROLES.includes(n.tags.role)) ||\n (target === \"plate\" && !plate);\n return retired ? renderGraph({ nodes }) : null;\n}\n\n/**\n * The render part of a one-picture graph, to rebuild on another plan (`rebuildRenderPart`):\n * null for a graph with no prefilter (hand-built, v1, native).\n */\nexport function renderGraph(input: { nodes?: unknown }): OldGraph | null {\n const nodes = (Array.isArray(input.nodes) ? input.nodes : []) as Node[];\n const prefilter = nodes.find((n) => n.tags?.role === VARIANT_PREFILTER_ROLE);\n if (!prefilter) return null;\n const calls = nodes.filter((n) => n.type === \"image_generate\" && n.tags?.role === STATIC_VARIANT_CALL_ROLE);\n const template = calls[0] ?? nodes.find((n) => n.type === \"image_generate\" && n.tags?.role === STATIC_VARIANTS_ROLE);\n if (!template) return null;\n const pick = nodes.find((n) => n.tags?.role === STATIC_PICK_ROLE && n.type === \"image_select\");\n const placements = prefilter?.params?.placements;\n const platforms = prefilter?.params?.platforms;\n const lead = prefilter?.params?.lead;\n const composite = compositeOf(nodes.find((n) => n.tags?.role === LOGO_COMPOSITE_ROLE));\n return {\n template,\n takes: Math.min(3, Math.max(1, calls.length)),\n removed: nodes.filter(\n (n) => (n.tags?.role && RENDER_ROLES.has(n.tags.role)) || (n.id === \"final\" && n.type === \"collect\"),\n ),\n ...(typeof pick?.params?.model === \"string\"\n ? { judgeModel: pick.params.model }\n : typeof prefilter.params?.judge_model === \"string\"\n ? { judgeModel: prefilter.params.judge_model }\n : {}),\n ...(Array.isArray(placements) && placements.every((p) => typeof p === \"string\") ? { placements } : {}),\n ...(typeof lead === \"string\" ? { lead } : {}),\n ...(Array.isArray(platforms) && platforms.every((p) => typeof p === \"string\") ? { platforms } : {}),\n ...(composite ? { compositeLogo: composite } : {}),\n sentence: SIZES_SENTENCE,\n };\n}\n\n/**\n * The logo a graph's composite places, its files and shape: a `static_logo`'s, or the one file an\n * older composite pasted (`inputs.logo`), planned as a wordmark until the next run measures it.\n */\nfunction compositeOf(node: Node | undefined): CompositeLogo | undefined {\n const files = node?.inputs?.logos ?? (node?.inputs?.logo === undefined ? undefined : [node.inputs.logo]);\n if (!Array.isArray(files) || files.length === 0 || !files.every((f) => typeof f === \"string\")) return undefined;\n const aspect = node?.params?.aspect;\n return { files: files as string[], aspect: typeof aspect === \"number\" && aspect > 0 ? aspect : 3 };\n}\n\n/** The format the band master's extended picture was delivered as: the one the final read from the paste-back. */\nfunction extendedFormat(nodes: Node[], formats: readonly string[]): string | undefined {\n const pasteback = nodes.find((n) => n.tags?.role === \"static_pasteback\")?.id;\n const images = nodes.find((n) => n.type === \"collect\" && n.id === \"final\")?.inputs?.images;\n const at = Array.isArray(images) && pasteback ? images.indexOf(`$ref:${pasteback}.image`) : -1;\n return at >= 0 ? formats[at] : undefined;\n}\n\n/** The logo file among the references the model draws from, so each re-laid-out size is handed it too. */\nfunction logoOf(nodes: Node[], reference: string[]): { logoRef?: string } {\n const logo = nodes.find((n) => n.type === \"ingest\" && n.tags?.role === BRAND_LOGO_ROLE);\n const ref = logo ? reference.find((r) => r.startsWith(`$ref:${logo.id}.`)) : undefined;\n return ref ? { logoRef: ref } : {};\n}\n\nfunction upgradedDescription(text: string, old: OldGraph, plan: ReturnType<typeof planStaticFormats>): string {\n const now =\n old.sentence === SIZES_SENTENCE\n ? describeSizes(plan)\n : old.takes > 1\n ? `${[\"\", \"One\", \"Two\", \"Three\"][old.takes]} variants of the finished ad are rendered and a judge keeps one. ${describeSizes(plan)}`\n : `One finished ad is rendered (no judge). ${describeSizes(plan)}`;\n return old.sentence.test(text) ? text.replace(old.sentence, now) : `${text} ${now}`.trim();\n}\n","import { AD_PLACEMENTS, AD_PLATFORMS } from \"@baker/canvas-contract\";\nimport { parseDocument, Scalar, visit } from \"yaml\";\nimport { AWARENESS_VALUES, type ViewerProfile } from \"../../viewer-profile.ts\";\nimport { languageTag } from \"../../language.ts\";\n\n// The scaffold's `creatives` collection (src/collections/creatives.ts) accepts exactly these;\n// `creative-definition.parity.test.ts` fails when the two lists drift. An unknown platform or\n// format degrades to the default rather than emitting a definition the collection would reject.\nexport const PLATFORM_VALUES = [\"meta\", \"google\", \"linkedin\", \"tiktok\", \"youtube\", \"x\", \"other\"] as const;\nexport const FORMAT_VALUES = [\"1:1\", \"4:5\", \"9:16\", \"16:9\", \"1.91:1\", \"2:3\"] as const;\n/** Where the ad runs (`platforms`), in the placement catalog's names: what its sizes are planned from. */\nexport const PLATFORMS_VALUES = AD_PLATFORMS;\nexport const CREATIVE_KIND_VALUES = [\"static\", \"video\"] as const;\nexport const CREATIVE_STATUS_VALUES = [\"draft\", \"rendered\", \"published\", \"archived\"] as const;\nexport const SOURCE_KIND_VALUES = [\"image\", \"video\"] as const;\nexport const EVIDENCE_VALUES = [\"observed\", \"interpreted\", \"hypothesized\", \"generated\"] as const;\n\n/** Frontmatter + body for a creative's `_definition.md`, mirroring the scaffold `creatives` collection schema. */\nexport type CreativeSourceKind = (typeof SOURCE_KIND_VALUES)[number];\n\nexport type CreativeDefinitionInput = {\n title: string;\n kind: (typeof CREATIVE_KIND_VALUES)[number];\n /** The collection's single coarse platform (`definitionPlatformOf`); omitted when nothing says where it runs. */\n platform?: string;\n /** Where it runs, in the catalog's names, main first (`PLATFORMS_VALUES`). */\n platforms?: string[];\n formats: string[];\n status?: (typeof CREATIVE_STATUS_VALUES)[number];\n sourceReferenceUrl?: string;\n sourceAdvertiser?: string;\n /** The library ad it adapted (`baker winning-ads` ids): what `baker_uses` in reference search counts. */\n sourceAdId?: string;\n sourcePlatform?: string;\n sourceAdvertiserId?: string;\n sourceKind?: CreativeSourceKind;\n /** Repo-relative path to the committed source asset (e.g. \"references/original.jpg\"). */\n sourcePath?: string;\n /** The Meta ad set the ad is made for (`baker ads meta adsets`). */\n targetAdSet?: string;\n /** Who that ad set reaches (`baker ads meta adsets --audience`), or the viewer read from the Knowledge. */\n viewer?: ViewerProfile;\n description?: string;\n};\n\n/** Title-case a slug: \"factorial-hr-4x5\" -> \"Factorial Hr 4x5\". Falls back to the slug when empty. */\nexport function titleFromSlug(slug: string): string {\n const title = slug\n .split(\"-\")\n .filter(Boolean)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \");\n return title || slug;\n}\n\n/** A platform flag as a collection-valid value, or undefined: nothing is made up (it was \"meta\"). */\nexport function resolvePlatform(platform: string | undefined): string | undefined {\n const value = platform?.trim();\n return value && (PLATFORM_VALUES as readonly string[]).includes(value) ? value : undefined;\n}\n\n/**\n * Where a video's definition says it runs: `--platforms` (catalog names; a placement id as its\n * platform, an unknown name dropped), else the retired `--platform`, else nothing. Video sizes\n * do not follow from it yet; the definition records it.\n */\nexport function definitionPlatformsOf(\n platformsFlag: string | undefined,\n legacyPlatform: string | undefined,\n): { platforms?: string[]; platform?: string } {\n const names = (platformsFlag ?? \"\")\n .split(\",\")\n .map((n) => n.trim().toLowerCase())\n .map((n) => AD_PLACEMENTS.find((p) => p.id === n)?.platform ?? n)\n .filter((n): n is (typeof AD_PLATFORMS)[number] => (AD_PLATFORMS as readonly string[]).includes(n));\n const platforms = [...new Set(names)];\n const first = platforms[0];\n if (first) return { platforms, platform: definitionPlatformOf(first) };\n const platform = resolvePlatform(legacyPlatform);\n return platform ? { platform } : {};\n}\n\n/**\n * A catalog platform (or placement id) as the definition's coarser `platform`: Google's\n * campaign types are `google`, a platform the collection has no name for is `other`.\n */\nexport function definitionPlatformOf(name: string): (typeof PLATFORM_VALUES)[number] {\n const platform = AD_PLACEMENTS.find((p) => p.id === name)?.platform ?? name;\n if (platform.startsWith(\"google_\")) return \"google\";\n return PLATFORM_VALUES.find((p) => p === platform) ?? \"other\";\n}\n\n/** A single-format array from the resolved aspect ratio (default [\"4:5\"] when unknown). */\nexport function resolveFormats(aspect: string | undefined): string[] {\n const value = aspect?.trim();\n return value && (FORMAT_VALUES as readonly string[]).includes(value) ? [value] : [\"4:5\"];\n}\n\n/** A deduped list of collection-valid formats (default [\"4:5\"] when none are recognized). */\nexport function resolveFormatList(formats: readonly string[]): string[] {\n const valid = [...new Set(formats.map((f) => f.trim()))].filter((f) =>\n (FORMAT_VALUES as readonly string[]).includes(f),\n );\n return valid.length > 0 ? valid : [\"4:5\"];\n}\n\n/** Best-effort human summary from an image_describe blueprint's ad_intent (for the definition body). */\nexport function describeBlueprintIntent(blueprint: unknown): string | undefined {\n const intent = (blueprint as { ad_intent?: unknown } | null)?.ad_intent;\n if (typeof intent === \"string\" && intent.trim()) return intent.trim();\n if (intent && typeof intent === \"object\") {\n const summary = (intent as { summary?: unknown }).summary ?? (intent as { feeling?: unknown }).feeling;\n if (typeof summary === \"string\" && summary.trim()) return summary.trim();\n }\n return undefined;\n}\n\n// Double-quoted YAML scalar via JSON.stringify — valid YAML that survives colons, quotes, and unicode.\nfunction yamlScalar(value: string): string {\n return JSON.stringify(value);\n}\n\n/** Render `_definition.md` (YAML frontmatter + body) for a creative. */\nexport function buildCreativeDefinition(input: CreativeDefinitionInput): string {\n const lines = [\"---\", `title: ${yamlScalar(input.title)}`, `kind: ${input.kind}`];\n if (input.platform) lines.push(`platform: ${input.platform}`);\n if (input.platforms && input.platforms.length > 0) lines.push(`platforms: [${input.platforms.join(\", \")}]`);\n lines.push(`formats: [${input.formats.map(yamlScalar).join(\", \")}]`);\n lines.push(`status: ${input.status ?? \"draft\"}`);\n if (input.sourceReferenceUrl) lines.push(`sourceReferenceUrl: ${yamlScalar(input.sourceReferenceUrl)}`);\n if (input.sourceAdvertiser) lines.push(`sourceAdvertiser: ${yamlScalar(input.sourceAdvertiser)}`);\n if (input.sourceAdvertiserId) lines.push(`sourceAdvertiserId: ${yamlScalar(input.sourceAdvertiserId)}`);\n if (input.sourceAdId) lines.push(`sourceAdId: ${yamlScalar(input.sourceAdId)}`);\n if (input.sourcePlatform) lines.push(`sourcePlatform: ${input.sourcePlatform}`);\n if (input.sourceKind) lines.push(`sourceKind: ${input.sourceKind}`);\n if (input.sourcePath) lines.push(`sourcePath: ${yamlScalar(input.sourcePath)}`);\n if (input.targetAdSet) lines.push(`targetAdSet: ${yamlScalar(input.targetAdSet)}`);\n // A JSON object is a YAML flow mapping: one line, and every string in it quoted.\n if (input.viewer) lines.push(`viewer: ${JSON.stringify(input.viewer)}`);\n lines.push(\"---\", \"\");\n const where = input.platforms?.[0] ?? input.platform;\n lines.push(input.description?.trim() || `${input.title} — canvas-built ${input.kind} ad${where ? ` for ${where}` : \"\"}.`);\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n\n/** The library ids a `_definition.md` names, as `DefinitionSourceFields`. */\nexport type DefinitionSourceFields = {\n sourceAdId?: string;\n sourcePlatform?: string;\n sourceAdvertiserId?: string;\n};\n\nconst SOURCE_FIELD_KEYS = [\"sourceAdId\", \"sourcePlatform\", \"sourceAdvertiserId\"] as const;\n\n/**\n * Read the library ids back out of a `_definition.md`, so a sync after the agent edited the\n * file still carries them. Tolerant: no frontmatter, a mid-edit parse error, or a non-string\n * value yields nothing for that field rather than a failed sync.\n */\nexport function parseDefinitionSourceFields(raw: string): DefinitionSourceFields {\n const match = raw.match(/^---\\r?\\n([\\s\\S]*?\\r?\\n)?---/);\n if (!match) return {};\n const doc = parseDocument(match[1] ?? \"\");\n if (doc.errors.length > 0) return {};\n const fields: DefinitionSourceFields = {};\n for (const key of SOURCE_FIELD_KEYS) {\n const value = doc.get(key);\n if (typeof value === \"string\" && value.trim()) fields[key] = value.trim();\n }\n return fields;\n}\n\n/** Why the creative exists, as a `_definition.md` states it (its `idea` sent as `ideaSlug`). */\nexport type DefinitionStrategyFields = {\n ideaSlug?: string;\n message?: string;\n evidence?: (typeof EVIDENCE_VALUES)[number];\n angle?: string;\n persona?: string;\n awareness?: (typeof AWARENESS_VALUES)[number];\n hypothesis?: string;\n /** The lead ad of the series this creative is one of (`series`): its picture is the lead's with other words. */\n seriesLead?: string;\n /** The language its words are in (`language`), as a canonical BCP-47 tag (`es-MX`): a translation's. */\n language?: string;\n};\n\nfunction oneOf<T extends string>(values: readonly T[], value: string | undefined): T | undefined {\n return values.find((allowed) => allowed === value);\n}\n\n/**\n * Read the creative's strategy back out of a `_definition.md`, so the dashboard holds it from the\n * first sync rather than from Publish. Tolerant like `parseDefinitionSourceFields`; an `evidence`\n * or `awareness` the collection would reject is dropped rather than sent.\n */\nexport function parseDefinitionStrategyFields(raw: string): DefinitionStrategyFields {\n const match = raw.match(/^---\\r?\\n([\\s\\S]*?\\r?\\n)?---/);\n if (!match) return {};\n const doc = parseDocument(match[1] ?? \"\");\n if (doc.errors.length > 0) return {};\n const text = (key: string): string | undefined => {\n const value = doc.get(key);\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n };\n const ideaSlug = text(\"idea\");\n const message = text(\"message\");\n const evidence = oneOf(EVIDENCE_VALUES, text(\"evidence\"));\n const angle = text(\"angle\");\n const persona = text(\"persona\");\n const awareness = oneOf(AWARENESS_VALUES, text(\"awareness\"));\n const hypothesis = text(\"hypothesis\");\n const seriesLead = text(\"series\");\n const language = languageTag(text(\"language\") ?? \"\");\n return {\n ...(seriesLead ? { seriesLead } : {}),\n ...(language ? { language } : {}),\n ...(ideaSlug ? { ideaSlug } : {}),\n ...(message ? { message } : {}),\n ...(evidence ? { evidence } : {}),\n ...(angle ? { angle } : {}),\n ...(persona ? { persona } : {}),\n ...(awareness ? { awareness } : {}),\n ...(hypothesis ? { hypothesis } : {}),\n };\n}\n\n/** Where a definition places its creative in a series: null for a field it does not name. */\nexport type DefinitionSeriesPlace = { seriesLead: string | null; language: string | null };\n\n/**\n * The series lead and language a `_definition.md` names, each null when it names none, so a\n * sync can tell the backend the creative left its series. Null when the front matter cannot be\n * read (none, or mid-edit invalid YAML): the sync then says nothing and the backend keeps what it has.\n */\nexport function parseDefinitionSeriesPlace(raw: string): DefinitionSeriesPlace | null {\n const match = raw.match(/^---\\r?\\n([\\s\\S]*?\\r?\\n)?---/);\n if (!match || parseDocument(match[1] ?? \"\").errors.length > 0) return null;\n const { seriesLead, language } = parseDefinitionStrategyFields(raw);\n return { seriesLead: seriesLead ?? null, language: language ?? null };\n}\n\n/** Who a `_definition.md` says the ad is for: its `targetAdSet` and its recorded `viewer`, unchecked. */\nexport type DefinitionViewerFields = { targetAdSet?: string; viewer?: unknown };\n\n/** Read `targetAdSet` and `viewer` back out of a `_definition.md`; tolerant like `parseDefinitionSourceFields`. */\nexport function parseDefinitionViewerFields(raw: string): DefinitionViewerFields {\n const match = raw.match(/^---\\r?\\n([\\s\\S]*?\\r?\\n)?---/);\n if (!match) return {};\n const doc = parseDocument(match[1] ?? \"\");\n if (doc.errors.length > 0) return {};\n const data = doc.toJS() as { targetAdSet?: unknown; viewer?: unknown } | null;\n const adSet = data?.targetAdSet;\n const targetAdSet = typeof adSet === \"string\" || typeof adSet === \"number\" ? String(adSet).trim() : \"\";\n return {\n ...(targetAdSet ? { targetAdSet } : {}),\n ...(data?.viewer !== undefined ? { viewer: data.viewer } : {}),\n };\n}\n\n/**\n * Record the ad set an ad is for and the viewer it reaches in an existing `_definition.md`,\n * keeping every other field and the body. A file without frontmatter, or one mid-edit, is\n * returned as it is: the viewer is then read again from the ad set on the next run.\n */\nexport function setDefinitionViewer(raw: string, fields: { targetAdSet?: string; viewer?: ViewerProfile }): string {\n const match = raw.match(/^---\\r?\\n([\\s\\S]*?\\r?\\n)?---/);\n if (!match) return raw;\n const doc = parseDocument(match[1] ?? \"\");\n if (doc.errors.length > 0) return raw;\n if (fields.targetAdSet) doc.set(\"targetAdSet\", fields.targetAdSet);\n if (fields.viewer) doc.set(\"viewer\", doc.createNode(fields.viewer, { flow: true }));\n return `---\\n${doc.toString()}---${raw.slice(match[0].length)}`;\n}\n\n/** The proven ad a creative is built on, as its `_definition.md` records it. */\ntype DefinitionSource = {\n sourceAdId: string;\n sourcePlatform: string;\n sourceAdvertiserId?: string;\n sourceAdvertiser?: string;\n sourceReferenceUrl?: string;\n};\n\nconst SOURCE_KEYS = [\"sourceAdId\", \"sourcePlatform\", \"sourceAdvertiserId\", \"sourceAdvertiser\", \"sourceReferenceUrl\"] as const;\n\n/**\n * An existing `_definition.md` for a creative rebuilt on `source`. Rebuilt on the proven ad it\n * already names (a re-cast), it is kept as it is, thinking included. Rebuilt on another, it names\n * the new one and loses its Thinking, which reasoned about the old ad: make writes it again for\n * this one (dev, Oct 2026: `make --reference` over a creative built on Ayrshare left the thinking\n * on Ayrshare's card under a canvas built on Platzi's meme). Unreadable front matter is kept as it is.\n */\nexport function rebasedDefinition(raw: string, source: DefinitionSource): string {\n const match = raw.match(/^---\\r?\\n([\\s\\S]*?\\r?\\n)?---/);\n if (!match) return raw;\n const doc = parseDocument(match[1] ?? \"\");\n if (doc.errors.length > 0 || parseDefinitionSourceFields(raw).sourceAdId === source.sourceAdId) return raw;\n for (const key of SOURCE_KEYS) {\n const value = source[key];\n if (value) doc.set(key, value);\n else doc.delete(key);\n }\n const body = raw.slice(match[0].length);\n const thinking = body.search(/^## Thinking\\s*$/m);\n return `---\\n${doc.toString()}---${thinking < 0 ? body : `${body.slice(0, thinking).trimEnd()}\\n`}`;\n}\n\n/**\n * Record where the ad runs and the sizes it is made in, in an existing `_definition.md`, keeping\n * every other field and the body. A file without frontmatter, or one mid-edit, is returned as it is.\n */\nexport function setDefinitionDelivery(\n raw: string,\n fields: { platforms: readonly string[]; platform: string; formats: readonly string[] },\n): string {\n const match = raw.match(/^---\\r?\\n([\\s\\S]*?\\r?\\n)?---/);\n if (!match) return raw;\n const doc = parseDocument(match[1] ?? \"\");\n if (doc.errors.length > 0) return raw;\n doc.set(\"platform\", fields.platform);\n doc.set(\"platforms\", doc.createNode([...fields.platforms], { flow: true }));\n // Quoted: the site reads front matter as YAML 1.1, where a bare 4:5 is the number 245.\n const formats = doc.createNode([...fields.formats], { flow: true });\n visit(formats, {\n Scalar(_, scalar) {\n scalar.type = Scalar.QUOTE_DOUBLE;\n },\n });\n doc.set(\"formats\", formats);\n return `---\\n${doc.toString()}---${raw.slice(match[0].length)}`;\n}\n","/**\n * The face a static ad's copy is set in, when the brand has no font FILE.\n *\n * A brand usually NAMES its typeface even without the file: in tokens.json, or in\n * BRAND.md, read in any language by the brand reader (a face it bans is never used). A named family is fetched as a web font file the render\n * stages like any other font. A brand that names nothing gets no face from here.\n */\n\nimport { brandTokensSchema } from \"@baker/api\";\nimport type { BrandDocReading } from \"../brand/brand-doc.ts\";\nimport { type BrandFontFace, GENERIC_FAMILIES, type ProviderDeps, resolveBrandFaces } from \"../brand/fonts.ts\";\n\nexport type FontOrigin = \"brand_file\" | \"tokens\" | \"brand_md\";\ntype Named = { family: string; origin: Extract<FontOrigin, \"tokens\" | \"brand_md\"> };\ntype NamedTypefaces = { headline?: Named; body?: Named };\n\n/** Where a face comes from: a file in the workspace, or a web font file by URL. */\nexport type FontSlot = { path: string } | { url: string };\n\n/** One role's face, and what the report says about it. */\nexport type ResolvedFont = { slot: FontSlot; family: string | null; origin: FontOrigin };\n\n/** The weight a headline face is fetched at. */\nconst HEADLINE_WEIGHT = 800;\n\n/** The faces the brand's documents name and use, by role; a banned face is never one. Pure. */\nfunction fromReading(reading: BrandDocReading): NamedTypefaces {\n const used = reading.fonts.filter((f) => f.use && !GENERIC_FAMILIES.has(f.family.toLowerCase()));\n const named = (family: string | undefined): Named | undefined =>\n family ? { family, origin: \"brand_md\" } : undefined;\n const loose = used.filter((f) => f.role === \"any\").map((f) => f.family);\n const headline = named(used.find((f) => f.role === \"heading\")?.family ?? loose[0]);\n const body = named(used.find((f) => f.role === \"body\")?.family ?? loose[1] ?? loose[0]);\n return { ...(headline ? { headline } : {}), ...(body ? { body } : {}) };\n}\n\nfunction fromTokens(tokensJson: string): NamedTypefaces {\n let json: unknown;\n try {\n json = JSON.parse(tokensJson);\n } catch {\n return {};\n }\n const parsed = brandTokensSchema.safeParse(json);\n if (!parsed.success) return {};\n const heading = parsed.data.fonts.find((f) => f.role === \"heading\")?.family;\n const body = parsed.data.fonts.find((f) => f.role === \"body\")?.family;\n return {\n ...(heading ? { headline: { family: heading, origin: \"tokens\" as const } } : {}),\n ...(body ? { body: { family: body, origin: \"tokens\" as const } } : {}),\n };\n}\n\n/**\n * The heading and body families the brand names: tokens.json first (the canonical\n * machine source), then what BRAND.md states, as the brand reader read it in\n * whatever language it is written (`brand-doc.ts`). Pure.\n */\nexport function namedTypefaces(sources: {\n tokensJson?: string | null;\n brandDoc?: BrandDocReading | null;\n}): NamedTypefaces {\n const tokens = sources.tokensJson ? fromTokens(sources.tokensJson) : {};\n const doc = sources.brandDoc ? fromReading(sources.brandDoc) : {};\n const headline = tokens.headline ?? doc.headline;\n const body = tokens.body ?? doc.body;\n return { ...(headline ? { headline } : {}), ...(body ? { body } : {}) };\n}\n\n/** The upright latin face nearest `weight` that a catalogue serves. */\nfunction nearest(faces: BrandFontFace[], weight: number): BrandFontFace | undefined {\n return [...faces]\n .filter((f) => f.style === \"normal\")\n .sort((a, b) => Math.abs(a.weight - weight) - Math.abs(b.weight - weight))[0];\n}\n\n/**\n * A web font FILE for a family at a weight, from Google Fonts or Fontsource, or null when\n * neither serves it (or neither answered). A weight the family lacks takes its nearest.\n */\nexport async function webFontUrl(family: string, weight: number, deps: ProviderDeps): Promise<string | null> {\n const first = await resolveBrandFaces(family, [weight], [\"latin\"], deps);\n if (first.ok) return nearest(first.faces, weight)?.url ?? null;\n if (first.reason !== \"weight\" || first.available.length === 0) return null;\n const closest = [...first.available].sort((a, b) => Math.abs(a - weight) - Math.abs(b - weight))[0];\n if (closest === undefined) return null;\n const retry = await resolveBrandFaces(family, [closest], [\"latin\"], deps);\n return retry.ok ? (nearest(retry.faces, closest)?.url ?? null) : null;\n}\n\ntype ResolveUrl = (family: string, weight: number) => Promise<string | null>;\n\nconst fileFace = (p: string): ResolvedFont => ({ slot: { path: p }, family: null, origin: \"brand_file\" });\n\n/**\n * The brand's OWN headline face: its font file, else the family it names (fetched as a web\n * font). Null when it has neither: a surface with a look of its own keeps it rather than\n * trading it for a face the brand never chose.\n */\nexport async function brandHeadlineFont(args: {\n file?: string;\n named: NamedTypefaces;\n resolveUrl: ResolveUrl;\n}): Promise<ResolvedFont | null> {\n if (args.file) return fileFace(args.file);\n const named = args.named.headline ?? args.named.body;\n if (!named) return null;\n const url = await args.resolveUrl(named.family, HEADLINE_WEIGHT);\n return url ? { slot: { url }, family: named.family, origin: named.origin } : null;\n}\n","import { readdir, readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { brandTokensSchema } from \"@baker/api\";\nimport { type BrandDocReading, LOGO_FILE, type ReadBrandDocs, readWorkspaceBrandDoc } from \"../brand/brand-doc.ts\";\nimport { BRAND_DIR, markIsReal, paletteFromBrandDoc, pickBrandMark } from \"./ad-brand-source.ts\";\nimport { namedTypefaces } from \"./static-fonts.ts\";\n\n/**\n * What a static ad draws with, read from the workspace's own brand folder.\n *\n * The render browser has no brand font unless it is handed one, and the brand's fonts\n * and logo already sit in `src/brand/`. `tokens.json` is the canonical source (it names\n * which face is the heading and which the body, and which colour is the CTA); a workspace\n * that predates it falls back to the fonts folder, BRAND.md's hexes, and the logos folder.\n * What only prose states (the brand's name, the words its logo prints, a colour it bans) is\n * read from BRAND.md and COMPANY.md by the brand reader, in any language (`brand-doc.ts`).\n * Paths come back absolute. Never throws: a workspace with no brand yet is ordinary.\n */\ntype StaticBrandKit = {\n /** The brand's name, as BRAND.md or COMPANY.md states it: every check that reads an ad needs it. */\n name?: string;\n /** The words the brand's logo prints: BRAND.md's wordmark, and a product a logo file is named after. */\n lockup?: string[];\n logo?: string;\n headlineFont?: string;\n bodyFont?: string;\n palette: string[];\n ctaColor?: string;\n /** The colours tokens.json gives a role: the page ground, the ink on it, the accent. */\n colors?: { background?: string; foreground?: string; accent?: string };\n};\n\n/**\n * The brand's colours as the render prompt binds them: the page ground, the ink, the\n * accent and the call to action. Written into prompt.json as `brand`, so the image model\n * reads the brand as a fact of the blueprint and never as a colour it may borrow from the\n * reference ad. Null when the workspace names no colour at all. Pure.\n */\nexport function brandBlock(kit: Pick<StaticBrandKit, \"palette\" | \"ctaColor\" | \"colors\" | \"name\" | \"lockup\">): {\n name?: string;\n lockup?: string[];\n ground?: string;\n ink?: string;\n accent?: string;\n cta?: string;\n palette: string[];\n} | null {\n const palette = [...new Set([...(kit.palette ?? []), ...(kit.ctaColor ? [kit.ctaColor] : [])])];\n const block = {\n ...(kit.name ? { name: kit.name } : {}),\n ...(kit.lockup && kit.lockup.length > 0 ? { lockup: kit.lockup } : {}),\n ...(kit.colors?.background ? { ground: kit.colors.background } : {}),\n ...(kit.colors?.foreground ? { ink: kit.colors.foreground } : {}),\n ...(kit.colors?.accent ? { accent: kit.colors.accent } : {}),\n ...(kit.ctaColor ? { cta: kit.ctaColor } : {}),\n palette,\n };\n return palette.length === 0 && Object.keys(block).length === 1 ? null : block;\n}\n\nconst FONT_FILE = /\\.(woff2|woff|ttf|otf)$/i;\nconst HEAVY = /(black|heavy|extra-?bold|bold|semi-?bold|[6-9]00)/i;\nconst REGULAR = /(regular|book|normal|roman|[^0-9]400)/i;\n\n/** The face for a role: the boldest of its files for headlines, the regular one for body. */\nfunction pickFace(files: string[], want: \"heavy\" | \"regular\"): string | undefined {\n if (files.length === 0) return undefined;\n const pattern = want === \"heavy\" ? HEAVY : REGULAR;\n return files.find((f) => pattern.test(path.basename(f))) ?? files[0];\n}\n\nfunction exists(file: string): Promise<boolean> {\n return readFile(file).then(\n () => true,\n () => false,\n );\n}\n\nasync function fromTokens(root: string): Promise<Partial<StaticBrandKit>> {\n const raw = await readFile(path.join(root, BRAND_DIR, \"tokens.json\"), \"utf8\").catch(() => null);\n if (!raw) return {};\n let json: unknown;\n try {\n json = JSON.parse(raw);\n } catch {\n return {};\n }\n const parsed = brandTokensSchema.safeParse(json);\n if (!parsed.success) return {};\n const tokens = parsed.data;\n const filesFor = async (role: \"heading\" | \"body\"): Promise<string[]> => {\n const out: string[] = [];\n for (const font of tokens.fonts.filter((f) => f.role === role)) {\n for (const file of font.files ?? []) {\n const abs = path.join(root, file);\n if (FONT_FILE.test(file) && (await exists(abs))) out.push(abs);\n }\n }\n return out;\n };\n const heading = await filesFor(\"heading\");\n const body = await filesFor(\"body\");\n const logos: string[] = [];\n for (const logo of tokens.logos) {\n if (await exists(path.join(root, logo.path))) logos.push(logo.path);\n }\n const mark = pickBrandMark(logos.map((l) => path.basename(l)));\n const markPath = mark ? logos.find((l) => path.basename(l) === mark) : undefined;\n return {\n headlineFont: pickFace(heading, \"heavy\") ?? pickFace(body, \"heavy\"),\n bodyFont: pickFace(body, \"regular\") ?? pickFace(heading, \"regular\"),\n palette: tokens.colors\n .filter((c) => c.role === \"cta\" || c.role === \"accent\" || c.role === \"other\")\n .map((c) => c.value.slice(0, 7).toLowerCase()),\n ctaColor: tokens.colors\n .find((c) => c.role === \"cta\")\n ?.value.slice(0, 7)\n .toLowerCase(),\n colors: Object.fromEntries(\n ([\"background\", \"foreground\", \"accent\"] as const).flatMap((role) => {\n const hex = tokens.colors\n .find((c) => c.role === role)\n ?.value.slice(0, 7)\n .toLowerCase();\n return hex ? [[role, hex]] : [];\n }),\n ),\n ...(markPath ? { logo: path.join(root, markPath) } : {}),\n };\n}\n\n/** The brand's mark: the one tokens.json names, else the best file in the logos folder; never a typed stand-in. */\nasync function realLogo(root: string, named: string | undefined): Promise<string | undefined> {\n let logo = named;\n if (!logo) {\n const logosDir = path.join(root, BRAND_DIR, \"logos\");\n const mark = pickBrandMark(\n ((await readdir(logosDir).catch(() => [])) as string[]).filter((f) => !f.startsWith(\".\")),\n );\n if (mark) logo = path.join(logosDir, mark);\n }\n // A typed SVG stand-in (a wordmark set in <text>) is not the company's logo: leave the slot open.\n return logo && (await markIsReal(logo, root)) ? logo : undefined;\n}\n\n/** The palette a brand document gives, without any colour it bans. Pure. */\nfunction documentPalette(doc: string | null, reading: BrandDocReading | null): string[] {\n const banned = new Set((reading?.colors ?? []).filter((c) => !c.use).map((c) => c.hex));\n return doc ? paletteFromBrandDoc(doc).filter((hex) => !banned.has(hex)) : [];\n}\n\nexport async function readStaticBrandKit(\n root = \".\",\n opts: { readBrandDoc?: ReadBrandDocs } = {},\n): Promise<StaticBrandKit> {\n const tokens = await fromTokens(root);\n const fontsDir = path.join(root, BRAND_DIR, \"fonts\");\n const fontFiles = ((await readdir(fontsDir).catch(() => [])) as string[])\n .filter((f) => FONT_FILE.test(f))\n .sort()\n .map((f) => path.join(fontsDir, f));\n const headlineFont = tokens.headlineFont ?? pickFace(fontFiles, \"heavy\");\n const bodyFont = tokens.bodyFont ?? pickFace(fontFiles, \"regular\") ?? headlineFont;\n\n const doc = await readFile(path.join(root, BRAND_DIR, \"BRAND.md\"), \"utf8\").catch(() => null);\n const reading = await readWorkspaceBrandDoc(root, opts.readBrandDoc ? { read: opts.readBrandDoc } : {});\n let palette = tokens.palette ?? [];\n if (palette.length === 0) palette = documentPalette(doc, reading);\n const name = reading?.name;\n const lockup = reading?.wordmark ?? [];\n\n const logo = await realLogo(root, tokens.logo);\n\n return {\n ...(name ? { name } : {}),\n ...(lockup.length > 0 ? { lockup } : {}),\n ...(logo ? { logo } : {}),\n ...(headlineFont ? { headlineFont } : {}),\n ...(bodyFont ? { bodyFont } : {}),\n palette,\n ...(tokens.ctaColor ? { ctaColor: tokens.ctaColor } : {}),\n ...(tokens.colors && Object.keys(tokens.colors).length > 0 ? { colors: tokens.colors } : {}),\n };\n}\n\n/** The typefaces the workspace's brand names, in tokens.json or BRAND.md. Never throws. */\nexport async function readNamedTypefaces(\n root = \".\",\n opts: { readBrandDoc?: ReadBrandDocs } = {},\n): Promise<ReturnType<typeof namedTypefaces>> {\n const tokensJson = await readFile(path.join(root, BRAND_DIR, \"tokens.json\"), \"utf8\").catch(() => null);\n const tokens = namedTypefaces({ tokensJson });\n // tokens.json naming both roles is the whole answer: the documents are not read.\n if (tokens.headline && tokens.body) return tokens;\n const brandDoc = await readWorkspaceBrandDoc(root, opts.readBrandDoc ? { read: opts.readBrandDoc } : {});\n return namedTypefaces({ tokensJson, brandDoc });\n}\n\nconst MARK_FILE = /isotype|isologo|symbol|logomark|brandmark|(^|[-_ ])(mark|icon|avatar)([-_ .]|$)/i;\n\n/** The words a logo file's name uses for which logo, colour or size it is, never for whose artwork it holds. */\nconst VARIANT_WORDS = new Set(\n (\n \"logo logos logotype logotipo lockup wordmark isotype isotipo isologo symbol logomark brandmark mark icon avatar favicon \" +\n \"brand primary secondary main default full horizontal vertical stacked square round circle alt outline transparent \" +\n \"light dark white black mono inverse inverted negative positive negativo positivo reverse reversed color colour \" +\n \"on blanco negro negra claro clara oscuro oscura rgb cmyk small large sm md lg \" +\n \"red blue green yellow orange purple violet pink grey gray navy teal cyan magenta brown gold silver coral \" +\n \"rojo roja azul verde amarillo amarilla naranja morado morada rosa gris dorado dorada plateado plateada\"\n ).split(\" \"),\n);\n\n/** Whose artwork a logo file holds, as its name tells: the name with every variant, colour and size word dropped, and the brand's own name. \"\" is the brand's own. Pure. */\nfunction artworkOwner(file: string, slug: string): string {\n const rest = path\n .basename(file)\n .replace(/\\.[a-z0-9]+$/i, \"\")\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter((w) => w && !VARIANT_WORDS.has(w) && !/^\\d+(x|px|w|h)?$/.test(w))\n .join(\"\");\n return slug.length > 2 ? rest.replace(slug, \"\") : rest;\n}\n\n/**\n * The files that hold the brand's own logo, in its variants: the ones whose name says nothing\n * past which variant it is (or names the brand); with none, the largest family of one artwork,\n * a tie going to the family of the mark `pickBrandMark` picks. A partner's lockup filed beside\n * it (`logo-claude-code.png`) is another artwork, and never one of them. Pure.\n */\nfunction ownLogoFamily(files: string[], slug: string): string[] {\n const families = new Map<string, string[]>();\n for (const f of files) {\n const owner = artworkOwner(f, slug);\n families.set(owner, [...(families.get(owner) ?? []), f]);\n }\n const own = families.get(\"\");\n if (own) return own;\n const picked = pickBrandMark(files.map((f) => path.basename(f)));\n const ranked = [...families.values()].sort(\n (a, b) =>\n b.length - a.length ||\n Number(b.some((f) => path.basename(f) === picked)) - Number(a.some((f) => path.basename(f) === picked)),\n );\n return ranked[0] ?? [];\n}\n\n/**\n * Every variant of the brand's own logo (light and dark, lockup and wordmark), and its square\n * mark when a file is one: a native screen picks the variant that reads on it, and the mark is its\n * avatar. tokens.json's logos are the whole list when it names any. Without it, a file in\n * src/brand/logos is the brand's when its name says logo or carries the brand's name and holds\n * the brand's own artwork (`ownLogoFamily`); a tool's or partner's icon or lockup is not. Never throws.\n */\nexport async function readBrandLogoFiles(\n root: string,\n brandName?: string,\n): Promise<{ logos: string[]; mark?: string }> {\n const dir = path.join(root, BRAND_DIR, \"logos\");\n const slug = (brandName ?? \"\")\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"\");\n const named = await tokenLogos(root);\n let candidates: string[];\n if (named.length > 0) {\n candidates = named;\n } else {\n const files = ((await readdir(dir).catch(() => [])) as string[])\n .filter((f) => /\\.(png|jpe?g|webp|svg)$/i.test(f))\n .sort();\n const ours = (f: string) =>\n LOGO_FILE.test(f) ||\n (slug.length > 2 &&\n f\n .toLowerCase()\n .replace(/[^a-z0-9]/g, \"\")\n .includes(slug));\n candidates = ownLogoFamily(files.filter(ours), slug).map((f) => path.join(dir, f));\n }\n const notes = await Promise.all(\n [path.join(root, BRAND_DIR, \"BRAND.md\"), path.join(dir, \"README.md\")].map((f) =>\n readFile(f, \"utf8\").catch(() => \"\"),\n ),\n );\n const retired = retiredLogos(notes.join(\"\\n\"));\n const real: string[] = [];\n for (const full of candidates) {\n if (retired.has(path.basename(full).toLowerCase())) continue;\n if (await markIsReal(full, root)) real.push(full);\n }\n const mark = real.find((f) => MARK_FILE.test(path.basename(f)));\n const logos = real.filter((f) => f !== mark);\n return { logos: logos.length > 0 ? logos : real, ...(mark ? { mark } : {}) };\n}\n\n/** A line that calls what it names retired: only words that mean \"no longer the brand's\", never a usage rule (\"never on white\"). */\nconst RETIRED =\n /\\b(retired|deprecated|legacy|outdated|obsolete|no longer (?:used|in use)|retirad[oa]|obsolet[oa]|antigu[oa])\\b/i;\n\n/**\n * The logo file names (lower case) the brand's notes retire: a line naming one file and a word that\n * retires it. A line naming two (\"logo-primary.svg replaces the retired logo-dark.svg\") cannot say\n * which, and retires neither. Pure.\n */\nfunction retiredLogos(notes: string): Set<string> {\n const out = new Set<string>();\n for (const line of notes.split(\"\\n\")) {\n if (!RETIRED.test(line)) continue;\n const named = [...line.matchAll(/[\\w.-]+\\.(?:png|jpe?g|webp|svg)\\b/gi)].map((m) => m[0].toLowerCase());\n if (new Set(named).size === 1 && named[0]) out.add(named[0]);\n }\n return out;\n}\n\n/** The logo files tokens.json lists that are on disk, absolute, in its order. Never throws. */\nasync function tokenLogos(root: string): Promise<string[]> {\n const raw = await readFile(path.join(root, BRAND_DIR, \"tokens.json\"), \"utf8\").catch(() => null);\n if (!raw) return [];\n let json: unknown;\n try {\n json = JSON.parse(raw);\n } catch {\n return [];\n }\n const parsed = brandTokensSchema.safeParse(json);\n if (!parsed.success) return [];\n const out: string[] = [];\n for (const logo of parsed.data.logos) {\n const abs = path.join(root, logo.path);\n if (/\\.(png|jpe?g|webp|svg)$/i.test(abs) && (await exists(abs)) && !out.includes(abs)) out.push(abs);\n }\n return out;\n}\n","/**\n * The render graph of a static ad drawn as a native surface (`native-surface.ts`), rebuilt from\n * prompt.json on every run:\n *\n * photo_<n> (image_generate: one plain photo the screen holds, no words) role native_photo\n * ref_photo_<n> (ingest: a photo of ours the spec names by `image`) role native_photo\n * native_<size> (static_native: the screen drawn at that size) role static_native\n * final (collect, one label per format)\n *\n * The prompt, the reference, the logo and font ingests of the canvas are kept; everything the\n * image route had (variants, prefilter, master, re-lays) goes, since no picture of the ad is\n * painted. Whether a static ad takes this route is prompt.json's to say (`native`), so adding\n * the block to an existing ad switches it on the next run, and removing it is a re-scaffold.\n *\n * Pure.\n */\nimport { nearestSupportedAspectRatio } from \"@baker/canvas-contract\";\nimport type { NodeDecl } from \"../schema/canvas.ts\";\nimport { avatarPhotoIds, type InterfaceWords, type NativePhoto, nativePhotosShown } from \"./native-surface.ts\";\nimport type { AdSpec } from \"./static-ad-spec.ts\";\nimport { BRAND_LOGO_ROLE, STATIC_AD_ROLE } from \"./static-render-briefs.ts\";\nimport { formatSlug } from \"./static-topology.ts\";\n\n/** A photo a native screen holds, rendered or ours. */\nexport const NATIVE_PHOTO_ROLE = \"native_photo\";\n/** One delivered size of a native screen. */\nexport const STATIC_NATIVE_ROLE = \"static_native\";\n/** The brand's square mark, an avatar on a native screen. */\nexport const BRAND_MARK_ROLE = \"brand_mark\";\n\ntype Node = {\n id?: unknown;\n type?: unknown;\n params?: Record<string, unknown>;\n inputs?: Record<string, unknown>;\n tags?: { role?: unknown; wired?: unknown };\n};\n\nfunction nodesOf(canvas: unknown): Node[] {\n const nodes = (canvas as { nodes?: unknown } | null)?.nodes;\n return Array.isArray(nodes) ? (nodes as Node[]) : [];\n}\n\n/** Whether the canvas draws its ad as a native surface. */\nexport function isNativeCanvas(canvas: unknown): boolean {\n return nodesOf(canvas).some((n) => n.tags?.role === STATIC_NATIVE_ROLE);\n}\n\n/** Where the people in a photo are from, and that they are ordinary people of there. */\nfunction peopleOf(spec: Pick<AdSpec, \"viewer\">): string {\n const country = spec.viewer?.market?.country;\n const where = country && country.toLowerCase() !== \"global\" ? ` who lives in ${countryName(country)}` : \"\";\n return `Anyone in it is an ordinary person${where}, the age and look the description gives, never a model: real skin with its lines and pores, everyday clothes, an unposed moment, unretouched.`;\n}\n\nconst COUNTRIES: Record<string, string> = {\n ES: \"Spain\",\n MX: \"Mexico\",\n AR: \"Argentina\",\n CO: \"Colombia\",\n CL: \"Chile\",\n PE: \"Peru\",\n BR: \"Brazil\",\n PT: \"Portugal\",\n US: \"the United States\",\n GB: \"the United Kingdom\",\n UK: \"the United Kingdom\",\n FR: \"France\",\n DE: \"Germany\",\n IT: \"Italy\",\n};\n\nfunction countryName(code: string): string {\n return COUNTRIES[code.toUpperCase()] ?? code;\n}\n\n/**\n * The prompt of one photo the screen holds: a plain photo, as a person would post it or a chat\n * would show it, with no words in it (the screen prints every word). Tier 1, Oct 2026: the people\n * the image model drew for an ad were \"young, good looking, very AI\" for a trade course aimed at\n * 45-60 year olds in Spain; so who is in it comes from the description and the market, and how\n * they look is a phone photo of ordinary people. Pure.\n */\nexport function nativePhotoBrief(photo: NativePhoto, spec: Pick<AdSpec, \"viewer\">, use: \"avatar\" | \"picture\"): string {\n const kind =\n photo.look === \"illustration\"\n ? \"An illustration\"\n : use === \"avatar\"\n ? \"A casual profile photo a person would use on their own account, head and shoulders, taken on a phone\"\n : \"A photo taken on a phone, the way a real person would post it\";\n return [\n `${kind}: ${photo.what.trim().replace(/\\.$/, \"\")}.`,\n photo.look === \"photo\" ? peopleOf(spec) : \"\",\n photo.look === \"photo\" ? \"Natural light, true colours, a little imperfect, nothing staged or stock-like.\" : \"\",\n \"No text, letters, numbers, logos, watermarks, borders, frames or interface anywhere in the picture.\",\n ]\n .filter(Boolean)\n .join(\" \");\n}\n\n/** The ratio `model` is asked for, for a photo's shape on the screen: the nearest it takes (the screen crops to the shape). */\nfunction photoRatio(photo: NativePhoto, use: \"avatar\" | \"picture\", model: string): string {\n return use === \"avatar\" ? \"1:1\" : nearestSupportedAspectRatio(\"image_generate\", model, photo.ratio);\n}\n\n/** Whether a photo is somebody's avatar on the screen (else a picture in a post or a card). */\nfunction useOf(photo: NativePhoto, spec: Pick<AdSpec, \"native\">): \"avatar\" | \"picture\" {\n return spec.native && avatarPhotoIds(spec.native).has(photo.id) ? \"avatar\" : \"picture\";\n}\n\nexport type NativeGraphOpts = {\n /** The image model the photos render on, and what each request asks for besides the prompt. */\n genModel: string;\n genParams: Record<string, unknown>;\n /** Every delivered format, in delivery order. */\n formats: readonly string[];\n /** The ad set's placements the 9:16 keeps clear of. */\n placements?: readonly string[];\n /** Paths (or URLs) of every variant of the brand's logo, and its square mark. */\n logos: readonly string[];\n mark?: string;\n /** The `$ref` of the brand's headline face, when the canvas ingests one. */\n fontRef?: string;\n /** Where a photo of ours (`photos[].image`) resolves from: the creative's folder. */\n resolve: (image: string) => { source: \"path\"; path: string } | { source: \"url\"; url: string };\n /** The interface's words written for the viewer's language (`needsInterfaceWords`), drawn by every screen. */\n interfaceWords?: InterfaceWords;\n};\n\n/** The ids the graph's own ingests take. */\nfunction logoId(i: number): string {\n return i === 0 ? \"brand_logo\" : `brand_logo_${i + 1}`;\n}\n\n/**\n * The canvas drawn as the spec's native surface: its spine (the prompt, the reference, the font)\n * kept, the brand's logos and mark ingested, one photo node per photo the screen shows and one\n * screen per size. Pure: canvas and spec in, the new canvas out.\n */\nexport function nativeCanvas<C extends { nodes: unknown[] }>(canvas: C, spec: AdSpec, opts: NativeGraphOpts): C {\n if (!spec.native) return canvas;\n const kept = nodesOf(canvas).filter(\n (n) => n.tags?.role === STATIC_AD_ROLE || n.id === \"original\" || n.id === \"font_headline\",\n ) as NodeDecl[];\n const wired = logosWired(canvas, opts);\n const logos: NodeDecl[] = wired.map((where, i) => ({\n id: logoId(i),\n type: \"ingest\",\n params: { ...where, expect: \"image\" },\n ...(i === 0 ? { tags: { role: BRAND_LOGO_ROLE, wired: wired.map(placeOf) } } : {}),\n }));\n const mark: NodeDecl[] = opts.mark\n ? [\n {\n id: \"brand_mark\",\n type: \"ingest\",\n params: { ...locate(opts.mark, opts), expect: \"image\" },\n tags: { role: BRAND_MARK_ROLE },\n },\n ]\n : [];\n const shown = nativePhotosShown(spec.native);\n const photos: NodeDecl[] = shown.map((photo) => {\n const id = photo.id.toLowerCase();\n if (photo.image) {\n return {\n id: `ref_${id}`,\n type: \"ingest\",\n params: { ...opts.resolve(photo.image), expect: \"image\" },\n tags: { role: NATIVE_PHOTO_ROLE },\n };\n }\n const use = useOf(photo, spec);\n return {\n id,\n type: \"image_generate\",\n params: {\n model: opts.genModel,\n aspect_ratio: photoRatio(photo, use, opts.genModel),\n ...opts.genParams,\n prompt: nativePhotoBrief(photo, spec, use),\n },\n tags: { role: NATIVE_PHOTO_ROLE },\n };\n });\n const photoRefs = shown.map((p) =>\n p.image ? `$ref:ref_${p.id.toLowerCase()}.asset` : `$ref:${p.id.toLowerCase()}.images#0`,\n );\n const screens: NodeDecl[] = opts.formats.map((format) => ({\n id: `native_${formatSlug(format)}`,\n type: \"static_native\",\n inputs: {\n spec: \"$ref:prompt.asset\",\n ...(logos.length > 0 ? { logos: logos.map((l) => `$ref:${l.id}.asset`) } : {}),\n ...(mark.length > 0 ? { mark: \"$ref:brand_mark.asset\" } : {}),\n ...(opts.fontRef ? { font: opts.fontRef } : {}),\n ...(photoRefs.length > 0 ? { photos: photoRefs } : {}),\n },\n params: {\n format,\n ...(opts.placements ? { placements: [...opts.placements] } : {}),\n photo_ids: shown.map((p) => p.id),\n ...(opts.interfaceWords ? { interface_words: opts.interfaceWords } : {}),\n },\n tags: { role: STATIC_NATIVE_ROLE },\n }));\n const final: NodeDecl = {\n id: \"final\",\n type: \"collect\",\n inputs: { images: screens.map((s) => `$ref:${s.id}.image`) },\n params: { labels: [...opts.formats] },\n };\n return { ...canvas, nodes: [...kept, ...logos, ...mark, ...photos, ...screens, final] };\n}\n\ntype Located = ReturnType<typeof locate>;\n\nfunction placeOf(where: Located): string {\n return where.source === \"url\" ? where.url : where.path;\n}\n\n/**\n * The logos the screens are handed: every one of the brand's own, unless the canvas ingests a\n * set other than the one it last wired itself (`tags.wired`), which is a logo an agent chose by\n * hand and survives the rebuild. One no longer among the brand's own (a partner's lockup wired\n * before, a file since retired) is dropped. Pure.\n */\nfunction logosWired(canvas: unknown, opts: NativeGraphOpts): Located[] {\n const own = opts.logos.map((file) => locate(file, opts));\n const ownPlaces = new Set(own.map(placeOf));\n const ingests = nodesOf(canvas).filter(\n (n) => n.type === \"ingest\" && typeof n.id === \"string\" && /^brand_logo(_\\d+)?$/.test(n.id),\n );\n const present = ingests.flatMap((n): Located[] => {\n const p = n.params;\n if (p?.source === \"url\" && typeof p.url === \"string\") return [locate(p.url, opts)];\n if (p?.source === \"path\" && typeof p.path === \"string\") return [locate(p.path, opts)];\n return [];\n });\n const lastWired = ingests.map((n) => n.tags?.wired).find(Array.isArray);\n const byHand =\n lastWired !== undefined &&\n (lastWired.length !== present.length || present.some((where, i) => placeOf(where) !== lastWired[i]));\n if (!byHand) return own;\n const chosen = present.filter((where) => {\n if (!ownPlaces.has(placeOf(where))) return false;\n ownPlaces.delete(placeOf(where));\n return true;\n });\n return chosen.length > 0 ? chosen : own;\n}\n\nfunction locate(file: string, opts: NativeGraphOpts) {\n return /^https?:\\/\\//i.test(file) ? { source: \"url\" as const, url: file } : opts.resolve(file);\n}\n\n/** The formats and placements a static canvas delivers, and the image model it renders on, read back off it. */\nexport function deliveryOf(canvas: unknown): {\n formats: string[];\n placements?: string[];\n genModel?: string;\n genParams: Record<string, unknown>;\n} {\n const nodes = nodesOf(canvas);\n const labels = nodes.find((n) => n.id === \"final\" && n.type === \"collect\")?.params?.labels;\n const formats = Array.isArray(labels) ? labels.filter((l): l is string => typeof l === \"string\") : [];\n const withPlacements = nodes.find((n) => Array.isArray(n.params?.placements));\n const placements = withPlacements?.params?.placements as string[] | undefined;\n const render = nodes.find(\n (n) =>\n n.type === \"image_generate\" &&\n (n.tags?.role === NATIVE_PHOTO_ROLE ||\n n.tags?.role === \"static_variants\" ||\n n.tags?.role === \"static_variant_call\"),\n );\n const genParams = { ...(render?.params ?? {}) };\n for (const key of [\"model\", \"prompt\", \"aspect_ratio\", \"n\"]) delete genParams[key];\n return {\n formats,\n ...(placements ? { placements } : {}),\n ...(typeof render?.params?.model === \"string\" ? { genModel: render.params.model } : {}),\n genParams,\n };\n}\n","import { readdir, readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { logoArtwork } from \"../../engine/nodes/local/lib/logo-raster.ts\";\nimport { logoColourways } from \"../../engine/scaffold/static-logo.ts\";\n\n/**\n * The brand's logo file as the composite places it: its shape (width over height of its artwork,\n * measured, to two places) and the same artwork in its other colours beside it in its folder\n * (absolute paths). Null when the file does not open as a picture: the model then draws it.\n */\nexport async function readLogoFile(file: string): Promise<{ aspect: number; colourways: string[] } | null> {\n let aspect: number;\n try {\n const art = await logoArtwork(await readFile(file));\n aspect = Math.round((art.width / art.height) * 100) / 100;\n } catch {\n return null;\n }\n const dir = path.dirname(file);\n const files = ((await readdir(dir).catch(() => [])) as string[]).filter((f) => /\\.(png|jpe?g|webp|svg)$/i.test(f));\n return { aspect, colourways: logoColourways(path.basename(file), files.sort()).map((f) => path.join(dir, f)) };\n}\n","import { readFile, stat, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { BRAND_DIR } from \"../../engine/scaffold/ad-brand-source.ts\";\nimport { AdSpecSchema, isAdSpec, readAdSpec, referenceNodeId } from \"../../engine/scaffold/static-ad-spec.ts\";\nimport { addNamedPeople, type FoundAvatar, type PeopleReader } from \"../../engine/scaffold/static-named-people.ts\";\nimport { type CitationJudge, citedPlatforms } from \"../../engine/scaffold/review-platforms.ts\";\nimport { addProofBadges } from \"../../engine/scaffold/static-proof.ts\";\nimport { readStaticBrandKit } from \"../../engine/scaffold/static-brand.ts\";\nimport { projectAdaptBriefs } from \"../../engine/scaffold/static-adapt-briefs.ts\";\nimport { projectFormatBriefs } from \"../../engine/scaffold/static-format-briefs.ts\";\nimport { projectLogoPlacement } from \"../../engine/scaffold/static-logo-briefs.ts\";\nimport { readLogoFile } from \"./logo-file.ts\";\nimport type { NodeDecl } from \"../../engine/schema/canvas.ts\";\nimport {\n BRAND_LOGO_COLOURWAY_ROLE,\n BRAND_LOGO_ROLE,\n isStaticBriefCanvas,\n projectStaticBriefs,\n} from \"../../engine/scaffold/static-render-briefs.ts\";\nimport type { CreativeRule } from \"../../engine/creative-rules/schema.ts\";\nimport { LOGO_COMPOSITE_ROLE, placeLogoFromFile } from \"../../engine/scaffold/static-topology.ts\";\n\n/**\n * Keep a static ad's render prompts where the agent edits the ad: `prompt.json`.\n *\n * The agent writes the ad spec in prompt.json (the canvas is not for hand edits), and every\n * render prompt is compiled from it (`static-render-briefs.ts`). Frozen at scaffold time, the\n * render was told the SOURCE ad's words while prompt.json said ours. This compiles the briefs\n * again before anything bills, the way `syncSceneNodeParams` re-flows scene files;\n * `prepareCanvas` then writes the result back to the canvas file, so the file (and the\n * dashboard) shows the prompt that renders, and an edit re-keys exactly the nodes it touches.\n * A canvas scaffolded before the compiler is upgraded in place the same way.\n */\ntype StaticCopySyncResult = \"regenerated\" | \"up_to_date\" | \"not_applicable\";\n\ntype CanvasNode = {\n id?: unknown;\n type?: unknown;\n params?: Record<string, unknown>;\n inputs?: Record<string, unknown>;\n tags?: { role?: unknown };\n};\n\nfunction nodesOf(canvas: unknown): CanvasNode[] {\n const nodes = (canvas as { nodes?: unknown } | null)?.nodes;\n return Array.isArray(nodes) ? (nodes as CanvasNode[]) : [];\n}\n\n/** The path of the `prompt` ingest a static ad renders from, once paths are resolved. */\nfunction blueprintPath(nodes: CanvasNode[]): string | null {\n const prompt = nodes.find((n) => n.id === \"prompt\" && n.type === \"ingest\");\n const p = prompt?.params;\n if (p?.source !== \"path\" || p.expect !== \"json\" || typeof p.path !== \"string\" || p.path.includes(\"[TODO\")) {\n return null;\n }\n return p.path;\n}\n\n/** The content of the prompt.json a static canvas renders from, or null when it has none. Throws on unreadable JSON. */\nexport async function readStaticPromptJson(canvas: unknown): Promise<unknown | null> {\n const source = blueprintPath(nodesOf(canvas));\n return source ? JSON.parse(await readFile(source, \"utf8\")) : null;\n}\n\n/**\n * The workspace whose brand a folder draws with: the nearest folder at or above it that holds\n * `src/brand`. Not `findWorkspaceRoot` (normalize-paths.ts), which stops at the nearest\n * `package.json` and anchors path healing and `canvas/` outputs; this one only feeds the brand kit.\n */\nexport async function findBrandRoot(start: string): Promise<string | null> {\n let dir = path.resolve(start);\n for (;;) {\n if (\n await stat(path.join(dir, BRAND_DIR)).then(\n (s) => s.isDirectory(),\n () => false,\n )\n )\n return dir;\n const parent = path.dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\n/**\n * Compile every render prompt (the takes, the re-lays, the judge) and the type specimen's\n * text from prompt.json, in place. Call AFTER `resolveRelativeCanvasPaths` and\n * `syncStaticAdLogo`. Throws when prompt.json is unreadable, not JSON, or an invalid ad spec:\n * the caller must stop before billing.\n */\nexport async function syncStaticAdBrief(\n canvas: unknown,\n log: (line: string) => void,\n /** The company's rules this ad is held to: the ones a picture can keep reach every take and the judge. */\n rules: readonly CreativeRule[] = [],\n): Promise<StaticCopySyncResult> {\n if (!isStaticBriefCanvas(canvas)) return \"not_applicable\";\n const promptJson = await readStaticPromptJson(canvas);\n if (promptJson === null) return \"not_applicable\";\n const changed =\n // Where the logo goes first: every brief that keeps its slot plain plans it from there.\n projectLogoPlacement(nodesOf(canvas) as Parameters<typeof projectLogoPlacement>[0], readAdSpec(promptJson)) +\n projectStaticBriefs(canvas, promptJson, rules) +\n projectAdaptBriefs(canvas, promptJson) +\n projectFormatBriefs(canvas, promptJson, rules);\n if (changed === 0) return \"up_to_date\";\n log(\"[brief] the ad was re-read from prompt.json; each render's brief and the type specimen now show it\");\n return \"regenerated\";\n}\n\n/**\n * The canvas without the composites that place the logos `ids` on its sizes: whatever read a\n * composite reads the size under it.\n */\nfunction dropLogoComposites<N extends { id?: unknown; inputs?: Record<string, unknown>; tags?: { role?: unknown } }>(\n nodes: N[],\n ids: ReadonlySet<string>,\n): N[] {\n const under = new Map<string, string>();\n for (const n of nodes) {\n // A composite places one file (`logo`, an older graph) or the logo's colourways (`logos`).\n const files = Array.isArray(n.inputs?.logos) ? n.inputs.logos : [n.inputs?.logo];\n const placesDropped = files.some((f) => ids.has(String(f ?? \"\").match(/^\\$ref:([a-z][a-z0-9_]*)\\./)?.[1] ?? \"\"));\n if (n.tags?.role === LOGO_COMPOSITE_ROLE && placesDropped && typeof n.inputs?.image === \"string\") {\n under.set(`$ref:${String(n.id)}.image`, n.inputs.image);\n }\n }\n if (under.size === 0) return nodes;\n const dropped = new Set([...under.keys()].map((ref) => ref.slice(\"$ref:\".length, -\".image\".length)));\n return nodes\n .filter((n) => !dropped.has(String(n.id)))\n .map((n) => {\n if (!n.inputs) return n;\n const text = JSON.stringify(n.inputs);\n const next = text.replace(/\"(\\$ref:[a-z][a-z0-9_]*\\.image)\"/g, (m, ref: string) =>\n under.has(ref) ? JSON.stringify(under.get(ref)) : m,\n );\n return next === text ? n : { ...n, inputs: JSON.parse(next) as Record<string, unknown> };\n });\n}\n\n/**\n * Keep the logo where the agent decides it: `prompt.json`. The scaffold wires the brand's\n * logo file for every standard ad; `\"logo\": false` in the ad spec (or, in an older\n * blueprint, the same key) is how the concept drops it,\n * and that has to reach the canvas on every run, or the model is still handed the file while\n * the review expects none. Removes the logo ingest and its reference in every render; the\n * brief compiled after it then asks for no logo. The reverse (a logo added to a canvas\n * scaffolded without the file) needs the file wired, so it is only reported. Throws when\n * prompt.json is unreadable, like the brief sync.\n */\n/**\n * The brand's logo file wired into a static canvas: one `brand_logo` ingest before the first\n * render, and its picture added to every render's references (the variants and each re-laid-out\n * size), so the brief projection that follows numbers it and tells the model to reproduce it.\n */\nfunction wireLogo(holder: { nodes?: unknown }, nodes: CanvasNode[], renders: CanvasNode[], file: string): void {\n const ref = \"$ref:brand_logo.asset\";\n for (const node of renders) {\n const reference = node.inputs?.reference;\n const list = Array.isArray(reference) ? reference : reference === undefined ? [] : [reference];\n node.inputs = { ...node.inputs, reference: [...list, ref] };\n }\n const logo: CanvasNode = {\n id: \"brand_logo\",\n type: \"ingest\",\n params: { source: \"path\", path: file, expect: \"image\" },\n tags: { role: BRAND_LOGO_ROLE },\n };\n const at = nodes.findIndex((n) => renders.includes(n));\n holder.nodes = [...nodes.slice(0, at), logo, ...nodes.slice(at)];\n}\n\nexport async function syncStaticAdLogo(canvas: unknown, log: (line: string) => void): Promise<StaticCopySyncResult> {\n const holder = canvas as { nodes?: unknown };\n const nodes = nodesOf(canvas);\n const source = blueprintPath(nodes);\n const logoNodes = nodes.filter((n) => n.type === \"ingest\" && n.tags?.role === BRAND_LOGO_ROLE);\n const colourways = nodes.filter((n) => n.type === \"ingest\" && n.tags?.role === BRAND_LOGO_COLOURWAY_ROLE);\n const renders = nodes.filter((n) => n.type === \"image_generate\" && typeof n.params?.prompt === \"string\");\n if (!source || renders.length === 0 || !isStaticBriefCanvas(canvas)) return \"not_applicable\";\n const wanted = readAdSpec(JSON.parse(await readFile(source, \"utf8\"))).logo;\n if (wanted && logoNodes.length === 0) {\n const root = await findBrandRoot(path.dirname(source));\n const file = root ? (await readStaticBrandKit(root)).logo : undefined;\n if (!file) {\n log(\"[logo] prompt.json keeps the logo but src/brand/logos/ has no real logo file: add it and the next run wires it\");\n return \"up_to_date\";\n }\n wireLogo(holder, nodes, renders, file);\n log(`[logo] prompt.json keeps the logo: wired the brand's logo file (${path.basename(file)}) into every render`);\n return \"regenerated\";\n }\n if (!wanted && logoNodes.length > 0) {\n const ids = new Set([...logoNodes, ...colourways].map((n) => String(n.id)));\n for (const node of renders) {\n const inputs = node.inputs ?? {};\n const reference = inputs.reference;\n if (Array.isArray(reference)) {\n const kept = reference.filter((r) => !ids.has(String(r).match(/^\\$ref:([a-z][a-z0-9_]*)\\./)?.[1] ?? \"\"));\n if (kept.length > 0) inputs.reference = kept;\n else delete inputs.reference;\n }\n }\n holder.nodes = dropLogoComposites(nodes, ids).filter((n) => !ids.has(String(n.id)));\n log(\"[logo] prompt.json no longer keeps the logo, so the logo file is unwired and the render is told to draw none\");\n return \"regenerated\";\n }\n return \"up_to_date\";\n}\n\n/**\n * Keep the brand's logo file placed on every size of a static canvas that places it\n * (`placeLogoFromFile`): every colour the file comes in beside it (`logoColourways`,\n * `brand_logo_<n>`) and the slot planned with the file's own shape. A canvas whose model draws the\n * logo from its file keeps drawing it: moving those onto the pasted file (Oct 2026) took the logo out\n * of every render's references and left a stamped corner the picture was never drawn around. A file\n * that does not open as a picture is left to the model, and the run says so. Call AFTER\n * `syncStaticAdLogo` and before the brief projection, which then tells every render to keep the slot plain.\n */\nexport async function syncLogoPlacement(canvas: unknown, log: (line: string) => void): Promise<StaticCopySyncResult> {\n const holder = canvas as { nodes?: unknown };\n const nodes = nodesOf(canvas);\n const source = blueprintPath(nodes);\n if (!source || !isStaticBriefCanvas(canvas)) return \"not_applicable\";\n if (!readAdSpec(JSON.parse(await readFile(source, \"utf8\"))).logo) return \"up_to_date\";\n if (!nodes.some((n) => n.tags?.role === LOGO_COMPOSITE_ROLE)) return \"up_to_date\";\n const logo = nodes.find((n) => n.type === \"ingest\" && n.tags?.role === BRAND_LOGO_ROLE);\n const file = logo?.params?.source === \"path\" && typeof logo.params.path === \"string\" ? logo.params.path : null;\n if (!logo || !file) return \"up_to_date\";\n const read = await readLogoFile(file);\n if (!read) {\n log(\n `[logo] the logo file ${path.basename(file)} could not be opened as a picture, so this run's model draws the logo from it; replace it in src/brand/logos/ with a PNG or SVG that opens, and the next run places it exactly`,\n );\n return \"up_to_date\";\n }\n const { aspect, colourways: others } = read;\n const colourways: CanvasNode[] = others.map((f, i) => ({\n id: `brand_logo_${i + 2}`,\n type: \"ingest\",\n params: { source: \"path\", path: f, expect: \"image\" },\n tags: { role: BRAND_LOGO_COLOURWAY_ROLE },\n }));\n const kept = nodes.filter((n) => n.tags?.role !== BRAND_LOGO_COLOURWAY_ROLE);\n const at = kept.indexOf(logo) + 1;\n const wired = { ...holder, nodes: [...kept.slice(0, at), ...colourways, ...kept.slice(at)] };\n const placed = placeLogoFromFile(wired as { nodes: NodeDecl[] }, {\n files: [`$ref:${String(logo.id)}.asset`, ...colourways.map((c) => `$ref:${String(c.id)}.asset`)],\n aspect,\n });\n if (JSON.stringify(placed.canvas.nodes) === JSON.stringify(nodes)) return \"up_to_date\";\n holder.nodes = placed.canvas.nodes;\n log(\n `[logo] the brand's logo file (${path.basename(file)}${others.length > 0 ? ` and ${others.map((f) => path.basename(f)).join(\", \")}` : \"\"}) is placed on every size exactly as it is; no model draws it`,\n );\n return \"regenerated\";\n}\n\nconst REF_NODE = /^ref_[a-z]+_\\d+$/;\n\n/**\n * Wire the pictures prompt.json names (`references[].image`) into a static canvas: one ingest per\n * picture (`ref_<id>`, a path from the creative's folder or a URL), added to every render's\n * references so the brief numbers it; a picture prompt.json no longer names is unwired. So a\n * picture of ours is named where the ad is written, never hand-wired in canvas.json (audited\n * Sept 2026: 64 hand edits of canvas.json in 8 chats). Runs before the brief projection.\n */\nexport async function syncStaticAdReferences(canvas: unknown, log: (line: string) => void): Promise<StaticCopySyncResult> {\n const holder = canvas as { nodes?: unknown };\n const nodes = nodesOf(canvas);\n const source = blueprintPath(nodes);\n const renders = nodes.filter((n) => n.type === \"image_generate\" && typeof n.params?.prompt === \"string\");\n if (!source || renders.length === 0 || !isStaticBriefCanvas(canvas)) return \"not_applicable\";\n const spec = readAdSpec(JSON.parse(await readFile(source, \"utf8\")));\n const wanted = new Map(\n spec.references.flatMap((r) => (r.image ? [[referenceNodeId(r), { id: r.id, image: r.image }] as const] : [])),\n );\n const paramsOf = (image: string) =>\n /^https?:\\/\\//i.test(image)\n ? { source: \"url\", url: image, expect: \"image\" }\n : { source: \"path\", path: path.resolve(path.dirname(source), image), expect: \"image\" };\n let changed = false;\n const stale = new Set(\n nodes.filter((n) => typeof n.id === \"string\" && REF_NODE.test(n.id) && !wanted.has(n.id)).map((n) => String(n.id)),\n );\n let next = nodes.filter((n) => !stale.has(String(n.id)));\n if (stale.size > 0) changed = true;\n for (const render of renders) {\n const reference = render.inputs?.reference;\n if (!Array.isArray(reference)) continue;\n const kept = reference.filter((r) => !stale.has(String(r).match(/^\\$ref:([a-z][a-z0-9_]*)\\./)?.[1] ?? \"\"));\n if (kept.length === reference.length) continue;\n if (kept.length > 0) render.inputs = { ...render.inputs, reference: kept };\n else {\n const { reference: _r, ...rest } = render.inputs ?? {};\n render.inputs = rest;\n }\n }\n for (const [id, { id: label, image }] of wanted) {\n const params = paramsOf(image);\n const existing = next.find((n) => n.id === id);\n if (existing) {\n if (JSON.stringify(existing.params) !== JSON.stringify(params)) {\n existing.params = params;\n changed = true;\n }\n continue;\n }\n const at = next.findIndex((n) => renders.includes(n));\n next = [...next.slice(0, at), { id, type: \"ingest\", params }, ...next.slice(at)];\n for (const render of renders) {\n const reference = render.inputs?.reference;\n const list = Array.isArray(reference) ? reference : reference === undefined ? [] : [reference];\n render.inputs = { ...render.inputs, reference: [...list, `$ref:${id}.asset`] };\n }\n log(`[pictures] prompt.json shows ${label} from ${image}: wired into every render`);\n changed = true;\n }\n holder.nodes = next;\n return changed ? \"regenerated\" : \"up_to_date\";\n}\n\n/**\n * Wire the real badge of every review platform prompt.json's copy cites (D3), writing it into\n * prompt.json where the ad is written: the platform's logo (`fetchLogo`, `baker images logo`) as\n * a `BADGE_n` reference and the platform as a proof brand. Run before the render's gate, so a\n * claim gets its source instead of a refusal; a claim the agent deletes later leaves a badge it\n * can delete too. Returns whether prompt.json changed. Never throws on a lookup that fails.\n */\nexport async function wireProofBadges(\n promptPath: string,\n fetchLogo: (domain: string) => Promise<string | null>,\n log: (line: string) => void,\n /** Which platform each line cites for reviews (`citedPlatforms`); the decision model unless given. */\n judge?: CitationJudge,\n): Promise<boolean> {\n let raw: unknown;\n try {\n raw = JSON.parse(await readFile(promptPath, \"utf8\"));\n } catch {\n return false;\n }\n if (!isAdSpec(raw)) return false;\n // A prompt.json with a bad field is the preflight's to report, in its usual words.\n const read = AdSpecSchema.safeParse(raw);\n if (!read.success) return false;\n const spec = read.data;\n const wired = await addProofBadges(spec, fetchLogo, await citedPlatforms(spec.copy.map((l) => l.text), judge));\n if (wired === spec) return false;\n const added = wired.third_party_brands.filter((b) => !spec.third_party_brands.some((o) => o.name === b.name));\n const next = { ...(raw as Record<string, unknown>), references: wired.references, third_party_brands: wired.third_party_brands };\n await writeFile(promptPath, `${JSON.stringify(next, null, 2)}\\n`, \"utf8\");\n log(`[proof] the copy cites ${added.map((b) => b.name).join(\", \")}: wired its real badge into prompt.json (\\`references\\`, \\`third_party_brands\\`)`);\n return true;\n}\n\n/**\n * Cast every real person prompt.json's copy names as themselves (a quote signed \"Lautaro Suarez,\n * CTO at Vibiz\", the founder): `research` finds their avatar (the company's, else built from their\n * public photos) and its identity sheet is written into prompt.json as a `PERSON_n` reference, so\n * every render shows their real face, never a stranger wearing their name (Oct 2026 bench). A\n * person it cannot find is left to the ad as written. Returns whether prompt.json changed.\n */\nexport async function wireNamedPeople(\n promptPath: string,\n research: (who: string) => Promise<FoundAvatar | null>,\n log: (line: string) => void,\n /** Who the copy names (`peopleReader`); with no reading, nobody is cast. */\n readNames: PeopleReader,\n): Promise<boolean> {\n let raw: unknown;\n try {\n raw = JSON.parse(await readFile(promptPath, \"utf8\"));\n } catch {\n return false;\n }\n if (!isAdSpec(raw)) return false;\n const read = AdSpecSchema.safeParse(raw);\n if (!read.success || read.data.native) return false;\n const spec = read.data;\n const people = (await readNames(spec.copy.map((l) => l.text)).catch(() => null)) ?? [];\n if (people.length === 0) return false;\n const cast = await addNamedPeople(spec, research, people);\n if (cast === spec) return false;\n const added = cast.references.filter((r) => !spec.references.some((o) => o.id === r.id));\n await writeFile(promptPath, `${JSON.stringify({ ...(raw as Record<string, unknown>), references: cast.references }, null, 2)}\\n`, \"utf8\");\n for (const ref of added) {\n log(\n `[people] the copy names a real person: cast them as themselves (@${ref.avatar}, ${ref.id} in prompt.json \\`references\\`). If \\`scene\\` or \\`direction\\` says there is no person, say where their photo sits instead.`,\n );\n }\n return true;\n}\n","/**\n * Real people a static ad's copy names: a quote signed \"Lautaro Suarez, CTO at Vibiz\", the founder,\n * a named team member. They are shown as themselves, from their own public photos (`baker avatars\n * research`), never as an invented face wearing their name (Oct 2026 bench: a CTO's quote drawn\n * beside a stranger). Who a line names is read by a text model, in any language or script\n * (`peoplePrompt`, `readPeople`); no list of job titles or capital letters decides it. Pure.\n */\nimport { z } from \"zod\";\nimport type { AdReference, AdSpec } from \"./static-ad-spec.ts\";\n\nexport type NamedPerson = {\n /** The copy line that names them. */\n line: string;\n name: string;\n /** How the research is asked for them: their name and the affiliation the line gives. */\n who: string;\n};\n\n/** Bump when the prompt changes who counts: cached readings of the old prompt are not reused. */\nexport const PEOPLE_PROMPT_VERSION = 2;\n\n/** What the model is asked about the copy: every real person a line names with who they are. Pure. */\nexport function peoplePrompt(lines: readonly string[]): string {\n return [\n 'Below are the lines of copy of an ad, numbered, in any language or several. List every real, specific person a line names together with who they are: a full name with their role or their company, as a quote\\'s signature or a team member is written (\"Lautaro Suarez, CTO at Vibiz\", \"— María López, Directora de Marketing en Acme\").',\n 'Not a person: a first name with only an initial (\"Enrique G., alumno\"), a name with no role and no company, a place, a product, a brand or a list of services.',\n \"\",\n \"For each person give:\",\n '- \"line\": the number of the line that names them',\n '- \"name\": their name exactly as the line writes it, one person each: a line naming two people together (\"Ana Ruiz y Leo Gil, fundadores\") gives two people, each with the role they share',\n '- \"affiliation\": their role, company or both, as the line gives them',\n \"\",\n \"Lines:\",\n ...lines.map((line, i) => `${i + 1}. ${JSON.stringify(line)}`),\n \"\",\n 'Reply with only this JSON: {\"people\": [{\"line\": 1, \"name\": \"…\", \"affiliation\": \"…\"}]}',\n ].join(\"\\n\");\n}\n\nconst Person = z.object({\n line: z.number().int(),\n name: z.string().trim().min(1),\n affiliation: z.string().trim().min(1),\n});\nconst Answer = z.object({ people: z.array(z.unknown()) });\n\nconst folded = (text: string) =>\n text\n .normalize(\"NFD\")\n .replace(/\\p{Diacritic}/gu, \"\")\n .toLowerCase();\n\n/**\n * The people a model's answer about `lines` names, each kept only when its line really writes the\n * name (a model never casts a name the copy does not hold; the affiliation may come back reworded,\n * \"cofundadora\" of \"cofundadores\"); null when the answer is not that shape at all. Pure.\n */\nexport function readPeople(answer: unknown, lines: readonly string[]): NamedPerson[] | null {\n const parsed = Answer.safeParse(answer);\n if (!parsed.success) return null;\n return parsed.data.people.flatMap((raw) => {\n const person = Person.safeParse(raw);\n if (!person.success) return [];\n const { line: n, name, affiliation } = person.data;\n const line = lines[n - 1];\n if (!line || !folded(line).includes(folded(name))) return [];\n return [{ line, name, who: `${name}, ${affiliation}` }];\n });\n}\n\n/** The people `lines` name (`readPeople`), or null when no model could read them. */\nexport type PeopleReader = (lines: readonly string[]) => Promise<NamedPerson[] | null>;\n\n/** A named person's avatar, as the research answers it: the handle and the identity sheet to ground on. */\nexport type FoundAvatar = { handle: string; sheetUrl: string };\n\nconst isCast = (references: readonly AdReference[], person: NamedPerson) =>\n references.some((r) => r.id.startsWith(\"PERSON_\") && r.avatar && folded(r.what).includes(folded(person.name)));\n\n/** The people the copy names (`people`, `readPeople`) that no person reference casts: the review blocks any face shown as them. */\nexport function uncastPeople(spec: Pick<AdSpec, \"references\">, people: readonly NamedPerson[]): string[] {\n return people.filter((person) => !isCast(spec.references, person)).map((person) => person.name);\n}\n\n/**\n * The spec with every person its copy names (`people`, `readPeople`) cast as themselves: `research(who)` finds their avatar\n * (the one the company has, else built from their public photos), and its identity sheet becomes a\n * `PERSON_n` reference, so every render shows their real face. A person already cast (a person\n * reference with an avatar that names them) is not asked about; one whose avatar is already cast\n * is named on that reference, never cast twice; one the research cannot find adds nothing.\n * Returns `spec` itself when nothing changed. Never throws on a lookup that fails.\n */\nexport async function addNamedPeople(\n spec: AdSpec,\n research: (who: string) => Promise<FoundAvatar | null>,\n people: readonly NamedPerson[],\n): Promise<AdSpec> {\n const references: AdReference[] = [...spec.references];\n let changed = false;\n for (const person of people) {\n if (isCast(references, person)) continue;\n const found = await research(person.who).catch(() => null);\n if (!found) continue;\n changed = true;\n // Their Avatar is already cast (`--avatar`): that reference is them, so it names them.\n const same = references.findIndex((r) => r.avatar === found.handle);\n const already = references[same];\n if (already) {\n references[same] = { ...already, what: `${person.name}, as themselves: ${already.what}` };\n continue;\n }\n references.push({\n id: `PERSON_${nextPersonNumber(references)}`,\n role: \"identity\",\n what: `${person.name}, the real person \"${person.line}\" names, shown as themselves with the face in this picture: as the scene places them, else a small round profile photo beside that line`,\n avatar: found.handle,\n image: found.sheetUrl,\n });\n }\n return changed ? { ...spec, references } : spec;\n}\n\n/** One past the highest `PERSON_n` already used, so a new id never repeats one (ids can have gaps). */\nfunction nextPersonNumber(references: readonly AdReference[]): number {\n const used = references.flatMap((r) => {\n const n = /^PERSON_(\\d+)$/.exec(r.id)?.[1];\n return n ? [Number(n)] : [];\n });\n return Math.max(0, ...used) + 1;\n}\n","/**\n * Proof on a static ad: a line that cites a review platform carries that platform's real badge\n * (D3), and a customer's words carry their name. The scaffold wires the badges (`addProofBadges`);\n * every run refuses an ad whose proof has none (`badgeProblems`, `unattributedQuotes`) before\n * anything bills. Whether a figure or a superlative is one the records hold is `claim-check.ts`.\n *\n * Pure, but for the logo lookup `addProofBadges` is handed and the decision model `readSignatures` asks.\n */\nimport { askJev } from \"../nodes/local/lib/jev.ts\";\nimport type { ReviewUsage } from \"../nodes/local/lib/render-review.ts\";\nimport { type Citations, citedBy } from \"./review-platforms.ts\";\nimport type { AdReference, AdSpec, AdThirdPartyBrand } from \"./static-ad-spec.ts\";\n\n/** The platform's badge is wired: a third-party brand of that name whose logo reference has a picture. */\nfunction badgeWired(spec: AdSpec, name: string): boolean {\n const brand = spec.third_party_brands.find((b) => b.name.toLowerCase() === name.toLowerCase());\n if (!brand?.logo) return false;\n const ref = spec.references.find((r) => r.id === brand.logo);\n return Boolean(ref && (ref.image || ref.slot));\n}\n\n/** This many words of a customer's quote in a row, in one copy line, set their words as the ad's. */\nconst QUOTED_RUN = 5;\n/** A line that signs a quote: its role, or a dash before a name (\"— Lena Fischer\"). */\nconst SIGNING_ROLE = /^(attribution|author|byline|name|reviewer|source|signature)$/i;\n/**\n * A signature by its shape alone, in any script and either case: a long dash opening the line, or a\n * dash right after the quote that opens the line closes, before a short close (\"«…» - lucía,\n * Valencia\"). A dash inside a sentence (\"Rápido — y gratis\") signs nothing, nor a minus before a\n * figure (\"-30% en tu primera factura\").\n */\nconst LEADING_DASH = /^\\s*[—–―]\\s*\\p{L}/u;\nconst QUOTED_THEN_DASH =\n /^\\s*[\\p{Pi}\"„「『][^\\p{Pf}\"」』]+[\\p{Pf}\"」』]\\s*(?:[—–―]\\s*|-\\s+)\\p{L}[^—–―\\p{Pi}\\p{Pf}\"]{0,40}$/u;\nconst NAME_WORD = \"\\\\p{Lu}[\\\\p{L}\\\\p{M}'’-]*\";\n/** A spaced dash closing the line with a first name and an initial (\"…no mess - Lena F.\", \"— Mary Ann K., Leeds\"). */\nconst SIGNED_WITH_INITIAL = new RegExp(\n `\\\\s[—–―-]\\\\s+${NAME_WORD}(?:\\\\s+${NAME_WORD})?\\\\s+\\\\p{Lu}\\\\.(?:,[^,—–―\\\\d]{1,40})?\\\\s*$`,\n \"u\",\n);\nconst signed = (text: string): boolean =>\n LEADING_DASH.test(text) || QUOTED_THEN_DASH.test(text) || SIGNED_WITH_INITIAL.test(text);\n/**\n * A spaced dash before a short capitalised close may sign a quote (\"…no mess - Lena Fischer, Leeds\")\n * or be the advertiser's call to action (\"Solar in one day - Free Survey\"), and so may a hyphen opening\n * a line (\"- Lena Fischer\", \"- Free installation\"), a long dash after a sentence ends (\"…happened. —\n * Lena Fischer\", \"…でした。— 田中\", \"Instalamos en un día. — Pide tu estudio\") and a dash after a\n * bracket or a quoted word (\"Paneles “premium” — instalación gratis\"): only what it means tells them apart.\n */\nconst MAYBE_SIGNED_AT_END =\n /\\s[—–―-]\\s+\\p{Lu}[\\p{L}\\p{M}.'’-]*(?:(?:\\s+[\\p{L}\\p{M}.'’-]+){0,2}\\s+\\p{Lu}[\\p{L}\\p{M}.'’-]*)?(?:,[^,—–―\\d]{1,40})?\\s*$/u;\nconst MAYBE_SIGNED_OPENING = /^\\s*-\\s+\\p{L}/u;\nconst MAYBE_SIGNED_AFTER_STOP = /[.!?…。!?]\\s*[—–―]\\s*\\p{L}|[\\p{Pf}\\p{Pe}\"]\\s*(?:[—–―]\\s*|-\\s+)\\p{L}/u;\n\n/** A line whose dash may sign a quote or be the advertiser's own copy: its meaning decides. Pure. */\nexport function maybeSigned(text: string): boolean {\n return (\n !signed(text) &&\n [MAYBE_SIGNED_AT_END, MAYBE_SIGNED_OPENING, MAYBE_SIGNED_AFTER_STOP].some((shape) => shape.test(text))\n );\n}\n\n/**\n * For refusing an unsigned quote, a quoted line's closing dash is unclear too: the close may be a\n * name (\"«…» — Lucía, Valencia\") or the advertiser's own words (\"“…” — Premium panels included\").\n * A translation still keeps such a line whole (`isCustomersWords`): the quote in it is theirs.\n */\nconst signedForSure = (text: string): boolean => LEADING_DASH.test(text) || SIGNED_WITH_INITIAL.test(text);\nconst signedUnclearly = (text: string): boolean =>\n !signedForSure(text) && (QUOTED_THEN_DASH.test(text) || maybeSigned(text));\n\n/** What a line is set as a customer's: a quote, or the name signing one. */\nconst QUOTE_ROLE = /^(quote|testimonial|review)$/i;\n\n/** A line that only signs: set as the signature, or opening with the dash before a name (\"— Lena Fischer\"). Pure. */\nexport function isSignatureLine(line: { text: string; role?: string | undefined }): boolean {\n return SIGNING_ROLE.test(line.role ?? \"\") || LEADING_DASH.test(line.text);\n}\n\n/**\n * A copy line that is a customer's own words or the name on them: signed with a dash before a\n * name, or set as a quote or its signature. A translation keeps it as they said it. Pure.\n */\nexport function isCustomersWords(line: { text: string; role?: string | undefined }): boolean {\n return signed(line.text) || QUOTE_ROLE.test(line.role ?? \"\") || SIGNING_ROLE.test(line.role ?? \"\");\n}\n\nconst quoteWords = (text: string): string[] =>\n text\n .toLowerCase()\n .split(/[^\\p{L}\\p{N}]+/u)\n .filter(Boolean);\n\nfunction quotes(line: string, quote: string): boolean {\n const said = ` ${quoteWords(line).join(\" \")} `;\n const words = quoteWords(quote);\n for (let i = 0; i + QUOTED_RUN <= words.length; i++) {\n if (said.includes(` ${words.slice(i, i + QUOTED_RUN).join(\" \")} `)) return true;\n }\n return false;\n}\n\n/** The line carries the first word of the name the research kept for the quote, beyond the quote's own words. */\nfunction namesAuthor(line: string, by: { quote: string; author?: string }): boolean {\n const first = by.author ? quoteWords(by.author)[0] : undefined;\n if (!first) return false;\n const quoted = new Set(quoteWords(by.quote));\n return !quoted.has(first) && quoteWords(line).includes(first);\n}\n\n/**\n * A customer's words set as copy with no name on them: the review blocks a quote nobody signed, and\n * a picture edit cannot invent the name (Dev, Oct 2026: three corrections in a row). The name is the\n * one the research kept (`author`); that name on the line, a dash before a name, or a line of its\n * own signs it. `signatures` holds the lines whose unclear dash (`maybeSigned`) the decision model\n * read as a name (`readSignatures`); without it, every such dash counts as one: a guess never\n * refuses an ad. Pure.\n */\nexport function unattributedQuotes(\n spec: AdSpec,\n said: ReadonlyArray<{ quote: string; author?: string }>,\n signatures?: ReadonlySet<string>,\n): string[] {\n const signedApart = spec.copy.some((line) => SIGNING_ROLE.test(line.role ?? \"\"));\n return spec.copy.flatMap((line) => {\n // The line already quotes a customer: a dash closing it with a name is their signature.\n const unclearSigned = signedUnclearly(line.text) && (!signatures || signatures.has(line.text));\n if (signedApart || signedForSure(line.text) || unclearSigned) return [];\n const by = said.find((q) => quotes(line.text, q.quote));\n if (!by || namesAuthor(line.text, by)) return [];\n const name = by.author ? `\"— ${by.author}\"` : '\"— <their first name and initial>\"';\n return [\n `\"${line.text}\" sets a customer's words with no name on them: add ${name} to the line (or a line of its own with role \"attribution\"); the review blocks a quote nobody signed.`,\n ];\n });\n}\n\n/** At or above this, the decision model reads a line's unclear dash as signing the quote with a name. */\nexport const SIGNS_QUOTE = 0.5;\n\nconst SIGNATURE_QUESTION =\n \"Does `line`, a customer's quote, carry the name of the person who said it after (or before) its dash, rather than the advertiser's own words such as a call to action or an offer, in whatever language it is written?\";\n\n/** For each line, the probability its dash signs the quote with a name; null when no judgment came back. */\nexport type SignatureJudge = (lines: string[]) => Promise<number[] | null>;\n\n/** The decision model as the judge, its spend reported to `onSpend`: one Noul per line, one request. */\nexport function jevSignatureJudge(onSpend?: (usage: ReviewUsage) => void): SignatureJudge {\n return (lines) =>\n askJev(\n lines.map((line) => ({ instructions: { line, question: SIGNATURE_QUESTION } })),\n onSpend,\n );\n}\n\n/**\n * The copy lines quoting a customer (`said`) whose unclear dash (`maybeSigned`) the decision model\n * reads as their name, for `unattributedQuotes`: one request for every such line, none when there is\n * none. Undefined when no judgment came back: an unclear dash then counts as a name.\n */\nexport async function readSignatures(\n spec: AdSpec,\n said: ReadonlyArray<{ quote: string; author?: string }>,\n judge: SignatureJudge = jevSignatureJudge(),\n): Promise<ReadonlySet<string> | undefined> {\n const asked = [\n ...new Set(\n spec.copy\n .map((line) => line.text)\n .filter((text) => signedUnclearly(text) && said.some((q) => quotes(text, q.quote) && !namesAuthor(text, q))),\n ),\n ];\n if (asked.length === 0) return new Set();\n const judged = await judge(asked).catch(() => null);\n if (judged?.length !== asked.length) return undefined;\n return new Set(asked.filter((_, k) => (judged[k] ?? 0) >= SIGNS_QUOTE));\n}\n\n/**\n * A review platform the copy names with no badge of it wired: the platform's real logo must be on\n * the ad (D3, Sept 2026: \"Reseña verificada en Trustpilot\" over generic stars). Whether the rating\n * or count it states is one the records hold is the claim gate's (`claim-check.ts`). `cited` is\n * the copy read for citations (`citedPlatforms`); without it, what each line shows alone. Pure.\n */\nexport function badgeProblems(spec: AdSpec, cited?: Citations): string[] {\n const problems: string[] = [];\n const named = new Set<string>();\n for (const line of spec.copy) {\n const platform = citedBy(line.text, cited);\n if (platform && !named.has(platform.name) && !badgeWired(spec, platform.name)) {\n named.add(platform.name);\n problems.push(\n `\"${line.text}\" names ${platform.name}, so ${platform.name}'s real badge must be on the ad: \\`baker images logo ${platform.domain}\\`, then in prompt.json a reference (\\`BADGE_1\\`, role prop, its \\`image\\` the logo's URL) and \\`third_party_brands: [{ \"name\": \"${platform.name}\", \"logo\": \"BADGE_1\", \"role\": \"proof\" }]\\`. Or drop the claim.`,\n );\n }\n }\n return problems;\n}\n\n/**\n * The spec with each review platform its copy cites wired as a proof badge: the platform's real\n * logo (`fetchLogo(domain)`, `baker images logo`) as a `BADGE_n` reference with its picture, and\n * the platform as a third-party brand whose logo that is. A platform already there, or whose\n * logo could not be fetched, is left as it is. `cited` as `badgeProblems` reads it.\n */\nexport async function addProofBadges(\n spec: AdSpec,\n fetchLogo: (domain: string) => Promise<string | null>,\n cited?: Citations,\n): Promise<AdSpec> {\n const references: AdReference[] = [...spec.references];\n const brands: AdThirdPartyBrand[] = [...spec.third_party_brands];\n let changed = false;\n const seen = new Set<string>();\n for (const line of spec.copy) {\n const platform = citedBy(line.text, cited);\n if (\n !platform ||\n seen.has(platform.name) ||\n badgeWired({ ...spec, references, third_party_brands: brands }, platform.name)\n )\n continue;\n seen.add(platform.name);\n const url = await fetchLogo(platform.domain).catch(() => null);\n if (!url) continue;\n let n = 1;\n while (references.some((r) => r.id === `BADGE_${n}`)) n++;\n const id = `BADGE_${n}`;\n references.push({ id, role: \"prop\", what: `the ${platform.name} logo`, image: url });\n const rest = brands.filter((b) => b.name.toLowerCase() !== platform.name.toLowerCase());\n brands.splice(0, brands.length, ...rest, {\n name: platform.name,\n what: \"the source of the reviews\",\n logo: id,\n role: \"proof\",\n });\n changed = true;\n }\n return changed ? { ...spec, references, third_party_brands: brands } : spec;\n}\n","import { supportedAspectRatios } from \"@baker/canvas-contract\";\n\n// Output ratios the scaffold can composite to (everything canvasDims knows).\nconst OUTPUT_ASPECTS = [\"1:1\", \"16:9\", \"9:16\", \"4:3\", \"3:4\", \"21:9\", \"4:5\", \"2:3\", \"3:2\"] as const;\n\n/** Parse \"W:H\" into a numeric ratio, or undefined when it isn't one. */\nexport function parseRatio(ar: string | undefined): number | undefined {\n const m = ar?.trim().match(/^(\\d+(?:\\.\\d+)?)[:x/](\\d+(?:\\.\\d+)?)$/);\n if (!m) return undefined;\n const w = Number(m[1]);\n const h = Number(m[2]);\n return w > 0 && h > 0 ? w / h : undefined;\n}\n\n/** The entry of `candidates` whose numeric ratio is closest to `ratio`. */\nfunction nearestAspect(ratio: number, candidates: readonly string[]): string {\n let best = candidates[0] as string;\n let bestDelta = Number.POSITIVE_INFINITY;\n for (const c of candidates) {\n const r = parseRatio(c);\n if (r === undefined) continue;\n const delta = Math.abs(ratio - r);\n if (delta < bestDelta) {\n best = c;\n bestDelta = delta;\n }\n }\n return best;\n}\n\n/**\n * Resolve the canvas's TWO aspect ratios from the deconstructed source (and an optional\n * explicit override, which wins and must be a known output ratio):\n * - `outAr` — the ad's true output ratio: drives every ffmpeg plate/still/composite dim\n * and the overlay composition size.\n * - `genAr` — the ratio clips + conditioning keyframes are GENERATED at: `outAr` when the\n * video model supports it, else the nearest supported ratio (e.g. 4:5 → 3:4; Seedance\n * has no 4:5). When they differ (`remapped`), every clip is normalized (center-cropped)\n * to `outAr` before it enters the spine — the ~6% crop is warned, never silent.\n * A source ratio like \"720:900\" snaps to the nearest known output ratio; an absent or\n * unparseable source falls back to 9:16. Pure.\n */\nexport function resolveAspect(\n sourceAr: string | undefined,\n override: string | undefined,\n genAspects: readonly string[],\n): { outAr: string; genAr: string; remapped: boolean } {\n let outAr: string;\n if (override !== undefined) {\n if (!OUTPUT_ASPECTS.includes(override as (typeof OUTPUT_ASPECTS)[number])) {\n throw new Error(`unsupported --aspect \"${override}\" — supported aspect ratios: ${OUTPUT_ASPECTS.join(\", \")}`);\n }\n outAr = override;\n } else {\n const ratio = parseRatio(sourceAr);\n outAr = ratio === undefined ? \"9:16\" : nearestAspect(ratio, OUTPUT_ASPECTS);\n }\n // `outAr` is always a known output ratio here, so it parses.\n const genAr = genAspects.includes(outAr) ? outAr : nearestAspect(parseRatio(outAr) ?? Number.NaN, genAspects);\n return { outAr, genAr, remapped: genAr !== outAr };\n}\n\n/** Canonical output pixel dims for a shared aspect ratio — social-grade, even numbers. */\nexport function canvasDims(ar: string | undefined): { w: number; h: number } {\n switch (ar) {\n case \"1:1\":\n return { w: 1080, h: 1080 };\n case \"16:9\":\n return { w: 1920, h: 1080 };\n case \"4:3\":\n return { w: 1440, h: 1080 };\n case \"3:4\":\n return { w: 1080, h: 1440 };\n case \"21:9\":\n return { w: 1920, h: 822 };\n case \"4:5\":\n return { w: 1080, h: 1350 };\n case \"2:3\":\n return { w: 1080, h: 1620 };\n case \"3:2\":\n return { w: 1620, h: 1080 };\n default:\n // 9:16 vertical — the social default and what most UGC ads ship.\n return { w: 1080, h: 1920 };\n }\n}\n\n/**\n * The aspect ratios clips are generated at on this video model: its registry\n * `aspect_ratio` enum, narrowed to the ratios the scaffold can composite (so 9:21, which\n * the keyframe image models cannot render, is never picked). Read from the registry\n * rather than matched by family: the default model (Gemini Omni) takes only 16:9 and\n * 9:16, and a family regex that fell through to Seedance's set wrote a 1:1 clip it rejects.\n * A model with no ratio enum generates at the output ratio itself.\n */\nexport function genAspectsFor(videoModel: string): readonly string[] {\n const accepted = supportedAspectRatios(\"video_generate\", videoModel);\n if (!accepted?.length) return OUTPUT_ASPECTS;\n const composable = accepted.filter((ar) => (OUTPUT_ASPECTS as readonly string[]).includes(ar));\n return composable.length > 0 ? composable : accepted;\n}\n","import {\n AD_IMAGE_MODEL,\n candidPersonPortraitPrompt,\n nearestSupportedAspectRatio,\n type VideoBlueprint,\n type VideoScene,\n} from \"@baker/canvas-contract\";\nimport { z } from \"zod\";\nimport { elementMentionKeywords } from \"../../engine/validator.ts\";\nimport type { NodeDecl } from \"../../schema/canvas.ts\";\nimport { avatarsLeftUncast, type CastAvatar, castAvatarsInOrder, recastPersonEntry } from \"../castAvatar.ts\";\nimport { ACTOR_SHEET_MODEL, assignElementLabels, elementTodo, referenceRole } from \"../lib/elements.ts\";\nimport { imageRenderParams } from \"../lib/image-params.ts\";\nimport { type Edge, ids, ref } from \"./ids.ts\";\nimport { compositeRegionsOf } from \"./routing.ts\";\n\nconst EDGES: Edge[] = [\"start\", \"end\"];\n// A video's recurring cast can change clothes (`same_as` looks), and its slots build a\n// sheet from any picture not marked as one already.\nconst VIDEO_CASTING = { looks: true, markSheet: true };\n\n// --- A recurring identity element chosen by the selection pass. ---\n// `appears_in`/`scenes` say which scene(s) — and optionally which edge — it is\n// visually present in; that drives which frames reference its shared source image.\nconst AppearsItem = z.union([z.number(), z.object({ scene: z.number(), edge: z.string().optional() }).loose()]);\nconst RecurringElement = z\n .object({\n // person | animal | product | logo | badge | other\n type: z.string(),\n label: z.string().optional(),\n description: z.string().optional(),\n expression: z.string().nullable().optional(),\n // When the element maps to a global cast entry, its stable id (for annotation).\n cast_id: z.string().nullable().optional(),\n // The label of another element that is the SAME individual as this one, shown\n // in a DIFFERENT wardrobe/persona/state (e.g. one creator playing skeptic in a\n // pink shirt and believer in a white shirt). Each look gets its own reference\n // slot, but the face/identity must stay identical across them.\n same_as: z.string().nullable().optional(),\n /**\n * A picture of this element that already exists — a cast Avatar's identity sheet,\n * a product photo, a real location shot. Given, the slot ingests it; absent, the\n * slot emits a TODO for somebody to drop one by hand.\n */\n source_image: z.string().optional(),\n /**\n * The supplied picture is ALREADY a multi-view reference sheet, so no sheet is\n * built from it.\n *\n * A cast Avatar's identity sheet is exactly that: a rendered turnaround of one\n * person, which is what `buildElementSheets` exists to produce. Fanning it into a\n * second sheet paid for an image generation to make a generation of a generation,\n * and every frame then grounded on the copy rather than on the avatar's own\n * identity — which is the drift the sheet is supposed to prevent.\n */\n source_is_sheet: z.boolean().optional(),\n // Scenes the element appears in. Either a bare list of scene indices (both\n // edges) or per-{scene,edge} entries. Both forms are accepted and merged.\n scenes: z.array(z.number()).optional(),\n appears_in: z.array(AppearsItem).optional(),\n })\n .loose();\nexport type RecurringElementT = z.infer<typeof RecurringElement>;\nexport const RecurringElements = z.array(RecurringElement);\n\n/**\n * Cast company Avatars into the recurring person slots, in order: the first distinct\n * person gets the first avatar, and so on. A `same_as` look of a cast person grounds on\n * that person's sheet too — it is the same face in other clothes.\n *\n * The sheet is the slot's picture, marked as a sheet so none is built from it. A person\n * left without an avatar keeps its TODO: casting nobody is how a canvas renders a stranger.\n */\nexport function castAvatarsOnElements(elementsInput: unknown, avatars: readonly CastAvatar[]): RecurringElementT[] {\n return castAvatarsInOrder(RecurringElements.parse(elementsInput), avatars, VIDEO_CASTING);\n}\n\n/**\n * The handles `castAvatarsOnElements` had no distinct person for, in the order given.\n * The selection keeps only recurring elements, so a one-scene presenter — or a second\n * handle on a one-person ad — leaves an avatar uncast, and that must be said, not assumed.\n */\nexport function avatarsNotCast(elementsInput: unknown, handles: readonly string[]): string[] {\n return avatarsLeftUncast(RecurringElements.parse(elementsInput), handles, VIDEO_CASTING);\n}\n\n/** Normalize an element's scene/edge presence into scene index → set of edges it appears on. */\nexport function presenceOf(el: RecurringElementT): Map<number, Set<Edge>> {\n const map = new Map<number, Set<Edge>>();\n const add = (scene: number, edge: Edge | null) => {\n if (!Number.isInteger(scene) || scene < 0) return;\n let set = map.get(scene);\n if (!set) {\n set = new Set<Edge>();\n map.set(scene, set);\n }\n if (edge) set.add(edge);\n else for (const e of EDGES) set.add(e);\n };\n for (const s of el.scenes ?? []) add(s, null);\n for (const a of el.appears_in ?? []) {\n if (typeof a === \"number\") add(a, null);\n else if (a && typeof a === \"object\") {\n const edge = a.edge === \"start\" || a.edge === \"end\" ? a.edge : null;\n add(a.scene, edge);\n }\n }\n return map;\n}\n\n/**\n * Label a cast entry with its slot, and rewrite it for the Avatar cast in the source actor's\n * place. Only the person's own slot rewrites it: a `same_as` look shares the entry, and its\n * description was written about the source actor, not the Avatar.\n */\nfunction stampCastEntry(entry: Record<string, unknown>, el: RecurringElementT, label: string): void {\n entry.reference_image = label;\n if (el.source_is_sheet && !el.same_as && el.type.toLowerCase() === \"person\" && el.description) {\n recastPersonEntry(entry, el.description);\n }\n}\n\n/**\n * Document the recurring elements in the baked prompt.json: add a top-level\n * `reference_elements` summary (label/type/description/scenes), and stamp\n * `reference_image: LABEL` onto the matching `global.cast[*]` entry by id — so\n * the human editing the JSON sees which wired slot grounds which persona. Clones\n * the input (never mutates the caller's object).\n */\nexport function annotateBlueprintWithElements(blueprintInput: unknown, elementsInput: unknown): unknown {\n if (!blueprintInput || typeof blueprintInput !== \"object\") return blueprintInput;\n const elements = RecurringElements.parse(elementsInput);\n const clone = JSON.parse(JSON.stringify(blueprintInput)) as Record<string, unknown>;\n const cast = ((clone.global as Record<string, unknown>)?.cast ?? null) as Array<Record<string, unknown>> | null;\n const summary: Array<Record<string, unknown>> = [];\n for (const { el, label } of assignElementLabels(elements, \"video\")) {\n const scenes = [...presenceOf(el).keys()].sort((a, b) => a - b);\n summary.push({ reference_image: label, type: el.type, description: el.description ?? null, scenes });\n const entry = el.cast_id && Array.isArray(cast) ? cast.find((c) => c?.id === el.cast_id) : undefined;\n if (entry && typeof entry === \"object\") stampCastEntry(entry, el, label);\n }\n clone.reference_elements = summary;\n return clone;\n}\n\n/**\n * What the generator should do with one reference slot. A `same_as` slot is the\n * SAME individual as another slot in a different wardrobe/persona — the face must\n * stay identical, only the outfit/state changes; everything else falls back to\n * the per-type role.\n */\nexport function roleForSlot(slot: ElementSlot): string {\n if (slot.sameAs) {\n const what = slot.description ? ` (${slot.description})` : \"\";\n return `the SAME individual as ${slot.sameAs}, shown in a DIFFERENT wardrobe/persona/state${what} — keep the FACE and identity IDENTICAL to the ${slot.sameAs} references; change ONLY wardrobe, styling, and expression. Ignore any caption text printed on this reference.`;\n }\n return referenceRole(slot.type, \"video\");\n}\n\nexport type ElementSlot = {\n id: string;\n ref: string;\n label: string;\n type: string;\n description?: string;\n // The label of another slot this is the same individual as (different wardrobe).\n sameAs?: string;\n // The cast id this element portrays (when the deconstruct linked it), so a speaker\n // can be matched to the element that shows them — i.e. is the presenter ON SCREEN\n // in this scene, or is it b-roll while they narrate?\n castId?: string;\n presence: Map<number, Set<Edge>>;\n // True once buildElementSheets has fused this slot's lone ingest into a multi-view\n // turnaround (`image_reference_sheet`) and repointed `ref` at the sheet, or the slot was\n // handed one (an Avatar's). Even a sheet does not stop a source frame's face leaking, so\n // a frame with people never takes the source frame (see buildFrameRef).\n sheetBacked?: boolean;\n /** The supplied picture is already a turnaround, so no sheet is built from it. */\n sourceIsSheet?: boolean;\n};\n\n/** Compute one shared ingest slot per recurring element (id, label, presence map). */\nexport function buildElementSlots(elements: RecurringElementT[]): ElementSlot[] {\n const usedIds = new Set<string>([\n ids.prompt,\n ids.spine,\n ids.overlaid,\n ids.captions,\n ids.captionsVoiceMix,\n ids.captionsTranscribe,\n ids.audioMix,\n ids.final,\n ids.musicBed,\n ]);\n const slots: ElementSlot[] = [];\n assignElementLabels(elements, \"video\").forEach(({ el, label }, i) => {\n let id = ids.element(label, i);\n while (usedIds.has(id)) id = `${id}_${i}`;\n usedIds.add(id);\n slots.push({\n id,\n ref: ref(id, \"asset\"),\n label,\n type: el.type,\n description: el.description,\n sameAs: el.same_as ?? undefined,\n castId: el.cast_id ?? undefined,\n sourceIsSheet: el.source_is_sheet === true,\n presence: presenceOf(el),\n });\n });\n return slots;\n}\n\n/** The element slots whose presence includes this scene/edge. */\nexport function slotsForFrame(slots: ElementSlot[], sceneIndex: number, edge: Edge): ElementSlot[] {\n return slots.filter((s) => s.presence.get(sceneIndex)?.has(edge));\n}\n\n// Identity-critical graphic types whose prompt mention MUST wire the reference — a\n// described-but-unwired mark renders wrong-identity (the audit's ~6\n// VIDEO_REFERENCE_MISSING logo warnings). Persons/animals are sheet-backed via cast\n// presence, and a keyword match on them would over-wire.\nconst MENTION_WIRED_TYPES = new Set([\"logo\", \"badge\"]);\n\nfunction promptMentionsSlot(prompt: string, slot: ElementSlot): boolean {\n // The SAME matcher the validator's reference-completeness check uses, so any frame\n // it would warn about is wired by construction.\n return elementMentionKeywords(slot).some((w) =>\n new RegExp(`\\\\b${w.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")}\\\\b`, \"i\").test(prompt),\n );\n}\n\n/** The scene's frame text for one edge (its own frame prompt + all region prompts). */\nfunction edgePromptText(scene: VideoScene, edge: Edge): string {\n const regionPrompts = (compositeRegionsOf(scene) ?? [])\n .map((r) => r.frame_prompt ?? \"\")\n .filter(Boolean)\n .join(\"\\n\");\n const own = (edge === \"start\" ? scene.start_frame_prompt : scene.end_frame_prompt) ?? \"\";\n return [own, regionPrompts].join(\"\\n\").trim();\n}\n\n/**\n * Extend slot presence to every scene whose frame prompts NAME the element. The\n * element-selection pass lists the scenes it noticed an element in; a frame prompt\n * can still describe it elsewhere (the deconstruct saw the logo in more scenes than\n * the selector listed), and a described-but-unwired element renders wrong-identity.\n * The prompt mention is the source of truth for wiring.\n */\nexport function extendPresenceByPromptMentions(slots: ElementSlot[], blueprint: VideoBlueprint): void {\n const extendable = slots.filter((s) => MENTION_WIRED_TYPES.has(s.type.toLowerCase()));\n if (extendable.length === 0) return;\n blueprint.scenes.forEach((scene, i) => {\n for (const edge of EDGES) {\n const text = edgePromptText(scene, edge);\n if (!text) continue;\n for (const slot of extendable) {\n if (!promptMentionsSlot(text, slot)) continue;\n const set = slot.presence.get(i) ?? new Set<Edge>();\n set.add(edge);\n slot.presence.set(i, set);\n }\n }\n });\n}\n\n// Element types that get a multi-view reference sheet, mapped to the\n// `image_reference_sheet` subject_type its schema accepts. A `location`/set is sheeted\n// too — as several CAMERA ANGLES of the same room, so a multi-scene shoot keeps one\n// consistent set (the clinic/exam-room reproduced from every angle, not a lone snapshot).\nconst SHEET_SUBJECT_TYPE: Record<string, \"person\" | \"character\" | \"product\" | \"location\"> = {\n person: \"person\",\n animal: \"character\",\n product: \"product\",\n location: \"location\",\n};\n\n/**\n * \"Build the element once, reuse everywhere.\" For each grounded base element — a\n * person, animal, product, OR location/set — fuse its dropped reference into ONE\n * multi-view sheet (`image_reference_sheet`) and repoint the slot so every frame grounds\n * on that SHEET instead of the lone ingest. The sheet is the strongest cross-scene\n * consistency lock the pipeline has: without it the same face/pet/pack/room drifts\n * clip-to-clip (a different look per scene), and a single flat photo gives the\n * generator only one angle to work from — exactly the \"we lose the essence of the\n * base asset / the angles look wrong\" failure. So we generate the multi-angle canvas\n * for EVERY recurring base element (a person/pet as a turnaround, a set as several\n * camera angles of the same room), even for a one-scene hero element (one strong\n * reference still beats a lone snapshot). Mutates `slot.ref` and sets `slot.sheetBacked`.\n * Sheets one subject per call — never a person plus their props — so each sheet stays\n * focused and clean.\n */\nexport function buildElementSheets(slots: ElementSlot[], nodes: NodeDecl[], sheetModel?: string): void {\n for (const slot of slots) {\n // Already a turnaround — an Avatar's identity sheet. Ground on it directly rather\n // than paying to render a copy of it.\n if (slot.sourceIsSheet) {\n slot.sheetBacked = true;\n continue;\n }\n const subjectType = SHEET_SUBJECT_TYPE[slot.type.toLowerCase()];\n if (!subjectType) continue;\n // A same_as slot reuses the linked slot's identity (a second wardrobe of the same\n // person); it grounds on that slot's reference, so it needs no sheet of its own.\n if (slot.sameAs) continue;\n if (slot.presence.size < 1) continue;\n const sheetId = ids.sheet(slot.id);\n const slotType = slot.type.toLowerCase();\n const isCast = slotType === \"person\" || slotType === \"animal\";\n nodes.push({\n id: sheetId,\n type: \"image_reference_sheet\",\n // The lone dropped ingest is the source; the sheet fans it into a turnaround.\n inputs: { references: [slot.ref] },\n params: {\n model: sheetModel ?? ACTOR_SHEET_MODEL,\n // The clean-plate clause mirrors the frame prompts' CLEAN PLATE block: a sheet\n // that comes back with a fake camera app baked in (P2-22) poisons EVERY frame\n // grounded on it, so the suppression must live on the sheet too.\n subject_description: `${slot.description ?? `the ${slot.type}`} — clean plate: no phone-camera UI chrome, no app interface, no watermarks, no captions or on-image text`,\n subject_type: subjectType,\n // 4K: the sheet packs up to 8 cells (angles + tight face/detail close-ups), and\n // it's the ONE reference every frame grounds on — per-cell sharpness here\n // propagates to every clip, so it's worth the highest tier on this single asset.\n image_size: \"4K\",\n // The sheet is the look that propagates to EVERY grounded frame, so a glossy\n // studio turnaround makes the whole UGC ad read as \"produced\" (the #1 AI tell).\n // Force a flat, real, front-camera look on the cast sheet so the actor stays\n // authentic, not an airbrushed influencer (CCA-02).\n ...(isCast\n ? {\n style:\n \"authentic UGC look: flat, even, natural front-camera lighting — no studio key/rim light, no seamless backdrop, no shallow depth of field; real skin texture and pores, no airbrushing or beauty retouch; true-to-life everyday styling\",\n }\n : {}),\n },\n });\n slot.ref = ref(sheetId, \"sheet\");\n slot.sheetBacked = true;\n }\n}\n\n/**\n * One shared ingest per recurring identity element, wired into every frame it appears in\n * (`slots[i]` is `elements[i]`). An element that already HAS its picture does not get a\n * hole to fill: this is the seam an Avatar arrives through — a cast avatar is exactly the\n * one real source image the slot was asking someone to drop by hand, and its identity\n * sheet is a URL, ingested as one.\n *\n * A person nobody cast is invented, not asked for: a candid portrait generated from their\n * description, which the sheet then fans into a turnaround, so every frame of this ad shows\n * one realistic person. An Avatar is for an actor who must come back across ads; demanding\n * one for everybody on screen made every video with a person wait on a casting session.\n */\nexport function emitElementIngests(slots: ElementSlot[], elements: RecurringElementT[], nodes: NodeDecl[]): void {\n slots.forEach((slot, i) => {\n const element = elements[i];\n if (!element) return;\n const supplied = element.source_image?.trim() ?? \"\";\n if (isInventedPerson(element)) {\n const description = element.description ?? `the ${slot.label.toLowerCase()} in this ad`;\n // A second look of an invented person is drawn from the first look's face, so it is\n // the same person in other clothes — no avatar exists that could match that face.\n const firstLook = element.same_as ? slots[elements.findIndex((e) => e.label === element.same_as)] : undefined;\n nodes.push(inventedPersonNode(slot.id, description, firstLook ? ref(firstLook.id, \"images#0\") : undefined));\n slot.ref = ref(slot.id, \"images#0\");\n return;\n }\n nodes.push({\n id: slot.id,\n type: \"ingest\",\n params: /^https?:\\/\\//i.test(supplied)\n ? { source: \"url\", url: supplied, expect: \"image\" }\n : { source: \"path\", path: supplied || elementTodo(element, slot.label, \"video\"), expect: \"image\" },\n });\n });\n}\n\n/** Tags the portrait of a person nobody cast: a face to fuse into a sheet, never a scene frame. */\nexport const INVENTED_PERSON_ROLE = \"invented_person\";\n\n/** A person nobody cast: no picture supplied, so the scaffold invents them from their description. */\nexport function isInventedPerson(el: Pick<RecurringElementT, \"type\" | \"source_image\">): boolean {\n return el.type.toLowerCase() === \"person\" && !el.source_image?.trim();\n}\n\n/**\n * The invented person's face, rendered on the model avatars are cast on. `firstLook` is the\n * portrait of the same person in their other outfit, when this is a second look of them.\n */\nfunction inventedPersonNode(id: string, description: string, firstLook?: string): NodeDecl {\n const portrait = candidPersonPortraitPrompt({ subject: description });\n return {\n id,\n type: \"image_generate\",\n tags: { role: INVENTED_PERSON_ROLE },\n ...(firstLook ? { inputs: { reference: [firstLook] } } : {}),\n params: {\n model: AD_IMAGE_MODEL,\n ...imageRenderParams(AD_IMAGE_MODEL, { size: \"2K\", quality: \"high\" }),\n prompt: firstLook\n ? `The same person as in the attached photo, in another look. Keep their face, hair, skin and build identical to the attached photo; change only the clothes and styling.\\n${portrait}`\n : portrait,\n aspect_ratio: nearestSupportedAspectRatio(\"image_generate\", AD_IMAGE_MODEL, \"3:4\"),\n },\n };\n}\n\n/** The element slots present anywhere in this scene (either edge) — for the motion brief. */\nexport function slotsForScene(slots: ElementSlot[], sceneIndex: number): ElementSlot[] {\n return slots.filter((s) => s.presence.has(sceneIndex));\n}\n\n// Reference ORDER matters for gpt-image: only the first reference gets \"extra richness\"\n// in texture, so the most identity-critical asset (the presenter, then the hero product,\n// then the logo) must lead. Lower rank = earlier. Stable within a rank.\nconst REFERENCE_RANK: Record<string, number> = { person: 0, animal: 0, product: 1, logo: 2, badge: 3, location: 4 };\nfunction referenceRank(type: string): number {\n return REFERENCE_RANK[type.toLowerCase()] ?? 5;\n}\n/** Order a scene's slots identity-critical first (presenter → product → logo → …). */\nexport function orderSlotsByIdentity(slots: ElementSlot[]): ElementSlot[] {\n return [...slots].sort((a, b) => referenceRank(a.type) - referenceRank(b.type));\n}\n","import type { NodeTags } from \"../../schema/canvas.ts\";\nimport { sanitizeId } from \"../lib/elements.ts\";\n\n/**\n * Every node id the video scaffold emits, built in one place.\n *\n * An id is an address, not a label: other nodes `$ref` it, the validator reads roles and\n * scenes off it on canvases written before nodes carried tags, an operator edits \"the\n * s3_start frame\" by name, and the content-addressed cache keys a billed node by what it\n * references. Two call sites spelling the same id by hand is how one of them drifts.\n *\n * A composited scene's region nodes carry a `_r<n>` suffix after the scene index (`s2_r1_clip`),\n * so a split-screen panel's frames never collide with the scene's or each other's.\n */\nfunction regionTag(region: number | undefined): string {\n return region === undefined ? \"\" : `_r${region}`;\n}\n\nexport type Edge = \"start\" | \"end\";\n\nexport const ids = {\n /** The baked blueprint, and the slim projection of it every frame reads. */\n prompt: \"prompt\",\n promptStyle: \"prompt_style\",\n spine: \"spine\",\n overlaid: \"overlaid\",\n captions: \"captions\",\n captionsVoiceMix: \"captions_voice_mix\",\n captionsTranscribe: \"captions_transcribe\",\n captionsTranscript: \"captions_transcript\",\n audioMix: \"audio_mix\",\n final: \"final\",\n musicBed: \"music_bed\",\n /** A scene's generated keyframe for one edge. */\n frame: (scene: number, edge: Edge, region?: number): string => `s${scene}${regionTag(region)}_${edge}`,\n /** The ingest of a scene's real source frame for one edge. */\n sourceFrame: (scene: number, edge: Edge, region?: number): string => `s${scene}${regionTag(region)}_${edge}_ref`,\n clip: (scene: number, region?: number): string => `s${scene}${regionTag(region)}_clip`,\n clipTrim: (scene: number, region?: number): string => `s${scene}${regionTag(region)}_clip_trim`,\n voiceExtract: (scene: number): string => `s${scene}_voextract`,\n ambient: (scene: number): string => `s${scene}_ambient`,\n key: (scene: number): string => `s${scene}_key`,\n composite: (scene: number): string => `s${scene}_composite`,\n screenRef: (scene: number): string => `s${scene}_screen_ref`,\n graphicRef: (scene: number): string => `s${scene}_graphic_ref`,\n sfx: (scene: number, k: number): string => `s${scene}_sfx${k}`,\n /** One recurring element's ingest slot, deduped by the caller. */\n element: (label: string, index: number): string => sanitizeId(`el_${label}`, `el_${index}`),\n sheet: (slotId: string): string => `${slotId}_sheet`,\n /** One speaker's casting, deduped by the caller. */\n voice: (speaker: string, ordinal: number): string => sanitizeId(`voice_${speaker}`, `voice_${ordinal}`),\n /** One read of a phrase, deduped by the caller. */\n phraseRead: (phrase: number, speaker: string): string => sanitizeId(`vo_ph${phrase}_${speaker}`, `vo_ph${phrase}`),\n /** A speaker's on-camera extracts laid on one track, and that track re-voiced. */\n voiceTrack: (voice: string): string => `${voice}_track`,\n voiceConv: (voice: string): string => `${voice}_conv`,\n} as const;\n\n/** A `$ref` to one output of a node. */\nexport function ref(id: string, output: string): string {\n return `$ref:${id}.${output}`;\n}\n\n/** What a scene node is, stated on the node: its scene, its region, its job in the assembly. */\nexport function sceneTags(scene: number, role: string, region?: number): NodeTags {\n return { scene, ...(region === undefined ? {} : { region }), role };\n}\n","import { type CompositionRegion, VideoBlueprintSchema, type VideoScene } from \"@baker/canvas-contract\";\n\n// Layouts the scaffold reproduces by building one clip per region and compositing\n// them. `full_frame` (or anything else) stays the single-shot path.\nconst COMPOSITE_LAYOUTS = new Set([\"split_screen\", \"pip\", \"keyed_overlay\"]);\n\n// A region whose content is a SCREEN/UI surface — an app, website, chat, dashboard, or\n// phone mockup. These must NEVER be generated by the video model: Seedance hallucinates\n// garbled UI text and non-brand chrome, and stacking one leaves a visible seam. They are\n// composited as a REAL screenshot or a brand HTML hyperframe on the overlay layer instead.\n// Strong UI signals only — bare \"screen\"/\"phone\" are excluded so a keyed \"green screen\"\n// presenter or a hand holding a phone isn't misread as an interface to composite.\nexport const UI_SURFACE_RE =\n /\\b(?:app|ui|web ?site|web ?page|website|browser|chat|interface|mock-?up|in[- ]?app|dashboard|app screen|phone screen|screen[- ]?(?:recording|capture|grab|share))\\b/i;\n// The deconstruct's typed `kind` is authoritative when present: screen_capture and\n// static_graphic are real-surface regions (screenshot / HTML rebuild), camera and\n// generated are footage. The prose regex is only the fallback for older blueprints —\n// and it reads panel + summary ONLY: a region's frame_prompt routinely carries the\n// clean-plate clause (\"no text or UI overlays\"), whose \"UI\" token made the PRESENTER\n// region classify as a UI surface (audit defect A4: the phone stub was labeled with\n// the presenter's description).\nexport function regionIsUiSurface(r: CompositionRegion): boolean {\n const kind = (r.kind ?? \"\").trim().toLowerCase();\n if (kind === \"screen_capture\" || kind === \"static_graphic\") return true;\n if (kind === \"camera\") return false;\n // `generated` is honored only when the prose agrees: the deconstruct flip-flops kinds\n // scene-to-scene (the same Excel panel typed static_graphic in one scene, generated in\n // the next), and trusting a mistyped `generated` re-opened the Seedance-paints-UI hole\n // the kinds exist to close. UI-flavored prose wins; a genuine b-roll region stays.\n return UI_SURFACE_RE.test(`${r.panel ?? \"\"} ${r.summary ?? \"\"}`);\n}\n/** True when every NON-presenter panel is a UI surface (≤1 real non-UI region remains). */\nexport function isUiOnlyComposite(regions: CompositionRegion[]): boolean {\n const ui = regions.filter(regionIsUiSurface).length;\n return ui >= 1 && regions.length - ui <= 1;\n}\n\n/** The composite regions of a scene, or null when it isn't a ≥2-region composite. */\nexport function compositeRegionsOf(scene: VideoScene): CompositionRegion[] | null {\n const comp = scene.composition;\n const layout = (comp?.layout ?? \"\").toLowerCase();\n if (!COMPOSITE_LAYOUTS.has(layout)) return null;\n const regions = (comp?.regions ?? []).filter((r): r is CompositionRegion => Boolean(r) && typeof r === \"object\");\n return regions.length >= 2 ? regions : null;\n}\n\n/**\n * The background-plate region of a UI-routed composite — the presenter/camera panel\n * the single-shot fallback actually renders (the UI panel lives on the overlay layer).\n */\nexport function compositePlateRegion(scene: VideoScene): CompositionRegion | null {\n const regions = compositeRegionsOf(scene);\n if (!regions) return null;\n return regions.find((r) => r.is_presenter) ?? regions.find((r) => !regionIsUiSurface(r)) ?? null;\n}\n\n/**\n * Scene indexes whose composite routes to the OVERLAY layer (real screen/graphic\n * surface, plain background clip) — decided PER PERSISTENT LAYOUT, not per scene.\n * Within a consecutive run of scenes sharing one composition signature (layout + axis\n * + panels), if ANY scene's regions classify UI-only the whole run routes UI-only:\n * the run is one unbroken physical layout, and Gemini merely described the same band\n * with different words scene to scene (\"screen recording\" vs \"landing page\" — the\n * audit's Superchat flip-flop, which AI-generated the document band on half the\n * scenes and stubbed it real on the others).\n */\nexport function uiRoutedSceneSet(input: unknown): Set<number> {\n return new Set(uiRoutedRuns(input).flat());\n}\n\n/**\n * The UI-routed scenes GROUPED into their persistent-layout runs (consecutive scenes\n * sharing one composition signature). Each run is ONE physical surface window — the\n * overlay layer seeds one grouped stub per run (one continuous screen recording with\n * a state timeline), never one stub per scene.\n */\nexport function uiRoutedRuns(input: unknown): number[][] {\n const blueprint = VideoBlueprintSchema.parse(input);\n const info = blueprint.scenes.map((scene) => {\n const regions = compositeRegionsOf(scene);\n if (!regions) return null;\n const comp = scene.composition;\n const panels = regions\n .map((r) => (r.panel ?? \"\").toLowerCase())\n .sort()\n .join(\",\");\n // A verified surface_id DOMINATES the signature: the deconstruct's continuity\n // pass assigns one id per real on-screen surface, so two scenes sharing it are\n // the same surface whatever the per-scene layout label says (Pass-2 flaps\n // pip ↔ keyed_overlay on the same phone insert). Conversely a different id\n // splits the run even under one unchanged layout — a source that splices two\n // distinct screen recordings needs two stubs, one screenshot can't cover both.\n const surfaceIds = regions\n .filter(regionIsUiSurface)\n .map((r) => (r.surface_id ?? \"\").trim())\n .filter(Boolean)\n .sort()\n .join(\",\");\n const sig = surfaceIds\n ? `sid:${surfaceIds}`\n : `${(comp?.layout ?? \"\").toLowerCase()}|${(comp?.split_axis ?? \"\").toLowerCase()}|${panels}`;\n return { sig, ui: isUiOnlyComposite(regions) };\n });\n const runs: number[][] = [];\n let run: number[] = [];\n const flushRun = () => {\n if (run.some((i) => info[i]?.ui)) runs.push(run);\n run = [];\n };\n info.forEach((inf, i) => {\n if (!inf) {\n flushRun();\n return;\n }\n const prev = i > 0 ? info[i - 1] : null;\n if (!prev || prev.sig !== inf.sig) flushRun();\n run.push(i);\n });\n flushRun();\n return runs;\n}\n","import {\n type BlueprintFloatingElement,\n BlueprintFloatingElementSchema,\n type BlueprintOverlay,\n BlueprintOverlaySchema,\n type CompositionRegion,\n type VideoBlueprint,\n VideoBlueprintSchema,\n type VideoScene,\n} from \"@baker/canvas-contract\";\nimport { z } from \"zod\";\nimport { escapeHtml } from \"../lib/html.ts\";\nimport { compositeRegionsOf, regionIsUiSurface, UI_SURFACE_RE, uiRoutedRuns } from \"./routing.ts\";\nimport { SEEDANCE_CEILING_S, type SpineClock, sceneCeilingS, spineClockFor } from \"./timing.ts\";\n\n// --- Overlay HTML generation: a faithful, EDITABLE draft, not a prop renderer. ---\n\n// `--` cannot appear inside an HTML comment (it would close `-->` early and leak\n// the rest as visible text). Collapse any run of dashes so blueprint-supplied\n// strings stay safely inside the comments we emit for floating-element stubs.\nexport function commentSafe(s: string): string {\n return escapeHtml(s).replace(/-{2,}/g, \"–\");\n}\n\n// The composition runtime only understands these canned entrances; every other\n// value (or none) renders as a plain fade. Normalize known synonyms so a\n// reference \"slide\" doesn't silently degrade, and drop anything unsupported\n// instead of emitting a dead `data-anim` the runtime ignores.\nconst SUPPORTED_ANIMS = new Set([\"fade\", \"slide_up\", \"slide_down\", \"pop\"]);\nfunction normalizeAnim(animation: string | undefined): string | undefined {\n if (!animation || animation === \"none\") return undefined;\n const mapped = animation === \"slide\" ? \"slide_up\" : animation;\n return SUPPORTED_ANIMS.has(mapped) ? mapped : undefined;\n}\n\n// Dead-center placements sit ON the talking-head's face. We push them to the bottom\n// band so a seeded overlay never covers the subject (the chips-over-the-cat defect).\nconst FACE_ZONE_POSITIONS = new Set([\n \"center\",\n \"centre\",\n \"mid-center\",\n \"mid-centre\",\n \"middle-center\",\n \"center-center\",\n \"mid\",\n \"middle\",\n]);\n\n/** A 9-grid position string (\"bottom_center\") → a CSS helper class (\"pos-bottom-center\"). */\nfunction positionClass(position: string | undefined): string {\n const p = (position ?? \"bottom_center\").toLowerCase().replace(/[^a-z]+/g, \"-\");\n // The vertical center band is the subject's face — never seed an overlay there.\n const safe = FACE_ZONE_POSITIONS.has(p) ? \"bottom-center\" : p;\n return `pos-${safe}`;\n}\n\ntype CaptionEntry = { text: string; at: number; end: number; ov: BlueprintOverlay };\n\n/**\n * Collect every text overlay across scenes at its ABSOLUTE time and merge a caption the\n * deconstruct repeats in both scenes it spans (identical text, touching windows) into ONE\n * continuous element — otherwise the same words re-animate (flicker) at the cut. Pure.\n */\nfunction collectCaptions(blueprint: VideoBlueprint, clock: SpineClock): CaptionEntry[] {\n return blueprint.scenes\n .flatMap((scene, i) => {\n const sceneStart = scene.start_s ?? 0;\n const overlays = z.array(BlueprintOverlaySchema).safeParse(scene.overlays ?? []);\n return overlays.success\n ? overlays.data\n .filter((ov): ov is BlueprintOverlay & { text: string } => Boolean(ov.text?.trim()))\n .map((ov) => {\n // Spine-clock placement: the overlay rides the PICTURE, so its window is\n // where this scene's picture actually sits, not the reference timestamp.\n const at = clock.map(i, ov.appears_at_s ?? sceneStart);\n return { text: ov.text.trim(), at, end: at + (ov.duration_s ?? 2.5), ov };\n })\n : [];\n })\n .sort((a, b) => a.at - b.at);\n}\n\n// An IDENTICAL caption/graphic re-detected within this gap of its last showing is the\n// deconstruct seeing one continuous element across a cut (or re-detecting it a beat\n// later) — merged/skipped so the render doesn't flicker the same words twice. A\n// deliberate re-show lands well beyond this window.\nconst OVERLAY_REDETECT_GAP_S = 2;\n// A graphic the deconstruct timed under this is a detection artifact no viewer\n// perceives — seeding it just litters the overlay HTML with junk stubs.\nconst OVERLAY_MIN_DUR_S = 0.5;\n\nfunction mergeCaptions(blueprint: VideoBlueprint, clock: SpineClock): CaptionEntry[] {\n // Group by text first — a repeated caption's fragments are interleaved with OTHER\n // captions in time order, so a consecutive-only merge misses them. Within each text,\n // fold windows that touch or re-show within the re-detect gap into one; genuinely\n // far-apart re-shows (a CTA that flashes twice seconds apart) keep their own elements.\n const byText = new Map<string, CaptionEntry[]>();\n for (const e of collectCaptions(blueprint, clock)) {\n const arr = byText.get(e.text);\n if (arr) arr.push(e);\n else byText.set(e.text, [e]);\n }\n const merged: CaptionEntry[] = [];\n for (const arr of byText.values()) {\n let cur: CaptionEntry | null = null;\n for (const e of arr) {\n if (cur && e.at <= cur.end + OVERLAY_REDETECT_GAP_S) cur.end = Math.max(cur.end, e.end);\n else {\n cur = { ...e };\n merged.push(cur);\n }\n }\n }\n return merged.sort((a, b) => a.at - b.at);\n}\n\n/** One text overlay → a positioned, timed, editable element (empty when no text). */\nfunction overlayElement(ov: BlueprintOverlay, at: number, dur: number): string {\n if (!ov.text?.trim()) return \"\";\n const role = ov.role ? ` data-role=\"${escapeHtml(ov.role)}\"` : \"\";\n const normAnim = normalizeAnim(ov.animation);\n const anim = normAnim ? ` data-anim=\"${normAnim}\"` : \"\";\n // Carry the reference's animation note as an escaped attribute (not an HTML\n // comment) so a detail like \"slow --> pop\" can't close the comment early and\n // leak as visible text — and stays machine-readable for a future runtime.\n const detail = ov.animation_detail ? ` data-anim-detail=\"${escapeHtml(ov.animation_detail)}\"` : \"\";\n // `clip` satisfies the hyperframes pre-render gate (a timed element needs\n // class=\"clip\"); the seeded GSAP timeline still drives the entrance/exit, so the\n // two timing systems coexist (proven on the shipped Barkibu render).\n return `<div class=\"ov clip ${positionClass(ov.position)}\" data-start=\"${at}\" data-dur=\"${dur}\"${role}${anim}${detail}>${escapeHtml(ov.text.trim())}</div>`;\n}\n\n// A rich, card-like overlay (notification popup, tweet/X post, chat bubble, comment,\n// review/social-proof card, stat counter) is best reproduced as an ANIMATED Hyperframes\n// block, not a flat static image — it should slide/pop in on its beat. Matched on the\n// element's kind/description so the agent gets the right tool.\nconst RICH_OVERLAY_RE =\n /notif|tweet|\\bx post\\b|post\\b|comment|message|chat|bubble|card|review|rating|stat|counter|toast|popup/;\n\n/** The command that best sources a real asset for a floating element kind. */\nfunction sourceHint(fe: BlueprintFloatingElement): string {\n const desc = fe.brand_name || fe.what_it_represents || fe.description || fe.kind || \"element\";\n const haystack = `${fe.kind ?? \"\"} ${fe.description ?? \"\"} ${fe.what_it_represents ?? \"\"}`.toLowerCase();\n switch ((fe.kind ?? \"\").toLowerCase()) {\n case \"logo\":\n return \"baker images logo <domain> (or baker images library)\";\n case \"emoji\":\n case \"sticker\":\n return `baker images sticker \"${desc}\" (or baker images gif)`;\n case \"product_cutout\":\n return `baker images library \"${desc}\" (the client's own product)`;\n default:\n // A notification/tweet/comment/social-proof CARD animates in — use a real\n // Hyperframes block, not a flat icon: `npx hyperframes catalog --type block`\n // then `add` (e.g. social-proof-card, notification-toast) and nest it.\n if (RICH_OVERLAY_RE.test(haystack)) {\n return `npx hyperframes add <social-card/notification block> for \"${desc}\" (animated overlay, not a static icon — see references/hyperframes/catalog.md)`;\n }\n // arrows, UI chrome, progress bars, badges, generic graphics → flat icon.\n return `baker images icon \"${desc}\"`;\n }\n}\n\n/**\n * One presence window per floating element, in timeline order. Accumulated in two\n * passes: elements are keyed by what+where; a re-detection within the re-detect gap\n * of a window's end EXTENDS that window (the same persistent watermark seen scene\n * after scene), a re-show beyond the gap starts a genuinely separate window. Floating\n * ui_elements that ARE a UI-routed scene's surface are skipped (the grouped surface\n * stub owns them); sub-perceptual flashes are dropped.\n */\ntype FloatWindow = { fe: BlueprintFloatingElement; at: number; end: number };\n\n/** Identity key for cross-scene float dedup: what the element is + where it sits. */\nfunction floatKey(fe: BlueprintFloatingElement): string {\n return [\n (fe.kind ?? \"element\").toLowerCase(),\n (fe.brand_name || fe.what_it_represents || fe.description || \"\").toLowerCase().trim(),\n positionClass(fe.position),\n ].join(\"|\");\n}\n\n/** A floating ui_element that IS a UI-routed scene's surface (the grouped stub owns it). */\nfunction floatIsRoutedSurface(fe: BlueprintFloatingElement, sceneIsUiRouted: boolean): boolean {\n return sceneIsUiRouted && (fe.kind ?? \"\").toLowerCase() === \"ui_element\" && UI_SURFACE_RE.test(fe.description ?? \"\");\n}\n\n/** Extend the element's latest window when this detection continues it, else open a new one. */\nfunction addFloatDetection(\n windows: Map<string, FloatWindow[]>,\n fe: BlueprintFloatingElement,\n at: number,\n end: number,\n): void {\n const wins = windows.get(floatKey(fe)) ?? [];\n const last = wins[wins.length - 1];\n if (last && at <= last.end + OVERLAY_REDETECT_GAP_S) {\n last.end = Math.max(last.end, end);\n return;\n }\n wins.push({ fe, at, end });\n windows.set(floatKey(fe), wins);\n}\n\nfunction collectFloatWindows(blueprint: VideoBlueprint, uiRouted: Set<number>, clock: SpineClock): FloatWindow[] {\n const windows = new Map<string, FloatWindow[]>();\n blueprint.scenes.forEach((scene, i) => {\n const sceneStart = scene.start_s ?? 0;\n const floats = z.array(BlueprintFloatingElementSchema).safeParse(scene.floating_elements ?? []);\n if (!floats.success) return;\n for (const fe of floats.data) {\n const at = clock.map(i, fe.appears_at_s ?? sceneStart);\n const dur = fe.duration_s ?? 2.5;\n if (floatIsRoutedSurface(fe, uiRouted.has(i)) || dur < OVERLAY_MIN_DUR_S) continue;\n addFloatDetection(windows, fe, at, at + dur);\n }\n });\n return [...windows.values()].flat().sort((a, b) => a.at - b.at);\n}\n\n/** One non-text element → a COMMENTED <img> stub (clean by default; agent sources a real image, then uncomments). */\nfunction floatingStub(fe: BlueprintFloatingElement, at: number, dur: number): string {\n // All interpolated into an HTML comment → must be comment-safe (no `--`).\n const kind = commentSafe(fe.kind ?? \"element\");\n const label = commentSafe(fe.brand_name || fe.what_it_represents || fe.description || fe.kind || \"element\");\n const hint = commentSafe(sourceHint(fe));\n const slug =\n (fe.kind ?? \"element\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\") || \"element\";\n return [\n `<!-- ${kind}: ${label} @ ${at}s for ${dur}s (${positionClass(fe.position)}). Source a real asset: ${hint} — drop it in this dir and uncomment:`,\n `<img class=\"ov clip ${positionClass(fe.position)}\" src=\"your-${slug}.png\" data-start=\"${at}\" data-dur=\"${dur}\" alt=\"\" /> -->`,\n ].join(\"\\n\");\n}\n\n/**\n * A UI-only-composite scene (an app/website/chat the deconstruct wanted as a split) →\n * a COMMENTED phone-mockup PIP stub: the talking-head plays clean full-frame underneath,\n * and the real UI rides on top as a phone PIP sourced from a REAL screenshot or a brand\n * HTML block — never Seedance. Names the exact sourcing command so the operator just\n * drops the asset and uncomments. Empty when the scene isn't a UI composite.\n */\nfunction uiSurfaceStub(blueprint: VideoBlueprint, run: number[], clock: SpineClock): string {\n const scenes = run.map((i) => blueprint.scenes[i]).filter((s): s is VideoScene => Boolean(s));\n if (scenes.length === 0) return \"\";\n // The surface region: the one classified UI, else (on a scene whose prose didn't\n // trip the classifier but whose layout RUN is UI-routed) the non-presenter panel.\n const surfaceOf = (scene: VideoScene): CompositionRegion | undefined => {\n const regions = compositeRegionsOf(scene) ?? [];\n return regions.find(regionIsUiSurface) ?? regions.find((r) => !r.is_presenter);\n };\n const ui = scenes.map(surfaceOf).find(Boolean);\n // Spine-clock window: from the run's first scene's picture start to the last's end.\n const [firstScene] = run;\n const lastScene = run.at(-1);\n if (firstScene === undefined || lastScene === undefined) return \"\";\n const at = clock.startOf(firstScene);\n const end = clock.startOf(lastScene + 1);\n const dur = Math.max(0.5, Math.round((end - at) * 100) / 100);\n const label = commentSafe(ui?.summary || ui?.frame_prompt || ui?.panel || \"the app screen\");\n // The surface's state timeline: one beat per scene, so the operator can produce ONE\n // continuous screen recording (or scripted phone-scroll) that hits every state.\n const states =\n scenes.length > 1\n ? run.map((i) => {\n const s = blueprint.scenes[i] as VideoScene;\n const beat = surfaceOf(s)?.summary || s.summary || \"…\";\n return ` @ ${clock.startOf(i)}s — ${commentSafe(beat)}`;\n })\n : [];\n // A designed panel (kind static_graphic) has no live page to screenshot — the\n // operator rebuilds it as brand HTML or supplies the design asset. Only a real\n // app/site screen gets the screenshot instruction.\n const isGraphic = scenes.some((s) => (compositeRegionsOf(s) ?? []).some((r) => r.kind === \"static_graphic\"));\n const sourcing = isGraphic\n ? [\n \" Build it as a real designed panel; never AI-generate its text/typography:\",\n \" hand-build a brand-accurate HTML block in this composition (restyle the seeded\",\n \" overlay text, or `npx hyperframes add <block>` for a ready-made card),\",\n \" — OR drop the design asset (export it from the brand kit) as panel.png here;\",\n \" then nest it as a timed clip:\",\n ]\n : [\n \" Build it as a real surface, never AI: capture the live page —\",\n \" baker images screenshot https://<brand-domain>/<path> (image-library skill)\",\n \" — OR hand-build a brand-accurate HTML screen; then frame it in a phone mockup:\",\n \" npx hyperframes add phone-scroll (writes compositions/phone-scroll.html)\",\n \" drop the screenshot as screenshot.png in this dir and nest it as a PIP clip:\",\n ];\n const kindLabel = isGraphic ? \"GRAPHIC PANEL\" : \"PHONE UI\";\n const noun = isGraphic ? \"the designed graphic panel this window shows\" : \"the app/site screen this window shows\";\n return [\n `<!-- ${kindLabel} @ ${at}s for ${dur}s — ${noun}: ${label}.`,\n ...(states.length > 0 ? [\" ONE continuous surface; its states over the window:\", ...states] : []),\n ...sourcing,\n ` <div class=\"clip\" data-composition-src=\"compositions/phone-scroll.html\" data-start=\"${at}\" data-duration=\"${dur}\" data-track-index=\"2\" data-width=\"1080\" data-height=\"1920\"></div> -->`,\n ].join(\"\\n\");\n}\n\n// Overlay roles that ARE transcript captions (karaoke/subtitle fragments). With an\n// active caption track they must NOT also seed as frozen static overlays — the track\n// re-creates the words word-synced from the rendered audio, and seeding both rendered\n// the same text twice (the audit's double-caption defect).\nconst CAPTION_ROLE_RE = /^(?:caption|captions|subtitle|subtitles|karaoke)$/i;\n\n/**\n * Build the overlay layer as REAL, hand-editable HTML — the faithful first draft\n * of the reference's on-screen graphics, NOT props fed to a styling engine. Each\n * overlay/floating element becomes a plain element with its text, a position class,\n * and `data-start`/`data-dur`/`data-anim` for the generic timeline runtime. The\n * operator opens index.html and paints: restyle, regroup, add a real <img> bug,\n * build a ticker — full control. The runtime only decides WHEN things show, never\n * HOW they look. Returned as a string the command injects at the composition's\n * `<!--OVERLAYS-->` marker.\n */\nexport function buildOverlayHtml(input: unknown, opts: { captionsActive?: boolean; videoModel?: string } = {}): string {\n const blueprint = VideoBlueprintSchema.parse(input);\n // Overlay windows are seeded on the SPINE clock (where each scene's picture actually\n // sits in the butted concat) so they land on their beats even when the reference had\n // dead air between scenes or a scene was clamped to the clip ceiling. The ceiling is the\n // video model's, so pass the one the canvas renders on or a clamped scene shifts them.\n const clock = spineClockFor(blueprint, opts.videoModel ? sceneCeilingS(opts.videoModel) : SEEDANCE_CEILING_S);\n const blocks: string[] = [\n [\n \"<!-- ⬇ OVERLAY LAYER — this is YOUR HTML to paint, and it is a REAL Hyperframes\",\n \" composition (our hyperframe_render runs the genuine `npx hyperframes` renderer).\",\n \" The reference's overlays are seeded below as plain elements (text + position\",\n \" class + data-start/data-dur). Restyle freely in <style>, regroup, animate, swap a\",\n \" logo placeholder for a real <img> you drop in this dir. But you can do FAR more:\",\n \" • pull a ready-made block — `npx hyperframes add <id>` (lower-third, social card,\",\n \" stat counter, chart, code, logo sting) — and nest it as a\",\n ' <div data-composition-src=\"compositions/<id>.html\" data-start data-track-index ...> clip;',\n \" • drive a real caption track off the transcript (karaoke / themed / kinetic);\",\n \" • animate with the named GSAP motion-rule vocabulary, not just fade/slide/pop;\",\n \" • frame a talking head as a video-call / PIP / split.\",\n \" See ../.claude/skills/creative-canvas-ads/references/hyperframes/ (start at README.md).\",\n \" Positions: edit the .pos-* classes or add your own. -->\",\n ].join(\"\\n\"),\n ];\n\n // Windows are clamped to the video end: an element seeded past `clock.totalS`\n // simply never hides (\"stuck last overlay\") and reads as a render bug.\n const clampDur = (at: number, end: number): number =>\n Math.max(0.1, Math.round((Math.min(end, clock.totalS) - at) * 1000) / 1000);\n const ovParts = mergeCaptions(blueprint, clock)\n .filter((e) => !(opts.captionsActive && CAPTION_ROLE_RE.test(e.ov.role ?? \"\")))\n .map((e) => overlayElement(e.ov, e.at, clampDur(e.at, e.end)))\n .filter(Boolean);\n if (ovParts.length > 0) blocks.push(ovParts.join(\"\\n\"));\n\n // The SAME graphic re-detected across scenes (a persistent watermark, a graphic that\n // spanned the cut or popped back a beat later) must seed ONE stub spanning the UNION\n // of its detections — emitting on first sight kept only the first scene's slice, so\n // a whole-video logo bug stubbed as a sub-second flash.\n const runs = uiRoutedRuns(blueprint);\n const uiRouted = new Set(runs.flat());\n const floatParts = collectFloatWindows(blueprint, uiRouted, clock)\n .map((w) => floatingStub(w.fe, w.at, clampDur(w.at, w.end)))\n .filter(Boolean);\n if (floatParts.length > 0) blocks.push(floatParts.join(\"\\n\"));\n\n // ONE grouped stub per persistent screen surface (per UI-routed layout run): the\n // surface is one continuous recording with a state timeline, not N per-scene\n // screenshots — the audit's per-scene stubs asked the operator for 7 screens of\n // what is a single 18s screen recording.\n for (const run of runs) {\n const stub = uiSurfaceStub(blueprint, run, clock);\n if (stub) blocks.push(stub);\n }\n\n return blocks.join(\"\\n\\n\");\n}\n","/** Escape text for an HTML text node or a double-quoted attribute. */\nexport function escapeHtml(s: string): string {\n return s.replace(/&/g, \"&\").replace(/</g, \"<\").replace(/>/g, \">\").replace(/\"/g, \""\");\n}\n","import {\n clipDurationsFor,\n SEEDANCE_DURATIONS,\n type VideoBlueprint,\n VideoBlueprintSchema,\n type VideoScene,\n} from \"@baker/canvas-contract\";\nimport { estSpeechS } from \"../../lib/speech.ts\";\n\n// Default length of a reproduced scene transition. Real ad transitions are brief;\n// keeping it short bounds how much footage the xfade overlap consumes.\nconst TRANSITION_DEFAULT_S = 0.4;\n// DECON transition type → the ffmpeg `xfade` transition it reproduces. Types not\n// in this map (cut, match_cut, none, other) stay HARD CUTS — a plain concat —\n// because a match cut blended by xfade would lose its seamless-cut effect.\nconst XFADE_BY_TYPE: Record<string, string> = {\n fade: \"fade\",\n dissolve: \"dissolve\",\n whip: \"smoothleft\",\n swipe: \"wipeleft\",\n zoom: \"zoomin\",\n};\n\n/**\n * The model-allowed GENERATION length for a scene: the smallest allowed clip duration\n * in `set` that is >= the real scene duration (capped at the set's max). We always\n * generate AT LEAST the scene length so we can trim the clip back down to the exact\n * scene duration afterwards — generating shorter (what nearest-snap does for e.g. a 5s\n * scene → 4s) would leave a gap that can't be filled. This is what keeps the\n * concatenated picture on the same timeline as the absolute-timed audio. Each video\n * model has its OWN duration set (Seedance ≠ Veo's {4,6,8}), so it is parameterized.\n */\nexport function ceilToDurations(set: readonly number[], durationS: number): number {\n const first = set[0] as number;\n const max = set[set.length - 1] as number;\n if (!Number.isFinite(durationS) || durationS <= 0) return first;\n for (const d of set) if (d >= durationS) return d;\n return max;\n}\n\n/**\n * The clip lengths a canvas generates at on `videoModel`: the registry's `duration` enum\n * (Veo's {4,6,8}, Kling's 3-15, Seedance 2.5's 4-30), else Seedance's. The ONE set the\n * scene clamp, the generation length and the report all read: a scene clamped to\n * Seedance's 15s while Omni stops at 10 put a 12s window on the timeline over a 10s clip,\n * and the difference rendered as a black tail.\n */\nexport function clipDurationSet(videoModel: string): readonly number[] {\n return clipDurationsFor(videoModel) ?? SEEDANCE_DURATIONS;\n}\n\n/** The longest clip `videoModel` renders: no scene holds the timeline for longer. */\nexport function sceneCeilingS(videoModel: string): number {\n return Math.max(...clipDurationSet(videoModel));\n}\n\n/** Seedance's ceiling, for the readings that are about the source rather than a model. */\nexport const SEEDANCE_CEILING_S = Math.max(...SEEDANCE_DURATIONS);\n\n/** The real scene length to place on the timeline, clamped to the video model's ceiling. */\nexport function sceneDurationS(scene: VideoScene, ceilingS: number): number {\n const raw = scene.duration_s ?? (scene.end_s != null && scene.start_s != null ? scene.end_s - scene.start_s : 5);\n return Math.min(Math.max(raw, 0.5), ceilingS);\n}\n\n/**\n * THE one clock of the reproduction: the spine. The picture is physically a butted\n * concat of clips of length `sceneDurationS`, so scene i's picture starts at\n * Σ_{j<i} sceneDurationS(j) — regardless of the reference's own scene timestamps.\n * Everything placed at an absolute second (voice, SFX, music, overlays, the mix\n * length) must be expressed on THIS clock, or dead-air gaps / clamped scenes in the\n * blueprint make the picture run ahead of the audio and never recover. `map` is the\n * identity when scenes tile the source exactly (the common case).\n */\nexport type SpineClock = {\n /** Scene i's picture start on the spine: Σ_{j<i} sceneDurationS(j). */\n startOf(scene: number): number;\n /** A blueprint-absolute second inside scene i → its spine second (clamped to the scene's window). */\n map(scene: number, absS: number): number;\n /** A blueprint-absolute second → its spine second (scene located by the blueprint's own windows). */\n mapAbs(absS: number): number;\n /** The spine's total length: Σ sceneDurationS — what the audio mix must be pinned to. */\n totalS: number;\n};\n\nexport function spineClockFor(blueprint: VideoBlueprint, ceilingS: number): SpineClock {\n // Per scene: its start on the REFERENCE clock (falling back to the previous scene's end\n // when the deconstruct omitted start_s, used to translate absolute stamps), its start on\n // the spine, and its length there.\n const windows: Array<{ refStart: number; spineStart: number; dur: number }> = [];\n let cursor = 0;\n let acc = 0;\n for (const s of blueprint.scenes) {\n const dur = sceneDurationS(s, ceilingS);\n const refStart = s.start_s ?? cursor;\n cursor = s.end_s ?? refStart + dur;\n windows.push({ refStart, spineStart: acc, dur });\n acc += dur;\n }\n const totalS = round3(acc);\n const startOf = (scene: number): number => round3(windows[scene]?.spineStart ?? totalS);\n const map = (scene: number, absS: number): number => {\n // A blueprint has at least one scene, so the clamped index always names a window.\n const w = windows[Math.min(Math.max(scene, 0), windows.length - 1)];\n if (!w) return 0;\n return round3(w.spineStart + Math.min(Math.max(absS - w.refStart, 0), w.dur));\n };\n const mapAbs = (absS: number): number => {\n let i = 0;\n windows.forEach((w, j) => {\n if (j > 0 && w.refStart <= absS) i = j;\n });\n return map(i, absS);\n };\n return { startOf, map, mapAbs, totalS };\n}\n\nfunction round3(n: number): number {\n return Math.round(n * 1000) / 1000;\n}\n\n/** Public, parse-tolerant entry for the spine clock (tests, overlay generation). */\nexport function buildSpineClock(input: unknown, videoModel?: string): SpineClock {\n return spineClockFor(VideoBlueprintSchema.parse(input), videoModel ? sceneCeilingS(videoModel) : SEEDANCE_CEILING_S);\n}\n\n/**\n * The outgoing transition to reproduce at scene `i`'s boundary, or null for a hard\n * cut. The LAST scene never has one (nothing follows it). Only recognized non-cut\n * types map to an xfade; everything else is a hard cut.\n */\nfunction sceneOutTransition(scene: VideoScene, isLast: boolean): { xfade: string; dur: number } | null {\n if (isLast) return null;\n const type = scene.transition_out?.type?.toLowerCase();\n const xfade = type ? XFADE_BY_TYPE[type] : undefined;\n return xfade ? { xfade, dur: TRANSITION_DEFAULT_S } : null;\n}\n\n/**\n * Resolve a scene's timeline lengths: its on-timeline duration, the outgoing\n * transition (dropped when the clip ceiling leaves no room for its tail), the trim\n * target (scene + tail), and the generation length (≥ trim and ≥ the spoken line). Pure.\n */\nexport type SceneLengths = {\n /** The scene's length on the timeline. */\n dur: number;\n /** Its outgoing transition, or null for a hard cut. */\n out: { xfade: string; dur: number } | null;\n /** The footage the scene consumes: its length plus the transition tail. */\n trimTarget: number;\n /** The clip length asked of the model: a length it renders, at least `trimTarget` and the line. */\n genDur: number;\n};\n\nexport function sceneTiming(\n scene: VideoScene,\n isLast: boolean,\n // The line the video model voices in this scene, when it voices one: the clip must be\n // long enough to say it.\n nativeLine: string | undefined,\n // The clip's video model duration set (`clipDurationSet`): Veo's {4,6,8} differs from\n // the Seedance set, so the generation length must snap to the RIGHT set (a Seedance-only\n // length is a hard provider error on Veo), and the scene is clamped to that set's max.\n durationSet: readonly number[],\n): SceneLengths {\n const dur = sceneDurationS(scene, Math.max(...durationSet));\n let out = sceneOutTransition(scene, isLast);\n let trimTarget = dur + (out?.dur ?? 0);\n // A scene at the clip ceiling has no room for the transition tail: the xfade overlap\n // would run past the clip end and drift the picture off the audio timeline. Fall back\n // to a hard cut when the tail can't fit.\n if (out && ceilToDurations(durationSet, trimTarget) < trimTarget) {\n out = null;\n trimTarget = dur;\n }\n const speech = nativeLine === undefined ? 0 : estSpeechS(nativeLine);\n const genDur = ceilToDurations(durationSet, Math.max(trimTarget, speech));\n return { dur, out, trimTarget, genDur };\n}\n\n// Seedance's API max clip is 15s, but the generation gateway frequently times out\n// (HTTP 524) before it can deliver a clip longer than ~10s — the advertised ceiling is\n// not deliverable in practice. So the scaffold never asks for a clip past this SAFE\n// duration: a single shot longer than this splits into the next take (at a scene boundary\n// when the deconstruct pre-split the shot, joined by the shared boundary frame the spine\n// seam-dedups), so every emitted clip stays inside the gateway-deliverable window. 10s is\n// a Seedance-allowed duration, so the split clip still snaps cleanly. (A single scene\n// longer than this that the deconstruct did NOT pre-split can't be split here — the\n// splitter only breaks at scene boundaries — so it's flagged as `report.oversize_scenes`.)\nexport const SEEDANCE_SAFE_MAX_S: number = SEEDANCE_DURATIONS.find((d) => d >= 10) ?? 10;\nexport const PHRASE_MAX_S = SEEDANCE_SAFE_MAX_S;\n","// The only blueprint fields the element-selection prompt reads per scene. Keeping just\n// these lets the (often >256KB) blueprint fit a literal select prompt without dragging in\n// dialogue/overlays/transcript/frame-composition the selector never looks at.\nconst SELECT_SCENE_FIELDS = [\n \"index\",\n \"start_s\",\n \"end_s\",\n \"duration_s\",\n \"summary\",\n \"narrative_role\",\n \"action_detail\",\n \"start_frame_prompt\",\n \"end_frame_prompt\",\n] as const;\nconst SELECT_GLOBAL_FIELDS = [\"cast\", \"branding\", \"voiceover\"] as const;\n\n/**\n * Project a deconstruct blueprint down to ONLY the fields the element-selection pass\n * reads (global cast/branding/voiceover + a handful of per-scene prompt fields). The\n * full blueprint stays the source of truth for prompt.json and scaffolding; this slim\n * is what gets inlined into the select prompt so a long ad's blueprint never blows the\n * inline-prompt limit. Defensive: returns the input unchanged when it isn't an object,\n * copies only keys that exist, and never throws on an unexpected shape.\n */\nexport function slimBlueprintForSelection(blueprintInput: unknown): unknown {\n if (!blueprintInput || typeof blueprintInput !== \"object\" || Array.isArray(blueprintInput)) return blueprintInput;\n const bp = blueprintInput as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n for (const k of [\"version\", \"source\"] as const) if (k in bp) out[k] = bp[k];\n if (bp.global && typeof bp.global === \"object\" && !Array.isArray(bp.global)) {\n const g = bp.global as Record<string, unknown>;\n const slimG: Record<string, unknown> = {};\n for (const k of SELECT_GLOBAL_FIELDS) if (k in g) slimG[k] = g[k];\n out.global = slimG;\n }\n if (Array.isArray(bp.scenes)) {\n out.scenes = bp.scenes.map((s) => {\n if (!s || typeof s !== \"object\" || Array.isArray(s)) return s;\n const sr = s as Record<string, unknown>;\n const slim: Record<string, unknown> = {};\n for (const k of SELECT_SCENE_FIELDS) if (k in sr) slim[k] = sr[k];\n return slim;\n });\n }\n return out;\n}\n\n/**\n * Project a deconstruct blueprint down to ONLY its GLOBAL, cross-frame identity: the ad\n * spec every boundary frame must stay consistent with (cast identity, palette, brand,\n * typography mood, aspect ratio). This is what `target_blueprint` is meant to be — a\n * demoted SHARED style reference, not the source of any one frame's content (each frame's\n * content already lives verbatim in its own `params.prompt`). The full per-scene array is\n * dropped: a frame node inlining all N scenes' prompts/dialogue/transcript per image is\n * pure waste (a 33-scene blueprint is ~200 KB inlined into every one of a dozen frame\n * prompts) and invites the model to blend in another scene's content. Defensive: returns\n * the input unchanged when it isn't an object; never throws on an unexpected shape.\n */\nexport function slimBlueprintForFrameStyle(blueprintInput: unknown): unknown {\n if (!blueprintInput || typeof blueprintInput !== \"object\" || Array.isArray(blueprintInput)) return blueprintInput;\n const bp = blueprintInput as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n // version+source carry the aspect ratio; global carries style/palette/cast/branding;\n // reference_elements names the recurring cast/logo the frames ground on. Everything a\n // frame needs to stay ON-BRAND — and nothing per-scene.\n for (const k of [\"version\", \"source\", \"global\", \"reference_elements\"] as const) if (k in bp) out[k] = bp[k];\n return out;\n}\n","import { VideoBlueprintSchema, type VideoScene } from \"@baker/canvas-contract\";\nimport { estSpeechWindowS } from \"../../lib/speech.ts\";\nimport { assignElementLabels, elementTodo } from \"../lib/elements.ts\";\nimport { isInventedPerson, presenceOf, RecurringElements } from \"./elements.ts\";\nimport { ceilToDurations, clipDurationSet, SEEDANCE_SAFE_MAX_S, sceneDurationS } from \"./timing.ts\";\n\nexport type VideoReport = {\n scene_count: number;\n // `asset_todo` is null when the slot already has its picture (`source_image`, e.g. a cast avatar's sheet).\n elements: Array<{\n label: string;\n type: string;\n description: string | null;\n scenes: number[];\n asset_todo: string | null;\n source_image?: string;\n }>;\n dialogue: Array<{ scene: number; speaker: string; line: string; voice_description: string | null }>;\n sfx_count: number;\n overlay_count: number;\n // Scenes longer than the video model's longest clip, held on the timeline at that length.\n clamped_scenes: Array<{ scene: number; original_s: number; clip_s: number }>;\n // Scenes whose OWN footage span exceeds the gateway-safe clip ceiling. The phrase\n // splitter only breaks a long run at scene boundaries, so a SINGLE scene longer than the\n // ceiling (typically a silent b-roll shot, or a one-shot monologue) still generates an\n // over-long clip that 524s at the gateway. The scaffold can't split it for you — break it\n // into two scenes in prompt.json. Advisory, not a hard error.\n oversize_scenes: Array<{ scene: number; scene_s: number; clip_s: number }>;\n // Scenes whose estimated spoken length runs well past their window (the scaffold\n // over-stuffed the beat). The line will overrun its scene, pushing the picture off the\n // audio timeline — shorten the copy or lengthen the scene. Advisory, not a hard error.\n overstuffed_scenes: Array<{ scene: number; scene_s: number; est_speech_s: number }>;\n has_music: boolean;\n};\n\n// A scene whose estimated speech exceeds its window by more than this is flagged as\n// over-stuffed: a little overrun is fine (a native line continues a beat past its visual\n// cut), but well past the window the audio timeline drifts and lips fall behind.\nconst OVERSTUFF_RATIO = 1.3;\n\n/**\n * The three clip-length advisories for one scene, appended to the report's lists:\n * clamped (truncated past the video model's longest clip), oversize (a single scene whose\n * own clip exceeds the gateway-safe ceiling: unsplittable, will 524), and overstuffed (the\n * estimated speech overruns the scene window).\n */\nfunction collectClipAdvisories(\n scene: VideoScene,\n i: number,\n durationSet: readonly number[],\n out: {\n clamped: VideoReport[\"clamped_scenes\"];\n oversize: VideoReport[\"oversize_scenes\"];\n overstuffed: VideoReport[\"overstuffed_scenes\"];\n },\n): void {\n const round2 = (n: number) => Math.round(n * 100) / 100;\n const ceilingS = Math.max(...durationSet);\n const original = scene.duration_s ?? 5;\n if (original > ceilingS) out.clamped.push({ scene: i, original_s: original, clip_s: ceilingS });\n // The scene window the clip/speech has to fit in (clamped to the model's ceiling).\n const window = sceneDurationS(scene, ceilingS);\n // A single scene longer than the gateway-safe ceiling can't be split (the splitter only\n // breaks at scene boundaries) — its clip will 524. Flag it so the user can split it.\n if (window > SEEDANCE_SAFE_MAX_S)\n out.oversize.push({ scene: i, scene_s: round2(window), clip_s: ceilToDurations(durationSet, window) });\n const speech = (scene.dialogue ?? []).reduce(\n (s, line) => s + (line.line ? estSpeechWindowS(line.line, line.start_s, line.end_s) : 0),\n 0,\n );\n if (speech > window * OVERSTUFF_RATIO)\n out.overstuffed.push({ scene: i, scene_s: round2(window), est_speech_s: round2(speech) });\n}\n\n/** Human-facing checklist the command prints — what needs review/assets after scaffolding. */\nexport function videoReport(input: unknown, elementsInput: unknown, videoModel: string): VideoReport {\n const blueprint = VideoBlueprintSchema.parse(input);\n const elements = RecurringElements.parse(elementsInput);\n const dialogue: VideoReport[\"dialogue\"] = [];\n const clamped: VideoReport[\"clamped_scenes\"] = [];\n const oversize: VideoReport[\"oversize_scenes\"] = [];\n const overstuffed: VideoReport[\"overstuffed_scenes\"] = [];\n let sfxCount = 0;\n let overlayCount = 0;\n blueprint.scenes.forEach((scene, i) => {\n for (const line of scene.dialogue ?? []) {\n if (line.line) {\n dialogue.push({\n scene: i,\n speaker: line.speaker ?? \"voiceover\",\n line: line.line,\n voice_description: line.voice_description ?? null,\n });\n }\n }\n sfxCount += (scene.sfx ?? []).length;\n overlayCount += (scene.overlays ?? []).length;\n collectClipAdvisories(scene, i, clipDurationSet(videoModel), { clamped, oversize, overstuffed });\n });\n return {\n scene_count: blueprint.scenes.length,\n elements: assignElementLabels(elements, \"video\").map(({ el, label }) => ({\n label,\n type: el.type,\n description: el.description ?? null,\n scenes: [...presenceOf(el).keys()].sort((a, b) => a - b),\n asset_todo: el.source_image?.trim()\n ? null\n : isInventedPerson(el)\n ? \"none: an invented, realistic person generated from the description (pass --avatar to keep one actor across ads)\"\n : elementTodo(el, label, \"video\"),\n ...(el.source_image?.trim() ? { source_image: el.source_image.trim() } : {}),\n })),\n dialogue,\n sfx_count: sfxCount,\n overlay_count: overlayCount,\n clamped_scenes: clamped,\n oversize_scenes: oversize,\n overstuffed_scenes: overstuffed,\n has_music: Boolean(blueprint.global?.music?.music_prompt),\n };\n}\n","/**\n * The language a script is spoken in, as the voice pipeline needs it: the English name\n * `voice_select` filters voices on (\"spanish\"), the ISO 639-1 code ElevenLabs reads numbers\n * by (`language_code`; without it eleven_v3 normalizes text with its English rules, so a\n * French ad's \"6900\" was spoken in English) and the country a regional tag names.\n *\n * Everything is derived from a BCP-47 tag with `Intl`, never from a table of languages: an\n * ad can be in any language, and a declared tag (`voice.language`, a translation's\n * `language`) is the best source there is. With none declared, the script's language is\n * Jev's to decide (`languageQuestion`), over every language `Intl` can name.\n */\n\nimport { languageName, languageRegion, languageTag } from \"../../../language.ts\";\nimport type { JevAnswer, JevQuestion } from \"../../nodes/local/lib/jev.ts\";\n\nexport type SpokenLanguage = { tag: string; iso: string; name: string; region?: { code: string; name: string } };\n\n/** What a BCP-47 tag means to the voice pipeline; null when it names no language. Pure. */\nexport function spokenLanguage(code: string): SpokenLanguage | null {\n const tag = languageTag(code);\n if (!tag) return null;\n const iso = new Intl.Locale(tag).language;\n const name = languageName(iso);\n if (!name) return null;\n const region = languageRegion(tag);\n return { tag, iso, name: name.toLowerCase(), ...(region ? { region } : {}) };\n}\n\nconst NAMES = new Intl.DisplayNames([\"en\"], { type: \"language\", fallback: \"none\" });\nconst LETTERS = \"abcdefghijklmnopqrstuvwxyz\";\n\n/**\n * Every language with an ISO 639-1 code that `Intl` can name (about 190), as Jev's options:\n * generated, so no language is missing because nobody typed it in. Measured: a flat Choice this\n * wide still named the language of one short line (\"Bestel nu.\", \"Zamów teraz.\").\n */\nconst LANGUAGE_OPTIONS: Readonly<Record<string, string>> = (() => {\n // A deprecated code (\"mo\", \"iw\", \"in\") reads the same name as the current one: two \"Romanian\"s split Jev's\n // probability in half and neither ever holds, so only the canonical code is offered, and each name once.\n const options: Record<string, string> = {};\n const named = new Set<string>();\n for (const a of LETTERS) {\n for (const b of LETTERS) {\n const code = `${a}${b}`;\n const name = NAMES.of(code);\n if (!name || name.toLowerCase() === code || named.has(name)) continue;\n if (Intl.getCanonicalLocales(code)[0] !== code) continue;\n named.add(name);\n options[code] = name;\n }\n }\n return options;\n})();\n\n/** At or above this probability, Jev's pick is the script's language. Measured: see docs/decision-model.md. */\nexport const LANGUAGE_HELD = 0.8;\n\n/** The question that names the language `lines` are written in: a Choice over every language. Pure. */\nexport function languageQuestion(lines: readonly string[]): JevQuestion {\n return {\n type: \"choice\",\n instructions: {\n lines: lines.join(\"\\n\"),\n question: \"Which language are `lines` written in? When they mix languages, the one most of the words are in.\",\n },\n criteria: { ...LANGUAGE_OPTIONS },\n };\n}\n\n/** The ISO 639-1 code Jev named with enough probability; undefined below `LANGUAGE_HELD` or with no answer. Pure. */\nexport function languageFromAnswer(answer: JevAnswer | undefined): string | undefined {\n if (!answer || !(\"choice\" in answer)) return undefined;\n return (answer.probabilities[answer.choice] ?? 0) >= LANGUAGE_HELD ? answer.choice : undefined;\n}\n\n/**\n * The code of a language named in English (\"spanish\" → \"es\"). Only for a canvas scaffolded\n * before the voice's language was stored as a tag, whose rebuild context holds the name. Pure.\n */\nexport function languageCodeNamed(name: string): string | undefined {\n const wanted = name.trim().toLowerCase();\n return Object.entries(LANGUAGE_OPTIONS).find(([, n]) => n.toLowerCase() === wanted)?.[0];\n}\n\n/** The voice's language from a canvas's rebuild context: its tag, else the name an older canvas stored. Pure. */\nexport function voiceLanguageOf(opts: { spokenLanguage?: string; voiceLanguage?: string }):\n | {\n name: string;\n iso?: string;\n }\n | undefined {\n const spoken = opts.spokenLanguage ? spokenLanguage(opts.spokenLanguage) : null;\n if (spoken) return { name: spoken.name, iso: spoken.iso };\n const legacy = opts.voiceLanguage?.trim().toLowerCase();\n if (!legacy) return undefined;\n const iso = languageCodeNamed(legacy);\n return iso ? { name: legacy, iso } : { name: legacy };\n}\n","import type { VideoBlueprint } from \"@baker/canvas-contract\";\nimport type { VideoConcatClipInput } from \"../../nodes/local/videoConcat.ts\";\nimport type { NodeDecl } from \"../../schema/canvas.ts\";\nimport type { AudioTrack } from \"./audio.ts\";\nimport { ids, ref } from \"./ids.ts\";\nimport type { ScaffoldVideoOpts } from \"./opts.ts\";\nimport type { SceneClip } from \"./timeline-env.ts\";\nimport type { SpineClock } from \"./timing.ts\";\n\n// The assembly after the scenes: the spine that joins their clips, the overlay layer over\n// it, the audio mix, the burned-in captions, and the final mux. Every node here is\n// emitted once, complete: what each one consumes is decided before it is built, so no\n// node is patched after it is on the canvas.\n\ntype SeamMode = NonNullable<ScaffoldVideoOpts[\"seamDedup\"]>;\n\n/**\n * One scene clip as a `video_concat` clip: its timeline length, how the spine gives it\n * that length (a generated clip cut to its window, a still held, or the input as\n * rendered), its fit, its outgoing transition and whether it repeats the previous\n * clip's splice frame. The spine node owns the ffmpeg that follows from these.\n */\nfunction concatClipOf(c: SceneClip): VideoConcatClipInput {\n const length = c.trim ? \"trim\" : c.still ? \"still\" : undefined;\n return {\n duration_s: c.scene_s,\n ...(length ? { length } : {}),\n ...(c.trim && c.trim.offset_s > 0 ? { offset_s: c.trim.offset_s } : {}),\n ...(c.still?.fit === \"pad\" ? { fit: \"pad\" as const } : {}),\n ...(c.out ? { transition: { type: c.out.xfade, duration_s: c.out.dur } } : {}),\n ...(c.continuesFrame ? { continues_frame: true } : {}),\n };\n}\n\n/**\n * Emit the visual spine: a `video_concat` joining the per-scene clips in order (hard\n * cuts, or xfades where the deconstruct detected a transition). Every input lands on\n * the OUTPUT canvas raster, and each clip's length work (a cut to its scene window, a\n * still held for the scene) rides the node's own per-input chain, so no standalone\n * trim node is needed. Returns the spine video ref.\n */\nexport function buildSpine(\n clips: SceneClip[],\n seam: SeamMode,\n dims: { w: number; h: number },\n nodes: NodeDecl[],\n): string {\n const inputs: Record<string, unknown> = {};\n clips.forEach((c, i) => {\n inputs[`c${i}`] = c.ref;\n });\n nodes.push({\n id: ids.spine,\n type: \"video_concat\",\n tags: { role: \"spine\" },\n inputs,\n params: { width: dims.w, height: dims.h, seam_dedup: seam, clips: clips.map(concatClipOf) },\n });\n return ref(ids.spine, \"video\");\n}\n\n/**\n * Emit the two blueprint ingests: `prompt` (the full deconstruct — the human-editable\n * source of truth, and the artifact the command writes) and `prompt_style` (the SLIM\n * projection every frame reads via target_blueprint — global cast/palette/brand only, no\n * per-scene array, so no image inlines ~200 KB of other scenes to render one frame).\n * `prompt_style` is DERIVED: `baker canvas validate`/`run` regenerate it from prompt.json\n * (syncStyleProjection) whenever they diverge, so operator edits to prompt.json actually\n * reach the frames — the projection is never the editing surface.\n */\nexport function emitBlueprintIngests(opts: ScaffoldVideoOpts, nodes: NodeDecl[]): void {\n nodes.push({\n id: ids.prompt,\n type: \"ingest\",\n params: { source: \"path\", path: opts.blueprintPath ?? \"./prompt.json\", expect: \"json\" },\n });\n nodes.push({\n id: ids.promptStyle,\n type: \"ingest\",\n params: { source: \"path\", path: opts.blueprintStylePath ?? \"./prompt.style.json\", expect: \"json\" },\n });\n}\n\n/**\n * Where the burned-in captions' words come from, or null for an ad with no captions.\n *\n * `transcribe` — the normal path, for an ad with a voice: the RENDERED read is\n * transcribed, so the cards match what was actually said. `static` — for an ad nobody\n * speaks, a transcript supplied as a file: transcribing a music-led ad's near-silence is\n * how one came back captioned \"Thank you.\" for sixteen seconds, and with the script itself\n * the words and beat boundaries are exact. With neither, the ad carries no captions.\n */\nexport type CaptionPlan = { source: \"transcribe\" | \"static\"; transcriptRef: string; wordsPerGroup: number | undefined };\n\nexport function planCaptions(opts: ScaffoldVideoOpts, voTracks: AudioTrack[]): CaptionPlan | null {\n if (!opts.captionsCompositionPath) return null;\n const wordsPerGroup = opts.captionWordsPerGroup || undefined;\n if (voTracks.some((t) => t.kind === \"vo\")) {\n return { source: \"transcribe\", transcriptRef: ref(ids.captionsTranscribe, \"transcript\"), wordsPerGroup };\n }\n if (!opts.staticTranscriptPath) return null;\n return { source: \"static\", transcriptRef: ref(ids.captionsTranscript, \"json\"), wordsPerGroup };\n}\n\n/**\n * The burned-in overlay pass, or null when the reference shows nothing to overlay. The\n * overlay content is NOT passed as props — the command bakes it into the composition's\n * index.html as real, editable HTML/CSS (see buildOverlayHtml) so the operator paints the\n * broadcast look directly; the node composites that HTML over the video. With captions,\n * the same render also draws the caption track (its optional `transcript` input): the\n * caption text is picture-independent, and one headless render is one fewer generational\n * encode than a second pass.\n */\nexport function overlayNode(opts: ScaffoldVideoOpts, background: string, captions: CaptionPlan | null): NodeDecl {\n return {\n id: ids.overlaid,\n type: \"hyperframe_render\",\n tags: { role: \"overlay\" },\n inputs: { background, ...(captions ? { transcript: captions.transcriptRef } : {}) },\n params: {\n composition: opts.overlayCompositionPath,\n ...(captions?.wordsPerGroup ? { words_per_group: captions.wordsPerGroup } : {}),\n },\n };\n}\n\n/**\n * Mix voiceover + SFX + music onto the timeline, the music bed ducked under the voice\n * tracks: when the creator speaks the bed drops and recovers in the gaps, so it stays a\n * true background under the words. Returns the mix ref, or undefined with nothing to mix.\n */\nexport function emitAudioMix(tracks: AudioTrack[], clock: SpineClock, nodes: NodeDecl[]): string | undefined {\n if (tracks.length === 0) return undefined;\n const mixInputs: Record<string, unknown> = {};\n for (const t of tracks) mixInputs[t.slot] = t.ref;\n const musicTrack = tracks.find((t) => t.kind === \"music\");\n const voiceSlots = tracks.filter((t) => t.kind === \"vo\").map((t) => t.slot);\n const duck = musicTrack && voiceSlots.length > 0 ? { duck: { track: musicTrack.slot, against: voiceSlots } } : {};\n nodes.push({\n id: ids.audioMix,\n type: \"audio_timeline\",\n inputs: mixInputs,\n params: {\n tracks: tracks.map((t) => ({\n slot: t.slot,\n start_s: t.start_s,\n ...(t.duration_s !== undefined ? { duration_s: t.duration_s } : {}),\n ...(t.gain_db !== undefined ? { gain_db: t.gain_db } : {}),\n })),\n // Pinned to the SPINE length — the one clock. The reference duration can\n // include dead air the butted picture does not reproduce, and `-shortest`\n // at the final mux silently truncates whichever stream runs longer.\n total_ms: Math.round(clock.totalS * 1000),\n ...duck,\n },\n });\n return ref(ids.audioMix, \"audio\");\n}\n\n/**\n * Every line the ad's voice is asked to say, in the order it is said: the text its captions\n * print when `captionsFromScript` is on. Read off the blueprint, so an edited line re-flows.\n */\nfunction scriptOfRecord(blueprint: VideoBlueprint): string {\n return (\n blueprint.scenes\n .flatMap((scene) =>\n (scene.dialogue ?? []).map((line) => ({\n text: line.line?.trim() ?? \"\",\n at: line.start_s ?? scene.start_s ?? 0,\n })),\n )\n .filter((line) => line.text)\n // Stable, so lines that start together keep the order they were written in.\n .sort((a, b) => a.at - b.at)\n .map((line) => line.text)\n .join(\" \")\n );\n}\n\n/**\n * The caption chain's own nodes. Transcribed captions read the clean VOICE BUS (vo tracks\n * only — no music/SFX, which smear Whisper's word timings) through `captions_transcribe`;\n * static ones ingest the supplied transcript. When an overlay layer is wired it already\n * draws them (see `overlayNode`); otherwise the standalone caption composition renders\n * them over the picture, and that becomes the video.\n */\nexport function emitCaptionChain(\n captions: CaptionPlan,\n env: { blueprint: VideoBlueprint; opts: ScaffoldVideoOpts; clock: SpineClock; ttsLanguageCode?: string },\n tracks: AudioTrack[],\n videoRef: string,\n overlaid: boolean,\n nodes: NodeDecl[],\n): { videoRef: string; videoNode?: string } {\n const { opts } = env;\n if (captions.source === \"transcribe\") {\n const script = opts.captionsFromScript ? scriptOfRecord(env.blueprint) : \"\";\n const voTrackList = tracks.filter((t) => t.kind === \"vo\");\n const voiceMixInputs: Record<string, unknown> = {};\n for (const t of voTrackList) voiceMixInputs[t.slot] = t.ref;\n nodes.push({\n id: ids.captionsVoiceMix,\n type: \"audio_timeline\",\n inputs: voiceMixInputs,\n params: {\n tracks: voTrackList.map((t) => ({\n slot: t.slot,\n start_s: t.start_s,\n ...(t.duration_s !== undefined ? { duration_s: t.duration_s } : {}),\n })),\n total_ms: Math.round(env.clock.totalS * 1000),\n },\n });\n nodes.push({\n id: ids.captionsTranscribe,\n type: \"video_transcribe\",\n inputs: { video: ref(ids.captionsVoiceMix, \"audio\") },\n params: {\n ...(env.ttsLanguageCode ? { language: env.ttsLanguageCode } : {}),\n ...(script ? { script } : {}),\n },\n });\n } else {\n nodes.push({\n id: ids.captionsTranscript,\n type: \"ingest\",\n params: { source: \"path\", path: opts.staticTranscriptPath, expect: \"json\" },\n });\n }\n if (overlaid) return { videoRef };\n // Captions-only ad (no overlay layer wired): the standalone caption composition.\n nodes.push({\n id: ids.captions,\n type: \"hyperframe_render\",\n inputs: { background: videoRef, transcript: captions.transcriptRef },\n params: {\n composition: opts.captionsCompositionPath,\n ...(captions.wordsPerGroup ? { words_per_group: captions.wordsPerGroup } : {}),\n ...(opts.captionCarriesOn?.length ? { carries_on: opts.captionCarriesOn } : {}),\n },\n });\n return { videoRef: ref(ids.captions, \"video\"), videoNode: ids.captions };\n}\n\n/**\n * Mux the audio under the (possibly captioned) picture, LAST, so loudness normalization\n * and the stereo upmix land on the final cut. The raw mix is a quiet mono track (tts +\n * ducked bed) that reads as \"no sound\" in casual players, so it is normalized to the\n * social target (-14 LUFS, -1.5 dBTP) in stereo. `shortest` is safe because the picture\n * and the mix are both pinned to the spine clock, and `canvas validate` proves it.\n */\nexport function emitFinalMux(videoRef: string, audioRef: string, nodes: NodeDecl[]): void {\n nodes.push({\n id: ids.final,\n type: \"av_mux\",\n tags: { role: \"mux\" },\n inputs: { video: videoRef, audio: audioRef },\n params: { loudnorm: { i: -14, tp: -1.5, lra: 11 }, length: \"shortest\" },\n });\n}\n","import {\n ELEVENLABS_MAX_MUSIC_LENGTH_MS,\n MUSIC_BED_MODEL,\n SOUND_EFFECT_MODEL,\n type VideoBlueprint,\n VOICE_CONVERT_MODEL,\n VOICEOVER_MODEL,\n} from \"@baker/canvas-contract\";\nimport type { NodeDecl } from \"../../schema/canvas.ts\";\nimport { ids, ref } from \"./ids.ts\";\nimport type { SpineClock } from \"./timing.ts\";\n\n// The audio models are registry roles (`MODEL_ROLES`), named here under the scaffold's own names.\nexport const FIXED_TTS_MODEL = VOICEOVER_MODEL;\nconst FIXED_SFX_MODEL = SOUND_EFFECT_MODEL;\nconst FIXED_MUSIC_MODEL = MUSIC_BED_MODEL;\n// Re-voices a Seedance talking clip's native audio to one consistent brand voice.\nexport const FIXED_VOICE_CONVERT_MODEL = VOICE_CONVERT_MODEL;\n// The music bed is a background texture under a talking-head, never a foreground\n// layer — it sits well below the voice so the words always win. -12 dB let an\n// acoustic bed crowd the VO; -20 keeps it firmly in the background (and the bed is\n// additionally sidechain-ducked under the voice, see buildSfxMusic).\nconst MUSIC_BED_GAIN_DB = -20;\n// Native b-roll ambient sits even deeper than the music bed — it's world tone, a\n// texture under everything, not a foreground layer (opt-in via opts.ambient).\nexport const AMBIENT_BED_GAIN_DB = -20;\n\n/**\n * The emotional arc across scenes for the music bed — so the bed rises/settles with\n * the message. We deliberately do NOT feed the spoken script in: `elevenlabs/music-v1`\n * is vocal-capable, and handing it the ad's words made it SING them over the\n * voiceover. The bed is an instrumental texture shaped to the arc, nothing more — the\n * voice carries the words (and `force_instrumental` is set on the node).\n */\nfunction musicArcDigest(blueprint: VideoBlueprint): string {\n const roles = blueprint.scenes.map((s) => s.narrative_role).filter((r): r is string => Boolean(r));\n const arc = roles.length > 0 ? roles.join(\" → \") : \"\";\n return arc\n ? `\\n\\nEmotional arc across scenes: ${arc}. Shape the bed's energy to this arc, swelling on the payoff. Purely instrumental — no vocals, no singing, no spoken words.`\n : \"\";\n}\n\n/**\n * The music-bed generation prompt, conditioned on the ad's own script + emotional\n * arc so the bed fits the message. When the deconstruct identified the real reference\n * track (via AudD), also style the bed after its vibe — but NEVER reproduce it (that\n * would be a copyright lift); we generate original music that matches mood/tempo/energy.\n */\nfunction musicBedPrompt(blueprint: VideoBlueprint, musicPrompt: string): string {\n const digest = musicArcDigest(blueprint);\n const track = blueprint.global?.music?.identified_track;\n const title = track?.title?.trim();\n const vibe = title\n ? `\\n\\nReference vibe: the original used \"${title}\"${track?.artist?.trim() ? ` by ${track.artist.trim()}` : \"\"} (identified via AudD). Match its mood, tempo, and energy with ORIGINAL music — do not reproduce the track.`\n : \"\";\n return `${musicPrompt}${digest}${vibe}`;\n}\n\n// `end_s`/`kind` are carried internally for timeline reasoning (overlap checks,\n// lip-sync audio routing); only `slot`/`start_s`/`gain_db` reach the emitted\n// audio_timeline params (its track schema is strict).\nexport type AudioTrack = {\n slot: string;\n ref: string;\n start_s: number;\n end_s?: number;\n // Hard cap on the clip's length in the mix (audio_timeline atrim) — used to bound\n // a converted voice track to the timeline so an oversized STS return can't leak.\n duration_s?: number;\n gain_db?: number;\n kind?: TrackKind;\n};\ntype TrackKind = \"vo\" | \"sfx\" | \"music\" | \"ambient\";\n\n/** Build the SFX and music nodes; return their tracks (music ducked under the voices). */\nexport function buildSfxMusic(blueprint: VideoBlueprint, clock: SpineClock, nodes: NodeDecl[]): AudioTrack[] {\n const tracks: AudioTrack[] = [];\n\n // SFX: one node per scene sound-effect event, placed on the spine clock.\n blueprint.scenes.forEach((scene, i) => {\n (scene.sfx ?? []).forEach((sfx, k) => {\n const text = sfx.sound_effect_prompt ?? sfx.description;\n if (!text) return;\n const id = ids.sfx(i, k);\n const params: Record<string, unknown> = { model: FIXED_SFX_MODEL, text };\n // Clamp to the provider range so the emitted canvas self-validates.\n if (typeof sfx.duration_s === \"number\") params.duration_seconds = Math.min(Math.max(sfx.duration_s, 0.5), 30);\n nodes.push({ id, type: \"sound_effect\", params });\n tracks.push({\n slot: `sfx_s${i}_${k}`,\n ref: ref(id, \"audio\"),\n start_s: clock.map(i, sfx.at_s ?? scene.start_s ?? 0),\n kind: \"sfx\",\n });\n });\n });\n\n const musicPrompt = blueprint.global?.music?.music_prompt;\n if (musicPrompt) {\n const total = clock.totalS;\n // The bed NEVER plays over the hook — the opening line is the scroll-stopper and\n // it must read clean. Start no earlier than the end of scene 1 (the hook window),\n // and honor a later reference entry point if the original came in even later. Only\n // the remaining span is generated, so the timing — and the cost — match.\n const hookEnd = clock.startOf(1);\n const refStart = blueprint.global?.music?.starts_at_s;\n const startAt = Math.min(\n Math.max(refStart != null ? clock.mapAbs(refStart) : 0, hookEnd),\n Math.max(total - 0.5, 0),\n );\n const totalMs = Math.round((total - startAt) * 1000);\n // Clamp to the validated range so very long sources still scaffold; the\n // audio_timeline pads/trims the bed to the real length anyway.\n const musicMs = Math.min(Math.max(totalMs, 3000), ELEVENLABS_MAX_MUSIC_LENGTH_MS);\n nodes.push({\n id: ids.musicBed,\n type: \"music\",\n // force_instrumental: the model is vocal-capable; without this it can SING the\n // mood (and feeding it the script made it sing the ad). The voice owns the words.\n params: {\n model: FIXED_MUSIC_MODEL,\n prompt: musicBedPrompt(blueprint, musicPrompt),\n music_length_ms: musicMs,\n force_instrumental: true,\n },\n });\n // Background level (-20 dB) AND sidechain-ducked under the voice in audio_mix, so\n // the bed drops further whenever the creator speaks and recovers in the gaps.\n tracks.push({\n slot: \"music\",\n ref: ref(ids.musicBed, \"audio\"),\n start_s: startAt,\n gain_db: MUSIC_BED_GAIN_DB,\n kind: \"music\",\n });\n }\n\n return tracks;\n}\n","/** The step-by-step next-steps guide embedded in the canvas (and printed by the command). */\nexport const VIDEO_GUIDE = [\n \"Scaffolded by `baker canvas scaffold-video` — a runnable reproduction of your reference video, built like an editing timeline. It is a sequence of clear SHOTS separated at COMPLETE BREAKS (hard cuts): two adjacent presenter shots at a cut are TWO clips, never glued into one take. What stays continuous is the VOICE — a voiceover narration is ONE read across the b-roll it plays over, and a b-roll CUTAWAY between two on-camera moments leaves the presenter shot continuous with the insert sliced in — and each person keeps ONE brand voice (all their clips' native audio re-voiced in a single per-speaker pass), so timbre holds across the cuts. A presenter shot is ONE Seedance clip (native lip-sync + audio); a pure-voiceover stretch is one ElevenLabs tts read; a sub-2s flash is a still hold. A single shot too long for one clip splits into takes that share a boundary frame — the spine drops the duplicated frame (`--seam-dedup head|tail|off`). Every clip gets a CLEAN-PLATE start AND end keyframe (no baked text), RECAST to your dropped reference assets — Seedance interpolates real in-shot motion between them. Each frame grounds only on its own extracted frame + el_* slots (never another generated frame), so all frames render in PARALLEL (no cross-frame cascade). A SPLIT-SCREEN / PICTURE-IN-PICTURE / KEYED-PRESENTER scene is reproduced as one clip PER REGION, stacked or overlaid (see `metadata.todo.composition`). On-screen text/graphics are a separate HTML overlay layer you paint; audio is the voice + SFX + a ducked music bed, normalized stereo. It is a STARTING POINT, not a locked render: add, delete, reorder, split, merge, or re-time scenes freely — see `metadata.todo.full_flexibility`.\",\n \"\",\n \"WHAT TO DO NEXT:\",\n \"0. RE-CRAFT THE SCRIPT FIRST (don't clone). This reference already won in-market, but copying a video is much harder than a static: the hook is targeting and may not transfer, and the message must become TRUE for our brand. Work the `metadata.todo.script_recraft` checklist — for each scene judge its role (hook/body/CTA), decide keep/cut/reorder/replace, and re-author every line for OUR customer's pain + OUR offer. See `references/script-craft.md` (hook/body/CTA framework) and the `meta-ads-playbook` skill. Most of the work lives here.\",\n \"1. Edit each frame's prompt IN PLACE. Every `s<i>_start` keyframe node has its OWN self-contained `params.prompt` (the FRAME DESCRIPTION) — editing one changes only that frame. Rewrite the cast, product, claims, palette into the ad you want. The frame is RECAST to the el_* reference images you drop (the source ad's people are never reused), so describe pose/action/framing here and let the references carry identity.\",\n \"1b. STORYBOARD FIRST — align the look on the cheap stills before clips bill. Each scene's keyframe IS your storyboard; `metadata.video.motion_board` lays out each scene's frame, time window, spoken line, and the graphics scheduled in it. Lock the keyframes + check each graphic lands on its spoken beat, THEN run the clips (images are cheap, videos aren't; the cache re-bills only what you change). See references/video-reproduce.md.\",\n \"2. Fill each `el_*` ingest `[TODO]` path. A PERSON has no slot: they are invented from their description (a candid portrait the sheet is fused from), or played by a company Avatar cast by re-scaffolding with `--avatar <handle>` when the same actor must recur across ads — never a photo of a real person, whose face the image model would reproduce; every other element is ONE real source image. Each is reused across every frame it appears in, so the same identity stays consistent. `baker canvas run` REFUSES to start until every `[TODO]` slot holds a real source — so this is mandatory, not optional.\",\n \"3. Talking heads are NATIVE: a scene with one on-camera speaker is voiced by the video model itself (the line goes in the clip's prompt; models with a `generate_audio` toggle get it set, and the default model always renders audio), so lips and voice are generated together — no separate tts, no post-hoc lip-sync. Edit the line in the scene's `s<i>_clip` prompt to re-author the words TRUE for your brand. Off-camera narration scenes still use a sequenced `tts` per turn.\",\n \"4. Voice consistency: every native talking clip's audio is re-voiced to ONE brand voice via `audio_voice_convert` (timing preserved → lips stay matched). Confirm the `voice_select` casting (one per speaker) — its `voice_id` is the brand voice; set its gender/language so the voice matches the creator.\",\n \"5. Overlays are REAL HTML you paint. Open `video-overlay-composition/index.html`: the reference's overlays are seeded inside `#overlay-root` as plain elements (text + a `.pos-*` class + `data-start`/`data-dur`). Restyle the CSS freely — build lower-thirds, a ticker, whatever the look needs — and replace a logo placeholder with a real `<img>` you source (`baker images icon/sticker/gif/logo`) and drop in that dir. The runtime only shows/hides by timestamp; it makes no styling decisions. Drop `brand-bold.otf` / `brand-regular.otf` there for on-brand type.\",\n \"6. `baker canvas validate` (proves native-audio + timing for free) then `baker canvas run` (generates many billed image/video/audio assets — not free).\",\n \"\",\n \"CRAFT — raises every clip's realism (one-liners; full rationale in references/video-craft.md):\",\n \"- Iterate cheaply, do NOT brute-force takes: credits are scarce. Strong inputs (locked reference + a precise move-by-move prompt) make 1–2 takes land. When a take misses, change the SMALLEST thing and re-run — the cache re-bills only that node. Images are cheap, videos aren't: fix on the frame/reference, not by re-rolling clips.\",\n \"- Keep clips SHORT (trust the scene-length trim — don't pad) and LOCK THE CAMERA: unmotivated AI drift is the top tell.\",\n \"- One generation = one speaking voice — Seedance can't voice two on-camera speakers in one clip; split a two-speaker beat into separate scenes (or one stays silent). Lip-sync follows the line verbatim; carry delivery and emotion in PROSE around the quoted line, never in [brackets] (Seedance renders brackets literally).\",\n \"- Preview cheap → finalize high-res (never prompt the aspect ratio in prose — the pipeline sets it).\",\n \"- Nail the pack shot (final product hero — motivated move, matched light). Geometry drifting? drop a high-angle SCHEMATIC still as an extra reference (a map beats a paragraph). Before/after (dry→wet) = two separate locked references, not words mid-scene.\",\n \"- The hook reads SOUND-OFF: scene 1's frame + overlay carry it in ~1s — don't bury the hook in the spoken line (meta-ads-playbook §39/§48).\",\n \"\",\n \"Tip: `prompt.json` is the deconstruction provenance + the authoritative SHARED AD SPEC for cast identity, palette, brand, and type cohesion. Frames read it through `prompt.style.json`, a DERIVED projection `baker canvas validate`/`run` regenerate from prompt.json automatically — edit prompt.json, never the derived file. The per-frame editing surface is the frame node's own FRAME DESCRIPTION.\",\n \"Production craft: references/video-craft.md. Hook/message/script-structure layer: references/script-craft.md + the meta-ads-playbook skill.\",\n].join(\"\\n\");\n","import {\n BlueprintFloatingElementSchema,\n BlueprintOverlaySchema,\n type VideoBlueprint,\n type VideoScene,\n} from \"@baker/canvas-contract\";\nimport { z } from \"zod\";\nimport type { NodeDecl } from \"../../schema/canvas.ts\";\nimport { sceneRole } from \"../lib/scene-role.ts\";\nimport type { ElementSlot } from \"./elements.ts\";\nimport { ids } from \"./ids.ts\";\nimport type { SceneRoute, TalkScene, VoSeg } from \"./timeline-env.ts\";\nimport { SEEDANCE_CEILING_S, type SpineClock, sceneDurationS } from \"./timing.ts\";\n\n/** The per-scene route map + node histogram stamped into `metadata.video.graph_stats`. */\nfunction buildGraphStats(\n blueprint: VideoBlueprint,\n routes: Map<number, SceneRoute>,\n nodes: NodeDecl[],\n ceilingS: number,\n) {\n const histogram: Record<string, number> = {};\n for (const n of nodes) histogram[n.type] = (histogram[n.type] ?? 0) + 1;\n const billable = nodes.filter((n) => n.type === \"image_generate\" || n.type === \"video_generate\").length;\n return {\n nodes_total: nodes.length,\n nodes_billable: billable,\n node_types: histogram,\n scene_routes: blueprint.scenes.map((scene, i) => ({\n scene: i,\n route: routes.get(i) ?? \"clip\",\n window_s: Math.round(sceneDurationS(scene, ceilingS) * 100) / 100,\n })),\n };\n}\n\n/**\n * The static timing plan the validator proves: VO segments (no overlap, audio ≈ video\n * length) and talking scenes (each presenter phrase / composite presenter has a\n * native-audio clip + an `audio_voice_convert` node). Computed by `buildTimeline`.\n */\nexport function buildVideoMeta(\n blueprint: VideoBlueprint,\n clock: SpineClock,\n ceilingS: number,\n meta: { vo_segments: VoSeg[]; talking_scenes: TalkScene[]; routes: Map<number, SceneRoute> },\n slots: ElementSlot[],\n nodes: NodeDecl[],\n hasAudioMix: boolean,\n) {\n return {\n // WHY the graph has the nodes it has: one route per scene (the dispatcher's own\n // record) + a node-type histogram. The first thing to read when a canvas looks big.\n graph_stats: buildGraphStats(blueprint, meta.routes, nodes, ceilingS),\n // The SPINE length (Σ scene durations) — what the picture and the mix are pinned to.\n duration_s: clock.totalS,\n // The one-clock contract the validator enforces on the LIVE graph: the spine's\n // summed clip lengths and every audio timeline's total_ms must agree with this.\n timeline: {\n spine_node: ids.spine,\n expected_total_s: clock.totalS,\n ...(hasAudioMix ? { audio_mix_node: ids.audioMix } : {}),\n },\n vo_segments: [...meta.vo_segments]\n .sort((a, b) => a.start_s - b.start_s)\n .map(({ onCamera: _onCamera, ...seg }) => seg),\n talking_scenes: meta.talking_scenes,\n lip_sync_caution: buildLipSyncCaution(meta.vo_segments),\n motion_board: buildMotionBoard(blueprint),\n // The wired recurring-element registry (the reference-completeness check reads\n // `ref`/`label`/`type` to warn when a frame describes an element it doesn't wire).\n elements: slots.map((s) => ({\n ref: s.ref,\n label: s.label,\n type: s.type,\n ...(s.description ? { description: s.description } : {}),\n })),\n clip_spans: buildClipSpans(blueprint, nodes),\n };\n}\n\n/**\n * Per generated `video_generate` node, the natural visual span of the scene it\n * renders (from the blueprint, before any model-duration clamping). The validator\n * compares each against the assigned video model's max clip duration and warns when a\n * span can't fit — e.g. a 9.2s scene on Veo (8s cap), which would truncate. The scene\n * index is the one the clip was tagged with when it was emitted.\n */\nfunction buildClipSpans(blueprint: VideoBlueprint, nodes: NodeDecl[]): Array<{ node: string; span_s: number }> {\n const spans: Array<{ node: string; span_s: number }> = [];\n for (const n of nodes) {\n if (n.type !== \"video_generate\" || n.tags?.scene === undefined) continue;\n const scene = blueprint.scenes[n.tags.scene];\n if (!scene) continue;\n // Seedance's ceiling, not the model's: this is the span the validator measures\n // against the model's max, and clamping it to that max first would hide the warning.\n spans.push({ node: n.id, span_s: Math.round(sceneDurationS(scene, SEEDANCE_CEILING_S) * 100) / 100 });\n }\n return spans;\n}\n\n/**\n * Flag scenes where a presenter's lips may NOT match the audio. A single held shot\n * can host only ONE native (lip-synced) clip — voiceover turns must not overlap, and\n * Seedance generates one continuous clip per shot — so when the SAME on-camera speaker\n * has more turns in that shot (a rapid back-and-forth: \"3000?\" … \"4000?\" with an\n * off-camera \"Plus\" between), the first turn is lip-synced but the rest play as `tts`\n * over the same clip, where the mouth is no longer saying those words. This is an\n * inherent limit of reproducing sparse same-shot dialogue, not a wiring bug. We can't\n * fix it without overlapping audio (breaks the no-overlap invariant) or cutting the\n * held shot into per-turn clips (visible camera jumps). So we SURFACE it: each flagged\n * scene's burned-in captions already show the spoken words, but the agent may prefer to\n * cut away to b-roll over those `tts` lines, or accept the captions carry them.\n */\nfunction buildLipSyncCaution(segments: VoSeg[]): Array<{ scene: number; speaker: string; tts_over_native: string[] }> {\n const out: Array<{ scene: number; speaker: string; tts_over_native: string[] }> = [];\n const byScene = new Map<number, VoSeg[]>();\n for (const s of segments) {\n const arr = byScene.get(s.scene) ?? [];\n arr.push(s);\n byScene.set(s.scene, arr);\n }\n for (const [scene, segs] of [...byScene.entries()].sort((a, b) => a[0] - b[0])) {\n // The speaker(s) lip-synced in this scene (their own on-camera voice).\n const nativeSpeakers = new Set(segs.filter((s) => s.onCamera).map((s) => s.speaker));\n for (const speaker of nativeSpeakers) {\n const ttsOver = segs.filter((s) => !s.onCamera && s.speaker === speaker).map((s) => s.slot);\n if (ttsOver.length > 0) out.push({ scene, speaker, tts_over_native: ttsOver });\n }\n }\n return out;\n}\n\n/** The spoken line(s) inside one scene's window, joined — for the motion board. */\nfunction sceneSpokenText(scene: VideoScene): string | null {\n return (\n (scene.dialogue ?? [])\n .map((d) => d.line?.trim())\n .filter((l): l is string => Boolean(l))\n .join(\" \") || null\n );\n}\n\n/**\n * The MOTION BOARD — the reviewable map of \"which graphic fires on which spoken\n * beat\", built from data the scaffold already computes. Per scene it pairs the\n * scene's time window + its spoken line with every overlay/floating graphic\n * scheduled inside it (and that graphic's absolute `at_s`). Review it BEFORE\n * rendering so each overlay lands on the word it's meant to punctuate — the\n * \"anchor every graphic to a spoken word\" discipline. The scene's keyframe\n * (`s<i>_start`) is this board's STORYBOARD: a cheap, cached still to align look on\n * before clips bill. See references/video-reproduce.md.\n */\nfunction buildMotionBoard(blueprint: VideoBlueprint) {\n const round = (n: number) => Math.round(n * 100) / 100;\n let cursor = 0;\n return blueprint.scenes.map((scene, i) => {\n const start_s = scene.start_s ?? cursor;\n const end_s = scene.end_s ?? start_s + sceneDurationS(scene, SEEDANCE_CEILING_S);\n cursor = end_s;\n const spoken = sceneSpokenText(scene);\n const overlays = z.array(BlueprintOverlaySchema).safeParse(scene.overlays ?? []);\n const floats = z.array(BlueprintFloatingElementSchema).safeParse(scene.floating_elements ?? []);\n const graphics = [\n ...(overlays.success ? overlays.data : [])\n .filter((ov) => ov.text?.trim())\n .map((ov) => ({\n kind: \"text\" as const,\n at_s: round(ov.appears_at_s ?? start_s),\n dur_s: round(ov.duration_s ?? 2.5),\n position: ov.position ?? \"bottom_center\",\n text: ov.text?.trim(),\n })),\n ...(floats.success ? floats.data : []).map((fe) => ({\n kind: \"graphic\" as const,\n at_s: round(fe.appears_at_s ?? start_s),\n dur_s: round(fe.duration_s ?? 2.5),\n position: fe.position ?? \"bottom_center\",\n label: fe.brand_name || fe.what_it_represents || fe.description || fe.kind || \"element\",\n })),\n ].sort((a, b) => a.at_s - b.at_s);\n return {\n scene: i,\n role: sceneRole(scene.narrative_role, i, blueprint.scenes.length),\n window_s: [round(start_s), round(end_s)] as [number, number],\n // A continuation b-roll scene shares the previous scene's end frame as its start\n // (no own `s<i>_start` node), so point the storyboard at that shared keyframe.\n storyboard_frames: [scene.continues_previous && i > 0 ? ids.frame(i - 1, \"end\") : ids.frame(i, \"start\")],\n spoken,\n graphics,\n };\n });\n}\n","import type { ClipIntent } from \"../../lib/prompt-profiles.ts\";\n\n/**\n * Where a scene sits in an ad's persuasion arc, read the three ways the scaffolds need it.\n *\n * One module because the three readings are one idea: the first beat stops the scroll, the\n * last asks for the click, the middle carries the argument. They differ only in what the\n * middle is called and in what a declared role may override, and each difference is a\n * decision a consumer depends on — kept as named functions here rather than re-derived at\n * each call site, where a reproduction and an authored ad had drifted into three spellings.\n */\n\n/** A beat's place in the arc, from its position alone. */\nexport type ArcPosition = \"hook\" | \"body\" | \"cta\";\n\n/**\n * The arc read off position. A one-scene video's only scene is the CTA, not a hook: there\n * is nothing after it for a hook to open.\n */\nexport function positionalRole(index: number, total: number): ArcPosition {\n if (index === 0 && total > 1) return \"hook\";\n if (index === total - 1) return \"cta\";\n return \"body\";\n}\n\n/**\n * A reproduced scene's role: the deconstruct's `narrative_role` when it named one (free text,\n * kept verbatim), else its position. Drives the script re-craft checklist and the motion board.\n */\nexport function sceneRole(narrativeRole: string | undefined, index: number, total: number): string {\n return narrativeRole?.trim() || positionalRole(index, total);\n}\n\n/**\n * An authored beat's role (`scaffold-ad`): positional, because it is positional in every ad\n * of that shape, with the middle split into the problem it raises and the proof that answers\n * it. The first beat is the hook whatever the length — an authored ad always opens on one.\n */\nexport function authoredRole(index: number, total: number): \"hook\" | \"problem\" | \"proof\" | \"cta\" {\n if (index === 0) return \"hook\";\n const role = positionalRole(index, total);\n if (role !== \"body\") return role;\n return index < total / 2 ? \"problem\" : \"proof\";\n}\n\n/** Whether a declared role marks the closing call to action. Exact, not a substring: see `clipIntent`. */\nexport function isCtaRole(narrativeRole: string | undefined): boolean {\n return narrativeRole?.trim() === \"cta\";\n}\n\n/**\n * The persuasion INTENT of a clip, used to key the per-intent param recipe\n * (`clipParamRecipe`). Scene 0 is always the hook; a scene whose `narrative_role`\n * reads as the reveal/hero/product beat earns the cine ceiling, as does one the\n * deconstruct saw moving hard; the CTA beat is its own class; everything else is body.\n * Kept deliberately tolerant — the role is free text from deconstruct, so this\n * matches on substrings.\n */\nexport function clipIntent(narrativeRole: string | undefined, index: number, motionLevel?: string): ClipIntent {\n if (index === 0) return \"hook\";\n const role = (narrativeRole ?? \"\").toLowerCase();\n if (/\\bcta\\b|call to action|offer/.test(role)) return \"cta\";\n if (/hero|reveal|product|payoff|transformation|result/.test(role) || motionLevel === \"dynamic\") return \"hero\";\n return \"body\";\n}\n","import type { CompositionRegion } from \"@baker/canvas-contract\";\nimport { ref } from \"../ids.ts\";\nimport { commentSafe } from \"../overlay-html.ts\";\nimport type { SceneCtx } from \"../timeline-env.ts\";\n\n/**\n * A scene whose picture is a REAL surface the operator supplies (a screen, a designed\n * panel): a `[TODO]` ingest (so the placeholder gate forces it before a billed run), held\n * for the scene length on the spine. NO image_generate / video_generate is emitted, so the\n * model can never paint garbled UI text or a baked sticker.\n *\n * One surface = ONE ingest: consecutive scenes the deconstruct verified as the SAME surface\n * (a shared `surface_id` — e.g. a 3-scene import flow) reuse a single ingest\n * (`env.surfaceIngests`), so the operator supplies it exactly ONCE instead of dropping the\n * same capture into a dozen back-to-back `[TODO]`s (the \"13 identical screen refs\" waste).\n * Distinct surfaces stay distinct.\n */\nexport function emitSurfaceStill(\n ctx: SceneCtx,\n surface: { id: string; fallbackLabel: string; todo: (label: string) => string },\n): void {\n const { scene, env } = ctx;\n const regions = (scene.composition?.regions ?? []).filter(\n (r): r is CompositionRegion => Boolean(r) && typeof r === \"object\",\n );\n const surfaceId = regions.find((r) => r.surface_id)?.surface_id;\n let refId = surfaceId ? env.surfaceIngests.get(surfaceId) : undefined;\n if (!refId) {\n const label = commentSafe((scene.summary || scene.start_frame_prompt || surface.fallbackLabel).slice(0, 120));\n refId = surface.id;\n ctx.out.nodes.push({\n id: refId,\n type: \"ingest\",\n params: { source: \"path\", path: surface.todo(label), expect: \"image\" },\n });\n if (surfaceId) env.surfaceIngests.set(surfaceId, refId);\n }\n // Fit-PADDED on the spine's per-input chain — a real screen/designed graphic must\n // never be cropped (cropping slices UI chrome and designed typography).\n ctx.out.clips.push({\n ref: ref(refId, \"asset\"),\n scene_s: ctx.lengths.dur,\n out: ctx.lengths.out,\n still: { fit: \"pad\" },\n });\n}\n","import type { CompositionRegion, VideoBlueprint, VideoScene } from \"@baker/canvas-contract\";\nimport { ids } from \"../ids.ts\";\nimport type { SceneCtx } from \"../timeline-env.ts\";\nimport { emitSurfaceStill } from \"./surface-still.ts\";\n\nfunction regionsOf(scene: VideoScene): CompositionRegion[] {\n return (scene.composition?.regions ?? []).filter((r): r is CompositionRegion => Boolean(r) && typeof r === \"object\");\n}\n\n/** Every region is designed graphics (some static_graphic, no camera feed at all) —\n * no one can be lip-synced on screen, so any dialogue here is voiceover by definition. */\nexport function sceneIsAllGraphic(scene: VideoScene): boolean {\n const regions = regionsOf(scene);\n if (regions.length === 0 || regions.some((r) => (r.kind ?? \"\").toLowerCase() === \"camera\")) return false;\n return regions.some((r) => (r.kind ?? \"\").toLowerCase() === \"static_graphic\");\n}\n\n/**\n * The full set of scenes rendered as a designed-graphic plate — a FULL-FRAME designed\n * graphic (meme collage, statue-with-logo card, animated marketing art) the deconstruct\n * typed a `static_graphic` region on. Generating one garbles wordmarks (the retro \"Google!\"\n * logo) and loses the designed look; the plate is the REAL design asset (or a brand-HTML\n * rebuild), with text/logos riding the overlay layer.\n *\n * The composition is the authority (it is frame-verified by the continuity checker);\n * element PRESENCE lists are transition-frame-noisy — the presenter \"present\" at a graphic\n * scene because the previous shot's last frames bleed in must not re-route the designed\n * panel to generation. No camera region ⇒ nobody is on screen, so a pip collage that\n * nests the presenter stays on the composite/stub path.\n *\n * Closed over `continues_previous` chains. One physical take is ONE content class —\n * Pass-2 routinely types a graphic's 0.6s transition tail but not its 4.5s body, and\n * splitting one take across Seedance and a real plate is visibly incoherent. Propagation\n * is blocked into a scene that shows a camera feed (a camera region, or an explicitly\n * on-camera dialogue line): a mistagged chain must never swallow a presenter shot.\n */\nexport function fullFrameGraphicScenes(blueprint: VideoBlueprint): Set<number> {\n const scenes = blueprint.scenes;\n const graphic = new Set<number>(scenes.flatMap((s, i) => (sceneIsAllGraphic(s) ? [i] : [])));\n const blocked = (s: VideoScene): boolean => {\n if (regionsOf(s).some((r) => (r.kind ?? \"\").toLowerCase() === \"camera\")) return true;\n return (s.dialogue ?? []).some((d) => d.on_camera === true);\n };\n let changed = true;\n while (changed) {\n changed = false;\n scenes.forEach((s, i) => {\n if (graphic.has(i)) return;\n const chainsToPrev = s.continues_previous && graphic.has(i - 1);\n const next = scenes[i + 1];\n const chainsToNext = Boolean(next?.continues_previous) && graphic.has(i + 1);\n if ((chainsToPrev || chainsToNext) && !blocked(s)) {\n graphic.add(i);\n changed = true;\n }\n });\n }\n return graphic;\n}\n\n/**\n * The `graphic_plate` route: like the screen route, but for a designed graphic panel — the\n * operator supplies or rebuilds the REAL design, with no screenshot instruction (there is\n * no live page).\n */\nexport function emitGraphicScene(ctx: SceneCtx): void {\n emitSurfaceStill(ctx, {\n id: ids.graphicRef(ctx.index),\n fallbackLabel: \"the designed panel\",\n todo: (label) =>\n `[TODO: supply the real designed graphic for \"${label}\" — never AI-generate a designed panel (its typography/wordmarks garble). Rebuild it as brand HTML in video-overlay-composition (the scene's text/logos are already seeded there), export the design from the brand kit, or source stock art; text rides the overlay layer, not this plate. Wire it in as a path relative to this canvas file, never an absolute path]`,\n });\n ctx.out.routes.set(ctx.index, \"graphic_plate\");\n}\n","import type { VideoBlueprint } from \"@baker/canvas-contract\";\nimport type { ElementSlot } from \"../elements.ts\";\nimport type { Edge } from \"../ids.ts\";\n\n// Speaker labels that mean \"narration over the picture,\" never a mouth on screen.\n// Used to decide whether a scene's talking subject should be lip-synced — and, in\n// `collapseVoiceover`, folded into a lone on-camera presenter as the same person's\n// off-camera narration. Adding a label here therefore also makes it foldable: never add one\n// a caller uses to mean a genuinely SECOND voice.\nconst NARRATOR_SPEAKERS = new Set([\n \"voiceover\",\n \"voice_over\",\n \"narrator\",\n \"narration\",\n \"vo\",\n \"announcer\",\n \"off_screen\",\n \"offscreen\",\n \"off-screen\",\n]);\n\n/** Whether the video uses on-screen mouths at all (vs pure narration over picture). */\nexport function onCameraDialogue(blueprint: VideoBlueprint): boolean {\n const mode = blueprint.global?.voiceover?.mode;\n return mode !== \"voiceover\" && mode !== \"none\";\n}\n\n/** Whether the source ad has a person in it anywhere: a deconstructed cast, or a recurring person element. */\nexport function sourceShowsPeople(blueprint: VideoBlueprint, slots: ElementSlot[]): boolean {\n return (blueprint.global?.cast ?? []).length > 0 || slots.some((s) => s.type.toLowerCase() === \"person\");\n}\n\nexport const castIdSet = (blueprint: VideoBlueprint): Set<string> =>\n new Set((blueprint.global?.cast ?? []).map((c) => c.id).filter((id): id is string => Boolean(id)));\n\n/** A speaker is \"on camera\" when the video shows mouths and the speaker is a named cast member. */\nexport function isOnCameraSpeaker(speaker: string, casts: Set<string>, cameraOn: boolean): boolean {\n if (!cameraOn) return false;\n if (NARRATOR_SPEAKERS.has(speaker.toLowerCase())) return false;\n return casts.has(speaker);\n}\n\n/**\n * \"Is the presenter actually ON SCREEN in this scene?\" — distinct from \"is the\n * presenter speaking\". A speaker is a cast member for their whole phrase, but the ad\n * often CUTS AWAY to b-roll (a product, a text card) while they keep narrating. We\n * decide visibility from the presenter ELEMENT's per-scene presence, not the speaker\n * label: only a scene where the element appears may slice its window from the talking\n * clip; a scene where the speaker narrates but the element is absent is b-roll.\n * Matches by `cast_id` when the deconstruct linked one, else falls back to the sole\n * `person` element (the single-presenter case). No presence info ⇒ don't constrain.\n */\nexport function makePresenterPresent(\n slots: ElementSlot[],\n canonical: (s: string) => string,\n // strict = no \"sole person\" fallback and no \"no person slots → assume present\"\n // default. Used to decide whether a SPECIFIC speaker is genuinely on screen (so an\n // OFF-camera voice in a one-presenter scene is NOT counted as a second on-camera\n // speaker). The lenient default keeps the slicing logic working when the deconstruct\n // links no element to a clearly-present presenter.\n opts: { strict?: boolean } = {},\n): (speaker: string, sceneIndex: number) => boolean {\n const personSlots = slots.filter((s) => s.type.toLowerCase() === \"person\");\n const bySpeaker = new Map<string, Map<number, Set<Edge>>>();\n for (const slot of personSlots) if (slot.castId) bySpeaker.set(canonical(slot.castId), slot.presence);\n const solePerson = !opts.strict && personSlots.length === 1 ? (personSlots[0] as ElementSlot).presence : null;\n return (speaker, sceneIndex) => {\n const presence = bySpeaker.get(speaker) ?? solePerson;\n if (!presence) return !opts.strict;\n return presence.has(sceneIndex);\n };\n}\n\n/**\n * One person = one VOICE. The deconstruct sometimes labels the same person's on-camera\n * lines `creator_1` and their off-camera narration `voiceover`. When there is exactly\n * one on-camera presenter, fold narrator labels into that presenter so both resolve to\n * a single voice. (Primary fix is the deconstruct prompt; this is the scaffold safety\n * net for older/mislabeled blueprints.) Returns a speaker → canonical-speaker map fn.\n *\n * A caller that needs two speakers to STAY two — a scaffolded ad, where a cutaway beat is\n * its own shot rather than an insert inside a continuous read — must not name its narrator\n * with one of these labels, because this fold cannot tell that case from the one it exists\n * for. `AD_NARRATOR_ID` is what that looks like: a narrator named so it is nobody's\n * mislabelled second voice.\n */\nexport function collapseVoiceover(blueprint: VideoBlueprint): (speaker: string) => string {\n const casts = castIdSet(blueprint);\n const cameraOn = onCameraDialogue(blueprint);\n const presenters = new Set<string>();\n for (const scene of blueprint.scenes)\n for (const l of scene.dialogue ?? []) {\n const sp = l.speaker ?? \"voiceover\";\n if (isOnCameraSpeaker(sp, casts, cameraOn)) presenters.add(sp);\n }\n const [presenter] = presenters;\n if (presenters.size !== 1 || presenter === undefined) return (s) => s;\n return (speaker) => (NARRATOR_SPEAKERS.has(speaker.toLowerCase()) ? presenter : speaker);\n}\n","import type { BlueprintDialogueLine, VideoBlueprint } from \"@baker/canvas-contract\";\nimport { estSpeechS } from \"../../../lib/speech.ts\";\nimport { sceneIsAllGraphic } from \"../routes/graphic-plate.ts\";\nimport { PHRASE_MAX_S } from \"../timing.ts\";\nimport { castIdSet, isOnCameraSpeaker, onCameraDialogue } from \"./speakers.ts\";\n\n// --- PHRASE/SHOT MODEL: one clip per real SHOT, separated at COMPLETE BREAKS. ---\n//\n// A PHRASE is one clip. The reference is a sequence of clear shots with complete breaks\n// (hard cuts) between them, and that is what the scaffold separates by: two adjacent SHOWN\n// presenter shots at a hard cut become TWO clips, never glued into one invented take just\n// because the speech is continuous. What stays continuous: a VOICEOVER narration is ONE\n// read across the b-roll it plays over, and a b-roll CUTAWAY between two shown scenes leaves\n// the presenter shot continuous (the shown scenes aren't adjacent — the insert is sliced in,\n// the voice plays under it). A presenter-shown phrase is ONE Seedance clip (native lip-sync\n// + audio) voice-converted to the brand voice; a phrase shown NOWHERE is one ElevenLabs\n// `tts` read. A single shot longer than the clip ceiling splits into contiguous takes that\n// share a boundary frame (the spine seam-dedups the duplicate). Composite scenes voice on\n// their own (they break a phrase run).\n\n// Two of a voice's lines closer than this are one breath — kept in one continuous read.\nconst PAUSE_GAP_S = 0.6;\n\n/**\n * True when this SHOWN line starts a new clip because it is a COMPLETE BREAK from the run's\n * current shot: it is on camera, the run already showed a presenter, and its scene is the one\n * IMMEDIATELY after the last shown scene while NOT a `continues_previous` continuation — a\n * hard cut between two distinct presenter shots. A cutaway (a b-roll insert between the two\n * shown scenes) leaves them non-adjacent, so this is false and the shots stay one continuous\n * clip with the insert sliced in. Pure.\n */\nfunction isAdjacentShownCut(\n ln: { shown: boolean; sceneIndex: number },\n lastShownScene: number | null,\n scenes: VideoBlueprint[\"scenes\"],\n): boolean {\n if (!ln.shown || lastShownScene === null) return false;\n return ln.sceneIndex === lastShownScene + 1 && scenes[ln.sceneIndex]?.continues_previous !== true;\n}\n\n/** The running phrase state the break decision reads (a subset of the buildPhrases accumulator). */\ntype PhraseBreakState = {\n speaker: string;\n end: number;\n coverEnd: number;\n clipStart: number;\n lastShownScene: number | null;\n};\n\n/**\n * Whether `ln` starts a NEW phrase/clip rather than extending `cur`: a speaker change, a real\n * audio pause, a complete break between two adjacent shown shots, or the run passing the\n * Seedance clip ceiling (a length-split). See buildPhrases for the full rationale. Pure.\n */\nfunction breaksPhrase(\n cur: PhraseBreakState,\n ln: { speaker: string; shown: boolean; sceneIndex: number; start: number },\n lineCover: number,\n lineClipStart: number,\n scenes: VideoBlueprint[\"scenes\"],\n): boolean {\n return (\n cur.speaker !== ln.speaker ||\n ln.start - cur.end > PAUSE_GAP_S ||\n isAdjacentShownCut(ln, cur.lastShownScene, scenes) ||\n Math.max(cur.coverEnd, lineCover) - Math.min(cur.clipStart, lineClipStart) > PHRASE_MAX_S\n );\n}\n\n// The deconstruct anchors scenes to visual shot cuts, so a sentence sliced mid-word\n// gets its boundary words transcribed into BOTH adjacent scenes. Joining verbatim makes\n// the presenter stutter the seam (\"…en téléconsultation en téléconsultation 7J/7\").\n// Cap the dedup window: a longer repeat is deliberate rhetoric, not a boundary artifact.\nconst JOIN_DEDUP_MAX_WORDS = 4;\n\n/** A word normalized for boundary comparison only (case/punctuation-insensitive). */\nfunction joinKey(word: string): string {\n return word.toLowerCase().replace(/[^\\p{L}\\p{N}]+/gu, \"\");\n}\n\n/**\n * Join a phrase's dialogue lines, deduping the words the deconstruct duplicated across\n * a scene boundary: when the next line OPENS with the same 1–4 words the previous line\n * CLOSED with (compared case/punctuation-insensitively), the duplicate opening is\n * dropped. Pure.\n */\nexport function joinDialogueTexts(texts: string[]): string {\n const out: string[] = [];\n for (const text of texts) {\n const prev = out[out.length - 1];\n if (!prev) {\n out.push(text);\n continue;\n }\n const prevWords = prev.split(/\\s+/).filter(Boolean);\n const nextWords = text.split(/\\s+/).filter(Boolean);\n let overlap = 0;\n const maxK = Math.min(JOIN_DEDUP_MAX_WORDS, prevWords.length, nextWords.length);\n for (let k = maxK; k >= 1; k--) {\n const tail = prevWords.slice(-k).map(joinKey).join(\" \");\n const head = nextWords.slice(0, k).map(joinKey).join(\" \");\n if (tail && tail === head) {\n overlap = k;\n break;\n }\n }\n const rest = nextWords.slice(overlap).join(\" \");\n if (rest) out.push(rest);\n }\n return out.join(\" \");\n}\n\nexport type Phrase = {\n speaker: string;\n start_s: number;\n end_s: number;\n text: string;\n // The scene index of the phrase's first line (for metadata attribution).\n firstScene: number;\n // Scene indices where this voice is SHOWN on camera (their video is sliced from the\n // phrase clip). Empty ⇒ pure-b-roll phrase (no presenter clip; tts voice).\n shownScenes: number[];\n presenterShown: boolean;\n};\n\n/**\n * Fold a phrase with no shot of its own into the one before it, so nothing is READ.\n *\n * A phrase claims the scenes it is shown in; a later phrase whose scenes are all taken\n * gets no clip, and the engine falls back to speaking it with ElevenLabs over the picture.\n * For an avatar that is the wrong trade twice over: the mouth on screen is saying\n * different words (the clip was generated from its own line), and the voice is not theirs.\n * Measured, and the reason this exists: \"ElevenLabs should not generate the audio, because\n * the mouths come out wrong — we have to go all in on the model getting the voice right.\"\n *\n * So the text goes into the clip that DOES own that moment: the model says both lines, one\n * mouth, one voice, no overlay. Only ever applied when the rendered voice is being kept —\n * a genuine voiceover has no mouth to contradict and is still read.\n *\n * Pure, and exported for tests.\n */\nexport function foldUnshownPhrases(phrases: readonly Phrase[], keepRenderedVoice: boolean): Phrase[] {\n if (!keepRenderedVoice) return [...phrases];\n const claimed = new Set<number>();\n const kept: Phrase[] = [];\n for (const phrase of phrases) {\n // A phrase nobody is shown speaking is a genuine VOICEOVER, and it is read — there is\n // no mouth on screen for the words to contradict, which is the entire defect this fold\n // exists to prevent. Folding one moved narration into a presenter's clip and had them\n // say it on camera, words the shot was never generated for. Both docstrings here said\n // so; the code did not, because the `presenterShown` test sat inside the same condition\n // as the scene test and a `false` fell through to the fold. The test that should have\n // caught it used a DIFFERENT speaker, so it passed on the speaker check instead.\n if (!phrase.presenterShown) {\n kept.push(phrase);\n continue;\n }\n const available = phrase.shownScenes.filter((scene) => !claimed.has(scene));\n if (available.length > 0) {\n for (const scene of available) claimed.add(scene);\n kept.push(phrase);\n continue;\n }\n // Backwards to the nearest phrase of the SAME speaker that did get a shot. A different\n // speaker's clip would put these words in somebody else's mouth, which is the defect\n // this is here to avoid, so that phrase is left alone to be read.\n const host = [...kept].reverse().find((candidate) => candidate.speaker === phrase.speaker);\n if (!host) {\n kept.push(phrase);\n continue;\n }\n host.text = joinDialogueTexts([host.text, phrase.text]);\n host.end_s = Math.max(host.end_s, phrase.end_s);\n }\n return kept;\n}\n\n/**\n * Scenes with TWO+ distinct on-camera speakers ACTUALLY ON SCREEN — they can't be one\n * presenter clip (Seedance voices one mouth per clip), so both speakers become tts over a\n * plain (silent) scene clip. The discriminator is on-SCREEN presence, not just \"is a cast\n * member\": a lone presenter trading lines with an OFF-camera voice (an interviewer heard but\n * not shown) must stay NATIVE lip-synced. Element presence refines the set ONLY when there\n * is positive evidence (at least one on-camera speaker explicitly on screen); with no element\n * data we keep the conservative \"every on-camera cast speaker counts\" so a real two-hander\n * still trips the gate. Pure.\n */\nfunction multiSpeakerScenes(\n blueprint: VideoBlueprint,\n casts: Set<string>,\n cameraOn: boolean,\n canonical: (s: string) => string,\n presentStrict: (speaker: string, sceneIndex: number) => boolean,\n): Set<number> {\n const multiSpeaker = new Set<number>();\n blueprint.scenes.forEach((scene, i) => {\n const onCamAll = new Set(\n (scene.dialogue ?? [])\n .map((l) => l.speaker ?? \"voiceover\")\n .filter((sp) => isOnCameraSpeaker(sp, casts, cameraOn)),\n );\n const onCamPresent = [...onCamAll].filter((sp) => presentStrict(canonical(sp), i));\n const effective = onCamPresent.length > 0 ? new Set(onCamPresent) : onCamAll;\n if (effective.size >= 2) multiSpeaker.add(i);\n });\n return multiSpeaker;\n}\n\n/** One spoken line flattened out of the blueprint, tagged with whether its speaker is SHOWN. */\ntype PhraseLine = { sceneIndex: number; speaker: string; shown: boolean; start: number; end: number; text: string };\n\n/**\n * The clip window one line forces the phrase clip to cover: always the spoken end/start, plus\n * — when the line is SHOWN (its video is sliced from the clip) — the whole scene's end/start,\n * so a silent lead-in or tail is still generated. `clipStart`/`cover` feed the ceiling cap. Pure.\n */\nfunction lineClipWindow(ln: PhraseLine, scenes: VideoBlueprint[\"scenes\"]): { cover: number; clipStart: number } {\n if (!ln.shown) return { cover: ln.end, clipStart: ln.start };\n const sc = scenes[ln.sceneIndex];\n const sceneEnd = sc?.end_s ?? sc?.start_s ?? 0;\n return { cover: Math.max(ln.end, sceneEnd), clipStart: Math.min(ln.start, sc?.start_s ?? ln.start) };\n}\n\n/**\n * Flatten every non-composite scene's dialogue into time-sorted lines, tagging each with\n * `shown` (the speaker is a cast member AND actually on screen here, not a cutaway or\n * voiceover). A line with no `end_s` is estimated from its words, NOT the scene end (which\n * would fabricate continuity across a silent b-roll gap and merge two separate phrases). Pure.\n */\nfunction dialogueLines(\n blueprint: VideoBlueprint,\n ctx: {\n compositeScenes: Set<number>;\n multiSpeaker: Set<number>;\n canonical: (s: string) => string;\n casts: Set<string>;\n cameraOn: boolean;\n presenterPresent: (speaker: string, sceneIndex: number) => boolean;\n },\n): PhraseLine[] {\n return blueprint.scenes\n .flatMap((scene, sceneIndex): PhraseLine[] => {\n if (ctx.compositeScenes.has(sceneIndex)) return [];\n return (scene.dialogue ?? [])\n .filter((l): l is BlueprintDialogueLine & { line: string } => Boolean(l.line?.trim()))\n .map((l) => {\n const raw = l.speaker ?? \"voiceover\";\n const text = l.line.trim();\n const start = l.start_s ?? scene.start_s ?? 0;\n const shown =\n l.on_camera !== false &&\n !sceneIsAllGraphic(scene) &&\n isOnCameraSpeaker(raw, ctx.casts, ctx.cameraOn) &&\n !ctx.multiSpeaker.has(sceneIndex) &&\n ctx.presenterPresent(ctx.canonical(raw), sceneIndex);\n return {\n sceneIndex,\n speaker: ctx.canonical(raw),\n shown,\n start,\n end: l.end_s ?? start + estSpeechS(text),\n text,\n };\n });\n })\n .sort((a, b) => a.start - b.start);\n}\n\n/**\n * Group dialogue into PHRASES — a phrase is one clip. A new phrase starts on a speaker\n * change, a real audio pause (> PAUSE_GAP_S), a COMPLETE BREAK between two adjacent SHOWN\n * shots (a hard cut, see isAdjacentShownCut — this is the \"several clear clips separated by\n * complete breaks\" the user wants), when the run would exceed the Seedance clip ceiling (a\n * long shot split for length, rejoined via a shared boundary frame the spine seam-dedups),\n * or across a composite scene (voiced on its own). What it does NOT split: a continuous\n * VOICEOVER narration stays ONE read across the b-roll it plays over, and a cutaway insert\n * (b-roll between two shown scenes) leaves the presenter shot continuous with the insert\n * sliced in — neither is a complete break. Pure.\n */\nexport function buildPhrases(\n blueprint: VideoBlueprint,\n canonical: (s: string) => string,\n compositeScenes: Set<number>,\n presenterPresent: (speaker: string, sceneIndex: number) => boolean,\n // Stricter \"is this speaker genuinely on screen\" (explicit element link only). Used\n // ONLY for the multi-speaker gate so an off-camera voice isn't miscounted as a second\n // on-camera mouth — the lenient presenterPresent still drives slicing.\n presentStrict: (speaker: string, sceneIndex: number) => boolean,\n): Phrase[] {\n const casts = castIdSet(blueprint);\n const cameraOn = onCameraDialogue(blueprint);\n const multiSpeaker = multiSpeakerScenes(blueprint, casts, cameraOn, canonical, presentStrict);\n const lines = dialogueLines(blueprint, {\n compositeScenes,\n multiSpeaker,\n canonical,\n casts,\n cameraOn,\n presenterPresent,\n });\n\n const phrases: Phrase[] = [];\n let cur: {\n speaker: string;\n firstScene: number;\n start: number;\n end: number;\n // The latest time the phrase CLIP must cover: every shown scene's end (its window is\n // sliced from the clip) plus the spoken-line ends. Capped so the clip never exceeds\n // the Seedance ceiling — a longer run splits into the next take at a scene boundary.\n coverEnd: number;\n // The earliest time the clip must start: the first line's start, but pulled back to a\n // shown scene's visual start when its line begins after a silent lead-in. The clip span\n // (coverEnd − clipStart) is what the Seedance ceiling caps.\n clipStart: number;\n texts: string[];\n // The last ON-CAMERA scene this run showed (null until one appears) — the next shown\n // scene breaks a new clip only when it is the immediately-following scene AND a hard cut\n // (so two adjacent presenter shots split, but a cutaway insert between them does not).\n lastShownScene: number | null;\n shown: Set<number>;\n } | null = null;\n const flush = () => {\n if (!cur) return;\n const shownScenes = [...cur.shown].sort((a, b) => a - b);\n phrases.push({\n speaker: cur.speaker,\n start_s: cur.start,\n end_s: cur.end,\n text: joinDialogueTexts(cur.texts),\n firstScene: cur.firstScene,\n shownScenes,\n presenterShown: shownScenes.length > 0,\n });\n cur = null;\n };\n for (const ln of lines) {\n const { cover: lineCover, clipStart: lineClipStart } = lineClipWindow(ln, blueprint.scenes);\n // A new phrase/clip starts on a speaker change, a real audio pause (keeps a voiceover ONE\n // fluid read across b-roll), a complete break between two adjacent SHOWN shots (the \"clips\n // separated by complete breaks\" — NOT fired across a cutaway insert, whose shown scenes\n // aren't adjacent), or the run passing the Seedance ceiling (a length-split rejoined by a\n // shared frame the spine seam-dedups). See breaksPhrase.\n const breakRun = !cur || breaksPhrase(cur, ln, lineCover, lineClipStart, blueprint.scenes);\n if (breakRun || !cur) {\n flush();\n cur = {\n speaker: ln.speaker,\n firstScene: ln.sceneIndex,\n start: ln.start,\n end: ln.end,\n coverEnd: lineCover,\n clipStart: lineClipStart,\n texts: [ln.text],\n lastShownScene: ln.shown ? ln.sceneIndex : null,\n shown: new Set(),\n };\n } else {\n cur.texts.push(ln.text);\n cur.end = Math.max(cur.end, ln.end);\n cur.coverEnd = Math.max(cur.coverEnd, lineCover);\n cur.clipStart = Math.min(cur.clipStart, lineClipStart);\n if (ln.shown) cur.lastShownScene = ln.sceneIndex;\n }\n if (ln.shown) cur.shown.add(ln.sceneIndex);\n }\n flush();\n return phrases;\n}\n","/** Scale-to-fill (crop overflow, never distort) + normalize a clip to a target panel size. */\nfunction fillPanel(label: string, w: number, h: number, out: string): string {\n return `[${label}]scale=${w}:${h}:force_original_aspect_ratio=increase,crop=${w}:${h},setsar=1,fps=30[${out}]`;\n}\n\n/**\n * ffmpeg argv: composite N region clips into ONE split-screen frame. Each clip is\n * scaled to fill its panel (overflow cropped, no distortion) then stacked along the\n * split axis — `vertical` ⇒ top/bottom (vstack), `horizontal` ⇒ left/right (hstack).\n * Inputs are c0..c(N-1); output is the composited scene picture.\n */\nexport function splitStackArgs(\n count: number,\n axis: \"vertical\" | \"horizontal\",\n dims: { w: number; h: number },\n): string[] {\n // Every panel dimension must be EVEN (libx264 yuv420p hard-fails on odd sizes) and\n // the panels must SUM to the canvas (stack output = canvas, or the spine concat gets\n // a mismatched raster). Base panels floor to even; the last absorbs the remainder —\n // which stays even because the canvas dims are all even.\n const span = axis === \"horizontal\" ? dims.w : dims.h;\n const base = Math.floor(span / count / 2) * 2;\n const sizeAt = (i: number): number => (i === count - 1 ? span - base * (count - 1) : base);\n const inputs: string[] = [];\n const filt: string[] = [];\n let labels = \"\";\n for (let i = 0; i < count; i++) {\n inputs.push(\"-i\", `{{in.c${i}}}`);\n const pw = axis === \"horizontal\" ? sizeAt(i) : dims.w;\n const ph = axis === \"vertical\" ? sizeAt(i) : dims.h;\n filt.push(fillPanel(`${i}:v`, pw, ph, `p${i}`));\n labels += `[p${i}]`;\n }\n const stack = axis === \"vertical\" ? \"vstack\" : \"hstack\";\n filt.push(`${labels}${stack}=inputs=${count}[v]`);\n return [...inputs, \"-filter_complex\", filt.join(\";\"), \"-map\", \"[v]\", \"{{out.video}}\"];\n}\n\n// 9-grid position → ffmpeg `overlay` x:y expression (W/H = background, w/h = inset),\n// offset by a uniform margin so the inset never kisses the frame edge.\nfunction overlayXY(position: string | undefined, marginPx: number): { x: string; y: string } {\n const p = (position ?? \"bottom_right\").toLowerCase();\n const x = p.includes(\"left\") ? `${marginPx}` : p.includes(\"right\") ? `W-w-${marginPx}` : \"(W-w)/2\";\n const y = p.includes(\"top\") ? `${marginPx}` : p.includes(\"bottom\") ? `H-h-${marginPx}` : \"(H-h)/2\";\n return { x, y };\n}\n\n/**\n * ffmpeg argv: composite N inset clips over a full-frame background (c0 = background,\n * c1..cN = insets, one `overlay` stage each, folded left). Each inset is scaled to its\n * `wpct` of the frame width (height auto, aspect kept) and overlaid at its 9-grid\n * `position` with a uniform margin. A keyed inset arrives pre-alpha'd (`format=auto`\n * honors its transparency); a plain PIP is an opaque rounded box. Compositing EVERY\n * region matters: each one is a billed generated clip — dropping the 3rd+ region paid\n * for a clip that never reached the frame.\n */\nexport function pipOverlayArgs(\n dims: { w: number; h: number },\n insets: Array<{ position?: string; wpct: number }>,\n): string[] {\n const margin = Math.round(dims.w * 0.04);\n const inputs = [\"-i\", \"{{in.c0}}\"];\n const filt = [fillPanel(\"0:v\", dims.w, dims.h, \"bg\")];\n let cur = \"bg\";\n insets.forEach((inset, k) => {\n inputs.push(\"-i\", `{{in.c${k + 1}}}`);\n const iw = Math.round(dims.w * inset.wpct);\n const { x, y } = overlayXY(inset.position, margin);\n const outLabel = k === insets.length - 1 ? \"v\" : `o${k + 1}`;\n filt.push(`[${k + 1}:v]scale=${iw}:-2,setsar=1,fps=30[fg${k + 1}]`);\n filt.push(`[${cur}][fg${k + 1}]overlay=x=${x}:y=${y}:format=auto[${outLabel}]`);\n cur = outLabel;\n });\n return [...inputs, \"-filter_complex\", filt.join(\";\"), \"-map\", \"[v]\", \"{{out.video}}\"];\n}\n\n/**\n * ffmpeg argv: cut a clip to an exact duration (re-encode for frame accuracy, drop\n * audio). With `offsetS > 0` it cuts the sub-window [offset, offset+duration] — used\n * to slice ONE presenter scene's window out of its phrase's continuous clip. `-ss`\n * is placed AFTER `-i` for frame-accurate seeking (the spine must stay aligned).\n * With `dims` the trim also normalizes the picture to the output canvas (scale-to-fill,\n * center-crop) — how a clip GENERATED at the video model's nearest ratio (e.g. 3:4)\n * lands on the ad's true canvas (e.g. 4:5). Free: the trim re-encodes anyway.\n */\nexport function trimArgs(durationS: number, offsetS = 0, dims?: { w: number; h: number }): string[] {\n return [\n \"-i\",\n \"{{in.clip}}\",\n ...(offsetS > 0 ? [\"-ss\", offsetS.toFixed(3)] : []),\n \"-t\",\n durationS.toFixed(3),\n ...(dims\n ? [\"-vf\", `scale=${dims.w}:${dims.h}:force_original_aspect_ratio=increase,crop=${dims.w}:${dims.h},setsar=1`]\n : []),\n \"-an\",\n \"-c:v\",\n \"libx264\",\n // Preserve the seedance source quality through the trim. libx264 DEFAULTS\n // (crf 23) halve the bitrate (measured 9.57→4.40 Mbps) and band on motion;\n // the spine stream-copies the result, so the loss is permanent without this.\n \"-crf\",\n \"18\",\n \"-preset\",\n \"slow\",\n \"-pix_fmt\",\n \"yuv420p\",\n \"{{out.video}}\",\n ];\n}\n\n/** ffmpeg argv: demux a clip's audio AND trim it to the exact spoken window (optionally\n * skipping a silent lead-in when the clip starts before the line). */\nexport function audioExtractArgs(durationS: number, offsetS = 0): string[] {\n return [\n \"-i\",\n \"{{in.clip}}\",\n ...(offsetS > 0.05 ? [\"-ss\", offsetS.toFixed(3)] : []),\n \"-t\",\n durationS.toFixed(3),\n \"-vn\",\n \"-acodec\",\n \"libmp3lame\",\n \"-q:a\",\n \"2\",\n \"{{out.audio}}\",\n ];\n}\n\n/** ffmpeg argv: a full-frame solid colour clip (lavfi color source — no input file).\n * Exact canvas dims, so no letterbox/grey-bar gap behind the overlay CTA card. */\nexport function colorPlateArgs(durationS: number, dims: { w: number; h: number }, color: string): string[] {\n return [\n \"-f\",\n \"lavfi\",\n \"-i\",\n `color=c=${color}:s=${dims.w}x${dims.h}:r=30`,\n \"-t\",\n durationS.toFixed(3),\n \"-c:v\",\n \"libx264\",\n \"-crf\",\n \"18\",\n \"-preset\",\n \"slow\",\n \"-pix_fmt\",\n \"yuv420p\",\n \"{{out.video}}\",\n ];\n}\n","import type { VideoBlueprint } from \"@baker/canvas-contract\";\nimport type { NodeDecl } from \"../../../schema/canvas.ts\";\nimport { AMBIENT_BED_GAIN_DB, type AudioTrack, FIXED_TTS_MODEL, FIXED_VOICE_CONVERT_MODEL } from \"../audio.ts\";\nimport { audioExtractArgs } from \"../ffmpeg-args.ts\";\nimport { ids, ref, sceneTags } from \"../ids.ts\";\nimport type { NativeTurn, SceneCtx, TimelineEnv, TimelineOut } from \"../timeline-env.ts\";\nimport type { Phrase } from \"./phrases.ts\";\nimport type { VoiceGender } from \"./voice-gender.ts\";\n\n/** A native talking scene's extracted clip audio, awaiting a per-speaker conversion. */\nexport type NativeSegment = { voiceNode: string; ref: string; start_s: number; end_s: number };\n\n/**\n * A native talking scene's audio chain. The video model voices the line in its own clip\n * (Seedance 2.0 generates lip-synced speech NATIVELY when the line is in the prompt with\n * `generate_audio`, so no post-hoc lip-sync); this extracts the clip's spoken window into\n * a segment. The segments are merged PER SPEAKER and converted ONCE downstream\n * (`buildPerSpeakerVoiceConversion`: one brand-voice pass over the whole track, not a\n * separate convert per scene), which preserves timing so the lips stay matched.\n *\n * `clip` is the clip carrying the voice — a phrase's clip, or a composited scene's PRESENTER\n * region — with its generated length and where the line starts inside it.\n */\nexport function emitNativeExtract(\n ctx: SceneCtx,\n turn: NativeTurn,\n clip: { ref: string; lengthS: number; offsetS?: number },\n): void {\n const { index } = ctx;\n const offsetS = clip.offsetS ?? 0;\n // Extract the real SPOKEN window (turn start→end), not a word-count estimate. Padding\n // to the estimate ran each composite scene's voice long and overlapped the next scene's\n // on the merged per-speaker track (echo during fast montages). Bounded by the clip.\n const extractLen = Math.min(Math.max(0.5, turn.end_s - turn.start_s), Math.max(0.5, clip.lengthS - offsetS));\n const extractId = ids.voiceExtract(index);\n ctx.out.nodes.push({\n id: extractId,\n type: \"ffmpeg\",\n tags: sceneTags(index, \"voice_extract\"),\n inputs: { clip: clip.ref },\n params: { args: audioExtractArgs(extractLen, offsetS), outputs: { audio: { kind: \"audio\", ext: \"mp3\" } } },\n });\n // Placement is on the spine clock: the line starts where its scene's picture sits.\n const spineStart = ctx.env.clock.map(index, turn.start_s);\n ctx.out.nativeSegments.push({\n voiceNode: turn.voiceNode,\n ref: ref(extractId, \"audio\"),\n start_s: spineStart,\n end_s: spineStart + extractLen,\n });\n}\n\n/** An opt-in ambient b-roll scene: the clip's diegetic ambience, extracted and laid deep under the bed. */\nexport function emitAmbientExtract(ctx: SceneCtx, clipRef: string): void {\n const { index, lengths } = ctx;\n const ambientId = ids.ambient(index);\n const ambientStart = ctx.env.clock.startOf(index);\n ctx.out.nodes.push({\n id: ambientId,\n type: \"ffmpeg\",\n tags: sceneTags(index, \"ambient_extract\"),\n inputs: { clip: clipRef },\n params: { args: audioExtractArgs(lengths.dur), outputs: { audio: { kind: \"audio\", ext: \"mp3\" } } },\n });\n ctx.out.voTracks.push({\n slot: ambientId,\n ref: ref(ambientId, \"audio\"),\n start_s: ambientStart,\n end_s: ambientStart + lengths.dur,\n gain_db: AMBIENT_BED_GAIN_DB,\n kind: \"ambient\",\n });\n}\n\n/**\n * One speaker's extracted segments → the `audio_timeline` track entries that lay them\n * out, in start order, each capped (`duration_s`) where its natural window would run\n * into the SAME speaker's next segment — otherwise both extracts play at once and the\n * voice doubles into an echo. A deconstruct only has to mistime two windows by 40ms\n * (observed live) for the overlap to ship; the cap makes it structurally impossible.\n */\nexport function sameSpeakerTrackEntries(\n segments: Array<Pick<NativeSegment, \"start_s\" | \"end_s\">>,\n): Array<{ slot: string; start_s: number; duration_s?: number }> {\n const sorted = [...segments].sort((a, b) => a.start_s - b.start_s);\n return sorted.map((s, k) => {\n const next = sorted[k + 1];\n const naturalLen = s.end_s - s.start_s;\n const cap = next ? Math.min(s.end_s, next.start_s) - s.start_s : naturalLen;\n const capped = cap < naturalLen - 0.001;\n return {\n slot: `seg${k}`,\n start_s: s.start_s,\n ...(capped ? { duration_s: Math.round(Math.max(0.1, cap) * 1000) / 1000 } : {}),\n };\n });\n}\n\n/**\n * Re-voice the native talking audio to the brand voice in ONE pass per speaker, over\n * the MERGED track — not a separate convert per scene. For each distinct speaker the\n * scene extracts are placed at their absolute starts on a per-speaker `audio_timeline`\n * (`<voice>_track`), then a single `audio_voice_convert` (`<voice>_conv`) maps the whole\n * track to that speaker's brand voice (speech-to-speech preserves timing, so lip-sync\n * survives). Returns one full-length VO track per speaker for the final mix. The\n * separate extract step is unavoidable: `audio_voice_convert` runs in a Convex action\n * with no ffmpeg and ElevenLabs speech-to-speech takes audio bytes only.\n */\nexport function buildPerSpeakerVoiceConversion(\n segments: NativeSegment[],\n totalMs: number,\n nodes: NodeDecl[],\n /** See `ScaffoldVideoOpts.keepRenderedVoice` — the merged track ships as rendered. */\n keepRenderedVoice = false,\n): AudioTrack[] {\n const bySpeaker = new Map<string, NativeSegment[]>();\n for (const seg of segments) {\n const arr = bySpeaker.get(seg.voiceNode) ?? [];\n arr.push(seg);\n bySpeaker.set(seg.voiceNode, arr);\n }\n const tracks: AudioTrack[] = [];\n for (const [voiceNode, segs] of bySpeaker) {\n // The merged native track carries the `_conv` id whether or not it is converted: it\n // is this speaker's on-camera voice either way, and the mix slot, the vo segments and\n // the talking-scene entries all name it by that id. What marks it as a rendered voice\n // rather than a read one is its `on_camera` tag (and the segments' `onCamera`), never\n // the suffix.\n const convId = ids.voiceConv(voiceNode);\n const trackId = keepRenderedVoice ? convId : ids.voiceTrack(voiceNode);\n // Wire inputs in the SAME start order the track entries use — seg{k} ↔ sorted[k].\n const sorted = [...segs].sort((a, b) => a.start_s - b.start_s);\n const mixInputs: Record<string, unknown> = {};\n sorted.forEach((s, k) => {\n mixInputs[`seg${k}`] = s.ref;\n });\n nodes.push({\n id: trackId,\n type: \"audio_timeline\",\n tags: { role: keepRenderedVoice ? \"voice\" : \"voice_track\", on_camera: true },\n inputs: mixInputs,\n params: {\n tracks: sameSpeakerTrackEntries(sorted),\n total_ms: totalMs,\n },\n });\n if (!keepRenderedVoice) {\n nodes.push({\n id: convId,\n type: \"audio_voice_convert\",\n tags: { role: \"voice\", on_camera: true },\n inputs: { audio: ref(trackId, \"audio\"), voice_ref: ref(voiceNode, \"voice_id\") },\n params: { model: FIXED_VOICE_CONVERT_MODEL, voice: \"{{voice_ref}}\" },\n });\n }\n // The merged track is already absolute-timed, so it sits at 0 on the final mix —\n // hard-capped to the timeline length so an oversized STS return (ElevenLabs\n // speech-to-speech is ASSUMED to preserve duration, but nothing verifies it)\n // truncates instead of pushing the mix past the picture into `-shortest`.\n tracks.push({ slot: convId, ref: ref(convId, \"audio\"), start_s: 0, duration_s: totalMs / 1000, kind: \"vo\" });\n }\n return tracks;\n}\n\n/**\n * One voice_select per distinct (canonical) speaker, cast from its description and reused.\n *\n * A speaker's casting is decided before anything is emitted: `isCast(speaker)` says whether\n * any node will read their voice. Every speaker keeps an id — the name the phrase and the\n * segments carry — but only a cast speaker gets the node. The one who does not is an\n * on-camera speaker whose rendered voice is kept (`keepRenderedVoice`) and who has no line\n * read over the picture: a casting there is a billed ElevenLabs search picking a voice for\n * a face that already has one, which nothing would ever reference.\n */\nexport function makeVoiceFactory(\n blueprint: VideoBlueprint,\n canonical: (s: string) => string,\n nodes: NodeDecl[],\n isCast: (speaker: string) => boolean,\n /**\n * The hard filters the caller knows: the voice's language (the English name `voice_select`\n * filters on) and the gender each description asks for. See `ScaffoldVideoOpts`.\n */\n filters: { language?: string; genders?: Readonly<Record<string, VoiceGender>> },\n /** A voice already chosen, so nothing is cast. See `ScaffoldVideoOpts.voiceId`. */\n pinnedVoiceId?: string,\n): (speaker: string) => string {\n const bySpeaker = new Map<string, string>();\n const describe = (speaker: string): string => {\n for (const scene of blueprint.scenes)\n for (const line of scene.dialogue ?? [])\n if (canonical(line.speaker ?? \"voiceover\") === speaker && line.voice_description) return line.voice_description;\n const cast = blueprint.global?.cast?.find((c) => c.id === speaker);\n return cast?.description ?? blueprint.global?.voiceover?.voice_description ?? `${speaker} voice`;\n };\n return (speaker: string): string => {\n const existing = bySpeaker.get(speaker);\n if (existing) return existing;\n const id = ids.voice(speaker, bySpeaker.size);\n bySpeaker.set(speaker, id);\n if (!isCast(speaker)) return id;\n const description = describe(speaker);\n // Gender and language as explicit params so the backend's hard-filter can refuse a\n // wrong-gender voice (never cast a male voice for a French woman). Both were decided\n // when the canvas was scaffolded; with neither, the description alone ranks the cast.\n const genders = filters.genders ?? {};\n const gender = Object.hasOwn(genders, description) ? genders[description] : undefined;\n const traits = {\n ...(gender ? { gender } : {}),\n ...(filters.language ? { language: filters.language } : {}),\n };\n // A pinned voice still gets a node, so every downstream `$ref:<node>.voice_id`\n // keeps working — it just resolves to the id that was chosen instead of casting a\n // new one. `voice_select` with an exact `voice_id` short-circuits its own ranking.\n nodes.push(\n pinnedVoiceId\n ? { id, type: \"voice_select\", params: { description, voice_id: pinnedVoiceId, ...traits } }\n : { id, type: \"voice_select\", params: { description, ...traits } },\n );\n return id;\n };\n}\n\n/**\n * A phrase nobody is shown saying: ONE ElevenLabs tts read over the picture (a voiceover\n * over the cutaways, or one speaker of a scene two people talk in). `phraseIndex` names it.\n */\nexport function emitPhraseTts(\n phrase: Phrase,\n voiceNode: string,\n phraseIndex: number,\n env: TimelineEnv,\n out: TimelineOut,\n): void {\n let id = ids.phraseRead(phraseIndex, phrase.speaker);\n while (out.readIds.has(id)) id = `${id}_x`;\n out.readIds.add(id);\n out.nodes.push({\n id,\n type: \"tts\",\n tags: { scene: phrase.firstScene, role: \"voice\", on_camera: false },\n inputs: { voice_ref: ref(voiceNode, \"voice_id\") },\n params: {\n model: FIXED_TTS_MODEL,\n text: phrase.text,\n voice: \"{{voice_ref}}\",\n // ISO 639-1 of the spoken track, when known — forces ElevenLabs to normalize\n // numbers/units in that language instead of defaulting to English.\n ...(env.ttsLanguageCode ? { language_code: env.ttsLanguageCode } : {}),\n },\n });\n // Spine-clock placement: the read starts where its first scene's picture sits.\n const spineStart = env.clock.map(phrase.firstScene, phrase.start_s);\n const spineEnd = spineStart + (phrase.end_s - phrase.start_s);\n out.voTracks.push({ slot: id, ref: ref(id, \"audio\"), start_s: spineStart, end_s: spineEnd, kind: \"vo\" });\n out.voSegments.push({\n slot: id,\n start_s: spineStart,\n end_s: spineEnd,\n scene: phrase.firstScene,\n speaker: phrase.speaker,\n onCamera: false,\n });\n}\n","import type { VideoBlueprint } from \"@baker/canvas-contract\";\nimport { isCtaRole } from \"../../lib/scene-role.ts\";\nimport { canvasDims } from \"../aspect.ts\";\nimport { colorPlateArgs } from \"../ffmpeg-args.ts\";\nimport { ids, ref, sceneTags } from \"../ids.ts\";\nimport type { SceneCtx } from \"../timeline-env.ts\";\n\n// The prose cue for a CTA/end beat that is a SOLID brand/logo card, for a deconstructed\n// scene: a producer that wrote the beat as a brand card says so in `route_hint` instead.\nconst BRAND_CARD_RE =\n /\\b(?:solid|plain|flat|brand|logo|wordmark|end[- ]?card|cta card|title card|colou?r background|background colou?r)\\b/i;\n\n/**\n * A CTA/end beat that is a SOLID brand/logo card (not a photographic scene). Must NOT be\n * image_generate'd: a generative model garbles the wordmark and URL (\"Barkbu\",\n * \"barkaui.com\") and can letterbox the plate (CCA-05/12). Reproduced as a clean solid\n * colour plate; the real logo/URL/CTA ride the overlay layer's brand card.\n *\n * A scene whose producer marked it `route_hint: \"brand_card\"` (`scaffold-ad`'s closing\n * beat) is one. A deconstructed scene carries no hint and is read from its prose: the\n * closing (or declared CTA) beat, with a solid/brand/logo cue and no on-camera cast (a\n * presenter CTA stays a talking head).\n */\nexport function sceneIsBrandCard(ctx: SceneCtx): boolean {\n const { scene } = ctx;\n if (scene.route_hint) return scene.route_hint === \"brand_card\";\n if (!(isCtaRole(scene.narrative_role) || ctx.isLast)) return false;\n const hasCast = ctx.present.some((s) => {\n const t = s.type.toLowerCase();\n return t === \"person\" || t === \"animal\";\n });\n if (hasCast) return false;\n const hay = `${scene.summary ?? \"\"} ${scene.start_frame_prompt ?? \"\"} ${scene.end_frame_prompt ?? \"\"}`;\n return BRAND_CARD_RE.test(hay);\n}\n\nconst HEX6_RE = /^#?[0-9a-fA-F]{6}$/;\n/** The brand-card plate colour: the blueprint's dominant palette hex, else clean black\n * (the overlay CTA card carries the brand look, so a neutral plate is safe). */\nfunction brandPlateColor(blueprint: VideoBlueprint): string {\n const hex = blueprint.global?.style?.palette\n ?.map((p) => p.hex)\n .find((h): h is string => typeof h === \"string\" && HEX6_RE.test(h));\n return hex ? `0x${hex.replace(/^#/, \"\").toUpperCase()}` : \"0x000000\";\n}\n\n/** The `brand_card` route: a clean solid colour plate at the exact canvas size (never a generated logo). */\nexport function emitBrandCardScene(ctx: SceneCtx): void {\n const { env, index, lengths } = ctx;\n const plateId = ids.clip(index);\n ctx.out.nodes.push({\n id: plateId,\n type: \"ffmpeg\",\n tags: sceneTags(index, \"brand_card\"),\n inputs: {},\n params: {\n args: colorPlateArgs(lengths.trimTarget, canvasDims(env.outAr), brandPlateColor(env.blueprint)),\n outputs: { video: { kind: \"video\", ext: \"mp4\" } },\n },\n });\n ctx.out.clips.push({ ref: ref(plateId, \"video\"), scene_s: lengths.dur, out: lengths.out });\n ctx.out.routes.set(index, \"brand_card\");\n}\n","// Ad-native SHOOT-MODE grammar — the single source of truth for the \"look\" each\n// scene is captured in. A video ad is rarely one aesthetic end-to-end: a creator\n// selfie hook, a candid b-roll demo, and a clean pack-shot are filmed three\n// different ways. The scaffold used to bake ONE look (phone UGC) into every\n// frame; this picks the right capture block per scene instead.\n//\n// The reference doc `references/shoot-modes.md` in the creative-canvas-ads skill\n// describes these modes for the human; THIS file is the canonical definition the\n// scaffold actually emits — keep the two in sync conceptually, but never paste the\n// prose into both places (this is the source).\n//\n// Doctrine: UGC is still the default and the auto-derived modes are UGC/product\n// only (selfie, b-roll, studio-product). The polished lanes (lifestyle-cinematic,\n// screen/UI) exist but are opt-in — the deconstruct/agent must name them on a\n// scene, because a cinematic grade applied by accident is exactly the \"produced,\n// not filmed\" tell that kills UGC performance on feed.\n\nexport type ShootMode = \"ugc_selfie\" | \"ugc_broll\" | \"studio_product\" | \"lifestyle_cinematic\" | \"screen_ui\";\n\nconst SHOOT_MODES: readonly ShootMode[] = [\n \"ugc_selfie\",\n \"ugc_broll\",\n \"studio_product\",\n \"lifestyle_cinematic\",\n \"screen_ui\",\n] as const;\n\n/** Talking heads default here; the safest, highest-converting feed look. */\nexport const DEFAULT_SHOOT_MODE: ShootMode = \"ugc_selfie\";\n\ntype ShootModeSpec = {\n label: string;\n /** Whether shallow depth of field reads as native for this mode. UGC = flat. */\n allowsDoF: boolean;\n /** The frame capture block — the aesthetic + DoF rule injected into image_generate. */\n capture: string;\n /** The Seedance camera/motion default when the scene names no explicit move. */\n motion: string;\n /** Default diegetic-audio descriptor when the scene carries no `ambient` hint. */\n diegetic: string;\n};\n\nconst SHOOT_MODE_SPECS: Readonly<Record<ShootMode, ShootModeSpec>> = {\n ugc_selfie: {\n label: \"UGC selfie / talking-head\",\n allowsDoF: false,\n capture: [\n \"CAPTURE — AUTHENTIC PHONE UGC (front camera):\",\n \"Shot on a modern phone front camera — natural lens, real skin texture and pores,\",\n \"catchlights, mixed indoor white balance, faint sensor grain, slight handheld imperfection.\",\n \"NO shallow depth of field or background blur — native phone footage is flat front-to-back;\",\n \"blur reads as 'produced', not filmed-on-a-phone. Keep the whole frame in focus.\",\n ].join(\"\\n\"),\n motion:\n \"Lock the camera at arm's-length selfie distance; only natural handheld micro-movement. Move the camera only if a move is named above.\",\n diegetic: \"a quiet room tone with soft fabric and breath under the speaker's own voice\",\n },\n ugc_broll: {\n label: \"UGC b-roll / handheld\",\n allowsDoF: false,\n capture: [\n \"CAPTURE — AUTHENTIC PHONE UGC (rear camera, candid):\",\n \"Shot on a modern phone rear camera, handheld and candid — natural lens, real materials and\",\n \"textures, real hands in frame where natural, mixed natural white balance, faint sensor grain.\",\n \"NO shallow depth of field or background blur — native phone footage is flat front-to-back;\",\n \"keep the whole frame in focus.\",\n ].join(\"\\n\"),\n motion:\n \"Handheld, candid framing; keep any move small and motivated. Move the camera only if a move is named above.\",\n diegetic: \"the real ambient of the setting — handling sounds, footsteps, and room or outdoor tone\",\n },\n studio_product: {\n label: \"Studio / product (pack shot)\",\n allowsDoF: true,\n capture: [\n \"CAPTURE — CONTROLLED PRODUCT / STUDIO:\",\n \"Photographed on a controlled set — a clean seamless or one styled surface, a soft key with\",\n \"gentle fill and a subtle rim, true-to-life color. Shallow depth of field IS allowed to isolate\",\n \"the hero, with crisp specular highlights on the product's real materials.\",\n \"Still a real photograph, not CGI — no plastic or waxy surfaces, no over-render; real material\",\n \"texture and weight.\",\n ].join(\"\\n\"),\n motion: \"Lock off, or a slow motivated push-in / settle onto the product; otherwise hold.\",\n diegetic: \"minimal — soft product-handling sounds over a quiet room tone\",\n },\n lifestyle_cinematic: {\n label: \"Lifestyle / cinematic\",\n allowsDoF: true,\n capture: [\n \"CAPTURE — LIFESTYLE / CINEMATIC:\",\n \"A real camera in a real location — natural motivated light, true color, a gentle filmic grade,\",\n \"fine grain. A shallow depth of field is allowed when motivated by the moment.\",\n \"Photographic, not rendered — real skin and material texture, no airbrushing, no glossy 3D look.\",\n ].join(\"\\n\"),\n motion: \"A slow, motivated camera move (gentle push-in, drift, or settle) is allowed; otherwise hold.\",\n diegetic: \"the location's natural ambience — wind, traffic, water, or room tone as the setting implies\",\n },\n screen_ui: {\n label: \"Screen / UI / demo\",\n allowsDoF: true,\n capture: [\n \"CAPTURE — SCREEN / UI CAPTURE:\",\n \"A clean screen or app capture — crisp pixels, true on-screen color, optionally framed inside a\",\n \"real device held in a real hand. No human-skin realism is needed; the screen content is the subject.\",\n \"Do not bake invented UI copy into the plate beyond what the reference shows — editable text lives\",\n \"on the overlay layer.\",\n ].join(\"\\n\"),\n motion: \"Hold on the screen; allow a slow push-in or a UI scroll only if a move is named above.\",\n diegetic: \"soft UI taps and device handling over a quiet room tone\",\n },\n};\n\nexport function isShootMode(value: unknown): value is ShootMode {\n return typeof value === \"string\" && (SHOOT_MODES as readonly string[]).includes(value);\n}\n\n/** The capture block (aesthetic + DoF rule) for a frame in this mode. */\nexport function captureBlockFor(mode: ShootMode): string {\n return SHOOT_MODE_SPECS[mode].capture;\n}\n\n/** The default camera/motion line for a Seedance clip in this mode. */\nexport function seedanceMotionFor(mode: ShootMode): string {\n return SHOOT_MODE_SPECS[mode].motion;\n}\n\n/** The default diegetic-audio descriptor for a scene in this mode. */\nexport function diegeticFor(mode: ShootMode): string {\n return SHOOT_MODE_SPECS[mode].diegetic;\n}\n\n/**\n * Pick the shoot mode for a scene. An explicit `scene.shoot_mode` the deconstruct\n * or a human set always wins. Otherwise we auto-derive — and on purpose only ever\n * choose a UGC/product mode: talking → selfie, a product-only beat → pack shot,\n * everything else → candid b-roll. The cinematic and screen lanes are never\n * auto-selected; they must be named, so the UGC default holds unless asked.\n */\nexport function deriveShootMode(opts: {\n explicit?: unknown;\n talking: boolean;\n hasPerson: boolean;\n hasProduct: boolean;\n}): ShootMode {\n if (isShootMode(opts.explicit)) return opts.explicit;\n if (opts.talking) return \"ugc_selfie\";\n if (opts.hasProduct && !opts.hasPerson) return \"studio_product\";\n return \"ugc_broll\";\n}\n","import type { VideoScene } from \"@baker/canvas-contract\";\nimport { imageProfileFor } from \"../../../lib/prompt-profiles.ts\";\nimport { captureBlockFor, type ShootMode } from \"../../lib/shoot-modes.ts\";\nimport { type ElementSlot, roleForSlot } from \"../elements.ts\";\nimport type { Edge } from \"../ids.ts\";\n\n/** Ends the FRAME DESCRIPTION a frame gets when its blueprint gave it none: a prompt to write one, not one. */\nexport const FRAME_PLACEHOLDER_NOTE = \"(Edit this line to change ONLY this frame.)\";\n\n/**\n * Build the static-ad-grade prompt for one boundary frame.\n *\n * The prompt is SELF-CONTAINED and is the per-frame editable surface: the FRAME\n * DESCRIPTION is inlined verbatim from the blueprint's `{edge}_frame_prompt`, so\n * editing this one node's `params.prompt` changes ONLY this frame — no other\n * frame and no shared file is touched. The blueprint (`{{target_blueprint}}`) is\n * kept ONLY as a demoted, shared style reference (global cast identity, palette,\n * typography mood, aspect ratio) — never as the source of this frame's content.\n */\nexport function buildFramePrompt(frame: {\n edge: Edge;\n sceneIndex: number;\n /** The frame's own description; a placeholder asks for one when the blueprint has none. */\n framePrompt: string | undefined;\n /** The references the frame grounds on, in the order they are wired. */\n present: ElementSlot[];\n /** Whether the source frame rides last as a composition-only anchor. */\n hasAnchor: boolean;\n mode: ShootMode;\n sceneStyle: SceneStyle | undefined;\n // The frame's image model — picks the model's PROMPT profile: gpt-image weights\n // early text as composition, so its exclusions go LAST and it needs an explicit\n // \"photorealistic\" cue; Gemini reads exclusions inline; Recraft renders vector art.\n imageModel: string;\n}): string {\n const { edge, sceneIndex, framePrompt, present, hasAnchor, mode, sceneStyle } = frame;\n const profile = imageProfileFor(frame.imageModel);\n const exclusionsLast = profile?.constraintPlacement === \"last\";\n // Default photoreal ON for unprofiled models (frames are photographic unless a\n // vector model like Recraft opts out).\n const photoreal = profile ? profile.photorealCue : true;\n const EDGE = edge.toUpperCase();\n const legend = [\n ...present.map((s) => `- ${s.label} — ${roleForSlot(s)}`),\n ...(hasAnchor\n ? [\n \"- ORIGINAL_FRAME — use ONLY for composition: framing, camera angle, shot size, subject placement, pose, and proportions. IGNORE its text, logo, brand name, colors, AND the identity of every person/animal/object in it — those come from the labeled reference images above, never from this frame. It is a DIFFERENT brand's footage with DIFFERENT actors, here ONLY to anchor where things sit and how the shot is framed (e.g. a profile/side angle stays a profile/side angle), never who they are or what palette to use.\",\n ]\n : []),\n ].join(\"\\n\");\n const description =\n framePrompt?.trim() ||\n `the ${edge} frame of scene ${sceneIndex + 1} — describe the full composition, subjects, setting, action, lighting, and palette here. ${FRAME_PLACEHOLDER_NOTE}`;\n // The hook frame (scene 1's opening) carries the ad sound-off: the feed plays\n // muted, so this single frame + its overlay must read in ~1 second.\n const isHookFrame = sceneIndex === 0 && edge === \"start\";\n // The clean-plate exclusions. Their PLACEMENT is model-specific: gpt-image treats\n // early exclusions as compositional guidance, so for it we hoist them to the very\n // end; other models read them fine up top.\n const cleanPlateBlock = [\n \"CRITICAL — RENDER A CLEAN PLATE WITH ZERO TEXT OR GRAPHIC OVERLAYS:\",\n \"This frame is a background plate. Every overlay element is composited afterwards as a\",\n \"separate hyperframe HTML overlay layer — NOT painted into this image. Render NONE of:\",\n \"words, captions, subtitles, headlines, lower-third bars, news tickers/crawls, chyrons,\",\n \"station bugs, watermarks, numbers, prices; and NONE of the graphic overlays layered on\",\n \"the picture either — icons, stickers, emojis, badges, rating/trust seals, progress bars,\",\n \"UI chrome/buttons, and arrows. No legible text anywhere, not even in the background, on a\",\n \"desk, on screens, or as part of a 'broadcast look'. If a reference image (a logo, a desk,\",\n \"a studio) contains any text or graphics, DO NOT reproduce them — render the subject/scene\",\n \"only, leaving the regions where overlays will sit clean. Imperfect/garbled letterforms or\",\n \"stray icons are the worst outcome; leave those areas blank.\",\n \"A SCREEN/UI surface — an app, website, chat, dashboard, or phone display — is NEVER\",\n \"rendered here: leave any phone/screen OFF or blank-screened. The real interface is\",\n \"composited later as a screenshot or a brand HTML block, never AI-generated.\",\n ];\n return [\n `Render the ${EDGE} frame of scene ${sceneIndex + 1} as a single${photoreal ? \", photorealistic\" : \"\"} still image. This prompt is self-contained and edit-per-frame: change the FRAME DESCRIPTION below to alter ONLY this frame.`,\n \"\",\n // gpt-image (exclusionsLast): exclusions are hoisted to the tail (below); here we\n // lead with the positive brief. All other models keep the exclusions up front.\n ...(exclusionsLast ? [] : [...cleanPlateBlock, \"\"]),\n \"FRAMING — ONE UNCUT FRAME:\",\n \"Render ONE single uncut photographic frame: NO split screen, NO panels, NO dividing line,\",\n \"NO collage, NO before/after. Avoid the AI look — no waxy/plastic skin, no airbrushing, no\",\n \"over-smoothing, no over-saturation, no glossy 3D render. Every descriptor needs a technical\",\n 'anchor (a named lens / focal length / color grade) — no empty adjectives like \"cinematic\",',\n '\"beautiful\", \"high quality\"; they waste tokens and don\\'t move the model.',\n \"\",\n // The capture aesthetic + depth-of-field rule are SHOOT-MODE specific: a UGC\n // selfie is flat phone footage; a pack shot is a controlled studio frame. Only\n // this block varies by mode — the clean-plate and framing rules above are universal.\n captureBlockFor(mode),\n \"\",\n // Moderation-safe phrasing — Seedance routes around the real-person filter but\n // prompts still hit provider moderation; age-blind, role-based descriptions trip\n // it far less. (The client's own brand assets come from the references, not here.)\n \"Describe any person by role, wardrobe, and build — never by name and never by age\",\n \"(no child/kid/teen/young/elderly); do not invent brand logos or marks.\",\n ...(isHookFrame\n ? [\n \"\",\n \"HOOK FRAME (scene 1 opens the ad): the feed plays muted, so this frame must read\",\n \"INSTANTLY SOUND-OFF — one clear subject, legible at a glance in ~1 second, no clutter.\",\n ]\n : []),\n \"\",\n \"REFERENCE IMAGES (in the order provided):\",\n legend,\n \"\",\n // RECAST is the whole point of a transform: the dropped el_* images define who/\n // what is on screen, NOT the source footage and NOT the prose. Without this, the\n // model reproduces the original ad's people (a proven failure mode).\n ...(present.length > 0\n ? [\n \"IDENTITY & AESTHETIC — RECAST (this is a transform, not a copy):\",\n \"Identity comes from the reference image, never from the source footage or this prose. Render every\",\n \"person, animal, product, and set to MATCH its labeled reference image above — that image is the ONLY\",\n \"source of their identity, wardrobe, styling, and look. This is a complete recast: do NOT reproduce,\",\n \"trace, or resemble any individual, animal, product, or set from the source ad. Where the FRAME\",\n \"DESCRIPTION below names an appearance detail (hair, outfit, color, age, breed, brand of an object),\",\n \"IGNORE that wording — the reference image is the truth; use the description ONLY for pose, expression,\",\n \"action, framing, lighting, and palette.\",\n \"\",\n ]\n : [\n \"Identity comes from the reference image, never from prose — render the subject to MATCH it and\",\n \"describe only pose, expression, action, framing, and lighting in the FRAME DESCRIPTION below.\",\n \"\",\n ]),\n // Per-scene style deltas (a mid-video wardrobe/set change, a scene-specific\n // ambience) never reach the SHARED spec — it is global-only by design — so they\n // are baked HERE, on this scene's own frames. Inserted BEFORE the FRAME\n // DESCRIPTION marker so the validator's description slicing stays intact.\n ...(sceneStyle?.setting || sceneStyle?.ambient\n ? [\n \"SCENE STYLE (this scene's own setting/ambience — where it differs from the SHARED AD SPEC, this wins):\",\n [sceneStyle.setting, sceneStyle.ambient].filter(Boolean).join(\" — \"),\n \"\",\n ]\n : []),\n \"FRAME DESCRIPTION (this frame's editable prompt):\",\n description,\n \"\",\n \"Render exactly what the FRAME DESCRIPTION and the SHARED AD SPEC specify — this is the authoritative ad: its cast identity (via the reference images), palette, brand, and intent are law. Keep every recurring element identical to its reference image across all frames. Again: clean plate only — no rendered text, and no icons/stickers/emojis/badges (those live on the overlay layer).\",\n \"\",\n \"SHARED AD SPEC (authoritative — the ad blueprint this frame belongs to; align cast/palette/brand/type with it):\",\n \"{{target_blueprint}}\",\n // gpt-image weights early text as compositional guidance and late text as pure\n // exclusion — so for it the clean-plate rules land HERE, after all positive content.\n ...(exclusionsLast ? [\"\", ...cleanPlateBlock] : []),\n ].join(\"\\n\");\n}\n\n// A scene's own style deltas (setting/wardrobe/ambience) baked into ITS frames only —\n// the shared spec is global by design, so per-scene changes must ride the frame prompt.\nexport type SceneStyle = { setting?: string; ambient?: string };\n\n/** The frame-prompt style block for a scene: its own setting + ambience, when present. */\nexport function sceneStyleOf(scene: VideoScene): SceneStyle | undefined {\n const setting = scene.scene_setting?.trim();\n const ambient = scene.ambient?.trim();\n return setting || ambient ? { ...(setting ? { setting } : {}), ...(ambient ? { ambient } : {}) } : undefined;\n}\n","import { nearestSupportedAspectRatio } from \"@baker/canvas-contract\";\nimport { imageRenderParams } from \"../lib/image-params.ts\";\nimport { type ElementSlot, orderSlotsByIdentity } from \"./elements.ts\";\nimport { type Edge, ids, ref, sceneTags } from \"./ids.ts\";\nimport { buildFramePrompt, sceneStyleOf } from \"./prompts/frame.ts\";\nimport type { SceneCtx } from \"./timeline-env.ts\";\n\n// The tier keyframes ask for. Video models downscale to their own output anyway,\n// but a sharp source frame is what keeps the clip from looking softer than the\n// storyboard; snapped down per model by `imageRenderParams`.\nconst KEYFRAME_IMAGE_SIZE = \"2K\";\n// The step asked for on every frame a clip is built from; snapped down per model by\n// `imageRenderParams`, exactly as the size above is.\nconst FRAME_QUALITY = \"xhigh\";\n\n/** One keyframe to build: its edge, the source frame it reproduces, and who is in it. */\nexport type FrameSource = {\n edge: Edge;\n /** The real extracted frame, when the deconstruct kept one. */\n url: string | undefined;\n /** The frame's own description (its FRAME DESCRIPTION). */\n prompt: string | undefined;\n /** The recurring-element slots present in the frame. */\n present: ElementSlot[];\n /** The region of a composited scene the frame belongs to; absent for a full frame. */\n region?: number;\n};\n\n/**\n * Ingest a source-frame URL exactly once per canvas (a source-frame URL → its ingest ref in\n * `env.ingestCache`) and return its asset ref. Two scenes that share a frame URL reuse the\n * same ingest node.\n */\nfunction ingestFrameRef(ctx: SceneCtx, frame: FrameSource, url: string): string {\n const cached = ctx.env.ingestCache.get(url);\n if (cached) return cached;\n const refId = ids.sourceFrame(ctx.index, frame.edge, frame.region);\n ctx.out.nodes.push({ id: refId, type: \"ingest\", params: { source: \"url\", url, expect: \"image\" } });\n const assetRef = ref(refId, \"asset\");\n ctx.env.ingestCache.set(url, assetRef);\n return assetRef;\n}\n\n/**\n * Emit the node(s) for one clip's SINGLE keyframe and return the ref to wire into\n * video_generate's `first_frame`. Ingest the real frame (when present), then either\n * reuse it directly (faithful mode) or regenerate it static-ad-style — the baked\n * blueprint as target_blueprint, the shared recurring-element images + the real\n * frame as references, and a per-element legend.\n *\n * Every keyframe grounds ONLY on its OWN extracted frame + el_* identity slots — no\n * reference to any OTHER generated frame. So every image_generate is independent and\n * the whole canvas's frames render in PARALLEL (no cascade), and Seedance animates\n * each clip forward from its single first_frame.\n */\nexport function buildFrameRef(ctx: SceneCtx, frame: FrameSource): string {\n const { env } = ctx;\n const { url, present } = frame;\n // Reuse mode: wire the real source frame straight in (faithful, no regen).\n if (env.reuse && url) return ingestFrameRef(ctx, frame, url);\n\n // Generate mode — built EXACTLY like a static-ad frame: the `el_*` recast images own\n // identity/aesthetic (first). The ORIGINAL extracted frame may be kept LAST as a\n // pure-composition anchor (framing / camera angle / shot size / pose / proportions).\n //\n // Keeping that anchor reproduces the source's framing — but on ANY identity-bearing\n // frame (a person/pet present) it LEAKS the SOURCE identity: the model copies the\n // competitor's face from a strong close-up even when the cast is sheet-backed\n // (CCA-01 — the source actress rendered on the hook/CTA, then morphed mid-clip\n // between two mismatched keyframes). A multi-view sheet was NOT a strong enough lock.\n // So drop the raw anchor whenever a person/animal is present and ground purely on the\n // recast `el_*` sheets — framing is carried by the frame prompt's pose/angle/shot-size\n // instead. Keep the anchor only for NON-identity scenes (product / scenery / b-roll),\n // where it can't leak a face and genuinely helps the composition. The frame prompt's\n // ORIGINAL_FRAME legend still forbids taking identity/text/palette from it.\n //\n // The per-frame cast is not enough on its own: presence comes from the element\n // selection, which is told to leave a scene out when in doubt, so a frame of the\n // source actor can arrive here with no person slot. In an ad that shows people at all,\n // no source frame is a reference (BAKER-652).\n const castSlots = present.filter((s) => {\n const t = s.type.toLowerCase();\n return t === \"person\" || t === \"animal\";\n });\n const originalRef =\n url && castSlots.length === 0 && !env.sourceShowsPeople ? ingestFrameRef(ctx, frame, url) : undefined;\n // Identity-critical assets lead (the presenter's face gets the first-reference richness\n // gpt-image reserves); the pure-composition anchor always stays last. The legend order\n // inside the prompt is built from this same ordered list, so they can't disagree.\n const presentOrdered = orderSlotsByIdentity(present);\n const reference = [...presentOrdered.map((s) => s.ref), ...(originalRef ? [originalRef] : [])];\n const imageModel = env.opts.imageModel;\n const genParams: Record<string, unknown> = {\n model: imageModel,\n // Size tier, quality step and the model's profile defaults, each snapped to what the\n // chosen model offers (gpt-image has no size knob; Nano Banana 2 Lite renders 1K only).\n // We do NOT send input_fidelity, which gpt-image forces high automatically. The frame IS\n // the clip's first moment, and the video model animates whatever it is handed: a soft\n // frame is a soft clip for its whole length, so it asks for the best step there is.\n ...imageRenderParams(imageModel, { size: KEYFRAME_IMAGE_SIZE, quality: FRAME_QUALITY }),\n prompt: buildFramePrompt({\n edge: frame.edge,\n sceneIndex: ctx.index,\n framePrompt: frame.prompt,\n present: presentOrdered,\n hasAnchor: originalRef !== undefined,\n mode: ctx.mode,\n sceneStyle: sceneStyleOf(ctx.scene),\n imageModel,\n }),\n // The keyframes condition the clip, so they are generated at the clip's ratio.\n aspect_ratio: nearestSupportedAspectRatio(\"image_generate\", imageModel, env.genAr),\n };\n const genId = ids.frame(ctx.index, frame.edge, frame.region);\n ctx.out.nodes.push({\n id: genId,\n type: \"image_generate\",\n tags: sceneTags(ctx.index, \"frame\", frame.region),\n // `params.prompt` is this frame's authoritative, edit-per-frame description.\n // `target_blueprint` is the SLIM shared ad spec (global cast identity, palette, brand,\n // type — no per-scene content) the frame must stay consistent with; editing one frame\n // never touches another, and no image inlines the whole film to render one frame.\n inputs: { target_blueprint: ref(ids.promptStyle, \"asset\"), ...(reference.length > 0 ? { reference } : {}) },\n params: genParams,\n });\n return ref(genId, \"images#0\");\n}\n","import { MODEL_REGISTRY } from \"@baker/canvas-contract\";\n\n// Seedance (and Veo) default to a LOW output resolution when `resolution` is unset,\n// which downscales the 2K `image_generate` keyframes and is the top cause of the\n// \"the video looks way worse than the frames\" complaint. Pin the highest tier both\n// the default video model (Seedance: 480/720/1080p) and the cheap test model (Veo:\n// 720/1080p) share, so the clip preserves the keyframe's sharpness. Override per run\n// via `--resolution`. Only applied to models whose registry schema accepts it.\nconst DEFAULT_VIDEO_RESOLUTION = \"1080p\";\n// Derived from the registry (not hardcoded) so a future video model that declares a\n// `resolution` param is pinned automatically — a hardcoded list would silently leave\n// it on the model's low default, reproducing the regression this pin fixes.\nconst VIDEO_MODELS_WITH_RESOLUTION = new Set(\n Object.entries(MODEL_REGISTRY.video_generate)\n .filter(([, spec]) => \"resolution\" in spec.params)\n .map(([id]) => id),\n);\n/** The `resolution` param to merge into a video_generate node, or {} when the model has none. */\nexport function videoResolutionParam(videoModel: string, resolution: string | undefined): { resolution?: string } {\n if (!VIDEO_MODELS_WITH_RESOLUTION.has(videoModel)) return {};\n return { resolution: resolution ?? DEFAULT_VIDEO_RESOLUTION };\n}\n\n// `duration` and `generate_audio` are gated the same registry-derived way as\n// resolution: emitting a param the model has no schema slot for is a hard\n// `unknown_param` failure and the whole canvas refuses to run.\n//\n// Their status differs today. `generate_audio` genuinely varies — Gemini Omni has\n// no toggle (it always renders sound), so the helper really does return `{}`.\n// EVERY curated model declares `duration`, so `videoDurationParam` currently always\n// emits; it is kept for symmetry with its siblings so a future fixed-length model\n// is handled here rather than silently breaking every canvas that picks it.\nconst VIDEO_MODELS_WITH_DURATION = new Set(\n Object.entries(MODEL_REGISTRY.video_generate)\n .filter(([, spec]) => \"duration\" in spec.params)\n .map(([id]) => id),\n);\nconst VIDEO_MODELS_WITH_AUDIO_TOGGLE = new Set(\n Object.entries(MODEL_REGISTRY.video_generate)\n .filter(([, spec]) => \"generate_audio\" in spec.params)\n .map(([id]) => id),\n);\n\n/** The `duration` param for a video_generate node, or {} if the model declares none. */\nexport function videoDurationParam(videoModel: string, duration: number): { duration?: number } {\n if (!VIDEO_MODELS_WITH_DURATION.has(videoModel)) return {};\n return { duration };\n}\n\n/**\n * The `generate_audio` param, or {} when the model has no toggle. A model without\n * one (Omni) always produces audio, so a caller asking for a silent clip gets\n * sound anyway — the spine mutes it downstream rather than the model omitting it.\n */\nexport function videoAudioParam(videoModel: string, generateAudio: boolean): { generate_audio?: boolean } {\n if (!VIDEO_MODELS_WITH_AUDIO_TOGGLE.has(videoModel)) return {};\n return { generate_audio: generateAudio };\n}\n","import { BlueprintFloatingElementSchema, type CompositionRegion, type VideoScene } from \"@baker/canvas-contract\";\nimport { z } from \"zod\";\nimport type { ClipPromptProfile } from \"../../../lib/prompt-profiles.ts\";\nimport { diegeticFor, type ShootMode, seedanceMotionFor } from \"../../lib/shoot-modes.ts\";\nimport { localizeNumeralsForNative } from \"../dialogue/numbers.ts\";\nimport type { ElementSlot } from \"../elements.ts\";\nimport { compositePlateRegion, UI_SURFACE_RE } from \"../routing.ts\";\nimport type { TimelineEnv } from \"../timeline-env.ts\";\n\n/**\n * The raw ASR transcript for a clip prompt — silent clips only. On a NATIVE clip the\n * Dialogue line is authoritative; echoing the transcript there doubles the chance\n * Seedance vocalizes recognition noise (mis-heard brand names, stutter fragments).\n */\nfunction silentClipTranscript(scene: VideoScene, native: boolean): string {\n if (native) return \"\";\n return (scene.transcript_slice ?? [])\n .map((w) => w.text?.trim())\n .filter(Boolean)\n .join(\" \")\n .trim();\n}\n\n/**\n * The diegetic audio line for a Seedance clip, or null when the clip is silent.\n * Native sound is generated, so when audio is on we name the diegetic ambience the\n * clip should produce and forbid music outright — the music bed is a separate,\n * ducked track and a Seedance-invented soundtrack would fight it. Ambient defaults\n * to the shoot mode's ambience when the scene names none.\n */\nfunction seedanceAudioLine(scene: VideoScene, mode: ShootMode, audio: boolean, nativeLine?: string): string | null {\n const ambient = scene.ambient?.trim() || diegeticFor(mode);\n if (nativeLine) {\n return `Audio: diegetic only — the speaker's own voice over ${ambient}; no music, no song, no soundtrack (the music bed is a separate track).`;\n }\n if (audio) {\n return `Audio: diegetic ambient only — ${ambient}; no spoken dialogue, no music, no song, no soundtrack (voice and music are separate tracks).`;\n }\n return null;\n}\n\n// Words too generic to identify a floating element (they'd nuke innocent sentences).\nconst FLOAT_STOP_WORDS = new Set([\n \"with\",\n \"across\",\n \"around\",\n \"above\",\n \"below\",\n \"over\",\n \"under\",\n \"screen\",\n \"frame\",\n \"scene\",\n \"video\",\n \"element\",\n \"elements\",\n \"graphic\",\n \"overlay\",\n \"animated\",\n \"floating\",\n \"small\",\n \"large\",\n \"white\",\n \"black\",\n \"color\",\n \"colored\",\n]);\n\n/** Distinctive tokens of a floating element's description (for sentence matching). */\nfunction floatTokens(desc: string): string[] {\n return desc\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter((w) => w.length >= 4 && !FLOAT_STOP_WORDS.has(w));\n}\n\n/**\n * Drop brief sentences that narrate an overlay-routed floating element (FX like\n * floating hearts, badges, torn-paper wipes). The element rides the hyperframes\n * overlay layer as a REAL asset — narrating it in the motion brief makes Seedance\n * bake a second, uneditable copy underneath (the double-phone defect class, for FX).\n * A sentence is dropped when it shares ≥2 distinctive tokens with one float.\n */\nexport function scrubFloatSentences(text: string, floatDescs: string[]): string {\n if (floatDescs.length === 0 || !text) return text;\n const tokenSets = floatDescs.map((d) => new Set(floatTokens(d)));\n const kept = text\n .split(/(?<=[.!?])\\s+/)\n .filter((sentence) => {\n const words = new Set(floatTokens(sentence));\n return !tokenSets.some((ts) => {\n let hits = 0;\n for (const w of words) if (ts.has(w)) hits++;\n return hits >= 2;\n });\n })\n .join(\" \")\n .trim();\n return kept;\n}\n\n/** The scene's floating-element descriptions (all ride the overlay layer). */\nfunction sceneFloatDescs(scene: VideoScene): string[] {\n const floats = z.array(BlueprintFloatingElementSchema).safeParse(scene.floating_elements ?? []);\n if (!floats.success) return [];\n return floats.data.map((f) => f.description?.trim() ?? \"\").filter(Boolean);\n}\n\n/** The brief's visual lines: summary, action, camera, motion — plate-scoped when set. */\nfunction visualBriefParts(scene: VideoScene, sceneIndex: number, plate: CompositionRegion | null): string[] {\n const parts: string[] = [];\n const floats = sceneFloatDescs(scene);\n const scrub = (s: string | undefined): string | undefined => {\n if (!s) return s;\n const out = scrubFloatSentences(s, floats);\n return out || undefined;\n };\n const summary = scrub((plate ? plate.summary : scene.summary)?.trim());\n parts.push(summary ? `Scene ${sceneIndex + 1}: ${summary}` : `Scene ${sceneIndex + 1}`);\n const action = !plate ? scrub(scene.action_detail) : undefined;\n if (action) parts.push(`Action: ${action}`);\n const cm = scene.camera_motion;\n if (cm) {\n const camera = [cm.movement, cm.detail].filter(Boolean).join(\" — \");\n if (camera) parts.push(`Camera: ${camera}`);\n }\n const motion = scrub(plate ? plate.motion_prompt : scene.motion_prompt);\n if (motion) parts.push(`Motion: ${motion}`);\n // A UI-flavored float (\"mobile screen recording card…\") is covered by the blanket\n // no-screen directive — quoting its description verbatim would prime the generator\n // with the exact words the plate scrub removed. Only non-UI FX floats are named.\n const uiFloats = floats.filter((d) => UI_SURFACE_RE.test(d));\n const fxFloats = floats.filter((d) => !UI_SURFACE_RE.test(d));\n if (plate || uiFloats.length > 0) {\n parts.push(\n \"NEVER render any screen, phone, app, website, or UI element — this clip is the clean background plate; the screen surface is composited on top later as a separate real layer.\",\n );\n }\n if (fxFloats.length > 0) {\n // Categorical on purpose: quoting the element's description verbatim (\"pink\n // hearts…\") primes the generator with exactly the words the scrub removed.\n parts.push(\n \"NEVER render floating decorative elements — no hearts, sparkles, confetti, badges, stickers, icons, or particle effects. They are composited later as a separate real overlay layer; the picture stays clean of them.\",\n );\n }\n return parts;\n}\n\n/**\n * The spoken-text lines of a clip prompt: the native dialogue directive (per-model\n * syntax), or the silent clip's spoken context + transcript. Numbers in anything the\n * model can vocalize are spelled into the spoken language by `loc` — a bare \"6930\"\n * reintroduces the English digits the localization just fixed.\n */\nfunction spokenTextParts(\n scene: VideoScene,\n nativeLine: string | undefined,\n loc: (s: string) => string,\n profile: ClipPromptProfile,\n // Which variety of the language the speech is in. The model picks one otherwise, and\n // picks the commonest: ads set in Spain came back in Latin American Spanish, which the\n // pinned peninsular voice could not undo because the re-voicing keeps the delivery.\n spokenAccent?: string,\n): string[] {\n const parts: string[] = [];\n if (nativeLine) {\n // Native talking head: the model generates the speech + matching lip-sync. Spell any\n // numbers into the target language so they aren't read in English. Delivery is carried\n // in prose around the quoted line (both Seedance 2.0 and Veo — brackets misfire).\n parts.push(profile.dialogueDirective(loc(nativeLine), spokenAccent));\n } else {\n const lines = (scene.dialogue ?? []).map((d) => d.line?.trim()).filter((l): l is string => Boolean(l));\n if (lines.length > 0)\n parts.push(`Spoken context (do not render as audio): ${lines.map((l) => `\"${l}\"`).join(\" \")}`);\n }\n const transcript = silentClipTranscript(scene, Boolean(nativeLine));\n if (transcript) parts.push(`Transcript: ${loc(transcript)}`);\n return parts;\n}\n\n/** What one generated clip shows and says: the input its prompt and its node are built from. */\nexport type ClipShot = {\n /** The scene, or one region's view of it. */\n scene: VideoScene;\n index: number;\n /** The region of a composited scene the clip renders; absent for a full-frame scene. */\n region?: number;\n /** The recurring elements the clip keeps consistent with their references. */\n present: ElementSlot[];\n mode: ShootMode;\n /** The line the model voices itself; undefined for b-roll or narration over the picture. */\n nativeLine?: string;\n /** Whether the clip is generated WITH native audio: a native line, or opt-in ambient b-roll. */\n audio: boolean;\n /**\n * The scene's screen/graphic surface rides the overlay layer (see uiRoutedSceneSet), so\n * the clip renders the background plate only.\n */\n uiRouted: boolean;\n};\n\n/**\n * Compose the ultra-detailed motion brief handed to the video model for one clip.\n *\n * When `shot.nativeLine` is set, the scene's single on-camera speaker is voiced by the\n * model NATIVELY: the line goes in double quotes (Seedance keys on quoted speech to\n * generate matching lip movements + voice), with `generate_audio` on the clip. The native\n * voice is then normalized to the brand voice downstream (`audio_voice_convert`). Without\n * one the scene is b-roll or narration-over-picture: the spoken lines are kept only as\n * context (the clip is generated silent) and the voiceover is a separate tts track.\n *\n * The prompt follows the video model's profile (dialogue syntax, model-specific hard\n * rules). Numerals are spelled into `env.ttsLanguageCode`'s words ONLY in text the model\n * SPEAKS (the quoted line and the transcript): Seedance has no language hint, so \"6930\" is\n * read in English even in a French line. Visual descriptions keep their digits: they\n * describe on-screen figures (a progress bar's \"4%\", a price tag), and spelling those\n * corrupted the picture (\"quattro% to diciassette%\").\n */\nexport function buildClipPrompt(\n shot: ClipShot,\n env: Pick<TimelineEnv, \"clipProfile\" | \"ttsLanguageCode\" | \"spokenAccent\">,\n): string {\n const { scene, nativeLine, present, mode } = shot;\n const profile = env.clipProfile;\n // On a native clip, spell numerals in the text Seedance SPEAKS; no-op for a silent clip.\n const loc = (s: string): string => (nativeLine ? localizeNumeralsForNative(s, env.ttsLanguageCode) : s);\n // A UI-routed composite renders as a plain background plate (the screen surface is\n // composited later as a REAL overlay layer) — so the brief must describe the PLATE\n // region only. The scene-level summary/action/motion narrate the overlay (\"share\n // options menu slides up…\"), and passing them through made Seedance hallucinate a\n // garbled UI underneath the real composited one.\n // With every region a UI surface (no camera plate at all) fall back to an empty\n // plate: a bare \"Scene N\" line plus the no-screen directive beats narrating the UI.\n const plate = shot.uiRouted ? (compositePlateRegion(scene) ?? {}) : null;\n const parts: string[] = visualBriefParts(scene, shot.index, plate);\n // On a plate clip, drop UI-surface elements from the consistency line — naming the\n // app's reference here is an instruction to render it.\n const refs = plate ? present.filter((s) => !UI_SURFACE_RE.test(s.description ?? \"\")) : present;\n if (refs.length > 0) {\n parts.push(\n `Keep these consistent with their references: ${refs.map((s) => `${s.label} (${s.description ?? s.type})`).join(\"; \")}`,\n );\n }\n parts.push(...spokenTextParts(scene, nativeLine, loc, profile, env.spokenAccent));\n const audioLine = seedanceAudioLine(scene, mode, shot.audio, nativeLine);\n if (audioLine) parts.push(audioLine);\n // Motion-brief directives: the start/end frames already encode the content, so\n // the clip prompt must describe MOTION ONLY and stay short — verbosity makes the\n // model skip beats. The camera default is shoot-mode specific (UGC locks; studio\n // and lifestyle may permit a slow motivated move), and a named move always wins.\n parts.push(\n `Direction: describe MOTION ONLY — the frames carry the content; keep it short. ${seedanceMotionFor(mode)} ` +\n \"Spell choreography move-by-move (not 'she dances' but the actual beats: head nod, shoulder roll, knee dip). \" +\n \"One short continuous beat with real physical weight on any impact. \" +\n \"Describe any person by role and wardrobe, never by name or age.\",\n );\n // The image-to-video keyframe carries the content; tell the model to hold it. Model-\n // specific: Seedance keeps composition/colors, Veo describes the transition instead.\n parts.push(profile.keyframeInstruction);\n // Models with no negative_prompt param (Seedance) carry anti-artifact intent as an\n // AFFIRMATIVE stability line — a positive \"keep it clean\" beats an \"Avoid:\" list, which\n // tends to plant the artifact it names (seedance-mechanics.md §3). Veo/Kling route this\n // through their negative_prompt param instead, so their list stays empty here.\n if (profile.stabilityDirectives.length > 0)\n parts.push(`Keep it clean and stable: ${profile.stabilityDirectives.join(\"; \")}.`);\n parts.push(...profile.extraDirectives);\n return parts.join(\"\\n\");\n}\n","import { canSpellNumbers, spellNumber } from \"../../../lib/spell-number.ts\";\n\n// --- Numeral → words, for NATIVE (Seedance) dialogue only. ---\n// A `tts` node gets `language_code`, so ElevenLabs reads its numbers in the right\n// tongue. But a NATIVE talking clip's line is voiced by Seedance, which has no\n// language hint — so a bare \"6930\" in a French line is read in English (\"six\n// thousand nine hundred thirty\"), the reported defect. Spelling the number into\n// target-language words in the QUOTED dialogue forces the right pronunciation (and\n// the lips follow the words). Every language the blueprint can resolve has a speller\n// (`engine/lib/spell-number.ts`); a language we can't resolve leaves digits (the `tts` path still\n// localizes them via language_code).\n\n/**\n * Spell standalone integers in `text` into `langCode` words, for a NATIVE spoken line.\n * Leaves the text untouched when there's no speller for the language. Only plain\n * integers up to 9 digits are converted (prices/counts); anything with a decimal,\n * separators, or an adjacent letter/digit/hyphen (e.g. \"1er\", a \"555-1234\" phone\n * number, a \"30-second\" range) is left alone — `-` is in the boundary set so neither\n * half of a hyphenated number is spelled in isolation.\n */\nexport function localizeNumeralsForNative(text: string, langCode: string | undefined): string {\n if (!langCode || !canSpellNumbers(langCode)) return text;\n return text.replace(/(?<![\\w.,-])\\d{1,9}(?![\\w.,-])/g, (m) => spellNumber(langCode, Number.parseInt(m, 10)));\n}\n","import { supportsLastFrame } from \"@baker/canvas-contract\";\nimport { clipParamRecipe } from \"../../../lib/prompt-profiles.ts\";\nimport type { NodeDecl } from \"../../../schema/canvas.ts\";\nimport { clipIntent } from \"../../lib/scene-role.ts\";\nimport { canvasDims } from \"../aspect.ts\";\nimport { emitAmbientExtract } from \"../dialogue/voices.ts\";\nimport { slotsForFrame } from \"../elements.ts\";\nimport { trimArgs } from \"../ffmpeg-args.ts\";\nimport { buildFrameRef } from \"../frames.ts\";\nimport { ids, ref, sceneTags } from \"../ids.ts\";\nimport { videoAudioParam, videoDurationParam, videoResolutionParam } from \"../model-params.ts\";\nimport { buildClipPrompt, type ClipShot } from \"../prompts/clip.ts\";\nimport type { SceneClip, SceneCtx, TimelineEnv } from \"../timeline-env.ts\";\n\n/** The keyframes a clip is conditioned on. A model that takes one image drops `last`. */\nexport type ClipFrames = { first: string; last?: string };\n\n/**\n * The `video_generate` node for one clip — every clip the scaffold bills is built here, the\n * b-roll shot, a composite's region and a presenter's phrase alike, so they cannot drift\n * apart in the params that decide what the provider renders and what the cache keys on.\n *\n * `genDur` is a length the model renders (`ceilToDurations`), at least the window the clip\n * fills. An end frame can exist purely as the NEXT scene's splice frame, so having one is not\n * permission to wire it: a model that takes a single conditioning image silently drops it.\n */\nexport function clipNode(shot: ClipShot, env: TimelineEnv, frames: ClipFrames, genDur: number): NodeDecl {\n const videoModel = env.opts.videoModel;\n return {\n id: ids.clip(shot.index, shot.region),\n type: \"video_generate\",\n tags: sceneTags(shot.index, \"clip\", shot.region),\n inputs: {\n first_frame: frames.first,\n ...(frames.last && supportsLastFrame(videoModel) ? { last_frame: frames.last } : {}),\n },\n params: {\n model: videoModel,\n // Per-model request defaults (Veo: person_generation=allow_adult + a caption-\n // suppressing negative_prompt). Spread first so the explicit fields below win.\n ...env.clipProfile.paramDefaults,\n prompt: buildClipPrompt(shot, env),\n ...videoDurationParam(videoModel, genDur),\n ...videoResolutionParam(videoModel, env.opts.resolution),\n // Native talking scene → the model generates the spoken audio + lip-sync; an opt-in\n // ambient b-roll beat generates diegetic ambient only; otherwise the clip is silent.\n ...videoAudioParam(videoModel, shot.audio),\n // Intent-keyed \"astonishing default\" overrides — merged LAST so a hero/reveal\n // beat can claim the 1080p ceiling over the aspect-derived resolution.\n ...clipParamRecipe(\n videoModel,\n env.clipProfile,\n clipIntent(shot.scene.narrative_role, shot.index, shot.scene.motion_level),\n ),\n aspect_ratio: env.genAr,\n },\n };\n}\n\n/**\n * Emit one scene's `video_generate` clip and return the SceneClip. Both keyframes are\n * wired (`first_frame` + `last_frame`) so the model interpolates real in-shot motion.\n * The clip is generated at one of the model's fixed durations (>= the scene length), so\n * it must be cut back to the EXACT scene length — a duration-snap so the picture stays on\n * the absolute-timed audio (and a clip generated at another ratio than the output canvas\n * is normalized onto it). A SPINE-destined clip (`defer`) carries that cut as\n * SceneClip.trim, absorbed into the `video_concat` spine's per-input chain, with no\n * standalone node; a clip consumed elsewhere (a composite region) still emits the\n * `s<i>_clip_trim` ffmpeg node, because its consumer isn't the spine.\n */\nexport function emitSceneClip(\n ctx: SceneCtx,\n shot: ClipShot,\n frames: ClipFrames,\n spine: { out: SceneClip[\"out\"]; defer: boolean },\n): SceneClip {\n const { env, lengths } = ctx;\n ctx.out.nodes.push(clipNode(shot, env, frames, lengths.genDur));\n const base = ref(ids.clip(shot.index, shot.region), \"video\");\n // A clip generated at a DIFFERENT ratio than the output canvas (Seedance has no 4:5)\n // must be normalized (scale-to-fill, center-crop) before it enters the spine — the\n // raw-clip fast path is only safe when the two ratios match.\n const normDims = env.genAr !== env.outAr ? canvasDims(env.outAr) : undefined;\n if (lengths.genDur === lengths.trimTarget && !normDims) return { ref: base, scene_s: lengths.dur, out: spine.out };\n // A spine-destined clip defers the duration-snap to the spine's per-input chain\n // (the spine always normalizes the raster, so the remap case is covered for free).\n if (spine.defer) {\n return {\n ref: base,\n scene_s: lengths.dur,\n out: spine.out,\n ...(lengths.genDur !== lengths.trimTarget ? { trim: { offset_s: 0 } } : {}),\n };\n }\n // Every model renders a fixed set of durations; this trims the generated clip down to\n // the exact window length so each segment sits flush on the timeline (and normalizes\n // remapped-ratio clips onto the output canvas).\n const trimId = ids.clipTrim(shot.index, shot.region);\n ctx.out.nodes.push({\n id: trimId,\n type: \"ffmpeg\",\n tags: sceneTags(shot.index, \"clip_trim\", shot.region),\n inputs: { clip: base },\n params: { args: trimArgs(lengths.trimTarget, 0, normDims), outputs: { video: { kind: \"video\", ext: \"mp4\" } } },\n });\n return { ref: ref(trimId, \"video\"), scene_s: lengths.dur, out: spine.out };\n}\n\n/**\n * A b-roll scene's conditioning keyframes. Independent start AND end frames (the model\n * interpolates real motion between them), each grounded on its OWN extracted frame —\n * no cross-frame cascade, renders in parallel. Two exceptions: a continuation of the\n * same shot starts from the PREVIOUS scene's end frame (seamless splice), and a SHORT\n * (≤4s, one Seedance floor clip) take skips the end keyframe entirely — over so short\n * a span the second keyframe adds no motion guidance, so it's a billed image that buys\n * nothing — unless the NEXT scene continues this take and needs the shared splice frame.\n */\nfunction brollKeyframes(\n ctx: SceneCtx,\n prevEndFrame: string | undefined,\n): { first: string; last: string | undefined; sharesPrevFrame: boolean } {\n const { env, scene, index } = ctx;\n const sharesPrevFrame = Boolean(scene.continues_previous && prevEndFrame);\n const first =\n sharesPrevFrame && prevEndFrame\n ? prevEndFrame\n : buildFrameRef(ctx, {\n edge: \"start\",\n url: scene.start_frame_asset?.url,\n prompt: scene.start_frame_prompt,\n present: slotsForFrame(env.slots, index, \"start\"),\n });\n // The end keyframe earns its cost two ways: the model interpolates between the\n // pair (and the shot is long enough to be worth guiding), or the NEXT scene\n // continues this take and splices from it. A one-image model (Omni) satisfies\n // neither on its own, so it only gets one when the splice needs it — otherwise\n // this is a billed image_generate per clip that the renderer discards.\n const nextContinues = Boolean(env.blueprint.scenes[index + 1]?.continues_previous);\n const guidesMotion = supportsLastFrame(env.opts.videoModel) && ctx.lengths.trimTarget > 4;\n const last =\n guidesMotion || nextContinues\n ? buildFrameRef(ctx, {\n edge: \"end\",\n url: scene.end_frame_asset?.url,\n prompt: scene.end_frame_prompt,\n present: slotsForFrame(env.slots, index, \"end\"),\n })\n : undefined;\n return { first, last, sharesPrevFrame };\n}\n\n/**\n * The `clip` route: a b-roll scene (no presenter shown) as its own silent clip — or, with\n * `ambient`, a clip carrying its diegetic ambience, extracted and laid deep under the bed.\n * Returns this scene's END keyframe ref so the next scene, if it is a continuation of the\n * same shot (`continues_previous`), can reuse it as its start frame for a seamless splice.\n */\nexport function emitClipScene(ctx: SceneCtx, prevEndFrame: string | undefined, ambient: boolean): string | undefined {\n const { env, index } = ctx;\n const { first, last, sharesPrevFrame } = brollKeyframes(ctx, prevEndFrame);\n const shot: ClipShot = {\n scene: ctx.scene,\n index,\n present: ctx.present,\n mode: ctx.mode,\n audio: ambient,\n uiRouted: env.uiRouted.has(index),\n };\n const clip = emitSceneClip(ctx, shot, { first, last }, { out: ctx.lengths.out, defer: true });\n if (ambient) emitAmbientExtract(ctx, ref(ids.clip(index), \"video\"));\n ctx.out.clips.push(sharesPrevFrame ? { ...clip, continuesFrame: true } : clip);\n ctx.out.routes.set(index, \"clip\");\n return last;\n}\n","import type { VideoBlueprint, VideoScene } from \"@baker/canvas-contract\";\nimport type { ClipPromptProfile } from \"../../lib/prompt-profiles.ts\";\nimport type { NodeDecl } from \"../../schema/canvas.ts\";\nimport { deriveShootMode, type ShootMode } from \"../lib/shoot-modes.ts\";\nimport type { AudioTrack } from \"./audio.ts\";\nimport { isOnCameraSpeaker } from \"./dialogue/speakers.ts\";\nimport type { NativeSegment } from \"./dialogue/voices.ts\";\nimport { type ElementSlot, slotsForScene } from \"./elements.ts\";\nimport type { ScaffoldVideoOpts } from \"./opts.ts\";\nimport { type SceneLengths, type SpineClock, sceneTiming } from \"./timing.ts\";\n\n// One concatenated scene clip: the picture ref, the scene's on-timeline length,\n// and its outgoing transition (null = hard cut). `scene_s` is the length the scene\n// occupies on the final timeline — the xfade overlap is consumed from EXTRA footage\n// (the clip is trimmed to `scene_s + out.dur`), so the totals stay timeline-exact.\nexport type SceneClip = {\n ref: string;\n scene_s: number;\n out: { xfade: string; dur: number } | null;\n // True when this clip's FIRST frame is the previous clip's LAST frame (a shared splice\n // frame from a length-split shot). The spine drops the duplicate per `opts.seamDedup`.\n continuesFrame?: boolean;\n // Per-input work the `video_concat` spine absorbs into its own chain instead of a\n // standalone ffmpeg node: cut a longer clip to the scene window (`trim`, its clip\n // `length: \"trim\"`) or hold a still image/screenshot for the scene length (`still`).\n // The input length is always `scene_s + out.dur`.\n trim?: { offset_s: number };\n still?: { fit: \"fill\" | \"pad\" };\n};\n\n/**\n * A line the video model voices itself, in the clip it generates: one on-camera speaker's\n * words, their spoken window on the reference clock, and the casting their voice resolves to.\n */\nexport type NativeTurn = {\n text: string;\n start_s: number;\n end_s: number;\n // The shared voice_select node casting this speaker (brand voice).\n voiceNode: string;\n};\n\n// `onCamera`: the speaker's own lip-synced voice (a native clip's converted audio), as\n// opposed to a read over the picture. Internal: stripped from the canvas metadata.\nexport type VoSeg = { slot: string; start_s: number; end_s: number; scene: number; speaker: string; onCamera: boolean };\nexport type TalkScene = {\n scene: number;\n voice_convert_node: string;\n scene_s?: number;\n est_speech_s?: number;\n speech_words?: number;\n};\n// A presenter scene's window cut from its phrase clip. `skip` marks a scene whose window\n// was FOLDED into a preceding scene's merged run-segment — the spine emits nothing for it\n// (its picture already rides the earlier segment), it exists only so the dispatch loop\n// doesn't fall the scene through to the b-roll path.\nexport type SliceInfo = {\n clipRef: string;\n offset: number;\n len: number;\n clipDur: number;\n skip?: boolean;\n // True when this slice's clip starts on the previous phrase clip's shared end frame (a\n // length-split of the same shot) — the spine seam-dedups the duplicated boundary frame.\n continuesFrame?: boolean;\n};\n\n/** The canvas-wide facts every scene is emitted against, each computed once per scaffold. */\nexport type TimelineEnv = {\n blueprint: VideoBlueprint;\n // The spine clock — every absolute placement (voice, SFX, ambient) maps through it.\n clock: SpineClock;\n slots: ElementSlot[];\n opts: ScaffoldVideoOpts;\n // The ad's true output ratio (drives every ffmpeg dim + composite canvas)…\n outAr: string;\n // …and the ratio clips/keyframes GENERATE at (the video model's nearest supported\n // ratio). When they differ, every clip is normalized to outAr before the spine.\n genAr: string;\n /** The clip lengths the video model renders (`clipDurationSet`); its longest is the scene ceiling. */\n durationSet: readonly number[];\n ceilingS: number;\n /** The video model's prompt profile: Seedance's when the model has none of its own. */\n clipProfile: ClipPromptProfile;\n reuse: boolean;\n /**\n * The source ad shows people somewhere (a cast, or a recurring person element).\n * Then no generated frame takes a source frame as a reference: which scenes a person\n * is in is a model's guess, and one frame it misses hands the image model the source\n * actor's face, which it copies whatever the prompt says.\n */\n sourceShowsPeople: boolean;\n cameraOn: boolean;\n casts: Set<string>;\n /** Folds a speaker label onto the one voice it belongs to (see `collapseVoiceover`). */\n canonical: (speaker: string) => string;\n // Shared across all frames in a canvas: a source-frame URL → its ingest ref, so\n // the same extracted frame is ingested ONCE and reused (no duplicate ingest nodes\n // when two scenes happen to share a frame URL).\n ingestCache: Map<string, string>;\n // Scene indexes whose screen/graphic surface routes to the overlay layer (per\n // persistent layout, see uiRoutedSceneSet) — their clips render the plate only.\n uiRouted: Set<number>;\n // Scene indexes reproduced as a real designed-graphic plate (typed full-frame\n // static_graphic scenes, closed over continues_previous chains — one take is one\n // content class, so an untyped chain member inherits its sibling's graphic route).\n graphicScenes: Set<number>;\n // surface_id → ingest node id: scenes sharing one checker-owned surface reuse ONE\n // supplied design asset instead of stubbing a TODO ingest per scene.\n surfaceIngests: Map<string, string>;\n // ISO 639-1 of the spoken track (when known), stamped onto every tts node.\n ttsLanguageCode?: string;\n // The spoken language's English name, the hard filter `voice_select` casts on.\n spokenLanguageName?: string;\n spokenAccent?: string;\n /** See `ScaffoldVideoOpts.keepRenderedVoice`. */\n keepRenderedVoice?: boolean;\n};\n\n// The mutable sinks the timeline helpers append to.\nexport type TimelineOut = {\n nodes: NodeDecl[];\n clips: SceneClip[];\n voTracks: AudioTrack[];\n voSegments: VoSeg[];\n talkingScenes: TalkScene[];\n nativeSegments: NativeSegment[];\n sceneSlice: Map<number, SliceInfo>;\n // Per-scene route the dispatcher took — stamped into metadata.video.graph_stats so\n // an operator can see WHY each scene got its nodes (the \"why so many nodes\" answer).\n routes: Map<number, SceneRoute>;\n // The previous phrase clip's END keyframe ref and the scene it depicts, so a\n // mid-take follow-up phrase can chain from it (shared splice frame, no jump).\n phraseEnd?: { ref: string; scene: number };\n /** The casting of each speaker: returns their voice_select node, emitting it on first use. */\n voiceOf: (speaker: string) => string;\n /** Ids already taken by `tts` reads, so two reads of one speaker never collide. */\n readIds: Set<string>;\n};\n\n// How a scene's picture is produced. clip = its own billed video_generate; still_hold =\n// a generated keyframe looped on the spine; screen_still / graphic_plate = a REAL\n// ingest looped on the spine; brand_card = a colour plate; phrase_slice = a window cut\n// from its phrase's talking clip; phrase_run = folded into a preceding merged slice;\n// composite = stacked/overlaid region clips.\nexport type SceneRoute =\n | \"clip\"\n | \"still_hold\"\n | \"screen_still\"\n | \"graphic_plate\"\n | \"brand_card\"\n | \"phrase_slice\"\n | \"phrase_run\"\n | \"composite\";\n\n/** One scene, as every route that emits it sees it: the canvas, the sinks, and what the scene is. */\nexport type SceneCtx = {\n env: TimelineEnv;\n out: TimelineOut;\n index: number;\n scene: VideoScene;\n isLast: boolean;\n /** The recurring-element slots present anywhere in the scene. */\n present: ElementSlot[];\n mode: ShootMode;\n lengths: SceneLengths;\n};\n\n/** The shoot mode for a scene: an explicit override wins, else auto-derive from talking/cast/product presence. */\nfunction sceneShootMode(\n scene: VideoScene,\n present: ElementSlot[],\n nativeTurn: NativeTurn | undefined,\n env: TimelineEnv,\n): ShootMode {\n // A \"talking\" beat (→ selfie look) = an on-camera cast member speaks: native\n // single-speaker OR a multi-speaker on-camera scene.\n const talking =\n Boolean(nativeTurn) ||\n (env.cameraOn &&\n (scene.dialogue ?? []).some(\n (d) => d.line?.trim() && isOnCameraSpeaker(d.speaker ?? \"voiceover\", env.casts, env.cameraOn),\n ));\n return deriveShootMode({\n explicit: scene.shoot_mode,\n talking,\n hasPerson: present.some((s) => s.type.toLowerCase() === \"person\" || s.type.toLowerCase() === \"animal\"),\n hasProduct: present.some((s) => s.type.toLowerCase() === \"product\"),\n });\n}\n\n/** The context scene `index` is emitted in, given the line (if any) the video model voices in it. */\nexport function sceneCtx(env: TimelineEnv, out: TimelineOut, index: number, nativeTurn?: NativeTurn): SceneCtx {\n const scene = env.blueprint.scenes[index];\n if (!scene) throw new Error(`scaffold invariant: scene ${index} does not exist`);\n const present = slotsForScene(env.slots, index);\n const isLast = index === env.blueprint.scenes.length - 1;\n return {\n env,\n out,\n index,\n scene,\n isLast,\n present,\n mode: sceneShootMode(scene, present, nativeTurn, env),\n lengths: sceneTiming(scene, isLast, nativeTurn?.text, env.durationSet),\n };\n}\n","import {\n type BlueprintDialogueLine,\n type CompositionRegion,\n type SceneComposition,\n supportsLastFrame,\n type VideoScene,\n} from \"@baker/canvas-contract\";\nimport { estSpeechS, estSpeechWindowS, wordCount } from \"../../../lib/speech.ts\";\nimport { canvasDims } from \"../aspect.ts\";\nimport { isOnCameraSpeaker } from \"../dialogue/speakers.ts\";\nimport { emitNativeExtract, emitPhraseTts } from \"../dialogue/voices.ts\";\nimport type { ElementSlot } from \"../elements.ts\";\nimport { pipOverlayArgs, splitStackArgs } from \"../ffmpeg-args.ts\";\nimport { buildFrameRef } from \"../frames.ts\";\nimport { ids, ref, sceneTags } from \"../ids.ts\";\nimport { compositeRegionsOf } from \"../routing.ts\";\nimport {\n type NativeTurn,\n type SceneClip,\n type SceneCtx,\n sceneCtx,\n type TimelineEnv,\n type TimelineOut,\n} from \"../timeline-env.ts\";\nimport { sceneDurationS } from \"../timing.ts\";\nimport { emitSceneClip } from \"./clip.ts\";\n\n/** A scene's spatial layout when it is layered: which layout, its regions, and the raw composition. */\nexport type LayeredComposition = { layout: string; regions: CompositionRegion[]; comp: SceneComposition };\n\n/** A scene's layered composition, or null when it's a plain full-frame shot. */\nexport function layeredComposition(\n scene: VideoScene,\n // True when this scene's layout run is UI-routed (see uiRoutedSceneSet): the real\n // screen/graphic surface is composited on the overlay layer, so the scene drops to\n // the single-shot path (one clean background plate) — a Seedance split would garble\n // the UI and leave a stack seam.\n uiRouted: boolean,\n): LayeredComposition | null {\n const regions = compositeRegionsOf(scene);\n // Need ≥2 streams to composite; otherwise fall back to the single-shot path.\n if (!regions) return null;\n if (uiRouted) return null;\n return { layout: (scene.composition?.layout ?? \"\").toLowerCase(), regions, comp: scene.composition ?? {} };\n}\n\n/**\n * Stack direction for a split, derived from the region PANELS (authoritative — a\n * model labels top/bottom reliably but conflates split_axis \"horizontal\" with a\n * horizontal dividing LINE). top/bottom ⇒ vertical (vstack); left/right ⇒ horizontal\n * (hstack); fall back to split_axis only when panels are unlabeled.\n */\nfunction splitAxisOf(comp: SceneComposition, regions: CompositionRegion[]): \"vertical\" | \"horizontal\" {\n const panels = regions.map((r) => (r.panel ?? \"\").toLowerCase());\n if (panels.some((p) => p === \"top\" || p === \"bottom\")) return \"vertical\";\n if (panels.some((p) => p === \"left\" || p === \"right\")) return \"horizontal\";\n return (comp.split_axis ?? \"\").toLowerCase() === \"horizontal\" ? \"horizontal\" : \"vertical\";\n}\n\n/** A panel label's visual rank along the stack axis (numbered labels are explicit). */\nfunction panelRank(panel: string | undefined, axis: \"vertical\" | \"horizontal\"): number {\n const p = (panel ?? \"\").toLowerCase();\n // A numbered label (\"panel 2\", \"p3\") is an explicit order — honor it directly.\n const numbered = /(\\d+)/.exec(p);\n if (numbered) return Number(numbered[1]);\n if (axis === \"vertical\") return p === \"top\" ? 0 : p === \"bottom\" ? 2 : 1;\n return p === \"left\" ? 0 : p === \"right\" ? 2 : 1;\n}\n\n/**\n * Order split-screen region refs into VISUAL stacking order for the axis: top before\n * bottom (vertical), left before right (horizontal). The `panel` label carries the\n * placement; the `regions` array order does not, so without this a model that lists the\n * bottom/right panel first would render the split inverted. A stable sort keeps the\n * original order among unlabeled panels.\n */\nexport function orderSplitRefs(\n regions: CompositionRegion[],\n regionRefs: string[],\n axis: \"vertical\" | \"horizontal\",\n): string[] {\n return regionRefs\n .map((input, k) => ({ input, k, rank: panelRank(regions[k]?.panel, axis) }))\n .sort((a, b) => a.rank - b.rank || a.k - b.k)\n .map((x) => x.input);\n}\n\n// A region holds the presenter (the lip-synced talking head) when it's flagged\n// is_presenter; a person/animal region wins by default when a scene has spoken audio\n// but the model forgot the flag (so the voice always lands on a real mouth).\nfunction presenterIndexOf(regions: CompositionRegion[], hasNative: boolean): number {\n const flagged = regions.findIndex((r) => r.is_presenter);\n if (flagged >= 0) return flagged;\n return hasNative ? 0 : -1;\n}\n\n/** The recurring-element slots that belong to ONE region: the presenter region gets\n * the people/animals present in the scene; b-roll/background regions get the sets,\n * products, and logos (so the right reference grounds the right panel). */\nfunction slotsForRegion(present: ElementSlot[], isPresenter: boolean): ElementSlot[] {\n return present.filter((s) => {\n const t = s.type.toLowerCase();\n const person = t === \"person\" || t === \"animal\";\n return isPresenter ? person : !person;\n });\n}\n\ntype SpokenLine = BlueprintDialogueLine & { line: string };\n\n/**\n * Who speaks on camera in a composite scene. The video model voices ONE mouth per clip,\n * so a composite with two+ distinct on-camera speakers can't be voiced natively under a\n * single voice (that would put both lines in the first speaker's voice). Only a\n * single-voice composite goes native; a multi-speaker one renders silent and reads each\n * speaker as a tts track, mirroring the plain-scene multi-speaker fallback in `buildPhrases`.\n */\nexport function compositeVoicing(\n scene: VideoScene,\n env: Pick<TimelineEnv, \"casts\" | \"cameraOn\" | \"canonical\">,\n): { lines: SpokenLine[]; speakers: Set<string>; native: boolean } {\n const lines = (scene.dialogue ?? []).filter(\n (l): l is SpokenLine =>\n Boolean(l.line?.trim()) && isOnCameraSpeaker(l.speaker ?? \"voiceover\", env.casts, env.cameraOn),\n );\n const speakers = new Set(lines.map((l) => env.canonical(l.speaker ?? \"voiceover\")));\n return { lines, speakers, native: lines.length > 0 && speakers.size === 1 };\n}\n\n/**\n * Reproduce a COMPOSITED scene: build one clip per region (its own frames + motion\n * brief), then stack (split-screen) or overlay (PIP / keyed presenter) them into one\n * picture. Returns the composited scene clip plus the PRESENTER region's raw clip ref\n * (the one carrying the spoken audio) so the per-speaker voice conversion extracts\n * from the right panel. Generate-mode only — `reuse` keeps the single-shot path.\n */\nfunction buildCompositeScene(\n ctx: SceneCtx,\n composite: LayeredComposition,\n nativeTurn: NativeTurn | undefined,\n): { clip: SceneClip; presenterClipRef: string | undefined } {\n const { env, scene, index } = ctx;\n const { layout, regions, comp } = composite;\n const presIdx = presenterIndexOf(regions, Boolean(nativeTurn));\n const regionRefs = regions.map((region, r) => {\n const isPresenter = r === presIdx;\n const regionSlots = slotsForRegion(ctx.present, isPresenter);\n // Independent start AND end keyframes (the model interpolates real in-shot motion).\n // Both ground only on el_*/recast — no cross-frame reference — so they render in parallel.\n // A one-image model gets no end frame: it would be a billed image_generate PER\n // REGION that the renderer discards.\n const first = buildFrameRef(ctx, {\n edge: \"start\",\n url: undefined,\n prompt: region.frame_prompt ?? scene.start_frame_prompt,\n present: regionSlots,\n region: r,\n });\n const last = supportsLastFrame(env.opts.videoModel)\n ? buildFrameRef(ctx, {\n edge: \"end\",\n url: undefined,\n prompt: region.frame_prompt ?? scene.end_frame_prompt,\n present: regionSlots,\n region: r,\n })\n : undefined;\n // The b-roll/background panels are silent; only the presenter panel speaks.\n const regionNative = isPresenter ? nativeTurn : undefined;\n const regionScene = {\n ...scene,\n summary: region.summary ?? scene.summary,\n motion_prompt: region.motion_prompt ?? scene.motion_prompt,\n dialogue: isPresenter ? scene.dialogue : [],\n };\n // A composite scene is never UI-routed: a scene whose own regions route to the overlay\n // layer is dropped to the single-shot path before it gets here (`layeredComposition`).\n const shot = {\n scene: regionScene,\n index,\n region: r,\n present: regionSlots,\n mode: ctx.mode,\n nativeLine: regionNative?.text,\n audio: Boolean(regionNative),\n uiRouted: false,\n };\n return emitSceneClip(ctx, shot, { first, last }, { out: null, defer: false }).ref;\n });\n\n const dims = canvasDims(env.outAr);\n const compInputs: Record<string, unknown> = {};\n let args: string[];\n if (layout === \"split_screen\") {\n const axis = splitAxisOf(comp, regions);\n // Stack panels in VISUAL order (top→bottom / left→right) per their `panel` label,\n // not in the order the model happened to list `regions` — splitStackArgs places c0\n // first (top/left), so an unordered array would render the split inverted.\n orderSplitRefs(regions, regionRefs, axis).forEach((input, k) => {\n compInputs[`c${k}`] = input;\n });\n args = splitStackArgs(regionRefs.length, axis, dims);\n } else {\n args = overlayRegions(ctx, composite, regionRefs, presIdx, compInputs);\n }\n const compositeId = ids.composite(index);\n ctx.out.nodes.push({\n id: compositeId,\n type: \"ffmpeg\",\n tags: sceneTags(index, \"composite\"),\n inputs: compInputs,\n params: { args, outputs: { video: { kind: \"video\", ext: \"mp4\" } } },\n });\n return {\n clip: { ref: ref(compositeId, \"video\"), scene_s: ctx.lengths.dur, out: ctx.lengths.out },\n presenterClipRef: presIdx >= 0 ? ref(ids.clip(index, presIdx), \"video\") : undefined,\n };\n}\n\n/**\n * pip / keyed_overlay: one region is the full-frame background, EVERY other region rides\n * on top as an inset (the presenter keyed = cut to transparency first). All regions\n * composite — each is a billed generated clip, and dropping any of them paid for a clip\n * that never reached the frame. Fills `compInputs` (c0 = background, c1.. = insets) and\n * returns the overlay argv.\n */\nfunction overlayRegions(\n ctx: SceneCtx,\n { layout, regions }: LayeredComposition,\n regionRefs: string[],\n presIdx: number,\n compInputs: Record<string, unknown>,\n): string[] {\n const bgIdx = regions.findIndex((_, k) => k !== presIdx);\n const effBgIdx = bgIdx >= 0 ? bgIdx : 0;\n // With no flagged presenter (presIdx -1) the schema convention holds: background\n // first, the overlaid region second — so the fallback presenter is regions[1].\n const effPresIdx = presIdx >= 0 ? presIdx : 1;\n // Only a flagged (or native) presenter's own position anchors it; the fallback one\n // takes the next free corner like any unlabeled inset.\n const presenterPosition = presIdx >= 0 ? regions[presIdx]?.position : undefined;\n compInputs.c0 = regionRefs[effBgIdx];\n // Unlabeled extra insets cascade through distinct corners so they never stack\n // on the presenter's slot.\n const cornerCascade = [\"top_left\", \"top_right\", \"bottom_left\", \"bottom_right\"];\n let cornerCursor = 0;\n const insets: Array<{ position?: string; wpct: number }> = [];\n regions.forEach((region, r) => {\n if (r === effBgIdx) return;\n const isPresenter = r === effPresIdx;\n let input = regionRefs[r];\n if (isPresenter && layout === \"keyed_overlay\") {\n // The green-screen look: strip the presenter's background to alpha, then overlay.\n // Applied to the FALLBACK presenter too — skipping the key when no region was\n // flagged is_presenter shipped an opaque box instead of a cut-out.\n const keyId = ids.key(ctx.index);\n ctx.out.nodes.push({\n id: keyId,\n type: \"video_background_remove\",\n tags: sceneTags(ctx.index, \"key\", r),\n inputs: { video: input },\n params: {},\n });\n input = ref(keyId, \"video\");\n }\n compInputs[`c${insets.length + 1}`] = input;\n const fallback = cornerCascade[cornerCursor++ % cornerCascade.length];\n insets.push({\n position: (isPresenter ? presenterPosition : region.position) ?? fallback,\n // Keyed cut-outs read as a larger presence than a boxed PIP pill.\n wpct: isPresenter && layout === \"keyed_overlay\" ? 0.5 : 0.34,\n });\n });\n return pipOverlayArgs(canvasDims(ctx.env.outAr), insets);\n}\n\n/**\n * The `composite` route: a split-screen / PIP / keyed-presenter scene, voiced on its own —\n * its single on-camera speaker natively (their line in the presenter region's clip, then\n * the per-speaker convert), or each of several speakers as their own tts read over the\n * silent composite. The caller breaks the continuation chain (a composite has no single\n * splice frame).\n */\nexport function emitCompositeScene(\n env: TimelineEnv,\n out: TimelineOut,\n index: number,\n composite: LayeredComposition,\n): void {\n const scene = env.blueprint.scenes[index];\n if (!scene) return;\n const voicing = compositeVoicing(scene, env);\n const [firstLine] = voicing.lines;\n let nativeTurn: NativeTurn | undefined;\n if (voicing.native && firstLine) {\n const lastLine = voicing.lines.at(-1) ?? firstLine;\n const start = firstLine.start_s ?? scene.start_s ?? 0;\n const end = lastLine.end_s ?? scene.end_s ?? start;\n const text = voicing.lines.map((l) => l.line.trim()).join(\" \");\n const voiceNode = out.voiceOf(env.canonical(firstLine.speaker ?? \"voiceover\"));\n nativeTurn = { text, start_s: start, end_s: end, voiceNode };\n out.talkingScenes.push({\n scene: index,\n voice_convert_node: ids.voiceConv(voiceNode),\n scene_s: Math.round(sceneDurationS(scene, env.ceilingS) * 100) / 100,\n est_speech_s: Math.round(estSpeechWindowS(text, start, end) * 100) / 100,\n speech_words: wordCount(text),\n });\n }\n const ctx = sceneCtx(env, out, index, nativeTurn);\n const built = buildCompositeScene(ctx, composite, nativeTurn);\n if (nativeTurn) {\n if (!built.presenterClipRef) {\n throw new Error(`scaffold invariant: scene ${index} has a native turn but no clip to extract audio from`);\n }\n emitNativeExtract(ctx, nativeTurn, { ref: built.presenterClipRef, lengthS: ctx.lengths.genDur });\n }\n out.clips.push(built.clip);\n if (!nativeTurn && voicing.speakers.size >= 2) emitCompositeReads(ctx, voicing.lines);\n out.routes.set(index, \"composite\");\n}\n\n/**\n * Voice a multi-speaker composite scene: one `tts` read per distinct speaker over the\n * (silent) composite clip. The clip carries no native speech, so — exactly like the\n * plain-scene multi-speaker path — each speaker's lines are read in their own brand\n * voice instead of being collapsed into one.\n */\nfunction emitCompositeReads(ctx: SceneCtx, lines: SpokenLine[]): void {\n const { env, out, scene, index } = ctx;\n const bySpeaker = new Map<string, { lines: string[]; start: number; end: number }>();\n for (const l of lines) {\n const speaker = env.canonical(l.speaker ?? \"voiceover\");\n const text = l.line.trim();\n const start = l.start_s ?? scene.start_s ?? 0;\n const end = l.end_s ?? start + estSpeechS(text);\n const cur = bySpeaker.get(speaker);\n if (cur) {\n cur.lines.push(text);\n cur.start = Math.min(cur.start, start);\n cur.end = Math.max(cur.end, end);\n } else {\n bySpeaker.set(speaker, { lines: [text], start, end });\n }\n }\n for (const [speaker, agg] of bySpeaker) {\n emitPhraseTts(\n {\n speaker,\n start_s: agg.start,\n end_s: agg.end,\n text: agg.lines.join(\" \"),\n firstScene: index,\n shownScenes: [],\n presenterShown: false,\n },\n out.voiceOf(speaker),\n index,\n env,\n out,\n );\n }\n}\n","import { supportsLastFrame } from \"@baker/canvas-contract\";\nimport { estSpeechWindowS, wordCount } from \"../../../lib/speech.ts\";\nimport type { Phrase } from \"../dialogue/phrases.ts\";\nimport { emitNativeExtract } from \"../dialogue/voices.ts\";\nimport { slotsForFrame } from \"../elements.ts\";\nimport { buildFrameRef } from \"../frames.ts\";\nimport { ids, ref } from \"../ids.ts\";\nimport { type SceneCtx, type SliceInfo, sceneCtx, type TimelineEnv, type TimelineOut } from \"../timeline-env.ts\";\nimport { ceilToDurations, sceneDurationS } from \"../timing.ts\";\nimport { clipNode } from \"./clip.ts\";\n\n/**\n * A presenter-shown phrase: ONE clip over the whole phrase (native lip-sync + audio) →\n * extract → voice_convert to the brand voice. Records, for each shown scene, the slice\n * (offset+length) to cut its window out of this clip. The clip is named for the phrase's\n * first shown scene (`s<anchor>_clip`) so the validator's native-audio check finds it,\n * and its keyframes carry that scene's id and style, the end frame included.\n */\nexport function emitPhraseClip(phrase: Phrase, voiceNode: string, env: TimelineEnv, out: TimelineOut): void {\n const [anchor] = phrase.shownScenes;\n if (anchor === undefined || !env.blueprint.scenes[anchor]) return;\n const ctx = sceneCtx(env, out, anchor, {\n text: phrase.text,\n start_s: phrase.start_s,\n end_s: phrase.end_s,\n voiceNode,\n });\n const anchorScene = ctx.scene;\n // A phrase whose anchor CONTINUES the previous scene's camera take starts from the\n // PREVIOUS phrase's end keyframe — the join sits mid-take (an LLM content beat, not\n // a real cut), and two independently generated keyframes there produced a visible\n // identity/pose jump inside one continuous shot (audit defect A7).\n const chained = anchorScene.continues_previous && out.phraseEnd?.scene === anchor - 1 ? out.phraseEnd.ref : undefined;\n const first =\n chained ??\n buildFrameRef(ctx, {\n edge: \"start\",\n url: anchorScene.start_frame_asset?.url,\n prompt: anchorScene.start_frame_prompt,\n present: slotsForFrame(env.slots, anchor, \"start\"),\n });\n // The phrase clip gets a last_frame when the model can USE one (Seedance/Veo/Kling\n // interpolate real in-shot motion between the pair) — the END frame of the phrase's\n // last shown scene, grounded on its OWN extracted frame (no cross-frame cascade,\n // renders in parallel with `first`).\n //\n // On a one-image model (Omni) it is generated ONLY when the next scene splices from\n // it. Building it unconditionally billed an `image_generate` per clip for a frame\n // the renderer drops — the exact waste `VIDEO_MODEL_IGNORES_INPUT` warns about, and\n // the default scaffold path was tripping our own warning on every clip.\n const lastShown = phrase.shownScenes.at(-1) ?? anchor;\n const lastScene = env.blueprint.scenes[lastShown] ?? anchorScene;\n const nextSplicesFromEnd = Boolean(env.blueprint.scenes[lastShown + 1]?.continues_previous);\n const last =\n supportsLastFrame(env.opts.videoModel) || nextSplicesFromEnd\n ? buildFrameRef(ctx, {\n edge: \"end\",\n url: lastScene.end_frame_asset?.url,\n prompt: lastScene.end_frame_prompt,\n present: slotsForFrame(env.slots, lastShown, \"end\"),\n })\n : undefined;\n // The clip is anchored at the EARLIEST shown scene's visual start — not the line's\n // start. A scene whose spoken line begins well after its visual start (a silent lead-in)\n // must still have its whole window generated; sizing the clip from the line start left\n // the lead-in ungenerated and made the clip too short for the scene (truncated picture +\n // spine under-run). It must also cover every sliced scene's end. Every slice offset is\n // then measured from this same origin, so offsets are always ≥ 0.\n const clipStart = phrase.shownScenes.reduce(\n (m, s) => Math.min(m, env.blueprint.scenes[s]?.start_s ?? phrase.start_s),\n phrase.start_s,\n );\n const coverEnd = phrase.shownScenes.reduce((m, s) => Math.max(m, env.blueprint.scenes[s]?.end_s ?? 0), phrase.end_s);\n const phraseLen = Math.max(0.5, coverEnd - clipStart);\n // Clip length = the COVERAGE window (buildPhrases caps it at the Seedance ceiling). We\n // do NOT pad to a word-count speech estimate — that bloated the clip past its window,\n // which is what made the extracted voice spill into the next phrase. The model paces the\n // quoted text to fit, keeping the original ad's timing.\n const genDur = ceilToDurations(env.durationSet, phraseLen);\n out.nodes.push(\n clipNode(\n {\n scene: anchorScene,\n index: anchor,\n present: ctx.present,\n mode: ctx.mode,\n nativeLine: phrase.text,\n audio: true,\n uiRouted: env.uiRouted.has(anchor),\n },\n env,\n { first, last },\n genDur,\n ),\n );\n // Only publish a splice frame when one exists — the next phrase reads this to\n // continue the take, and a missing ref would dangle.\n out.phraseEnd = last ? { ref: last, scene: lastShown } : undefined;\n const clipRef = ref(ids.clip(anchor), \"video\");\n // Extract ONLY the spoken window (pause to pause), never the whole clip — extracting\n // the full clip ran the converted voice the clip's whole length and overlapped the\n // next phrase's voice. Skip the silent lead-in (when the clip starts before the line)\n // so the extracted voice is the speech, not the lead-in. The brand-voice conversion is\n // deferred to `buildPerSpeakerVoiceConversion`, which re-voices ALL of a speaker's\n // windows in ONE pass (same as composite scenes) instead of a convert node per clip:\n // fewer nodes, fewer ElevenLabs calls, and a MORE consistent brand voice (the model\n // keys the timbre off the whole track, not each clip in isolation).\n emitNativeExtract(\n ctx,\n { text: phrase.text, start_s: phrase.start_s, end_s: phrase.end_s, voiceNode },\n {\n ref: clipRef,\n lengthS: genDur,\n offsetS: Math.max(0, phrase.start_s - clipStart),\n },\n );\n // The per-speaker convert node is `<voiceNode>_conv`. Placement is on the SPINE clock:\n // the phrase starts where its anchor scene's picture actually sits in the butted concat,\n // not at its reference timestamp.\n const convId = ids.voiceConv(voiceNode);\n const spineStart = env.clock.map(anchor, phrase.start_s);\n out.voSegments.push({\n slot: convId,\n start_s: spineStart,\n end_s: spineStart + (phrase.end_s - phrase.start_s),\n scene: anchor,\n speaker: phrase.speaker,\n onCamera: true,\n });\n out.talkingScenes.push({\n scene: anchor,\n voice_convert_node: convId,\n scene_s: Math.round(phraseLen * 100) / 100,\n est_speech_s: Math.round(estSpeechWindowS(phrase.text, phrase.start_s, phrase.end_s) * 100) / 100,\n speech_words: wordCount(phrase.text),\n });\n registerMergedPhraseSlices(\n ctx,\n phrase.shownScenes,\n { ref: clipRef, start: clipStart, dur: genDur },\n Boolean(chained),\n );\n}\n\n/**\n * A merged run's picture length on the SPINE clock: the sum of its scenes' sceneDurationS,\n * NOT the raw reference span (last.end_s - first.start_s). The spine places every scene's\n * picture at Σ sceneDurationS, so a duration_s override, a sub-0.5s clamp, or a gap between\n * scenes makes the raw span diverge from where the audio/captions sit — desyncing the merged\n * picture and failing checkSpineTotal. Summing the same sceneDurationS the clock uses keeps\n * this slice on the one clock.\n */\nfunction sumSceneDurations(env: TimelineEnv, first: number, last: number): number {\n let total = 0;\n for (let s = first; s <= last; s++) {\n const sc = env.blueprint.scenes[s];\n if (sc) total += sceneDurationS(sc, env.ceilingS);\n }\n return total;\n}\n\n/** Scene indexes grouped into runs of consecutive indexes, in order. */\nfunction consecutiveRuns(scenes: readonly number[]): Array<{ first: number; last: number }> {\n const runs: Array<{ first: number; last: number }> = [];\n for (const scene of [...scenes].sort((a, b) => a - b)) {\n const run = runs.at(-1);\n if (run && scene === run.last + 1) run.last = scene;\n else runs.push({ first: scene, last: scene });\n }\n return runs;\n}\n\n/**\n * Register a phrase clip's scene slices, MERGING consecutive shown scenes into ONE segment.\n * A phrase clip is a single continuous take; slicing it back into a segment per\n * micro-scene and re-concatenating them in the spine is pure round-trip waste — the\n * deconstruct's shot-cuts inside one take aren't real cuts, and presenter slices never carry\n * a transition. So a run of index-consecutive shown scenes registers ONE slice on its first\n * scene (covering the whole run) and marks the rest `skip`; a run that tiles the whole clip\n * then rides the RAW clip (whole-clip fast path) with no `_seg` at all. `chained` flags the\n * ANCHOR slice (the phrase's first) as sharing the previous phrase clip's end frame, so the\n * spine seam-dedups that one duplicated boundary frame.\n */\nfunction registerMergedPhraseSlices(\n ctx: SceneCtx,\n shownScenes: readonly number[],\n clip: { ref: string; start: number; dur: number },\n chained: boolean,\n): void {\n const { env, out } = ctx;\n let firstRegistered = true;\n for (const { first, last } of consecutiveRuns(shownScenes)) {\n const firstSc = env.blueprint.scenes[first];\n if (!firstSc) continue;\n const rawOffset = (firstSc.start_s ?? clip.start) - clip.start;\n out.sceneSlice.set(first, {\n clipRef: clip.ref,\n // Snap a sub-frame offset (line-start vs scene-start drift) to 0 so a run that tiles\n // the clip hits the whole-clip fast path instead of a needless re-encode + tiny shift.\n offset: rawOffset < 0.05 ? 0 : rawOffset,\n len: Math.max(0.5, sumSceneDurations(env, first, last)),\n clipDur: clip.dur,\n ...(firstRegistered && chained ? { continuesFrame: true } : {}),\n });\n firstRegistered = false;\n // The rest of the run: no segment of their own — their picture rides the merged one.\n for (let s = first + 1; s <= last; s++) {\n out.sceneSlice.set(s, { clipRef: clip.ref, offset: 0, len: 0, clipDur: clip.dur, skip: true });\n }\n }\n}\n\n/**\n * The `phrase_slice` and `phrase_run` routes: a presenter scene's spine clip is its window\n * cut out of the phrase clip (video only; the phrase's converted voice plays underneath —\n * same clip ⇒ lip-sync holds). A `skip` scene (`phrase_run`) was folded into a preceding\n * merged run-segment, so it emits nothing. When the slice IS the whole clip (offset 0,\n * exact length) the raw clip is the segment; otherwise the window cut rides the spine's\n * per-input chain (SceneClip.trim) — no standalone `s<i>_seg` node, and the spine's\n * normalize covers any ratio remap.\n */\nexport function emitSliceScene(index: number, slice: SliceInfo, out: TimelineOut): void {\n out.routes.set(index, slice.skip ? \"phrase_run\" : \"phrase_slice\");\n if (slice.skip) return;\n const whole = slice.offset === 0 && Math.abs(slice.len - slice.clipDur) <= 0.05;\n out.clips.push({\n ref: slice.clipRef,\n scene_s: slice.len,\n out: null,\n ...(slice.continuesFrame ? { continuesFrame: true } : {}),\n ...(whole ? {} : { trim: { offset_s: slice.offset } }),\n });\n}\n","import { isCtaRole } from \"../../lib/scene-role.ts\";\nimport { ids } from \"../ids.ts\";\nimport { UI_SURFACE_RE } from \"../routing.ts\";\nimport type { SceneCtx } from \"../timeline-env.ts\";\nimport { emitSurfaceStill } from \"./surface-still.ts\";\n\n/**\n * A FULL-FRAME app/UI/website/chat screen scene (the reference's screen-recording\n * beats — quote checklist, claim-approved card, coverage screen). The deconstruct\n * describes these as \"a clean mobile app interface …\", and the scaffold MUST NOT\n * route them to image_generate/video_generate: a generative model garbles UI text\n * and brand chrome (CCA-07/08 — the baked \"Demande acceptée\" pill, the sliced\n * caption). They are reproduced from a REAL screenshot fit-padded full-frame.\n * Gated on NO on-camera person/animal being present (a screen beat has no cast),\n * so a talking head that merely mentions an app is never misrouted.\n */\nexport function sceneIsFullScreenUi(ctx: SceneCtx): boolean {\n const { scene } = ctx;\n // An explicit CTA is a brand end-card, never a screen recording — even when its copy\n // mentions a \"website URL\" or \"app\". Yield so the dispatch falls through to the\n // brand-card route (a clean colour plate + the overlay's crisp wordmark/URL); otherwise\n // the screen route would ask the operator to screenshot a URL that doesn't exist.\n if (isCtaRole(scene.narrative_role)) return false;\n const hasCast = ctx.present.some((s) => {\n const t = s.type.toLowerCase();\n return t === \"person\" || t === \"animal\";\n });\n if (hasCast) return false;\n const hay = `${scene.summary ?? \"\"} ${scene.start_frame_prompt ?? \"\"} ${scene.end_frame_prompt ?? \"\"} ${scene.action_detail ?? \"\"}`;\n return UI_SURFACE_RE.test(hay);\n}\n\n/**\n * The `screen_still` route: a full-frame SCREEN scene from a REAL screenshot the operator\n * supplies — the faithful, non-garbled reproduction of an app/UI beat. The `[TODO]` names\n * the exact capture command.\n */\nexport function emitScreenScene(ctx: SceneCtx): void {\n emitSurfaceStill(ctx, {\n id: ids.screenRef(ctx.index),\n fallbackLabel: \"the app screen\",\n todo: (label) =>\n `[TODO: supply the real screen for \"${label}\" — never AI-generate a UI. Capture a clean, text-free screenshot with \\`baker images screenshot https://<brand-domain>/<path>\\` (image-library skill); spoken/overlay text rides the overlay layer, not the screenshot. Wire it in as a path relative to this canvas file, never an absolute path]`,\n });\n ctx.out.routes.set(ctx.index, \"screen_still\");\n}\n","import { slotsForFrame } from \"../elements.ts\";\nimport { buildFrameRef } from \"../frames.ts\";\nimport type { SceneCtx } from \"../timeline-env.ts\";\n\n// A scene shorter than this with NO spoken audio is a montage FLASH: a ~1-2s b-roll\n// beat. Seedance's shortest clip is 4s, so generating one (then trimming away ~75%)\n// burns credits for motion no viewer perceives in a flash. We hold the keyframe as a\n// still instead — same look, a fraction of the cost. (Below the Seedance floor of 4s.)\nconst FLASH_HOLD_MAX_S = 2;\n// The raised hold ceiling for a beat the deconstruct EXPLICITLY stamped static/subtle\n// (montage b-roll under a voiceover): just under the Seedance 4s floor, so a 2.5-3.5s\n// near-still beat doesn't bill a 4s clip only to discard most of it in the spine cut.\nconst MONTAGE_HOLD_MAX_S = 3.5;\n\n/**\n * Whether a silent b-roll scene is short and still enough to hold as a keyframe.\n *\n * A flash with REAL subject motion (deconstruct-stamped `dynamic`) keeps a real clip —\n * freezing a pour/spread/hands-working beat turns the montage into a slideshow. Only\n * static/subtle (or unstamped, old-blueprint) flashes hold stills. An EXPLICITLY\n * static/subtle montage beat holds up to the higher MONTAGE_HOLD ceiling: the deconstruct\n * verified its motion is negligible, so a 2.5-3.5s beat billing a 4s clip and discarding\n * most of it buys nothing a held keyframe doesn't. An unstamped scene keeps the\n * conservative 2s ceiling. A scene carrying its own ambience is never held: a still has\n * no sound to extract.\n */\nexport function holdsAsStill(ctx: SceneCtx, ambient: boolean): boolean {\n const { motion_level: motion } = ctx.scene;\n const ceiling = motion === \"static\" || motion === \"subtle\" ? MONTAGE_HOLD_MAX_S : FLASH_HOLD_MAX_S;\n return !ambient && ctx.lengths.dur <= ceiling && motion !== \"dynamic\";\n}\n\n/**\n * The `still_hold` route: a montage FLASH held as a still — one keyframe looped to the\n * scene length on the spine, no billed video_generate.\n */\nexport function emitStillHold(ctx: SceneCtx): void {\n const { scene, index } = ctx;\n const frame = buildFrameRef(ctx, {\n edge: \"start\",\n url: scene.start_frame_asset?.url,\n prompt: scene.start_frame_prompt,\n present: slotsForFrame(ctx.env.slots, index, \"start\"),\n });\n ctx.out.clips.push({ ref: frame, scene_s: ctx.lengths.dur, out: ctx.lengths.out, still: { fit: \"fill\" } });\n ctx.out.routes.set(index, \"still_hold\");\n}\n","import type { VideoBlueprint } from \"@baker/canvas-contract\";\nimport { clipProfileFor, SEEDANCE_PROFILE } from \"../../lib/prompt-profiles.ts\";\nimport type { NodeDecl } from \"../../schema/canvas.ts\";\nimport { voiceLanguageOf } from \"../lib/language.ts\";\nimport type { AudioTrack } from \"./audio.ts\";\nimport { buildPhrases, foldUnshownPhrases, type Phrase } from \"./dialogue/phrases.ts\";\nimport {\n castIdSet,\n collapseVoiceover,\n makePresenterPresent,\n onCameraDialogue,\n sourceShowsPeople,\n} from \"./dialogue/speakers.ts\";\nimport { buildPerSpeakerVoiceConversion, emitPhraseTts, makeVoiceFactory } from \"./dialogue/voices.ts\";\nimport type { ElementSlot } from \"./elements.ts\";\nimport type { ScaffoldVideoOpts } from \"./opts.ts\";\nimport { emitBrandCardScene, sceneIsBrandCard } from \"./routes/brand-card.ts\";\nimport { emitClipScene } from \"./routes/clip.ts\";\nimport {\n compositeVoicing,\n emitCompositeScene,\n type LayeredComposition,\n layeredComposition,\n} from \"./routes/composite.ts\";\nimport { emitGraphicScene, fullFrameGraphicScenes } from \"./routes/graphic-plate.ts\";\nimport { emitPhraseClip, emitSliceScene } from \"./routes/phrase-slice.ts\";\nimport { emitScreenScene, sceneIsFullScreenUi } from \"./routes/screen-still.ts\";\nimport { emitStillHold, holdsAsStill } from \"./routes/still-hold.ts\";\nimport { uiRoutedSceneSet } from \"./routing.ts\";\nimport {\n type SceneCtx,\n type SceneRoute,\n sceneCtx,\n type TalkScene,\n type TimelineEnv,\n type TimelineOut,\n type VoSeg,\n} from \"./timeline-env.ts\";\nimport { clipDurationSet, spineClockFor } from \"./timing.ts\";\n\n/** Build the canvas-wide timeline context, each fact computed once. */\nexport function timelineEnv(args: {\n blueprint: VideoBlueprint;\n slots: ElementSlot[];\n opts: ScaffoldVideoOpts;\n aspect: { outAr: string; genAr: string };\n}): TimelineEnv {\n const { blueprint, slots, opts } = args;\n const durationSet = clipDurationSet(opts.videoModel);\n const ceilingS = Math.max(...durationSet);\n return {\n blueprint,\n clock: spineClockFor(blueprint, ceilingS),\n slots,\n opts,\n outAr: args.aspect.outAr,\n genAr: args.aspect.genAr,\n durationSet,\n ceilingS,\n clipProfile: clipProfileFor(opts.videoModel) ?? SEEDANCE_PROFILE,\n reuse: opts.frames === \"reuse\",\n sourceShowsPeople: sourceShowsPeople(blueprint, slots),\n cameraOn: onCameraDialogue(blueprint),\n casts: castIdSet(blueprint),\n canonical: collapseVoiceover(blueprint),\n ingestCache: new Map<string, string>(),\n uiRouted: uiRoutedSceneSet(blueprint),\n graphicScenes: fullFrameGraphicScenes(blueprint),\n surfaceIngests: new Map<string, string>(),\n ttsLanguageCode: voiceLanguageOf(opts)?.iso,\n spokenLanguageName: voiceLanguageOf(opts)?.name,\n spokenAccent: blueprint.global?.voiceover?.accent?.trim() || undefined,\n keepRenderedVoice: opts.keepRenderedVoice,\n };\n}\n\n/**\n * A b-roll scene (no presenter shown), routed by what its picture IS. Checked in order:\n * - a DESIGNED graphic (meme collage, logo card, marketing art) → the real design asset\n * fit-padded full-frame, never a generated frame (generation garbles designed typography\n * and third-party wordmarks). Checked before the prose screen route: the typed kind is\n * authoritative, and a designed panel must get the design-rebuild wording, not\n * \"screenshot the live page\". Membership is chain-closed: an untyped continuation of a\n * typed graphic take is the same graphic.\n * - a full-frame app/UI screen beat → a REAL screenshot fit-padded full-frame, NEVER a\n * generated frame — before the hold/clip paths, so even a sub-2s screen flash is real.\n * - a solid brand/logo CTA card → a clean colour plate, never a generated logo (the\n * overlay layer's CTA card carries the crisp wordmark + URL).\n * - a short, still flash → a held keyframe.\n * - anything else → its own clip.\n * Returns the scene's END keyframe ref when it is a clip (the next scene may splice from it).\n */\nfunction emitBrollScene(ctx: SceneCtx, prevEndFrame: string | undefined): string | undefined {\n const { env } = ctx;\n const ambient = Boolean(env.opts.ambient) && ctx.mode !== \"ugc_selfie\";\n if (!env.reuse && env.graphicScenes.has(ctx.index)) emitGraphicScene(ctx);\n else if (!env.reuse && sceneIsFullScreenUi(ctx)) emitScreenScene(ctx);\n else if (!env.reuse && sceneIsBrandCard(ctx)) emitBrandCardScene(ctx);\n else if (holdsAsStill(ctx, ambient)) emitStillHold(ctx);\n else return emitClipScene(ctx, prevEndFrame, ambient);\n return undefined;\n}\n\n/**\n * Which phrases get a clip of their own, decided before anything is emitted. A scene is the\n * slice target of at most ONE phrase — if a later phrase shares an already-claimed scene (a\n * within-scene pause), it falls back to a tts read over that scene's clip. `clipScenes` is\n * the scenes a clip phrase slices, and undefined for a read.\n */\nfunction planPhrases(phrases: Phrase[]): Array<{ phrase: Phrase; clipScenes?: number[] }> {\n const claimed = new Set<number>();\n return phrases.map((phrase) => {\n const available = phrase.shownScenes.filter((s) => !claimed.has(s));\n if (!phrase.presenterShown || available.length === 0) return { phrase };\n for (const s of available) claimed.add(s);\n return { phrase, clipScenes: available };\n });\n}\n\n/**\n * Build the whole timeline: the continuous per-phrase voice (presenter clips +\n * converts, or pure-b-roll tts), then the visual spine scene-by-scene — a presenter\n * scene's video is a slice of its phrase clip, a b-roll scene its own silent clip/still,\n * a composite scene its own stacked/overlaid clip. Returns the spine clips, the audio\n * tracks, and the timing plan (`vo_segments`/`talking_scenes`) the validator proves.\n */\nexport function buildTimeline(\n env: TimelineEnv,\n nodes: NodeDecl[],\n): {\n clips: TimelineOut[\"clips\"];\n voTracks: AudioTrack[];\n vo_segments: VoSeg[];\n talking_scenes: TalkScene[];\n routes: Map<number, SceneRoute>;\n} {\n const { blueprint, canonical } = env;\n const composites = new Map<number, LayeredComposition>();\n if (!env.reuse) {\n blueprint.scenes.forEach((s, i) => {\n const composite = layeredComposition(s, env.uiRouted.has(i));\n if (composite) composites.set(i, composite);\n });\n }\n\n // 1. The voice, phrase by phrase (continuous; cut only at pauses).\n const presenterPresent = makePresenterPresent(env.slots, canonical);\n const presentStrict = makePresenterPresent(env.slots, canonical, { strict: true });\n const compositeScenes = new Set(composites.keys());\n const phrases = buildPhrases(blueprint, canonical, compositeScenes, presenterPresent, presentStrict);\n const plan = planPhrases(foldUnshownPhrases(phrases, env.keepRenderedVoice === true));\n // A speaker is cast when a node will read their voice: every read does, and the\n // re-voicing of their on-camera track does unless the rendered voice is kept.\n const readSpeakers = new Set(plan.filter((p) => !p.clipScenes).map((p) => p.phrase.speaker));\n for (const i of compositeScenes) {\n const scene = blueprint.scenes[i];\n const voicing = scene ? compositeVoicing(scene, env) : undefined;\n if (voicing && !voicing.native && voicing.speakers.size >= 2) for (const s of voicing.speakers) readSpeakers.add(s);\n }\n const out: TimelineOut = {\n nodes,\n routes: new Map(),\n clips: [],\n voTracks: [],\n voSegments: [],\n talkingScenes: [],\n nativeSegments: [],\n sceneSlice: new Map(),\n voiceOf: makeVoiceFactory(\n blueprint,\n canonical,\n nodes,\n (speaker) => env.keepRenderedVoice !== true || readSpeakers.has(speaker),\n { language: env.spokenLanguageName, genders: env.opts.voiceGenders },\n env.opts.voiceId,\n ),\n readIds: new Set<string>(),\n };\n plan.forEach(({ phrase, clipScenes }, k) => {\n const voiceNode = out.voiceOf(phrase.speaker);\n if (clipScenes) emitPhraseClip({ ...phrase, shownScenes: clipScenes }, voiceNode, env, out);\n else emitPhraseTts(phrase, voiceNode, k, env, out);\n });\n\n // 2. The visual spine, scene by scene. `prevEndFrame` carries the previous scene's\n // END keyframe ref so a length-split CONTINUATION scene (same physical shot) can\n // reuse it as its START frame — a byte-identical splice, no hard cut. Only the b-roll\n // path produces a shareable single frame; presenter-slice and composite scenes break\n // the chain (they have no single end keyframe), so they reset it.\n let prevEndFrame: string | undefined;\n blueprint.scenes.forEach((_, i) => {\n const composite = composites.get(i);\n const slice = out.sceneSlice.get(i);\n if (composite) {\n emitCompositeScene(env, out, i, composite);\n prevEndFrame = undefined;\n } else if (slice) {\n emitSliceScene(i, slice, out);\n prevEndFrame = undefined;\n } else {\n prevEndFrame = emitBrollScene(sceneCtx(env, out, i), prevEndFrame);\n }\n });\n\n // Every speaker's native audio: one merged convert per speaker. The track length\n // is the SPINE length — the reference duration can include dead air the picture\n // does not reproduce, and `-shortest` at the final mux truncates the longer stream.\n const totalMs = Math.round(env.clock.totalS * 1000);\n out.voTracks.push(...buildPerSpeakerVoiceConversion(out.nativeSegments, totalMs, nodes, env.keepRenderedVoice));\n\n return {\n clips: out.clips,\n voTracks: out.voTracks,\n vo_segments: out.voSegments,\n talking_scenes: out.talkingScenes,\n routes: out.routes,\n };\n}\n","import { MODEL_REGISTRY, type VideoBlueprint } from \"@baker/canvas-contract\";\nimport { sceneRole } from \"../lib/scene-role.ts\";\nimport { canvasDims, parseRatio, type resolveAspect } from \"./aspect.ts\";\nimport type { ScaffoldVideoOpts } from \"./opts.ts\";\nimport type { VideoReport } from \"./report.ts\";\n\n/** The operator-facing `metadata.todo.aspect_remap` note, when the ratios differ. */\nexport function aspectRemapTodo(aspect: ReturnType<typeof resolveAspect>): { aspect_remap?: string } {\n if (!aspect.remapped) return {};\n const dims = canvasDims(aspect.outAr);\n const trims = (parseRatio(aspect.genAr) ?? 0) > (parseRatio(aspect.outAr) ?? 0) ? \"sides\" : \"top/bottom\";\n return {\n aspect_remap:\n `Output is ${aspect.outAr} (${dims.w}×${dims.h}) but the video model generates ${aspect.genAr}; every ` +\n `clip is center-cropped onto the ${aspect.outAr} canvas before the spine. Keep subjects centered in ` +\n `frame prompts — the crop trims the ${trims}.`,\n };\n}\n\n/**\n * A per-curated-video-model constraint summary embedded in `metadata.todo` so an\n * operator swapping a clip's model (e.g. Seedance→Veo to route around the photoreal\n * content-policy block) sees the cross-model deltas inline — the constraints that\n * otherwise only surface after a failed run: aspect must agree across ALL clips,\n * duration is a per-model hard enum, and person_generation differs. `validate` gates\n * all three before any billed render.\n */\nexport function buildModelConstraints(): {\n note: string;\n models: Record<string, { label: string; aspect_ratios: unknown; durations_s: unknown; person_generation: unknown }>;\n} {\n const models: Record<\n string,\n { label: string; aspect_ratios: unknown; durations_s: unknown; person_generation: unknown }\n > = {};\n for (const [id, spec] of Object.entries(MODEL_REGISTRY.video_generate)) {\n const p = spec.params as Record<string, { enum?: readonly unknown[] } | undefined>;\n models[id] = {\n label: spec.label,\n aspect_ratios: p.aspect_ratio?.enum ?? null,\n durations_s: p.duration?.enum ?? null,\n person_generation: p.person_generation?.enum ?? null,\n };\n }\n return {\n note: \"Switching a clip's video model has cross-node constraints. All video_generate nodes in one canvas must share one aspect_ratio (the composite silently crops otherwise). Each model's `duration` is a hard enum and differs per model — a scene longer than the model's max must be split. `person_generation` differs (Veo requires \\\"allow_all\\\"). `baker canvas validate` gates duration, aspect agreement, per-model params, and a scene-span-vs-model-max advisory before any billed run — run it after every model edit.\",\n models,\n };\n}\n\n/**\n * Index of the scene that actually holds the hook — the first scene resolving to\n * role \"hook\", or -1 when none does. The hook is NOT always scene 0: a single-scene\n * video's one scene is the CTA (no hook), and a windowed deconstruct can merge scenes\n * from multiple passes and assign `narrative_role: \"hook\"` to a non-zero index. Every\n * hook instruction derives its `s<i>` references from this so they never point at the\n * wrong scene.\n */\nfunction findHookSceneIndex(blueprint: VideoBlueprint): number {\n const total = blueprint.scenes.length;\n return blueprint.scenes.findIndex((s, i) => sceneRole(s.narrative_role, i, total) === \"hook\");\n}\n\n/**\n * The opener criteria, shared by the per-scene `[RECRAFT HOOK]` flag and the top-level\n * `hook` todo so the thresholds (~2s, ~1s) can't drift between the two prose strings.\n */\nconst HOOK_OPENER_CRITERIA =\n \"statement not question; benefit by ~2s; first frame legible SOUND-OFF in ~1s (the feed plays muted); no bait-and-switch (the hook sets up the body)\";\n\n/**\n * The re-craft instruction is role-aware: the HOOK is the highest-leverage beat\n * (it's targeting, and a competitor's hook often does NOT transfer), so it carries\n * the decision criteria inline and routes to references/hook-craft.md. Other roles\n * keep the generic \"rewrite for OUR brand\" line. Every variant leads with \"[RECRAFT\"\n * so the flag is greppable and never shipped as the reference's words. `sceneIndex`\n * pins the hook variant's `s<i>` references to the scene that actually holds the hook.\n */\nfunction recraftTextForRole(role: string, sceneIndex: number): string {\n if (role === \"hook\") {\n return `[RECRAFT HOOK — the #1 decision, but usually the LIGHTEST move wins: this hook already worked, so default to KEEPING it and building on top (swap only the specifics for ours). REBUILD only when it doesn't transfer — a claim we lack or a different funnel/awareness stage — by reaching for its deeper INNER MECHANIC and delivering that truthfully. DIAGNOSE (device + mechanic + stage) → DECIDE keep/adapt/rebuild → hold the opener to criteria: ${HOOK_OPENER_CRITERIA}. It lives on s${sceneIndex}_start (first frame) + the scene-${sceneIndex} overlay. See references/hook-craft.md + meta-ads-playbook §10/§39.]`;\n }\n if (role === \"cta\") {\n return \"[RECRAFT CTA — the close: state what to do (where to go) + what to expect (offer/bundle/discount) for OUR brand; soft for top-of-funnel, hard for bottom. Don't render the reference's words. See references/script-craft.md.]\";\n }\n return `[RECRAFT: rewrite this ${role} for OUR brand — true claims only; do NOT render the reference's words. See references/script-craft.md + meta-ads-playbook.]`;\n}\n\n/**\n * The per-scene script re-craft checklist (WS11). A video reproduction is\n * INSPIRATION from a winning ad, not a clone: the hook is targeting and doesn't\n * always transfer, so the agent must re-author each scene's line for OUR brand\n * before rendering. We tag each scene's role (DECON `narrative_role`, else\n * inferred from position) and carry the original line FLAGGED so it is never\n * shipped as the competitor's words/claims.\n */\nfunction buildScriptRecraft(blueprint: VideoBlueprint): Array<Record<string, unknown>> {\n const total = blueprint.scenes.length;\n return blueprint.scenes.map((scene, i) => {\n const role = sceneRole(scene.narrative_role, i, total);\n const original = (scene.dialogue ?? [])\n .map((d) => d.line?.trim())\n .filter((l): l is string => Boolean(l))\n .join(\" \");\n return {\n scene: i,\n role,\n original_line: original || null,\n recraft: recraftTextForRole(role, i),\n };\n });\n}\n\n/** Build the structured, in-canvas checklist mirroring the command's stdout report. */\nexport function buildVideoTodo(\n report: VideoReport,\n overlayCount: number,\n floatingCount: number,\n opts: ScaffoldVideoOpts,\n blueprint: VideoBlueprint,\n): Record<string, unknown> {\n // The hook is not always scene 0 (single-scene videos have none; windowed merges can\n // place it at a non-zero index), so derive its index and only emit the `hook` todo when\n // a hook scene actually exists — otherwise it would contradict `script_recraft`'s role.\n const hookSceneIndex = findHookSceneIndex(blueprint);\n const h = hookSceneIndex; // shorthand for the s<i> references below\n return {\n full_flexibility:\n \"THIS CANVAS IS A STARTING POINT, NOT A LOCKED RENDER. It mirrors the reference's structure so you have a faithful scaffold — but you have FULL EDITING FREEDOM and should use it. You can: ADD a scene (new s<i>_start/_end + s<i>_clip, wired into `spine` as the next `c<n>` input with a matching entry in its `clips`), DELETE a scene (drop its nodes, its `spine` input and its `clips` entry), REORDER scenes, SPLIT one beat into two or MERGE two into one, change any frame prompt or motion brief, swap an element reference, re-time or rewrite any overlay/voice, or change a scene's LAYOUT (make a full-frame beat a split-screen/PIP, or flatten a composite to one shot — see `composition`). Re-craft for OUR brand and OUR best ad; the reference is inspiration, not a spec to trace. The content-addressed cache re-bills only what you actually change, so iterate freely. `baker canvas validate` re-checks timing/lip-sync after any edit.\",\n composition:\n \"Some scenes are COMPOSITED, not single shots — `prompt.json`'s scene.composition.layout tells you which: `split_screen` (panels each showing different footage — e.g. b-roll on top, presenter on the bottom), `pip` (a presenter boxed in a corner over full-frame background), or `keyed_overlay` (a green-screen/cut-out presenter over background). Each is reproduced as ONE generated clip PER REGION (`s<i>_r0_*`, `s<i>_r1_*`, …) stacked (vstack/hstack) or overlaid by an `s<i>_composite` ffmpeg node; a keyed presenter runs through `s<i>_key` (video_background_remove) for a transparent cut-out first. Edit each region's own keyframe prompt + motion brief independently. The presenter region (is_presenter) carries the lip-synced voice. To CHANGE a layout, edit composition in prompt.json and re-scaffold, or hand-edit the s<i>_composite ffmpeg args (splitStackArgs/pipOverlayArgs patterns). A clean full-frame talking head is simpler than a composite — flatten when the brand's version doesn't need the split.\",\n recraft_the_script_first: `VIDEO IS INSPIRATION, NOT A CLONE. Before rendering, re-craft the script (hook → body → CTA) for OUR brand — the reference already won in-market, but its hook is targeting and may not transfer.${h >= 0 ? \" The HOOK is the #1 decision (see the `hook` todo);\" : \"\"} ${h >= 0 ? \"then work\" : \"Work\"} the per-scene \\`script_recraft\\` checklist. References: references/hook-craft.md (the hook), references/script-craft.md (body/CTA) + the meta-ads-playbook skill.`,\n ...(h >= 0\n ? {\n hook: `THE HOOK IS THE HIGHEST-LEVERAGE BEAT — the first frame + first 3–4s decide whether the ad is watched at all, and the hook is TARGETING. But highest-leverage does NOT mean always rewrite: this hook already won, so MOST OF THE TIME you KEEP it and build on top (swap only the specifics). REBUILD is the exception — only when it doesn't transfer (a claim we lack or a different funnel/awareness stage), and then by reaching for its deeper INNER MECHANIC and delivering that truthfully, not inventing a new opener from nothing. For scene ${h}: DIAGNOSE it (device + mechanic + what stage it targets), DECIDE keep/adapt/rebuild, then hold the opener to the criteria — ${HOOK_OPENER_CRITERIA}. The hook lives across s${h}_start (the scroll-stopping first frame), the scene-${h} overlay text, the s${h}_clip line, an optional ~0.5s micro-hook, and the ramp into the body. Full diagnose→decide→(keep/adapt/rebuild) discipline + the proven hook-type menu: references/hook-craft.md (+ meta-ads-playbook §10/§17/§39).`,\n }\n : {}),\n script_recraft: buildScriptRecraft(blueprint),\n edit_frames_in_place:\n \"Each s<i>_start keyframe node has its own editable params.prompt (FRAME DESCRIPTION). Edit per frame; prompt.json is the authoritative shared ad spec (cast identity, palette, brand) — its global edits reach every frame automatically because validate/run regenerate the derived prompt.style.json projection each frame reads. Frames are RECAST to the el_* reference images (the source ad's cast is never reused) and are CLEAN PLATES — they render no on-screen text; all text is the overlay HTML layer.\",\n frames_mode: opts.frames ?? \"generate\",\n review_storyboard_before_clips:\n \"STORYBOARD FIRST. Each scene's keyframe (s<i>_start) IS your storyboard — align the LOOK on it before clips bill. Images are cheap, videos aren't, and the content-addressed cache re-bills only changed nodes, so iterate prompts here first and let the storyboard lock before the video_generate clips run. `metadata.video.motion_board` lists each scene's keyframe, window, spoken line, and the graphics scheduled in it — walk it scene by scene.\",\n motion_board:\n \"`metadata.video.motion_board` maps which overlay/graphic fires on which spoken beat (per scene: window_s, spoken line, each graphic's at_s). Review it so every graphic lands on the word it punctuates — don't let an overlay drift off its beat. Adjust an overlay's data-start in video-overlay-composition/index.html (or appears_at_s in prompt.json) to retime it.\",\n assets_required:\n \"MANDATORY: drop a real image at every el_* [TODO] ingest before running — `baker canvas run` refuses to start (and bills nothing) until each placeholder holds a real source.\",\n sourcing:\n 'Resolve each el_* [TODO]: a PERSON needs no slot — they are invented from their description; edit that description (el_* image_generate prompt) to change who they are, or re-scaffold with `--avatar <handle>` when the same actor must recur across ads; never a photo of a real person from the web or the source ad, because the image model reproduces that face. Everything else: the client\\'s OWN assets first — `baker images library \"<subject>\"` and `baker images logo <domain>` for the brand mark; otherwise a FRESH real reference — `baker images find \"<subject>\" --sources pinterest` (photo-real/candid, best for pets, sets and objects) or generate one with the image model. el_location and animals are [SOURCE FRESH]: a DIFFERENT set/animal than the original ad.',\n recurring_elements_to_supply: report.elements,\n text_strategy:\n \"Decide per ad: text is either baked by the generated creative OR painted via the overlay HTML — not both. Default here is clean text-free frames + the HTML overlay layer (video-overlay-composition/index.html) as the single text source, which you fully control.\",\n timeline:\n \"Automatic: each clip is generated at >= its scene length then trimmed back to the real scene duration, so the concatenated picture stays on the same timeline as the audio. You don't manage it.\",\n voices_to_confirm: report.dialogue.map((d) => ({\n scene: d.scene,\n speaker: d.speaker,\n voice_description: d.voice_description,\n line: d.line,\n })),\n talking_head_note:\n \"SHOT-NATIVE: a presenter shot is ONE video clip (its line quoted in s<anchor>_clip's prompt, plus generate_audio on the models that expose it) so lips+voice are generated together — no tts, no veed-lipsync. Two adjacent presenter shots at a hard cut are SEPARATE clips; a cutaway phrase (the presenter on camera, cut to b-roll, back on camera) stays one clip whose on-camera windows are cut inside the spine's per-input chains (no extra nodes). Edit the line in the s<anchor>_clip prompt to re-author it. A pure-voiceover phrase (speaker never shown) is one ElevenLabs tts read instead.\",\n voice_note:\n \"ONE voice per person: a single voice_select is reused across all that person's shots (on-camera AND off — the deconstruct's `voiceover` label folds into the sole presenter). Every presenter clip's native audio is extracted and re-voiced to that brand voice through a SINGLE merged audio_voice_convert per speaker (<voice>_conv, eleven_multilingual_sts_v2, timing preserved so lips stay matched) — so timbre stays consistent across the separate shot clips. Set voice_select.voice_id's gender/language to match the creator.\",\n native_timing:\n \"Clips separate at COMPLETE BREAKS between shots, but the VOICE stays continuous where it should: a voiceover narration is ONE read across the b-roll it plays over, and a cutaway leaves the presenter's read continuous under the insert. Each clip is generated long enough for its estimated speech. `metadata.video.talking_scenes` carries each shot's scene_s vs est_speech_s. CAVEAT: a b-roll cutaway INSIDE a phrase lands at an approximate (proportional) time — no video model exposes word timing — so if a cutaway is off its beat, nudge the scene boundary (it's a starting point). NOTE: a native clip's voice is extracted for the SPOKEN window only (`s<i>_voextract`'s `-t`) — when the scene runs longer than the line, the picture tail is deliberately silent (extracting the full clip would put post-line breathing/babble on the voice bus); trim the scene or extend the line if the dead air reads wrong.\",\n craft: {\n note: \"Production-craft principles that raise every clip's realism. Full rationale: references/video-craft.md (production craft); references/script-craft.md + meta-ads-playbook for the hook/message layer.\",\n principles: [\n \"Iterate cheaply — do NOT brute-force takes. Credits are scarce. Strong inputs (a locked reference + a precise move-by-move prompt) make 1–2 takes land; bad input = bad output. When a take misses, change the SMALLEST thing and re-run — the content-addressed cache re-bills only that node. Images are cheap, videos aren't: fix on the frame/reference, not by re-rolling clips.\",\n \"Keep clips SHORT — the longer a shot holds, the more the eye catches the AI tell. Trust the scene-length trim; don't pad.\",\n \"LOCK THE CAMERA — Seedance animates forward from the single keyframe; only move when the motion brief specifies a move. Unmotivated camera drift is the top realism tell.\",\n \"One generation = one speaking voice. Seedance can't voice two on-camera speakers in one clip — split a two-speaker beat into separate scenes (or one stays silent). Fragment long dialogue at a natural pause and stitch via the shared boundary frame. Lip-sync follows the line verbatim; carry delivery cues in PROSE around the quoted line, never in [brackets] (Seedance renders brackets literally).\",\n \"Preview cheap → finalize high-res (credit discipline). Never prompt the aspect ratio in prose ('make it vertical' → stretch artifacts) — the pipeline sets aspect_ratio as a param.\",\n \"Nail the PACK SHOT — the final product hero sells (motivated camera move, light matched to the rest of the ad).\",\n \"Geometry/objects drifting frame to frame? A MAP beats a paragraph — drop a high-angle schematic still (marked positions) as an extra el_*/reference rather than adding more words.\",\n \"Before/after (dry→wet, skeptic→believer) = two SEPARATE locked reference images — don't ask words to transform a subject mid-scene (cheaper and more reliable than re-rolling clips).\",\n \"The hook is VISUAL-FIRST: the feed plays muted, so the hook scene's opening frame + its overlay text must read sound-off in ~1 second — don't bury the hook in the spoken line alone (meta-ads-playbook §39 visual-hooks-beat-audio, §48 the 1-second/feed-native rule). The hook is also the #1 re-craft decision — diagnose/decide/rebuild it against criteria in references/hook-craft.md (see the `hook` todo).\",\n ],\n },\n transitions:\n \"Scene-to-scene cuts the deconstruct flagged as fade/whip/zoom/dissolve/swipe are reproduced as an ffmpeg xfade at the boundary (everything else stays a hard cut). The overlap is consumed from extra generated footage, so the picture stays exactly on the audio timeline. To change a transition, edit the scene's `transition_out.type` in prompt.json and re-scaffold, or edit that clip's `transition` in the `spine` node's `clips`. For a richer HERO cut (whip-pan, glitch, light-leak, gravitational-lens…), the overlay layer can run a Hyperframes shader/CSS transition instead — see references/hyperframes/blueprints-and-transitions.md (pick 2–3 transition types total; the motion IS the handoff).\",\n overlay_capabilities:\n 'The overlay layer (video-overlay-composition/index.html) is a REAL Hyperframes composition, not a plain text layer — our hyperframe_render node runs the genuine `npx hyperframes` renderer. So it can do far more than fade/slide/pop: (1) PULL a ready-made block — `npx hyperframes catalog --type block` then `npx hyperframes add <id>` into the composition dir, and nest it with a <div data-composition-src=\"compositions/<id>.html\" data-start data-track-index data-width data-height> clip (~154 blocks: lower-thirds, social-proof cards, stat counters, charts, code, logo stings); (2) animate with the named GSAP motion-rule vocabulary (kinetic-beat-slam, svg-path-draw, counting-dynamic-scale, multi-phase-camera…); (3) frame a talking head as a video-call/PIP/split. The whole engine + how to build new effects is documented in references/hyperframes/ (start at README.md → catalog.md, motion-rules.md). Reach for this whenever the reference\\'s graphics are richer than plain text.',\n caption_system:\n \"Sound-off feed = burned-in captions carry the message. The deconstruct produced a word-level transcript — drive a real caption track off it (karaoke highlight → themed → kinetic), not hand-typed text. Floor: `npx hyperframes add caption-highlight` (TikTok karaoke); escalate by content register (caption-kinetic-slam for hype, caption-editorial-emphasis for premium, caption-neon-glow for AI/crypto). Group on meaning, sync within 80ms. Full ladder + transcript contract: references/hyperframes/captions-and-audio.md.\",\n talking_head_overlay:\n \"For a scene where a presenter shows something (screen-share, app demo, product, a 'video call' look), frame the talking-head clip in the overlay composition: presenter full-bleed → shrinks to a rounded corner PIP pill while a content card takes the stage (or split/stack/overlay-glass-card). The pattern, the #video-wrap→corner-pill tween, the glass call card, and the corner-coord presets are in references/hyperframes/talking-head-and-overlays.md. A ready exemplar ships as the `video-call-composition` move — copy it next to your canvas, drop brand fonts in the dir, point a `hyperframe_render` at it with the presenter clip as its `background`.\",\n text_overlays: {\n count: overlayCount,\n note: \"Seeded as editable HTML inside `#overlay-root` in video-overlay-composition/index.html (text + a .pos-* class + data-start/data-dur). PAINT it: restyle the CSS, build lower-thirds/tickers, drop brand-*.otf for on-brand type. The runtime only shows/hides by timestamp.\",\n },\n floating_elements: {\n count: floatingCount,\n note:\n floatingCount > 0\n ? \"Seeded as commented <img> stubs in index.html (each names the `baker images icon/sticker/gif/logo` command to source it) — source the asset, drop it in video-overlay-composition/, uncomment the <img>. For a graphic that should ANIMATE (a lower-third, a social-proof/review card, a stat counter, a chart, a logo sting), prefer a ready-made Hyperframes block instead of a static <img>: `npx hyperframes add <id>` and nest it (see `overlay_capabilities` + references/hyperframes/catalog.md).\"\n : \"none detected by the deconstruct — see `completeness_check`, the reference may still have icons/stickers it missed.\",\n },\n sound_effects: {\n count: report.sfx_count,\n note:\n report.sfx_count > 0\n ? \"Seeded as `sound_effect` nodes on `audio_mix` at their timestamps — edit the prompt or retime.\"\n : \"none detected by the deconstruct — see `completeness_check`, the reference may still have sound cues it missed.\",\n },\n music: {\n present: report.has_music,\n note: report.has_music\n ? \"Original bed regenerated from the deconstruct prompt (styled after the AudD-identified track when available); ducked under the voices.\"\n : \"no music bed scaffolded — if the reference has music, see `completeness_check`.\",\n },\n // ALWAYS-ON safety net: the scaffold can only seed what the deconstruct\n // cataloged, and it under-detects on-image graphics + sound cues. Never trust\n // \"none detected\" — re-watch the reference and fill the gaps with the right tool.\n completeness_check:\n \"The scaffold mirrors the deconstruct's catalog, which UNDER-DETECTS — never trust a 0 count. Re-watch the reference frame-by-frame and add anything missing: \" +\n '(1) ON-IMAGE GRAPHICS not in floating_elements (dollar/coin icons, emojis, checkmarks, rating stars, price tags, arrows, progress bars, app UI) → source each with `baker images icon \"<desc>\"` / `baker images sticker` / `baker images gif` / `baker images logo <domain>` and add it as an <img class=\"ov pos-* \" data-start data-dur> in video-overlay-composition/index.html (never bake graphics into the frame plates). ' +\n \"(2) SOUND CUES not in sound_effects (cha-ching/coin, whoosh, ding, pop, notification, keyboard) → add a `sound_effect` node (eleven_text_to_sound) and wire it onto `audio_mix` at its timestamp. \" +\n \"(3) RECURRING people/animals/products/logos/sets with no el_* slot → add an `ingest` [TODO] slot and reference it from the frames they appear in. \" +\n '(4) Burned-in captions/text not in text_overlays → add an <img>-free <div class=\"ov\"> in index.html. ' +\n \"(5) ONE person playing MULTIPLE personas/wardrobes (skeptic vs believer, before vs after, two outfits) collapsed into a single el_* slot → split into one el_* slot PER look, each linked as the SAME individual via `same_as` so every outfit has its own reference image but the face/identity stays identical.\",\n scenes_clamped_to_clip_max: report.clamped_scenes,\n oversize_scenes:\n report.oversize_scenes.length > 0\n ? {\n scenes: report.oversize_scenes,\n fix: \"Each listed scene's own footage is longer than the gateway-safe ~10s clip ceiling, so its clip will fail the gateway (HTTP 524) — and the scaffold can't auto-split a single scene. Split each into two scenes in prompt.json (scene N+1's start frame = scene N's end frame, so the action stays continuous) before rendering.\",\n }\n : \"none — every scene fits within the gateway-safe clip ceiling.\",\n overstuffed_scenes:\n report.overstuffed_scenes.length > 0\n ? {\n scenes: report.overstuffed_scenes,\n fix: \"Each listed scene's estimated speech runs well past its window — the line will overrun the scene and push the picture off the audio timeline (lips fall behind). Shorten the copy in prompt.json or lengthen the scene before rendering.\",\n }\n : \"none — every scene's spoken length fits its window.\",\n run_warning: \"`baker canvas run` generates many billed image/video/audio assets — validate first, it is not free.\",\n };\n}\n","// Pure transform: a `video-deconstruct/1` blueprint + an AI-selected list of the\n// video's RECURRING identity elements → a runnable `baker-canvas/1` reproduction\n// canvas. No IO — the command layer runs the deconstruct + element-selection\n// passes, bakes the blueprint to `prompt.json`, calls this, validates, and writes.\n//\n// This is the video analogue of `staticAd.ts`, extended for time: every scene\n// boundary is a static-ad-grade `image_generate` (the baked blueprint as\n// `target_blueprint`, a dynamic reference legend, the real extracted frame as a\n// composition anchor), and any recurring element — a person, animal, product, or\n// logo — gets ONE shared `ingest` slot wired into every frame it appears in, so\n// the same actor is grounded by the same source image across the whole video.\n// The per-scene clip (`video_generate`) is fed an ultra-detailed motion brief\n// composed from the scene's action, camera, dialogue, and transcript.\n//\n// This module is the entry: it runs the assembly and names the scaffolder's public\n// surface. Each piece lives in the `video/` module that owns it.\n\nimport { type VideoBlueprint, VideoBlueprintSchema } from \"@baker/canvas-contract\";\nimport type { Canvas, NodeDecl } from \"../schema/canvas.ts\";\nimport { canvasDims, genAspectsFor, resolveAspect } from \"./video/aspect.ts\";\nimport {\n buildSpine,\n emitAudioMix,\n emitBlueprintIngests,\n emitCaptionChain,\n emitFinalMux,\n overlayNode,\n planCaptions,\n} from \"./video/assembly.ts\";\nimport { buildSfxMusic } from \"./video/audio.ts\";\nimport {\n annotateBlueprintWithElements,\n avatarsNotCast,\n buildElementSheets,\n buildElementSlots,\n castAvatarsOnElements,\n emitElementIngests,\n extendPresenceByPromptMentions,\n RecurringElements,\n type RecurringElementT,\n} from \"./video/elements.ts\";\nimport { VIDEO_GUIDE } from \"./video/guide.ts\";\nimport { ids, ref } from \"./video/ids.ts\";\nimport { buildVideoMeta } from \"./video/meta.ts\";\nimport type { ScaffoldVideoOpts } from \"./video/opts.ts\";\nimport { buildOverlayHtml } from \"./video/overlay-html.ts\";\nimport { slimBlueprintForFrameStyle, slimBlueprintForSelection } from \"./video/projections.ts\";\nimport { videoReport } from \"./video/report.ts\";\nimport { buildTimeline, timelineEnv } from \"./video/timeline.ts\";\nimport { buildSpineClock, type SpineClock } from \"./video/timing.ts\";\nimport { aspectRemapTodo, buildModelConstraints, buildVideoTodo } from \"./video/todo.ts\";\n\n// The public surface of the video scaffolder, named from the modules that own each piece.\nexport {\n annotateBlueprintWithElements,\n avatarsNotCast,\n buildOverlayHtml,\n buildSpineClock,\n canvasDims,\n castAvatarsOnElements,\n genAspectsFor,\n resolveAspect,\n type ScaffoldVideoOpts,\n type SpineClock,\n slimBlueprintForFrameStyle,\n slimBlueprintForSelection,\n videoReport,\n};\n\n/**\n * Carry the hook's engineered physical state into its start-frame description so the\n * generator renders it (sweaty/breathless/urgent), not a calm influencer. The\n * deconstruct captures it in `hook_mechanic.why_it_stops_scroll`; without this the\n * blueprint holds the state but the frame prompt never asks for it (CCA-11). Mutates\n * the parsed blueprint in place; idempotent (skips if already injected).\n */\nfunction injectHookPhysicality(blueprint: VideoBlueprint): void {\n for (const scene of blueprint.scenes) {\n const why = scene.hook_mechanic?.why_it_stops_scroll?.trim();\n const prompt = scene.start_frame_prompt?.trim();\n if (!why || !prompt || prompt.includes(why)) continue;\n scene.start_frame_prompt = `${prompt} The subject's physical state IS the scroll-stopper — render it explicitly, not a calm pose: ${why}.`;\n }\n}\n\n/**\n * Why `--frames reuse` cannot apply to this ad, or undefined when it can. Reuse wires the\n * source video's own frames into the clips unchanged, and the source may be somebody\n * else's ad: nothing tells footage the company owns from a competitor's, so an ad with\n * people in it (a deconstructed cast or a recurring person) would ship their faces.\n * Such an ad falls back to generated frames, recast to the `el_*` references.\n */\nfunction framesReuseRefusal(\n blueprint: VideoBlueprint,\n elements: RecurringElementT[],\n requested: ScaffoldVideoOpts[\"frames\"],\n): string | undefined {\n if (requested !== \"reuse\") return undefined;\n const showsPeople =\n (blueprint.global?.cast ?? []).length > 0 || elements.some((e) => e.type.toLowerCase() === \"person\");\n if (!showsPeople) return undefined;\n return \"--frames reuse was not applied: this video shows people, and reusing its frames would put the source's actors into our ad. Every frame is generated instead, recast to the el_* references. Reuse applies only to a video with nobody in it.\";\n}\n\n/**\n * Assemble a full video reproduction canvas. The baked blueprint as the editable\n * `prompt`, one shared `ingest` per recurring element, then the visual spine\n * (per-scene boundary frames → clips → concat), an optional burned-in overlay\n * pass, and an optional audio mix (music + voiceover + SFX) muxed under the video.\n */\nexport function scaffoldVideoCanvas(input: unknown, elementsInput: unknown, requested: ScaffoldVideoOpts): Canvas {\n const blueprint = VideoBlueprintSchema.parse(input);\n injectHookPhysicality(blueprint);\n const elements = RecurringElements.parse(elementsInput);\n const reuseRefused = framesReuseRefusal(blueprint, elements, requested.frames);\n const opts: ScaffoldVideoOpts = reuseRefused ? { ...requested, frames: \"generate\" } : requested;\n // The canvas's two ratios (output, and the one clips generate at) and its one clock,\n // each decided once: every scene, the spine, the mix and the report read the same ones.\n const aspect = resolveAspect(blueprint.source?.aspect_ratio, opts.aspect, genAspectsFor(opts.videoModel));\n const nodes: NodeDecl[] = [];\n\n emitBlueprintIngests(opts, nodes);\n\n // One shared ingest per recurring identity element, wired into every frame it appears in.\n const slots = buildElementSlots(elements);\n // A frame prompt that NAMES an element must also wire it, even when the selection\n // pass missed that scene — a described-but-unwired logo/badge renders wrong-identity.\n extendPresenceByPromptMentions(slots, blueprint);\n emitElementIngests(slots, elements, nodes);\n\n // Fuse each recurring base element (person / animal / product / location) into a\n // multi-view sheet the frames ground on — the single strongest cross-scene consistency\n // lock, so the same face/pet/pack/room is rendered everywhere from ONE multi-angle\n // sheet instead of a lone flat snapshot. Mutates slot.ref + marks slot.sheetBacked\n // before frames read it. (same_as slots reuse their linked slot's identity, no sheet.)\n buildElementSheets(slots, nodes, opts.sheetModel);\n\n // The whole timeline in one pass: the continuous per-phrase voice (presenter clips\n // voice-converted to the brand voice, or pure-b-roll tts) + the scene-by-scene\n // visual spine (presenter scenes sliced from their phrase clip, b-roll/composite on\n // their own). Voice conversion is merged per speaker, so timbre stays continuous even\n // though each shot is its own clip.\n const env = timelineEnv({ blueprint, slots, opts, aspect });\n const { clock } = env;\n const { clips, voTracks, vo_segments, talking_scenes, routes } = buildTimeline(env, nodes);\n\n // Join the per-shot clips into the visual spine (hard cuts, or xfade where the deconstruct\n // detected a transition), deduping the frame a length-split shot shares at its splice.\n // Every input is normalized onto the OUTPUT canvas raster (size/fps/SAR/timebase).\n let videoRef = buildSpine(clips, opts.seamDedup ?? \"head\", canvasDims(aspect.outAr), nodes);\n let videoNode: string = ids.spine;\n\n // Where the burned-in captions' words come from — decided now, because the overlay\n // layer (when there is one) is also what draws them.\n const captions = planCaptions(opts, voTracks);\n\n // Burned-in overlay pass. A UI-routed composite scene contributes no overlay/floating\n // element but still bakes a grouped surface stub into the composition (see\n // uiSurfaceStub), so the overlay layer must be wired for that stub to render once the\n // operator fills it in.\n const overlays = blueprint.scenes.flatMap((s) => s.overlays ?? []);\n const floating = blueprint.scenes.flatMap((s) => s.floating_elements ?? []);\n const overlaid = overlays.length > 0 || floating.length > 0 || env.uiRouted.size > 0;\n if (overlaid) {\n nodes.push(overlayNode(opts, videoRef, captions));\n videoRef = ref(ids.overlaid, \"video\");\n videoNode = ids.overlaid;\n }\n\n // Audio: mix voiceover (built above) + SFX + music onto the timeline. Built BEFORE the\n // caption track (the captions are transcribed from this real mix, below) and muxed under\n // the picture LAST. Voiceover turns are already placed at their real starts.\n const tracks = [...voTracks, ...buildSfxMusic(blueprint, clock, nodes)];\n const audioMixRef = emitAudioMix(tracks, clock, nodes);\n\n // Burned-in word-synced captions (sound-off feed). The caption text is TRANSCRIBED FROM\n // THE REAL GENERATED AUDIO — NOT the deconstruct's original transcript. This is a\n // correctness boundary: wiring the source transcript would burn the COMPETITOR's words\n // (their brand name, a claim we can't make) over our ad once the script is re-authored;\n // transcribing the rendered audio can only ever show what is actually spoken, so it\n // always tracks our re-written lines. On by DEFAULT whenever the command staged the\n // caption composition and there is voice.\n if (captions) {\n const captioned = emitCaptionChain(captions, env, tracks, videoRef, overlaid, nodes);\n videoRef = captioned.videoRef;\n videoNode = captioned.videoNode ?? videoNode;\n }\n\n if (audioMixRef) {\n emitFinalMux(videoRef, audioMixRef, nodes);\n videoNode = ids.final;\n }\n\n const todo = {\n ...buildVideoTodo(\n videoReport(input, elementsInput, opts.videoModel),\n overlays.length,\n floating.length,\n opts,\n blueprint,\n ),\n ...(reuseRefused ? { frames_reuse_refused: reuseRefused } : {}),\n ...aspectRemapTodo(aspect),\n model_constraints: buildModelConstraints(),\n };\n return {\n schema: \"baker-canvas/1\",\n metadata: {\n name: \"video reproduction\",\n description: VIDEO_GUIDE,\n todo,\n // The timing plan `baker canvas validate` checks before any billed render:\n // sequenced voiceover turns (no overlap), audio ≈ video length, and which\n // scenes must be lip-synced.\n video: buildVideoMeta(\n blueprint,\n clock,\n env.ceilingS,\n { vo_segments, talking_scenes, routes },\n slots,\n nodes,\n Boolean(audioMixRef),\n ),\n },\n nodes,\n output: { node: videoNode, output: \"video\" },\n };\n}\n","/**\n * Where a burned-in caption breaks.\n *\n * The karaoke composition sliced the transcript into fixed N-word groups, and a\n * word count knows nothing about the sentence it is cutting. Rendered, that gave\n * cards reading \"OTRA VEZ, EN\" and \"TU CASA GENERA\" — half-thoughts ending on a\n * preposition, which is how a caption track announces that nobody read it.\n *\n * So the break follows the script: a card closes when the line does. The word cap\n * stays as a ceiling, because a fifteen-word clause has to be split somewhere or\n * it renders as a paragraph, and a linking word is never left hanging at the end\n * of a card — \"de\", \"al\", \"y\" carry the sentence into the next word, and a card\n * that ends on one reads as interrupted. Which words those are is decided per script\n * by Jev when the canvas is scaffolded (`carriesOnQuestions`), never listed here: an ad\n * is in any language.\n *\n * Shared with the composition rather than duplicated in it: this is the same rule\n * `caption-style.ts` checks for, and a rule enforced in one place and checked in\n * another is a rule that drifts.\n */\n\nimport type { JevAnswer, JevQuestion } from \"./jev.ts\";\n\n/**\n * One timed word, named as the engine emits it.\n *\n * The field is `text`, not `word` — the video blueprint's transcript words\n * (`transcript_slice`, `@baker/canvas-contract`) define it and every producer follows. Calling it `word` here is what broke the\n * rule below in the composition that renders it: the check read `w.word`, got\n * `undefined` on every real word, and silently fell back to slicing on the word\n * cap — the exact behaviour this module exists to replace.\n */\nexport type CaptionWord = { text: string; start: number; end: number };\n\n/** Terminal marks that end a card. */\nconst CLOSES = /[.,;:!?…]$/;\n\n/** A word as a card's rule compares it: without its closing mark, in lower case. Pure. */\nexport function captionWordKey(text: string): string {\n return text.replace(/[.,;:!?…]+$/, \"\").toLocaleLowerCase();\n}\n\n/**\n * At or above this probability, Jev says the word leans on the next one. Measured: see\n * docs/decision-model.md.\n */\nexport const CARRIES_ON_HELD = 0.4;\n\nconst CARRIES_ON_QUESTION =\n \"Is `word`, as used in `line`, a function word that cannot close a phrase: an article, a preposition, a conjunction, a possessive or another determiner? A noun, verb, adjective, adverb, name or number is not.\";\n\n/**\n * One yes/no question per distinct word of the script, asked in the first line it appears in:\n * whether a card may end on it. Asked of Jev rather than a list of words, because a script is\n * in any language, or two at once, and a list only knows the ones somebody typed. Pure.\n */\nexport function carriesOnQuestions(lines: readonly string[]): { questions: JevQuestion[]; words: string[] } {\n const seen = new Set<string>();\n const questions: JevQuestion[] = [];\n for (const line of lines) {\n for (const text of line.split(/\\s+/)) {\n const word = captionWordKey(text);\n if (!word || seen.has(word)) continue;\n seen.add(word);\n questions.push({ type: \"noul\", instructions: { line, word, question: CARRIES_ON_QUESTION } });\n }\n }\n return { questions, words: [...seen] };\n}\n\n/** The words Jev held as leaning on the next one; none when it could not answer. Pure. */\nexport function carriesOnFromAnswers(words: readonly string[], answers: readonly JevAnswer[] | null): string[] {\n if (!answers) return [];\n return words.filter((_, i) => {\n const answer = answers[i];\n return answer !== undefined && \"noul\" in answer && answer.noul >= CARRIES_ON_HELD;\n });\n}\n\n/**\n * The script's words cut into cards. `carriesOn` holds the words a card may not end on\n * (`captionWordKey` form); empty, the cap alone closes a long clause.\n */\nexport function groupCaptionWords(\n words: CaptionWord[],\n maxPerGroup: number,\n carriesOn: ReadonlySet<string> = new Set(),\n): CaptionWord[][] {\n const cap = Math.max(1, maxPerGroup);\n const groups: CaptionWord[][] = [];\n let current: CaptionWord[] = [];\n\n for (const word of words) {\n current.push(word);\n const last = current[current.length - 1] as CaptionWord;\n // A clause end closes the card outright. The cap only closes it when the card\n // would otherwise run long — and never onto a word that carries on, because\n // that just moves the interrupted thought one word later.\n //\n // So the cap is a PREFERENCE, not a ceiling, and a card can come back a word or two\n // over it: the run of linking words bounds the overshoot, and it is short. That is\n // deliberate and it was measured — \"en la factura de la luz.\" ships as one six-word\n // card at a cap of four, because every earlier cut left a preposition hanging at the\n // end of a card nobody wrote that way. Closing before the linking word instead breaks\n // that same reading: it is the interrupted thought again, one card earlier.\n const closes = CLOSES.test(last.text) || (current.length >= cap && !carriesOn.has(captionWordKey(last.text)));\n if (closes) {\n groups.push(current);\n current = [];\n }\n }\n if (current.length > 0) groups.push(current);\n return groups;\n}\n","/**\n * What a reproduced video's speech says, read when `scaffold-video` builds the canvas: Jev\n * decides, in one request, the language the lines are spoken in (when nobody declared it and the\n * transcriber did not hear it) and the words a caption card may not end on; a text model reads,\n * beside it, the voice each description asks for. Kept in the canvas's rebuild context, so a\n * rebuild never asks again.\n *\n * When a reader cannot answer, nothing is guessed: no language (ElevenLabs detects it from the\n * text), no gender filter (the description alone ranks the cast), the word cap alone.\n */\nimport { carriesOnFromAnswers, carriesOnQuestions } from \"../../nodes/local/lib/caption-groups.ts\";\nimport type { JevAnswer, JevQuestion } from \"../../nodes/local/lib/jev.ts\";\nimport { languageFromAnswer, languageQuestion, spokenLanguage, voiceLanguageOf } from \"../lib/language.ts\";\nimport type { ReadVoiceGenders, VoiceGender } from \"./dialogue/voice-gender.ts\";\nimport type { ScaffoldVideoOpts } from \"./opts.ts\";\n\nexport type SpeechReaders = {\n ask: (questions: readonly JevQuestion[]) => Promise<JevAnswer[] | null>;\n genders: ReadVoiceGenders;\n};\n\nexport type BlueprintSpeech = {\n /** BCP-47 tag of the spoken language: declared, else Jev's when it was sure. */\n spokenLanguage?: string;\n voiceGenders: Record<string, VoiceGender>;\n captionCarriesOn: string[];\n read: boolean;\n};\n\ntype Line = { line?: string; voice_description?: string };\ntype SpeechBlueprint = {\n global?: { cast?: Array<{ description?: string }>; voiceover?: { voice_description?: string } };\n scenes?: Array<{ dialogue?: Line[] }>;\n};\n\nconst asBlueprint = (input: unknown) => (input && typeof input === \"object\" ? (input as SpeechBlueprint) : {});\nconst dialogueOf = (b: SpeechBlueprint): Line[] => (b.scenes ?? []).flatMap((s) => s.dialogue ?? []);\n\n/** Every description a speaker can be cast from (`makeVoiceFactory`), once each, in that order. Pure. */\nexport function blueprintVoices(input: unknown): string[] {\n const b = asBlueprint(input);\n const all = [\n ...dialogueOf(b).map((l) => l.voice_description),\n ...(b.global?.cast ?? []).map((c) => c.description),\n b.global?.voiceover?.voice_description,\n ];\n return [...new Set(all.filter((d): d is string => typeof d === \"string\" && d.length > 0))];\n}\n\n/** Read the blueprint's speech; `declaredLanguage` (a tag) is kept over the lines. */\nexport async function readBlueprintSpeech(\n input: unknown,\n known: { declaredLanguage?: string },\n readers: SpeechReaders,\n): Promise<BlueprintSpeech> {\n const lines = dialogueOf(asBlueprint(input))\n .map((l) => l.line?.trim() ?? \"\")\n .filter(Boolean);\n const declared = known.declaredLanguage ? spokenLanguage(known.declaredLanguage)?.tag : undefined;\n const voices = blueprintVoices(input);\n const carries = carriesOnQuestions(lines);\n const language = !declared && lines.length > 0 ? [languageQuestion(lines)] : [];\n const [answers, genders] = await Promise.all([\n readers.ask([...language, ...carries.questions]),\n readers.genders(voices).catch(() => null),\n ]);\n const voiceGenders: Record<string, VoiceGender> = genders ?? {};\n if (!answers)\n return { ...(declared ? { spokenLanguage: declared } : {}), voiceGenders, captionCarriesOn: [], read: false };\n const read = declared ?? (language.length > 0 ? languageFromAnswer(answers[0]) : undefined);\n return {\n ...(read ? { spokenLanguage: read } : {}),\n voiceGenders,\n captionCarriesOn: carriesOnFromAnswers(carries.words, answers.slice(language.length)),\n read: true,\n };\n}\n\n/**\n * The speech facts a rebuild context written before they were read at scaffold time lacks: the\n * spoken language (unless it names one, as a tag or an older English name) and each voice's\n * gender. Null when the context already has them, or when a reader could not answer — then\n * nothing is guessed and the next rebuild asks again. A context scaffolded since always carries\n * `voiceGenders`, so that field is what marks it as read.\n */\nexport async function speechMissingFromRebuild(\n input: unknown,\n opts: Pick<ScaffoldVideoOpts, \"spokenLanguage\" | \"voiceLanguage\" | \"voiceGenders\">,\n readers: SpeechReaders,\n): Promise<Pick<ScaffoldVideoOpts, \"spokenLanguage\" | \"voiceGenders\"> | null> {\n if (opts.voiceGenders !== undefined) return null;\n const lines = dialogueOf(asBlueprint(input))\n .map((l) => l.line?.trim() ?? \"\")\n .filter(Boolean);\n const voices = blueprintVoices(input);\n if (lines.length === 0 && voices.length === 0) return null;\n const askLanguage = !voiceLanguageOf(opts) && lines.length > 0;\n const [answers, genders] = await Promise.all([\n askLanguage ? readers.ask([languageQuestion(lines)]).catch(() => null) : Promise.resolve([]),\n readers.genders(voices).catch(() => null),\n ]);\n if (!answers || !genders) return null;\n const language = askLanguage ? languageFromAnswer(answers[0]) : undefined;\n return { ...(language ? { spokenLanguage: language } : {}), voiceGenders: genders };\n}\n","import { mkdir, readFile, readdir, rm, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\n/**\n * Per-scene source-of-truth files for a video creative.\n *\n * The video scaffold used to bake the WHOLE deconstruct blueprint — global cast/\n * palette plus a per-scene array that dominates the file (2000+ lines for a 15-scene\n * ad) — into one `prompt.json`. An agent adapting the ad had to edit that monolith\n * (and the equally large canvas), which is too big to edit reliably.\n *\n * Now the blueprint is split: `prompt.json` keeps only the GLOBAL slice, and each\n * scene is written to `scenes/sNN.json`. An agent edits one small scene file at a\n * time; `run`/`validate` re-assemble the full blueprint and re-flow every scene's\n * prompt back into the graph (see `scene-projection.ts`). The scene file is the\n * single source of truth for that scene — the inlined canvas node prompts are a\n * scaffold-time snapshot the sync regenerates.\n */\nexport const SCENES_DIR = \"scenes\";\n/** Global (scene-less) blueprint surface — the file the agent edits for cast/palette/brand. */\nexport const GLOBAL_PROMPT_FILE = \"prompt.json\";\n/**\n * Frozen, non-operator-edited rebuild context ({ elements, opts }) the sync feeds\n * back into `scaffoldVideoCanvas` to regenerate scene prompts deterministically,\n * with NO model call. Written once at scaffold time; never hand-edited.\n */\nexport const REBUILD_FILE = \"prompt.rebuild.json\";\n\n/** `scenes/s00.json`-style name, zero-padded to a stable width so a lexical sort is a scene-order sort. */\nexport function sceneFileName(index: number, total: number): string {\n const width = Math.max(2, String(Math.max(0, total - 1)).length);\n return `s${String(index).padStart(width, \"0\")}.json`;\n}\n\n/** Split an annotated blueprint into its global slice (no scenes) and its scene list. */\nexport function splitBlueprint(blueprint: unknown): { global: Record<string, unknown>; scenes: unknown[] } {\n if (!blueprint || typeof blueprint !== \"object\") {\n return { global: {}, scenes: [] };\n }\n const { scenes, ...global } = blueprint as Record<string, unknown>;\n return { global, scenes: Array.isArray(scenes) ? scenes : [] };\n}\n\n/**\n * Write the split blueprint: `prompt.json` (global only) + `scenes/sNN.json` per\n * scene. Any stale `scenes/*.json` from a previous scaffold with MORE scenes is\n * removed so the directory always mirrors the current blueprint exactly.\n */\nexport async function writeSceneFiles(outDir: string, blueprint: unknown): Promise<void> {\n const { global, scenes } = splitBlueprint(blueprint);\n await writeFile(path.join(outDir, GLOBAL_PROMPT_FILE), `${JSON.stringify(global, null, 2)}\\n`, \"utf8\");\n const scenesDir = path.join(outDir, SCENES_DIR);\n await mkdir(scenesDir, { recursive: true });\n const written = new Set<string>();\n for (let i = 0; i < scenes.length; i++) {\n const name = sceneFileName(i, scenes.length);\n written.add(name);\n await writeFile(path.join(scenesDir, name), `${JSON.stringify(scenes[i], null, 2)}\\n`, \"utf8\");\n }\n for (const name of await listSceneFileNames(scenesDir)) {\n if (!written.has(name)) await rm(path.join(scenesDir, name), { force: true });\n }\n}\n\n/** Scene file names (`sNN.json`) in scene order. Empty when the dir is absent. */\nasync function listSceneFileNames(scenesDir: string): Promise<string[]> {\n let entries: string[];\n try {\n entries = await readdir(scenesDir);\n } catch {\n return [];\n }\n return entries.filter((n) => /^s\\d+\\.json$/.test(n)).sort(bySceneIndex);\n}\n\n/** Absolute scene file paths in scene order for a creative dir. Empty when there is no scenes dir. */\nexport async function listSceneFiles(creativeDir: string): Promise<string[]> {\n const scenesDir = path.join(creativeDir, SCENES_DIR);\n return (await listSceneFileNames(scenesDir)).map((n) => path.join(scenesDir, n));\n}\n\n/**\n * Re-assemble the full blueprint from the global `prompt.json` + `scenes/*.json`.\n * Returns null when the creative has no scene files (an old, unsplit canvas), so\n * the caller can degrade to the legacy single-file behavior.\n */\nexport async function reassembleBlueprint(creativeDir: string): Promise<Record<string, unknown> | null> {\n const files = await listSceneFiles(creativeDir);\n if (files.length === 0) return null;\n const globalRaw = await readFile(path.join(creativeDir, GLOBAL_PROMPT_FILE), \"utf8\");\n const global = JSON.parse(globalRaw) as Record<string, unknown>;\n const scenes: unknown[] = [];\n for (const file of files) {\n scenes.push(JSON.parse(await readFile(file, \"utf8\")));\n }\n return { ...global, scenes };\n}\n\nfunction bySceneIndex(a: string, b: string): number {\n const ai = Number(a.match(/^s(\\d+)\\.json$/)?.[1] ?? 0);\n const bi = Number(b.match(/^s(\\d+)\\.json$/)?.[1] ?? 0);\n return ai - bi;\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport {\n AD_IMAGE_MODEL,\n DEFAULT_VIDEO_GENERATE_MODEL,\n isRegisteredModel,\n type NodeKind,\n REFERENCE_SHEET_MODEL,\n} from \"@baker/canvas-contract\";\nimport { type ScaffoldVideoOpts, scaffoldVideoCanvas } from \"../../engine/scaffold/video.ts\";\nimport { type SpeechReaders, speechMissingFromRebuild } from \"../../engine/scaffold/video/speech-reading.ts\";\nimport type { CreativeRule } from \"../../engine/creative-rules/schema.ts\";\nimport { briefRules, rulesBlock } from \"../../engine/creative-rules/select.ts\";\nimport { listSceneFiles, REBUILD_FILE, reassembleBlueprint } from \"./scene-files.ts\";\n\n/**\n * Re-flow per-scene edits back into the video graph before billing.\n *\n * The scaffold splits the blueprint into `prompt.json` (global) + `scenes/sNN.json`\n * (one per scene). Each scene's generative prompt is ALSO inlined into its\n * `image_generate` / `video_generate` node's `params.prompt` at scaffold time —\n * frozen there, read by the run. So editing a scene file does nothing to the render\n * on its own. This sync closes that gap: it re-assembles the full blueprint from the\n * (edited) scene files, feeds it back through the SAME deterministic builder\n * (`scaffoldVideoCanvas`, no model call) using the frozen rebuild context, and copies\n * the regenerated `params.prompt` onto the matching live nodes. The node's changed\n * param re-keys the content-addressed cache, so only the edited scenes re-bill.\n *\n * It mirrors `syncStyleProjection` (which does the same for global cast/palette via\n * the `prompt_style` projection). It mutates the canvas it is handed; `prepareCanvas`\n * then writes the result back to the canvas file, so the file on disk always carries the\n * prompts that render. The scene files stay the source of truth: an edit to a projected\n * node prompt in the canvas is overwritten on the next preflight.\n *\n * SCOPE: prompt text, and the captions' script (the spoken lines). A timing/structural edit (changed scene window, a scene\n * whose route flips clip↔still, added/removed scenes) is NOT a prompt re-flow — it\n * needs a fresh `baker canvas scaffold-video`. Such edits surface here as a drift\n * warning (a non-prompt param diverged, or the node-id sets don't match), never a\n * silent partial apply.\n */\nconst PROMPT_NODE_TYPES = new Set([\"image_generate\", \"video_generate\"]);\n\ntype CanvasNode = { id?: unknown; type?: unknown; params?: Record<string, unknown> };\n\nexport type SceneSyncResult = \"regenerated\" | \"up_to_date\" | \"not_applicable\";\n\nfunction nodesOfTypes(canvas: unknown, types: ReadonlySet<string>): Map<string, CanvasNode> {\n const out = new Map<string, CanvasNode>();\n const nodes = (canvas as { nodes?: unknown })?.nodes;\n if (!Array.isArray(nodes)) return out;\n for (const n of nodes as CanvasNode[]) {\n if (typeof n?.id === \"string\" && typeof n?.type === \"string\" && types.has(n.type)) {\n out.set(n.id, n);\n }\n }\n return out;\n}\n\nconst promptNodes = (canvas: unknown) => nodesOfTypes(canvas, PROMPT_NODE_TYPES);\n\n/**\n * The captions' `script` is the spoken lines, so a line edited in a scene file has to reach\n * it too. Otherwise the regenerated clip says the new words and the captions, aligned to the\n * old script, print the old ones. Returns how many transcribe nodes changed.\n */\nfunction syncCaptionScripts(canvas: unknown, rebuilt: unknown): number {\n const transcribe = new Set([\"video_transcribe\"]);\n const liveNodes = nodesOfTypes(canvas, transcribe);\n let changed = 0;\n for (const [id, rebuiltNode] of nodesOfTypes(rebuilt, transcribe)) {\n const live = liveNodes.get(id);\n const script = rebuiltNode.params?.script;\n if (!live || typeof script !== \"string\" || live.params?.script === script) continue;\n (live.params ??= {}).script = script;\n changed++;\n }\n return changed;\n}\n\n/** Shallow-equal a node's params EXCEPT `prompt` — a diff here means a structural/timing edit. */\nfunction nonPromptParamsDiverge(live: Record<string, unknown> = {}, rebuilt: Record<string, unknown> = {}): boolean {\n const keys = new Set([...Object.keys(live), ...Object.keys(rebuilt)]);\n keys.delete(\"prompt\");\n for (const k of keys) {\n if (JSON.stringify(live[k]) !== JSON.stringify(rebuilt[k])) return true;\n }\n return false;\n}\n\n/** Each model a rebuild context pins, the node kind it runs as, and the role default that stands in for it. */\nconst REBUILD_MODEL_ROLES: ReadonlyArray<{\n field: \"imageModel\" | \"videoModel\" | \"sheetModel\";\n kind: NodeKind;\n fallback: string;\n}> = [\n { field: \"imageModel\", kind: \"image_generate\", fallback: AD_IMAGE_MODEL },\n { field: \"videoModel\", kind: \"video_generate\", fallback: DEFAULT_VIDEO_GENERATE_MODEL },\n { field: \"sheetModel\", kind: \"image_reference_sheet\", fallback: REFERENCE_SHEET_MODEL },\n];\n\nexport type RebuildModelReplacement = { field: string; from: string; to: string };\n\n/**\n * The rebuild context with every pinned model the registry accepts for its role.\n *\n * A frozen `prompt.rebuild.json` keeps whatever model ids the scaffold wrote, and some\n * are wrong: creatives scaffolded before the sheet model was pinned stored gpt-image\n * as `sheetModel`, which `image_reference_sheet` does not register, so the rebuilt graph\n * would carry an `unknown_model` sheet. Such a model is replaced with its role default\n * and reported, never silently kept. An absent optional model stays absent.\n */\nexport function registeredRebuildOpts(opts: ScaffoldVideoOpts): {\n opts: ScaffoldVideoOpts;\n replaced: RebuildModelReplacement[];\n} {\n const next: ScaffoldVideoOpts = { ...opts };\n const replaced: RebuildModelReplacement[] = [];\n for (const { field, kind, fallback } of REBUILD_MODEL_ROLES) {\n const model = next[field];\n if (model === undefined || isRegisteredModel(kind, model)) continue;\n next[field] = fallback;\n replaced.push({ field, from: model, to: fallback });\n }\n return { opts: next, replaced };\n}\n\n/** One line naming every pinned model the rebuild stood a role default in for, or nothing. */\nfunction warnReplacedModels(replaced: RebuildModelReplacement[], log: (line: string) => void): void {\n if (replaced.length === 0) return;\n const from = replaced.map((r) => `${r.field} \"${r.from}\"`).join(\", \");\n const to = replaced.map((r) => `\"${r.to}\"`).join(\", \");\n log(\n `[scenes] ${REBUILD_FILE} pins ${from}, which the model registry does not accept for that role; ` +\n `rebuilding with ${to} instead. Re-scaffold the creative to record the new model.`,\n );\n}\n\n/** The frozen rebuild context, with its models checked against the registry (see `registeredRebuildOpts`). */\nfunction parseRebuild(raw: string): {\n elements: unknown;\n opts: ScaffoldVideoOpts;\n replaced: RebuildModelReplacement[];\n} {\n const { elements, opts } = JSON.parse(raw) as { elements: unknown; opts: ScaffoldVideoOpts };\n return { elements, ...registeredRebuildOpts(opts) };\n}\n\n/**\n * The rebuild context with the spoken language and each voice's gender, read once for a context\n * written before the scaffold read them and kept in `prompt.rebuild.json`, so every later rebuild\n * reads and casts in them without asking again. Without it, a rebuilt French video read its\n * numbers with English rules and cast its voice with no gender filter. A reader that cannot\n * answer leaves the context as it is.\n */\nasync function withSpeechRead(\n file: string,\n rebuildRaw: string,\n blueprint: unknown,\n opts: ScaffoldVideoOpts,\n readers: SpeechReaders,\n): Promise<ScaffoldVideoOpts> {\n const read = await speechMissingFromRebuild(blueprint, opts, readers);\n if (!read) return opts;\n const stored = JSON.parse(rebuildRaw) as { opts: ScaffoldVideoOpts };\n const kept = { ...stored, opts: { ...stored.opts, ...read } };\n await writeFile(file, `${JSON.stringify(kept, null, 2)}\\n`, \"utf8\").catch(() => undefined);\n return { ...opts, ...read };\n}\n\n/**\n * The canvas nodes whose `params.prompt` the scene files own, each with the scene file it\n * is rebuilt from. Empty for a canvas with no scene files or no rebuild context (its\n * prompts are its own). Throws like `syncSceneNodeParams` on an unreadable scene file.\n */\nexport async function sceneOwnedPrompts(canvasPath: string): Promise<Map<string, string>> {\n const creativeDir = path.dirname(canvasPath);\n const blueprint = await reassembleBlueprint(creativeDir);\n if (!blueprint) return new Map();\n let rebuildRaw: string;\n try {\n rebuildRaw = await readFile(path.join(creativeDir, REBUILD_FILE), \"utf8\");\n } catch {\n return new Map();\n }\n const { elements, opts } = parseRebuild(rebuildRaw);\n const sceneFiles = await listSceneFiles(creativeDir);\n const owned = new Map<string, string>();\n for (const node of scaffoldVideoCanvas(blueprint, elements, opts).nodes) {\n if (!PROMPT_NODE_TYPES.has(node.type)) continue;\n // The video builder tags every frame and clip with the scene it renders, in\n // scene-file order; a node with no scene (an identity sheet) belongs to no file.\n const index = node.tags?.scene;\n const file = index === undefined ? undefined : sceneFiles[index];\n if (file) owned.set(node.id, file);\n }\n return owned;\n}\n\n/**\n * Regenerate scene node prompts from the (possibly edited) scene files and splice them\n * onto `canvas` in place. Call AFTER `resolveRelativeCanvasPaths`, BEFORE billing.\n * `canvasPath` locates the sibling `scenes/` dir and rebuild sidecar. Throws when a\n * scene file / rebuild context is unreadable or the rebuild fails — the caller must\n * fail before billing. Returns `not_applicable` for a canvas with no scene files\n * (a legacy, unsplit creative) so those keep working unchanged.\n */\nexport async function syncSceneNodeParams(\n canvas: unknown,\n canvasPath: string,\n log: (line: string) => void,\n /** Read the speech facts an older rebuild context lacks (`withSpeechRead`); absent, it is rebuilt as it is. */\n readers?: SpeechReaders,\n /** The company's rules: the ones a picture can keep are told to every frame (`briefRules`). */\n rules: readonly CreativeRule[] = [],\n): Promise<SceneSyncResult> {\n const creativeDir = path.dirname(canvasPath);\n const blueprint = await reassembleBlueprint(creativeDir);\n if (!blueprint) return \"not_applicable\";\n\n let rebuildRaw: string;\n try {\n rebuildRaw = await readFile(path.join(creativeDir, REBUILD_FILE), \"utf8\");\n } catch {\n // No frozen rebuild context. For a canvas with no scene files at all this is an old,\n // unsplit creative and staying quiet is right. But a canvas that HAS scene files and\n // no sidecar is the bad case: someone edits a shot, re-runs, and the edit is\n // discarded without a word. An ad scaffolded before `scaffold-ad` wrote this file\n // behaved exactly that way, and the agent could only report that the frame \"was\n // still cached\" — it was not cached, it was never rebuilt.\n log(\n `[scenes] this creative has scene files but no ${REBUILD_FILE}, so edits to scenes/*.json are NOT reaching ` +\n \"the render — the prompts inlined in the canvas are what renders. Re-scaffold the creative to restore the \" +\n \"link, or edit the canvas node prompts directly.\",\n );\n return \"not_applicable\";\n }\n const parsed = parseRebuild(rebuildRaw);\n const { elements, replaced } = parsed;\n warnReplacedModels(replaced, log);\n const opts = readers\n ? await withSpeechRead(path.join(creativeDir, REBUILD_FILE), rebuildRaw, blueprint, parsed.opts, readers)\n : parsed.opts;\n\n const rebuilt = scaffoldVideoCanvas(blueprint, elements, opts);\n const rebuiltNodes = promptNodes(rebuilt);\n // The frames are pictures: each is told the company's rules a picture can keep, in a block the\n // fingerprint leaves out (a rule is the company's, never one ad's edit).\n const ruled = rulesBlock(briefRules(rules), \"The company's own rules for every ad it makes, each one kept in this frame:\");\n if (ruled) {\n for (const node of rebuiltNodes.values()) {\n if (node.type === \"image_generate\" && typeof node.params?.prompt === \"string\") {\n node.params.prompt = `${node.params.prompt}\\n\\n${ruled}`;\n }\n }\n }\n const liveNodes = promptNodes(canvas);\n\n const missingInLive = [...rebuiltNodes.keys()].filter((id) => !liveNodes.has(id));\n const missingInRebuilt = [...liveNodes.keys()].filter((id) => !rebuiltNodes.has(id));\n if (missingInLive.length > 0 || missingInRebuilt.length > 0) {\n log(\n \"[scenes] scene structure changed since scaffold (a scene's route, timing, or count differs) — \" +\n \"re-run `baker canvas scaffold-video` to rebuild the graph. Prompt-only edits were still applied where the nodes still match.\",\n );\n }\n\n let changed = 0;\n let structural = false;\n for (const [id, rebuiltNode] of rebuiltNodes) {\n const live = liveNodes.get(id);\n if (!live) continue;\n const liveParams = (live.params ??= {});\n const rebuiltParams = rebuiltNode.params ?? {};\n if (nonPromptParamsDiverge(liveParams, rebuiltParams)) structural = true;\n if (typeof rebuiltParams.prompt === \"string\" && liveParams.prompt !== rebuiltParams.prompt) {\n liveParams.prompt = rebuiltParams.prompt;\n changed++;\n }\n }\n\n if (structural) {\n log(\n \"[scenes] a scene edit changed clip timing or audio (not just prompt text) — the graph's timing nodes were NOT updated; \" +\n \"re-run `baker canvas scaffold-video` so the spine and voice tracks match.\",\n );\n }\n changed += syncCaptionScripts(canvas, rebuilt);\n if (changed === 0) return \"up_to_date\";\n log(\n `[scenes] re-flowed ${changed} scene prompt(s) from scenes/*.json into the graph — the affected frames/clips will re-bill on the next run`,\n );\n return \"regenerated\";\n}\n","import { readdir, readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { canonicalize } from \"@baker/canvas-contract\";\nimport { parse as parseYaml } from \"yaml\";\nimport { withoutRulesDeep } from \"../../engine/creative-rules/select.ts\";\nimport { looksLikeHttpUrl } from \"../../engine/lib/url.ts\";\nimport { sha256Hex } from \"../../engine/storage/sha256.ts\";\nimport { listSceneFiles } from \"./scene-files.ts\";\n\n/**\n * THE fingerprint of a creative's editable source: everything an edit can change that\n * changes what the models are sent. It is the one answer to \"was this edited since it last\n * rendered\", and every place that asks uses it:\n *\n * - `baker canvas sync-definition` posts it on every edit (the dashboard's \"current\" half),\n * - a completed `baker canvas run` posts it and records it locally as what it rendered,\n * - `baker canvas stale` (read by the Stop hook and the `validate-creative-renders` check)\n * compares the two,\n * - remote resume adopts an interrupted run only for the same fingerprint.\n *\n * Folded in, length-prefixed so bytes cannot move across a boundary unnoticed:\n * - the graph as it renders: `graph` when the caller has projected it (`prepareCanvas`\n * applies the copy, logo, scene and, later, brief projections, so whatever the models\n * receive from the blueprint lands in the node params hashed here), else\n * `{slug}.canvas.json` as it stands; the company's rules a compiled prompt carries\n * (`<company_rules>`) are left out, since a rule is the company's and never one ad's edit,\n *\n * - its sibling `prompt.json`, without its bookkeeping (`BLUEPRINT_BOOKKEEPING_KEYS`),\n * - every `scenes/sNN.json`, in scene order,\n * - every local composition directory a `hyperframe_render`/`hyperframe_snapshot` node\n * renders (`layout-*`, `_composition-*`, captions), file by file with their paths,\n * - the `formats` list in `_definition.md` (the rest of that file, status and strategy\n * included, is bookkeeping and never changes a render).\n *\n * JSON is hashed in canonical form (sorted keys, no whitespace), so a formatter reflowing a\n * file is not an edit. Content-addressed (never mtime), so a checkout at another path or a\n * clone reads the same. Derived files (`prompt.style.json`, `prompt.plate.json`,\n * `prompt.compose.json`, `prompt.rebuild.json`) are left out: they are rebuilt from the\n * sources above.\n *\n * Prefixed `v3:`. The v1 rule hashed raw bytes; v2 hashed this rule over the graphs before a\n * static ad could be rebuilt on one picture (`upgradeStaticCanvas`). `isSourceStale`\n * (`@baker/api`) never compares fingerprints of different versions, so moving to this one\n * marks nothing already rendered as edited. The cost: a creative truly edited before the move\n * shows as unedited until it is rendered again.\n */\nexport async function computeSourceSha(canvasPath: string, opts: { graph?: unknown } = {}): Promise<string | undefined> {\n let canvasBytes: Buffer;\n try {\n canvasBytes = await readFile(canvasPath);\n } catch {\n // No canvas to fingerprint: the caller degrades (skips staleness), never fails.\n return undefined;\n }\n const canvasDir = path.dirname(canvasPath);\n const parts: Buffer[] = [];\n const fold = (bytes: Buffer) => parts.push(Buffer.from(`${bytes.length}\\0`), bytes);\n\n const graph = opts.graph !== undefined ? opts.graph : parseOrUndefined(canvasBytes);\n // The company's rules ride in compiled prompts but are never one ad's edit (`withoutRulesDeep`).\n fold(graph === undefined ? canvasBytes : Buffer.from(canonicalize(withoutRulesDeep(graph))));\n fold(canonicalJson(await readOrEmpty(path.join(canvasDir, \"prompt.json\")), withoutBookkeeping));\n for (const sceneFile of await listSceneFiles(canvasDir)) fold(canonicalJson(await readOrEmpty(sceneFile)));\n for (const dir of compositionDirs(graph, canvasPath)) {\n fold(Buffer.from(`composition:${toPosix(path.relative(canvasDir, dir))}`));\n for (const file of await listCompositionFiles(dir)) {\n fold(Buffer.from(toPosix(path.relative(dir, file))));\n fold(await readOrEmpty(file));\n }\n }\n fold(Buffer.from(JSON.stringify(await definitionFormats(canvasDir))));\n return `${SOURCE_SHA_VERSION}:${sha256Hex(Buffer.concat(parts))}`;\n}\n\nconst SOURCE_SHA_VERSION = \"v3\";\n\nfunction parseOrUndefined(bytes: Buffer): unknown {\n try {\n return JSON.parse(bytes.toString(\"utf8\"));\n } catch {\n return undefined;\n }\n}\n\n/**\n * A JSON source as its canonical form (sorted keys, no whitespace), so a formatter\n * reflowing the file is not an edit. Bytes that do not parse (mid-edit, or empty) count\n * as they are.\n */\nfunction canonicalJson(bytes: Buffer, project: (value: unknown) => unknown = (value) => value): Buffer {\n if (bytes.length === 0) return bytes;\n try {\n return Buffer.from(canonicalize(project(JSON.parse(bytes.toString(\"utf8\")))));\n } catch {\n return bytes;\n }\n}\n\n/**\n * The blueprint's top-level fields that record where the ad came from and why, never what\n * it shows: the winners library's read of the reference (`reference`), the source ad's\n * advertiser and market (`source_context`), and the agent's `notes`. Editing them after a\n * render never makes it stale.\n */\nexport const BLUEPRINT_BOOKKEEPING_KEYS: ReadonlySet<string> = new Set([\"reference\", \"source_context\", \"notes\"]);\n\nfunction withoutBookkeeping(blueprint: unknown): unknown {\n if (!blueprint || typeof blueprint !== \"object\" || Array.isArray(blueprint)) return blueprint;\n return Object.fromEntries(Object.entries(blueprint).filter(([key]) => !BLUEPRINT_BOOKKEEPING_KEYS.has(key)));\n}\n\nasync function readOrEmpty(file: string): Promise<Buffer> {\n try {\n return await readFile(file);\n } catch {\n return Buffer.alloc(0);\n }\n}\n\nconst COMPOSITION_NODE_TYPES = new Set([\"hyperframe_render\", \"hyperframe_snapshot\"]);\n\n/**\n * The local composition directories the canvas renders, resolved against the canvas file,\n * deduped and sorted. A directory holding the canvas itself is skipped: it would fold the\n * whole creative (and every render reference in it) in twice.\n */\nfunction compositionDirs(canvas: unknown, canvasPath: string): string[] {\n const nodes = (canvas as { nodes?: unknown } | null)?.nodes;\n if (!Array.isArray(nodes)) return [];\n const canvasDir = path.dirname(canvasPath);\n const dirs = new Set<string>();\n for (const node of nodes as Array<{ type?: unknown; params?: { composition?: unknown } }>) {\n if (typeof node?.type !== \"string\" || !COMPOSITION_NODE_TYPES.has(node.type)) continue;\n const ref = node.params?.composition;\n if (typeof ref !== \"string\" || ref.length === 0 || ref.includes(\"[TODO\") || looksLikeHttpUrl(ref)) continue;\n const dir = path.resolve(canvasDir, ref);\n const rel = path.relative(dir, canvasDir);\n if (rel === \"\" || (!rel.startsWith(\"..\") && !path.isAbsolute(rel))) continue;\n dirs.add(dir);\n }\n return [...dirs].sort();\n}\n\n// What the renderer itself never copies out of a composition (hyperframe.ts `copyComposition`).\nconst SKIPPED_ENTRIES = new Set([\".cache\", \"node_modules\", \".git\", \".DS_Store\"]);\n\nasync function listCompositionFiles(dir: string): Promise<string[]> {\n let entries: Array<{ name: string; parentPath: string; isFile(): boolean }>;\n try {\n entries = await readdir(dir, { recursive: true, withFileTypes: true });\n } catch {\n return [];\n }\n return entries\n .filter((entry) => entry.isFile())\n .map((entry) => path.join(entry.parentPath, entry.name))\n .filter((file) => !path.relative(dir, file).split(path.sep).some((part) => SKIPPED_ENTRIES.has(part)))\n .sort();\n}\n\n/** The `formats` list from `_definition.md`'s frontmatter, or [] when there is none to read. */\nasync function definitionFormats(canvasDir: string): Promise<unknown[]> {\n let raw: string;\n try {\n raw = await readFile(path.join(canvasDir, \"_definition.md\"), \"utf8\");\n } catch {\n return [];\n }\n const frontmatter = raw.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---/)?.[1];\n if (!frontmatter) return [];\n try {\n const formats = (parseYaml(frontmatter) as { formats?: unknown } | null)?.formats;\n return Array.isArray(formats) ? formats : [];\n } catch {\n return [];\n }\n}\n\nfunction toPosix(p: string): string {\n return p.split(path.sep).join(\"/\");\n}\n","/**\n * Jev's answers kept on disk, by the questions and the pinned model. Its probabilities drift by\n * a point between identical calls, so a decision near its threshold could flip from one run to\n * the next and change a prompt that was already paid for; kept, the same spec reads the same.\n */\nimport { createHash } from \"node:crypto\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport { JEV_MODEL, type JevAnswer, type JevQuestion } from \"./jev.ts\";\n\ntype Ask = (questions: readonly JevQuestion[]) => Promise<JevAnswer[] | null>;\n\nconst Kept = z.array(\n z.union([\n z.object({ choice: z.string(), probabilities: z.record(z.string(), z.number()), confidence: z.number() }),\n z.object({ noul: z.number() }),\n ]),\n);\n\n/** `ask`, its answers kept in `<cacheDir>/jev`; an answer that did not come back is never kept. */\nexport function cachedJev(cacheDir: string, ask: Ask): Ask {\n const dir = path.join(cacheDir, \"jev\");\n return async (questions) => {\n const key = createHash(\"sha256\")\n .update(JSON.stringify([JEV_MODEL, questions]))\n .digest(\"hex\");\n const file = path.join(dir, `${key}.json`);\n const kept = Kept.safeParse(\n await readFile(file, \"utf8\")\n .then(JSON.parse, () => null)\n .catch(() => null),\n );\n if (kept.success && kept.data.length === questions.length) return kept.data;\n const answers = await ask(questions);\n if (answers) {\n await mkdir(dir, { recursive: true });\n await writeFile(file, JSON.stringify(answers), \"utf8\");\n }\n return answers;\n };\n}\n","/**\n * Whether a free-text voice description asks for a woman's or a man's voice, so `voice_select`\n * can HARD-filter the cast: its soft scorer alone let a male voice win for a clearly female\n * creator. A description is written in any language (\"Marta, mujer de 40 años\", \"Frau, Mitte\n * 30\", \"若い女性\", \"Narradora cercana\"), so a text model reads it rather than a list of English\n * gender words, which never read the Spanish one and cast a Spanish woman from the English\n * stock voices.\n *\n * A text model, not Jev: this pulls a value out of the words, and the words often carry it in\n * grammar alone. Jev read \"Narradora cercana y cálida\" and \"Locutor profesional\" as not saying,\n * where Gemini Flash-Lite, pinned to one provider, read all 21 labelled descriptions in nine\n * languages right (scripts/ad-spec-reading-evals).\n *\n * Read once, when the canvas is scaffolded, kept in the workspace's cache and in the canvas's\n * rebuild context (`ScaffoldVideoOpts.voiceGenders`), so a rebuild never asks again. With no\n * answer, no description has a gender and the cast is ranked on the description alone.\n */\nimport { createHash } from \"node:crypto\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport { askAboutText, type ReviewUsage } from \"../../../nodes/local/lib/render-review.ts\";\n\nexport type VoiceGender = \"female\" | \"male\";\n\n/** The genders of `voices`, keyed by description, those that say; null when nothing could read them. */\nexport type ReadVoiceGenders = (voices: readonly string[]) => Promise<Record<string, VoiceGender> | null>;\n\n/**\n * Reads, does not judge: a fast model pinned to one provider and a seed, so a description reads the\n * same. Vertex takes no temperature for 3.5 Flash-Lite, and AI Studio, which does, fails the key's\n * zero-data-retention guardrail, so the seed pins the draw. Measured 2026-10-11 with\n * scripts/ad-spec-reading-evals: 21/21 genders (211/211 in all) on three runs, p50 about 0.55 s;\n * 2.5 Flash-Lite, which it replaces, also 21/21 at 0.43 s.\n */\nexport const VOICE_GENDER_MODEL = \"google/gemini-3.5-flash-lite\";\nconst PROMPT_VERSION = 1;\nconst REQUEST = {\n provider: { order: [\"google-vertex\"], allow_fallbacks: false },\n seed: 0,\n response_format: { type: \"json_object\" },\n};\nconst TIMEOUT_MS = 20_000;\n\n/** What the model is asked: every description at once, one answer each, in order. Pure. */\nexport function voiceGenderPrompt(voices: readonly string[]): string {\n return [\n \"Each line below describes the voice wanted for a speaker in an ad, written in any language.\",\n \"For each, say whether it asks for a woman's voice or a man's voice. Read it in its own language: a noun that is feminine or masculine by itself says so. Answer null when it does not say.\",\n \"\",\n ...voices.map((voice, i) => `${i + 1}. ${JSON.stringify(voice)}`),\n \"\",\n `Reply with only this JSON: {\"genders\": [\"female\" | \"male\" | null, ... one per line, ${voices.length} in order]}`,\n ].join(\"\\n\");\n}\n\nconst Answer = z.object({ genders: z.array(z.enum([\"female\", \"male\"]).nullable()) });\n\n/** The genders the answer gives, keyed by description; null for an answer of another shape or length. Pure. */\nexport function parseVoiceGenders(answer: unknown, voices: readonly string[]): Record<string, VoiceGender> | null {\n const parsed = Answer.safeParse(answer);\n if (!parsed.success || parsed.data.genders.length !== voices.length) return null;\n const out: Record<string, VoiceGender> = {};\n voices.forEach((voice, i) => {\n const gender = parsed.data.genders[i];\n if (gender) out[voice] = gender;\n });\n return out;\n}\n\n/** The real model, each set of descriptions read once and kept in `<cacheDir>/voice-gender`; spend to `onSpend`. */\nexport function voiceGenderModel(cacheDir: string, onSpend: (usage: ReviewUsage) => void): ReadVoiceGenders {\n const dir = path.join(cacheDir, \"voice-gender\");\n return async (voices) => {\n if (voices.length === 0) return {};\n const key = createHash(\"sha256\")\n .update(JSON.stringify([PROMPT_VERSION, VOICE_GENDER_MODEL, voices]))\n .digest(\"hex\");\n const file = path.join(dir, `${key}.json`);\n const kept = parseVoiceGenders(\n await readFile(file, \"utf8\")\n .then(JSON.parse, () => null)\n .catch(() => null),\n voices,\n );\n if (kept) return kept;\n const answer = await askAboutText(VOICE_GENDER_MODEL, voiceGenderPrompt(voices), onSpend, {\n timeoutMs: TIMEOUT_MS,\n request: REQUEST,\n }).catch(() => null);\n const genders = parseVoiceGenders(answer, voices);\n if (genders) {\n await mkdir(dir, { recursive: true });\n await writeFile(file, JSON.stringify(answer), \"utf8\");\n }\n return genders;\n };\n}\n","/**\n * Who appears in an ad and what of the product it shows, decided in the definition's thinking\n * before the canvas is written, from what the company really has. Production, Oct 2026: across\n * twelve chats the person was invented by the image model or an Avatar was picked by looks while\n * the company had real customers, a real ex-student and its founder on file; the product was\n * never shown (\"doesn't say what it is\"); the logo was drawn or missing. Each was patched in\n * later rounds, at 50 to 100 renders a chat. These lines are the decision, in a form a run reads.\n */\n\nexport const CAST_HEADING = \"Who appears and what we show\";\n\n/** The decisions, as written under their heading; absent when the line is missing. */\nexport type CastDecision = { cast?: string; product?: string; logo?: string };\n\n/** A cast: Avatars by handle, a real customer, real footage, or nobody. */\nconst CAST = /^(?:@[a-z][a-z0-9-]*(?:\\s*(?:,|and|y)\\s*@[a-z][a-z0-9-]*)*|customer\\s+\\S|footage\\s+\\S|nobody\\b)/i;\n/** The product as it really is: a library picture, a capture, a Hyperframe, footage, or none. */\nconst PRODUCT = /^(?:image\\s+\\S|screenshot\\s+\\S|hyperframe\\b|footage\\s+\\S|none\\b)/i;\n/** The logo: a file of the brand's own, or none. */\nconst LOGO = /^(?:\\S*src\\/brand\\/\\S+|none\\b)/i;\n\nconst DECISION_KEYS: Record<string, keyof CastDecision> = {\n Cast: \"cast\",\n Logo: \"logo\",\n};\n\n/** The decision lines under the heading `make` writes; null when the definition has no such section. Pure. */\nexport function castDecision(definition: string): CastDecision | null {\n const lines = definition.split(\"\\n\");\n const start = lines.findIndex((l) => l.trim() === `### ${CAST_HEADING}`);\n if (start === -1) return null;\n const decision: CastDecision = {};\n for (const line of lines.slice(start + 1)) {\n if (/^#{2,3}\\s/.test(line)) break;\n const m = /^-\\s*(Cast|Product shown|Logo):\\s*(.*)$/.exec(line.trim());\n if (!m?.[1]) continue;\n decision[DECISION_KEYS[m[1]] ?? \"product\"] = (m[2] ?? \"\").trim().replace(/^`|`$/g, \"\");\n }\n return decision;\n}\n\n/** The Avatar handles a cast names, in order. Pure. */\nexport const castHandles = (cast: string): string[] =>\n [...cast.matchAll(/@([a-z][a-z0-9-]*)/gi)].map((m) => (m[1] ?? \"\").toLowerCase());\n\n/** The Avatars prompt.json grounds its people on. Pure. */\nfunction groundedAvatars(spec: unknown): string[] {\n const references = (spec as { references?: unknown } | null)?.references;\n if (!Array.isArray(references)) return [];\n return references.flatMap((r) => {\n const avatar = (r as { avatar?: unknown } | null)?.avatar;\n return typeof avatar === \"string\" ? [avatar.toLowerCase()] : [];\n });\n}\n\n/**\n * A company rule that only real people appear (`check.people: real`), and the Avatars on its roster,\n * each real or made for a role (`avatarsOf`); null when the roster could not be read.\n */\nexport type RealPeopleOnly = {\n rule: { id: string; text: string; quote?: string };\n avatars: ReadonlyArray<{ handle: string; real: boolean }> | null;\n};\n\n/** Each Avatar of the cast made for a role, under a rule that only real people appear. Pure. */\nfunction roleAvatarProblems(cast: string, realOnly: RealPeopleOnly): string[] {\n const { rule, avatars } = realOnly;\n if (!avatars) return [];\n const quote = rule.quote ? ` (their words: \"${rule.quote}\")` : \"\";\n return castHandles(cast)\n .filter((handle) => avatars.some((a) => a.handle === handle && !a.real))\n .map(\n (handle) =>\n `@${handle} is an Avatar made for a role, and ${rule.id} says only real people appear: \"${rule.text}\"${quote}. Cast a real person's Avatar, a customer, footage or nobody.`,\n );\n}\n\n/** What the workspace holds of the brand's logo: whether a real file is registered, and the ids of the company's rules on the logo. */\nexport type LogoOnFile = { onFile: boolean; ruleIds: readonly string[] };\n\n/**\n * A \"Logo: none\" is refused for a standard ad (its brand shown as itself, not as a native\n * disguise's small sender mark) when the company's logo file is on file, unless the reason quotes\n * one of the company's rules on the logo. With no file on file there is nothing to refuse: the\n * scaffold already hinted where to add it. Pure.\n */\nfunction logoNoneProblems(logo: string, spec: unknown, held: LogoOnFile | undefined): string[] {\n if (!held?.onFile || !/^none\\b/i.test(logo)) return [];\n if ((spec as { brand_presence?: unknown } | null | undefined)?.brand_presence === \"native\") return [];\n const reason = logo.toLowerCase();\n if (held.ruleIds.some((id) => reason.includes(id.toLowerCase()))) return [];\n return [\n `\"Logo: ${logo}\" is not a decision of ours: the company's logo is on file under src/brand/logos/ and a standard ad shows it. Write the file instead, or quote the company rule that keeps the logo off this ad (its id).`,\n ];\n}\n\n/** The Avatars the company has, each with who it is to the company and the published words it gave. null when they could not be read. */\nexport type CastRoster = ReadonlyArray<{\n handle: string;\n relation: string;\n who: string;\n quotes: readonly string[];\n}> | null;\n\n/** Lowercase words of a text without accents or punctuation. Pure. */\nconst wordsOf = (text: string): string[] =>\n text\n .normalize(\"NFD\")\n .replace(/\\p{M}/gu, \"\")\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}]+/gu, \" \")\n .trim()\n .split(\" \")\n .filter(Boolean);\n\n/** The fewest words of a published quote the ad's copy must carry for the quote to be in it. */\nconst QUOTE_WORDS = 6;\n\n/** Whether the ad's copy carries a run of six or more words of one of the quotes (normalised). Pure. */\nfunction copyQuotes(spec: unknown, quotes: readonly string[]): boolean {\n const copy = (spec as { copy?: unknown } | null)?.copy;\n if (!Array.isArray(copy)) return false;\n const lines = copy.map((c) => ` ${wordsOf(String((c as { text?: unknown } | null)?.text ?? \"\")).join(\" \")} `);\n return quotes.some((quote) => {\n const words = wordsOf(quote);\n for (let i = 0; i + QUOTE_WORDS <= words.length; i++) {\n const run = ` ${words.slice(i, i + QUOTE_WORDS).join(\" \")} `;\n if (lines.some((line) => line.includes(run))) return true;\n }\n return false;\n });\n}\n\nconst CASTABLE_RELATIONS = [\"team\", \"founder\", \"role\"];\n\n/** Each Avatar cast who is a customer, a partner or unknown, unless the ad quotes their own published words. Pure. */\nfunction customerProblems(cast: string, spec: unknown, roster: NonNullable<CastRoster>): string[] {\n return castHandles(cast).flatMap((handle) => {\n const avatar = roster.find((a) => a.handle === handle);\n if (!avatar || CASTABLE_RELATIONS.includes(avatar.relation)) return [];\n if (copyQuotes(spec, avatar.quotes)) return [];\n const kind = avatar.relation === \"unknown\" ? \"customer\" : avatar.relation;\n return [\n `@${handle} is a ${kind} (${avatar.who}): a ${kind} appears only in a testimonial ad quoting their own published words. Cast a team or founder Avatar, one made for the role, or nobody.`,\n ];\n });\n}\n\n/** The company's policy on the decision: the logo, who may be cast, and a customer's face. Pure. */\nfunction policyProblems(\n decision: CastDecision,\n spec: unknown,\n realOnly: RealPeopleOnly | undefined,\n roster: CastRoster | undefined,\n logo: LogoOnFile | undefined,\n): string[] {\n const problems: string[] = [];\n if (decision.logo && LOGO.test(decision.logo)) problems.push(...logoNoneProblems(decision.logo, spec, logo));\n const cast = decision.cast && CAST.test(decision.cast) ? decision.cast : undefined;\n if (cast && realOnly) problems.push(...roleAvatarProblems(cast, realOnly));\n if (cast && roster && spec !== undefined) problems.push(...customerProblems(cast, spec, roster));\n return problems;\n}\n\n/**\n * What is wrong with the decision, one sentence each, naming the line; none when it is decided.\n * With the ad's spec, an Avatar cast must be the one its people are grounded on; under a rule that\n * only real people appear, never an Avatar made for a role. With the company's roster of a static,\n * a customer's, a partner's or an unknown person's Avatar only in an ad that quotes their own\n * published words; Pure.\n */\nexport function castProblems(\n definition: string,\n spec?: unknown,\n realOnly?: RealPeopleOnly,\n roster?: CastRoster,\n logo?: LogoOnFile,\n): string[] {\n const decision = castDecision(definition);\n if (!decision) return [];\n const problems: string[] = [];\n const check = (label: string, value: string | undefined, form: RegExp, forms: string) => {\n if (value === undefined) problems.push(`\"- ${label}:\" is missing: ${forms}.`);\n else if (!form.test(value)) problems.push(`\"${label}: ${value}\" is not a decision of ours: ${forms}.`);\n };\n check(\n \"Cast\",\n decision.cast,\n CAST,\n \"write @<avatar handle> (a real person's Avatar or one made for this role), customer <name> (a real customer with their own words), footage <video id>, or nobody, then why; a person the image model invents is never the cast\",\n );\n check(\n \"Product shown\",\n decision.product,\n PRODUCT,\n \"write image <library id or URL>, screenshot <url>, hyperframe <what it shows>, footage <video id>, or none, then why; the product is never drawn by the image model\",\n );\n check(\"Logo\", decision.logo, LOGO, \"write the brand's logo file under src/brand/, or none and why\");\n problems.push(...policyProblems(decision, spec, realOnly, roster, logo));\n if (spec !== undefined && decision.cast && CAST.test(decision.cast)) {\n const grounded = groundedAvatars(spec);\n const missing = castHandles(decision.cast).filter((h) => !grounded.includes(h));\n if (missing.length > 0) {\n problems.push(\n `The cast is ${missing.map((h) => `@${h}`).join(\", \")}, but prompt.json grounds no person on ${missing.length === 1 ? \"that Avatar\" : \"those Avatars\"}${grounded.length > 0 ? ` (it has @${grounded.join(\", @\")})` : \"\"}.`,\n );\n }\n }\n return problems;\n}\n","/**\n * The thinking a creative is made from: why its reference won, what of it can work for this\n * company's viewer, and what we will make. `baker creatives make` writes it into the creative's\n * `_definition.md` as an outline of open questions, and `baker canvas run` renders nothing while\n * one is still open: the definition comes first and prompt.json is written from it.\n * Production, Oct 2026: ads written straight into prompt.json copied a winner's surface (its\n * layout, its colours) and lost what made it win (the joke, the face people recognise).\n */\nimport {\n type AdLoadBearing,\n decisionOf,\n type KeepDecision,\n type LoadBearingJob,\n type MemeAudience,\n} from \"../../engine/scaffold/static-ad-spec.ts\";\nimport type { FitAnswer } from \"../winning-ads/fit.ts\";\nimport { CAST_HEADING } from \"./cast-decision.ts\";\nimport type { CastInventory } from \"./cast-inventory.ts\";\nimport type { Idea } from \"./ideas-model.ts\";\nimport type { Avoid, Take } from \"./reference-pick.ts\";\n\nexport const THINKING_HEADING = \"## Thinking\";\n\n/** What an open question starts with: the scaffold's own placeholder marker. */\nconst OPEN = \"[TODO\";\n\n/**\n * The proven ad: its id, why it was picked, the fit's read, its picture saved in the workspace when\n * it could be, and its static container (`lifestyle_photo`) when the library knows it.\n */\ntype ThinkingReference = {\n adId: string;\n why: string;\n fit?: FitAnswer;\n picture?: string;\n container?: string;\n /** Why the side-by-side look chose it over the other proven ads that fit. */\n preferred?: string;\n /** Every proven ad that fit, this one first, with its picture saved in the workspace when it could be. */\n board?: { adId: string; advertiser?: string; picture?: string }[];\n /** What the side-by-side look said our ad takes from which of them. */\n takes?: Take[];\n /** What it said our ad must not copy from them. */\n avoid?: Avoid[];\n};\n\nconst question = (text: string) => `${OPEN}: ${text}]`;\n\n/** What the check that picked the reference already read of why it won: a first read, never the answer. Pure. */\nfunction firstRead(reference: ThinkingReference): string {\n const layers = reference.fit?.why_it_wins ?? {};\n const read = [\n reference.why ? `- Picked because: ${reference.why}` : \"\",\n reference.preferred ? `- Chosen over the others because: ${reference.preferred}` : \"\",\n layers.disguise ? `- Looks like: ${layers.disguise}` : \"\",\n layers.attention ? `- Stops the scroll with: ${layers.attention}` : \"\",\n layers.trigger ? `- Triggers: ${layers.trigger}` : \"\",\n layers.voice ? `- Voice: ${layers.voice}` : \"\",\n layers.logic ? `- Convinces by: ${layers.logic}` : \"\",\n ...(reference.fit?.load_bearing ?? []).flatMap((l) =>\n l.job === \"stop\"\n ? [`- What stops the scroll: ${l.element}`]\n : l.job === \"proof\"\n ? [`- The proof: ${l.element}`]\n : [],\n ),\n reference.fit?.recognition ? `- Recognised as: ${reference.fit.recognition}` : \"\",\n reference.fit?.our_viewer\n ? `- Would our viewer stop: ${reference.fit.our_viewer.stops}${reference.fit.our_viewer.why ? `, ${reference.fit.our_viewer.why}` : \"\"}`\n : \"\",\n ].filter(Boolean);\n return read.length > 0 ? `First read, from the check that picked it:\\n\\n${read.join(\"\\n\")}\\n\\n` : \"\";\n}\n\n/** Where the agent looks at the reference itself: its picture, never only the check's words about it. Pure. */\nfunction lookFirst(reference: ThinkingReference): string {\n return reference.picture\n ? `Open ${reference.picture} and look at the picture itself, at full size, before you write a word: the read below is a summary and misses most of what stops a thumb. `\n : \"Download the picture the canvas's `original` node names into canvas/references/ and open it at full size before you write a word: the read below is a summary and misses most of what stops a thumb. \";\n}\n\n/** The format the plan settles: the idea's, or, when the proven ad's differs, which of the two. Pure. */\nfunction planFormat(format: string | undefined, reference: ThinkingReference | null): string {\n const theirs = reference?.container;\n if (!format) return theirs ? `the format (the proven ad's ${theirs.replace(/_/g, \" \")})` : \"the format\";\n if (!theirs || theirs === format) return `the format (${format})`;\n const words = (f: string) => f.replace(/_/g, \" \");\n return `the format (the proven ad is a ${words(theirs)}, the idea named a ${words(format)}: keep the proven ad's unless the idea's says the message better, and say which)`;\n}\n\n/** The order decision lines are asked in: what stops the scroll, the proof, the rest. */\nconst JOB_ORDER: readonly LoadBearingJob[] = [\"stop\", \"proof\", \"other\"];\n\n/** How a decision line names what an element does for the reference. */\nconst JOB_LABEL: Record<LoadBearingJob, string> = {\n stop: \"Stops the scroll\",\n proof: \"Proof\",\n other: \"Also carries it\",\n};\n\n/** What of ours may replace an element of the proven ad, as the thinking and the keep gate name it. */\nexport const REPLACE_WITH =\n \"a meme our buyer persona knows and relates to, from `baker images meme` with our words (what won is a meme the viewer relates to, not that meme: the proven ad's own template only when our persona knows it best; a two-panel reaction becomes two real templates, top and bottom), one of our team's, founder's or a made-for-a-role Avatars (never a customer: a customer's face appears only in a testimonial ad quoting their own published words; an Avatar pulling the same reaction only when the brand's voice does not run memes), the ✓/✗ marks in our colours\";\n\n/** The decision a line is asked for, as its placeholder says it. */\nconst DECIDE =\n 'keep, replace with <what of ours does the same job> or impossible: \"<the company rule that forbids it, word for word>\"';\n\n/** The check's read of one element, as a placeholder may quote it (no bracket closes it early). Pure. */\nfunction firstReadOf(l: AdLoadBearing): string {\n const decision = decisionOf(l);\n const ours = decision === \"replace\" && l.ours?.trim() ? ` with ${l.ours.trim()}` : \"\";\n const rule = l.rule?.trim() ? `, \"${l.rule.trim()}\"` : \"\";\n return `${decision}${ours}${rule}`.replace(/[[\\]]/g, \"\");\n}\n\n/**\n * One decision line per element the check said the reference cannot lose, what stops the scroll and\n * the proof first, each a placeholder with the check's first read, and how to decide them. Pure.\n */\nfunction loadBearing(reference: ThinkingReference): string {\n const elements = [...(reference.fit?.load_bearing ?? [])].sort(\n (a, b) => JOB_ORDER.indexOf(a.job ?? \"other\") - JOB_ORDER.indexOf(b.job ?? \"other\"),\n );\n if (elements.length === 0) return \"\";\n const lines = elements.map(\n (e) =>\n `- ${JOB_LABEL[e.job ?? \"other\"]}: ${e.element} — ${question(`${DECIDE}; the check's first read: ${firstReadOf(e)}`)}`,\n );\n return [\n `Decide what our ad does with each element the proven ad won on, one line each: keep it, replace it with something of ours that does the same job (named: ${REPLACE_WITH}), or impossible, quoting the company rule that forbids it. A rule forbids only what it names: \"no stock photography\" never rules out a meme's reaction face or our own people. What stops the scroll and the proof are never dropped: when one is impossible for us, this ad is built on another proven ad (\\`baker winning-ads fit <adId>\\` on the next candidates, then \\`baker creatives make <idea> --slug <new slug> --reference <adId>\\`), never a copy without it. Write each decision into prompt.json's \\`concept.load_bearing\\` (\\`decision\\`, \\`ours\\`, \\`rule\\`), the element's words unchanged.`,\n \"\",\n ...lines,\n \"\",\n \"\",\n ].join(\"\\n\");\n}\n\n/**\n * The proven ads that fit, side by side, and what the look said to take from which and not to copy:\n * a first read of the combination, the agent's to settle. Empty with one ad and no read. Pure.\n */\nfunction takeFromWhich(reference: ThinkingReference): string {\n const board = reference.board ?? [];\n if (board.length < 2 && !reference.takes?.length) return \"\";\n const ads = board.map(\n (b) =>\n `- ${b.adId}${b.advertiser ? ` (${b.advertiser})` : \"\"}: ${b.picture ?? \"its picture is in the library (baker winning-ads content)\"}`,\n );\n const takes = (reference.takes ?? []).map(\n (t) => `- ${t.element.replace(/_/g, \" \")}, from ${t.adId}: ${t.what}${t.applies ? ` (${t.applies})` : \"\"}`,\n );\n const avoid = (reference.avoid ?? []).map((a) => `- Not from ${a.adId}: ${a.what}${a.why ? ` (${a.why})` : \"\"}`);\n return [\n ads.length > 0 ? `The proven ads that fit, built on the first:\\n\\n${ads.join(\"\\n\")}\\n\\n` : \"\",\n takes.length + avoid.length > 0\n ? `First read, from the look that compared them:\\n\\n${[...takes, ...avoid].join(\"\\n\")}\\n\\n`\n : \"\",\n question(\n \"open every picture above and decide, element by element (the hook, the visual, who appears, the proof, the layout, the call to action), which ad's version stops our viewer and why it applies to them, or that ours comes from our own material (a real customer's words, our product, our team). One ad may give the whole idea, or the hook of one and the proof of another. Name what you leave, and never copy what misleads or the platform restricts (a fake news page, a fake notification), dated urgency, or another brand's marks.\",\n ),\n ].join(\"\");\n}\n\n/** What the company has to build with, as the agent chooses from it. Pure. */\nfunction inventoryText(inventory: CastInventory | undefined): string {\n if (!inventory) return \"\";\n const avatars = inventory.avatars.map((a) =>\n a.castable\n ? `- @${a.handle}: ${a.real ? \"a real person\" : \"made for a role\"}, ${a.who}`\n : `- @${a.handle}: a ${a.relation === \"unknown\" ? \"customer\" : a.relation} (${a.who}); only in an ad quoting their own published words, never as a reaction face or a model`,\n );\n const customers = inventory.customers.map(\n (c) => `- ${c.name ?? \"A customer\"} (${c.source}${c.photo ? \", with photo\" : \"\"}): \"${c.words}\"`,\n );\n const founder = `\\`baker avatars research \"the founder of ${inventory.company ?? \"<company>\"}\" --create\\` finds them and builds their Avatar from their own photos.`;\n return [\n \"What the company has:\\n\",\n `Avatars:\\n${avatars.length > 0 ? avatars.join(\"\\n\") : \"- none ready yet\"}\\n`,\n `Customers' own words closest to this message (check they say it):\\n${customers.length > 0 ? customers.join(\"\\n\") : \"- none found (`baker testimonials search` with other words)\"}\\n`,\n `The founder or the team: ${inventory.avatars.some((a) => a.real && a.castable) ? \"the real people above, or \" : \"\"}${founder}\\n`,\n `The product as it really looks: \\`baker images library \"<product>\"\\`, \\`baker videos search \"<product>\"\\`, a capture of the site or app (\\`baker images screenshot <url>\\`), or a Hyperframe of its interface.\\n`,\n `Logos: ${inventory.logos.length > 0 ? inventory.logos.join(\", \") : \"none registered (`baker images logo <domain>`)\"}\\n\\n`,\n ].join(\"\\n\");\n}\n\n/** A company rule on who appears, what shows or the logo, as the outline lists it. */\nexport type CastRule = { id: string; strength: string; text: string };\n\n/** The company's rules on who appears, what shows and its logo, and how a person's ask departs from one. Pure. */\nfunction rulesText(rules: readonly CastRule[]): string {\n if (rules.length === 0) return \"\";\n return [\n \"The company's rules on who appears, what shows and its logo (every finished ad is checked against them):\",\n ...rules.map((r) => `- [${r.strength}] ${r.id}: ${r.text}`),\n 'Only when the person asked this ad to depart from one, keep their ask and record it in prompt.json: \"waive\": [{\"rule\": \"<id>\", \"why\": \"<their ask>\"}].\\n\\n',\n ].join(\"\\n\");\n}\n\n/** Who appears and what of the product shows: the inventory, the rules, the question, and the three decision lines. Pure. */\nfunction castAndShow(inventory: CastInventory | undefined, rules: readonly CastRule[]): string {\n return `${inventoryText(inventory)}${rulesText(rules)}${question(\n \"who appears and what of the product shows, chosen from what the company has, for this viewer. A real customer with their own words, the founder or someone of the team (their real photos, as an Avatar), an Avatar made for this role whose identity (age, accent, life) fits the viewer and the company's rules as it is, or nobody but the product; a customer's Avatar appears only in a testimonial ad that quotes them. When the proven ad stops the scroll with a meme reaction and the brand's voice runs memes (the Memes line above), a real meme our buyer persona knows and relates to for that reaction (`baker images meme \\\"<meme name>\\\"`, not necessarily the proven ad's) is the face, our words on it, wired as a reference: never an Avatar or a redraw. Say why that face sells this message to this viewer and why the others would not. A person the image model invents, or an Avatar rewritten to fit, is never the cast: pick another or make one. Then the product as it really is, and the brand's real logo. When the Avatar to cast is not the one the canvas was built with, `baker creatives make <idea> --avatar <handle>` rebuilds it before you write prompt.json, keeping this thinking\",\n )}\n\n- Cast: ${question(\"@<avatar handle>, customer <name>, footage <video id>, or nobody; then why\")}\n- Product shown: ${question(\"image <library id or URL>, screenshot <url>, hyperframe <what>, footage <video id>, or none; then why\")}\n- Logo: ${question(\"the logo file under src/brand/ (none only when a company rule keeps the logo off this ad, or no file is on file; say which)\")}`;\n}\n\n/** Whether our brand's voice runs a meme, as a line of the thinking: the register and the voice line behind it. Pure. */\nfunction memesRecord(audience: MemeAudience | undefined): string {\n if (!audience) return \"\";\n const why = audience.why ? ` (${audience.why})` : \"\";\n return audience.memes === \"off_brand\"\n ? `- Memes: off brand for our voice${why}: no meme or reaction-face ad.\\n\\n`\n : `- Memes: our brand's voice runs them${why}; a real meme template (\\`baker images meme\\`) may do a meme's job.\\n\\n`;\n}\n\n/**\n * The outline `make` writes: one section per question, each an open question until answered.\n * Built on a proven ad, it starts from what that ad is and why it won; from an idea alone, from\n * why ours should work. Pure.\n */\nexport function thinkingOutline(input: {\n idea: Pick<Idea, \"message\" | \"who\" | \"angle\" | \"format\" | \"shows\">;\n reference: ThinkingReference | null;\n /** What the company has to cast and show, when it could be read. */\n inventory?: CastInventory;\n /** The company's rules on who appears, what shows and its logo, as they hold for this ad. */\n rules?: readonly CastRule[];\n /** Whether its voice runs memes, and the voice line that says so. */\n audience?: MemeAudience;\n}): string {\n const { idea, reference } = input;\n const sections: Array<[string, string]> = [[\"The moment in the feed\", feedMoment(idea, reference, input.audience)]];\n if (reference) {\n sections.push(\n [\n \"What the ad is\",\n question(\n `${lookFirst(reference)}Read .claude/skills/creative-canvas-ads/references/reading-a-winner.md, then describe proven ad ${reference.adId} as a viewer meets it in the feed, lever by lever: the photo (camera, lens, filter, grain, flash, light, framing), the person (who, face, expression, gaze, hair, body, clothes, how attractive or ordinary), the setting and props, the words and the type, the composition, the tone, and what it pretends to be (a meme, a screenshot, a post, an ad).`,\n ),\n ],\n [\n \"Why it won\",\n `${firstRead(reference)}${question(\n \"go past that read, lever by lever. Which pattern interrupt stopped the thumb in the first half-second: a face too close, a body, an attractive person, a look that is wrong for an ad (a filter, a flash photo, a fisheye selfie, a cheap screenshot) or too polished, an odd scale, a joke, a meme people know, a trend of right now? Which feeling did it hit: humour, desire, envy, fear, outrage, nostalgia, cuteness, being seen? What made them believe it, and what made them click? Name the one detail doing the work, then the two that support it, and say what stops the scroll and the proof that makes it believed, as they show in the picture. Keep apart what you can see, what the library measured, and what you suppose.\",\n )}`,\n ],\n );\n const combined = takeFromWhich(reference);\n if (combined) sections.push([\"What we take, from which ad\", combined]);\n }\n sections.push(\n [\n \"The hook, the angle and the call to action\",\n question(\n `our message is \"${idea.message}\". Write the hook ${reference ? \"the reference's hook becomes\" : \"that opens it\"} for us, in our customers' words, and say why it stops this viewer; give the two or three you weighed and why this one won. The angle (the idea says \"${idea.angle}\"${reference ? \"; say the one the reference wins on\" : \"\"}) and why it is right for this viewer at this stage. Then the call to action: what we ask, how big an ask it is for this viewer, what lowers the risk (an offer, a guarantee, a free step), and where and how it shows (a button, a line, a native ask, or none).`,\n ),\n ],\n [CAST_HEADING, castAndShow(input.inventory, input.rules ?? [])],\n );\n if (reference) {\n sections.push([\n \"What survives and what changes\",\n `${loadBearing(reference)}${question(\n \"the few details that, removed, would kill what made it win: keep those, carried by our own people, product and words. Everything that is the other company's (its words, logo, claims, people, products) changes. Say what each of ours replaces.\",\n )}`,\n ]);\n }\n sections.push([\n \"The plan\",\n question(\n `the ad we will make, as the viewer will see it: the scene, every line of copy, who is in it, ${planFormat(idea.format, reference)} and the sizes. Then write exactly this into prompt.json: the render reads prompt.json, not this page.`,\n ),\n ]);\n return [THINKING_HEADING, \"\", ...sections.flatMap(([title, body]) => [`### ${title}`, \"\", body, \"\"])].join(\"\\n\");\n}\n\n/**\n * The first question: the viewer scrolling, and what in the first second makes them stop, see\n * themselves and want more; then whether the proven ad shows that, or the bet's case without one.\n * Prod, Oct 2026: the definition opened on the reference, and ten of them argued for a picture\n * none of the ads needed. Pure.\n */\nfunction feedMoment(\n idea: Pick<Idea, \"message\" | \"who\" | \"shows\">,\n reference: ThinkingReference | null,\n audience: MemeAudience | undefined,\n): string {\n const viewer = idea.who.replace(/[-_]/g, \" \");\n const shows = idea.shows ? `What ours shows first: ${idea.shows}.\\n\\n` : \"\";\n const ask = `${viewer} is scrolling, not looking for an ad. In the first second ours must break their pattern (they stop), make them think \"this is for me\" (their problem, their words, someone like them) and make them want to know more. Say what of ours does each of the three${idea.shows ? \"\" : \", starting with what the picture shows\"}, and what would leave them scrolling.`;\n const tied = reference\n ? ` Then: does proven ad ${reference.adId} show that, or the same kind of picture doing the same job? If it does not, it is the wrong reference: find one that does (\\`baker winning-ads search \"<what ours shows>\"\\`) and rebuild on it (\\`baker creatives make <idea> --reference <adId>\\`) before answering anything below.`\n : \" No proven ad fits, so this is a bet: say why it should stop them and what would prove it wrong.\";\n return `${shows}${memesRecord(audience)}${question(`${ask}${tied}`)}`;\n}\n\n/** The definition with the outline appended to its body, unless it already holds its thinking. Pure. */\nexport function withThinking(definition: string, outline: string): string {\n if (definition.split(\"\\n\").some((line) => line.trim() === THINKING_HEADING)) return definition;\n return `${definition.trimEnd()}\\n\\n${outline.trimEnd()}\\n`;\n}\n\n/** One element's decision as \"What survives and what changes\" writes it: `open` while a question, `unclear` when it is no decision. */\nexport type SurvivalDecision = {\n job: LoadBearingJob;\n element: string;\n decision: KeepDecision | \"open\" | \"unclear\";\n /** What of ours replaces it, for `replace`. */\n ours?: string;\n /** The company rule that forbids it, for `impossible`. */\n rule?: string;\n /** What the line says in place of a decision, for `unclear`. */\n said?: string;\n};\n\nconst SURVIVES_HEADING = \"### What survives and what changes\";\nconst LABEL_JOB = new Map(\n Object.entries(JOB_LABEL).map(([job, label]) => [label.toLowerCase(), job as LoadBearingJob]),\n);\n/** A decision line: its label, the element, a dash, and what is decided. */\nconst DECISION_LINE = /^-\\s*(Stops the scroll|Proof|Also carries it)\\s*:\\s*(.+)$/i;\n/**\n * Where the element ends: the first dash, colon or full stop followed by a decision (or the open\n * question), else the first dash. Producers write \"<element>: replace with …\" and \"<element>. Kept\"\n * as often as the dash (prod, Oct 2026).\n */\nconst DECIDED = /^(.+?)(?:\\s+(?:—|–|--?)|\\s*[—–:.])\\s+((?:\\[TODO|(?:keep|keeps|kept|impossible)\\b|replace).*)$/i;\nconst DASHED = /^(.+?)\\s+(?:—|–|--?)\\s+(.*)$/;\n\n/** What a line decided, from the words after its dash. Pure. */\nfunction readDecision(said: string): Pick<SurvivalDecision, \"decision\" | \"ours\" | \"rule\" | \"said\"> {\n const text = said.trim();\n if (text.startsWith(OPEN)) return { decision: \"open\" };\n if (/^(?:keep|keeps|kept)\\b/i.test(text)) return { decision: \"keep\" };\n const replaced = /^replace[ds]?\\b(?:\\s+(?:it|them))?(?:\\s+(?:with|by)\\s+|\\s*:\\s*)(.+)$/i\n .exec(text)?.[1]\n ?.trim()\n .replace(/\\.$/, \"\");\n if (replaced) return { decision: \"replace\", ours: replaced };\n if (/^impossible\\b/i.test(text)) {\n const rest = text.replace(/^impossible\\b[\\s:—–-]*/i, \"\").trim();\n const quoted = /[\"“]([^\"”]+)[\"”]/.exec(rest)?.[1]?.trim();\n const rule = quoted ?? rest;\n return { decision: \"impossible\", ...(rule ? { rule } : {}) };\n }\n return { decision: \"unclear\", said: text };\n}\n\n/**\n * The decision lines under \"What survives and what changes\", in order: what our ad does with each\n * element the proven ad won on, as `make` asked for them. None in a definition made before. Pure.\n */\nexport function survivalDecisions(definition: string): SurvivalDecision[] {\n const lines = definition.split(\"\\n\");\n const start = lines.findIndex((l) => l.trim() === SURVIVES_HEADING);\n if (start === -1) return [];\n const out: SurvivalDecision[] = [];\n for (const line of lines.slice(start + 1)) {\n if (/^#{2,3}\\s/.test(line)) break;\n // A label set in bold (\"**Stops the scroll**:\") is the same line.\n const labelled = DECISION_LINE.exec(line.trim().replace(/\\*\\*|__/g, \"\"));\n const job = labelled?.[1] ? LABEL_JOB.get(labelled[1].toLowerCase()) : undefined;\n if (!labelled?.[2] || !job) continue;\n const decided = DECIDED.exec(labelled[2]) ?? DASHED.exec(labelled[2]);\n const element = (decided?.[1] ?? labelled[2]).trim();\n out.push({\n job,\n element,\n ...(decided?.[2] ? readDecision(decided[2]) : { decision: \"unclear\" as const, said: \"\" }),\n });\n }\n return out;\n}\n\n/** The thinking sections of a definition still holding an open question, by title, in order. Pure. */\nexport function unthoughtSections(definition: string): string[] {\n const start = definition.split(\"\\n\").findIndex((line) => line.trim() === THINKING_HEADING);\n if (start === -1) return [];\n const open: string[] = [];\n let title: string | null = null;\n for (const line of definition.split(\"\\n\").slice(start + 1)) {\n if (/^##\\s/.test(line)) break;\n const heading = /^###\\s+(.+?)\\s*$/.exec(line);\n if (heading?.[1]) title = heading[1];\n else if (title && line.includes(OPEN) && !open.includes(title)) open.push(title);\n }\n return open;\n}\n","/**\n * The idea of one creative, as the person saw it: what an edit keeps unless they asked to change it.\n *\n * Production, Oct 2026: follow-up rounds stripped an offer, swapped the reference without saying so,\n * changed a hook's promise, lost the layout that made the reference win, and re-laid out an ad whose\n * button was all that was asked for; the definition was read again in only 28 of 62 such rounds. So\n * the idea is read off the files that already hold it (`_definition.md`, `prompt.json`, a video's\n * `scenes/*.json` and canvas), never stored a second time, and a run compares it with the version the\n * person saw (`idea-gate.ts`). A change they asked for is one plain line under `## Changes`.\n */\nimport { readdir, readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { castDecision } from \"../../commands/creatives/cast-decision.ts\";\nimport { frontmatterOf } from \"../../commands/creatives/ideas-model.ts\";\nimport { languageTag } from \"../../language.ts\";\nimport { marketFromCompanyDoc } from \"../../viewer-profile.ts\";\nimport type { ConceptCarry } from \"../scaffold/static-ad-spec.ts\";\nimport { readAdWords } from \"./ad-words.ts\";\n\nexport type IdeaAnchor = {\n kind: \"static\" | \"video\";\n /** The one thing the ad tells the viewer: prompt.json's `message`, else the definition's. */\n message?: string;\n /** The language its words are in (a BCP-47 tag): the ad's own, else the company's. */\n language?: string;\n /** Who the ad is for: prompt.json's `viewer.who`, else the definition's `persona`. */\n viewer?: string;\n /** The market it is for: prompt.json's `viewer.market.country`. */\n market?: string;\n /** The reference it is built on and what of it we take; absent with no concept, or one rejected. */\n reference?: { adId?: string; carry: ConceptCarry; mustKeep: string[] };\n /** Why the reference won, layer by layer (`concept.why_it_wins`); absent with no reference. */\n whyItWon?: string;\n /** What survives of the reference: the first sentence under \"### What survives and what changes\". */\n survives?: string;\n /** A video: the accent its speech is in. */\n accent?: string;\n /** A video: every voice description it is cast from, sorted. */\n voices?: string[];\n /** A video: the voices already chosen (`voice_select` with a `voice_id`), sorted. */\n voiceIds?: string[];\n /** A video: how it is voiced (`on_camera`, `mixed`, `voiceover`, `none`). */\n route?: string;\n /** A video: who is in it (an Avatar's handle, else the cast's descriptions), sorted. */\n cast?: string[];\n /** An ad of a series: its lead owns the reference, what we take and what we keep. */\n seriesLead?: string;\n /** The lines under `## Changes` when this anchor was taken. */\n changes: string[];\n};\n\n/** The anchor with what a person reads beside it; display only, never stored. */\nexport type IdeaView = IdeaAnchor & {\n slug: string;\n why?: string;\n /** Who appears, as the definition decided it. */\n who?: string;\n advertiser?: string;\n};\n\nconst CARRY_LEVELS: readonly ConceptCarry[] = [\"whole_ad\", \"layout\", \"hook\", \"angle\"];\n\nconst text = (value: unknown): string | undefined =>\n typeof value === \"string\" && value.trim() ? value.trim().replace(/\\s+/g, \" \") : undefined;\n\nconst record = (value: unknown): Record<string, unknown> =>\n value !== null && typeof value === \"object\" && !Array.isArray(value) ? (value as Record<string, unknown>) : {};\n\nconst list = (value: unknown): unknown[] => (Array.isArray(value) ? value : []);\n\nconst sortedSet = (values: Array<string | undefined>): string[] =>\n [...new Set(values.filter((v): v is string => v !== undefined))].sort();\n\n/** The `- ` lines under `## Changes`, up to the next `## ` heading, as written. Pure. */\nexport function recordedChanges(definition: string): string[] {\n const lines = definition.split(\"\\n\");\n const start = lines.findIndex((l) => /^##\\s+Changes\\s*$/i.test(l.trim()));\n if (start === -1) return [];\n const out: string[] = [];\n for (const line of lines.slice(start + 1)) {\n if (/^##\\s/.test(line)) break;\n const item = /^\\s*[-*]\\s+(.*\\S)\\s*$/.exec(line)?.[1];\n if (item) out.push(item);\n }\n return out;\n}\n\n/** The layers of why a reference won, as `concept.why_it_wins` states them (\"attention: …; logic: …\"). Pure. */\nfunction whyItWonOf(spec: Record<string, unknown>): string | undefined {\n const wins = record(record(spec.concept).why_it_wins);\n const layers = [\"disguise\", \"voice\", \"trigger\", \"attention\", \"logic\"].flatMap((layer) => {\n const said = text(wins[layer]);\n return said ? [`${layer}: ${said}`] : [];\n });\n return layers.length > 0 ? layers.join(\"; \") : undefined;\n}\n\n/** Who the ad is for, its market, the reference it keeps, why that won and what survives of it. Pure. */\nfunction forWhomAndWhy(\n spec: Record<string, unknown>,\n fm: Record<string, unknown>,\n definition: string,\n video: boolean,\n): Pick<IdeaAnchor, \"viewer\" | \"market\" | \"reference\" | \"whyItWon\" | \"survives\"> {\n const viewer = (video ? undefined : text(record(spec.viewer).who)) ?? text(fm.persona);\n const market = video ? undefined : text(record(record(spec.viewer).market).country);\n const reference = video ? undefined : referenceOf(spec, fm);\n const whyItWon = reference ? whyItWonOf(spec) : undefined;\n const survives = firstSentenceUnder(definition, SURVIVES);\n return {\n ...(viewer ? { viewer } : {}),\n ...(market ? { market } : {}),\n ...(reference ? { reference } : {}),\n ...(whyItWon ? { whyItWon } : {}),\n ...(survives ? { survives } : {}),\n };\n}\n\n/**\n * One element the concept keeps, as the anchor holds it: what stops the scroll and the proof with what\n * of ours carries each, so an edit that swaps or drops what carries it changes the idea; any other\n * element by its words alone. Pure.\n */\nfunction keptElement(l: unknown): string[] {\n const held = record(l);\n const element = text(held.element);\n if (!element) return [];\n if (held.job !== \"stop\" && held.job !== \"proof\") return [element];\n const ours = text(held.ours);\n const kept = held.decision === \"keep\" || (held.decision === undefined && held.have === \"have\");\n if (kept) return [`${element}, kept as in the proven ad`];\n return [ours ? `${element}, carried by ${ours}` : element];\n}\n\n/** What a static's concept keeps of its reference; undefined with none or a rejected one. Pure. */\nfunction referenceOf(spec: Record<string, unknown>, fm: Record<string, unknown>): IdeaAnchor[\"reference\"] {\n const concept = record(spec.concept);\n if (!spec.concept || concept.verdict === \"reject\") return undefined;\n const carry = CARRY_LEVELS.find((level) => level === concept.carry) ?? \"whole_ad\";\n const adId = text(concept.reference_ad_id) ?? text(fm.sourceAdId);\n const mustKeep = list(concept.load_bearing).flatMap(keptElement);\n return { ...(adId ? { adId } : {}), carry, mustKeep };\n}\n\n/** A video's voice, accent, route and cast, from its blueprint (never the projected graph). Pure. */\nfunction videoVoice(\n spec: Record<string, unknown>,\n scenes: readonly unknown[],\n canvas: unknown,\n adSpec: unknown,\n): Pick<IdeaAnchor, \"accent\" | \"voices\" | \"voiceIds\" | \"route\" | \"cast\"> {\n const global = record(spec.global);\n const voiceover = record(global.voiceover);\n const allScenes = [...list(spec.scenes), ...scenes];\n const voices = sortedSet([\n text(voiceover.voice_description),\n ...allScenes.flatMap((s) => list(record(s).dialogue).map((d) => text(record(d).voice_description))),\n ]);\n const voiceIds = sortedSet(\n list(record(canvas).nodes)\n .map(record)\n .filter((n) => n.type === \"voice_select\")\n .map((n) => text(record(n.params).voice_id)),\n );\n const avatar = text(record(record(adSpec).cast).avatar);\n const cast = avatar ? [`@${avatar}`] : sortedSet(list(global.cast).map((c) => text(record(c).description)));\n const accent = text(voiceover.accent);\n const route = text(voiceover.mode);\n return {\n ...(accent ? { accent } : {}),\n ...(voices.length ? { voices } : {}),\n ...(voiceIds.length ? { voiceIds } : {}),\n ...(route ? { route } : {}),\n ...(cast.length ? { cast } : {}),\n };\n}\n\n/** Whether a prompt.json is a video's blueprint rather than a static's ad spec. Pure. */\nexport function isVideoBlueprint(spec: Record<string, unknown>): boolean {\n return typeof spec.schema !== \"string\" && (\"global\" in spec || \"scenes\" in spec);\n}\n\n/** The idea of one creative, from its definition, its prompt.json and (a video) its scenes and canvas. Pure. */\nexport function anchorOf(input: {\n definition: string;\n spec: unknown;\n scenes?: readonly unknown[];\n canvas?: unknown;\n adSpec?: unknown;\n adLanguage?: string;\n companyLanguage?: string;\n}): IdeaAnchor {\n const fm = frontmatterOf(input.definition) ?? {};\n const spec = record(input.spec);\n const video = fm.kind === \"video\" || (fm.kind !== \"static\" && isVideoBlueprint(spec));\n const message = (video ? undefined : text(spec.message)) ?? text(fm.message);\n const staticLanguage = video ? undefined : text(record(record(spec.viewer).market).language);\n const language = staticLanguage ?? text(fm.language) ?? text(input.adLanguage) ?? text(input.companyLanguage);\n const seriesLead = text(fm.series);\n return {\n kind: video ? \"video\" : \"static\",\n ...(message ? { message } : {}),\n ...(language ? { language } : {}),\n ...forWhomAndWhy(spec, fm, input.definition, video),\n ...(video ? videoVoice(spec, input.scenes ?? [], input.canvas, input.adSpec) : {}),\n ...(seriesLead ? { seriesLead } : {}),\n changes: recordedChanges(input.definition),\n };\n}\n\n/** The definition's section that says what survives of the reference. */\nconst SURVIVES = /^###\\s+What survives and what changes$/i;\n\nconst LINE_MAX = 160;\n\nconst clip = (line: string): string => (line.length <= LINE_MAX ? line : `${line.slice(0, LINE_MAX - 1).trimEnd()}…`);\n\n/** The first sentence under a `### <heading>`; undefined when the section is missing or empty. Pure. */\nfunction firstSentenceUnder(definition: string, heading: RegExp): string | undefined {\n const lines = definition.split(\"\\n\");\n const start = lines.findIndex((l) => heading.test(l.trim()));\n if (start === -1) return undefined;\n const body: string[] = [];\n for (const line of lines.slice(start + 1)) {\n if (/^#{2,3}\\s/.test(line)) break;\n if (line.trim()) body.push(line.trim());\n }\n const joined = body.join(\" \");\n return text(/^.*?[.!?](?=\\s|$)/.exec(joined)?.[0] ?? joined);\n}\n\n/** What a person reads beside the anchor: why it wins, who appears, what survives, whose ad it is. Pure. */\nexport function viewOf(slug: string, anchor: IdeaAnchor, definition: string, spec: unknown): IdeaView {\n const fm = frontmatterOf(definition) ?? {};\n const wins = record(record(record(spec).concept).why_it_wins);\n const why = [text(wins.attention), text(wins.logic)].filter(Boolean).join(\"; \");\n const who = text(castDecision(definition)?.cast);\n const survives = firstSentenceUnder(definition, SURVIVES);\n const advertiser = text(fm.sourceAdvertiser);\n return {\n ...anchor,\n slug,\n ...(why ? { why: clip(why) } : {}),\n ...(who ? { who } : {}),\n ...(survives ? { survives } : {}),\n ...(advertiser ? { advertiser } : {}),\n };\n}\n\nconst CARRY_WORDS: Record<ConceptCarry, string> = {\n whole_ad: \"the whole ad\",\n layout: \"its layout\",\n hook: \"its hook\",\n angle: \"its angle\",\n};\n\n/** Where the idea comes from: the series it belongs to, or the reference and what we take of it. */\nfunction referenceLine(view: IdeaView): string | undefined {\n if (view.seriesLead) return `An ad of the series led by ${view.seriesLead}: the lead owns its reference and layout`;\n const reference = view.reference;\n if (!reference) return undefined;\n const advertiser = view.advertiser ? `${view.advertiser}'s ad` : \"ad\";\n const whose = reference.adId ? `${advertiser} ${reference.adId}` : \"its reference ad\";\n const keep = reference.mustKeep.length ? `; must keep: ${reference.mustKeep.join(\", \")}` : \"\";\n return `Built on ${whose}, taking ${CARRY_WORDS[reference.carry]}${keep}`;\n}\n\n/** How a video is voiced, and by whom. */\nfunction voiceLine(view: IdeaView): string | undefined {\n if (view.kind !== \"video\" || !(view.voices?.length || view.route)) return undefined;\n const how = view.route ? ` ${view.route.replace(/_/g, \" \")}` : \"\";\n return `Voiced${how}${view.voices?.length ? ` by ${view.voices.join(\"; \")}` : \"\"}`;\n}\n\n/** The idea in at most six plain English lines of at most 160 characters each. Pure. */\nexport function anchorLines(view: IdeaView): string[] {\n const language = [view.language, view.accent ? `with ${view.accent}` : \"\"].filter(Boolean).join(\" \");\n const who = view.cast?.join(\", \") ?? view.who;\n const lines = [\n view.message ? `The message: \"${view.message}\"` : undefined,\n referenceLine(view),\n language ? `In ${language}` : undefined,\n voiceLine(view),\n who ? `Who appears: ${who}` : undefined,\n view.survives,\n ];\n return lines\n .filter((l): l is string => Boolean(l))\n .slice(0, 6)\n .map(clip);\n}\n\nconst json = (file: string): Promise<unknown> =>\n readFile(file, \"utf8\")\n .then((raw): unknown => JSON.parse(raw))\n .catch(() => null);\n\n/** The workspace a creative folder is in: the nearest folder above it with a package.json. */\nasync function workspaceOf(creativeDir: string): Promise<string | null> {\n let dir = path.resolve(creativeDir);\n for (let i = 0; i < 12; i++) {\n if ((await readFile(path.join(dir, \"package.json\"), \"utf8\").catch(() => null)) !== null) return dir;\n const parent = path.dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n return null;\n}\n\n/** The language COMPANY.md states (`Language: es-ES`), else the one the market it names speaks. Pure. */\nexport function companyLanguageOf(doc: string | null | undefined): string | undefined {\n const stated = /(?<![\\p{L}\\d])(?:language|idioma)\\s*:\\s*([a-z]{2,3}(?:-[a-z]{2})?)(?![\\p{L}\\d-])/iu.exec(\n doc ?? \"\",\n )?.[1];\n const tag = stated ? languageTag(stated) : null;\n return tag ?? marketFromCompanyDoc(doc)?.language;\n}\n\n/**\n * The idea of one creative folder as it stands on disk, and its view; null before prompt.json is\n * written. `opts.spec` reads it with another prompt.json in place of the folder's own (the one a\n * version shown elsewhere drew); `opts.recorded` likewise replaces the folder's scene files, canvas and\n * ad.spec.json with the ones that version recorded. Never throws.\n */\nexport async function readIdeaAnchor(\n creativeDir: string,\n opts: { spec?: unknown; recorded?: { scenes: readonly unknown[]; canvas: unknown; adSpec: unknown } } = {},\n): Promise<{ anchor: IdeaAnchor; view: IdeaView } | null> {\n try {\n const spec = opts.spec ?? (await json(path.join(creativeDir, \"prompt.json\")));\n if (!spec || typeof spec !== \"object\") return null;\n const slug = path.basename(creativeDir);\n const definition = await readFile(path.join(creativeDir, \"_definition.md\"), \"utf8\").catch(() => \"\");\n const sceneDir = path.join(creativeDir, \"scenes\");\n const sceneNames = opts.recorded\n ? []\n : (await readdir(sceneDir).catch(() => [] as string[])).filter((f) => f.endsWith(\".json\")).sort();\n const [scenes, canvas, adSpec, words, root] = await Promise.all([\n opts.recorded ? opts.recorded.scenes : Promise.all(sceneNames.map((f) => json(path.join(sceneDir, f)))),\n opts.recorded ? opts.recorded.canvas : json(path.join(creativeDir, `${slug}.canvas.json`)),\n opts.recorded ? opts.recorded.adSpec : json(path.join(creativeDir, \"ad.spec.json\")),\n readAdWords(creativeDir).catch(() => null),\n workspaceOf(path.dirname(creativeDir)),\n ]);\n const company = root ? await readFile(path.join(root, \"COMPANY.md\"), \"utf8\").catch(() => null) : null;\n const companyLanguage = companyLanguageOf(company);\n const anchor = anchorOf({\n definition,\n spec,\n scenes,\n canvas,\n adSpec,\n ...(words?.language ? { adLanguage: words.language } : {}),\n ...(companyLanguage ? { companyLanguage } : {}),\n });\n return { anchor, view: viewOf(slug, anchor, definition, spec) };\n } catch {\n return null;\n }\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { slimBlueprintForFrameStyle } from \"../../engine/scaffold/video.ts\";\n\n/**\n * Keep `prompt.style.json` a pure DERIVED artifact of `prompt.json`.\n *\n * Every scaffolded frame reads its shared ad spec via the `prompt_style` ingest —\n * NOT `prompt.json` directly (inlining all scenes into 28 frame prompts is pure\n * waste). The operator is told to edit `prompt.json`; without this sync those edits\n * never reach a single frame, because the projection was written once at scaffold\n * time and nothing regenerated it. Every canvas command's preflight (`prepareCanvas`)\n * calls `syncStyleProjection`, so the projection always reflects the blueprint before\n * anything bills.\n *\n * Cache semantics ride the `ingest` node's mtime:size key: a byte-identical\n * projection is NOT rewritten (no churn on scenes-only edits), and a real style\n * change re-keys the ingest → new asset sha → exactly the affected frames re-bill.\n */\nexport function findBlueprintProjection(canvas: unknown): { promptPath: string; stylePath: string } | null {\n if (!canvas || typeof canvas !== \"object\") return null;\n const nodes = (canvas as { nodes?: unknown }).nodes;\n if (!Array.isArray(nodes)) return null;\n const pathOf = (id: string): string | null => {\n const node = nodes.find((n) => (n as { id?: unknown })?.id === id) as\n | { type?: unknown; params?: { source?: unknown; path?: unknown; expect?: unknown } }\n | undefined;\n if (!node || node.type !== \"ingest\") return null;\n const p = node.params;\n if (p?.source !== \"path\" || p.expect !== \"json\" || typeof p.path !== \"string\" || p.path.includes(\"[TODO\")) {\n return null;\n }\n return p.path;\n };\n const promptPath = pathOf(\"prompt\");\n const stylePath = pathOf(\"prompt_style\");\n return promptPath && stylePath ? { promptPath, stylePath } : null;\n}\n\n/** prompt.json bytes → the slim projection's bytes, in the scaffold's exact format. */\nexport function renderStyleProjection(promptJsonRaw: string): string {\n return renderStyleProjectionFromValue(JSON.parse(promptJsonRaw));\n}\n\n/** The one formatter both the scaffold's initial write and the sync go through. */\nexport function renderStyleProjectionFromValue(blueprint: unknown): string {\n return `${JSON.stringify(slimBlueprintForFrameStyle(blueprint), null, 2)}\\n`;\n}\n\n/**\n * Re-derive prompt.style.json from prompt.json when their contents diverge. Call\n * AFTER `resolveRelativeCanvasPaths` (paths must be absolute). Throws when\n * prompt.json is unreadable or not valid JSON — the caller must fail BEFORE billing.\n */\nexport async function syncStyleProjection(\n canvas: unknown,\n log: (line: string) => void,\n): Promise<\"regenerated\" | \"up_to_date\" | \"not_applicable\"> {\n const pair = findBlueprintProjection(canvas);\n if (!pair) return \"not_applicable\";\n const rendered = renderStyleProjection(await readFile(pair.promptPath, \"utf8\"));\n const current = await readFile(pair.stylePath, \"utf8\").catch(() => null);\n if (current === rendered) return \"up_to_date\";\n await writeFile(pair.stylePath, rendered, \"utf8\");\n log(\n \"[style] prompt.style.json regenerated from prompt.json — every frame's shared ad spec changed; affected image frames will re-bill on the next run\",\n );\n return \"regenerated\";\n}\n","import { readdir, readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { type CanvasPathRewrite, findWorkspaceRoot, healCanvasPaths, normalizeCanvasPaths } from \"./normalize-paths.ts\";\nimport { unsuppliedPlaceholderAssets } from \"./placeholders.ts\";\nimport { interfaceWordsWriter } from \"./interface-words.ts\";\nimport { syncNativeGraph } from \"./native-projection.ts\";\nimport { backendDurableUrlFor, promoteCanvasOutputPaths } from \"./promote-canvas-outputs.ts\";\nimport { localPathParam, resolveRelativeCanvasPaths } from \"./resolve-paths.ts\";\nimport { type SceneSyncResult, syncSceneNodeParams } from \"./scene-projection.ts\";\nimport { claimModels, claimProblems, type RecordPart } from \"./claim-check.ts\";\nimport { computeSourceSha } from \"./source-version.ts\";\nimport { holdUnbilledSpend } from \"./unbilled-spend.ts\";\nimport {\n findBrandRoot,\n readStaticPromptJson,\n syncLogoPlacement,\n syncStaticAdBrief,\n syncStaticAdLogo,\n syncStaticAdReferences,\n} from \"./static-copy-projection.ts\";\nimport { nativeGateProblems } from \"../../engine/scaffold/native-surface.ts\";\nimport { adSpecErrorText, conceptProblems, readAdSpec, sceneWordProblems, unwrittenProblems } from \"../../engine/scaffold/static-ad-spec.ts\";\nimport type { ReviewUsage } from \"../../engine/nodes/local/lib/render-review.ts\";\nimport { askJevQuestions } from \"../../engine/nodes/local/lib/jev.ts\";\nimport { cachedJev } from \"../../engine/nodes/local/lib/jev-cache.ts\";\nimport { voiceGenderModel } from \"../../engine/scaffold/video/dialogue/voice-gender.ts\";\nimport { citedPlatforms, jevCitationJudge } from \"../../engine/scaffold/review-platforms.ts\";\nimport { badgeProblems, jevSignatureJudge, readSignatures, unattributedQuotes } from \"../../engine/scaffold/static-proof.ts\";\nimport { isStaticBriefCanvas } from \"../../engine/scaffold/static-render-briefs.ts\";\nimport { frontmatterOf, parseIdea, sourcesClaims } from \"../creatives/ideas-model.ts\";\nimport { readInsights } from \"../creatives/ideas-workspace.ts\";\nimport { storeProductReads } from \"../creatives/store-product.ts\";\nimport { CAST_HEADING, castDecision, castHandles, castProblems, type LogoOnFile } from \"../creatives/cast-decision.ts\";\nimport { liveCastRoster } from \"../creatives/cast-roster.ts\";\nimport { unthoughtSections } from \"../creatives/thinking.ts\";\nimport { heldRules, ruleGate } from \"./rule-gate.ts\";\nimport { readBrandLogoFiles } from \"../../engine/scaffold/static-brand.ts\";\nimport { type IdeaAnchor, readIdeaAnchor } from \"../../engine/creative-context/anchor.ts\";\nimport { ideaDrift, ideaRefusal, unrecordedDrift } from \"./idea-gate.ts\";\nimport { keepRefusal } from \"./keep-gate.ts\";\nimport { copyLanguageCheck } from \"./copy-language.ts\";\n\ntype SpecGate = {\n code: \"ad_not_written\" | \"scene_words_not_in_copy\" | \"concept_does_not_fit\" | \"proof_without_source\" | \"native_screen_invalid\";\n problems: string[];\n fix: string;\n};\n\n/**\n * What stops a static ad's prompt.json from rendering, all at once under the first category's\n * code: scene words the copy lacks, a concept that does not fit (C1), proof with no source (D3),\n * an invalid native screen. Nothing when it has no readable spec (the brief projection reports that).\n */\nasync function staticSpecGate(canvas: unknown, canvasDir: string): Promise<SpecGate | null> {\n let spec: ReturnType<typeof readAdSpec>;\n try {\n const json = await readStaticPromptJson(canvas);\n if (json === null) return null;\n spec = readAdSpec(json);\n } catch {\n return null;\n }\n const unwritten = unwrittenProblems(spec);\n if (unwritten.length > 0) {\n return {\n code: \"ad_not_written\",\n problems: unwritten,\n fix: \"Write the ad in prompt.json: the scene the viewer sees and each line of copy as it prints. Then re-run.\",\n };\n }\n // What stops the scroll and the proof of its proven ad, held in the thinking and prompt.json alike.\n const kept = keepRefusal(await readFile(path.join(canvasDir, \"_definition.md\"), \"utf8\").catch(() => \"\"), spec);\n const concept: SpecGate = {\n code: \"concept_does_not_fit\",\n problems: [...conceptProblems(spec), ...(kept?.problems ?? [])],\n fix: [\n ...(kept ? [kept.fix] : []),\n \"Edit prompt.json's `concept`: name what of ours carries each missing element (`ours`), or pick another reference with `baker winning-ads fit`. Never render a copy that has lost what the reference wins on.\",\n ].join(\" \"),\n };\n const root = (await findBrandRoot(canvasDir)) ?? findWorkspaceRoot(canvasDir) ?? canvasDir;\n const parts = await readRecordParts(root, canvasDir);\n const records = parts.map((p) => p.text).join(\"\\n\");\n const ours = (await readInsights(root)).filter(sourcesClaims);\n const cacheDir = path.join(findWorkspaceRoot(canvasDir) ?? root, \"canvas\", \".cache\");\n const spent: ReviewUsage[] = [];\n const claims = spec.native\n ? { problems: [], unheld: [] }\n : await claimProblems(\n spec.copy.map((l) => l.text),\n { parts },\n claimModels(cacheDir, (u) => spent.push(u)),\n );\n // Which review platform each line cites for its reviews, read in any language.\n const cited = spec.native\n ? new Map()\n : await citedPlatforms(\n spec.copy.map((l) => l.text),\n jevCitationJudge((u) => spent.push(u)),\n );\n // Which unclear dashes after a customer's words sign them, read before the paid render.\n const signatures = spec.native\n ? undefined\n : await readSignatures(spec, ours, jevSignatureJudge((u) => spent.push(u)));\n // A cent's worth of reading: billed with the workspace's next run, like a translation.\n await holdUnbilledSpend(cacheDir, spent);\n // Every problem in one refusal, each once: one at a time, a producer paid a refusal per problem.\n const gates: SpecGate[] = spec.native\n ? [\n concept,\n {\n // A native screen's people are photos it describes, briefed as ordinary people of the market.\n code: \"native_screen_invalid\",\n problems: nativeGateProblems(spec.native, records, spec.brand?.name),\n fix: \"Fix prompt.json's `native` block.\",\n },\n ]\n : [\n {\n // Words the scene asks for that the copy does not hold: refused here, free, rather than erased by a paid round.\n code: \"scene_words_not_in_copy\",\n problems: sceneWordProblems(spec),\n fix: \"Edit prompt.json: every word or figure the picture shows is a `copy` line (`in_scene`, with `on`); describe any other surface without words.\",\n },\n concept,\n {\n code: \"proof_without_source\",\n problems: [...badgeProblems(spec, cited), ...claims.problems, ...unattributedQuotes(spec, ours, signatures)],\n fix: proofFix(claims.unheld),\n },\n ];\n return oneRefusal(gates.filter((g) => g.problems.length > 0));\n}\n\n/**\n * The proof gate's fix, naming the claims to drop: an agent often reads only a refusal's last\n * lines. Only the company can say a claim is true, so the fix never invites the agent to write\n * one into the records: told to \"source it in the Knowledge\", one wrote it into COMPANY.md. Pure.\n */\nfunction proofFix(claims: readonly string[]): string {\n const named =\n claims.length > 0\n ? `drop ${claims.map((c) => `\"${c}\"`).join(\", \")} (a store product's price, was price or saving counts once the creative's idea names the product: \\`product: <handle>\\` in src/creatives/_ideas/<idea>.md; otherwise, if the user may know it is true, ask them, and record it in the Knowledge only once they confirm it, citing them), and `\n : \"\";\n return `In prompt.json, ${named}wire the badge or drop any other claim named above, everywhere it appears (copy and scene), and sign each customer quote named above with the name given. Never write a claim into the Knowledge or COMPANY.md yourself to pass this check.`;\n}\n\n/** Every refusal at once under the first one's code, each problem once; null when there is none. Pure. */\nfunction oneRefusal(gates: readonly SpecGate[]): SpecGate | null {\n const first = gates[0];\n if (!first) return null;\n return {\n code: first.code,\n problems: [...new Set(gates.flatMap((g) => g.problems))],\n fix: `${gates.map((g) => g.fix).join(\" \")} Then re-run.`,\n };\n}\n\n/**\n * The company's own records a figure must be in: COMPANY.md, every file of src/content but the\n * insights, the quotes of our own customers as written (a stranger's number is never ours), and the\n * store's record of the product the creative sells (`product` in its _definition.md). Never throws.\n */\nasync function readRecordParts(root: string, canvasDir: string): Promise<RecordPart[]> {\n const parts: RecordPart[] = [\n { source: \"COMPANY.md\", text: await readFile(path.join(root, \"COMPANY.md\"), \"utf8\").catch(() => \"\") },\n ];\n const content = path.join(root, \"src\", \"content\");\n const files = ((await readdir(content, { recursive: true }).catch(() => [])) as string[]).filter(\n // An insight may be a stranger's figure, and a creative rule is how ads are made: neither sources a claim.\n (f) => /\\.(md|mdx|json|ya?ml)$/.test(f) && !/^(?:insights|creative-rules)\\//.test(f.replace(/\\\\/g, \"/\")),\n );\n for (const file of files.slice(0, 400)) {\n parts.push({ source: file, text: await readFile(path.join(content, file), \"utf8\").catch(() => \"\") });\n }\n const quotes = (await readInsights(root)).filter(sourcesClaims).map((insight) => insight.quote);\n if (quotes.length > 0) parts.push({ source: \"customers' words\", text: quotes.join(\"\\n\") });\n const product = await ideaProduct(canvasDir);\n if (product) {\n const read = (await storeProductReads([product])).get(product);\n if (read && \"record\" in read) parts.push({ source: \"the store\", text: read.record });\n }\n return parts.filter((p) => p.text.trim());\n}\n\n/** The store product the creative's idea names (src/creatives/_ideas/<idea>.md `product`), if any. Never throws. */\nasync function ideaProduct(canvasDir: string): Promise<string | undefined> {\n const idea = frontmatterOf(await readFile(path.join(canvasDir, \"_definition.md\"), \"utf8\").catch(() => \"\"))?.idea;\n if (typeof idea !== \"string\" || !/^[\\w-]+$/.test(idea)) return undefined;\n const ideaFile = path.join(canvasDir, \"..\", \"_ideas\", `${idea}.md`);\n return parseIdea(idea, await readFile(ideaFile, \"utf8\").catch(() => \"\")).idea?.product;\n}\nimport { reroutedOnSpec, upgradeNote, upgradeStaticCanvas } from \"../../engine/scaffold/static-upgrade.ts\";\nimport { sizesFromDefinition } from \"./definition-sizes.ts\";\nimport type { CreativeRule } from \"../../engine/creative-rules/schema.ts\";\nimport { syncStyleProjection } from \"./style-projection.ts\";\n\n/**\n * The one preflight every canvas command runs: `validate`, `run`, `critique`,\n * `sync-definition` and `set-prompt` all see the same graph, and (all but the read-only\n * `sync-definition`) leave it in the file.\n *\n * A creative is edited in its blueprint (`prompt.json`, `scenes/sNN.json`), never in the\n * canvas, and several parts of the canvas are projections of it: each scene's frame and\n * clip prompts, a static ad's copy block and type specimen, and the derived style file\n * the frames ingest (`prompt.style.json`). Those projections used to be applied in memory\n * by some commands and not others, so the file on disk, the graph the dashboard drew, the\n * graph the critic scored and the graph that rendered were four different things. Here\n * they are applied once and WRITTEN BACK, so the canvas file says what renders.\n *\n * In order: parse, heal absolute and URL-in-path references (saved), resolve paths against\n * the canvas folder, run every projection, write the projected graph back (relative paths\n * kept, only when it changed), optionally refuse unfilled asset slots, then fingerprint the\n * projected graph.\n *\n * `gate: true` (run, validate) refuses a static ad its prompt.json cannot render honestly: a\n * concept that does not fit, a rating with no source, an invalid native screen.\n *\n * `write: false` is the read-only preview for `sync-definition`, which the file watcher runs\n * over EVERY creative on every edit: it returns the graph that would render (heal, scene and\n * copy projections applied in memory) and touches no file, so an edit to one creative never\n * rewrites another one's files. The derived style file is skipped there: it changes what a\n * frame reads, not the graph.\n */\nexport type PreparedCanvas = {\n /** The graph as it renders: projected, local paths resolved against the canvas folder. */\n canvas: unknown;\n /**\n * The same projected graph in the canvas file's own spelling (canvas-relative paths): what\n * the file says after a write, or would say with `write: false`. What the dashboard is sent.\n */\n fileGraph: unknown;\n /** The canvas file's text as it now stands on disk. */\n text: string;\n /**\n * Fingerprint of the editable source, taken over the projected graph (`fileGraph`), so a\n * read-only preview and a render of the same source agree (see `computeSourceSha`).\n */\n sourceSha: string | undefined;\n /** Whether the projected graph differed from the file and was written to it. */\n written: boolean;\n rewrites: CanvasPathRewrite[];\n projections: {\n style: \"regenerated\" | \"up_to_date\" | \"not_applicable\";\n staticCopy: \"regenerated\" | \"up_to_date\" | \"not_applicable\";\n scenes: SceneSyncResult;\n };\n /** What the projections said (regenerated files, structural drift), for the operator. */\n notes: string[];\n};\n\nexport type CanvasPrepareErrorCode = \"parse\" | \"sizes_disagree\" | \"definition_not_thought\" | \"cast_not_decided\" | \"rule_broken\" | \"style_projection\" | \"scene_projection\" | \"unsupplied_assets\" | \"ad_not_written\" | \"scene_words_not_in_copy\" | \"concept_does_not_fit\" | \"proof_without_source\" | \"native_screen_invalid\" | \"idea_changed\" | \"copy_language\";\n\n/** A preflight failure: nothing was billed, and the message says what to fix. */\nexport class CanvasPrepareError extends Error {\n readonly code: CanvasPrepareErrorCode;\n readonly fix: string | undefined;\n readonly details: Record<string, unknown> | undefined;\n constructor(code: CanvasPrepareErrorCode, message: string, opts: { fix?: string; details?: Record<string, unknown> } = {}) {\n super(message);\n this.name = \"CanvasPrepareError\";\n this.code = code;\n this.fix = opts.fix;\n this.details = opts.details;\n }\n\n /** The `{ ok: false, error }` envelope every canvas command prints for it. */\n toEnvelope(): { ok: false; error: Record<string, unknown> } {\n return {\n ok: false,\n error: { code: this.code, message: this.message, ...(this.fix ? { fix: this.fix } : {}), ...(this.details ?? {}) },\n };\n }\n}\n\nexport async function prepareCanvas(\n canvasPath: string,\n opts: {\n requireSuppliedAssets?: boolean;\n write?: boolean;\n gate?: boolean;\n log?: (line: string) => void;\n /** With `gate`: the idea the person saw (`shown-anchor.ts`); an edit that changes it unrecorded is refused. */\n baseline?: IdeaAnchor;\n /** With `gate`: no version of this creative was ever rendered, so its shape may still follow prompt.json (`reroutedOnSpec`). */\n firstRender?: boolean;\n } = {},\n): Promise<PreparedCanvas> {\n const filePath = path.resolve(canvasPath);\n const canvasDir = path.dirname(filePath);\n const notes: string[] = [];\n const log = (line: string) => {\n notes.push(line);\n opts.log?.(line);\n };\n\n const raw = await readFile(filePath, \"utf8\");\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (e) {\n throw new CanvasPrepareError(\"parse\", `${filePath}: JSON parse error: ${errorMessage(e)}`);\n }\n\n const write = opts.write !== false;\n const healed = write ? await healCanvasPaths(filePath, parsed) : healInMemory(filePath, parsed);\n let onDisk = healed.canvas;\n let text = healed.text ?? raw;\n const rewrites = [...healed.rewrites];\n if (write) {\n const workspaceRoot = findWorkspaceRoot(canvasDir);\n const promoted = workspaceRoot\n ? await promoteCanvasOutputPaths(onDisk, canvasDir, workspaceRoot, backendDurableUrlFor(log), log)\n : { canvas: onDisk, rewrites: [] };\n if (promoted.rewrites.length > 0) {\n onDisk = promoted.canvas;\n text = `${JSON.stringify(onDisk, null, 2)}\\n`;\n await writeFile(filePath, text, \"utf8\");\n rewrites.push(...promoted.rewrites);\n }\n }\n\n // Projections mutate nodes in place and path resolution shares untouched nodes with its\n // input, so they work on a copy: `onDisk` stays the file's own graph to diff against.\n // A static ad scaffolded before the one-picture graph is upgraded first, so everything below\n // (logo, briefs, fingerprint) sees the graph that will render.\n const upgrade = upgradeStaticCanvas(resolveRelativeCanvasPaths(structuredClone(onDisk), canvasDir));\n let canvas = upgrade.canvas;\n if (upgrade.upgraded) {\n log(upgradeNote(canvas));\n }\n // Where it runs decides its sizes: a definition naming another platform re-plans them before the run bills.\n if (opts.gate) {\n const sizes = await sizesFromDefinition(canvas, canvasDir);\n if (sizes.status === \"refused\") throw new CanvasPrepareError(\"sizes_disagree\", sizes.message, { fix: sizes.fix });\n if (sizes.status === \"replanned\") {\n canvas = sizes.canvas;\n log(sizes.note);\n }\n }\n // `make` routed the shape on the proven ad's drafted words; its first render routes on the ad written since.\n if (opts.gate && opts.firstRender && isStaticBriefCanvas(canvas)) {\n const spec = await readFile(path.join(canvasDir, \"prompt.json\"), \"utf8\")\n .then((t): unknown => JSON.parse(t))\n .catch(() => undefined);\n const routed = spec === undefined ? null : reroutedOnSpec(canvas, spec);\n if (routed?.rerouted) {\n canvas = routed.canvas;\n const reason = (canvas as { metadata?: { master_shape_reason?: unknown } }).metadata?.master_shape_reason;\n log(`[shape] the ad as written is ${String(reason)}`);\n }\n }\n\n // The company's rules this ad is held to, read once, only for a prepare that writes (a run, a\n // validate): the read-only preview the watcher runs over every creative never reads them.\n let held: Promise<CreativeRule[]> | undefined;\n const rulesForRun = (): Promise<CreativeRule[]> => {\n if (!write) return Promise.resolve([]);\n held ??= heldRules(canvasDir).then((h) => h.rules, () => []);\n return held;\n };\n let style: PreparedCanvas[\"projections\"][\"style\"] = \"not_applicable\";\n let staticCopy: PreparedCanvas[\"projections\"][\"staticCopy\"];\n try {\n if (write) style = await syncStyleProjection(canvas, log);\n // A native screen's graph is rebuilt from prompt.json first; the static projections leave it alone.\n // Its interface's words, in a language nobody checked, are written once and billed with the next run.\n const cacheDir = path.join(findWorkspaceRoot(canvasDir) ?? canvasDir, \"canvas\", \".cache\");\n const writing: ReviewUsage[] = [];\n const native = await syncNativeGraph(canvas, log, interfaceWordsWriter(cacheDir, (u) => writing.push(u)));\n await holdUnbilledSpend(cacheDir, writing);\n // The logo first: a dropped logo is unwired before the briefs are compiled without it.\n const logo = native === \"not_applicable\" ? await syncStaticAdLogo(canvas, log) : \"not_applicable\";\n // The logo kept is placed from its file on every size, never drawn by a model.\n const placed = native === \"not_applicable\" ? await syncLogoPlacement(canvas, log) : \"not_applicable\";\n const pictures = native === \"not_applicable\" ? await syncStaticAdReferences(canvas, log) : \"not_applicable\";\n // The company's rules reach the renders a run makes; the read-only preview, which the watcher runs over\n // every creative, never reads them (they are left out of the fingerprint either way).\n const rules = native === \"not_applicable\" && isStaticBriefCanvas(canvas) ? await rulesForRun() : [];\n staticCopy = native === \"not_applicable\" ? await syncStaticAdBrief(canvas, log, rules) : native;\n if (logo === \"regenerated\" || placed === \"regenerated\" || pictures === \"regenerated\") staticCopy = \"regenerated\";\n } catch (e) {\n throw new CanvasPrepareError(\"style_projection\", `prompt.json is not readable or not a valid ad:\\n${adSpecErrorText(e)}`, {\n fix: `Fix ${path.join(canvasDir, \"prompt.json\")} so it parses as JSON (and, for a static ad, matches the ad spec the message names), then re-run.`,\n });\n }\n // The definition is thought before the ad is written: refused, free, while it still asks a question.\n if (opts.gate) {\n const definition = await readFile(path.join(canvasDir, \"_definition.md\"), \"utf8\").catch(() => \"\");\n const open = unthoughtSections(definition);\n if (open.length > 0) {\n throw new CanvasPrepareError(\n \"definition_not_thought\",\n `_definition.md's thinking still has questions open: ${open.join(\", \")}. The thinking decides the ad, so it comes before the render.`,\n {\n fix: `Answer each open question in ${path.join(canvasDir, \"_definition.md\")} (replace its [TODO: …] with your answer, for this company and this viewer), then write prompt.json from \"The plan\" and re-run.`,\n },\n );\n }\n // A static grounds its people on prompt.json's references: the Avatar cast must be one of them.\n const spec = isStaticBriefCanvas(canvas)\n ? await readFile(path.join(canvasDir, \"prompt.json\"), \"utf8\").then(\n (text): unknown => JSON.parse(text),\n () => undefined,\n )\n : undefined;\n // The company's rules on the ad: its words, and who may appear.\n const rules = await ruleGate(canvasDir);\n // Who the cast is to the company, read free before any spend: a customer's face only in their own testimonial.\n const castNames = castHandles(castDecision(definition)?.cast ?? \"\");\n const roster = spec !== undefined && castNames.length > 0 ? await liveCastRoster(findWorkspaceRoot(canvasDir) ?? canvasDir, castNames) : null;\n const cast = castProblems(definition, spec, rules.realOnly ?? undefined, roster, await logoOnFile(canvasDir));\n if (cast.length > 0) {\n throw new CanvasPrepareError(\"cast_not_decided\", cast.join(\" \"), {\n fix: `Decide from what the company has, under \"${CAST_HEADING}\" in ${path.join(canvasDir, \"_definition.md\")}. An Avatar not yet in the ad: set the person's reference in prompt.json to \\`\"avatar\": \"<handle>\"\\` with its sheet as \\`image\\` (\\`baker avatars get <handle>\\`), or, before prompt.json is written, rebuild with \\`baker creatives make <idea> --avatar <handle>\\`.`,\n });\n }\n // The company's wording rules, on the ad's words: refused here, free, never found by a person after a render.\n if (rules.broken) throw new CanvasPrepareError(\"rule_broken\", rules.broken.problems.join(\" \"), { fix: rules.broken.fix });\n // An edit keeps the idea the person saw: a change of it nobody recorded under \"## Changes\" is refused.\n if (opts.baseline) {\n const now = (await readIdeaAnchor(canvasDir))?.anchor;\n const drift = now ? unrecordedDrift(ideaDrift(opts.baseline, now), opts.baseline, definition) : [];\n if (drift.length > 0) {\n const refusal = ideaRefusal(drift, canvasDir, new Date().toISOString().slice(0, 10));\n throw new CanvasPrepareError(\"idea_changed\", refusal.problems.join(\" \"), { fix: refusal.fix, details: { changed: drift } });\n }\n }\n // The ad's words are in the language its viewer reads: blocked when the reading is sure, else a warning.\n const languageCache = path.join(findWorkspaceRoot(canvasDir) ?? canvasDir, \"canvas\", \".cache\");\n const languageSpent: ReviewUsage[] = [];\n const language = await copyLanguageCheck(\n canvasDir,\n cachedJev(languageCache, (questions) => askJevQuestions(questions, (u) => languageSpent.push(u))),\n );\n await holdUnbilledSpend(languageCache, languageSpent).catch(() => undefined);\n if (language?.kind === \"block\") throw new CanvasPrepareError(\"copy_language\", language.message, { fix: language.fix });\n if (language) log(language.message);\n }\n // A concept that does not fit, a rating with no source: refused before anything bills.\n // Only a run or a validate asks (`gate`): critique and set-prompt are advisory, and the read-only\n // preview the dashboard is synced from never stops.\n const gate = opts.gate && isStaticBriefCanvas(canvas) ? await staticSpecGate(canvas, canvasDir) : null;\n if (gate) throw new CanvasPrepareError(gate.code, gate.problems.join(\" \"), { fix: gate.fix });\n let scenes: SceneSyncResult;\n try {\n // A creative scaffolded before its speech was read gets it read once here and kept in its\n // rebuild context; only a writing prepare asks, and its spend waits for the next run record.\n const speechCache = path.join(findWorkspaceRoot(canvasDir) ?? canvasDir, \"canvas\", \".cache\");\n const speechSpent: ReviewUsage[] = [];\n const readers = write\n ? {\n ask: cachedJev(speechCache, (questions) => askJevQuestions(questions, (u) => speechSpent.push(u))),\n genders: voiceGenderModel(speechCache, (u) => speechSpent.push(u)),\n }\n : undefined;\n // A run's frames are told the company's rules; the read-only preview never reads them.\n scenes = await syncSceneNodeParams(canvas, filePath, log, readers, await rulesForRun());\n await holdUnbilledSpend(speechCache, speechSpent).catch(() => undefined);\n } catch (e) {\n throw new CanvasPrepareError(\n \"scene_projection\",\n `a scenes/*.json file is not readable/valid or its rebuild failed: ${errorMessage(e)}`,\n { fix: `Fix the scene files in ${path.join(canvasDir, \"scenes\")} so each parses as JSON, then re-run.` },\n );\n }\n\n const projected = withFilePaths(canvas, onDisk, canvasDir);\n let written = false;\n if (write && projected !== null && JSON.stringify(projected) !== JSON.stringify(onDisk)) {\n text = `${JSON.stringify(projected, null, 2)}\\n`;\n await writeFile(filePath, text, \"utf8\");\n written = true;\n }\n\n if (opts.requireSuppliedAssets) {\n const pending = unsuppliedPlaceholderAssets(canvas);\n if (pending.length > 0) {\n throw new CanvasPrepareError(\n \"unsupplied_assets\",\n \"This canvas still has placeholder asset slots. Supply a real image (or video) at each before running.\",\n {\n fix: \"Each `el_*` ingest is a [TODO] you fill with the real logo, subject or product (a path relative to the canvas file), then re-run.\",\n details: { assets: pending },\n },\n );\n }\n }\n\n return {\n canvas,\n fileGraph: projected ?? onDisk,\n text,\n sourceSha: await computeSourceSha(filePath, { graph: projected ?? onDisk }),\n written,\n rewrites,\n projections: { style, staticCopy, scenes },\n notes,\n };\n}\n\n/** `healCanvasPaths` without the save: what the file would say once healed. */\nfunction healInMemory(filePath: string, canvas: unknown): { canvas: unknown; rewrites: CanvasPathRewrite[]; text: null } {\n const canvasDir = path.dirname(filePath);\n const workspaceRoot = findWorkspaceRoot(canvasDir);\n if (!workspaceRoot) return { canvas, rewrites: [], text: null };\n return { ...normalizeCanvasPaths(canvas, canvasDir, workspaceRoot), text: null };\n}\n\n/**\n * The projected graph in the file's own spelling: every local path param takes back the\n * value the file had for that node (relative, as the scaffold wrote it), so resolving\n * paths for this process never leaks absolute paths into the committed canvas. A node a\n * projection added (the brand's logo, wired from prompt.json) gets its path relative to the\n * canvas. Null when a node has no id to pair it by: such a canvas fails validation anyway and is\n * left alone.\n */\nfunction withFilePaths(projected: unknown, onDisk: unknown, canvasDir: string): unknown {\n const nodes = (projected as { nodes?: unknown } | null)?.nodes;\n const fileNodes = (onDisk as { nodes?: unknown } | null)?.nodes;\n if (!Array.isArray(nodes) || !Array.isArray(fileNodes)) return null;\n const byId = new Map<string, { params?: Record<string, unknown> }>();\n for (const node of fileNodes as Array<{ id?: unknown; params?: Record<string, unknown> }>) {\n if (typeof node?.id !== \"string\") return null;\n byId.set(node.id, node);\n }\n const out = structuredClone(projected) as { nodes: Array<{ id?: unknown; type?: unknown; params?: Record<string, unknown> }> };\n for (const node of out.nodes) {\n if (typeof node?.id !== \"string\") return null;\n const key = localPathParam(node);\n if (!key || !node.params || typeof node.params[key] !== \"string\") continue;\n const value = node.params[key] as string;\n const original = byId.get(node.id)?.params?.[key];\n // The file keeps its own spelling of a path that still names the same file; a path a\n // projection changed (a reference's new picture) is written relative to the canvas.\n if (typeof original === \"string\" && path.resolve(canvasDir, original) === path.resolve(canvasDir, value)) {\n node.params[key] = original;\n } else if (path.isAbsolute(value)) {\n const rel = path.relative(canvasDir, value).split(path.sep).join(\"/\");\n node.params[key] = rel.startsWith(\".\") ? rel : `./${rel}`;\n }\n }\n return out;\n}\n\n/**\n * Print a preflight failure the way every canvas command reports one and exit 2 (nothing\n * ran, nothing was billed). Anything that is not a preflight failure is rethrown.\n */\nexport function exitOnPrepareError(e: unknown): never {\n if (!(e instanceof CanvasPrepareError)) throw e;\n process.stderr.write(`${JSON.stringify(e.toEnvelope(), null, 2)}\\n`);\n process.exit(2);\n}\n\nfunction errorMessage(e: unknown): string {\n return e instanceof Error ? e.message : String(e);\n}\n\n/** Whether the company's logo is on file for the ad in `canvasDir`, and the ids of its rules on the logo. Never throws. */\nasync function logoOnFile(canvasDir: string): Promise<LogoOnFile> {\n const root = (await findBrandRoot(canvasDir)) ?? findWorkspaceRoot(canvasDir) ?? canvasDir;\n const [files, held] = await Promise.all([\n readBrandLogoFiles(root).catch(() => ({ logos: [] as string[] })),\n heldRules(canvasDir).catch(() => ({ rules: [] })),\n ]);\n return { onFile: files.logos.length > 0, ruleIds: held.rules.filter((r) => r.applies === \"logo\").map((r) => r.id) };\n}\n","/**\n * Scaffolds (e.g. `scaffold-video`, `scaffold-static-ad`) emit `ingest` nodes whose\n * path is a `[TODO: drop one real source image …]` placeholder — assets the operator\n * must supply before a billed run. Running with them unfilled used to fail deep in\n * the run with a cryptic `file_not_found` AFTER billing had started. This finds them\n * up front so `run` can refuse early with a clear, teaching message.\n */\nexport function unsuppliedPlaceholderAssets(canvas: unknown): Array<{ node: string; placeholder: string }> {\n const nodes = (canvas as { nodes?: unknown })?.nodes;\n if (!Array.isArray(nodes)) return [];\n const out: Array<{ node: string; placeholder: string }> = [];\n for (const n of nodes) {\n const node = n as { id?: unknown; type?: unknown; params?: { source?: unknown; path?: unknown } };\n if (node?.type !== \"ingest\") continue;\n const params = node.params;\n if (params?.source === \"path\" && typeof params.path === \"string\" && params.path.includes(\"[TODO\")) {\n out.push({ node: String(node.id ?? \"?\"), placeholder: params.path });\n }\n }\n return out;\n}\n","/**\n * The words a native screen's own interface prints (WhatsApp's \"Today\", Trustpilot's \"Verified\"),\n * written for a viewer's language that nobody checked against the apps (`native-surface.ts`\n * `needsInterfaceWords`): once per language by the text model the claim gate reads with, pinned to\n * one provider at temperature 0, and kept in the workspace's cache, so every ad in that language\n * prints the same words and the review expects exactly those. A writing that fails is null: the\n * screen speaks English, as it did.\n */\nimport { createHash } from \"node:crypto\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { askAboutText, type ReviewUsage } from \"../../engine/nodes/local/lib/render-review.ts\";\nimport {\n INTERFACE_WORDS_PROMPT_VERSION,\n interfaceWordsPrompt,\n readInterfaceWords,\n} from \"../../engine/scaffold/native-surface.ts\";\nimport { CLAIMS_MODEL, CLAIMS_REQUEST } from \"./claim-check.ts\";\nimport type { InterfaceWordsWriter } from \"./native-projection.ts\";\n\nconst WORDS_TIMEOUT_MS = 30_000;\n\n/** The real writer: each language written once and kept in `cacheDir`, the spend of every call made going to `spent`. */\nexport function interfaceWordsWriter(cacheDir: string, spent: (usage: ReviewUsage) => void): InterfaceWordsWriter {\n const dir = path.join(cacheDir, \"interface-words\");\n return async (language) => {\n const tag = language.trim().toLowerCase();\n const key = createHash(\"sha256\")\n .update(JSON.stringify([INTERFACE_WORDS_PROMPT_VERSION, CLAIMS_MODEL, tag]))\n .digest(\"hex\");\n const file = path.join(dir, `${key}.json`);\n const cached = await readFile(file, \"utf8\")\n .then((text) => readInterfaceWords(JSON.parse(text)))\n .catch(() => null);\n if (cached) return cached;\n const words = readInterfaceWords(\n await askAboutText(CLAIMS_MODEL, interfaceWordsPrompt(language), spent, {\n timeoutMs: WORDS_TIMEOUT_MS,\n request: CLAIMS_REQUEST,\n }),\n );\n if (words) {\n await mkdir(dir, { recursive: true });\n await writeFile(file, JSON.stringify(words), \"utf8\");\n }\n return words;\n };\n}\n","/**\n * The claim gate: every claim an ad's copy makes is one the company's records make too, before\n * anything renders. Language is the models' job and equality is code's (`ad-claims.ts`):\n *\n * 1. A text model lists the copy's claims, each as a kind, a number and a unit, in whatever\n * language or languages the ad is written in. A claim the records write in its own words is\n * held (`recordsSay`): two readings of the same words may not agree. An ad with none left is done here.\n * 2. The same model lists the records' claims, in batches, each cached by its text, so a\n * workspace reads its records once until they change.\n * 3. Code holds a figure by a record of the same kind, number and unit.\n * 4. A claim to be the best or the only one is held when the decision model (Jev) says a record\n * makes the same claim: there is no number to compare.\n *\n * When a model cannot answer, the gate degrades and never refuses on a guess: with no reading of\n * the copy, every number it writes in digits must be in the records; with no reading of the\n * records, a figure's number must be; with no judgment, a superlative passes. Measured on\n * 2026-10-07 (scripts/claim-check-evals): see docs/decision-model.md.\n */\nimport { createHash } from \"node:crypto\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport {\n CLAIMS_PROMPT_VERSION,\n type Claim,\n claimsPrompt,\n digitsWithoutSource,\n heldBy,\n parseClaims,\n recordsSay,\n recordsWrite,\n} from \"../../engine/scaffold/ad-claims.ts\";\nimport { askJev } from \"../../engine/nodes/local/lib/jev.ts\";\nimport { askAboutText, type ReviewUsage } from \"../../engine/nodes/local/lib/render-review.ts\";\n\n/**\n * Reads claims, it does not judge them: a fast model, pinned to one provider and a seed so the\n * same text reads the same (Vertex takes no temperature for 3.5 Flash-Lite, and AI Studio, which\n * does, fails the key's zero-data-retention guardrail). Asked to judge whether a record held a\n * claim, Flash-Lite held \"zwei Tagen\" by \"one day\", which is why it only extracts\n * (docs/decision-model.md § Where it fits in this repo). Measured 2026-10-11: claim-check-evals\n * 20/20 and named-people-evals 24/24 on three runs each, p50 about 0.65 s, once the prompts asked\n * for a claim's whole phrase and one entry per person.\n */\nexport const CLAIMS_MODEL = \"google/gemini-3.5-flash-lite\";\nexport const CLAIMS_REQUEST = {\n provider: { order: [\"google-vertex\"], allow_fallbacks: false },\n seed: 0,\n response_format: { type: \"json_object\" },\n};\nconst CLAIMS_TIMEOUT_MS = 30_000;\n/** At or above this, Jev says a record makes the superlative's claim. Measured: held 0.90–0.96, not held 0.22 or less. */\nexport const SUPERLATIVE_HELD = 0.7;\n/** About 10k tokens of records per reading: small enough that none of its claims is missed. */\nconst RECORDS_BATCH_CHARS = 40_000;\n\nexport type RecordPart = { source: string; text: string };\n\nexport type ClaimModels = {\n /** The claims of `text`, or null when no model could read it. */\n extract: (what: \"ad\" | \"records\", text: string) => Promise<Claim[] | null>;\n /** For each pair, the probability the record makes the claim's claim; null when no judgment came back. */\n judge: (pairs: ReadonlyArray<{ claim: string; record: string }>) => Promise<number[] | null>;\n};\n\n/** A line longer than a reading is read in chunks this much apart less than a reading, so a figure on a cut is whole in one. */\nconst CHUNK_OVERLAP = 200;\n\n/** `pieces` joined with `joiner` into as few runs of at most `RECORDS_BATCH_CHARS` as their order allows. Pure. */\nfunction pack(pieces: readonly string[], joiner: string): string[] {\n const runs: string[] = [];\n let run = \"\";\n for (const piece of pieces) {\n if (run && run.length + joiner.length + piece.length > RECORDS_BATCH_CHARS) {\n runs.push(run);\n run = \"\";\n }\n run = run ? `${run}${joiner}${piece}` : piece;\n }\n return run ? [...runs, run] : runs;\n}\n\n/**\n * `text` in pieces of at most `RECORDS_BATCH_CHARS`, none of it left out: split at its paragraphs, a paragraph\n * still too long at its lines (pretty-printed JSON has no blank line), and a line still too long in overlapping chunks.\n */\nfunction withinReading(text: string, cuts: ReadonlyArray<{ at: RegExp; joiner: string }>): string[] {\n if (text.length <= RECORDS_BATCH_CHARS) return [text];\n const [cut, ...finer] = cuts;\n if (!cut) {\n const chunks: string[] = [];\n for (let at = 0; at < text.length; at += RECORDS_BATCH_CHARS - CHUNK_OVERLAP) {\n chunks.push(text.slice(at, at + RECORDS_BATCH_CHARS));\n if (at + RECORDS_BATCH_CHARS >= text.length) break;\n }\n return chunks;\n }\n return pack(\n text.split(cut.at).flatMap((piece) => withinReading(piece, finer)),\n cut.joiner,\n );\n}\n\nconst CUTS = [\n { at: /\\n\\s*\\n/, joiner: \"\\n\\n\" },\n { at: /\\n/, joiner: \"\\n\" },\n];\n\n/**\n * `text` with each line that says something read once: a line written word for word again (the\n * `\"rating\": 5` of every review) holds no claim the first did not, and a reader asked to list\n * every claim lists it each time, past any answer. Pure.\n */\nfunction saidOnce(text: string): string {\n const seen = new Set<string>();\n return text\n .split(\"\\n\")\n .filter((line) => {\n const said = line.trim();\n if (!/[\\p{L}\\p{N}]/u.test(said)) return true;\n if (seen.has(said)) return false;\n seen.add(said);\n return true;\n })\n .join(\"\\n\");\n}\n\n/** The records in readings of at most `RECORDS_BATCH_CHARS`, in their order, a long part split at its paragraphs. Pure. */\nexport function recordBatches(parts: readonly RecordPart[]): string[] {\n const pieces = parts.flatMap((part) => withinReading(saidOnce(part.text), CUTS));\n return pack(\n pieces.filter((p) => p.trim()),\n \"\\n\\n\",\n );\n}\n\nconst RECORDS_SAY = \"the company's records (src/content, COMPANY.md, its customers' words) do not hold\";\n\n/** The line a claim was read from: the one that holds its words, else the first. */\nfunction lineOf(claim: string, lines: readonly string[]): string {\n const words = claim.toLocaleLowerCase();\n return lines.find((l) => l.toLocaleLowerCase().includes(words)) ?? lines[0] ?? claim;\n}\n\nfunction problemsFor(unheld: readonly string[], lines: readonly string[]): string[] {\n const byLine = new Map<string, string[]>();\n for (const claim of unheld) {\n const line = lineOf(claim, lines);\n byLine.set(line, [...(byLine.get(line) ?? []), claim]);\n }\n return [...byLine].map(([line, claims]) => {\n const named = claims.map((c) => `\"${c}\"`).join(\", \");\n const where = claims.length === 1 && claims[0]?.trim() === line.trim() ? named : `${named} in \"${line}\"`;\n return `${where}: ${RECORDS_SAY} it, so the line promises what nobody wrote. Say only what they record, or drop ${claims.length === 1 ? \"it\" : \"them\"}.`;\n });\n}\n\n/** The claims of `lines` the records do not make, and the refusal's lines for them. Never throws. */\nexport async function claimProblems(\n lines: readonly string[],\n records: { parts: readonly RecordPart[] },\n models: ClaimModels,\n): Promise<{ problems: string[]; unheld: string[] }> {\n const said = lines.filter((l) => l.trim());\n if (said.length === 0) return { problems: [], unheld: [] };\n const text = records.parts.map((p) => p.text).join(\"\\n\\n\");\n const read = await models.extract(\"ad\", said.join(\"\\n\"));\n if (read === null) {\n const unheld = digitsWithoutSource(said, text);\n return { problems: problemsFor(unheld, said), unheld };\n }\n // A claim the records write in the same words is held before any reading is compared.\n const claims = read.filter((c) => !recordsSay(text, c.text));\n if (claims.length === 0) return { problems: [], unheld: [] };\n\n const readings = await Promise.all(recordBatches(records.parts).map((batch) => models.extract(\"records\", batch)));\n const facts = readings.every((r) => r !== null) ? readings.flat() : null;\n const figures = claims.filter((c) => c.kind !== \"superlative\");\n const unheldFigures = figures.filter((c) =>\n facts\n ? !heldBy(c, facts)\n : // No reading of the records: its number, written anywhere in them.\n c.value === null || !recordsWrite(text, String(c.value)),\n );\n\n const superlatives = claims.filter((c) => c.kind === \"superlative\");\n const recorded = (facts ?? []).filter((f) => f.kind === \"superlative\");\n let unheldSuperlatives: Claim[] = [];\n if (superlatives.length > 0 && facts !== null) {\n if (recorded.length === 0) {\n unheldSuperlatives = superlatives;\n } else {\n const pairs = superlatives.flatMap((c) =>\n recorded.map((r) => ({ claim: c.text, record: r.about ? `${r.about}: ${r.text}` : r.text })),\n );\n const judged = await models.judge(pairs);\n if (judged !== null) {\n unheldSuperlatives = superlatives.filter(\n (_, i) => !recorded.some((_, j) => (judged[i * recorded.length + j] ?? 0) >= SUPERLATIVE_HELD),\n );\n }\n }\n }\n const unheld = [...new Set([...unheldFigures, ...unheldSuperlatives].map((c) => c.text))];\n return { problems: problemsFor(unheld, said), unheld };\n}\n\nconst JUDGE_QUESTION =\n \"Does `record` state the claim `claim` makes: the same claim, about the same thing, for the same place or group, in whatever language either is written? A broader claim (a bigger place, best instead of only) is not the same claim.\";\n\n/**\n * The real models: each text's claims read once and kept in `cacheDir` by the text, the model\n * and the prompt, so the same copy and the same records read the same on every run; the spend of\n * every call made goes to `spent`.\n */\nexport function claimModels(cacheDir: string, spent: (usage: ReviewUsage) => void): ClaimModels {\n const dir = path.join(cacheDir, \"claims\");\n return {\n async extract(what, text) {\n const key = createHash(\"sha256\")\n .update(JSON.stringify([CLAIMS_PROMPT_VERSION, CLAIMS_MODEL, what, text]))\n .digest(\"hex\");\n const file = path.join(dir, `${key}.json`);\n const cached = parseClaims(await readFile(file, \"utf8\").then(JSON.parse, () => null).catch(() => null));\n if (cached) return cached;\n const answer = await askAboutText(CLAIMS_MODEL, claimsPrompt(what, text), spent, {\n timeoutMs: CLAIMS_TIMEOUT_MS,\n request: CLAIMS_REQUEST,\n });\n const claims = parseClaims(answer);\n if (claims) {\n await mkdir(dir, { recursive: true });\n await writeFile(file, JSON.stringify({ claims }), \"utf8\");\n }\n return claims;\n },\n judge: (pairs) =>\n askJev(\n pairs.map((p) => ({ instructions: { claim: p.claim, record: p.record, question: JUDGE_QUESTION } })),\n spent,\n ),\n };\n}\n","/**\n * What an ad promises, and whether the company's records promise the same. A model reads the\n * words, in any language or several in one ad (\"en un día\", \"in zwei Tagen\", \"9日で\"), and gives\n * each claim as a kind, a number and a unit; code then compares those exactly, so no list of\n * words decides what a claim is, and no model decides whether two numbers are equal. A claim to\n * be the best or the only one has no number to compare: the decision model judges it\n * (`claim-check.ts`). Pure.\n */\nimport { z } from \"zod\";\nimport { figureForms } from \"./review-platforms.ts\";\n\nexport const CLAIM_KINDS = [\"price\", \"percent\", \"multiple\", \"duration\", \"count\", \"rating\", \"superlative\"] as const;\nconst DURATION_UNITS = [\"minute\", \"hour\", \"day\", \"week\", \"month\", \"year\"] as const;\n\nexport const Claim = z.object({\n /** The claim as it is written, in its own language. */\n text: z.string().min(1),\n kind: z.enum(CLAIM_KINDS),\n /** The number it states, as a number; null for a superlative. */\n value: z.number().nullable().catch(null),\n /** A duration's unit, a price's ISO currency, what a count or rating counts (in English); else null. */\n unit: z.string().nullable().catch(null),\n /** What it is about, in a few English words: what the decision model compares a superlative on. */\n about: z.string().catch(\"\"),\n});\nexport type Claim = z.infer<typeof Claim>;\n\nconst Answer = z.object({ claims: z.array(z.unknown()) });\n\n/** Bump when the prompt changes what a claim is: cached answers of the old prompt are not reused. */\nexport const CLAIMS_PROMPT_VERSION = 2;\n\n/** What the model is asked about `text` (an ad's copy, or a part of the records): every claim, normalised. Pure. */\nexport function claimsPrompt(what: \"ad\" | \"records\", text: string): string {\n const label = what === \"ad\" ? \"the copy of an ad, one line per line\" : \"a part of a company's own records\";\n return [\n `Below is ${label}, in any language or several. List every claim in it: a specific price, percentage, multiple, duration, count or rating (written in digits or in words), or a claim to be the best, the only, the first, the fastest, number one or a leader. Plain words with no number and no such claim are not claims: \"Get a quote\" and \"free\" are not.`,\n \"\",\n \"For each claim give:\",\n '- \"text\": the whole claim exactly as written there, with what it is about: \"the only bakery in Leeds open on Sundays\", \"entrega en tres días\", never a lone word such as \"only\" or \"tres\"',\n `- \"kind\": ${CLAIM_KINDS.join(\" | \")}`,\n '- \"value\": the number as a plain number (one day → 1, \"4,8\" → 4.8, \"1.200 reviews\" → 1200, half the bill → kind percent, 50), or null for a superlative',\n `- \"unit\": for a duration one of ${DURATION_UNITS.join(\" | \")}; for a price its ISO currency; for a count or rating what is counted or rated, in English (reviews, stars, homes); else null`,\n '- \"about\": what the claim is about, in a few English words (install time, warranty, bill savings, Trustpilot rating, battery recycling in Valencia)',\n \"\",\n \"Text:\",\n '\"\"\"',\n text,\n '\"\"\"',\n \"\",\n 'Reply with only this JSON: {\"claims\": [{\"text\": \"…\", \"kind\": \"…\", \"value\": …, \"unit\": …, \"about\": \"…\"}]}',\n ].join(\"\\n\");\n}\n\n/** The claims of a model's answer, each one it gave in the shape asked; null when the answer is not that shape at all. Pure. */\nexport function parseClaims(answer: unknown): Claim[] | null {\n const parsed = Answer.safeParse(answer);\n if (!parsed.success) return null;\n return parsed.data.claims.flatMap((c) => {\n const claim = Claim.safeParse(c);\n return claim.success ? [claim.data] : [];\n });\n}\n\nconst singular = (unit: string | null) => (unit ?? \"\").trim().toLowerCase().replace(/s$/, \"\");\n\nfunction sameNumber(a: number | null, b: number | null): boolean {\n return a !== null && b !== null && Math.abs(a - b) <= 1e-9 * Math.max(1, Math.abs(a));\n}\n\n/**\n * The claim is one of `facts`: the same kind and number, and for a duration, a price or a count\n * the same unit (a share, a multiple or a rating is its number). A fact read with no number holds\n * the number its own words write. A superlative is never held\n * here: whether two are the same claim is a judgment, not an equality. Pure.\n */\nexport function heldBy(claim: Claim, facts: readonly Claim[]): boolean {\n if (claim.kind === \"superlative\") return false;\n return facts.some((fact) => {\n const sameFigure =\n sameNumber(fact.value, claim.value) ||\n (fact.value === null && claim.value !== null && recordsWrite(fact.text, String(claim.value)));\n if (fact.kind !== claim.kind || !sameFigure) return false;\n if (claim.kind === \"duration\" || claim.kind === \"price\" || claim.kind === \"count\") {\n return !fact.unit || !claim.unit || singular(fact.unit) === singular(claim.unit);\n }\n return true;\n });\n}\n\n/** Words as compared literally: accents and case aside, punctuation as space. */\nconst literalWords = (text: string) =>\n text\n .normalize(\"NFKD\")\n .replace(/\\p{M}/gu, \"\")\n .toLocaleLowerCase()\n .replace(/[^\\p{L}\\p{N}]+/gu, \" \")\n .trim();\n\n/**\n * The records write the claim in its own words (\"zero mess\", \"halved\"), accents, case and punctuation\n * aside: held whatever kind or number either reading gave it, as a customer's quote recorded word\n * for word holds every claim in it. Code equality, in any language. Pure.\n */\nexport function recordsSay(records: string, claim: string): boolean {\n const words = literalWords(claim);\n return words !== \"\" && ` ${literalWords(records)} `.includes(` ${words} `);\n}\n\nconst escapeRegExp = (text: string) => text.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\n/** `records` write `figure` as a number of its own (not inside \"19\" or \"4.9\"), either decimal mark alike. Pure. */\nexport function recordsWrite(records: string, figure: string): boolean {\n return figureForms(figure).some((form) =>\n new RegExp(`(?<![\\\\d.,])${escapeRegExp(form)}(?![\\\\d]|[.,]\\\\d)`).test(records),\n );\n}\n\n/** A number written in digits, what every language and script shares, with the word written right after it (\"15 minutes\", \"30%\"). */\nconst FIGURE = /(\\d+(?:[.,]\\d+)*)(?:\\s?[\\p{L}%]+)?/gu;\n\n/**\n * When no model can read the copy, the one check no language can fool: every number the copy\n * writes in digits is one the records write too (\"4,8\" and \"4.8\" alike). Each figure that is\n * not, once, with the word it is written beside, so the agent knows which claim to drop. Pure.\n */\nexport function digitsWithoutSource(lines: readonly string[], records: string): string[] {\n const unheld = lines.flatMap((line) =>\n [...line.matchAll(FIGURE)].filter((m) => !recordsWrite(records, m[1] ?? \"\")).map((m) => m[0].trim()),\n );\n return [...new Set(unheld)];\n}\n","/**\n * A static ad whose prompt.json holds a `native` block is drawn as that screen (`static-native-graph.ts`):\n * on every run its render graph is rebuilt from prompt.json, so adding the block to an existing ad\n * switches it to the native route, and a photo added, changed or removed in the spec is the only\n * thing that renders again. Runs before the static projections, which leave a native canvas alone.\n */\nimport path from \"node:path\";\nimport { pickImageModel } from \"../../engine/lib/image-model-router.ts\";\nimport { type InterfaceWords, needsInterfaceWords } from \"../../engine/scaffold/native-surface.ts\";\nimport { readAdSpec } from \"../../engine/scaffold/static-ad-spec.ts\";\nimport { readBrandLogoFiles, readStaticBrandKit } from \"../../engine/scaffold/static-brand.ts\";\nimport { deliveryOf, isNativeCanvas, nativeCanvas } from \"../../engine/scaffold/static-native-graph.ts\";\nimport { STATIC_AD_ROLE } from \"../../engine/scaffold/static-render-briefs.ts\";\nimport { renderParamsFor } from \"../../engine/scaffold/staticAd.ts\";\nimport { findBrandRoot, readStaticPromptJson } from \"./static-copy-projection.ts\";\n\nexport type NativeSyncResult = \"not_applicable\" | \"up_to_date\" | \"regenerated\";\n\ntype Holder = { nodes?: unknown };\n\nfunction promptPathOf(canvas: unknown): string | null {\n const nodes = (canvas as Holder | null)?.nodes;\n if (!Array.isArray(nodes)) return null;\n const prompt = nodes.find(\n (n: { id?: unknown; type?: unknown; tags?: { role?: unknown } }) =>\n n?.id === \"prompt\" && n.type === \"ingest\" && n.tags?.role === STATIC_AD_ROLE,\n ) as { params?: { path?: unknown } } | undefined;\n return typeof prompt?.params?.path === \"string\" ? prompt.params.path : null;\n}\n\n/** Writes the interface's words for a language (`interface-words.ts`), or null when no model could. */\nexport type InterfaceWordsWriter = (language: string) => Promise<InterfaceWords | null>;\n\n/**\n * Rebuild a native static ad's graph from its prompt.json; leave every other canvas as it is. A\n * viewer's language with no checked interface words has them written once (`writeWords`) and handed\n * to every screen, so the page and the review print the same; with none, the screen speaks English.\n */\nexport async function syncNativeGraph(\n canvas: unknown,\n log: (line: string) => void,\n writeWords?: InterfaceWordsWriter,\n): Promise<NativeSyncResult> {\n const source = promptPathOf(canvas);\n if (!source) return \"not_applicable\";\n const raw = await readStaticPromptJson(canvas);\n if (!raw) return \"not_applicable\";\n const spec = readAdSpec(raw);\n if (!spec.native) return \"not_applicable\";\n const was = isNativeCanvas(canvas);\n const delivery = deliveryOf(canvas);\n const genModel = delivery.genModel ?? pickImageModel(\"photo_people\", \"generate\");\n const root = await findBrandRoot(path.dirname(source));\n const name = spec.brand?.name ?? (root ? (await readStaticBrandKit(root)).name : undefined);\n const files = root ? await readBrandLogoFiles(root, name) : { logos: [] };\n const holder = canvas as Holder & { nodes: unknown[] };\n const before = JSON.stringify(holder.nodes);\n const fontRef = holder.nodes.some((n) => (n as { id?: unknown }).id === \"font_headline\")\n ? \"$ref:font_headline.asset\"\n : undefined;\n const language = spec.viewer?.market?.language;\n const interfaceWords =\n language && writeWords && needsInterfaceWords(language) ? await writeWords(language).catch(() => null) : null;\n const next = nativeCanvas(holder, spec, {\n ...(interfaceWords ? { interfaceWords } : {}),\n genModel,\n genParams: Object.keys(delivery.genParams).length > 0 ? delivery.genParams : renderParamsFor(genModel),\n formats: delivery.formats.length > 0 ? delivery.formats : (spec.formats ?? [\"4:5\"]),\n ...(delivery.placements ? { placements: delivery.placements } : {}),\n logos: spec.logo || spec.native.frame.logo || usesLogo(spec) ? files.logos : [],\n ...(files.mark && usesLogo(spec) ? { mark: files.mark } : {}),\n ...(fontRef ? { fontRef } : {}),\n resolve: (image) =>\n /^https?:\\/\\//i.test(image)\n ? { source: \"url\", url: image }\n : { source: \"path\", path: path.resolve(path.dirname(source), image) },\n });\n holder.nodes = next.nodes;\n if (JSON.stringify(holder.nodes) === before) return \"up_to_date\";\n log(\n was\n ? \"[native] prompt.json's screen changed: the photos it shows are rendered again only where their description changed\"\n : `[native] prompt.json draws this ad as a ${spec.native.surface.replace(\"_\", \" \")} screen: every size is drawn exactly from it, and the image model renders only the photos it holds`,\n );\n return \"regenerated\";\n}\n\n/** Whether the screen shows the brand's logo anywhere (an avatar, the review site's summary, the frame). */\nfunction usesLogo(spec: ReturnType<typeof readAdSpec>): boolean {\n const native = spec.native;\n if (!native) return false;\n return native.frame.logo || JSON.stringify(native).includes('\"avatar\":\"logo\"') || \"summary\" in native;\n}\n","import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { BackendClient } from \"../../engine/client/backend-client.ts\";\nimport { optionalConnection } from \"../../env.ts\";\nimport { canvasAssetMime, inferMimeFromPath } from \"../../engine/nodes/ingest.ts\";\nimport type { AssetKind } from \"../../engine/schema/refs.ts\";\nimport { sha256Hex } from \"../../engine/storage/sha256.ts\";\nimport type { CanvasPathRewrite } from \"./normalize-paths.ts\";\n\n/**\n * The durable URL of the asset with this sha, or null when the store does not hold it.\n * Given `bytes`, it keeps them first, so the answer is never null for a file in hand.\n */\nexport type DurableUrlFor = (args: { sha256: string; mime: string; bytes?: Buffer }) => Promise<string | null>;\n\n/**\n * Point every `ingest` that reads from `canvas/` at the durable copy of what it reads.\n *\n * `canvas/` is the engine's own working folder — the content-addressed cache\n * (`canvas/.cache/assets/<xx>/<sha>.<ext>`) and each run's outputs (`canvas/r_<id>/…`) —\n * and it is gitignored. A canvas that reads from it renders in the Session that wrote it\n * and nowhere else: the commit gate sees the file and passes, then every later Session,\n * which starts without that folder, fails its publish on a creative nobody is looking at.\n * That is what happened to four published UGC ads whose voice takes were wired from the\n * cache after a download failed.\n *\n * There is nothing to ask the author: the bytes are already in our store under their sha\n * (or are kept now, from the file in hand), and an ingest of that URL returns the same\n * asset with the same sha, so nothing downstream re-renders. A cache path names its sha in\n * its own filename, so it heals even after the cache is gone. Anything the store cannot\n * vouch for is left as it is, for `validate-creatives` to report.\n */\nexport async function promoteCanvasOutputPaths(\n canvas: unknown,\n canvasDir: string,\n workspaceRoot: string,\n durableUrlFor: DurableUrlFor,\n log: (line: string) => void = () => undefined,\n): Promise<{ canvas: unknown; rewrites: CanvasPathRewrite[] }> {\n if (!canvas || typeof canvas !== \"object\") return { canvas, rewrites: [] };\n const nodes = (canvas as { nodes?: unknown }).nodes;\n if (!Array.isArray(nodes)) return { canvas, rewrites: [] };\n\n const outputsRoot = path.join(path.resolve(workspaceRoot), \"canvas\");\n const rewrites: CanvasPathRewrite[] = [];\n const promoted: unknown[] = [];\n // One at a time: each may read a large file and upload it, and the rewrites are reported in order.\n for (const node of nodes) {\n promoted.push(await promoteNode(node));\n }\n return rewrites.length === 0 ? { canvas, rewrites } : { canvas: { ...(canvas as object), nodes: promoted }, rewrites };\n\n async function promoteNode(node: unknown): Promise<unknown> {\n const n = node as { id?: unknown; type?: unknown; params?: Record<string, unknown> } | null;\n const params = n?.params;\n if (n?.type !== \"ingest\" || !params || params.source !== \"path\" || typeof params.path !== \"string\") return node;\n const from = params.path;\n const target = path.resolve(canvasDir, from);\n const inOutputs = path.relative(outputsRoot, target);\n if (inOutputs === \"\" || inOutputs.startsWith(\"..\") || path.isAbsolute(inOutputs)) return node;\n\n const nodeId = typeof n.id === \"string\" ? n.id : \"?\";\n const url = await durableCopyOf(target, inOutputs, durableUrlFor);\n if (url === null) {\n log(`[canvas] ${nodeId}: \"${from}\" is in canvas/, which is not committed, and no durable copy could be found for it`);\n return node;\n }\n const expect = typeof params.expect === \"string\" ? params.expect : \"\";\n if (!isAssetKind(expect) || canvasAssetMime(url, expect) === null) {\n log(`[canvas] ${nodeId}: \"${from}\" is in canvas/; its durable copy ${url} would not ingest back as ${expect || \"its kind\"}, so the path was left as it is`);\n return node;\n }\n const { path: _path, ...rest } = params;\n rewrites.push({ nodeId, param: \"source\", from, to: url });\n return { ...n, params: { ...rest, source: \"url\", url } };\n }\n}\n\nfunction isAssetKind(value: string): value is AssetKind {\n return [\"image\", \"video\", \"audio\", \"text\", \"json\", \"font\"].includes(value);\n}\n\n/** The durable URL for a file under `canvas/`, read from disk or, for a cache path, from its name. */\nasync function durableCopyOf(target: string, inOutputs: string, durableUrlFor: DurableUrlFor): Promise<string | null> {\n const bytes = await readFile(target).catch(() => null);\n if (bytes !== null) {\n return durableUrlFor({ sha256: sha256Hex(bytes), mime: inferMimeFromPath(target, bytes), bytes });\n }\n const address = /^\\.cache[/\\\\]assets[/\\\\]([0-9a-f]{2})[/\\\\]([0-9a-f]{64})\\.[a-z0-9]+$/.exec(inOutputs);\n if (!address?.[2] || !address[2].startsWith(address[1] ?? \"\")) return null;\n return durableUrlFor({ sha256: address[2], mime: inferMimeFromPath(target, Buffer.alloc(0)) });\n}\n\n/**\n * The store's own answer, through the backend: the public URL it would serve this sha\n * from, confirmed by a HEAD, and the bytes kept when they are in hand and missing. Asked\n * as `purpose: \"source\"` because the URL is about to be written into a committed file,\n * which pins the object against the asset sweep. Without a Baker connection nothing can\n * be vouched for, so nothing is rewritten and the commit gate reports the path instead.\n */\nexport function backendDurableUrlFor(log: (line: string) => void = () => undefined): DurableUrlFor {\n const connection = optionalConnection();\n if (!connection) return async () => null;\n const client = new BackendClient(connection);\n return async ({ sha256, mime, bytes }) => {\n try {\n const { putUrl, publicUrl, conditional } = await client.presignAssetUpload(sha256, mime, undefined, \"source\", true);\n const held = await fetch(publicUrl, { method: \"HEAD\" }).then(\n (res) => res.ok,\n () => false,\n );\n if (held) return publicUrl;\n if (!bytes) {\n log(`[canvas] the asset store does not hold ${sha256.slice(0, 12)}…, and the file is not here to keep`);\n return null;\n }\n const put = await fetch(putUrl, {\n method: \"PUT\",\n body: new Uint8Array(bytes),\n headers: conditional ? { \"Content-Type\": mime, \"If-None-Match\": \"*\" } : { \"Content-Type\": mime },\n });\n if (put.ok || (conditional === true && put.status === 412)) return publicUrl;\n log(`[canvas] could not keep ${sha256.slice(0, 12)}… in the asset store (upload answered ${put.status})`);\n return null;\n } catch (e) {\n log(`[canvas] could not reach the asset store for ${sha256.slice(0, 12)}…: ${e instanceof Error ? e.message : String(e)}`);\n return null;\n }\n };\n}\n","/**\n * Who the company's Avatars are to it and what each customer has said in public, read before any\n * render is billed: the cast check lets a customer's face appear only in an ad quoting them.\n */\nimport type { AvatarsListResponse, TestimonialsSearchResponse } from \"@baker/api\";\nimport { apiPost } from \"../../client.ts\";\nimport { readAvatars } from \"../avatars/transport.ts\";\nimport type { CastRoster } from \"./cast-decision.ts\";\nimport { avatarRelation, castCompany } from \"./cast-inventory.ts\";\n\nconst nameKey = (name: string) =>\n name\n .normalize(\"NFD\")\n .replace(/\\p{M}/gu, \"\")\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}]/gu, \"\");\n\n/** The published words of the testimonials linked to an Avatar or given under the person's name. Pure. */\nexport function quotesOf(\n avatar: { name: string; handle: string; testimonialIds?: readonly string[] },\n found: TestimonialsSearchResponse,\n): string[] {\n const names = [nameKey(avatar.name), nameKey(avatar.handle)].filter((k) => k.length >= 4);\n return found\n .filter((t) => {\n if (avatar.testimonialIds?.includes(t._id)) return true;\n const reviewer = nameKey(t.reviewerName ?? \"\");\n return reviewer.length >= 4 && names.some((n) => n === reviewer);\n })\n .flatMap((t) => [t.reviewText, t.highlight])\n .filter((text): text is string => typeof text === \"string\" && text.trim().length > 0)\n .map((text) => text.trim());\n}\n\n/**\n * The roster of a workspace's ready Avatars; for those named by `handles` who are not the team's, the\n * published words they gave (`/api/testimonials/search`, a free read). null when the Avatars cannot be read.\n */\nexport async function liveCastRoster(root: string, handles: readonly string[]): Promise<CastRoster> {\n const [response, company] = await Promise.all([\n readAvatars<AvatarsListResponse>(\"/api/avatars\", { status: \"ready\" }).catch(() => null),\n castCompany(root),\n ]);\n if (!response) return null;\n return await Promise.all(\n response.avatars.map(async (a) => {\n const relation = avatarRelation(a, company);\n const castable = relation === \"team\" || relation === \"founder\" || relation === \"role\";\n const found =\n !castable && handles.includes(a.handle)\n ? await apiPost<TestimonialsSearchResponse>(\"/api/testimonials/search\", { query: a.name, limit: 10 }).catch(\n () => [] as TestimonialsSearchResponse,\n )\n : [];\n return {\n handle: a.handle,\n relation,\n who: [a.person?.role, a.person?.company].filter(Boolean).join(\" at \") || a.subjectDescription || a.name,\n quotes: quotesOf(a, found),\n };\n }),\n );\n}\n","/**\n * An edit keeps the idea: a run is refused (`idea_changed`, free, before anything bills) when the\n * message, who it is for and its market, the reference, what we take from it, why it won and what\n * survives of it, the language, or a video's accent, voice, route or cast moved since the version the person saw, and no line under `## Changes` in `_definition.md`\n * says so. The anchor itself is read off the files (`anchor.ts`); this module only compares.\n *\n * Pure.\n */\nimport { type IdeaAnchor, recordedChanges } from \"../../engine/creative-context/anchor.ts\";\nimport { frontmatterOf } from \"../creatives/ideas-model.ts\";\n\nexport type DriftField =\n | \"message\"\n | \"viewer\"\n | \"market\"\n | \"reference\"\n | \"why_it_won\"\n | \"survives\"\n | \"carry\"\n | \"must_keep\"\n | \"language\"\n | \"accent\"\n | \"voice\"\n | \"voice_id\"\n | \"route\"\n | \"cast\";\n\nexport type IdeaDrift = { field: DriftField; was: string; now: string };\n\nconst NONE = \"none\";\n\n/** Text as two readings of the same idea compare it: case, spacing, quotes and end punctuation aside. */\nfunction norm(value: string | undefined): string {\n return (value ?? \"\")\n .trim()\n .replace(/\\s+/g, \" \")\n .toLowerCase()\n .replace(/^[\"'“”«»]+|[\"'“”«»]+$/g, \"\")\n .replace(/[.!?…;:,]+$/u, \"\")\n .trim();\n}\n\nconst sameList = (a: readonly string[] = [], b: readonly string[] = []): boolean =>\n a.length === b.length && a.every((v, i) => norm(v) === norm(b[i]));\n\nconst listText = (values: readonly string[] | undefined): string => (values?.length ? values.join(\"; \") : NONE);\n\n/** What the reference part of the idea moved by, for an ad that is not a series member. */\nfunction referenceDrift(seen: IdeaAnchor, now: IdeaAnchor): IdeaDrift[] {\n const was = seen.reference;\n const is = now.reference;\n if (!was && !is) return [];\n if (!was || !is || norm(was.adId) !== norm(is.adId)) {\n return [{ field: \"reference\", was: was ? (was.adId ?? \"its reference\") : NONE, now: is ? (is.adId ?? \"its reference\") : NONE }];\n }\n const out: IdeaDrift[] = [];\n if (was.carry !== is.carry) out.push({ field: \"carry\", was: was.carry, now: is.carry });\n const kept = new Set(is.mustKeep.map(norm));\n for (const element of was.mustKeep) {\n if (!kept.has(norm(element))) out.push({ field: \"must_keep\", was: element, now: \"dropped\" });\n }\n return out;\n}\n\n/** Why the reference won and what survives of it, moved while the reference stayed (its own drift says the rest). */\nfunction whyDrift(seen: IdeaAnchor, now: IdeaAnchor): IdeaDrift[] {\n if (!seen.reference || !now.reference || norm(seen.reference.adId) !== norm(now.reference.adId)) return [];\n return [\n ...textDrift(\"why_it_won\", seen.whyItWon, now.whyItWon),\n ...textDrift(\"survives\", seen.survives, now.survives),\n ];\n}\n\n/** A text part of the idea that moved, case, spacing and end punctuation aside; none when it was never set. */\nfunction textDrift(field: DriftField, was: string | undefined, now: string | undefined): IdeaDrift[] {\n return was && norm(was) !== norm(now) ? [{ field, was, now: now ?? NONE }] : [];\n}\n\n/** A list part of the idea that moved; none when it was empty. */\nfunction listDrift(\n field: DriftField,\n was: readonly string[] | undefined,\n now: readonly string[] | undefined,\n): IdeaDrift[] {\n return was?.length && !sameList(was, now) ? [{ field, was: listText(was), now: listText(now) }] : [];\n}\n\n/** Every way `now` departs from the idea the person saw (`seen`). Pure. */\nexport function ideaDrift(seen: IdeaAnchor, now: IdeaAnchor): IdeaDrift[] {\n const ownReference = !seen.seriesLead && !now.seriesLead;\n return [\n ...textDrift(\"message\", seen.message, now.message),\n ...textDrift(\"viewer\", seen.viewer, now.viewer),\n ...textDrift(\"market\", seen.market, now.market),\n ...(ownReference ? [...referenceDrift(seen, now), ...whyDrift(seen, now)] : []),\n ...textDrift(\"language\", seen.language, now.language),\n ...textDrift(\"accent\", seen.accent, now.accent),\n ...listDrift(\"voice\", seen.voices, now.voices),\n ...listDrift(\"voice_id\", seen.voiceIds, now.voiceIds),\n ...textDrift(\"route\", seen.route, now.route),\n ...listDrift(\"cast\", seen.cast, now.cast),\n ];\n}\n\nconst CARRY_WORDS: Record<string, string> = { whole_ad: \"whole ad\", layout: \"layout\", hook: \"hook\", angle: \"angle\" };\n\nconst ROUTE_WORDS: Record<string, string> = {\n on_camera: \"on camera\",\n mixed: \"on camera and in voiceover\",\n voiceover: \"a voiceover\",\n none: \"no voice\",\n};\n\n/** How each field is written under `## Changes`: its lead words, and the value the line must name (null: the lead alone). */\nconst RECORDING: Record<DriftField, { lead: string; value: (d: IdeaDrift) => string | null }> = {\n message: { lead: \"The message\", value: (d) => d.now },\n viewer: { lead: \"Who it is for\", value: (d) => d.now },\n market: { lead: \"The market\", value: (d) => d.now },\n why_it_won: { lead: \"Why the reference won\", value: () => null },\n survives: { lead: \"What survives\", value: () => null },\n reference: { lead: \"The reference ad\", value: (d) => d.now },\n carry: { lead: \"What we take from it\", value: (d) => CARRY_WORDS[d.now] ?? d.now },\n must_keep: { lead: \"We no longer keep\", value: (d) => d.was },\n language: { lead: \"The language\", value: (d) => d.now },\n accent: { lead: \"The accent\", value: (d) => d.now },\n voice: { lead: \"The voice\", value: () => null },\n voice_id: { lead: \"The voice\", value: () => null },\n route: { lead: \"How it is voiced\", value: (d) => ROUTE_WORDS[d.now] ?? d.now },\n cast: { lead: \"Who appears\", value: () => null },\n};\n\n/** A reason after a dash: ` — they asked for …`. */\nconst REASON = /\\s[—–-]{1,2}\\s*\\S.{2,}$/u;\n\n/** Whether `line` records `drift`: its lead words, then the new value, then a dash and a reason. */\nfunction records(line: string, drift: IdeaDrift): boolean {\n const said = line.replace(/\\s+/g, \" \").toLowerCase();\n const { lead, value } = RECORDING[drift.field];\n const leadAt = said.indexOf(lead.toLowerCase());\n if (leadAt === -1) return false;\n const named = value(drift);\n let rest = said.slice(leadAt + lead.length);\n if (named !== null) {\n const needle = norm(named);\n const at = needle ? rest.indexOf(needle) : -1;\n if (at === -1) return false;\n rest = rest.slice(at + needle.length);\n }\n return REASON.test(rest);\n}\n\n/** Whether the definition's front matter, where it names the field, agrees with the new value. */\nfunction frontMatterAgrees(drift: IdeaDrift, fm: Record<string, unknown>): boolean {\n const named = (key: string): string | undefined => (typeof fm[key] === \"string\" ? (fm[key] as string) : undefined);\n const check = (key: string) => {\n const value = named(key);\n return value === undefined || norm(value) === norm(drift.now);\n };\n if (drift.field === \"message\") return check(\"message\");\n if (drift.field === \"reference\") return drift.now === NONE || check(\"sourceAdId\");\n if (drift.field === \"language\") return check(\"language\");\n return true;\n}\n\n/**\n * The drift no new line under `## Changes` records. Only lines added since the version the person\n * saw count (`seen.changes`), so a line written for an earlier ask never clears a later one; and\n * where the front matter names the field (`message:`, `sourceAdId:`, `language:`), it must agree. Pure.\n */\nexport function unrecordedDrift(drift: readonly IdeaDrift[], seen: IdeaAnchor, definition: string): IdeaDrift[] {\n const before = new Set(seen.changes.map(norm));\n const fresh = recordedChanges(definition).filter((line) => !before.has(norm(line)));\n const fm = frontmatterOf(definition) ?? {};\n return drift.filter((d) => !(fresh.some((line) => records(line, d)) && frontMatterAgrees(d, fm)));\n}\n\nconst FIELD_WORDS: Record<DriftField, string> = {\n message: \"the message\",\n viewer: \"who it is for\",\n market: \"the market\",\n why_it_won: \"why the reference won\",\n survives: \"what survives of the reference\",\n reference: \"the reference ad\",\n carry: \"what we take from the reference\",\n must_keep: \"a must-keep element of the reference\",\n language: \"the language\",\n accent: \"the accent\",\n voice: \"the voice\",\n voice_id: \"the chosen voice\",\n route: \"how it is voiced\",\n cast: \"who appears\",\n};\n\nconst RESTORE: Record<DriftField, string> = {\n message: 'prompt.json `message` (a video: `message:` in _definition.md)',\n viewer: \"prompt.json `viewer.who` (a video: `persona:` in _definition.md)\",\n market: \"prompt.json `viewer.market.country`\",\n why_it_won: \"prompt.json `concept.why_it_wins`\",\n survives: '\"### What survives and what changes\" in _definition.md',\n reference: \"prompt.json `concept.reference_ad_id`\",\n carry: \"prompt.json `concept.carry`\",\n must_keep: \"prompt.json `concept.load_bearing`\",\n language: \"prompt.json `viewer.market.language` (a video: `language:` in _definition.md)\",\n accent: \"prompt.json `global.voiceover.accent`\",\n voice: \"prompt.json `global.voiceover.voice_description` or scenes/NN.json `voice_description`\",\n voice_id: \"the canvas's `voice_select` `voice_id`\",\n route: \"prompt.json `global.voiceover.mode`\",\n cast: \"ad.spec.json `cast` (or prompt.json `global.cast`)\",\n};\n\n/** The `## Changes` line that records one drift. */\nfunction changeLine(d: IdeaDrift, today: string): string {\n const { lead, value } = RECORDING[d.field];\n const named = value(d);\n const said =\n d.field === \"message\"\n ? `${lead} is now \"${d.now}\"`\n : d.field === \"must_keep\"\n ? `${lead} ${d.was}`\n : named !== null\n ? `${lead} is now ${named}`\n : `${lead} is now <what it is now, in plain words>`;\n return `\\`- ${today} ${said} — <why they asked>\\``;\n}\n\n/** The refusal for drift nobody recorded: what moved, and the two ways out. Pure. */\nexport function ideaRefusal(\n drift: readonly IdeaDrift[],\n creativeDir: string,\n today: string,\n): { problems: string[]; fix: string } {\n const moved = drift.map((d) =>\n d.field === \"must_keep\"\n ? `${FIELD_WORDS[d.field]} \"${d.was}\" is gone`\n : `${FIELD_WORDS[d.field]} \"${d.now}\" (was \"${d.was}\")`,\n );\n const restore = [...new Set(drift.map((d) => RESTORE[d.field]))].join(\"; \");\n const fields = new Set(drift.map((d) => d.field));\n const frontMatter = [\n fields.has(\"message\") ? \"`message:`\" : \"\",\n fields.has(\"reference\") ? \"`sourceAdId:`\" : \"\",\n fields.has(\"language\") ? \"`language:` (if it has one)\" : \"\",\n ].filter(Boolean);\n return {\n problems: [\n `This run changes the ad's idea since the version the person saw: ${moved.join(\"; \")}. An edit keeps the idea unless the person asked to change it.`,\n ],\n fix: [\n `If they did not ask, put it back: ${restore}.`,\n `If they did, add under \"## Changes\" in ${creativeDir}/_definition.md one line per change, the reason after the dash: ${drift.map((d) => changeLine(d, today)).join(\" \")}`,\n frontMatter.length ? `Update ${frontMatter.join(\", \")} in its front matter to match.` : \"\",\n \"Update the Thinking section it changes, then run again.\",\n ]\n .filter(Boolean)\n .join(\" \"),\n };\n}\n\n/**\n * The idea this run is held to, and the turn's record to keep when it starts one. In a turn that\n * already started, what the person saw when it did (none: a creation turn, nothing held); in a new\n * turn, or a run outside a chat, the last render here, else the version shown elsewhere. Pure.\n */\nexport function ideaBaseline(\n state: { anchor?: IdeaAnchor; seen?: { turnId: string; anchor?: IdeaAnchor } },\n turnId: string | undefined,\n fallback: IdeaAnchor | undefined,\n): { baseline?: IdeaAnchor; seen?: { turnId: string; anchor?: IdeaAnchor } } {\n if (turnId !== undefined && state.seen?.turnId === turnId) {\n return state.seen.anchor ? { baseline: state.seen.anchor } : {};\n }\n const baseline = state.anchor ?? fallback;\n return {\n ...(baseline ? { baseline } : {}),\n ...(turnId !== undefined ? { seen: { turnId, ...(baseline ? { anchor: baseline } : {}) } } : {}),\n };\n}\n","/**\n * A plan keeps what made its proven ad win: what stops the scroll and the proof (`concept.load_bearing`\n * with `job: stop | proof`). Dev, Oct 2026: the thinking of an ad built on a then/now meme wrote \"the\n * faces go (nothing replaces them but the contrast)\" and the ad came back a feature comparison; a\n * before/after kept its two columns and lost its ✗/✓ marks. The plan holds the decision twice, in the\n * thinking's decision lines (`survivalDecisions`) and in prompt.json's concept, and a run is refused\n * (`concept_does_not_fit`, free) while either drops a stop or proof element, leaves it impossible,\n * replaces it with nothing named or with an Avatar nobody is grounded on, or the two disagree.\n *\n * Pure.\n */\nimport {\n type AdLoadBearing,\n type AdSpec,\n decisionOf,\n isVital,\n type VitalJob,\n} from \"../../engine/scaffold/static-ad-spec.ts\";\nimport { castDecision, castHandles } from \"../creatives/cast-decision.ts\";\nimport { frontmatterOf } from \"../creatives/ideas-model.ts\";\nimport { REPLACE_WITH, type SurvivalDecision, survivalDecisions } from \"../creatives/thinking.ts\";\n\n/** How a refusal names what an element does for the proven ad. */\nconst ROLE: Record<VitalJob, string> = {\n stop: \"what stops the scroll in the proven ad\",\n proof: \"the proof in the proven ad\",\n};\n\nconst SURVIVES = /^###\\s+What survives and what changes\\s*$/im;\n\n/** An element's words as two records of it compare: case, spacing, quotes and end punctuation aside. */\nconst norm = (text: string): string =>\n text\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, \" \")\n .replace(/^[\"'“”«»]+|[\"'“”«».]+$/g, \"\")\n .trim();\n\n/** What a run refusing the plan says. */\ntype KeepRefusal = { problems: string[]; fix: string };\n\n/** `unreadable`: a line the thinking holds that reads as no element of the concept, never one to keep. */\ntype Problem = { element: string; text: string; another?: boolean; unreadable?: boolean };\n\n/** How a decision line names its element's job. */\nconst LABEL: Record<VitalJob, string> = { stop: \"Stops the scroll\", proof: \"Proof\" };\n\n/** The company rule an element quotes, as a refusal says it. */\nconst because = (rule: string | undefined): string => (rule?.trim() ? ` (a company rule: \"${rule.trim()}\")` : \"\");\n\n/** What is wrong with one stop or proof element in prompt.json's concept alone. */\nfunction specProblems(l: AdLoadBearing & { job: VitalJob }, spec: Pick<AdSpec, \"references\">): Problem[] {\n const said = `\"${l.element}\", ${ROLE[l.job]}`;\n const decision = decisionOf(l);\n if (decision === \"impossible\") {\n return [\n {\n element: l.element,\n text: `${said}, cannot be ours${because(l.rule)}: this ad cannot be built on it.`,\n another: true,\n },\n ];\n }\n if (decision === \"replace\" && !l.ours?.trim()) {\n return [{ element: l.element, text: `${said}, is replaced in prompt.json's concept with nothing named.` }];\n }\n const grounded = new Set(spec.references.flatMap((r) => (r.avatar ? [r.avatar.toLowerCase()] : [])));\n return castHandles(l.ours ?? \"\")\n .filter((handle) => !grounded.has(handle))\n .map((handle) => ({\n element: l.element,\n text: `${said}, is replaced with @${handle}, but prompt.json grounds no person on @${handle} (a reference with \"avatar\": \"${handle}\").`,\n }));\n}\n\n/** Where the thinking's line for one element departs from prompt.json's concept. */\nfunction lineProblems(l: AdLoadBearing & { job: VitalJob }, line: SurvivalDecision | undefined): Problem[] {\n const said = `\"${l.element}\", ${ROLE[l.job]}`;\n if (!line) return [{ element: l.element, text: `${said}, has no decision under \"What survives and what changes\".` }];\n if (line.decision === \"open\") return [];\n if (line.decision === \"unclear\") {\n return [\n {\n element: l.element,\n text: `${said}: \"${line.said ?? \"\"}\" under \"What survives and what changes\" is no decision (keep, replace with …, or impossible: \"<rule>\").`,\n },\n ];\n }\n const decision = decisionOf(l);\n if (line.decision === \"impossible\" && decision !== \"impossible\") {\n return [\n {\n element: l.element,\n text: `${said}, is impossible for us in the thinking${because(line.rule)}: this ad cannot be built on it.`,\n another: true,\n },\n ];\n }\n return line.decision === decision\n ? []\n : [\n {\n element: l.element,\n text: `${said}: the thinking decides ${line.decision}, prompt.json's concept ${decision}.`,\n },\n ];\n}\n\n/** Stop and proof lines the thinking decided whose element prompt.json's concept no longer carries as one. */\nfunction droppedProblems(lines: readonly SurvivalDecision[], concept: NonNullable<AdSpec[\"concept\"]>): Problem[] {\n return lines.flatMap((d) => {\n if (d.job === \"other\") return [];\n const held = concept.load_bearing.find((l) => norm(l.element) === norm(d.element));\n if (!held && d.decision === \"unclear\") {\n // Read whole, the line is no element and no decision: show it the shape, never ask to keep it.\n const job = d.job;\n const shapes = concept.load_bearing\n .filter((l) => l.job === job)\n .map((l) => `\"- ${LABEL[job]}: ${l.element} — replace with <what of ours>\" (or \"— keep\", or \"— impossible: \\\"<rule>\\\"\")`);\n return [\n {\n element: d.element,\n unreadable: true,\n text: `\"${d.element}\" under \"What survives and what changes\" is no decision line: write ${shapes.join(\" and \") || \"the element's words, a dash, then keep, replace with … or impossible\"}, the element's words exactly as prompt.json's concept has them.`,\n },\n ];\n }\n if (!held) {\n return [\n {\n element: d.element,\n text: `\"${d.element}\", ${ROLE[d.job]}, is decided under \"What survives and what changes\" but gone from prompt.json's concept.`,\n },\n ];\n }\n return held.job === d.job\n ? []\n : [\n {\n element: d.element,\n text: `\"${d.element}\" is ${ROLE[d.job]} in the thinking, but prompt.json's concept no longer says so (\\`\"job\": \"${d.job}\"\\`).`,\n },\n ];\n });\n}\n\n/** An Avatar a stop or proof is replaced with that the cast decision does not name. */\nfunction uncastReplacements(definition: string, vital: ReadonlyArray<AdLoadBearing & { job: VitalJob }>): Problem[] {\n const cast = castDecision(definition)?.cast;\n if (cast === undefined) return [];\n const named = new Set(castHandles(cast));\n return vital.flatMap((l) =>\n castHandles(l.ours ?? \"\")\n .filter((handle) => !named.has(handle))\n .map((handle) => ({\n element: l.element,\n text: `\"${l.element}\", ${ROLE[l.job]}, is replaced with @${handle}, but the cast is \"${cast}\": cast @${handle} under \"Who appears and what we show\".`,\n })),\n );\n}\n\n/** The fix, naming every element refused: decide and carry it, or build on another proven ad. */\nfunction keepFix(problems: readonly Problem[], idea: string | undefined): string {\n const lost = new Set(problems.filter((p) => p.another).map((p) => p.element));\n const kept = new Set(problems.filter((p) => !lost.has(p.element) && !p.unreadable).map((p) => p.element));\n const quoted = (elements: ReadonlySet<string>) => [...elements].map((e) => `\"${e}\"`).join(\", \");\n const another = quoted(lost);\n const named = quoted(kept);\n const make = `\\`baker winning-ads fit <adId>\\` on the next candidates, then \\`baker creatives make ${idea ?? \"<idea>\"} --slug <new slug> --reference <adId>\\``;\n return [\n another\n ? `Nothing of ours may carry ${another}, so this ad cannot be built on this proven ad: build the idea on another (${make}) and tell the person why, in one line.`\n : \"\",\n named\n ? `Keep ${named}: decide each under \"What survives and what changes\" (keep it, or replace it with what of ours does the same job, named: ${REPLACE_WITH}), write the same decision into prompt.json's \\`concept.load_bearing\\` (\\`decision\\`, \\`ours\\`, \\`rule\\`; the element's words unchanged), ground an Avatar it names in \\`references\\` and cast it, and carry it in the scene and the lines' \\`look\\`. Never delete it from either; when nothing of ours may carry it, build on another proven ad (${make}).`\n : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n}\n\n/**\n * Why a run of this plan is refused: a stop or proof element of its proven ad that the plan drops,\n * leaves impossible, replaces with nothing or with an Avatar it does not ground and cast, or decides\n * differently in the thinking and prompt.json; null when it keeps them all, or keeps no concept. The\n * thinking is held only when it has its \"What survives and what changes\" section. Pure.\n */\nexport function keepRefusal(definition: string, spec: Pick<AdSpec, \"concept\" | \"references\">): KeepRefusal | null {\n const concept = spec.concept;\n if (!concept || concept.verdict === \"reject\") return null;\n const vital = concept.load_bearing.filter((l): l is AdLoadBearing & { job: VitalJob } => isVital(l));\n const lines = SURVIVES.test(definition) ? survivalDecisions(definition) : null;\n const problems = [\n ...vital.flatMap((l) => specProblems(l, spec)),\n ...(lines\n ? [\n ...vital.flatMap((l) =>\n lineProblems(\n l,\n lines.find((d) => norm(d.element) === norm(l.element)),\n ),\n ),\n ...droppedProblems(lines, concept),\n ...uncastReplacements(definition, vital),\n ]\n : []),\n ];\n if (problems.length === 0) return null;\n const idea = frontmatterOf(definition)?.idea;\n return {\n problems: [...new Set(problems.map((p) => p.text))],\n fix: keepFix(problems, typeof idea === \"string\" ? idea : undefined),\n };\n}\n","/**\n * The ad's words are in the language its viewer reads (the owner's ask, Oct 2026: a Spanish ad whose\n * copy an edit switched to English must never render). No production verdict showed it on static copy\n * yet (the language complaints were about spoken takes), so a run reads the copy's language (Jev, one\n * Choice over every language `Intl` names: docs/decision-model.md) against the language the ad is for\n * (its own, else the company's: `anchor.ts`), blocks only a reading it is sure of, and warns otherwise.\n *\n * Measured 2026-10-12 on twelve ad copies (Spanish with English loanwords and brand names, English,\n * Catalan, Brazilian Portuguese, half-English Spanish), twice: every copy read as its language at 0.86\n * or more, a switched one at 0.99; the half-English one stayed Spanish (0.86-0.90), so it never blocks.\n */\nimport { languageName } from \"../../language.ts\";\nimport type { JevAnswer, JevQuestion } from \"../../engine/nodes/local/lib/jev.ts\";\nimport { readAdWords } from \"../../engine/creative-context/ad-words.ts\";\nimport { readIdeaAnchor } from \"../../engine/creative-context/anchor.ts\";\nimport { languageQuestion } from \"../../engine/scaffold/lib/language.ts\";\n\n/** At or above it, a reading of another language blocks the run; below it, it warns. */\nexport const COPY_LANGUAGE_BLOCKS = 0.9;\n/** Fewer words than this never block: two words can be read as more than one language. */\nconst COPY_LANGUAGE_MIN_WORDS = 3;\n\nexport type CopyLanguageVerdict = { kind: \"block\" | \"warn\"; message: string; fix: string };\n\ntype Ask = (questions: readonly JevQuestion[]) => Promise<JevAnswer[] | null>;\n\nconst named = (tag: string): string => languageName(tag.split(\"-\")[0] ?? tag) ?? tag;\n\n/** Whether `lines`, read as `answer`, are in the language `declared` names. Pure. */\nexport function copyLanguageVerdict(input: {\n declared: string;\n lines: readonly string[];\n answer: JevAnswer | undefined;\n}): CopyLanguageVerdict | null {\n const answer = input.answer;\n if (!answer || !(\"choice\" in answer)) return null;\n const wanted = (input.declared.split(\"-\")[0] ?? \"\").toLowerCase();\n if (!wanted || answer.choice.toLowerCase() === wanted) return null;\n const p = answer.probabilities[answer.choice] ?? 0;\n const words = input.lines.join(\" \").split(/\\s+/).filter((w) => /\\p{L}/u.test(w)).length;\n const sure = p >= COPY_LANGUAGE_BLOCKS && words >= COPY_LANGUAGE_MIN_WORDS;\n const reads = named(answer.choice);\n const forReaders = `${named(input.declared)} (${input.declared})`;\n const fix = `Write every line of prompt.json's copy (a video: its spoken lines and on-screen words) in ${named(input.declared)}. If the person asked for ${reads}, set prompt.json \\`viewer.market\\` to its country and language tag (a video: \\`language:\\` in _definition.md), add the line under \"## Changes\" (- <date> The language is now <tag> — <why they asked>), then run again.`;\n return sure\n ? { kind: \"block\", message: `The ad's words read as ${reads}, but the ad is for ${forReaders} readers.`, fix }\n : {\n kind: \"warn\",\n message: `[language] the ad's words may not all be in ${forReaders}: they read as ${reads} (${p.toFixed(2)}). Check every line is in the language its viewer reads.`,\n fix,\n };\n}\n\n/** One creative folder's words against the language it is for; null when either is unknown or nothing answered. */\nexport async function copyLanguageCheck(creativeDir: string, ask: Ask): Promise<CopyLanguageVerdict | null> {\n const [words, idea] = await Promise.all([readAdWords(creativeDir), readIdeaAnchor(creativeDir)]);\n const declared = idea?.anchor.language;\n const lines = words?.lines.filter((l) => l.trim()) ?? [];\n if (!declared || lines.length === 0) return null;\n const answers = await ask([languageQuestion(lines)]).catch(() => null);\n return copyLanguageVerdict({ declared, lines, answer: answers?.[0] });\n}\n","/**\n * A static ad's sizes follow where its `_definition.md` says it runs: a definition edited to\n * another platform (or other sizes) re-plans the canvas on the next validate or run, before\n * anything bills (`static-replan.ts`), and the definition's `formats` follow. Only `prepareCanvas`\n * with `gate` (run, validate) asks; the read-only preview the watcher runs never re-plans.\n */\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { parseDefinitionDelivery } from \"../../engine/scaffold/static-delivery.ts\";\nimport { replanStaticCanvas, sizesToReplan } from \"../../engine/scaffold/static-replan.ts\";\nimport { definitionPlatformOf, setDefinitionDelivery } from \"./creative-definition.ts\";\n\nexport type DefinitionSizes =\n | { status: \"unchanged\" }\n | { status: \"replanned\"; canvas: unknown; note: string }\n | { status: \"refused\"; message: string; fix: string };\n\n/** The canvas re-planned for what its definition now says, or unchanged, or why it cannot be. */\nexport async function sizesFromDefinition(canvas: unknown, canvasDir: string): Promise<DefinitionSizes> {\n const definitionPath = path.join(canvasDir, \"_definition.md\");\n const raw = await readFile(definitionPath, \"utf8\").catch(() => null);\n const definition = raw === null ? null : parseDefinitionDelivery(raw);\n if (raw === null || !definition?.platforms) return { status: \"unchanged\" };\n const target = sizesToReplan(canvas, definition);\n if (!target) return { status: \"unchanged\" };\n const replanned = replanStaticCanvas(canvas, target);\n if (\"refused\" in replanned) {\n return {\n status: \"refused\",\n message: `_definition.md says this ad runs on ${definition.platforms.join(\", \")}, in ${target.formats.join(\", \")}, and the canvas delivers other sizes. ${replanned.refused}`,\n fix: `Put _definition.md's platforms and formats back to what the canvas delivers, or ${replanned.refused.charAt(0).toLowerCase()}${replanned.refused.slice(1)}`,\n };\n }\n await writeFile(\n definitionPath,\n setDefinitionDelivery(raw, {\n platforms: definition.platforms,\n platform: definitionPlatformOf(definition.platforms[0] ?? \"\"),\n formats: target.formats,\n }),\n \"utf8\",\n );\n return {\n status: \"replanned\",\n canvas: replanned.canvas,\n note: `[sizes] _definition.md says this ad runs on ${definition.platforms.join(\", \")}: it now delivers ${target.formats.join(\", \")}, the ${target.lead} designed first; the sizes that changed render on this run.`,\n };\n}\n","/**\n * A static ad whose `_definition.md` now says it runs elsewhere, re-planned on its next run.\n *\n * The canvas records the platforms its sizes were planned for (the prefilter's `platforms`). When\n * the definition names other platforms, or asks other sizes on the same ones, the render part is\n * rebuilt for them (`rebuildRenderPart`): the variants keep their model, params and pictures, so\n * adding a size that keeps the lead asks the variants for nothing new. A canvas made before\n * platforms is touched only when its definition is given platforms whose sizes differ from what it\n * delivers. A series ad, a native screen and a hand-built graph are never rebuilt here. Pure.\n */\nimport { AD_PLACEMENTS } from \"@baker/canvas-contract\";\nimport type { NodeDecl } from \"../schema/canvas.ts\";\nimport { type DefinitionDelivery, type StaticDelivery, staticDeliveryOf } from \"./static-delivery.ts\";\nimport { isNativeCanvas } from \"./static-native-graph.ts\";\nimport { seriesOf } from \"./static-render-briefs.ts\";\nimport {\n DEFAULT_MASTER_SHAPE,\n MASTER_SHAPES,\n type MasterShape,\n planStaticFormats,\n plateDrawnLead,\n} from \"./static-sizes.ts\";\nimport { VARIANT_PREFILTER_ROLE } from \"./static-topology.ts\";\nimport { rebuildRenderPart, renderGraph } from \"./static-upgrade.ts\";\n\ntype Node = { id: string; type: string; params?: Record<string, unknown>; tags?: { role?: string } };\n\nconst nodesOf = (canvas: unknown): Node[] => {\n const nodes = (canvas as { nodes?: unknown } | null)?.nodes;\n return Array.isArray(nodes) ? (nodes as Node[]) : [];\n};\nconst strings = (value: unknown): string[] | undefined =>\n Array.isArray(value) && value.every((v) => typeof v === \"string\") ? (value as string[]) : undefined;\n\n/** What the canvas delivers and what it was planned for, read off it; null when it is no designed static. */\nfunction plannedOn(\n canvas: unknown,\n): { formats: string[]; master?: string; shape?: unknown; platforms?: string[] } | null {\n const nodes = nodesOf(canvas);\n const prefilter = nodes.find((n) => n.tags?.role === VARIANT_PREFILTER_ROLE);\n const formats = strings(nodes.find((n) => n.id === \"final\" && n.type === \"collect\")?.params?.labels);\n if (!prefilter || !formats || formats.length === 0) return null;\n const lead = prefilter.params?.lead;\n const platforms = strings(prefilter.params?.platforms);\n return {\n formats,\n shape: prefilter.params?.master_shape,\n ...(typeof lead === \"string\" ? { master: lead } : {}),\n ...(platforms ? { platforms } : {}),\n };\n}\n\n/** A catalog name (a platform, or a placement id) as the platform the definition records. */\nconst platformOf = (name: string) => AD_PLACEMENTS.find((p) => p.id === name)?.platform ?? name;\nconst sameList = (a: readonly string[], b: readonly string[]) => a.length === b.length && a.every((x, i) => x === b[i]);\nconst sameSet = (a: readonly string[], b: readonly string[]) => a.length === b.length && a.every((x) => b.includes(x));\n\n/**\n * The sizes the canvas should deliver for what its definition now says, or null when it already\n * does (or the definition names no platforms: nothing is re-planned for a creative made before them).\n * The same platforms keep the canvas's own names (a placement chosen alone stays alone) and take the\n * definition's sizes as asked; other platforms take their own sizes.\n */\nexport function sizesToReplan(canvas: unknown, definition: DefinitionDelivery): StaticDelivery | null {\n const named = definition.platforms;\n if (!named || named.length === 0) return null;\n const planned = plannedOn(canvas);\n if (!planned) return null;\n const same = planned.platforms !== undefined && sameList([...new Set(planned.platforms.map(platformOf))], named);\n const target = same ? staticDeliveryOf(planned.platforms ?? named, definition.formats) : staticDeliveryOf(named);\n if (target.formats.length === 0) return null;\n // A canvas made before platforms records no lead: its master was the feed size, as the platform's.\n // On one picture a wide lead beside tall sizes is recorded as the tall size it is drawn at.\n const lead = planned.shape === \"plate\" ? plateDrawnLead(target.formats, target.lead) : target.lead;\n const unchanged =\n sameSet(target.formats, planned.formats) && (planned.master === undefined || planned.master === lead);\n return unchanged ? null : target;\n}\n\n/** The canvas rebuilt to deliver `target`'s sizes, or why it cannot be here. */\nexport function replanStaticCanvas(canvas: unknown, target: StaticDelivery): { canvas: unknown } | { refused: string } {\n const series = seriesOf(canvas);\n if (series) {\n return {\n refused: `This ad is one of the series led by ${series.lead}: its sizes are the lead's. Change where ${series.lead} runs.`,\n };\n }\n if (isNativeCanvas(canvas)) {\n return {\n refused: \"A native screen's sizes are drawn from its canvas: scaffold it again with --platforms to change them.\",\n };\n }\n const holder = canvas as { nodes?: unknown; metadata?: { description?: unknown } };\n const old = renderGraph(holder);\n if (!old) return { refused: \"This canvas was built by hand: change its sizes on the canvas itself.\" };\n const prefilter = nodesOf(canvas).find((n) => n.tags?.role === VARIANT_PREFILTER_ROLE);\n const shape = MASTER_SHAPES.find((s) => s === prefilter?.params?.master_shape) as MasterShape | undefined;\n // The ad set's own placements (not the catalog's) stay; the catalog's are the new platforms'.\n const viewer = (old.placements ?? []).filter((p) => !AD_PLACEMENTS.some((c) => c.id === p));\n const placements =\n viewer.length > 0\n ? [...new Set([...viewer, ...target.placements.filter((p) => !p.startsWith(\"meta_\"))])]\n : target.placements;\n const plan = planStaticFormats(String(old.template.params?.model ?? \"\"), target.formats, {\n masterShape: shape ?? DEFAULT_MASTER_SHAPE,\n ...(placements.length > 0 ? { placements } : {}),\n lead: target.lead,\n platforms: target.platforms,\n });\n const rebuilt = rebuildRenderPart(holder, { ...old, ...(placements.length > 0 ? { placements } : {}) }, plan);\n return { canvas: rebuilt as { nodes: NodeDecl[] } };\n}\n"],"mappings":"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","names":["text","changed","text","ref","named","list","changed","text","plannedPlacements","changed","list","text","named","nodesOf","plannedPlacements","text","record","named","text","path","named","text","loadBearing","ref","UNCOMPILED","list","renderGraph","text","ref","parseDocument","parseDocument","text","named","json","fromTokens","json","named","nodesOf","readdir","readFile","path","readFile","path","readdir","readFile","path","z","text","changed","ref","text","named","changed","nodesOf","readFile","path","changed","ids","ref","text","list","z","z","text","isCast","z","z","NAMES","named","text","z","z","refId","changed","text","span","clip","isCast","refId","z","text","text","z","clip","text","clip","showsPeople","text","readFile","readdir","writeFile","path","readFile","writeFile","path","changed","writeFile","path","readFile","readdir","readFile","path","readFile","path","ref","readdir","mkdir","readFile","writeFile","path","z","z","path","readFile","mkdir","writeFile","createHash","mkdir","readFile","writeFile","path","z","Answer","z","path","createHash","readFile","mkdir","writeFile","text","quotes","text","readdir","readFile","path","text","readFile","path","readdir","readFile","writeFile","readFile","writeFile","readdir","readFile","writeFile","path","createHash","mkdir","readFile","writeFile","path","createHash","mkdir","readFile","writeFile","path","z","z","Answer","text","records","text","named","records","unheld","_","path","createHash","readFile","mkdir","writeFile","path","createHash","readFile","text","mkdir","writeFile","path","path","readFile","path","path","readFile","text","CARRY_WORDS","named","SURVIVES","norm","text","named","readFile","writeFile","path","nodesOf","sameList","named","renderGraph","path","readFile","writeFile","json","readFile","path","records","named","readdir","quotes","text","writeFile"]}
|