stillmade-sdk 0.1.41 → 0.1.43

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 (285) hide show
  1. package/.stillmade/sdk-baseline.json +19 -21
  2. package/AGENTS.md +17 -12
  3. package/FRAME_VIEWS.md +113 -0
  4. package/INTERFACE_DESIGN.md +67 -22
  5. package/MOBILE_UI.md +4 -2
  6. package/MODULES.md +152 -6
  7. package/PASTE_TO_LLM.md +42 -32
  8. package/README.md +3 -2
  9. package/SDK.md +1028 -563
  10. package/UI_AESTHETIC.md +30 -3
  11. package/blocks/generate/package.js +1 -0
  12. package/blocks/generate/versions/1.0.0/package.js +463 -0
  13. package/docs/build/audio-to-editor.md +36 -0
  14. package/docs/build/block-builder-contract.md +150 -0
  15. package/docs/build/comfyui.md +227 -0
  16. package/docs/build/concepts.md +40 -0
  17. package/docs/build/context.md +159 -0
  18. package/docs/build/cookbook.md +57 -0
  19. package/docs/build/custom-interface.md +617 -0
  20. package/docs/build/data-types.md +83 -0
  21. package/docs/build/frame-views.md +259 -0
  22. package/docs/build/generate-media.md +59 -0
  23. package/docs/build/github-applications.md +314 -0
  24. package/docs/build/hosted-images.md +214 -0
  25. package/docs/build/hosted-music.md +39 -0
  26. package/docs/build/hosted-speech.md +157 -0
  27. package/docs/build/hosted-text.md +246 -0
  28. package/docs/build/image-description.md +49 -0
  29. package/docs/build/interface-design.md +343 -0
  30. package/docs/build/javascript.md +63 -0
  31. package/docs/build/local-preview.md +61 -0
  32. package/docs/build/media-analysis.md +27 -0
  33. package/docs/build/media.md +400 -0
  34. package/docs/build/mobile-ui.md +106 -0
  35. package/docs/build/modules.md +487 -0
  36. package/docs/build/original-blocks.md +70 -0
  37. package/docs/build/outside-apis.md +128 -0
  38. package/docs/build/production-context-templates.md +12 -0
  39. package/docs/build/project-storage.md +94 -0
  40. package/docs/build/quickstart.md +48 -0
  41. package/docs/build/recipes.md +103 -0
  42. package/docs/build/script-handoff.md +45 -0
  43. package/docs/build/script-writer.md +34 -0
  44. package/docs/build/state.md +223 -0
  45. package/docs/build/testing.md +112 -0
  46. package/docs/build/timeline-edits.md +116 -0
  47. package/docs/build/timeline-proposals.md +76 -0
  48. package/docs/build/transcription.md +59 -0
  49. package/docs/build/triggers.md +59 -0
  50. package/docs/build/tutorial.md +52 -0
  51. package/docs/build/typescript.md +34 -0
  52. package/docs/build/video-generation.md +61 -0
  53. package/docs/build/web-reading.md +37 -0
  54. package/docs/build/with-your-ai.md +27 -0
  55. package/docs/changelog.md +9 -0
  56. package/docs/creators.md +21 -0
  57. package/docs/distribute/discovery.md +43 -0
  58. package/docs/distribute/imports.md +58 -0
  59. package/docs/distribute/publishing.md +29 -0
  60. package/docs/distribute/sdk-versions.md +36 -0
  61. package/docs/distribute/selling.md +14 -0
  62. package/docs/distribute/teams.md +60 -0
  63. package/docs/distribute/versioning.md +28 -0
  64. package/docs/examples.md +23 -0
  65. package/docs/gallery.md +26 -0
  66. package/docs/index.md +50 -0
  67. package/docs/native-mcp.md +307 -0
  68. package/docs/project-types/automation.md +43 -0
  69. package/docs/project-types/batches.md +50 -0
  70. package/docs/project-types/build.md +42 -0
  71. package/docs/project-types/completion.md +15 -0
  72. package/docs/project-types/conditions.md +21 -0
  73. package/docs/project-types/hosted-review.md +115 -0
  74. package/docs/project-types/onboarding.md +75 -0
  75. package/docs/project-types/running.md +309 -0
  76. package/docs/project-types/testing.md +72 -0
  77. package/docs/reference/application-artifacts.md +87 -0
  78. package/docs/reference/authoring-guide.md +134 -0
  79. package/docs/reference/browser-applications.md +267 -0
  80. package/docs/reference/capabilities.md +45 -0
  81. package/docs/reference/cli.md +71 -0
  82. package/docs/reference/connection-api.md +59 -0
  83. package/docs/reference/cooperative-jobs.md +13 -0
  84. package/docs/reference/desktop-capabilities.md +172 -0
  85. package/docs/reference/desktop-execution.md +77 -0
  86. package/docs/reference/errors.md +233 -0
  87. package/docs/reference/execution.md +800 -0
  88. package/docs/reference/first-party-blocks.md +40 -0
  89. package/docs/reference/generation-models.md +59 -0
  90. package/docs/reference/limits.md +306 -0
  91. package/docs/reference/manifest-kinds-controls.md +36 -0
  92. package/docs/reference/manifest.md +181 -0
  93. package/docs/reference/operations.md +36 -0
  94. package/docs/reference/package-jobs.md +35 -0
  95. package/docs/reference/parity.md +55 -0
  96. package/docs/reference/permissions.md +86 -0
  97. package/docs/reference/ports.md +26 -0
  98. package/docs/reference/types.md +268 -0
  99. package/docs/reference/universal-resolver.md +303 -0
  100. package/docs/reference/view-bridge.md +60 -0
  101. package/docs/reference/view-rules.md +15 -0
  102. package/docs/reference/workspace-sync.md +25 -0
  103. package/docs/sdk.md +34 -0
  104. package/docs/tools/block-remix.md +211 -0
  105. package/docs/tools/llm.md +2213 -0
  106. package/docs/tools/repository-adaptation.md +613 -0
  107. package/examples/check-clip.stillmade.json +8 -1
  108. package/examples/clean-text.stillmade.json +4 -0
  109. package/examples/custom-interface.stillmade.json +4 -0
  110. package/examples/describe-image.stillmade.json +4 -0
  111. package/examples/foley-cue.stillmade.json +4 -0
  112. package/examples/generate-image.stillmade.json +4 -0
  113. package/examples/generate-video.stillmade.json +10 -2
  114. package/examples/module-word-stats/stillmade.block.json +4 -0
  115. package/examples/narrate-script.stillmade.json +4 -0
  116. package/examples/numbered-takes.stillmade.json +4 -0
  117. package/examples/research-topic.stillmade.json +9 -1
  118. package/examples/score-a-scene.stillmade.json +4 -0
  119. package/examples/script-draft.stillmade.json +4 -0
  120. package/examples/summarize-page.stillmade.json +4 -0
  121. package/examples/text-workflow.stillmade.json +7 -32
  122. package/examples/thicken-lines.stillmade.json +4 -0
  123. package/examples/timeline-polish.stillmade.json +15 -3
  124. package/examples/transcribe-audio.stillmade.json +15 -3
  125. package/examples/word-count.stillmade.json +4 -0
  126. package/package.json +1 -1
  127. package/packages/block-cli/cli.js +13 -6
  128. package/packages/block-cli/dev-host/assets/host.js +81 -38
  129. package/packages/block-cli/dev-host/assets/index.css +1 -1
  130. package/packages/block-cli/format.js +1 -1
  131. package/packages/block-cli/ready-gate.js +4 -0
  132. package/packages/block-cli/templates.js +37 -19
  133. package/packages/block-cli/type-packages.js +119 -0
  134. package/packages/block-platform/block-readiness.js +8 -1
  135. package/packages/block-platform/canvas.js +2 -1
  136. package/packages/block-platform/catalog.js +27 -48
  137. package/packages/block-platform/native-host-inventory.js +0 -226
  138. package/packages/block-platform/plain-descriptions.js +1 -25
  139. package/packages/block-platform/project-type-starters.js +13 -53
  140. package/packages/block-platform/script-handoff.js +2 -4
  141. package/packages/block-platform/type-workspace.js +2 -0
  142. package/packages/block-sdk/appearance.js +3 -1
  143. package/packages/block-sdk/audio-generation-example.js +2 -2
  144. package/packages/block-sdk/block-tier.js +1 -1
  145. package/packages/block-sdk/builder-contract.js +13 -11
  146. package/packages/block-sdk/capabilities.js +1 -1
  147. package/packages/block-sdk/capability-example.js +1 -1
  148. package/packages/block-sdk/contracts.js +6 -2
  149. package/packages/block-sdk/examples.js +3 -3
  150. package/packages/block-sdk/first-party-identities.js +1 -84
  151. package/packages/block-sdk/first-party-packages.js +3 -85
  152. package/packages/block-sdk/generation-catalog.js +15 -3
  153. package/packages/block-sdk/image-description-example.js +1 -1
  154. package/packages/block-sdk/image-generation-example.js +1 -1
  155. package/packages/block-sdk/index.d.ts +2 -1
  156. package/packages/block-sdk/media-analysis-example.js +2 -2
  157. package/packages/block-sdk/mock-host.js +7 -1
  158. package/packages/block-sdk/module-example.js +1 -1
  159. package/packages/block-sdk/module-host-calls.js +35 -10
  160. package/packages/block-sdk/module-hosted.js +15 -2
  161. package/packages/block-sdk/module-media-access.js +71 -0
  162. package/packages/block-sdk/module-node.js +1 -1
  163. package/packages/block-sdk/portable-media-actions.js +1 -1
  164. package/packages/block-sdk/runtime.js +1 -1
  165. package/packages/block-sdk/speech-example.js +1 -1
  166. package/packages/block-sdk/state-example.js +1 -1
  167. package/packages/block-sdk/timeline-proposal-example.js +1 -1
  168. package/packages/block-sdk/transcription-example.js +1 -1
  169. package/packages/block-sdk/trigger-examples.js +2 -2
  170. package/packages/block-sdk/video-generation-example.js +1 -1
  171. package/packages/block-sdk/view-bridge.js +4 -1
  172. package/packages/block-sdk/view-design.js +44 -15
  173. package/packages/block-sdk/web-example.js +2 -2
  174. package/packages/design-system/block-kit.css +53 -12
  175. package/packages/design-system/block-kit.html +3 -2
  176. package/blocks/mcp-motion-planner/versions/1.1.0/package.js +0 -97
  177. package/blocks/motion-designer/versions/1.0.1/package.js +0 -173318
  178. package/blocks/motion-designer/versions/1.0.2/package.js +0 -173318
  179. package/blocks/motion-frame-review/versions/1.1.1/package.js +0 -465
  180. package/blocks/motion-frame-review/versions/1.1.2/package.snapshot.js +0 -572
  181. package/blocks/narration/package.js +0 -1
  182. package/blocks/narration/versions/1.0.0/package.js +0 -221
  183. package/blocks/narration/versions/1.0.1/package.js +0 -221
  184. package/blocks/native/sm.animated-scene/versions/2.0.0/package.js +0 -475
  185. package/blocks/native/sm.animated-scene/versions/2.1.0/package.js +0 -498
  186. package/blocks/native/sm.animated-scene/versions/2.2.0/package.js +0 -524
  187. package/blocks/native/sm.animated-scene/versions/2.3.0/package.js +0 -618
  188. package/blocks/native/sm.animated-scene/versions/2.3.1/package.js +0 -618
  189. package/blocks/native/sm.animated-scene/versions/2.3.2/package.js +0 -723
  190. package/blocks/native/sm.animated-scene/versions/2.3.3/package.js +0 -723
  191. package/blocks/native/sm.animated-scene/versions/2.3.4/package.js +0 -676
  192. package/blocks/native/sm.animated-scene/versions/2.3.5/package.js +0 -693
  193. package/blocks/native/sm.animated-scene/versions/2.3.6/package.js +0 -700
  194. package/blocks/native/sm.animated-scene/versions/2.3.7/package.js +0 -747
  195. package/blocks/native/sm.animated-scene/versions/2.3.8/package.js +0 -769
  196. package/blocks/native/sm.animated-scene/versions/2.3.9/package.js +0 -769
  197. package/blocks/native/sm.animated-scene-assistant/versions/1.0.0/package.js +0 -183
  198. package/blocks/native/sm.blueprint/versions/2.0.0/package.js +0 -358
  199. package/blocks/native/sm.blueprint/versions/2.1.0/package.js +0 -358
  200. package/blocks/native/sm.blueprint/versions/2.1.1/package.js +0 -358
  201. package/blocks/native/sm.blueprint/versions/2.1.2/package.js +0 -358
  202. package/blocks/native/sm.blueprint/versions/2.1.3/package.js +0 -381
  203. package/blocks/native/sm.blueprint/versions/2.1.4/package.js +0 -381
  204. package/blocks/native/sm.blueprint/versions/2.1.5/package.js +0 -339
  205. package/blocks/native/sm.blueprint/versions/2.1.6/package.js +0 -356
  206. package/blocks/native/sm.blueprint/versions/2.1.7/package.js +0 -363
  207. package/blocks/native/sm.blueprint/versions/2.1.8/package.js +0 -410
  208. package/blocks/native/sm.blueprint/versions/2.1.9/package.js +0 -422
  209. package/blocks/native/sm.blueprint-assistant/versions/1.0.0/package.js +0 -172
  210. package/blocks/native/sm.chat/versions/2.0.0/package.js +0 -144
  211. package/blocks/native/sm.chat/versions/2.0.1/package.js +0 -97
  212. package/blocks/native/sm.chat/versions/2.0.2/package.js +0 -100
  213. package/blocks/native/sm.chat/versions/2.0.3/package.js +0 -100
  214. package/blocks/native/sm.continue-if/versions/1.0.0/package.js +0 -168
  215. package/blocks/native/sm.describe-media/versions/2.0.0/package.js +0 -153
  216. package/blocks/native/sm.describe-media/versions/2.0.1/package.js +0 -156
  217. package/blocks/native/sm.describe-media/versions/2.1.0/package.js +0 -140
  218. package/blocks/native/sm.image-editor/versions/2.0.0/package.js +0 -183
  219. package/blocks/native/sm.image-editor/versions/2.0.1/package.js +0 -190
  220. package/blocks/native/sm.new-items/versions/1.0.0/package.js +0 -191
  221. package/blocks/native/sm.pick-photos/versions/1.0.0/package.js +0 -334
  222. package/blocks/native/sm.quality-audit/versions/1.0.0/package.js +0 -192
  223. package/blocks/native/sm.quality-audit/versions/1.0.1/package.js +0 -192
  224. package/blocks/native/sm.quality-audit/versions/1.0.2/package.js +0 -195
  225. package/blocks/native/sm.research/versions/2.0.0/package.js +0 -175
  226. package/blocks/native/sm.research/versions/2.0.1/package.js +0 -184
  227. package/blocks/native/sm.research/versions/2.0.2/package.js +0 -187
  228. package/blocks/native/sm.script/versions/2.0.0/package.js +0 -144
  229. package/blocks/native/sm.script/versions/2.1.0/package.js +0 -144
  230. package/blocks/native/sm.script/versions/2.1.1/package.js +0 -144
  231. package/blocks/native/sm.script/versions/2.1.2/package.js +0 -105
  232. package/blocks/native/sm.script/versions/2.1.3/package.js +0 -152
  233. package/blocks/native/sm.script/versions/2.1.4/package.js +0 -156
  234. package/blocks/native/sm.script/versions/2.1.5/package.js +0 -156
  235. package/blocks/native/sm.shot-plan/versions/2.0.0/package.js +0 -301
  236. package/blocks/native/sm.shot-plan/versions/2.1.0/package.js +0 -528
  237. package/blocks/native/sm.shot-plan/versions/2.1.1/package.js +0 -528
  238. package/blocks/native/sm.shot-plan/versions/2.1.2/package.js +0 -528
  239. package/blocks/native/sm.shot-plan/versions/2.1.3/package.js +0 -536
  240. package/blocks/native/sm.shot-plan/versions/2.2.0/package.js +0 -800
  241. package/blocks/native/sm.shot-plan/versions/2.2.1/package.js +0 -920
  242. package/blocks/native/sm.shot-plan-assistant/versions/1.0.0/package.js +0 -173
  243. package/blocks/native/sm.stock-search/versions/2.0.0/package.js +0 -174
  244. package/blocks/native/sm.thumbnail/versions/2.0.0/package.js +0 -137
  245. package/blocks/native/sm.thumbnail/versions/2.0.1/package.js +0 -140
  246. package/blocks/native/sm.transcribe/versions/2.0.0/package.js +0 -163
  247. package/blocks/native/sm.transcribe/versions/2.0.1/package.js +0 -168
  248. package/blocks/native/sm.whiteboard-assistant/versions/1.0.0/package.js +0 -175
  249. package/blocks/native/sm.youtube/versions/2.0.0/package.js +0 -217
  250. package/blocks/occasion-story/package.js +0 -1
  251. package/blocks/occasion-story/versions/1.0.0/package.js +0 -1658
  252. package/blocks/occasion-story/versions/1.0.1/package.js +0 -1699
  253. package/blocks/occasion-story/versions/1.0.2/package.js +0 -1682
  254. package/blocks/photo-reel-composer/versions/1.0.0/package.js +0 -3043
  255. package/blocks/photo-reel-composer/versions/1.0.1/package.js +0 -3026
  256. package/blocks/photo-reel-composer/versions/1.0.2/package.js +0 -4149
  257. package/blocks/product-ad-variants/versions/1.0.0/package.js +0 -2911
  258. package/blocks/product-launch-director/versions/1.0.0/package.js +0 -103
  259. package/blocks/release-visuals/package.js +0 -1
  260. package/blocks/release-visuals/versions/1.0.0/package.js +0 -1492
  261. package/blocks/release-visuals/versions/1.0.1/package.js +0 -1517
  262. package/blocks/release-visuals/versions/1.0.2/package.js +0 -1500
  263. package/blocks/screen-recorder/package.js +0 -1
  264. package/blocks/screen-recorder/versions/1.0.0/package.js +0 -223
  265. package/blocks/screen-recorder/versions/1.0.1/package.js +0 -223
  266. package/blocks/short-form-finish/package.js +0 -1
  267. package/blocks/short-form-finish/versions/1.0.0/package.js +0 -1043
  268. package/blocks/short-form-finish/versions/1.0.1/package.js +0 -1043
  269. package/blocks/short-form-finish/versions/1.0.2/package.js +0 -1043
  270. package/blocks/short-form-finish/versions/1.0.3/package.js +0 -1026
  271. package/examples/saas-product-launch-reviewed-source.stillmade.json +0 -383
  272. package/examples/saas-product-launch.stillmade.json +0 -304
  273. package/packages/block-platform/dealer-inventory-video-project-type.js +0 -38
  274. package/packages/block-platform/first-revenue-project-types.js +0 -46
  275. package/packages/block-platform/fixture-starters.js +0 -13
  276. package/packages/block-platform/launch-project-source.js +0 -10
  277. package/packages/block-platform/launch-project.js +0 -30
  278. package/packages/block-platform/motion-project-types.js +0 -55
  279. package/packages/block-platform/motion-starters.js +0 -14
  280. package/packages/block-platform/product-ad-variants-project-type.js +0 -30
  281. package/packages/block-platform/product-launch-updated.js +0 -90
  282. package/packages/block-platform/revenue-review-project-types.js +0 -36
  283. package/packages/block-platform/revenue-review-starters.js +0 -13
  284. package/packages/block-platform/script-writer.js +0 -29
  285. package/packages/block-platform/website-source-block.js +0 -14
