@hypit/hypit 0.1.3 → 0.1.5

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 (486) hide show
  1. package/README.md +5 -3
  2. package/dist/public/caption.d.ts +206 -183
  3. package/dist/public/composition.d.ts +25 -3
  4. package/dist/public/endpoint-kit.d.ts +24 -2
  5. package/dist/public/generation.d.ts +5 -1
  6. package/dist/public/hyperframes.d.ts +19 -1
  7. package/dist/public/narrative.d.ts +17 -3
  8. package/dist/public/performance.d.ts +1590 -0
  9. package/dist/public/program-space.d.ts +179 -32
  10. package/dist/public/runtime-kit.d.ts +21 -8
  11. package/dist/public/sound.d.ts +822 -0
  12. package/dist/public/speech.d.ts +41 -0
  13. package/dist/public/studio-adapter.d.ts +107 -16
  14. package/dist/public/temporal-markup.d.ts +9 -44
  15. package/dist/public/temporal.d.ts +37 -28
  16. package/dist/public/{semantic-track.d.ts → timeline.d.ts} +62 -49
  17. package/examples/README.md +18 -10
  18. package/examples/minimal-author-package/packages/example-component/preview/preview.svml +19 -12
  19. package/examples/minimal-author-package/packages/example-component/src/component.ts +5 -5
  20. package/examples/minimal-author-package/packages/example-component/src/fragment.ts +3 -5
  21. package/examples/minimal-author-package/packages/example-component/src/manifest.ts +8 -10
  22. package/examples/minimal-author-package/packages/example-component/src/surface.ts +2 -2
  23. package/examples/provider-package/README.md +78 -0
  24. package/examples/provider-package/hypit.runtime.json +12 -0
  25. package/examples/provider-package/packages/provider-images/package.json +11 -0
  26. package/examples/provider-package/packages/provider-images/src/activation.ts +24 -0
  27. package/examples/provider-package/packages/provider-images/src/provider.ts +122 -0
  28. package/examples/provider-package/packages/provider-images/tsconfig.json +9 -0
  29. package/examples/semantic-composition/README.md +6 -0
  30. package/examples/semantic-composition/chat.svml +6 -5
  31. package/examples/semantic-composition/packages/chat-scene/README.md +3 -3
  32. package/examples/semantic-composition/packages/chat-scene/src/activation.ts +18 -21
  33. package/examples/semantic-composition/packages/chat-scene/src/render.ts +4 -4
  34. package/examples/semantic-composition/packages/performance-styles/README.md +42 -0
  35. package/examples/semantic-composition/packages/performance-styles/package.json +25 -0
  36. package/examples/semantic-composition/packages/performance-styles/src/activation.ts +57 -0
  37. package/examples/semantic-composition/packages/performance-styles/src/render.ts +54 -0
  38. package/examples/semantic-composition/packages/performance-styles/src/studio.ts +28 -0
  39. package/examples/semantic-composition/packages/performance-styles/tsconfig.json +18 -0
  40. package/examples/semantic-composition/packages/responsive-explainer/README.md +16 -9
  41. package/examples/semantic-composition/packages/responsive-explainer/src/activation.ts +12 -12
  42. package/examples/semantic-composition/packages/responsive-explainer/src/render.ts +5 -5
  43. package/examples/semantic-composition/packages/sound-styles/README.md +36 -0
  44. package/examples/semantic-composition/packages/sound-styles/package.json +25 -0
  45. package/examples/semantic-composition/packages/sound-styles/src/activation.ts +53 -0
  46. package/examples/semantic-composition/packages/sound-styles/src/render.ts +14 -0
  47. package/examples/semantic-composition/packages/sound-styles/tsconfig.json +18 -0
  48. package/package.json +35 -15
  49. package/packages/audio-track/README.md +20 -13
  50. package/packages/audio-track/package.json +1 -1
  51. package/packages/audio-track/src/component.ts +4 -4
  52. package/packages/audio-track/src/fragment.ts +6 -5
  53. package/packages/audio-track/src/index.ts +1 -1
  54. package/packages/audio-track/src/manifest.ts +17 -16
  55. package/packages/audio-track/src/program.ts +21 -25
  56. package/packages/audio-track/src/surface.ts +19 -18
  57. package/packages/audio-track-studio/README.md +23 -0
  58. package/packages/audio-track-studio/src/index.ts +33 -19
  59. package/packages/author-kit/README.md +1 -1
  60. package/packages/background-removal/README.md +4 -7
  61. package/packages/browser-capture/package.json +1 -1
  62. package/packages/build-result/README.md +69 -0
  63. package/packages/build-result/package.json +2 -1
  64. package/packages/build-result/src/decode.ts +12 -8
  65. package/packages/build-result/src/execution-log.ts +17 -0
  66. package/packages/build-result/src/file-reference.ts +42 -0
  67. package/packages/build-result/src/index.ts +4 -0
  68. package/packages/build-result/src/replace-file-windows.ts +58 -0
  69. package/packages/build-result/src/replace-file.ts +11 -0
  70. package/packages/build-result/src/store.ts +58 -14
  71. package/packages/build-result/src/types.ts +41 -8
  72. package/packages/build-result/src/writer.ts +12 -1
  73. package/packages/build-result-fs/README.md +23 -1
  74. package/packages/build-result-s3/README.md +5 -0
  75. package/packages/build-result-s3/src/repository.ts +23 -5
  76. package/packages/caption/README.md +61 -73
  77. package/packages/caption/package.json +3 -2
  78. package/packages/caption/src/activation.ts +2 -2
  79. package/packages/caption/src/component.ts +20 -5
  80. package/packages/caption/src/display.ts +3 -18
  81. package/packages/caption/src/fragment.ts +3 -7
  82. package/packages/caption/src/index.ts +6 -5
  83. package/packages/caption/src/manifest.ts +29 -46
  84. package/packages/caption/src/style.ts +24 -135
  85. package/packages/caption/src/surface.ts +12 -92
  86. package/packages/caption/src/temporalize.ts +18 -53
  87. package/packages/caption/src/types.ts +8 -35
  88. package/packages/caption/src/visibility.ts +23 -0
  89. package/packages/caption-fine/README.md +31 -11
  90. package/packages/caption-fine/package.json +4 -2
  91. package/packages/caption-fine/src/component.ts +3 -3
  92. package/packages/caption-fine/src/fragment.ts +7 -19
  93. package/packages/caption-fine/src/index.ts +2 -0
  94. package/packages/caption-fine/src/manifest.ts +27 -18
  95. package/packages/caption-fine/src/recipe.ts +7 -0
  96. package/packages/caption-fine/src/render.ts +62 -49
  97. package/packages/caption-fine/src/schedule.ts +39 -35
  98. package/packages/caption-fine/src/style.ts +10 -9
  99. package/packages/caption-fine/src/surface.ts +62 -35
  100. package/packages/caption-fine/src/types.ts +2 -0
  101. package/packages/caption-fine-studio/README.md +24 -2
  102. package/packages/caption-fine-studio/package.json +10 -3
  103. package/packages/caption-fine-studio/src/activation.ts +3 -3
  104. package/packages/caption-fine-studio/src/index.ts +61 -40
  105. package/packages/cli/README.md +81 -3
  106. package/packages/cli/package.json +1 -0
  107. package/packages/cli/src/arguments.ts +39 -15
  108. package/packages/cli/src/build-planning.ts +9 -3
  109. package/packages/cli/src/command.ts +7 -1
  110. package/packages/cli/src/commands/environment.ts +66 -27
  111. package/packages/cli/src/commands/execution.ts +81 -26
  112. package/packages/cli/src/commands/results.ts +7 -11
  113. package/packages/cli/src/index.ts +2 -2
  114. package/packages/cli/src/machine-view.ts +15 -5
  115. package/packages/cli/src/main.ts +38 -42
  116. package/packages/cli/src/observation.ts +7 -1
  117. package/packages/cli/src/output.ts +92 -34
  118. package/packages/cli/src/result-export.ts +22 -13
  119. package/packages/cli/src/run-file.ts +19 -8
  120. package/packages/cli/src/view.ts +64 -18
  121. package/packages/comment-sticker/README.md +3 -3
  122. package/packages/comment-sticker/package.json +1 -1
  123. package/packages/comment-sticker/src/component.ts +4 -4
  124. package/packages/comment-sticker/src/fragment.ts +5 -4
  125. package/packages/comment-sticker/src/manifest.ts +7 -6
  126. package/packages/comment-sticker/src/program.ts +9 -9
  127. package/packages/comment-sticker/src/surface.ts +6 -7
  128. package/packages/comment-sticker-studio/src/index.ts +2 -1
  129. package/packages/compiler-node/src/compiler.ts +1 -0
  130. package/packages/composition/README.md +21 -0
  131. package/packages/composition/src/audio-presentation.ts +44 -0
  132. package/packages/composition/src/index.ts +3 -0
  133. package/packages/composition/src/schema.ts +8 -3
  134. package/packages/composition/src/track.ts +15 -1
  135. package/packages/credential-store-env/README.md +1 -1
  136. package/packages/deck-track/README.md +3 -3
  137. package/packages/deck-track/package.json +1 -1
  138. package/packages/deck-track/src/component.ts +5 -5
  139. package/packages/deck-track/src/fragment.ts +6 -5
  140. package/packages/deck-track/src/lower.ts +12 -12
  141. package/packages/deck-track/src/manifest.ts +8 -7
  142. package/packages/deck-track/src/program.ts +13 -16
  143. package/packages/deck-track/src/surface.ts +9 -10
  144. package/packages/driver-node/src/driver.ts +41 -3
  145. package/packages/elevenlabs-speech/README.md +27 -0
  146. package/packages/{provider-xiaomi-mimo → elevenlabs-speech}/package.json +5 -8
  147. package/packages/elevenlabs-speech/src/activation.ts +26 -0
  148. package/packages/elevenlabs-speech/src/fragment.ts +11 -0
  149. package/packages/elevenlabs-speech/src/index.ts +111 -0
  150. package/packages/elevenlabs-speech/src/surface.ts +167 -0
  151. package/packages/endpoint-kit/README.md +24 -0
  152. package/packages/endpoint-kit/src/index.ts +7 -1
  153. package/packages/estimate/README.md +56 -3
  154. package/packages/estimate/src/program.ts +7 -8
  155. package/packages/film/README.md +12 -7
  156. package/packages/film/package.json +1 -1
  157. package/packages/film/src/component.ts +4 -4
  158. package/packages/film/src/fragment.ts +6 -5
  159. package/packages/film/src/manifest.ts +11 -10
  160. package/packages/film/src/program.ts +5 -5
  161. package/packages/film/src/recipe.ts +2 -1
  162. package/packages/film/src/surface.ts +6 -6
  163. package/packages/film-studio/package.json +1 -1
  164. package/packages/film-studio/src/index.ts +2 -2
  165. package/packages/fishaudio-speech/README.md +33 -0
  166. package/packages/fishaudio-speech/package.json +21 -0
  167. package/packages/fishaudio-speech/src/activation.ts +32 -0
  168. package/packages/fishaudio-speech/src/fragment.ts +11 -0
  169. package/packages/fishaudio-speech/src/index.ts +156 -0
  170. package/packages/fishaudio-speech/src/surface.ts +192 -0
  171. package/packages/fonts-open/README.md +5 -0
  172. package/packages/fonts-open/package.json +5 -1
  173. package/packages/fonts-open/src/studio.ts +21 -0
  174. package/packages/generation/README.md +11 -1
  175. package/packages/generation/src/mapping.ts +28 -30
  176. package/packages/gpt-image/README.md +1 -2
  177. package/packages/grok-imagine/README.md +1 -2
  178. package/packages/hyperframes/README.md +7 -3
  179. package/packages/hyperframes/src/browser-program.ts +11 -2
  180. package/packages/hyperframes/src/document.ts +15 -2
  181. package/packages/interview-emoji-reveal/README.md +4 -4
  182. package/packages/interview-emoji-reveal/package.json +1 -1
  183. package/packages/interview-emoji-reveal/src/component.ts +4 -4
  184. package/packages/interview-emoji-reveal/src/fragment.ts +6 -5
  185. package/packages/interview-emoji-reveal/src/manifest.ts +9 -8
  186. package/packages/interview-emoji-reveal/src/program.ts +14 -14
  187. package/packages/interview-emoji-reveal/src/surface.ts +8 -9
  188. package/packages/media-execution/README.md +7 -3
  189. package/packages/media-execution/src/audio-presentation.ts +23 -0
  190. package/packages/media-execution/src/execute.ts +2 -0
  191. package/packages/media-pipeline/README.md +7 -3
  192. package/packages/media-pipeline/src/audio-plan.ts +4 -1
  193. package/packages/media-pipeline/src/component.ts +16 -2
  194. package/packages/media-pipeline/src/manifest.ts +3 -1
  195. package/packages/media-pipeline/src/types.ts +2 -1
  196. package/packages/media-track/README.md +14 -47
  197. package/packages/media-track/package.json +1 -1
  198. package/packages/media-track/preview/preview.svml +5 -5
  199. package/packages/media-track/src/author.ts +12 -6
  200. package/packages/media-track/src/component.ts +10 -16
  201. package/packages/media-track/src/fragment.ts +8 -7
  202. package/packages/media-track/src/index.ts +3 -1
  203. package/packages/media-track/src/lower.ts +7 -7
  204. package/packages/media-track/src/manifest.ts +16 -38
  205. package/packages/media-track/src/program.ts +62 -67
  206. package/packages/media-track/src/sampling.ts +6 -6
  207. package/packages/media-track/src/sequence.ts +8 -8
  208. package/packages/media-track/src/surface.ts +25 -43
  209. package/packages/media-track-studio/README.md +9 -0
  210. package/packages/media-track-studio/src/index.ts +23 -13
  211. package/packages/mimo-speech/README.md +1 -1
  212. package/packages/minimax-h3/README.md +1 -1
  213. package/packages/nano-banana/README.md +1 -1
  214. package/packages/narrative/README.md +23 -1
  215. package/packages/narrative/src/identity.ts +11 -0
  216. package/packages/narrative/src/index.ts +3 -0
  217. package/packages/narrative/src/schema.ts +28 -27
  218. package/packages/narrative/src/selection.ts +52 -0
  219. package/packages/narrative/src/types.ts +2 -0
  220. package/packages/package-loader-node/README.md +30 -0
  221. package/packages/package-loader-node/package.json +5 -2
  222. package/packages/package-loader-node/src/distribution-resolution.ts +10 -3
  223. package/packages/package-loader-node/src/index.ts +1 -0
  224. package/packages/package-loader-node/src/loader.ts +12 -15
  225. package/packages/package-loader-node/src/location.ts +27 -1
  226. package/packages/package-loader-node/src/module-scope.ts +183 -0
  227. package/packages/package-loader-node/src/types.ts +4 -0
  228. package/packages/performance/README.md +83 -0
  229. package/packages/performance/package.json +30 -0
  230. package/packages/performance/src/activation.ts +11 -0
  231. package/packages/performance/src/component.ts +46 -0
  232. package/packages/performance/src/index.ts +6 -0
  233. package/packages/performance/src/manifest.ts +53 -0
  234. package/packages/{media-track/src/performance.ts → performance/src/media.ts} +9 -10
  235. package/packages/performance/src/program.ts +51 -0
  236. package/packages/performance/src/style.ts +35 -0
  237. package/packages/performance/src/surface.ts +99 -0
  238. package/packages/performance-studio/README.md +25 -0
  239. package/packages/performance-studio/package.json +21 -0
  240. package/packages/performance-studio/src/activation.ts +6 -0
  241. package/packages/performance-studio/src/index.ts +84 -0
  242. package/packages/program-space/README.md +9 -18
  243. package/packages/program-space/src/activation.ts +1 -5
  244. package/packages/program-space/src/index.ts +2 -11
  245. package/packages/program-space/src/surface.ts +1 -20
  246. package/packages/project-context-node/README.md +20 -0
  247. package/packages/project-context-node/package.json +10 -0
  248. package/packages/project-context-node/src/index.ts +3 -0
  249. package/packages/{cli → project-context-node}/src/runtime-selection.ts +7 -2
  250. package/packages/provider-hyperframes-local/README.md +43 -15
  251. package/packages/provider-hyperframes-local/src/activation.ts +4 -3
  252. package/packages/provider-hyperframes-local/src/capture-process.ts +26 -4
  253. package/packages/provider-hyperframes-local/src/capture.ts +96 -26
  254. package/packages/provider-hyperframes-local/src/concurrency.ts +86 -0
  255. package/packages/provider-hyperframes-local/src/opaque-capture.ts +92 -0
  256. package/packages/provider-hyperframes-local/src/options.ts +2 -0
  257. package/packages/provider-hyperframes-local/src/program.ts +6 -3
  258. package/packages/provider-hyperframes-local/src/progress.ts +53 -0
  259. package/packages/provider-hyperframes-local/src/provider.ts +18 -5
  260. package/packages/provider-hyperframes-local/src/render.ts +48 -7
  261. package/packages/provider-hypihub/README.md +48 -17
  262. package/packages/provider-hypihub/package.json +2 -0
  263. package/packages/provider-hypihub/src/mapping.ts +31 -7
  264. package/packages/provider-hypihub/src/oauth.ts +6 -0
  265. package/packages/provider-hypihub/src/provider.ts +25 -13
  266. package/packages/provider-hypihub/src/routes.ts +1 -2
  267. package/packages/provider-hypihub/src/upload.ts +2 -0
  268. package/packages/provider-media-local/README.md +3 -4
  269. package/packages/provider-whisperx-local/README.md +57 -0
  270. package/packages/provider-whisperx-local/src/program.ts +1 -0
  271. package/packages/provider-whisperx-local/src/provider.ts +3 -0
  272. package/packages/ranking/README.md +8 -6
  273. package/packages/ranking/package.json +1 -1
  274. package/packages/ranking/src/component.ts +6 -6
  275. package/packages/ranking/src/fragment.ts +11 -7
  276. package/packages/ranking/src/manifest.ts +21 -14
  277. package/packages/ranking/src/render.ts +33 -35
  278. package/packages/ranking/src/schedule.ts +16 -19
  279. package/packages/ranking/src/surface.ts +12 -13
  280. package/packages/ranking-studio/README.md +29 -0
  281. package/packages/ranking-studio/package.json +8 -3
  282. package/packages/ranking-studio/src/index.ts +71 -12
  283. package/packages/render-hyperframes/README.md +7 -7
  284. package/packages/render-hyperframes/package.json +1 -1
  285. package/packages/render-hyperframes/src/component.ts +11 -1
  286. package/packages/render-hyperframes/src/fragment.ts +7 -4
  287. package/packages/render-hyperframes/src/manifest.ts +4 -4
  288. package/packages/render-hyperframes/src/surface.ts +6 -6
  289. package/packages/runtime/README.md +8 -1
  290. package/packages/runtime/src/catalog.ts +2 -0
  291. package/packages/runtime/src/execution.ts +15 -4
  292. package/packages/runtime/src/index.ts +2 -1
  293. package/packages/runtime/src/log.ts +51 -0
  294. package/packages/runtime/src/types.ts +5 -8
  295. package/packages/runtime-host-node/README.md +30 -0
  296. package/packages/runtime-host-node/package.json +1 -0
  297. package/packages/runtime-host-node/src/index.ts +25 -9
  298. package/packages/runtime-host-node/src/packages.ts +47 -50
  299. package/packages/runtime-kit/README.md +5 -0
  300. package/packages/runtime-kit/src/index.ts +3 -1
  301. package/packages/runtime-local/README.md +111 -4
  302. package/packages/runtime-local/src/config.ts +202 -56
  303. package/packages/runtime-local/src/control.ts +9 -1
  304. package/packages/runtime-local/src/executor.ts +66 -0
  305. package/packages/runtime-local/src/host.ts +37 -17
  306. package/packages/runtime-local/src/log.ts +48 -0
  307. package/packages/runtime-local/src/programs.ts +41 -25
  308. package/packages/runtime-local/src/result-writer.ts +2 -0
  309. package/packages/runtime-local/src/runtime.ts +10 -6
  310. package/packages/runtime-local/src/supervisor.ts +142 -0
  311. package/packages/runtime-local/src/types.ts +9 -2
  312. package/packages/runtime-local/src/worker-process.ts +7 -24
  313. package/packages/runtime-local/src/worker.ts +55 -83
  314. package/packages/screen-overlay/README.md +3 -3
  315. package/packages/screen-overlay/package.json +1 -1
  316. package/packages/screen-overlay/src/component.ts +3 -3
  317. package/packages/screen-overlay/src/fragment.ts +5 -4
  318. package/packages/screen-overlay/src/manifest.ts +7 -6
  319. package/packages/screen-overlay/src/program.ts +9 -9
  320. package/packages/screen-overlay/src/surface.ts +6 -7
  321. package/packages/script/README.md +37 -2
  322. package/packages/script/src/edit.ts +123 -73
  323. package/packages/script/src/lexical.ts +40 -6
  324. package/packages/script/src/manifest.ts +2 -2
  325. package/packages/script/src/narrative.ts +1 -0
  326. package/packages/script/src/parser.ts +36 -8
  327. package/packages/script/src/surface.ts +4 -3
  328. package/packages/script/src/types.ts +5 -1
  329. package/packages/script-studio/package.json +9 -3
  330. package/packages/script-studio/src/index.ts +2 -0
  331. package/packages/script-studio/src/projection.ts +105 -0
  332. package/packages/seedance/README.md +30 -1
  333. package/packages/seedance/src/index.ts +18 -7
  334. package/packages/seedance/src/surface.ts +17 -4
  335. package/packages/seedance-kits/README.md +10 -2
  336. package/packages/seedance-kits/kits/speaker-v1.svs +5 -5
  337. package/packages/seedream/README.md +1 -1
  338. package/packages/sound/README.md +81 -0
  339. package/packages/sound/package.json +25 -0
  340. package/packages/sound/src/activation.ts +11 -0
  341. package/packages/sound/src/component.ts +28 -0
  342. package/packages/sound/src/index.ts +5 -0
  343. package/packages/sound/src/manifest.ts +47 -0
  344. package/packages/sound/src/program.ts +84 -0
  345. package/packages/sound/src/style.ts +34 -0
  346. package/packages/sound/src/surface.ts +90 -0
  347. package/packages/sound-studio/README.md +22 -0
  348. package/packages/sound-studio/package.json +20 -0
  349. package/packages/sound-studio/src/activation.ts +6 -0
  350. package/packages/sound-studio/src/index.ts +74 -0
  351. package/packages/speech/README.md +2 -2
  352. package/packages/speech-alignment/src/align.ts +45 -21
  353. package/packages/speech-alignment/src/local.ts +8 -0
  354. package/packages/speech-alignment/src/locate.ts +1 -1
  355. package/packages/store-sqlite/README.md +7 -0
  356. package/packages/store-sqlite/src/store.ts +84 -83
  357. package/packages/studio/INSPECTOR.md +117 -0
  358. package/packages/studio/README.md +149 -14
  359. package/packages/studio/package.json +8 -7
  360. package/packages/studio/src/build-library.ts +99 -84
  361. package/packages/studio/src/companion-assembly.ts +1 -0
  362. package/packages/studio/src/domain.ts +1 -1
  363. package/packages/studio/src/fallback-companions.ts +3 -3
  364. package/packages/studio/src/feedback-server.ts +51 -0
  365. package/packages/studio/src/feedback-store.ts +66 -0
  366. package/packages/studio/src/feedback.ts +60 -0
  367. package/packages/studio/src/library-media.ts +19 -0
  368. package/packages/studio/src/parameter-values.ts +83 -1
  369. package/packages/studio/src/parameters.ts +132 -43
  370. package/packages/studio/src/preview/render.ts +5 -1
  371. package/packages/studio/src/preview/runtime-shim.ts +49 -3
  372. package/packages/studio/src/programme.ts +14 -30
  373. package/packages/studio/src/server.ts +66 -34
  374. package/packages/studio/src/shared.ts +24 -8
  375. package/packages/studio/src/snapshot.ts +21 -132
  376. package/packages/studio/src/studio-preflight.ts +3 -3
  377. package/packages/studio/src/studio-registry.ts +72 -6
  378. package/packages/studio/src/style.css +342 -190
  379. package/packages/studio/src/temporal-edit.ts +131 -0
  380. package/packages/studio/src/ui/artifact-name.ts +80 -0
  381. package/packages/studio/src/ui/artifact-preview.ts +99 -0
  382. package/packages/studio/src/ui/comments.ts +233 -0
  383. package/packages/studio/src/ui/icons.ts +10 -1
  384. package/packages/studio/src/ui/library.ts +373 -192
  385. package/packages/studio/src/ui/main.ts +291 -110
  386. package/packages/studio/src/ui/material-preview.ts +1 -1
  387. package/packages/studio/src/ui/overlay.ts +31 -26
  388. package/packages/studio/src/ui/scrub-preview.ts +108 -0
  389. package/packages/studio/src/ui/sidebar-panel.ts +31 -0
  390. package/packages/studio/src/ui/stage.ts +188 -9
  391. package/packages/studio/src/ui/timeline.ts +187 -281
  392. package/packages/studio/start.ts +19 -5
  393. package/packages/studio-adapter/README.md +151 -11
  394. package/packages/studio-adapter/src/index.ts +126 -14
  395. package/packages/temporal/README.md +6 -6
  396. package/packages/temporal/package.json +1 -1
  397. package/packages/temporal/src/component.ts +5 -6
  398. package/packages/temporal/src/index.ts +8 -6
  399. package/packages/temporal/src/location.ts +11 -11
  400. package/packages/temporal/src/projection.ts +19 -19
  401. package/packages/temporal/src/rational.ts +4 -4
  402. package/packages/temporal-markup/EDITING.md +183 -0
  403. package/packages/temporal-markup/README.md +31 -11
  404. package/packages/temporal-markup/package.json +1 -1
  405. package/packages/temporal-markup/src/index.ts +20 -25
  406. package/packages/temporal-markup/src/space.ts +10 -41
  407. package/packages/timeline/README.md +31 -0
  408. package/packages/{semantic-track → timeline}/package.json +1 -1
  409. package/packages/timeline/src/activation.ts +8 -0
  410. package/packages/timeline/src/component.ts +24 -0
  411. package/packages/timeline/src/identity.ts +60 -0
  412. package/packages/timeline/src/index.ts +6 -0
  413. package/packages/{semantic-track → timeline}/src/location.ts +20 -20
  414. package/packages/timeline/src/manifest.ts +39 -0
  415. package/packages/{semantic-track → timeline}/src/projection.ts +14 -14
  416. package/packages/timeline/src/types.ts +24 -0
  417. package/packages/timeline-author/README.md +68 -0
  418. package/packages/{speech-track → timeline-author}/package.json +6 -4
  419. package/packages/timeline-author/src/activation.ts +22 -0
  420. package/packages/{speech-track → timeline-author}/src/component.ts +15 -13
  421. package/packages/{speech-track → timeline-author}/src/fragment.ts +14 -23
  422. package/packages/timeline-author/src/index.ts +7 -0
  423. package/packages/timeline-author/src/manifest.ts +78 -0
  424. package/packages/timeline-author/src/program.ts +107 -0
  425. package/packages/timeline-author/src/surface.ts +46 -0
  426. package/packages/timeline-author/src/types.ts +6 -0
  427. package/packages/typography-track/README.md +4 -4
  428. package/packages/typography-track/package.json +1 -1
  429. package/packages/typography-track/src/component.ts +4 -4
  430. package/packages/typography-track/src/fragment.ts +4 -3
  431. package/packages/typography-track/src/manifest.ts +11 -9
  432. package/packages/typography-track/src/program.ts +15 -15
  433. package/packages/typography-track/src/surface.ts +17 -18
  434. package/packages/typography-track-studio/package.json +8 -3
  435. package/packages/typography-track-studio/src/index.ts +5 -1
  436. package/packages/video-cli/README.md +16 -4
  437. package/packages/video-cli/package.json +2 -1
  438. package/packages/video-cli/src/creation.ts +25 -9
  439. package/packages/video-cli/src/index.ts +1 -1
  440. package/packages/video-cli/src/studio-distribution.ts +2 -1
  441. package/packages/volcengine-matting/README.md +3 -3
  442. package/packages/whisperx/README.md +8 -1
  443. package/packages/workspace/src/index.ts +2 -0
  444. package/packages/workspace-fs-node/README.md +4 -1
  445. package/packages/workspace-fs-node/src/workspace.ts +3 -1
  446. package/services/whisperx/README.md +14 -0
  447. package/services/whisperx/pyproject.toml +2 -0
  448. package/services/whisperx/uv.lock +20 -20
  449. package/packages/provider-hyperframes-aws-lambda/README.md +0 -30
  450. package/packages/provider-hyperframes-aws-lambda/package.json +0 -30
  451. package/packages/provider-hyperframes-aws-lambda/src/activation.ts +0 -97
  452. package/packages/provider-hyperframes-aws-lambda/src/client.ts +0 -114
  453. package/packages/provider-hyperframes-aws-lambda/src/index.ts +0 -21
  454. package/packages/provider-hyperframes-aws-lambda/src/provider.ts +0 -522
  455. package/packages/provider-kie/README.md +0 -134
  456. package/packages/provider-kie/package.json +0 -43
  457. package/packages/provider-kie/src/activation.ts +0 -71
  458. package/packages/provider-kie/src/index.ts +0 -10
  459. package/packages/provider-kie/src/mapping.ts +0 -182
  460. package/packages/provider-kie/src/provider.ts +0 -657
  461. package/packages/provider-kie/src/routes.ts +0 -150
  462. package/packages/provider-xiaomi-mimo/README.md +0 -32
  463. package/packages/provider-xiaomi-mimo/src/activation.ts +0 -57
  464. package/packages/provider-xiaomi-mimo/src/index.ts +0 -5
  465. package/packages/provider-xiaomi-mimo/src/provider.ts +0 -214
  466. package/packages/runtime/src/environment.ts +0 -6
  467. package/packages/semantic-track/README.md +0 -21
  468. package/packages/semantic-track/src/activation.ts +0 -8
  469. package/packages/semantic-track/src/component.ts +0 -24
  470. package/packages/semantic-track/src/identity.ts +0 -58
  471. package/packages/semantic-track/src/index.ts +0 -6
  472. package/packages/semantic-track/src/manifest.ts +0 -38
  473. package/packages/semantic-track/src/types.ts +0 -26
  474. package/packages/speech-track/README.md +0 -51
  475. package/packages/speech-track/src/activation.ts +0 -19
  476. package/packages/speech-track/src/index.ts +0 -7
  477. package/packages/speech-track/src/manifest.ts +0 -73
  478. package/packages/speech-track/src/program.ts +0 -64
  479. package/packages/speech-track/src/surface.ts +0 -35
  480. package/packages/speech-track/src/types.ts +0 -6
  481. package/packages/speech-track-studio/README.md +0 -3
  482. package/packages/speech-track-studio/package.json +0 -14
  483. package/packages/speech-track-studio/src/activation.ts +0 -7
  484. package/packages/speech-track-studio/src/index.ts +0 -40
  485. /package/packages/{cli → project-context-node}/src/project-context.ts +0 -0
  486. /package/packages/{speech-track → timeline-author}/preview/Track.png +0 -0
