@field/cascade 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. package/AGENTS.md +7 -4
  2. package/ARCHITECTURE.md +5 -4
  3. package/CHANGELOG.md +195 -0
  4. package/README.md +1 -1
  5. package/dist/assets/AgentPanel-1JugFjE4.css +1 -0
  6. package/dist/assets/AgentPanel-BDL5MddA.js +5 -0
  7. package/dist/assets/{CodeEditor-4O7FQ__R.js → CodeEditor-C-xYG-Wn.js} +120 -120
  8. package/dist/assets/CodePanel-CtXd50m6.js +2 -0
  9. package/dist/assets/CookInfoPanel-B3NMhKJF.css +1 -0
  10. package/dist/assets/CookInfoPanel-DG4_TRsX.js +2 -0
  11. package/dist/assets/CustomNodeDialog-CHfZUs-r.js +1 -0
  12. package/dist/assets/DefinitionNode-CaRTXQ_b.js +1 -0
  13. package/dist/assets/DefinitionPanel-C3CxZY9r.js +1 -0
  14. package/dist/assets/DefinitionPanel-VNLnAiQD.css +1 -0
  15. package/dist/assets/OpenGraphDialog-BLdr6k_q.js +1 -0
  16. package/dist/assets/ProjectSettings-ZnvmIAir.js +2 -0
  17. package/dist/assets/{SettingsDialog-Bz8JxISH.js → SettingsDialog-CBX3Wa87.js} +1 -1
  18. package/dist/assets/TimelinePanel-CDeR0arY.css +1 -0
  19. package/dist/assets/TimelinePanel-CWgnFH1e.js +1 -0
  20. package/dist/assets/{VersionHistoryDialog-D5Z0nJ5-.js → VersionHistoryDialog-BOSoW1R-.js} +1 -1
  21. package/dist/assets/assert-BO2_erPD.js +1 -0
  22. package/dist/assets/assert-hvykGCnP.js +1 -0
  23. package/dist/assets/builder-BmBKcDix.js +1 -0
  24. package/dist/assets/camera-DFF7YA3F.js +1 -0
  25. package/dist/assets/checks-DAvyO9Gf.js +1 -0
  26. package/dist/assets/contactSheet-N1NcaWxw.js +2 -0
  27. package/dist/assets/{core-Yqi0Ni61.js → core-DB-MkGjj.js} +3 -4
  28. package/dist/assets/coreTypes-DtnDATZ7.js +1 -0
  29. package/dist/assets/{cssMode-CxUzc4vp.js → cssMode-DPVckSOc.js} +1 -1
  30. package/dist/assets/definitions-B227e7f_.js +1 -0
  31. package/dist/assets/definitions-D0WOUJd7.js +1 -0
  32. package/dist/assets/{editor.api-BNFb25CX.js → editor.api-Dkutg_Z1.js} +1 -1
  33. package/dist/assets/expressions-X-Z-GrgW.js +5 -0
  34. package/dist/assets/file-DAL6IfjV.js +1 -0
  35. package/dist/assets/filters-D3k1LRMa.js +1 -0
  36. package/dist/assets/{freemarker2-0ZDnWxeM.js → freemarker2-CLiLKk3B.js} +1 -1
  37. package/dist/assets/generators-BhDxRAFC.js +1 -0
  38. package/dist/assets/geo-BsMImJIJ.js +1 -0
  39. package/dist/assets/geo-C4YngDob.js +2 -0
  40. package/dist/assets/{handlebars-Cy18MoaD.js → handlebars-CcD3aMeL.js} +1 -1
  41. package/dist/assets/{html-B-2Dx7nq.js → html-DvZWGfqb.js} +1 -1
  42. package/dist/assets/{htmlMode-DUAc9B_d.js → htmlMode-DUD3VaoN.js} +1 -1
  43. package/dist/assets/image-0SfH-snh.js +1 -0
  44. package/dist/assets/image-Ck-RdGU4.js +2 -0
  45. package/dist/assets/index-BWnrmIB9.js +137 -0
  46. package/dist/assets/index-DIaxEONI.css +1 -0
  47. package/dist/assets/io-BGmt2g0D.js +1 -0
  48. package/dist/assets/{javascript-DeQsDqP5.js → javascript-Cap2ahgh.js} +1 -1
  49. package/dist/assets/{jsonMode-BiFwJVSk.js → jsonMode-B0uLjp9C.js} +1 -1
  50. package/dist/assets/{liquid-BLoHH68a.js → liquid-CnxwhfLn.js} +1 -1
  51. package/dist/assets/{lspLanguageFeatures-CNFgm1Kv.js → lspLanguageFeatures-Dn9hlKX6.js} +1 -1
  52. package/dist/assets/math-GeULS-sk.js +1 -0
  53. package/dist/assets/{mdx-CFXQVNfs.js → mdx-BV3jbrVa.js} +1 -1
  54. package/dist/assets/pop-KMF_qloi.js +1 -0
  55. package/dist/assets/preload-helper-Czpn1I53.js +1 -0
  56. package/dist/assets/{python-Cf7S7p2E.js → python-CGyFk4XK.js} +1 -1
  57. package/dist/assets/{razor-CMHBcG-g.js → razor-CQfzX3-N.js} +1 -1
  58. package/dist/assets/remap-5SjXQU-q.js +1 -0
  59. package/dist/assets/renderMarkdown-ork0Oir7.js +67 -0
  60. package/dist/assets/studioImages-CAyH-0Pl.js +1 -0
  61. package/dist/assets/text-ZpX7qNkx.js +2 -0
  62. package/dist/assets/time-P_OiBhcf.js +1 -0
  63. package/dist/assets/{tsMode-BEih0GDj.js → tsMode-BOeXzO9H.js} +1 -1
  64. package/dist/assets/{typescript-COEKYD_a.js → typescript-J1SnE_Tu.js} +1 -1
  65. package/dist/assets/{workers-BNhAhMNn.js → workers-CYwwTiVF.js} +1 -1
  66. package/dist/assets/{xml-CPiMpnPl.js → xml-DnPRNzK9.js} +1 -1
  67. package/dist/assets/{yaml-Bgp1ITLR.js → yaml-BmmYBNa9.js} +1 -1
  68. package/dist/cli/DefinitionNode-P7AA4TAU.js +15 -0
  69. package/dist/cli/{Graph-ZJJTRQTM.js → Graph-OB6EWSGL.js} +12 -12
  70. package/dist/cli/assert-GROGQNCQ.js +25 -0
  71. package/dist/cli/checks-3WB44XBL.js +189 -0
  72. package/dist/cli/{chunk-RQZ4SX5R.js → chunk-2JEU3MGB.js} +2 -2
  73. package/dist/cli/{chunk-WKURDVYP.js → chunk-3RXL5GHB.js} +28 -331
  74. package/dist/cli/chunk-53LGFPWX.js +138 -0
  75. package/dist/cli/chunk-5ORUQ6ES.js +267 -0
  76. package/dist/cli/chunk-73S4JZXK.js +336 -0
  77. package/dist/cli/{chunk-YAT5Y25U.js → chunk-7QE2ZNSN.js} +3 -3
  78. package/dist/cli/{chunk-SGJAET2L.js → chunk-BPODRH52.js} +8 -4
  79. package/dist/cli/{chunk-XWDSKG7N.js → chunk-BZ63XQ3I.js} +2 -2
  80. package/dist/cli/{chunk-FCDXJ6EK.js → chunk-CTPLRSWF.js} +2 -13
  81. package/dist/cli/chunk-EU4ZFZ7Y.js +122 -0
  82. package/dist/cli/{chunk-WIH4TEIS.js → chunk-EZRWJ4G2.js} +1 -1
  83. package/dist/cli/{chunk-BIJO5OFS.js → chunk-FWMSGKEH.js} +1 -1
  84. package/dist/cli/{chunk-POMMNKZZ.js → chunk-G23A2BZZ.js} +38 -5
  85. package/dist/cli/{chunk-35D343DC.js → chunk-GRIN2DDP.js} +19 -1
  86. package/dist/cli/chunk-JVOCK5W4.js +83 -0
  87. package/dist/cli/chunk-KBGUO27Q.js +15 -0
  88. package/dist/cli/{chunk-GFS6W3C5.js → chunk-L6B6FUQP.js} +54 -32
  89. package/dist/cli/chunk-LTXWBXOM.js +438 -0
  90. package/dist/cli/chunk-MI5JLQYA.js +220 -0
  91. package/dist/cli/{chunk-EUIAC3U3.js → chunk-MP653A5O.js} +884 -124
  92. package/dist/cli/{chunk-A4OAMOZH.js → chunk-NJFMDXHR.js} +13 -3
  93. package/dist/cli/{chunk-3JTJHF7V.js → chunk-OM6BEME6.js} +4 -4
  94. package/dist/cli/{chunk-DUIUFVU2.js → chunk-ST6LROUG.js} +49 -23
  95. package/dist/cli/{chunk-RLCAJBVR.js → chunk-TJW67QSI.js} +8 -7
  96. package/dist/cli/chunk-WGKPJZDY.js +364 -0
  97. package/dist/cli/{chunk-D6BUOHUG.js → chunk-X4WKAOQP.js} +4 -4
  98. package/dist/cli/{chunk-VVGSLVSF.js → chunk-X566FWBV.js} +6 -1
  99. package/dist/cli/chunk-YH637PDL.js +317 -0
  100. package/dist/cli/chunk-ZSCUZE6I.js +112 -0
  101. package/dist/cli/{cliCommands-UQSFGEHF.js → cliCommands-JJN5Z3ZC.js} +23 -17
  102. package/dist/cli/{commands-Q23M26QM.js → commands-PHYFYA3F.js} +129 -47
  103. package/dist/cli/contactSheet-2PQVRUFW.js +11 -0
  104. package/dist/cli/{definitions-HF2FTHYU.js → definitions-BPOPW52L.js} +7 -7
  105. package/dist/cli/{doctorCommand-B7BPQMN6.js → doctorCommand-ORWQRNYP.js} +36 -6
  106. package/dist/cli/{edit-JHCPTQFT.js → edit-S5KEQ5RA.js} +3 -3
  107. package/dist/cli/editorCommands-NFR32JOY.js +41 -0
  108. package/dist/cli/{encode-HAUZTYPT.js → encode-ICPEPMH5.js} +2 -2
  109. package/dist/cli/file-3HTQHPYQ.js +41 -0
  110. package/dist/cli/filters-6ODFWYK4.js +379 -0
  111. package/dist/cli/generators-YU7GB4MD.js +210 -0
  112. package/dist/cli/{geo-4RNK3QVN.js → geo-6ZPGKZRU.js} +7 -7
  113. package/dist/cli/{graphCommands-6BMAKGQE.js → graphCommands-EOUOBOIJ.js} +4 -4
  114. package/dist/cli/{graphFile-VPSQ6OF7.js → graphFile-YTGJB5F5.js} +25 -19
  115. package/dist/cli/{headlessCanvas-5XLDZT7M.js → headlessCanvas-ENRHC7GS.js} +3 -2
  116. package/dist/cli/{helpCommand-3VRE3KVO.js → helpCommand-PULH6ZYB.js} +9 -7
  117. package/dist/cli/image-TXELZZK5.js +55 -0
  118. package/dist/cli/index.js +14 -14
  119. package/dist/cli/{math-ZRMLKU2D.js → math-RSYRQ3C6.js} +5 -5
  120. package/dist/cli/{mcp-ZLEEMYGF.js → mcp-JVZFQOEX.js} +4 -4
  121. package/dist/cli/{parity-KINARCP2.js → parity-X6DEH2DV.js} +42 -36
  122. package/dist/cli/{pop-USDFXB7H.js → pop-B7SIIYKN.js} +5 -5
  123. package/dist/cli/project-VYGIA7JX.js +12 -0
  124. package/dist/cli/{projectDefinition-DMTZN2NE.js → projectDefinition-F3D7UIHJ.js} +8 -8
  125. package/dist/cli/{projectRuntime-Z5PJOH47.js → projectRuntime-2Q4JKEH3.js} +19 -12
  126. package/dist/cli/registerStandardNodes-BXJCB6E4.js +744 -0
  127. package/dist/cli/{render-YURAPPUI.js → render-PT4MWI6U.js} +24 -22
  128. package/dist/cli/{runCommand-PI764LEG.js → runCommand-HNPQVZMS.js} +3 -3
  129. package/dist/cli/runner-5XPXVW7J.js +43 -0
  130. package/dist/cli/runtime/image.ts +27 -2
  131. package/dist/cli/runtime/io.ts +78 -0
  132. package/dist/cli/share-MHF6TNRK.js +166 -0
  133. package/dist/cli/stageCache-TY2BFZJR.js +15 -0
  134. package/dist/cli/{stageRunner-KUNIMQKJ.js → stageRunner-KY2EJP7X.js} +2 -2
  135. package/dist/cli/text-MB3EKR4H.js +126 -0
  136. package/dist/cli/{verbs-RCE3K4VQ.js → verbs-PI2JH5FI.js} +2 -2
  137. package/dist/cli/webBuild-WPPMGGW7.js +44 -0
  138. package/dist/contracts/capabilities.d.ts +18 -1
  139. package/dist/contracts/color.d.ts +8 -0
  140. package/dist/contracts/color.js +23 -0
  141. package/dist/contracts/definition.d.ts +10 -0
  142. package/dist/contracts/schema.d.ts +1 -1
  143. package/dist/contracts/schema.js +1 -0
  144. package/dist/contracts/validate.js +11 -1
  145. package/dist/contracts/values.d.ts +24 -0
  146. package/dist/image.d.ts +15 -0
  147. package/dist/image.js +36 -2
  148. package/dist/index.html +8 -2
  149. package/dist/io.d.ts +29 -0
  150. package/dist/io.js +40 -0
  151. package/dist/player/app.js +3 -2
  152. package/dist/player/editor.js +3 -2
  153. package/dist/player/editorEngine.js +3 -2
  154. package/dist/runtime/builtins/assert/checks.d.ts +18 -0
  155. package/dist/runtime/builtins/assert/checks.js +207 -0
  156. package/dist/runtime/builtins/assert/definitions.d.ts +130 -0
  157. package/dist/runtime/builtins/assert/definitions.js +54 -0
  158. package/dist/runtime/builtins/assert/index.d.ts +152 -0
  159. package/dist/runtime/builtins/assert/index.js +36 -0
  160. package/dist/runtime/builtins/image/contactSheet.d.ts +3 -165
  161. package/dist/runtime/builtins/image/contactSheet.js +0 -49
  162. package/dist/runtime/builtins/image/definitions.d.ts +950 -0
  163. package/dist/runtime/builtins/image/definitions.js +343 -0
  164. package/dist/runtime/builtins/image/file.d.ts +8 -0
  165. package/dist/runtime/builtins/image/file.js +37 -0
  166. package/dist/runtime/builtins/image/filters.d.ts +8 -0
  167. package/dist/runtime/builtins/image/filters.js +394 -0
  168. package/dist/runtime/builtins/image/generators.d.ts +7 -0
  169. package/dist/runtime/builtins/image/generators.js +144 -0
  170. package/dist/runtime/builtins/image/index.d.ts +947 -4
  171. package/dist/runtime/builtins/image/index.js +41 -6
  172. package/dist/runtime/builtins/image/io.d.ts +100 -0
  173. package/dist/runtime/builtins/image/io.js +142 -0
  174. package/dist/runtime/builtins/image/planar.d.ts +55 -0
  175. package/dist/runtime/builtins/image/planar.js +274 -0
  176. package/dist/runtime/builtins/image/simplex.d.ts +22 -0
  177. package/dist/runtime/builtins/image/simplex.js +92 -0
  178. package/dist/runtime/builtins/image/text.d.ts +4 -0
  179. package/dist/runtime/builtins/image/text.js +141 -0
  180. package/dist/runtime/builtins/index.d.ts +3 -0
  181. package/dist/runtime/builtins/index.js +7 -0
  182. package/dist/runtime/gpu.d.ts +25 -0
  183. package/dist/runtime/gpu.js +40 -0
  184. package/dist/runtime/runtime.d.ts +2 -0
  185. package/dist/runtime/runtime.js +268 -44
  186. package/dist/runtime/types.d.ts +30 -0
  187. package/doc/CLI_REFERENCE.md +21 -3
  188. package/doc/EDITOR_EXPORT.md +26 -0
  189. package/doc/MCP.md +2 -1
  190. package/doc/NODE_REFERENCE.md +286 -14
  191. package/doc/PROJECT_AUTHORING.md +98 -3
  192. package/package.json +4 -1
  193. package/dist/assets/CodePanel-BU-autmq.js +0 -2
  194. package/dist/assets/CustomNodeDialog-BRpDfOV5.js +0 -1
  195. package/dist/assets/OpenGraphDialog-BwbRlC0X.js +0 -1
  196. package/dist/assets/ProjectSettings-DLOXLxcA.js +0 -2
  197. package/dist/assets/definitions-GreEMXLV.js +0 -1
  198. package/dist/assets/geo-u0n_jOsD.js +0 -1
  199. package/dist/assets/image-cAa-Nu9O.js +0 -2062
  200. package/dist/assets/index-5ZtDAuy2.js +0 -220
  201. package/dist/assets/index-7vae6YFC.css +0 -1
  202. package/dist/assets/math-DioIQOPJ.js +0 -1
  203. package/dist/assets/pop-DC_TQG9t.js +0 -1
  204. package/dist/cli/chunk-36P5K3SD.js +0 -631
  205. package/dist/cli/chunk-4UDFYF5G.js +0 -132
  206. package/dist/cli/chunk-53NMBJAO.js +0 -35
  207. package/dist/cli/chunk-MIIEFUGG.js +0 -623
  208. package/dist/cli/chunk-QBBKRNGY.js +0 -90
  209. package/dist/cli/chunk-WPUDGEFY.js +0 -20
  210. package/dist/cli/editorCommands-UIF5YLUZ.js +0 -33
  211. package/dist/cli/project-K3QIPGBB.js +0 -12
  212. package/dist/cli/registerStandardNodes-S2VLMF6J.js +0 -3081
  213. package/dist/cli/runner-RA6UKEPD.js +0 -37
  214. package/dist/cli/webBuild-GT4PZT5D.js +0 -37
  215. package/dist/runtime/builtins/headless.d.ts +0 -19
  216. package/dist/runtime/builtins/headless.js +0 -25