@@ -0,0 +1,150 @@
1
+ # Block builder contract
2
+
3
+ Contract `stillmade.block-builder@1.17.0`. Humans, coding agents, imported source, GitHub repositories and generated code all adapt to the Block platform; anything that becomes a StillMade Block obeys this contract.
4
+
5
+ ## Source of truth
6
+
7
+ Treat the current SDK (`stillmade.block.json` manifest, `packages/block-sdk` contracts, validators, examples and published docs) as the source of truth. Before writing code, read the manifest contract, at least two working first-party Blocks closest to the request, the runtime you will use, the typed port and resolver contracts, and the shared-interface contract when you need a custom view. Do not invent runtimes, operations, permissions, ports, host services or bridge calls. If the documentation and the validator disagree, the validator wins and the mismatch should be reported.
8
+
9
+ ## Reuse first
10
+
11
+ Before building, check what exists (`find_existing_blocks` over MCP, or the Marketplace and your library) by the goal's inputs, results and operations. Only a `likely` or `verified-contract` match (a Block or a chain of two) does the job: use it. `partial` is a close Block to look at: remix it (license, notices and credit stay attached) or build only the missing step. Never republish another creator's source without remix lineage: public copies are refused. Build new when nothing does the job or the person wants their own, and name similar Blocks you considered.
12
+
13
+ ## Three sizes of Block
14
+
15
+ Blocks come in three sizes and the manifest decides which (packages/block-sdk/block-tier.js): an app is a workspace a person works in (Editor, Canvas, Shots), placed in a Type and never wired automatically; a job is one deliverable a person would name (the narration, the captioned clip), built from the hosted operations it needs (`permissions.capabilities`) and reviewed in one place, the unit Chat picks for a Step; an ingredient is one hosted operation with nothing of its own (a declarative capability Block), what a job is made of. When two ingredients would stand in a row to make one deliverable (writing the words, then voicing them), build or pick the job that does both and keep the review point inside it. A job declares a second output when another Block consumes the intermediate (the script beside the voice); split into two jobs only when the intermediate has a life of its own or the halves have different owners or payment.
16
+
17
+ ## Choose the runtime
18
+
19
+ Pick the runtime from the job. No hosted AI: a recipe or isolated `javascript`, both able to run unattended. One text, script or brief prompt returning text, script or JSON: a `capability` Block. Hosted operations on other values (a transcript, media, structured data), several hosted operations in a row, or a result shaped in code: one `module` Block, `module/main.js` calling `stillmade.hosted.run(operation, request)` for each operation in `permissions.capabilities` (MODULES.md), never one Block per operation; it runs in the person's browser while StillMade is open. Build a new Block in a folder with `stillmade-block create`, `test`, `ready` and `pack`, and import the file `pack` writes (a module Block writes `<id>-<version>.stillmade-module.json`) through Create, then Import Block. A `.stillmade-block` archive is only for adapting a GitHub repository.
20
+
21
+ ## One job per Step
22
+
23
+ A Step is one job: the work between two moments where a person or the outside world must see the result. A guided job, one the person fills in and then gets a result from, is one Step with one Block whose own screen holds everything: the inputs and settings, then a cheap check before the expensive run (the script and a voice sample before the video), then the result. On a wide screen the inputs sit on the left and the result's place on the right; on a phone they stack, the result's place under the button. A cheap check or a review the person does on that screen never starts a new Step. Start a new Step only at one of these points; everything else is a part of the neighboring Step.
24
+
25
+ 1. **A person works with the result**: in a workspace they spend a while in (the Editor, a storyboard, a Canvas, a CAD or drawing tool), or someone else approves or takes it over (a hand-off). Turning what a workspace made into something else is the next Step: a CAD tool is its own Step, and the Block that takes pictures of its model and makes a video is the next one. So Bible, Canvas and Editor are separate Steps after Chat.
26
+ 2. **Finding new things turns into handling each one**: the trigger (a schedule or an app event), the app read, its filter and "only new" are the first job; what is done with each item is the next job. A trigger is a setting of the first job, never a Step of its own.
27
+ 3. **The result leaves StillMade**: it is sent, posted, published, paid or written into another app. Consecutive writes to the same app, with the glue that shapes data for them, are one job.
28
+ 4. **Setup or a wait**: a one-time setup that is not part of each job (a brand kit, capturing a voice or a likeness), or a render that takes minutes and is delivered later.
29
+
30
+ In a production the Steps are the workspaces a person opens: work feeding the next workspace is its part, else it joins the one before. A Block with its own interface (a workspace, editor or picker) is always its own Step; two such Steps are never one. A Type whose own Block renders the finished video (`timeline.render`) needs no Editor Step; the Editor (1.0, captions and export built in) is a Step only when the person edits the cut by hand, and Export video is never a Step beside it.
31
+
32
+ A part that only runs in the desktop app cannot share a Step with cloud parts. Before adding a Step, name which of these reasons makes it separate; if none applies, make it a part of a neighbor. A Step nobody would ever open must not exist on its own. Prefer an app task's own filter (a Gmail query such as `has:attachment filename:png`) to an AI check, and use AI decide only for judgement.
33
+
34
+ Build one Block for a job one Block can do: a module Block calls every hosted operation the job needs (it transcribes a sermon, then finds the verses said in it), a JavaScript Block does several local transforms, a workspace owns its whole document. A Block being built never takes an ingredient's result only so the ingredient can be its own part or Step (Transcribe in front of a verse finder): it calls that operation itself. Parts in one Step (`groups` in the Project Type) are for jobs made of Blocks that already exist and app tasks, each keeping its own permission, approval and credit rules. Never invent a combined runtime.
35
+
36
+ Examples: "a listing video from my photos and the home's facts" is one Step: one Block whose page takes the photos and facts, shows the script and a voice sample to check, then makes the video. "every new email with an image becomes a generated image" is two Steps, "Gmail · New emails with images" (When, fetch with an image filter, only new) and "Image from email" (AI write, Generate image); listing When, Fetch, Only new, AI decide, Continue only if, AI write and Generate image as seven Steps splits one job into its parts. "A new Meta lead goes to HubSpot" is three Steps: "Meta Ads · New leads", "Qualify lead" and "HubSpot · Add contact".
37
+
38
+ ## Define the capability first
39
+
40
+ Translate the request into an explicit capability contract before implementation: what the Block does; each input with its type, meaning and whether it is required (prefer optional settings with safe defaults over extra required questions); each output with its type and meaning; persistent state; project context it reads; permissions; UI; long-running behavior; expected failures; cancellation; determinism; and whether it needs hosted models, media, desktop tools or shared editing. Keep the public interface as small and general as possible (few required inputs, one primary output) and keep implementation details out of it; small means a small interface, never a fragment of a job. A Block that generates images, video or speech declares only its prompt and output: every Step that runs it gets the host’s generation settings (model, quality, length and resolution, voice, speed, how many), saved with the Step, changed on its page or by Chat, and shown with their cost before each run.
41
+
42
+ ## Blocks compose
43
+
44
+ A Block is one job: not a mini-app of many jobs and not a fragment of one. Its outputs become other Blocks' inputs and its inputs come from other Blocks, project context or the user. Use the typed port system: shared StillMade types (`image`, `video`, `audio`, `asset`, `script`, `shot[]`, ...), `required`, a short `description`, and a `semantic` only where it narrows what fits. Mark exactly one primary input and one primary output so Project Type Steps connect automatically, and use `kind: "task"`: a `workspace` Block owns a project document and is never connected automatically. Inputs marked `context` read the project and cannot receive a connection from another Step. Output reusable StillMade values: media references (`{kind,assetId,versionId,url}`) and structured production values with `schemaVersion: 1`, preserving provenance, versions and relationships downstream Blocks need. Never make ordinary users wire JSON, copy IDs, understand internal paths or translate one Block's output into another: `createUniversalResolver()` resolves inputs from compatible upstream outputs, permitted project context and, for optional non-context inputs, `StillMade.requestFromUser`.
45
+
46
+ ## Feature map
47
+
48
+ Every Block carries a feature map in `manifest.features`, written by whoever builds it while they build, so the person never writes it. Add one entry for each separate thing a person could ask for: a tool, a mode, a preset family or a kind of result (an editor's reaction GIFs, its motion presets, a recorder's screen recording), not one entry covering several tools. Each entry has a lowercase `id`, a `label` of 40 characters or fewer, `does` (what it does, 160 characters or fewer) and `asks`: 1–8 short requests in a customer's own words that this feature answers ("add a fire gif over my car"). `operation` names an id in the Block's own `manifest.operations` (omit it when there are none); `inputs`/`outputs` name declared ports. The gate fails a Block without one. Add or update the entry in the same change that adds or alters a tool, and remove it when the tool goes. List only what the code really does; listings are generated from this map, nobody can edit them, and StillMade matches requests to features. Features are not tested at publish: each shows as new until real use proves it.
49
+
50
+ ## Use platform primitives
51
+
52
+ Prefer, in order: an SDK capability; a documented host capability (the hosted operations are text.generate, audio.speech, audio.transcribe, audio.music, audio.sfx, image.generate, video.generate, image.describe, media.analyze, web.fetch, web.research, timeline.propose, workspace.propose, connection.execute; connected third-party apps go through `connection.execute`); an approved dependency the SDK already bundles; small Block-local code. Do not duplicate what StillMade provides. A Block never contains its own asset system, file picker, authentication, project-context system, input resolver, Block connection system, credit system, secrets store, permission system, progress system, multiplayer system, persistence system, model-provider abstraction or execution protocol.
53
+
54
+ ## No hidden workarounds
55
+
56
+ Never make a Block look functional through hard-coded local paths, developer-machine dependencies, undocumented environment variables, admin or database access, hidden core modifications, direct database writes, fake or mocked production results, hand-prepared test assets that hide incompatibilities, credentials in code, or assumptions about one user's machine. The finished Block must work through the same interfaces available to any installed Block; `permissions.filesystem` and `permissions.secrets` must be empty arrays, and so must `permissions.network`, except in a module Block, which lists the https origins it calls through `stillmade.net.fetch`.
57
+
58
+ ## Name it briefly
59
+
60
+ Give the Block a short, plain name of 40 characters or fewer that says what it does ("Captioned Clip", not "Captioned Business Clip Generator With Review"). The name appears in step bars, Project Type cards and pickers, so put the detail in the description instead. New releases with a longer name do not pass readiness.
61
+
62
+ ## Name inputs in the job's words
63
+
64
+ Name each input for what the person brings, in the job's words: `sermonVideo` for a sermon clip Block, `listingPhotos` for a listing, `lessonSlides` for a lesson podcast. StillMade titles the input from that name ("Sermon video") and words its drop area from it ("Drop your sermon video here", the formats, "Choose a video"), in StillMade and the SDK preview, so never draw your own upload box or `<input type="file">`: a Block's screen shows the files as tiles and adds more with `<button class="sm-add" data-stillmade-add="listingPhotos" aria-label="Add photos">`, which opens StillMade's picker and upload, and a list's tiles drop or reorder a file with `data-stillmade-remove="listingPhotos" data-index="2"` and `data-stillmade-move="listingPhotos" data-index="2" data-to="1"` buttons; the files arrive through `onInput`. Keep a bare type name (`video`, `file`) only when any file of that kind does the job. The `description` says what makes a good one.
65
+
66
+ ## Speak the job
67
+
68
+ These are StillMade's defaults: unless the person or the creator asked for something else, every screen speaks the job in its own words and adds nothing else. `manifest.action` names the Step's button, {label:"Plan the tour", running:"Planning the tour…"}, and StillMade adds the price ("Plan the tour · 1 credit"). Every Block whose Step shows StillMade's button declares it: any Block without its own screen, and any that calls operations. Without it StillMade can only guess from the Block's name or output ("Make clips"), and the readiness gate and StillMade's own builder send the Block back until it names the job. When the Block makes a picture, video or sound with AI the label starts with Generate and says what ("Generate tour", "Generate voiceover"); one that cuts or renders the person's own media says Make ("Make 6 clips"); never "Make it", "Run", "Submit", "Process" or a bare "Generate". The main button stands out: one solid `sm-primary` in the kit's ink, never restyled to the background; everything else is `sm-quiet` or an `sm-icon`, and close is an X icon. Report progress in the job's units with `stillmade.progress(fraction, label)` ("Moving through the kitchen, 4 of 9 rooms"), never "Processing". Head the result in the job's words ("9 rooms", "Your tour · 44 s"), never "Output". Say a problem in one line with its fix beside it ("No bathroom photo. Guests look for one." and Add photo). Stay quiet: no welcome text, tips under fields, tours or banners, and at most one line of guidance on a screen, only where the next move is not obvious; anything more goes in the input's `description`, which StillMade shows behind an (i). Say nothing about how the Block works (where it runs, saving, syncing, recovery, accounts, credits) or where a file is kept: StillMade tells the person what they need as one short notification, or nothing; never a sentence on the page, and never the same line under each item. Every drop area offers "Use a reference", which fills the Step from the person's saved photos, videos and notes: media inputs fill by kind, so take `video` or `asset` where a clip works as well as a photo, and text inputs fill by plain names and labels (`productName`, `website`, `brandColors`, `fonts`, `voice`, and `details` or `notes` for the reference's note); never build your own reference picker. Days and times are picked, never typed: use the `date` type, which StillMade shows as a calendar, with a list of times when the input is about a time (`postAt`, `startsAt`); a custom view uses `<input type="date">` or `type="datetime-local"`. Posting is a connector Step of its own, and StillMade words its button from the app and action ("Post to Instagram"). Before handing the Block back, clear every Wording note that `gate` and readiness list, unless the person asked for those words.
69
+
70
+ ## Interface
71
+
72
+ If the capability needs UI, use the Block UI SDK: generated `manifest.ui` controls first; a sandboxed custom view (`view.html`/`view.css`/`view.js`) only when the core interaction needs one. Build custom views from the Block kit the host injects (`block-kit.css`): the result in `sm-stage`, drawn before the first run in the shape and size of what is coming (`data-ratio="9:16"` for a vertical clip, lines for text, a player bar for sound) so every part of the screen is in place at once and the result fills a place the person already sees instead of popping in somewhere unexpected; StillMade draws it the same way on the Steps it draws; on a wide screen what goes in sits on the left and the result on the right, side by side, and they stack only on narrow screens and phones, the result's place under the button, picks as pictures in `sm-choices`, the picked one in the kit's ink fill (never restyled to an outline, a tint or the page's background) so it reads at a glance, one solid `sm-primary` naming the action in the job's words ("Plan the tour", "Generate voiceover"; never "Run" or "Make it") and no price (StillMade's run button adds it), extras in a closed `sm-more`; a look the person names wins. Fit one laptop screen without scrolling: label beside control, status in a few words, files as tiles, rare tools as icons, (i) on unclear controls. These compact rules are for a job or an ingredient. Size the view to the Block's tier (block-tier.js): an app, a workspace a person works in for a while (video editor, 3D configurator, CAD or drawing tool), looks and works like that kind of app instead of a compact page: its canvas or stage fills the view, with the panels, toolbars, inspector or timeline such an app has, direct manipulation (select, drag, zoom), keyboard shortcuts and undo; it keeps the host appearance and Block kit controls, its panels may scroll, and on a phone its tools fold into sheets while the canvas stays usable. Never shrink an app into a form of fields and one button. StillMade centers a standard view narrower than its Step and zooms a view to fill its space; an app that lays itself out (full-size canvas or WebGL, its own scroll, pan or zoom, its own Ctrl/Cmd +/- keys) puts `data-stillmade-layout="own"` on its outermost element, and StillMade then never centers, zooms or takes those keys. StillMade draws one player for every `<video controls>` (play, timeline, time, sound and full screen, shown while the pointer is on the video, with keys and touch) and a full-screen button on result pictures in `sm-stage` or `sm-gallery` and on any element marked `data-stillmade-expand` (the same value makes one set of pictures, `off` removes it); `data-stillmade-player="native"` keeps the browser's controls, and a `<video>` without `controls` is the Block's own and is never touched. A picture or clip that cannot show here (kept on another device, or it did not open) keeps its place as a quiet `sm-media-off` tile in its own shape with the `image-off` glyph and the reason in its label, never words in its place. Drop words nobody needs; put helpful ones in a closed `sm-hint`. Mark each button `data-stillmade-action` (`run` on the one that runs the Block, which the device checks press once; a page that checks first keeps `run` on that button for both presses; what it does on the others, `"play sample"`) and label each field: Chat presses and fills them. Expose the capability, not the implementation: sensible defaults, previews, progress, clear errors, visible outputs. Show no raw JSON, internal IDs, filesystem details, provider terms or developer settings unless the Block is a developer tool. When a person chooses among options they need to hear or see (voices, music, fonts, looks, templates, images), let them preview each option before choosing: a sample or thumbnail from the Block's own files or the host's free samples, never a paid generation. Skip previews only when there is nothing to preview. Choices StillMade owns (voices, models in the run review) already show samples. Follow the host appearance (Light, Dark and White) and one elastic layout: stacked on a 320px phone with no sideways scroll (the inputs, the button in normal flow, never pinned, then the result's place under it), and from 860px the controls left (≤380px), the result filling the right. Short settings sit side by side, each label beside its control (`sm-field`, `sm-settings`; three or four short options as one `data-segmented` row); many items are one line each (`sm-list`) that open in place; input files are small tiles (`sm-gallery data-size="small"`); on a phone chip rows scroll sideways and long lists show three. Compacting moves controls, never deletes them.
73
+
74
+ ## Shared editing
75
+
76
+ Projects are multiplayer. A custom view subscribes through `StillMade.onShared(callback)` and publishes every editable field: give static controls a unique `id` and `data-stillmade-share="field"` (the host owns their synchronization), use `StillMade.bindShared(field, elementId)` for controls created dynamically, and `StillMade.updateShared(values, before, options)` for structured values; private variables and DOM values are not shared. Mark a truly device-only control (playback, hover, device selection) with `data-stillmade-local`. Observe shared outputs as well as state, honor `canEdit` in every mutating callback (read-only participants cannot write), never run, click or call a paid integration in response to a remote update, and preserve conflicting drafts. Shared background work uses `sharedWork` with the `work.shared` permission.
77
+
78
+ ## External services
79
+
80
+ Reach external services only through StillMade's hosted operations, the connections service (`connection.execute`), or, in a module Block, `stillmade.net.fetch` to origins declared in `permissions.network` (with the key each needs), `stillmade.net.connect` for a live WebSocket to one of them, and `stillmade.connections.call` to adapters or catalog apps in `permissions.connections`; never put keys in code, inputs or headers: StillMade adds each person's own key on its servers. The host owns the model and provider choice, BYOK keys, StillMade credits, spending consent, authorization, token refresh, rate limits, retries and provider errors; a Block never receives a secret and never names a provider unless it must. Treat provider unavailability, timeout, cancellation and partial failure as outcomes the Block reports, not crashes: a call the result needs throws and fails the run (see Useful failures); an optional part's failure is caught, given its fallback and named in an optional `notes` text output. Generated images, video, voices, music and sound effects come from hosted operations or the `media.generate` action, paid with the user's StillMade credits at StillMade's prices; for structured model output declare a `json` output with `capability.schema` instead of parsing prose. When a Block needs npm libraries, WebAssembly (threaded: `"threads": true` in module.json) or heavy compute, use `runtime: "module"` and reach hosted operations through `stillmade.hosted.run` with the operations listed in `permissions.capabilities`. Decode, cut, join, re-encode, extract or normalise audio and video with `stillmade.media.transform` on the device; never ask for a server render. For a rich interactive interface (React or another framework, SVG, canvas, drag), use a frame view: `src/view.config.json` with `{"runtime":"frame"}` and `src/view.js` bundled as one IIFE, colored with StillMade's theme variables. For files and structured data use the `file`, `document`, `table`, `url`, `date` and `color` types and their generated controls and presentations, not JSON text.
81
+
82
+ ## Dependencies
83
+
84
+ A Block must declare everything it requires and must not assume anything is installed. Portable packages carry no package dependencies (`portable.dependencies` is empty): inline small, license-compatible code and record its license and notice in `manifest.license` and `manifest.provenance`. The copyright holder in the Block's own `provenance.notice` is the person it is made for: replace the placeholder `create` writes with their name, never StillMade, the SDK or yourself. Desktop-only tools are reached solely through declared desktop permissions and the host desktop bridge. If a dependency cannot be delivered through the Block runtime, report the incompatibility instead of assuming the user's machine has it.
85
+
86
+ ## Security
87
+
88
+ Treat Block code, external data, files, repositories, model output and network responses as untrusted. Request the minimum permissions and capabilities; `stillmade-block permissions --fix` declares exactly what the source uses. Do not weaken the sandbox (QuickJS has no fetch, DOM, timers, modules or Node APIs). Validate and bound every value crossing a boundary. Never expose secrets through logs, outputs, project context, UI, error messages or serialized state.
89
+
90
+ ## Execution lifecycle
91
+
92
+ A successful run means more than a returned value. Validate inputs before work; return only declared output ports with values matching their types; run long work as a cooperative job (`job.pending` with monotonic progress) instead of blocking; honor cancellation and the host timeout; keep persistent state in `manifest.state` (module Blocks: `stillmade.storage`) with migration routes so a reopened project and a repeated run behave the same; never leave orphaned jobs, temporary values or corrupted project state after cancellation or failure.
93
+
94
+ ## Useful failures
95
+
96
+ Errors must say what failed, why it likely failed, whether a retry makes sense and what the user can do, so the native project chat and controller can troubleshoot. In JavaScript, throw an `Error` with that message: the host reports it as a `JAVASCRIPT` run failure carrying your message (guest code cannot set its own error code). Reject invalid or oversized input up front with a message naming the input and the limit. Never reduce a failure to "Something went wrong".
97
+
98
+ ## Only supplied facts
99
+
100
+ A text Block that writes from supplied facts must not let its prompt template outrank its own "never invent" rule. Every section that needs a specific fact (phone, website, address, price, inspection, certification, warranty, features) is written only when the input supplies that fact; otherwise the section is left out or replaced by a generic line that asserts nothing (for example "Call us today to schedule your test drive."). Never default to "inspected", "certified", invented features or placeholder contact details such as 555 numbers or example websites. Prefer extract-then-generate: first list the facts the input actually contains, then write using only that list. Add a check after generation that rejects or removes sentences naming a claim, number or address not present in the input. Include fixtures with the facts omitted and with them supplied.
101
+
102
+ ## Adapt to the platform
103
+
104
+ Do not modify StillMade core because a request does not fit immediately. First implement the capability entirely through documented SDK and platform primitives. If that is impossible, classify why: A Block implementation problem (fix it), B missing SDK exposure of an existing host capability, C missing generic platform primitive, D security or permission restriction, E runtime or language incompatibility, F fundamentally incompatible capability. For B or C, name the smallest general primitive that would serve this Block and a meaningful class of future Blocks (shaped like `files.watch()` or `media.transform()`, never `supportThisSpecificBlock()`). Return `{"unsupported":"exact reason","gapClass":"B|C|D|E|F","primitive":"..."}` instead of a package that pretends to work.
105
+
106
+ ## What StillMade verifies
107
+
108
+ StillMade runs the readiness check on every Block it admits: manifest and contract validation, the source security scan, every fixture in the sandbox, wrong-type and over-limit inputs, declared output types, cancellation and timeout cleanup, state reopen and repeated runs, composition with a real upstream and downstream catalog Block through the resolver, a Project Type preview, the shared-interface contract with two participants editing a custom view in the real preview runtime (their edits must converge and a read-only participant must not write), and phone and desktop layout. Design for all of them and include normal and edge-case fixtures (1 to 50; stateful Blocks also declare `expectedState`). Test materially different inputs within the declared capability, and document limitations instead of overclaiming generality. Two of these checks need StillMade itself: two-participant shared editing and the phone and desktop UI profile run in StillMade's preview runtime when the Block is imported or released, so `ready` in the downloaded SDK reports them as not verified rather than passed.
109
+
110
+ ## Project Types
111
+
112
+ A Project Type is an ordered production workflow. Each Step's primary output must be a compatible input for the next Step, secondary values come from permitted project context, and every member Block obeys this contract. Install Blocks into a realistic Project Type: project chat must understand each Step, inputs must resolve intuitively, outputs and execution state must be visible, failures must be diagnosable, and the user must be able to continue through the workflow. Group the parts of one job into one Step instead of listing helper parts as Steps; most automations are two to four Steps.
113
+
114
+ ## Readiness report
115
+
116
+ Finish with a Block Readiness Report: capability, contract (inputs, outputs, permissions, dependencies), platform APIs used, tests actually performed and their results, the composition test (upstream, Block, downstream), known limitations, unsupported requirements and any platform gap with its smallest general primitive. Report exactly one status, the one StillMade's readiness check returned (`ready` in the SDK CLI, `check_block_readiness` over MCP), never one you chose: PRODUCTION READY (every applicable check passed), READY WITH DOCUMENTED LIMITATIONS (works reliably within stated boundaries), BLOCKED BY PLATFORM CAPABILITY (needs a missing generic primitive) or FAILED. Never label a Block production ready to satisfy a request, and never claim a check ran when it did not.
117
+
118
+ ## Definition of done
119
+
120
+ A Block is done only when every applicable item holds. Passing a compile, one unit test, a rendered UI or one happy-path sample is not done.
121
+
122
+ - DOD-01 Installs through the normal Block mechanism
123
+ - DOD-02 Manifest and contracts validate
124
+ - DOD-03 Runs through the normal runtime
125
+ - DOD-04 Required permissions are declared
126
+ - DOD-05 Required dependencies are reproducible
127
+ - DOD-06 Real inputs work
128
+ - DOD-07 Invalid inputs fail correctly
129
+ - DOD-08 Outputs conform to their declared types
130
+ - DOD-09 Outputs are usable by compatible downstream Blocks
131
+ - DOD-10 Universal resolver integration works
132
+ - DOD-11 Applicable project context works
133
+ - DOD-12 Applicable persistence works
134
+ - DOD-13 Applicable multiplayer behavior works
135
+ - DOD-14 Cancellation and failure cleanup work
136
+ - DOD-15 UI works in relevant states and screen sizes
137
+ - DOD-16 No hidden developer setup is required
138
+ - DOD-17 Security boundaries remain intact
139
+ - DOD-18 Relevant integration tests pass
140
+ - DOD-19 Works after application restart or project reopen
141
+ - DOD-20 A realistic Project Type execution succeeds when applicable
142
+
143
+ ## Platform gap classes
144
+
145
+ - A: Block implementation problem
146
+ - B: Missing SDK exposure of an existing host capability
147
+ - C: Missing generic platform primitive
148
+ - D: Security or permission restriction
149
+ - E: Runtime or language incompatibility
150
+ - F: Fundamentally incompatible capability
@@ -0,0 +1,227 @@
1
+ # ComfyUI Blocks
2
+
3
+ The reviewed adapter now supports core text-to-image and image-to-image generation. Use `CheckpointLoaderSimple`, `CLIPTextEncode`, `EmptyLatentImage`, `KSampler`, `VAEEncode` and `VAEDecode` with existing `PreviewImage` output. One installed safetensors checkpoint basename, one sampling pass, batch 1 and at most 40 steps are admitted. Generation dimensions are 64–1024 in multiples of 8, subject to the existing four-megapixel aggregate working budget (1024-square image-to-image can exceed it). The connection must report that checkpoint; filenames do not prove file hashes, licenses or GPU readiness. No weights are downloaded. `comfyModelRequirements(workflow)` returns the required model names. Text and numeric controls use typed scalar bindings. The import wizard preserves real sample inputs and prepares padded image-to-image fixture copies; project inputs are never silently resized. See `examples/comfy-text-to-image.stillmade.json` and replace the checkpoint placeholder before review.
4
+
5
+ A ComfyUI Block is a portable declaration of a reviewed image capability. Users
6
+ see its controls and resulting image, not its internal node wiring. Start with
7
+ [the complete example](https://stillmade.shop/block-sdk/examples/comfy-invert.stillmade.json).
8
+
9
+ ### Import an existing ComfyUI workflow
10
+
11
+ Choose **Import ComfyUI workflow** in the import tools, or choose its JSON file
12
+ with **Import package**. Export the **API format** from ComfyUI first; its
13
+ [API documentation](https://docs.comfy.org/development/cloud/overview) describes
14
+ the numbered node map. Visual exports containing `nodes` and `links` cannot be
15
+ converted without the exact frontend/node definitions and receive export guidance.
16
+ The importer accepts the prompt map itself or `{ "prompt": { … } }`. A ZIP may
17
+ contain one `workflow.json`, `workflow_api.json`, or `*.comfy.json` file.
18
+
19
+ The mapping screen asks for the Block name, description, source license, input
20
+ and result names, and the main image input/output. Multiple image inputs or
21
+ outputs require an explicit main choice. Optional semantic roles distinguish
22
+ source images from character references. Resize controls can stay fixed or become
23
+ user-editable inputs. Every LoadImage and PreviewImage must be mapped; unknown
24
+ nodes, dependencies, credentials, cycles, and disconnected processing are rejected.
25
+ This adapter accepts the reviewed image and diffusion classes listed below, not arbitrary custom-node workflows.
26
+
27
+ Choose a sample for every image input. The browser creates a copy no larger than
28
+ 128 pixels per side, with a combined fixture budget, and includes those pixels
29
+ in the downloaded source. Originals are unchanged. The sample stays local until
30
+ you explicitly run the backend review. Optional expected dimensions add fixture
31
+ assertions; leaving them blank still requires a valid decoded single image.
32
+ Choose sample images you may distribute with this Block.
33
+
34
+ **Continue to tests and preview** creates an SDK package, not an installation or
35
+ a successful test. The existing account connection, real fixtures, separate
36
+ sample execution, preview, rights review and **Confirm Import** follow. Importing
37
+ never republishes third-party code. The original API JSON is retained in
38
+ `manifest.provenance.comfyuiImport.source`; execution uses normalized placeholders
39
+ instead of its saved image filenames. Original `_meta.title` remains attribution,
40
+ not executable behavior. Review this retained source before sharing a release.
41
+
42
+ The downloadable SDK exposes the same static conversion API:
43
+
44
+ ```js
45
+ import {inspectComfyImport, buildComfyImportPackage}
46
+ from './packages/block-sdk/index.js';
47
+ import {comfyImageInvert} from './packages/block-sdk/comfyui-example.js';
48
+
49
+ // Replace with a supported API export. No backend is contacted by either call.
50
+ const raw = structuredClone(comfyImageInvert.comfyui.prompt);
51
+ raw['1'].inputs.image = 'my-example.png';
52
+ const inspection = inspectComfyImport(raw);
53
+ console.log(inspection.inputCandidates, inspection.outputCandidates);
54
+
55
+ const pkg = buildComfyImportPackage(raw, {
56
+ manifest: {...comfyImageInvert.manifest, id: 'my.invert', name: 'My invert'},
57
+ inputs: comfyImageInvert.comfyui.inputs,
58
+ outputs: comfyImageInvert.comfyui.outputs,
59
+ tests: comfyImageInvert.tests,
60
+ });
61
+ // Save pkg as JSON, then import it for real backend review and confirmation.
62
+ ```
63
+
64
+ `inspectComfyImport(raw)` returns `format`, inert `source`, normalized `prompt`,
65
+ `nodes`, `inputCandidates`, `outputCandidates`, `warnings`, and
66
+ `execution: "not-run"`. It does not choose names, roles, primary ports or fixtures.
67
+ `buildComfyImportPackage(raw, {manifest, inputs, outputs, tests})` requires those
68
+ explicit choices, validates their contracts and selected resize values, and
69
+ returns a package without execution receipts. Source is limited to 64 KiB and
70
+ the complete package to the usual bounded JSON/import limits.
71
+
72
+ ### Package and runtime contract
73
+
74
+ Set `manifest.runtime` to `comfyui`, `entry` to `src/comfyui.json`, and declare
75
+ `permissions: {project: [], capabilities: ["comfyui.execute"]}`. The top-level
76
+ package contains `manifest`, `comfyui`, `tests`, and an optional `view`. It cannot
77
+ contain `code` or `recipe`. Put the workflow in `comfyui` or, in an editable folder,
78
+ `src/comfyui.json`. Endpoints, tokens, connection IDs, file paths, dependencies,
79
+ and Python never belong in the package. Input/output types and semantic roles
80
+ use the same StillMade contract as other Blocks.
81
+
82
+ The workflow has four fields: `schemaVersion: 1`, `prompt`, `inputs`, and
83
+ `outputs`. `prompt` is an API-format map of numbered nodes with `class_type` and
84
+ `inputs`. Supported core classes are `LoadImage`, `ImageInvert`, `ImageScale`, `PreviewImage`, `CheckpointLoaderSimple`, `CLIPTextEncode`, `EmptyLatentImage`, `KSampler`, `VAEEncode` and `VAEDecode`. Every node must contribute to a declared output. A `LoadImage`
85
+ uses an empty filename placeholder and a binding such as
86
+ `image: {node: "1", input: "image", encoding: "uploaded-image"}`. StillMade uploads
87
+ verified input pixels and supplies the generated basename. Resize controls use
88
+ `encoding: "scalar"`. An output selects one image from a declared PreviewImage:
89
+ `image: {node: "3", collection: "images", index: 0}`.
90
+
91
+ Each fixture has `name`, `input`, and `expectations`. For example:
92
+
93
+ ```json
94
+ {"name":"One pixel","input":{"image":{"width":1,"height":1,"data":[20,80,200,255]}},"expectations":{"image":{"kind":"image","count":1,"width":1,"height":1,"maxBytes":4096}}}
95
+ ```
96
+
97
+ Every output requires `kind: "image"` and `count: 1`. Optional width, height,
98
+ maximum encoded bytes, and lowercase `sha256` check the host-decoded and
99
+ re-encoded PNG, not a claimed backend descriptor. Use deterministic hash fixtures
100
+ when exact image behavior matters. Bounds: 16 nodes, 8 inputs/outputs, one
101
+ megapixel per single-frame image, and four megapixels total working images.
102
+ Small inline fixtures fit the four-megabyte import limit. Large media inputs
103
+ should use existing account-owned media references.
104
+
105
+ In Settings → ComfyUI connections, save the public HTTPS endpoint and optional
106
+ bearer token. Tokens use the same stable account encryption key as BYOK with a
107
+ separate encryption purpose. They are never returned to the browser or guest UI.
108
+ StillMade rejects private network endpoints, redirects and arbitrary requests.
109
+ The backend is an explicitly selected service you operate or trust. Checking
110
+ its core-node schema is compatibility evidence, not attestation of its Python
111
+ implementation. Desktop loopback and arbitrary custom nodes are not available through this adapter. Reviewed core diffusion nodes may use the backend’s GPU after explicit approval.
112
+
113
+ Import the JSON or ZIP, choose the connection, and click **Run tests and sample**.
114
+ StillMade scans the package, records durable jobs, runs every fixture and a
115
+ separate sample, decodes outputs, and displays the before/after result. Only then
116
+ can you confirm rights and **Confirm Import**. Confirmation revalidates the
117
+ account/source/connection-bound receipt without silently submitting another job.
118
+ Changing source, connection revision, backend contract, or an expired receipt
119
+ requires another review. Saving a connection, opening a page, and custom iframe
120
+ JavaScript cannot confirm remote execution. Preview runs never install or
121
+ publish a Block. Cancellation targets only owned jobs; unsupported remote
122
+ cancellation can leave work running on the selected backend. The SDK rejects a
123
+ cancelled invocation immediately even if its trusted host callback is still
124
+ waiting. Source and input contracts are captured before dispatch; editing the
125
+ caller’s package during execution cannot change output validation.
126
+
127
+ In a saved project, the host checks edit access and finds a completed review for
128
+ this exact package and connection. A current backend compatibility check runs
129
+ without resubmitting fixtures. A successful import review can be reused for
130
+ project execution after its import-confirmation expiry; changed source,
131
+ connection revision, backend schema, or security status invalidates that reuse.
132
+ The host asks for **Run in project** before submitting the actual project input.
133
+ If review is required, **Run tests and sample** and its preview come first, then
134
+ a separate **Run in project** action. Custom interfaces cannot skip these actions.
135
+ Durable production jobs are associated with the saved project. Local demo and
136
+ Marketplace previews remain samples and cannot claim project access.
137
+
138
+ Offline `validate` and `pack` check and package source. For ComfyUI, `pack` returns
139
+ `reviewRequired: true` and zero executed tests. `test` and `preview` return
140
+ `RUNTIME_UNAVAILABLE` without a trusted host executor. A host integration may
141
+ pass `options.comfyui(package, input, {signal})` to `runPackageAsync` or
142
+ `testPackage`, returning `{outputs, metadata}` where every metadata entry has
143
+ verified width, height, bytes, `mimeType: "image/png"`, `frames: 1`, and optionally
144
+ SHA-256. This callback is trusted host code; it is never loaded from a package.
145
+
146
+ The server supports reviewed ComfyUI packages inside Project Types through the
147
+ account-bound envelope below. The import wizard opens each included ComfyUI Block
148
+ in its connection review panel. Unattended ComfyUI automation remains unavailable.
149
+ Existing recipe/JavaScript Project Types and exact-output fixture checks are unchanged.
150
+
151
+ ### ComfyUI packages in Project Types: host integration
152
+
153
+ The offline CLI can package ComfyUI-only or mixed hosted/local Project Types:
154
+
155
+ ```sh
156
+ node packages/block-cli/cli.js validate ./workflow.json
157
+ node packages/block-cli/cli.js pack ./workflow.json ./workflow.stillmade.json
158
+ ```
159
+
160
+ This performs static/schema checks on every embedded package and preserves exact
161
+ source. It never runs a provider, connects to ComfyUI, or executes local fixtures.
162
+ The result explicitly reports `tests: 0`, `reviewRequired: true`,
163
+ `liveVerified: false`, and `workflowComplete: false`. Import the result into
164
+ StillMade for authenticated backend review, local tests, sample execution, and
165
+ user confirmation. Unsupported ComfyUI nodes still fail the static package scan.
166
+
167
+
168
+ The authenticated review/import/release/install APIs accept `typeComfyuiReviews`
169
+ alongside `typeCapabilityReviews`. It is request metadata, never portable source:
170
+
171
+ ```json
172
+ {
173
+ "typeComfyuiReviews": {
174
+ "<exact package SHA-256>": {
175
+ "receiptId": "<account review UUID>",
176
+ "connectionId": "<account connection UUID>",
177
+ "connectionRevision": 1
178
+ }
179
+ }
180
+ }
181
+ ```
182
+
183
+ Provide exactly one entry for every embedded ComfyUI package, including unused
184
+ or disabled packages. The server authenticates every fixture and sample against
185
+ the selected backend contract, then checks the ledger again at the save boundary.
186
+ Missing, expired, foreign, cancelled, or changed-connection evidence is rejected.
187
+ Saved imports, release reports, and installation reports retain the fixture and
188
+ sample media. Another account must provide its own reviews. No prompt is
189
+ submitted by receipt verification.
190
+
191
+ A trusted SDK host can supply `verifyComfyPackage` in the third argument to
192
+ `verifyHostedProjectTypePackages(type, verifyCapabilityPackage, options)`.
193
+ The callback must return the server-verified Block report, including `receiptId`,
194
+ `connectionId`, and `connectionRevision`. The resulting opaque handle supports
195
+ `testProjectType` and `previewProjectType`; JSON claims cannot substitute for it.
196
+ Offline rehearsal defers reviewed ComfyUI execution and its dependent outputs.
197
+ Interactive rehearsal requires `verifyHostedResult` before downstream execution;
198
+ retained run metadata uses `comfyuiRun`. A passing package admission report still
199
+ does not prove that the complete connected workflow ran.
200
+
201
+ In the import or builder review, choose **Review Block** beside each ComfyUI
202
+ package, select your connection, and run its tests/sample (or reuse a fresh
203
+ matching review). Finish the package checks, inspect the result, and confirm
204
+ import. Connected workflow preview separately confirms each ComfyUI execution
205
+ and refetches its exact run evidence before handing images downstream. These
206
+ interactive controls do not enable unattended remote execution.
207
+
208
+
209
+ ### Connected ComfyUI execution in a project
210
+
211
+ **Run connected steps** can continue through ComfyUI Blocks when you approve each
212
+ run on your account connection. It reuses the existing reviewed-connection dialog;
213
+ missing fixtures require a separate review before the project input runs. Image
214
+ references reach the broker intact, so the server can check project access and
215
+ bind the exact input. Local image processors decode accepted images as needed.
216
+
217
+ The host uses `planSegment(..., {interactive: true})` and supplies an authenticated
218
+ `verifyHostedResult` callback to `runSegment`. ComfyUI results retain `comfyuiRun`
219
+ and `mediaReceipts`; hosted model results retain `capabilityRun`. These callbacks
220
+ are trusted StillMade integration code, never imported Block code. A resumed run
221
+ or **Use results** re-fetches and verifies each remote result against the current
222
+ project, source, inputs, and connection metadata before accepting it. Waiting for
223
+ consent or a remote backend does not consume the local computation budget.
224
+
225
+ Cancellation or failed verification stops downstream work and retains earlier
226
+ completed results for review. The default non-interactive planner still stops at
227
+ ComfyUI or hosted model Blocks; future-media automation cannot submit those jobs.
@@ -0,0 +1,40 @@
1
+ # Blocks, Steps, and Project Types
2
+
3
+ ## Block
4
+ A reusable production workspace or capability. The built-in catalog consists of full screens: Script Writer, Voiceover, Shots, Blueprint, Canvas, Editor, Image Panels, White Board Motion, and Assets. Chat is not a Block: it is the project's own conversation, which every Project Type starts with. Internal canvas nodes and individual editor controls are implementation details inside their workspace, not separate built-in Blocks.
5
+
6
+ External processing Blocks, such as Thicken Line Art or lip sync, add a capability to the workflow. A Block declares input and output ports, permissions, controls, and an implementation runtime.
7
+
8
+ ## Step
9
+ An instance of a Block inside a Project Type. Each Step has its own instance ID, pinned Block ID and version, configuration, enabled state, and optional condition. Reusing a Block in two positions creates two independent Steps.
10
+
11
+ ## Project Type
12
+ An ordered production workflow. Its persisted `stages` array stores Steps for compatibility with existing projects. Users can add, remove, duplicate, configure, disable, or reorder Steps. The protected starting chat belongs to the host and cannot be replaced or remixed.
13
+
14
+ ## One job per Step
15
+ A Step is one job: the work between two moments where a person or the outside world must see the result. A guided job, one the person fills in and then gets a result from, is one Step with one Block whose own screen holds everything: the inputs and settings, then a cheap check before the expensive run (the script and a voice sample before the video), then the result. On a wide screen the inputs sit on the left and the result's place on the right; on a phone they stack, the result's place under the button. A cheap check or a review the person does on that screen never starts a new Step. Start a new Step only at one of these points; everything else is a part of the neighboring Step.
16
+
17
+ 1. **A person works with the result**: in a workspace they spend a while in (the Editor, a storyboard, a Canvas, a CAD or drawing tool), or someone else approves or takes it over (a hand-off). Turning what a workspace made into something else is the next Step: a CAD tool is its own Step, and the Block that takes pictures of its model and makes a video is the next one. So Bible, Canvas and Editor are separate Steps after Chat.
18
+ 2. **Finding new things turns into handling each one**: the trigger (a schedule or an app event), the app read, its filter and "only new" are the first job; what is done with each item is the next job. A trigger is a setting of the first job, never a Step of its own.
19
+ 3. **The result leaves StillMade**: it is sent, posted, published, paid or written into another app. Consecutive writes to the same app, with the glue that shapes data for them, are one job.
20
+ 4. **Setup or a wait**: a one-time setup that is not part of each job (a brand kit, capturing a voice or a likeness), or a render that takes minutes and is delivered later.
21
+
22
+ In a production the Steps are the workspaces a person opens: work feeding the next workspace is its part, else it joins the one before. A Block with its own interface (a workspace, editor or picker) is always its own Step; two such Steps are never one. A Type whose own Block renders the finished video (`timeline.render`) needs no Editor Step; the Editor (1.0, captions and export built in) is a Step only when the person edits the cut by hand, and Export video is never a Step beside it.
23
+
24
+ A part that only runs in the desktop app cannot share a Step with cloud parts. Before adding a Step, name which of these reasons makes it separate; if none applies, make it a part of a neighbor. A Step nobody would ever open must not exist on its own. Prefer an app task's own filter (a Gmail query such as `has:attachment filename:png`) to an AI check, and use AI decide only for judgement.
25
+
26
+ Build one Block for a job one Block can do: a module Block calls every hosted operation the job needs (it transcribes a sermon, then finds the verses said in it), a JavaScript Block does several local transforms, a workspace owns its whole document. A Block being built never takes an ingredient's result only so the ingredient can be its own part or Step (Transcribe in front of a verse finder): it calls that operation itself. Parts in one Step (`groups` in the Project Type) are for jobs made of Blocks that already exist and app tasks, each keeping its own permission, approval and credit rules. Never invent a combined runtime.
27
+
28
+ Examples: "a listing video from my photos and the home's facts" is one Step: one Block whose page takes the photos and facts, shows the script and a voice sample to check, then makes the video. "every new email with an image becomes a generated image" is two Steps, "Gmail · New emails with images" (When, fetch with an image filter, only new) and "Image from email" (AI write, Generate image); listing When, Fetch, Only new, AI decide, Continue only if, AI write and Generate image as seven Steps splits one job into its parts. "A new Meta lead goes to HubSpot" is three Steps: "Meta Ads · New leads", "Qualify lead" and "HubSpot · Add contact".
29
+
30
+ ## Typed connections
31
+ An image-producing Block can connect to an image-consuming Block. Primary ports make insertion predictable; semantic roles distinguish a source image from a character reference. Secondary inputs can bind to project context.
32
+
33
+ See [types and compatibility](../reference/types.md), [context](context.md), and [Project Type construction](../project-types/build.md).
34
+
35
+ ## Complete workspace Blocks
36
+ Built-in Blocks are the existing complete production screens. A Guided Project Type starts with Chat, the project's conversation, then Voiceover → Shots → Blueprint → Canvas → Editor; export belongs to Editor. The reusable Script Writer is the full Narrative Compiler; it and the legacy Script adapter do not replace Chat. Canvas remains the home of persistent visual references and character consistency.
37
+
38
+ The Block boundary follows the complete user-placeable Step. Package and remix the complete workspace, including its related tools. For example, Motion Graphics remains inside the Editor; Image Panels, Blueprint, and the Whiteboard Step are each one Block. The White Board Motion Project Type starts with Chat, then three complete Blocks: Voiceover, Whiteboard, and Editor, with no extra Project-Type Block. Historical component IDs may remain resolvable for saved projects without becoming discoverable Blocks.
39
+
40
+ A source snapshot or host alias alone is not portable. A portable workspace owns its interface and executes through an installable SDK runtime. The first-party sm.blueprint@2.0.0, sm.board-editor@2.0.0, sm.editor@2.0.0, and sm.pipeline@2.0.0 packages in the downloadable SDK demonstrate complete sandboxed workspaces using typed documents and the public before/after workspace proposal contract. Whiteboard retains all boards, placed media, timing, transitions, motion settings, and custom fields as one remixable Block. Editor retains Motion Graphics and every other editing tool inside the Editor Block. Canvas retains its native content and layout while the Project Type builder owns Step placement and wiring. Package-supplied React bundles are not exposed; use [custom sandboxed HTML interfaces](custom-interface.md).
@@ -0,0 +1,159 @@
1
+ # Read project context
2
+
3
+ A Step can bind an input to an explicit project context field:
4
+
5
+ ```json
6
+ {
7
+ "inputs": {
8
+ "shots": {"type":"shot[]", "context":"shots"}
9
+ },
10
+ "permissions": {"project":["context.shots.read"]}
11
+ }
12
+ ```
13
+
14
+ Supported fields and exact types:
15
+
16
+ | Context field | Input type | Contents |
17
+ | --- | --- | --- |
18
+ | `script` | `script` | `{schemaVersion:1,text}`; selected-shot narration for a narrow selection |
19
+ | `scenes` | `scene[]` | Existing scene IDs, descriptions, and scoped `shotIds` |
20
+ | `shots` | `shot[]` | Existing shot/panel IDs, scene ownership, descriptions, dialogue and timing |
21
+ | `characters` | `character[]` | Canvas-selected visual references with blueprint descriptions |
22
+ | `locations` | `location[]` | Canvas-selected location references with blueprint descriptions |
23
+ | `styles` | `style[]` | Saved Canvas, blueprint, panel and board styles and references |
24
+ | `assets` | `asset[]` | Current media with `assetId`, `versionId`, `kind`, `url`, source and explicit ownership |
25
+ | `generations` | `metadata[]` | Retained generated-media records with `asset`, `active`, `status`, and saved generation metadata |
26
+ | `versions` | `metadata[]` | Retained media versions and project-level shot-plan/timeline version metadata |
27
+ | `timeline` | `timeline` | Current editor document; filtered collections in a scene/shot/asset selection |
28
+ | `metadata` | `metadata` | Project ID/name and host-selected `scope` |
29
+
30
+ Every binding requires its own `context.<field>.read` permission. These are exact
31
+ permissions: `context.assets.read` does not authorize `context.versions.read`.
32
+ The Step workspace, preview, and future-media worker derive this index from the
33
+ project's current source documents. No duplicate production state is saved.
34
+
35
+ Canvas remains authoritative for its existing asset IDs, approved/current version,
36
+ and selected character/location/style reference galleries. Legacy reference
37
+ images remain available without reselecting deliberately deselected images.
38
+ Panels and White Board Motion supply their existing scenes, panels, collage
39
+ media, transitions and voiceover. The editor supplies media-bin items, clips,
40
+ audio, saved score takes and retained timeline media. An editor item explicitly
41
+ linked by Canvas node/version or panel ID reuses that source identity; a stale
42
+ editor copy cannot promote a different Canvas version. URL-only panel histories
43
+ use deterministic version identifiers that survive history trimming. Different
44
+ assets sharing a URL remain distinct. Legacy global `assets`/`library` caches are
45
+ excluded because they can contain other projects' data.
46
+
47
+ Media history entries contain `{schemaVersion:1, id, assetId, versionId, asset,
48
+ source, active}` and only saved metadata such as timestamp, model or duration.
49
+ Generation entries additionally have `status:"completed"`. Missing model/provider
50
+ metadata is omitted, never guessed from a model currently selected in a control.
51
+ Document history entries contain `documentType`, `versionId`, `active` and a saved
52
+ label/name; they have no `asset`. These metadata entries do not contain old script
53
+ bodies. A URL is a reference, not permission for guest code to fetch it.
54
+
55
+ The host narrows context to the Step's selected scene, shots, or assets before
56
+ binding inputs. Only explicit scene/shot ownership and source associations count;
57
+ unowned media is excluded from narrow selections. Scene documents contain only
58
+ selected `shotIds`, script contains only selected narration, and a narrow timeline
59
+ omits unrelated collections, transcript and timeline histories. Unrelated
60
+ character/location references are excluded. `metadata.scope` describes the
61
+ selection. Guest inputs cannot widen it. Project-wide execution receives the
62
+ project-wide snapshot only for the exact requested fields.
63
+
64
+ `resolveContextInputs(manifest, explicitInputs, projectSnapshot)` copies only
65
+ requested fields into input bindings. Context bindings take precedence over manual
66
+ values. Guests have no live project handle, write-through access, credentials or
67
+ ambient filesystem/network access. Fixture inputs must include concrete context
68
+ values; offline execution does not invent a project. Context delivery is implemented
69
+ in the Step workspace, preview and automatic-processing worker, not the advanced
70
+ Canvas block runner.
71
+
72
+ For example, a history-aware Block can declare:
73
+
74
+ ```json
75
+ {
76
+ "inputs": {"history": {"type": "metadata[]", "context": "versions"}},
77
+ "permissions": {"project": ["context.versions.read"]}
78
+ }
79
+ ```
80
+
81
+ Its code reads `input.history` and checks for `record.asset` when processing media
82
+ records. It must not assume every version describes a file.
83
+
84
+ ## Complete shot-plan context
85
+ Use `{ "type": "shot-plan", "context": "shotPlan", "required": false }`
86
+ with `permissions.project: ["context.shotPlan.read"]` to receive the complete
87
+ saved shot-plan document. This preserves scene grouping, narration, timing and
88
+ other saved planning fields instead of rebuilding a document from flattened
89
+ `shots`. Array-based saved plans are normalized to `{schemaVersion: 1, shots: [...]}`;
90
+ object plans retain their fields with `schemaVersion: 1`.
91
+
92
+ This binding is available only for whole-project context. It is omitted for
93
+ scene, shot and asset selections, and when no plan exists. The host copies the
94
+ value; editing it does not save changes. Use the existing scoped `shots` binding
95
+ for selected-shot processing. Media URLs inside documents grant no media-read
96
+ permission; downloading still requires selected typed asset references and
97
+ `asset.read`. Exporters can also read the saved score from `timeline.audioScore`
98
+ under their existing `context.timeline.read` grant.
99
+
100
+ ## Standalone timeline export
101
+ [Download Export timeline 2.0.0](https://stillmade.shop/block-sdk/examples/export-timeline.stillmade-block).
102
+ This independently versioned JavaScript Block owns serialization and uses generated
103
+ SDK controls plus the shared Download result UI. Add it to a project with a timeline,
104
+ choose XML or XML + media, run it, then download. Its timeline, media, Blueprint,
105
+ shot-plan and project-name inputs bind automatically to authorized project context.
106
+
107
+ The canonical archive includes source, typed ports, UI schema, permissions,
108
+ MIT notices, original-source evidence, lineage and three executable fixtures.
109
+ Validate, test and remix it with the public CLI. No dependencies require manual
110
+ installation. The exact package is also available through the first-party catalog.
111
+
112
+ XML retains media links. ZIP bundles selected timeline media and fails if a
113
+ requested transfer is unavailable. Auxiliary project documents are retained as
114
+ metadata; their unrelated external media is not a full project backup. Device-local
115
+ media and bundled sounds depend on supported host transfers. Normal sandbox and
116
+ download limits apply. This is the existing StillMade XML serializer; compatibility
117
+ with every external editing application has not been established.
118
+
119
+ ## Timed captions and caption styling
120
+ [Download Captions 2.0.0](https://stillmade.shop/block-sdk/examples/captions.stillmade-block). This
121
+ standalone, remixable Block converts a transcript into editable timeline captions.
122
+ It owns phrase grouping, word timing and caption appearance, runs in the JavaScript
123
+ sandbox, and returns ordinary `timeline-edit` proposals for review and Apply.
124
+ It does not transcribe audio or spend execution credits.
125
+
126
+ The optional context binding `{ "type": "transcript", "context": "transcript",
127
+ "required": false }` requires `context.transcript.read`. At whole-project scope
128
+ it supplies a copied `{schemaVersion:1, words:[{text,start,end}], text, audioUrl?}`
129
+ from the saved voiceover when word timings exist. It is omitted when absent and
130
+ for scene, shot or asset selections. URL metadata grants no media access.
131
+ Explicitly connected transcript inputs remain separate from this fallback.
132
+
133
+ Captions uses a connected transcript first, then entered text, then the project's
134
+ saved transcript. Text without word timings uses estimated timing, identified in
135
+ the proposal title. Start offsets word times into the timeline. Duration zero
136
+ keeps transcript timing; a positive duration clips the result to that interval.
137
+ A proposal supports at most 100 lines and rejects longer results without silently
138
+ truncating them. Existing captions stay intact and locked tracks reject Apply.
139
+
140
+ `caption.add` retains its required `{id,trackId,text,start,end}` values and also
141
+ accepts these optional fields. Unknown fields and values outside these limits
142
+ are rejected by the same SDK validator and host apply path:
143
+
144
+ | Field | Accepted values |
145
+ | --- | --- |
146
+ | `words` | Up to 1,000 `{text,start,end}` entries, ordered by start, contained in the caption interval; nonempty text up to 5,000 characters, end at or after start |
147
+ | `font` | `Hanken Grotesk` |
148
+ | `size` | 8–200 |
149
+ | `color`, `highlightColor` | Three- or six-digit hex color |
150
+ | `background` | `none` or three- or six-digit hex color |
151
+ | `backgroundOpacity`, `backgroundPadding`, `backgroundRadius` | 0–100 |
152
+ | `position` | `top`, `middle`, or `bottom` followed by `left`, `center`, or `right`, separated by one space |
153
+ | `animation` | `none` or `fade` |
154
+
155
+ The host fills omitted appearance values with its existing defaults, preserves
156
+ provided styling and clones word timings before saving through ordinary edit
157
+ history. Caption updates retain their existing `{text,start,end}` contract.
158
+ Package source, MIT notices, lineage and three fixtures are retained in the
159
+ canonical archive; validate, test and remix it using the public CLI.