@@ -0,0 +1,42 @@
1
+ import { createReadStream } from "node:fs";
2
+ import { stat } from "node:fs/promises";
3
+ import { fileURLToPath } from "node:url";
4
+ import type { BuildResultFileRange, BuildResultFileRef } from "./types.js";
5
+
6
+ /** Address access belongs to the Repository adapter, not the value or domain graph. */
7
+ export type ExternalFileAccess = {
8
+ size(uri: string): Promise<number>;
9
+ open(uri: string, range?: BuildResultFileRange): Promise<AsyncIterable<Uint8Array>>;
10
+ };
11
+
12
+ /** The Node distribution's external files are explicit file: URLs supplied by its Workspace. */
13
+ export const localExternalFiles: ExternalFileAccess = {
14
+ async size(uri) { return (await stat(fileURLToPath(uri))).size; },
15
+ async open(uri, range) {
16
+ if (range !== undefined) {
17
+ const size = await localExternalFiles.size(uri);
18
+ if (!Number.isSafeInteger(range.start) || range.start < 0
19
+ || !Number.isSafeInteger(range.endExclusive) || range.endExclusive <= range.start
20
+ || range.endExclusive > size) throw new Error(`Invalid file range for ${uri}`);
21
+ }
22
+ return createReadStream(fileURLToPath(uri), range === undefined ? {} : { start: range.start, end: range.endExclusive - 1 });
23
+ },
24
+ };
25
+
26
+ export function fileReferenceIdentity(owner: string, file: BuildResultFileRef): string {
27
+ return file.kind === "external-file" ? JSON.stringify(["external", file.uri])
28
+ : JSON.stringify(["result", file.build ?? owner, file.path]);
29
+ }
30
+
31
+ /** Make a relative Result file reference independent of its enclosing value document. */
32
+ export function ownedFileReference(owner: string, file: BuildResultFileRef): BuildResultFileRef {
33
+ return file.kind === "build-file" ? { ...file, build: file.build ?? owner } : file;
34
+ }
35
+
36
+ /** Reopening an external reference reads its current metadata, without comparing versions. */
37
+ export async function currentFileReference(
38
+ file: BuildResultFileRef,
39
+ access: ExternalFileAccess = localExternalFiles,
40
+ ): Promise<BuildResultFileRef> {
41
+ return file.kind === "external-file" ? { ...file, size: await access.size(file.uri) } : file;
42
+ }
@@ -23,3 +23,7 @@ export {
23
23
  } from "./store.js";