@@ -1,62 +1,65 @@
1
1
  import {
2
- RunTrace
3
- } from "./chunk-4UDFYF5G.js";
4
- import {
5
- installProjectStages
6
- } from "./chunk-QBBKRNGY.js";
2
+ sceneDocument
3
+ } from "./chunk-73S4JZXK.js";
7
4
  import {
8
5
  setEmbeddedCompiler,
9
6
  setProjectModuleCompiler
10
7
  } from "./chunk-2KXB47FP.js";
11
8
  import {
12
- sceneDocument
13
- } from "./chunk-WKURDVYP.js";
14
- import "./chunk-3JTJHF7V.js";
9
+ installHeadlessCanvas
10
+ } from "./chunk-EZRWJ4G2.js";
11
+ import "./chunk-3RXL5GHB.js";
12
+ import "./chunk-OM6BEME6.js";
15
13
  import {
16
- cascadeVersion,
17
- compileEmbedded,
18
- compileProjectModule
19
- } from "./chunk-MIIEFUGG.js";
20
- import "./chunk-WPUDGEFY.js";
21
- import "./chunk-VVGSLVSF.js";
22
- import "./chunk-WD62JIP6.js";
14
+ composeContactSheet
15
+ } from "./chunk-53LGFPWX.js";
23
16
  import {
17
+ RunTrace,
24
18
  cookProjectGraph,
25
19
  installProjectIo,
20
+ installProjectStages,
26
21
  moduleId,
27
22
  projectModuleFile
28
- } from "./chunk-EUIAC3U3.js";
29
- import {
30
- composeContactSheet
31
- } from "./chunk-36P5K3SD.js";
32
- import "./chunk-D6BUOHUG.js";
23
+ } from "./chunk-MP653A5O.js";
24
+ import "./chunk-MI5JLQYA.js";
25
+ import "./chunk-GRIN2DDP.js";
26
+ import "./chunk-X4WKAOQP.js";
27
+ import "./chunk-DEQSEFFH.js";
33
28
  import "./chunk-RXDIMXN5.js";
34
29
  import "./chunk-QQPA2ZHH.js";
35
30
  import "./chunk-KH4MUBKF.js";
36
- import "./chunk-35D343DC.js";
37
- import "./chunk-DEQSEFFH.js";
38
31
  import "./chunk-HSNOBIVT.js";
39
- import {
40
- imagePath
41
- } from "./chunk-ICH7N5PN.js";
42
32
  import {
43
33
  graphSeed
44
- } from "./chunk-GFS6W3C5.js";
34
+ } from "./chunk-L6B6FUQP.js";
45
35
  import "./chunk-HFHWYL55.js";
36
+ import "./chunk-KBGUO27Q.js";
37
+ import {
38
+ imagePath
39
+ } from "./chunk-ICH7N5PN.js";
46
40
  import "./chunk-CO22XHNG.js";
41
+ import "./chunk-LTXWBXOM.js";
42
+ import "./chunk-BZ63XQ3I.js";
43
+ import {
44
+ compileEmbedded,
45
+ compileProjectModule
46
+ } from "./chunk-EU4ZFZ7Y.js";
47
+ import "./chunk-YH637PDL.js";
48
+ import "./chunk-X566FWBV.js";
49
+ import "./chunk-WD62JIP6.js";
50
+ import {
51
+ cascadeVersion
52
+ } from "./chunk-5ORUQ6ES.js";
47
53
  import {
48
54
  ProjectRoot
49
- } from "./chunk-RQZ4SX5R.js";
50
- import "./chunk-A4OAMOZH.js";
55
+ } from "./chunk-2JEU3MGB.js";
56
+ import "./chunk-NJFMDXHR.js";
51
57
  import "./chunk-J7VK7MNF.js";