24
24
  export type * from "./types.js";
25
25
  export type * from "./writer.js";
26
+
27
+ export { currentFileReference, fileReferenceIdentity, ownedFileReference, localExternalFiles } from "./file-reference.js";
28
+ export type { ExternalFileAccess } from "./file-reference.js";
29
+ export { preserveExecutionLog } from "./execution-log.js";
@@ -0,0 +1,58 @@
1
+ import { toNamespacedPath } from "node:path";
2
+ import koffi from "koffi";
3
+
4
+ const kernel = koffi.load("kernel32.dll");
5
+ const createFile = kernel.func("intptr_t __stdcall CreateFileW(const char16_t *path, uint32_t access, uint32_t share, void *security, uint32_t disposition, uint32_t attributes, intptr_t templateFile)");
6
+ const setInformation = kernel.func("int __stdcall SetFileInformationByHandle(intptr_t file, int infoClass, void *info, uint32_t size)");
7
+ const closeHandle = kernel.func("int __stdcall CloseHandle(intptr_t file)");
8
+ const getLastError = kernel.func("uint32_t __stdcall GetLastError()");
9
+
10
+ const renameInfo = koffi.struct({
11
+ Flags: "uint32_t",
12
+ RootDirectory: "void *",
13
+ FileNameLength: "uint32_t",
14
+ FileName: koffi.array("uint16_t", 1),
15
+ });
16
+
17
+ const DELETE = 0x00010000;
18
+ const SHARE_READ_WRITE_DELETE = 0x7;
19
+ const OPEN_EXISTING = 3;
20
+ const FILE_ATTRIBUTE_NORMAL = 0x80;
21
+ const FileRenameInfoEx = 22;
22
+ const REPLACE_IF_EXISTS = 0x1;
23
+ const POSIX_SEMANTICS = 0x2;
24
+
25
+ function failure(syscall: string, from: string, to: string): Error {
26
+ const win32Code = getLastError() as number;
27
+ return Object.assign(new Error(`Windows file replacement failed (${win32Code}): '${from}' -> '${to}'`), {
28
+ code: `WIN32_${win32Code}`, win32Code, syscall, path: from, dest: to,
29
+ });
30
+ }
31
+
32
+ /**
33
+ * FileRenameInfoEx preserves open readers of the old file while publishing the new name.
34
+ * Node's Windows rename uses MoveFileExW, whose replacement semantics differ here.
35
+ * https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/4217551b-d2c0-42cb-9dc1-69a716cf6d0c
36
+ */
37
+ export function replaceWindowsFile(from: string, to: string): void {
38
+ const filename = Buffer.from(toNamespacedPath(to), "utf16le");
39
+ const nameOffset = koffi.offsetof(renameInfo, "FileName");
40
+ // Win32 requires a NUL-terminated FileName even though FileNameLength excludes
41
+ // that terminator. Buffer.alloc leaves the final WCHAR zero-initialized.
42
+ // https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-file_rename_info
43
+ const info = Buffer.alloc(Math.max(koffi.sizeof(renameInfo), nameOffset + filename.length + 2));
44
+ info.writeUInt32LE(REPLACE_IF_EXISTS | POSIX_SEMANTICS, koffi.offsetof(renameInfo, "Flags"));
45
+ info.writeUInt32LE(filename.length, koffi.offsetof(renameInfo, "FileNameLength"));
46
+ filename.copy(info, nameOffset);
47
+
48
+ const handle = createFile(toNamespacedPath(from), DELETE, SHARE_READ_WRITE_DELETE,
49
+ null, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0) as number | bigint;
50
+ if (handle === -1 || handle === -1n) throw failure("CreateFileW", from, to);
51
+ try {
52
+ if (!setInformation(handle, FileRenameInfoEx, info, info.length)) {
53
+ throw failure("SetFileInformationByHandle", from, to);
54
+ }
55
+ } finally {
56
+ closeHandle(handle);
57
+ }
58
+ }
@@ -0,0 +1,11 @@
1
+ import { rename } from "node:fs/promises";
2
+
3
+ /** Publish a complete file without changing the bytes held by existing readers. */
4
+ export async function replaceFile(from: string, to: string): Promise<void> {
5
+ if (process.platform === "win32") {
6
+ const { replaceWindowsFile } = await import("./replace-file-windows.js");
7
+ replaceWindowsFile(from, to);
8
+ } else {
9
+ await rename(from, to);
10
+ }
11
+ }
@@ -1,3 +1,6 @@
1
+ import { preserveExecutionLog } from "./execution-log.js";
2
+ import { currentFileReference, localExternalFiles } from "./file-reference.js";
3
+ import type { ExternalFileAccess } from "./file-reference.js";
1
4
  import { randomUUID } from "node:crypto";