52
- import "./chunk-XWDSKG7N.js";
53
- import "./chunk-BIJO5OFS.js";
54
- import {
55
- installHeadlessCanvas
56
- } from "./chunk-WIH4TEIS.js";
58
+ import "./chunk-FWMSGKEH.js";
59
+ import "./chunk-JVOCK5W4.js";
57
60
 
58
61
  // src/cli/locks/commands.ts
59
- import path7 from "node:path";
62
+ import path8 from "node:path";
60
63
 
61
64
  // src/cli/locks/lock.ts
62
65
  import { execFile as execFile2 } from "node:child_process";
@@ -1001,6 +1004,69 @@ async function exists2(file) {
1001
1004
  }
1002
1005
  }
1003
1006
 
1007
+ // src/cli/locks/ladderCard.ts
1008
+ import fs6 from "node:fs/promises";
1009
+ import path7 from "node:path";
1010
+ var MAX_CHOICE_OPTIONS = 8;
1011
+ function checkCardSize(count) {
1012
+ if (count > MAX_CHOICE_OPTIONS) {
1013
+ throw new Error(`--cairn shows at most ${MAX_CHOICE_OPTIONS} options on a choice card (this ladder has ${count}); ladder fewer variants`);
1014
+ }
1015
+ }
1016
+ function pickValue(ladderId, index) {
1017
+ return `pick:${ladderId}:${index}`;
1018
+ }
1019
+ function choiceLabel(variant, seedVaried) {
1020
+ const parts = Object.entries(variant.set).map(([key, value]) => `${key}=${typeof value === "string" ? value : JSON.stringify(value)}`);
1021
+ if (seedVaried) parts.push(`seed ${variant.seed}`);
1022
+ return parts.join(", ");
1023
+ }
1024
+ async function writeLadderCard(root, ladder, directory, vault) {
1025
+ checkCardSize(ladder.variants.length);
1026
+ const target = path7.resolve(directory);
1027
+ const vaultRoot = vault ? path7.resolve(vault) : await findVault(target);
1028
+ const relative = path7.relative(vaultRoot, target);
1029
+ if (relative.startsWith("..") || path7.isAbsolute(relative)) throw new Error(`--cairn ${target} is not inside the vault ${vaultRoot}`);
1030
+ await fs6.mkdir(target, { recursive: true });
1031
+ const seedVaried = Boolean(ladder.seeds);
1032
+ const files = [];
1033
+ const options = [];
1034
+ for (const variant of ladder.variants) {
1035
+ const file = path7.join(target, `${ladder.id}-${String(variant.index).padStart(2, "0")}${path7.extname(variant.image).toLowerCase()}`);
1036
+ await fs6.copyFile(path7.join(root, variant.image), file);
1037
+ files.push(file);
1038
+ options.push({
1039
+ label: choiceLabel(variant, seedVaried) || `variant ${variant.index}`,
1040
+ value: pickValue(ladder.id, variant.index),
1041
+ image: path7.relative(vaultRoot, file).split(path7.sep).join("/")
1042
+ });
1043
+ }
1044
+ const choice = { prompt: `${ladder.name}: which one? (ladder ${ladder.id}, ${ladder.graph.file} ${ladder.graph.node})`, options };
1045
+ return { choice, fence: choiceFence(choice), vault: vaultRoot, files };
1046
+ }
1047
+ function choiceFence(choice) {
1048
+ return `\`\`\`cairn:choice
1049
+ ${JSON.stringify(choice)}
1050
+ \`\`\``;
1051
+ }
1052
+ async function findVault(start) {
1053
+ for (const marker of [".obsidian", ".git"]) {
1054
+ for (let directory = start; ; directory = path7.dirname(directory)) {
1055
+ if (await exists3(path7.join(directory, marker))) return directory;
1056
+ if (path7.dirname(directory) === directory) break;
1057
+ }
1058
+ }
1059
+ throw new Error(`--cairn ${start}: no vault above it (no .obsidian or .git); name it with --vault <dir>`);
1060
+ }
1061
+ async function exists3(file) {
1062
+ try {
1063
+ await fs6.access(file);
1064
+ return true;
1065
+ } catch {
1066
+ return false;
1067
+ }
1068
+ }
1069
+
1004
1070
  // src/cli/locks/commands.ts
1005
1071
  var LOCK_COMMANDS = ["lock", "locks", "replay", "ladder", "pick"];
1006
1072
  var LOCK_HELP = `
@@ -1031,13 +1097,18 @@ Ladders: three to five options side by side, and a lock at approval.
1031
1097
 
1032
1098
  cascade ladder <graph> <node> --name <name> [--vary <node.prop>=<a,b,c>]...
1033
1099
  [--seeds <a,b,c>] [--columns N] [--port <output>]... [--input <file>]...
1034
- [--note <text>] [--live] [--json]
1100
+ [--note <text>] [--live] [--cairn <vault dir> [--vault <dir>]] [--json]
1035
1101
  Cook <node> once per variant and write ladders/<id>/<n>.png, a labelled
1036
1102
  contact sheet ladders/<id>/sheet.png, and the record ladders/<id>.json
1037
1103
  (per variant: graph, params, seed, inputs, output fingerprint; the
1038
1104
  stored code and git commit once). Values are a JSON list without its
1039
1105
  brackets (0.5,1,2 or [1,2],[3,4]); lists are zipped, one value applies
1040
1106
  to every variant. Cooks from the stored code in a fresh copy unless --live.
1107
+ --cairn copies each variant to <dir>/<id>-<nn>.png (a space's
1108
+ _attachments/ladders/<id>/) and prints a cairn:choice card (--json:
1109
+ data.cairnChoice) whose images are relative to the vault (the nearest
1110
+ .obsidian or .git above, or --vault); at most 8 variants. A tap answers
1111
+ "Picked: <label> (pick:<id>:<n>)": run cascade pick <id> <n>.
1041
1112
 
1042
1113
  cascade pick <ladder-id | ladders/<id>.json> <n> [--name <lock name>] [--note <text>]
1043
1114
  [--status approved] [--supersedes <id>] [--project <dir>] [--json]
@@ -1130,9 +1201,9 @@ async function replayCommand(parsed, json, print) {
1130
1201
  if (result.status !== "match") process.exitCode = 1;
1131
1202
  }
1132
1203
  async function verifyCommand(parsed, json, print) {
1133
- const root = path7.resolve(one(parsed, "--project") ?? process.cwd());
1204
+ const root = path8.resolve(one(parsed, "--project") ?? process.cwd());
1134
1205
  const locks = parsed.positional.length ? await Promise.all(parsed.positional.map(async (id) => (await readLock(root, id)).lock)) : await listLocks(root);
1135
- if (!locks.length) throw new Error(`No locks in ${path7.join(root, "locks")}`);
1206
+ if (!locks.length) throw new Error(`No locks in ${path8.join(root, "locks")}`);
1136
1207
  const results = [];
1137
1208
  for (const lock of locks) {
1138
1209
  try {
@@ -1157,7 +1228,7 @@ ${results.length - failed} of ${results.length} locks reproduce${failed ? `; ${f
1157
1228
  if (failed) process.exitCode = 1;
1158
1229
  }