2
5
  import {
3
6
  mkdir,
@@ -40,6 +43,7 @@ import {
40
43
  encodeBuildResultManifest,
41
44
  } from "./decode.js";
42
45
  import { syncBuildResultOutputs } from "./writer.js";
46
+ import { replaceFile } from "./replace-file.js";
43
47
 
44
48
  const manifestName = "result.json";
45
49
  const writerStateName = ".writer.json";
@@ -83,6 +87,22 @@ export function applyBuildResultPresentation(
83
87
  if (highlighted.length === 0) delete base.highlightedOutputs;
84
88
  else base.highlightedOutputs = highlighted;
85
89
  }
90
+ if (update.outputDisplayNames !== undefined) {
91
+ const outputs = { ...manifest.outputs };
92
+ for (const [name, value] of Object.entries(update.outputDisplayNames)) {
93
+ const entry = manifest.outputs[name];
94
+ assert(Object.hasOwn(manifest.outputs, name) && entry !== undefined,
95
+ `Build Result ${manifest.id} has no Output ${name}`);
96
+ const { displayName: _priorName, ...rest } = entry;
97
+ if (value === null) outputs[name] = rest;
98
+ else {
99
+ const displayName = value.trim();
100
+ assert(displayName.length > 0, "Output display name must not be empty");
101
+ outputs[name] = { ...rest, displayName };
102
+ }
103
+ }
104
+ return { ...base, outputs };
105
+ }
86
106
  return base;
87
107
  }
88
108
 
@@ -95,7 +115,7 @@ async function writeJsonAtomic(path: string, value: unknown): Promise<void> {
95
115
  const temporary = `${path}.part-${randomUUID()}`;
96
116
  try {
97
117
  await writeFile(temporary, `${JSON.stringify(value, null, 2)}\n`, { flag: "wx" });
98
- await rename(temporary, path);
118
+ await replaceFile(temporary, path);
99
119
  } catch (error) {
100
120
  await rm(temporary, { force: true });
101
121
  throw error;
@@ -115,15 +135,24 @@ async function copyArtifactAtomic(
115
135
  await mkdir(dirname(destination), { recursive: true });
116
136
  const input = await source.open(artifact);
117
137
  if (input === undefined) throw new Error(`Build resource ${artifact.resource} is unavailable`);
138
+ await writeStreamAtomic(destination, input);
139
+ }
140
+
141
+ async function writeStreamAtomic(destination: string, input: AsyncIterable<Uint8Array>): Promise<void> {
142
+ await mkdir(dirname(destination), { recursive: true });
118
143
  const temporary = `${destination}.part-${randomUUID()}`;
119
144
  const output = await open(temporary, "wx");
120
145
  try {
121
146
  for await (const value of input) {
122
147
  const chunk = Uint8Array.from(value);
123
- await output.write(chunk);
148
+ let offset = 0;
149
+ while (offset < chunk.byteLength) {
150
+ const { bytesWritten } = await output.write(chunk, offset, chunk.byteLength - offset);
151
+ offset += bytesWritten;
152
+ }
124
153
  }
125
154
  await output.close();
126
- await rename(temporary, destination);
155
+ await replaceFile(temporary, destination);
127
156
  } catch (error) {
128
157
  await output.close().catch(() => undefined);
129
158
  await rm(temporary, { force: true });
@@ -221,6 +250,7 @@ export async function resolveBuildResultOutput(
221
250
  root: string,
222
251
  build: string,
223
252
  output: string,
253
+ externalFiles: ExternalFileAccess = localExternalFiles,
224
254
  ): Promise<ResolvedBuildResultOutput | undefined> {
225
255
  const seen = new Set<string>();
226
256
  let currentBuild = build;
@@ -254,14 +284,14 @@ export async function resolveBuildResultOutput(
254
284
  };
255
285
  }
256
286
  const terminalKind = (entry.value as { readonly kind?: unknown }).kind;
257
- assert(terminalKind === "build-file" || terminalKind === "inline",
287
+ assert(terminalKind === "build-file" || terminalKind === "external-file" || terminalKind === "inline",
258
288
  `Build ${currentBuild} Output ${currentOutput} has unsupported Result value kind ${String(terminalKind)}`);
259
289
  return {
260
290
  build: currentBuild,
261
291
  output: currentOutput,
262
292
  directory,
263
293
  type: entry.type,
264
- value: entry.value,
294
+ value: entry.value.kind === "external-file" ? await currentFileReference(entry.value, externalFiles) : entry.value,
265
295
  };
266
296
  }
267
297
  }
@@ -270,6 +300,7 @@ export async function describeBuildResultOutput(
270
300
  root: string,
271
301
  build: string,
272
302
  output: string,
303
+ externalFiles: ExternalFileAccess = localExternalFiles,
273
304
  ): Promise<RepositoryBuildResultOutputDescription | undefined> {
274
305
  const seen = new Set<string>();
275
306
  let currentBuild = build;
@@ -286,8 +317,9 @@ export async function describeBuildResultOutput(
286
317
  currentOutput = entry.value.output;
287
318
  continue;
288
319
  }
289
- return entry.value.kind === "build-file"
290
- ? { type: entry.type, kind: "resource", size: entry.value.size, mediaType: entry.value.mediaType }
320
+ const file = entry.value.kind === "external-file" ? await currentFileReference(entry.value, externalFiles) : entry.value;
321
+ return file.kind === "build-file" || file.kind === "external-file"
322
+ ? { type: entry.type, kind: "resource", size: file.size, mediaType: file.mediaType }
291
323
  : entry.value.kind === "value"
292
324
  ? { type: entry.type, kind: "composite" }
293
325
  : { type: entry.type, kind: "scalar" };
@@ -334,12 +366,12 @@ export class FileBuildResult {
334
366
  this.directory = resolve(directory);
335
367
  }
336
368
 
337
- static async create(root: string, seed: BuildResultSeed): Promise<FileBuildResult> {
369
+ static async create(root: string, seed: BuildResultSeed, externalFiles: ExternalFileAccess = localExternalFiles): Promise<FileBuildResult> {
338
370
  assertOrderedBuildId(seed.id);
339
371
  assertBuildResultSeed(seed);
340
372
  const forwards = await normalizeBuildResultForwards({
341
373
  read: async (build) => await readBuildResult(buildResultDirectory(root, build)),
342
- resolve: async (build, output) => await resolveBuildResultOutput(root, build, output),
374
+ resolve: async (build, output) => await resolveBuildResultOutput(root, build, output, externalFiles),
343
375
  }, seed.forwards ?? []);
344
376
  const directory = buildResultDirectory(root, seed.id);
345
377
  await mkdir(dirname(directory), { recursive: true });
@@ -360,6 +392,7 @@ export class FileBuildResult {
360
392
  resources: {},
361
393
  values: {},
362
394
  publishedOutputs: seed.publishedOutputs,
395
+ ...(seed.resourceReferences === undefined ? {} : { resourceReferences: seed.resourceReferences }),
363
396
  forwards,
364
397
  });
365
398
  await rename(temporary, directory);
@@ -405,6 +438,7 @@ export class FileBuildResult {
405
438
  },
406
439
  },
407
440
  });
441
+ if (!updated.changed) return manifest;
408
442
  await writeJsonAtomic(join(this.directory, writerStateName), updated.writer);
409
443
  await writeManifestAtomic(join(this.directory, manifestName), updated.manifest);
410
444
  return updated.manifest;
@@ -418,10 +452,13 @@ export class FileBuildResult {
418
452
  await rm(join(this.directory, writerStateName), { force: true });
419
453
  return manifest;
420
454
  }
455
+ const executionLog = await preserveExecutionLog(input.executionLog,
456
+ async (path, chunks) => await writeStreamAtomic(join(this.directory, path), chunks));
421
457
  const now = Date.now();
422
458
  const updated: BuildResultManifest = {
423
459
  ...manifest,
424
460
  outcome: input.outcome,
461
+ ...(executionLog === undefined ? {} : { executionLog }),
425
462
  ...(input.operations === undefined ? {} : { operations: input.operations }),
426
463
  finishedAt: manifest.finishedAt ?? now,
427
464
  ...(input.failure === undefined ? {} : { failure: input.failure }),
@@ -434,15 +471,17 @@ export class FileBuildResult {
434
471
 
435
472
  /** Default zero-configuration project repository backed by one ordinary directory tree. */
436
473
  export class FileBuildResultRepository implements BuildResultRepository {
474
+ readonly externalFiles: ExternalFileAccess;
437
475
  readonly root: string;
438
476
 
439
- constructor(root: string) {
477
+ constructor(root: string, externalFiles: ExternalFileAccess = localExternalFiles) {
478
+ this.externalFiles = externalFiles;
440
479
  assert(root.trim().length > 0, "Build Result root must not be empty");
441
480
  this.root = resolve(root);
442
481
  }
443
482
 
444
483
  async create(seed: BuildResultSeed): Promise<FileBuildResult> {
445
- return await FileBuildResult.create(this.root, seed);
484
+ return await FileBuildResult.create(this.root, seed, this.externalFiles);
446
485
  }
447
486
 
448
487
  async openWriter(build: string): Promise<FileBuildResult | undefined> {
@@ -477,22 +516,27 @@ export class FileBuildResultRepository implements BuildResultRepository {
477
516
  }
478
517
 
479
518
  async describeOutput(build: string, output: string): Promise<RepositoryBuildResultOutputDescription | undefined> {
480
- return await describeBuildResultOutput(this.root, build, output);
519
+ return await describeBuildResultOutput(this.root, build, output, this.externalFiles);
481
520
  }
482
521
 
483
522
  async resolve(build: string, output: string): Promise<RepositoryBuildResultOutput | undefined> {
484
- const resolvedOutput = await resolveBuildResultOutput(this.root, build, output);
523
+ const resolvedOutput = await resolveBuildResultOutput(this.root, build, output, this.externalFiles);
485
524
  if (resolvedOutput === undefined) return undefined;
486
525
  const { directory: _directory, ...portable } = resolvedOutput;
487
526
  return portable;
488
527
  }
489
528
 
529
+ async describeFile(_build: string, file: BuildResultFileRef): Promise<BuildResultFileRef> {
530
+ return await currentFileReference(file, this.externalFiles);
531
+ }
532
+
490
533
  async openFile(
491
534
  build: string,
492
535
  file: BuildResultFileRef,
493
536
  range?: BuildResultFileRange,
494
537
  ): Promise<AsyncIterable<Uint8Array> | undefined> {
495
- const directory = buildResultDirectory(this.root, build);
538
+ if (file.kind === "external-file") return await this.externalFiles.open(file.uri, range);
539
+ const directory = buildResultDirectory(this.root, file.build ?? build);
496
540
  const path = containedResultPath(directory, file.path);
497
541
  if (!await exists(path)) return undefined;
498
542
  if (range === undefined) return createReadStream(path);
@@ -1,3 +1,4 @@
1
+ import { assertOrderedBuildId } from "@hypit/protocol";
1
2
  import type {
2
3
  BlobRef,
3
4
  BuildState,
@@ -9,12 +10,19 @@ import type {
9
10
  export type BuildResultOutcome = "complete" | "failed" | "cancelled";
10
11
 
11
12
  export type BuildResultFileRef = {
13
+ readonly size: number;
14
+ readonly mediaType: string;
15
+ } & ({
12
16
  readonly kind: "build-file";
17
+ /** Absent for a file owned by the containing Result; explicit when reused elsewhere. */
18
+ readonly build?: string;
13
19
  /** Forward-only path relative to the owning Build's result directory. */
14
20
  readonly path: string;
15
- readonly size: number;
16
- readonly mediaType: string;
17
- };
21
+ } | {
22
+ readonly kind: "external-file";
23
+ /** Explicit address supplied by the Workspace; remains a live external dependency. */
24
+ readonly uri: string;
25
+ });
18
26
 
19
27
  /** A normalized half-open byte range within one Result file. */
20
28
  export type BuildResultFileRange = {
@@ -38,7 +46,7 @@ export type BuildResultResourceBinding = {
38
46
 
39
47
  /**
40
48
  * Durable encoding of one Composite value. Domain data stays ordinary canonical data while
41
- * Result-local Resource addresses live beside it, so reserved-looking domain objects cannot be
49
+ * Resource references live beside it, so reserved-looking domain objects cannot be
42
50
  * mistaken for persistence metadata.
43
51
  */
44
52
  export type BuildResultValueDocument = {
@@ -77,12 +85,18 @@ export function assertBuildResultFileRef(value: unknown, subject: string): asser
77
85
  throw new Error(`${subject} is not a Build file reference`);
78
86
  }
79
87
  const item = value as Readonly<Record<string, unknown>>;
80
- if (item.kind !== "build-file"
88
+ if ((item.kind !== "build-file" && item.kind !== "external-file")
81
89
  || typeof item.size !== "number" || !Number.isSafeInteger(item.size) || item.size < 0
82
90
  || typeof item.mediaType !== "string" || item.mediaType.length === 0) {
83
91
  throw new Error(`${subject} is not a valid Build file reference`);
84
92
  }
85
- assertBuildResultPath(item.path, `${subject}.path`);
93
+ if (item.kind === "external-file") {
94
+ if (typeof item.uri !== "string" || item.uri.length === 0) throw new Error(`${subject}.uri is missing`);
95
+ new URL(item.uri);
96
+ } else {
97
+ assertBuildResultPath(item.path, `${subject}.path`);
98
+ if (item.build !== undefined) assertOrderedBuildId(item.build as string);
99
+ }
86
100
  }
87
101
 
88
102
  function valueAtPath(value: CanonicalValue, path: BuildResultValuePath, subject: string): CanonicalValue {
@@ -150,6 +164,8 @@ export type BuildResultOutputValue =
150
164
  | { readonly kind: "value"; readonly path: string };
151
165
 
152
166
  export type BuildResultOutput = {
167
+ /** Author-provided display name; the Output identifier remains unchanged. */
168
+ readonly displayName?: string;
153
169
  readonly type: TypeRef;
154
170
  readonly value: BuildResultOutputValue;
155
171
  };
@@ -190,6 +206,7 @@ export type BuildResultManifest = {
190
206
  readonly failure?: string;
191
207
  readonly outputs: Readonly<Record<string, BuildResultOutput>>;
192
208
  readonly operations?: readonly BuildResultOperation[];
209
+ readonly executionLog?: BuildResultFileRef;
193
210
  };
194
211
 
195
212
  export type FinishedBuildResultManifest = BuildResultManifest & {
@@ -198,6 +215,8 @@ export type FinishedBuildResultManifest = BuildResultManifest & {
198
215
  };
199
216
 
200
217
  export type BuildResultPublishedOutput = {
218
+ /** Author-provided display name; the Output identifier remains unchanged. */
219
+ readonly displayName?: string;
201
220
  readonly name: string;
202
221
  readonly output: string;
203
222
  };
@@ -217,6 +236,8 @@ export type BuildResultSeed = {
217
236
  readonly targets: readonly string[];
218
237
  readonly publishedOutputs: readonly BuildResultPublishedOutput[];
219
238
  readonly forwards?: readonly BuildResultForward[];
239
+ /** Known file locations for admitted Resource identities, including nested uses. */
240
+ readonly resourceReferences?: Readonly<Record<string, BuildResultFileRef>>;
220
241
  };
221
242
 
222
243
  /** Validate the one-name-per-Output public Result surface before storage is touched. */
@@ -224,6 +245,11 @@ export function assertBuildResultSeed(seed: BuildResultSeed): void {
224
245
  if (seed.title !== undefined && seed.title.trim().length === 0) {
225
246
  throw new Error("Build Result title must not be empty");
226
247
  }
248
+ for (const [resource, file] of Object.entries(seed.resourceReferences ?? {})) {
249
+ if (resource.length === 0) throw new Error("Resource reference has no identity");
250
+ assertBuildResultFileRef(file, `Resource ${resource}`);
251
+ if (file.kind === "build-file" && file.build === undefined) throw new Error(`Resource ${resource} needs its owning Build`);
252
+ }
227
253
  const names = new Set<string>();
228
254
  const outputs = new Set<string>();
229
255
  for (const published of seed.publishedOutputs) {
@@ -269,12 +295,16 @@ export type BuildResultSync = {
269
295
  };
270
296
 
271
297
  export type BuildResultFinish = {
298
+ /** Closed execution evidence; Repository stores it before publishing the terminal manifest. */
299
+ readonly executionLog?: AsyncIterable<Uint8Array>;
272
300
  readonly operations?: readonly BuildResultOperation[];
273
301
  readonly outcome: BuildResultOutcome;
274
302
  readonly failure?: string;
275
303
  };
276
304
 
277
305
  export type BuildResultPresentationUpdate = {
306
+ /** Exact public Output names; null removes an override. */
307
+ readonly outputDisplayNames?: Readonly<Record<string, string | null>>;
278
308
  /** `null` removes the current title; omission leaves it unchanged. */
279
309
  readonly title?: string | null;
280
310
  /** `null` removes the current note; omission leaves it unchanged. */
@@ -325,13 +355,14 @@ export type RepositoryBuildResultOutputDescription = {
325
355
 
326
356
  export type BuildResultWriter = {
327
357
  read(): Promise<BuildResultManifest>;
358
+ /** Publish newly accepted public Outputs; no storage writes when none are new. */
328
359
  sync(input: BuildResultSync): Promise<BuildResultManifest>;
329
360
  finish(input: BuildResultFinish): Promise<BuildResultManifest>;
330
361
  };
331
362
 
332
363
  /**
333
- * Project result history addressed only by Build id, Output name and Build-relative file path.
334
- * Filesystem paths, bucket keys and service URLs remain implementation details.
364
+ * Project result history addressed by Build id and Output name. File references carry their
365
+ * ownership or explicit external address; each repository supplies the corresponding byte access.
335
366
  */
336
367
  export type BuildResultRepository = {
337
368
  create(seed: BuildResultSeed): Promise<BuildResultWriter>;
@@ -346,6 +377,8 @@ export type BuildResultRepository = {
346
377
  /** Follow explicit Output forwarding and describe its terminal value without opening content. */
347
378
  describeOutput(build: string, output: string): Promise<RepositoryBuildResultOutputDescription | undefined>;
348
379
  resolve(build: string, output: string): Promise<RepositoryBuildResultOutput | undefined>;
380
+ /** Read current metadata for a file reference, including external dependencies. */
381
+ describeFile(build: string, file: BuildResultFileRef): Promise<BuildResultFileRef>;
349
382
  openFile(
350
383
  build: string,
351
384
  file: BuildResultFileRef,
@@ -13,8 +13,9 @@ import type {
13
13
 
14
14
  export type BuildResultWriterState = {
15
15
  readonly resources: Readonly<Record<string, string>>;
16
+ readonly resourceReferences?: Readonly<Record<string, BuildResultFileRef>>;
16
17
  readonly values: Readonly<Record<string, string>>;
17
- readonly publishedOutputs: readonly { readonly name: string; readonly output: string }[];
18
+ readonly publishedOutputs: readonly { readonly name: string; readonly output: string; readonly displayName?: string }[];
18
19
  readonly forwards: readonly { readonly output: string; readonly build: string; readonly sourceOutput: string }[];
19
20
  };
20
21
 
@@ -28,6 +29,8 @@ export type BuildResultWriteTarget = {
28
29
  };
29
30
 
30
31
  export type BuildResultSyncResult = {
32
+ /** Whether accepted public Outputs were added to the manifest. */
33
+ readonly changed: boolean;
31
34
  readonly manifest: BuildResultManifest;
32
35
  readonly writer: BuildResultWriterState;
33
36
  };
@@ -97,6 +100,8 @@ export async function syncBuildResultOutputs(input: {
97
100
  const outputs: Record<string, BuildResultOutput> = { ...input.manifest.outputs };
98
101
 
99
102
  const materialize = async (artifact: BlobRef): Promise<BuildResultFileRef> => {
103
+ const reference = input.writer.resourceReferences?.[artifact.resource];
104
+ if (reference !== undefined) return { ...reference, mediaType: artifact.mediaType };
100
105
  const identity = artifact.resource;
101
106
  assert(identity.length > 0, "Build resource has no instance identity");
102
107
  let path = resources.get(identity);
@@ -166,14 +171,20 @@ export async function syncBuildResultOutputs(input: {
166
171
  }).sort((left, right) => outputRank(left.record, left.forward) - outputRank(right.record, right.forward)
167
172
  || left.published.name.localeCompare(right.published.name));
168
173
 
174
+ if (ready.length === 0) {
175
+ return { changed: false, manifest: input.manifest, writer: input.writer };
176
+ }
177
+
169
178
  for (const { published, record, forward } of ready) {
170
179
  outputs[published.name] = {
180
+ ...(published.displayName === undefined ? {} : { displayName: published.displayName }),
171
181
  type: record.type,
172
182
  value: forward ?? await outputValue(record),
173
183
  };
174
184
  }
175
185
 
176
186
  return {
187
+ changed: true,
177
188
  manifest: { ...input.manifest, outputs },
178
189
  writer: {
179
190
  ...input.writer,
@@ -15,7 +15,7 @@ An explicit selection can move the same repository elsewhere:
15
15
  ```
16
16
 
17
17
  Relative paths are resolved from the project root. Results are grouped by the UTC date already encoded
18
- in their ordered Build ids, and each Build then owns one intact directory with its `result.json`, public
18
+ in their ordered Build ids. Each Build has a directory containing its `result.json`, new public
19
19
  Resource files and Composite Value Documents:
20
20
 
21
21
  ```text
@@ -27,3 +27,25 @@ project-wide history database. Browsing sorts the shallow date buckets and enume
27
27
  only inside the dates reached while filling the requested cursor page; only those Result manifests are
28
28
  opened. File reads support byte ranges. Active diagnosis checks the selected directory (or its nearest
29
29
  existing parent) for read/write access without creating a probe file.
30
+
31
+ Existing resources keep their addresses, including inside nested Composite values. External Workspace
32
+ files remain live references; reused Result files retain their original owning Build. See the shared
33
+ [Result value and reference model](../build-result/README.md) for ownership and export behavior.
34
+
35
+ ## Publication
36
+
37
+ Runtime execution state stays in the Runtime's store. Result synchronization publishes newly accepted
38
+ public Outputs: it saves new Resource files and Value Documents, then replaces `result.json`.
39
+ Internal graph progress and already published Outputs cause no Result writes. A private `.writer.json`
40
+ holds the file assignments needed while publishing and is removed at completion. The Runtime saves
41
+ all accepted public Outputs and the final outcome before removing active execution state, including
42
+ when the Build fails or is cancelled.
43
+
44
+ Files are written completely beside their destination before publication. POSIX systems use `rename`;
45
+ Windows uses `SetFileInformationByHandle(FileRenameInfoEx)` with replacement and POSIX semantics through
46
+ Koffi. Existing readers keep their old file, while subsequent opens see the new one. This platform code
47
+ belongs to the filesystem implementation; the Result model and other repository adapters do not
48
+ depend on it. A filesystem that rejects this operation reports the Windows error without timed retries.
49
+
50
+ The Windows behavior is defined by Microsoft's
51
+ [FileRenameInformationEx documentation](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/4217551b-d2c0-42cb-9dc1-69a716cf6d0c).
@@ -33,6 +33,11 @@ The repository exposes the same logical shape as the filesystem adapter:
33
33
  Filesystem and S3 use the same Record-to-Result encoder. The adapter only writes the selected
34
34
  relative document or byte path; it does not interpret domain values. A Value Document keeps canonical
35
35
  domain data separate from the paths of nested Resources.
36
+ Nested reuse retains each Resource's original Build and path. Workspace files remain explicit external
37
+ references rather than being uploaded merely because this repository uses S3. The shared
38
+ [Result value and reference model](../build-result/README.md) describes ownership and external access.
39
+ Synchronization uploads new public Outputs and then their updated manifest. Internal graph progress
40
+ and repeated synchronization of already published Outputs produce no object writes.
36
41
 
37
42
  Physical object prefixes use a reversible descending-time form derived from the ordered Build id, so
38
43
  S3 can return a newest-first delimiter page directly. This is only adapter key layout: callers still