1159
1230
  async function locksCommand(parsed, json, print) {
1160
- const root = path7.resolve(parsed.positional[0] ?? one(parsed, "--project") ?? process.cwd());
1231
+ const root = path8.resolve(parsed.positional[0] ?? one(parsed, "--project") ?? process.cwd());
1161
1232
  const locks = await listLocks(root);
1162
1233
  if (json) {
1163
1234
  return print({
@@ -1176,7 +1247,7 @@ async function locksCommand(parsed, json, print) {
1176
1247
  }))
1177
1248
  });
1178
1249
  }
1179
- if (!locks.length) return console.log(`No locks in ${path7.join(root, "locks")}`);
1250
+ if (!locks.length) return console.log(`No locks in ${path8.join(root, "locks")}`);
1180
1251
  const width = Math.max(...locks.map((lock) => lock.id.length));
1181
1252
  for (const lock of locks) {
1182
1253
  const commit = lock.versions.project.commit ? ` @${lock.versions.project.commit.slice(0, 7)}${lock.versions.project.dirty ? "+" : ""}` : "";
@@ -1195,6 +1266,9 @@ async function ladderCommand(parsed, json, print) {
1195
1266
  vary[pair.slice(0, at)] = parseValues(pair.slice(at + 1));
1196
1267
  }
1197
1268
  const seedsText = one(parsed, "--seeds");
1269
+ const seeds = seedsText === void 0 ? void 0 : seedsText.split(",").map((text) => seedValue(text.trim()));
1270
+ const cairn = one(parsed, "--cairn");
1271
+ if (cairn) checkCardSize(Math.max(0, ...Object.values(vary).map((values) => values.length), seeds?.length ?? 0));
1198
1272
  const columns = one(parsed, "--columns");
1199
1273
  const { ladder, file } = await createLadder({
1200
1274
  graph,
@@ -1202,27 +1276,35 @@ async function ladderCommand(parsed, json, print) {
1202
1276
  name,
1203
1277
  note: one(parsed, "--note"),
1204
1278
  vary,
1205
- seeds: seedsText === void 0 ? void 0 : seedsText.split(",").map((text) => seedValue(text.trim())),
1279
+ seeds,
1206
1280
  columns: columns === void 0 ? void 0 : Number(columns),
1207
1281
  ports: parsed.values.get("--port"),
1208
1282
  inputs: parsed.values.get("--input"),
1209
1283
  live: parsed.switches.has("--live"),
1210
1284
  verbose: parsed.switches.has("--verbose")
1211
1285
  });
1212
- const root = path7.dirname(path7.dirname(file));
1286
+ const root = path8.dirname(path8.dirname(file));
1287
+ const card = cairn ? await writeLadderCard(root, ladder, cairn, one(parsed, "--vault")) : void 0;
1213
1288
  if (json) {
1214
1289
  return print({
1215
1290
  status: "laddered",
1216
1291
  file,
1217
- sheet: path7.join(root, ladder.sheet.file),
1218
- variants: ladder.variants.map((variant) => ({ index: variant.index, label: variant.label, image: path7.join(root, variant.image), set: variant.set, seed: variant.seed })),
1292
+ sheet: path8.join(root, ladder.sheet.file),
1293
+ variants: ladder.variants.map((variant) => ({ index: variant.index, label: variant.label, image: path8.join(root, variant.image), set: variant.set, seed: variant.seed })),
1294
+ ...card ? { cairnChoice: card.fence, cairn: { vault: card.vault, files: card.files, choice: card.choice } } : {},
1219
1295
  ladder
1220
1296
  });
1221
1297
  }
1222
1298
  console.log(`Ladder ${ladder.id} -> ${shown(file)}, cooked from the ${ladder.host.cooked}`);
1223
- console.log(` sheet ${shown(path7.join(root, ladder.sheet.file))}`);
1299
+ console.log(` sheet ${shown(path8.join(root, ladder.sheet.file))}`);
1224
1300
  for (const variant of ladder.variants) console.log(` ${variant.label} ${variant.image} (${seconds(variant.output.durationMs)})`);
1225
- console.log(`Pick one with: cascade pick ${ladder.id} <n>`);
1301
+ console.log(`Pick one with: cascade pick ${ladder.id} <n> --project ${root}`);
1302
+ if (card) {
1303
+ console.log(`
1304
+ Cairn choice card (images in ${shown(path8.dirname(card.files[0]))}); post it as is, and on "Picked: \u2026 (pick:${ladder.id}:<n>)" run cascade pick ${ladder.id} <n> --project ${root}:
1305
+ `);
1306
+ console.log(card.fence);
1307
+ }
1226
1308
  }
1227
1309
  async function pickCommand(parsed, json, print) {
1228
1310
  const [ladder, variant] = parsed.positional;
@@ -1272,7 +1354,7 @@ function describePort(fingerprint) {
1272
1354
  return `${fingerprint.path}${size} ${short(fingerprint.pixels ?? fingerprint.sha256)}`;
1273
1355
  }
1274
1356
  function shown(file) {
1275
- const relative = path7.relative(process.cwd(), file);
1357
+ const relative = path8.relative(process.cwd(), file);
1276
1358
  return relative.startsWith("..") ? file : relative;
1277
1359
  }
1278
1360
  function seedValue(text) {
@@ -1289,4 +1371,4 @@ export {
1289
1371
  LOCK_HELP,
1290
1372
  runLockCommand
1291
1373
  };
1292
- //# sourceMappingURL=commands-Q23M26QM.js.map
1374
+ //# sourceMappingURL=commands-PHYFYA3F.js.map
@@ -0,0 +1,11 @@
1
+ import {
2
+ composeContactSheet,
3
+ contactSheetLayout,
4
+ executeContactSheet
5
+ } from "./chunk-53LGFPWX.js";
6
+ export {
7
+ composeContactSheet,
8
+ contactSheetLayout,
9
+ executeContactSheet
10
+ };
11
+ //# sourceMappingURL=contactSheet-2PQVRUFW.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  registerDefinitionNodes
3
- } from "./chunk-SGJAET2L.js";
4
- import "./chunk-FCDXJ6EK.js";
3
+ } from "./chunk-BPODRH52.js";
4
+ import "./chunk-CTPLRSWF.js";
5
5
  import "./chunk-RUU3YWXU.js";
6
6
  import {
7
7
  cameraRegistration,
@@ -11,13 +11,13 @@ import {
11
11
  pickRegistration,
12
12
  previousRegistration,
13
13
  timeRegistration
14
- } from "./chunk-D6BUOHUG.js";
15
- import "./chunk-RXDIMXN5.js";
14
+ } from "./chunk-X4WKAOQP.js";
16
15
  import "./chunk-DEQSEFFH.js";
17
- import "./chunk-GFS6W3C5.js";
16
+ import "./chunk-RXDIMXN5.js";
17
+ import "./chunk-L6B6FUQP.js";
18
18
  import "./chunk-HFHWYL55.js";
19
19
  import "./chunk-CO22XHNG.js";
20
- import "./chunk-BIJO5OFS.js";
20
+ import "./chunk-FWMSGKEH.js";
21
21
 
22
22
  // src/nodes/core/definitions.ts
23
23
  registerDefinitionNodes([
@@ -29,4 +29,4 @@ registerDefinitionNodes([
29
29
  packRegistration,
30
30
  frozenRegistration
31
31
  ]);
32
- //# sourceMappingURL=definitions-HF2FTHYU.js.map
32
+ //# sourceMappingURL=definitions-BPOPW52L.js.map
@@ -37,18 +37,37 @@ async function doctor(root, options = {}) {
37
37
  }
38
38
  if (hasStages(root)) {
39
39
  try {
40
- const { ProjectRoot } = await import("./project-K3QIPGBB.js");
41
- const { readStageConfig } = await import("./stageRunner-KUNIMQKJ.js");
42
- const { python } = readStageConfig(new ProjectRoot(root));
40
+ const { ProjectRoot } = await import("./project-VYGIA7JX.js");
41
+ const { readStageConfig } = await import("./stageRunner-KY2EJP7X.js");
42
+ const { stageSources } = await import("./stageCache-TY2BFZJR.js");
43
+ const project = new ProjectRoot(root);
44
+ const config = readStageConfig(project);
45
+ const { python } = config;
43
46
  const version = await output(python, ["-c", "import sys; print(sys.version.split()[0], sys.executable)"], root);
44
47
  checks.push({ name: "stage interpreter", ok: true, detail: `Python ${version}` });
48
+ if (env?.state === "none") {
49
+ const sources = stageSources(project, config);
50
+ const importer = sources.files().find((file) => importsModule(project.resolveMedia(file), "numpy"));
51
+ if (importer) {
52
+ try {
53
+ await output(python, ["-c", "import numpy"], root);
54
+ checks.push({ name: "stage imports", ok: true, detail: `numpy (imported by ${importer}) loads in ${python}` });
55
+ } catch {
56
+ checks.push({
57
+ name: "stage imports",
58
+ ok: false,
59
+ detail: `${importer} imports numpy, which ${python} (Python ${version.split(" ")[0]}) does not have, and no environment is declared. Declare one in cascade.json ("python": { "requirements": ["numpy"] }) and run cascade doctor --fix, or point exec.stages.python at an interpreter that has it`
60
+ });
61
+ }
62
+ }
63
+ }
45
64
  } catch (error) {
46
65
  checks.push({ name: "stage interpreter", ok: false, detail: error instanceof Error ? error.message : String(error) });
47
66
  }
48
67
  }
49
- const { hasFfmpeg } = await import("./encode-HAUZTYPT.js");
68
+ const { hasFfmpeg } = await import("./encode-ICPEPMH5.js");
50
69
  checks.push(await hasFfmpeg() ? { name: "ffmpeg", ok: true, detail: "on the PATH" } : { name: "ffmpeg", ok: false, optional: true, detail: "not on the PATH: --mp4 and cascade render videos need it (brew install ffmpeg)" });
51
- const { canvasAvailable, CANVAS_PACKAGE } = await import("./headlessCanvas-5XLDZT7M.js");
70
+ const { canvasAvailable, CANVAS_PACKAGE } = await import("./headlessCanvas-ENRHC7GS.js");
52
71
  checks.push(await canvasAvailable() ? { name: "headless canvas", ok: true, detail: CANVAS_PACKAGE } : { name: "headless canvas", ok: false, optional: true, detail: `${CANVAS_PACKAGE} is not installed: drawing nodes cannot run headlessly (npm install ${CANVAS_PACKAGE})` });
53
72
  return checks;
54
73
  }
@@ -60,6 +79,16 @@ function hasStages(root) {
60
79
  return false;
61
80
  }
62
81
  }
82
+ function importsModule(file, module) {
83
+ let source;
84
+ try {
85
+ source = fs.readFileSync(file, "utf8");
86
+ } catch {
87
+ return false;
88
+ }
89
+ const name = module.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
90
+ return new RegExp(`^\\s*(?:import\\s+(?:[\\w.]+\\s*(?:as\\s+\\w+)?\\s*,\\s*)*${name}\\b|from\\s+${name}(?:\\.|\\s))`, "m").test(source);
91
+ }
63
92
  function output(command, args, cwd) {
64
93
  return new Promise((resolve, reject) => {
65
94
  execFile(command, args, { cwd, timeout: 3e4 }, (error, stdout, stderr) => {
@@ -71,6 +100,7 @@ function output(command, args, cwd) {
71
100
  export {
72
101
  DOCTOR_USAGE,
73
102
  doctor,
103
+ importsModule,
74
104
  runDoctorCommand
75
105
  };
76
- //# sourceMappingURL=doctorCommand-B7BPQMN6.js.map
106
+ //# sourceMappingURL=doctorCommand-ORWQRNYP.js.map
@@ -10,8 +10,8 @@ import {
10
10
  readWire,
11
11
  splitEndpoint,
12
12
  wireLabel
13
- } from "./chunk-XWDSKG7N.js";
14
- import "./chunk-BIJO5OFS.js";
13
+ } from "./chunk-BZ63XQ3I.js";
14
+ import "./chunk-FWMSGKEH.js";
15
15
  export {
16
16
  GRAPH_EDIT_OPERATIONS,
17
17
  GraphEditError,
@@ -25,4 +25,4 @@ export {
25
25
  splitEndpoint,
26
26
  wireLabel
27
27
  };
28
- //# sourceMappingURL=edit-JHCPTQFT.js.map
28
+ //# sourceMappingURL=edit-S5KEQ5RA.js.map
@@ -0,0 +1,41 @@
1
+ import {
2
+ EDITOR_COMMANDS,
3
+ EDITOR_HELP,
4
+ runEditorCommand,
5
+ sceneDocument
6
+ } from "./chunk-73S4JZXK.js";
7
+ import "./chunk-EZRWJ4G2.js";
8
+ import "./chunk-3RXL5GHB.js";
9
+ import "./chunk-OM6BEME6.js";
10
+ import "./chunk-MP653A5O.js";
11
+ import "./chunk-MI5JLQYA.js";
12
+ import "./chunk-GRIN2DDP.js";
13
+ import "./chunk-X4WKAOQP.js";
14
+ import "./chunk-DEQSEFFH.js";
15
+ import "./chunk-RXDIMXN5.js";
16
+ import "./chunk-QQPA2ZHH.js";
17
+ import "./chunk-KH4MUBKF.js";
18
+ import "./chunk-HSNOBIVT.js";
19
+ import "./chunk-L6B6FUQP.js";
20
+ import "./chunk-HFHWYL55.js";
21
+ import "./chunk-KBGUO27Q.js";
22
+ import "./chunk-ICH7N5PN.js";
23
+ import "./chunk-CO22XHNG.js";
24
+ import "./chunk-LTXWBXOM.js";
25
+ import "./chunk-BZ63XQ3I.js";
26
+ import "./chunk-YH637PDL.js";
27
+ import "./chunk-X566FWBV.js";
28
+ import "./chunk-WD62JIP6.js";
29
+ import "./chunk-5ORUQ6ES.js";
30
+ import "./chunk-2JEU3MGB.js";
31
+ import "./chunk-NJFMDXHR.js";
32
+ import "./chunk-J7VK7MNF.js";
33
+ import "./chunk-FWMSGKEH.js";
34
+ import "./chunk-JVOCK5W4.js";
35
+ export {
36
+ EDITOR_COMMANDS,
37
+ EDITOR_HELP,
38
+ runEditorCommand,
39
+ sceneDocument
40
+ };
41
+ //# sourceMappingURL=editorCommands-NFR32JOY.js.map
@@ -5,7 +5,7 @@ import {
5
5
  frameSequences,
6
6
  hasFfmpeg,
7
7
  timelineFrameSpec
8
- } from "./chunk-YAT5Y25U.js";
8
+ } from "./chunk-7QE2ZNSN.js";
9
9
  export {
10
10
  DEFAULT_CRF,
11
11
  encodeMp4,
@@ -14,4 +14,4 @@ export {
14
14
  hasFfmpeg,
15
15
  timelineFrameSpec
16
16
  };
17
- //# sourceMappingURL=encode-HAUZTYPT.js.map
17
+ //# sourceMappingURL=encode-ICPEPMH5.js.map
@@ -0,0 +1,41 @@
1
+ import {
2
+ imageReference,
3
+ output,
4
+ readPlanar,
5
+ resample
6
+ } from "./chunk-WGKPJZDY.js";
7
+
8
+ // packages/runtime/src/builtins/image/file.ts
9
+ async function executeImage(context) {
10
+ const { props } = context;
11
+ const source = await readPlanar(context, imageReference(context.inputs.image) ?? imageReference(props.file));
12
+ if (!source) return;
13
+ if (props.resolutionMode === "original") {
14
+ await output(context, source);
15
+ return;
16
+ }
17
+ if (props.resolutionMode === "max") {
18
+ const [maxWidth, maxHeight] = props.maxResolution;
19
+ const aspect = source.width / source.height;
20
+ let width2 = source.width;
21
+ let height2 = source.height;
22
+ if (width2 > maxWidth) {
23
+ width2 = maxWidth;
24
+ height2 = maxWidth / aspect;
25
+ }
26
+ if (height2 > maxHeight) {
27
+ height2 = maxHeight;
28
+ width2 = maxHeight * aspect;
29
+ }
30
+ width2 = Math.round(width2);
31
+ height2 = Math.round(height2);
32
+ await output(context, width2 !== source.width || height2 !== source.height ? resample(source, width2, height2) : source);
33
+ return;
34
+ }
35
+ const [width, height] = props.fixedResolution;
36
+ await output(context, resample(source, width, height));
37
+ }
38
+ export {
39
+ executeImage
40
+ };
41
+ //# sourceMappingURL=file-3HTQHPYQ.js.map