cozyclay 2.1.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (577) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +12 -30
  3. package/bin/agent/agent-routes.mjs +40 -113
  4. package/bin/agent/agent-runner.mjs +9 -10
  5. package/bin/agent/cliproxy-provider.mjs +135 -0
  6. package/bin/agent/credential-store.mjs +30 -7
  7. package/bin/agent/pi-tools.mjs +4 -1
  8. package/bin/agent/provider-keys.mjs +32 -0
  9. package/bin/agent/provider-login.mjs +110 -0
  10. package/bin/agent/provider-routes.mjs +99 -0
  11. package/bin/agent/providers.mjs +19 -97
  12. package/bin/agent/script-tool.mjs +17 -4
  13. package/bin/agent/studio-motion-reference.mjs +23 -0
  14. package/bin/agent/studio-prompt.mjs +1 -1
  15. package/bin/agent/studio-rebase-text.mjs +32 -0
  16. package/bin/agent/studio-rebase.mjs +26 -39
  17. package/bin/agent/studio-tools.mjs +9 -28
  18. package/bin/agent/tool-arguments.mjs +49 -0
  19. package/bin/agent/turn-frames.mjs +66 -0
  20. package/bin/codex-auth.mjs +9 -2
  21. package/bin/cozyclay.mjs +10 -116
  22. package/bin/live/cli.mjs +3 -3
  23. package/bin/mcp-runtime.mjs +2 -12
  24. package/bin/package-signature.mjs +0 -4
  25. package/dist/app/index.html +7 -6
  26. package/dist/assets/EXRLoader-CvVIvGVE.js +1 -0
  27. package/dist/assets/analytics-C9sUnndd.js +1 -0
  28. package/dist/assets/app-CCh--1Hc.js +5087 -0
  29. package/dist/assets/app-f-fkV5uP.css +1 -0
  30. package/dist/assets/compile-worker-CkxiD6lH.js +5 -0
  31. package/dist/assets/fflate.module-KbGj5-H6.js +5 -0
  32. package/dist/assets/{first-shot-handoff-msLI71g1.js → first-shot-handoff-CC4xe4HM.js} +1 -1
  33. package/dist/assets/{landing-ChUvB_zL.js → landing-DjHD8u7k.js} +1 -1
  34. package/dist/assets/scene-asset-sync-Hx_FzdOH.js +20 -0
  35. package/dist/assets/scene-asset-sync-_S8NQl5B.css +1 -0
  36. package/dist/assets/workflow-C4yKH1p4.js +179 -0
  37. package/dist/cozyclay-package.json +1 -1
  38. package/dist/index.html +3 -3
  39. package/dist/sw.js +3 -6
  40. package/dist/workflow/index.html +5 -4
  41. package/mcp/LIVE-PROTOCOL.md +7 -47
  42. package/mcp/README.md +16 -26
  43. package/mcp/live-hub.mjs +6 -10
  44. package/mcp/package.json +1 -3
  45. package/mcp/tool-handlers.mjs +4 -168
  46. package/package.json +3 -22
  47. package/src/App.jsx +150 -2624
  48. package/src/agent-progress.js +79 -0
  49. package/src/agent-turn-mark.js +30 -0
  50. package/src/analytics.js +1 -19
  51. package/src/app-context.js +5 -0
  52. package/src/app-stage.jsx +2 -34
  53. package/src/asset-pane.jsx +6 -5
  54. package/src/camera-block.js +21 -0
  55. package/src/camera-direction.js +120 -0
  56. package/src/character-kind.js +3 -9
  57. package/src/command-bus.js +8 -6
  58. package/src/commands/cast.js +5 -34
  59. package/src/commands/elements/character.js +1 -1
  60. package/src/commands/elements/motion.js +1 -6
  61. package/src/commands/elements/object.js +6 -2
  62. package/src/commands/elements/shot.js +4 -1
  63. package/src/commands/elements.js +38 -14
  64. package/src/commands/index.js +3 -1
  65. package/src/commands/kits.js +37 -0
  66. package/src/commands/motion-timing.js +57 -0
  67. package/src/commands/motion.js +9 -152
  68. package/src/commands/motion3-compile.js +65 -0
  69. package/src/commands/motion3.js +207 -0
  70. package/src/commands/objects.js +6 -4
  71. package/src/commands/shot.js +49 -11
  72. package/src/commands/stage.js +14 -1
  73. package/src/commands/view.js +4 -1
  74. package/src/document-mirrors.js +42 -0
  75. package/src/document-store.js +4 -0
  76. package/src/domains/cast.js +19 -194
  77. package/src/domains/motion/motion-range-pin-rules.js +1 -1
  78. package/src/domains/motion/take-source.js +51 -0
  79. package/src/domains/motion.js +60 -1838
  80. package/src/domains/scenes.js +12 -55
  81. package/src/domains/shots.js +2 -2
  82. package/src/domains/stage.js +4 -2
  83. package/src/draft-ghost.js +46 -0
  84. package/src/draft-ghost.jsx +129 -0
  85. package/src/dualview.jsx +4 -3
  86. package/src/effects/EffectsLayer.jsx +112 -0
  87. package/src/effects/effect-meshes.js +232 -0
  88. package/src/effects/effect-record.js +103 -0
  89. package/src/effects/emitter.js +59 -0
  90. package/src/effects/simulate.js +261 -0
  91. package/src/effects/state.js +59 -0
  92. package/src/execution-telemetry.js +2 -3
  93. package/src/first-success-guide.jsx +5 -5
  94. package/src/ghost-set.js +257 -0
  95. package/src/held-object-edit.jsx +113 -0
  96. package/src/held-object-pose.js +175 -0
  97. package/src/hierarchy-model.js +1 -1
  98. package/src/hierarchy-panel.jsx +1 -1
  99. package/src/imported-mesh.jsx +103 -0
  100. package/src/kits/held.js +84 -0
  101. package/src/kits/index.js +70 -0
  102. package/src/kits/smoking.js +57 -0
  103. package/src/light-blockers.js +93 -0
  104. package/src/motion/beat-board-model.js +84 -0
  105. package/src/motion/beat-board.css +124 -0
  106. package/src/motion/beat-board.jsx +59 -0
  107. package/src/motion/center-of-mass.js +66 -0
  108. package/src/motion/fix-collisions.js +850 -0
  109. package/src/motion/physics-review.js +118 -0
  110. package/src/{ardy → motion}/physics-support.js +1 -76
  111. package/src/motion/rig-snapshot.js +22 -0
  112. package/src/motion/take-segments.jsx +140 -0
  113. package/src/{ardy → motion}/timeline-coordinates.js +0 -21
  114. package/src/{ardy → motion}/timeline.css +1 -2
  115. package/src/{ardy → motion}/timeline.jsx +42 -413
  116. package/src/motion/waypoints.js +76 -0
  117. package/src/motion3/beats.js +83 -0
  118. package/src/motion3/body.js +158 -0
  119. package/src/motion3/bones.js +47 -0
  120. package/src/motion3/carried.js +47 -0
  121. package/src/motion3/compile-job.js +75 -0
  122. package/src/motion3/compile-worker.js +10 -0
  123. package/src/motion3/compiler/anchors.js +105 -0
  124. package/src/motion3/compiler/arm-orient.js +128 -0
  125. package/src/motion3/compiler/channels.js +125 -0
  126. package/src/motion3/compiler/compile.js +205 -0
  127. package/src/motion3/compiler/gait-rhythm.js +97 -0
  128. package/src/motion3/compiler/grip.js +171 -0
  129. package/src/motion3/compiler/head-steady.js +48 -0
  130. package/src/motion3/compiler/hold.js +134 -0
  131. package/src/motion3/compiler/idle.js +113 -0
  132. package/src/motion3/compiler/limbs.js +170 -0
  133. package/src/motion3/compiler/math.js +72 -0
  134. package/src/motion3/compiler/pose.js +162 -0
  135. package/src/motion3/compiler/quat.js +49 -0
  136. package/src/motion3/compiler/skeleton.js +74 -0
  137. package/src/motion3/compiler/validate-common.js +32 -0
  138. package/src/motion3/compiler/validate-goals.js +118 -0
  139. package/src/motion3/compiler/validate-objects.js +143 -0
  140. package/src/motion3/compiler/validate-parts.js +116 -0
  141. package/src/motion3/compiler/validate.js +122 -0
  142. package/src/motion3/compiler/vocab.js +73 -0
  143. package/src/motion3/compiler/walk-pelvis.js +275 -0
  144. package/src/motion3/compiler/walk.js +207 -0
  145. package/src/motion3/compiler/wrist-clamp.js +32 -0
  146. package/src/motion3/delta.js +47 -0
  147. package/src/motion3/describe.js +174 -0
  148. package/src/motion3/docs.js +27 -0
  149. package/src/motion3/edit-carry.js +21 -0
  150. package/src/motion3/fix/ease.js +16 -0
  151. package/src/motion3/fix/ground.js +37 -0
  152. package/src/motion3/fix/index.js +52 -0
  153. package/src/motion3/fix/push.js +71 -0
  154. package/src/motion3/fix/reach.js +46 -0
  155. package/src/motion3/fix/retime.js +79 -0
  156. package/src/motion3/fix/self.js +211 -0
  157. package/src/motion3/fix/slide.js +70 -0
  158. package/src/motion3/fix/turn.js +51 -0
  159. package/src/motion3/follow.js +39 -0
  160. package/src/motion3/free-motion.js +173 -0
  161. package/src/motion3/grip-choice.js +130 -0
  162. package/src/motion3/hold-plan.js +157 -0
  163. package/src/motion3/json-patch.js +77 -0
  164. package/src/motion3/key-aim.js +105 -0
  165. package/src/motion3/key-edit.js +82 -0
  166. package/src/motion3/lenient.js +127 -0
  167. package/src/motion3/object-keys.js +236 -0
  168. package/src/motion3/object-pose.js +182 -0
  169. package/src/motion3/object-tracks.js +12 -0
  170. package/src/motion3/pipeline.js +102 -0
  171. package/src/motion3/playback.js +51 -0
  172. package/src/motion3/probes.js +91 -0
  173. package/src/motion3/qa/body-checks.js +34 -0
  174. package/src/motion3/qa/check-names.js +14 -0
  175. package/src/motion3/qa/checks.js +121 -0
  176. package/src/motion3/qa/contact-checks.js +51 -0
  177. package/src/motion3/qa/explain.js +80 -0
  178. package/src/motion3/qa/fmt.js +5 -0
  179. package/src/motion3/qa/foot-checks.js +72 -0
  180. package/src/motion3/qa/geometry.js +77 -0
  181. package/src/motion3/qa/goals.js +191 -0
  182. package/src/motion3/qa/ground.js +60 -0
  183. package/src/motion3/qa/hints-contact.js +179 -0
  184. package/src/motion3/qa/hints-goal.js +160 -0
  185. package/src/motion3/qa/hints-knee.js +24 -0
  186. package/src/motion3/qa/hints-motion.js +209 -0
  187. package/src/motion3/qa/hints-object.js +91 -0
  188. package/src/motion3/qa/index.js +42 -0
  189. package/src/motion3/qa/key-checks.js +82 -0
  190. package/src/motion3/qa/near.js +96 -0
  191. package/src/motion3/qa/object-checks.js +135 -0
  192. package/src/motion3/qa/patch.js +161 -0
  193. package/src/motion3/qa/severity.js +38 -0
  194. package/src/motion3/qa/spec-checks.js +65 -0
  195. package/src/motion3/qa/style.js +218 -0
  196. package/src/motion3/qa/wrist-checks.js +69 -0
  197. package/src/motion3/qa/wrist-obs.js +60 -0
  198. package/src/motion3/refs.js +120 -0
  199. package/src/motion3/repair-tune.js +121 -0
  200. package/src/motion3/repair.js +83 -0
  201. package/src/motion3/report.js +67 -0
  202. package/src/motion3/rigs/index.js +14 -0
  203. package/src/motion3/rigs/x-bot-tpose-body.json +1 -0
  204. package/src/motion3/rigs/x-bot-tpose.json +1 -0
  205. package/src/motion3/rigs/y-bot-tpose-body.json +1 -0
  206. package/src/motion3/rigs/y-bot-tpose.json +1 -0
  207. package/src/motion3/scene.js +60 -0
  208. package/src/motion3/schema/brief.js +89 -0
  209. package/src/motion3/schema/fields.js +44 -0
  210. package/src/motion3/schema/spec-examples.js +46 -0
  211. package/src/motion3/schema/topics.js +111 -0
  212. package/src/motion3/schema/types.js +147 -0
  213. package/src/motion3/search.js +117 -0
  214. package/src/motion3/second-hand.js +112 -0
  215. package/src/motion3/skills/basic.js +82 -0
  216. package/src/motion3/skills/book.js +76 -0
  217. package/src/motion3/skills/car.js +145 -0
  218. package/src/motion3/skills/frames-auto.js +29 -0
  219. package/src/motion3/skills/index.js +83 -0
  220. package/src/motion3/skills/info.js +65 -0
  221. package/src/motion3/skills/smoke-kit.js +109 -0
  222. package/src/motion3/skills/smoke.js +160 -0
  223. package/src/motion3/spec-store.js +59 -0
  224. package/src/motion3/take-edit.js +155 -0
  225. package/src/motion3/take.js +63 -0
  226. package/src/motion3/timeline.js +127 -0
  227. package/src/motion3/views.js +121 -0
  228. package/src/motion3/walk-plan.js +119 -0
  229. package/src/object-catalog.jsx +7 -1
  230. package/src/object-colors.js +98 -0
  231. package/src/object-gizmo-parts.js +115 -0
  232. package/src/object-gizmo.jsx +37 -122
  233. package/src/object-glow.js +139 -0
  234. package/src/object-hidden.js +33 -0
  235. package/src/object-look.js +196 -0
  236. package/src/object-size.js +10 -0
  237. package/src/object-travel.js +71 -6
  238. package/src/panels/CameraPanel.jsx +7 -7
  239. package/src/panels/HdrEnvironmentControls.jsx +59 -0
  240. package/src/panels/LightPanel.jsx +25 -4
  241. package/src/panels/ObjectLookPanel.jsx +88 -0
  242. package/src/panels/PosePanel.jsx +2 -17
  243. package/src/panels/RigControlPanel.jsx +5 -53
  244. package/src/panels/SubjectBox.jsx +4 -1
  245. package/src/panels/details.css +14 -0
  246. package/src/posestudio.jsx +4 -27
  247. package/src/project-browser.jsx +3 -4
  248. package/src/project-resources.js +18 -31
  249. package/src/project.js +13 -104
  250. package/src/props.jsx +25 -280
  251. package/src/rail-dot-drag.js +23 -0
  252. package/src/render-passes.js +10 -0
  253. package/src/resource-status.jsx +1 -0
  254. package/src/result-modal.jsx +4 -19
  255. package/src/room.jsx +20 -12
  256. package/src/scene-assets.js +8 -6
  257. package/src/scene-light-place.js +72 -0
  258. package/src/scene-lights.jsx +148 -0
  259. package/src/scene-objects.js +31 -139
  260. package/src/scenes.js +15 -105
  261. package/src/semantic-edit.js +2 -5
  262. package/src/set-pieces.jsx +183 -0
  263. package/src/settings-menu.jsx +3 -11
  264. package/src/shell/BottomDock.jsx +9 -51
  265. package/src/shell/DetailsSlot.jsx +16 -200
  266. package/src/shell/GhostsMenuGroup.jsx +74 -0
  267. package/src/shell/LibrarySlot.jsx +1 -3
  268. package/src/shell/MenuBar.jsx +3 -3
  269. package/src/shell/PreferencesDialog.jsx +15 -264
  270. package/src/shell/PreferencesSlot.jsx +2 -8
  271. package/src/shell/TopBar.jsx +5 -84
  272. package/src/shell/ViewportToolbar.jsx +10 -70
  273. package/src/shell/agent-glass.css +19 -6
  274. package/src/shell/details-selection.js +42 -0
  275. package/src/shell/ghosts-menu.css +22 -0
  276. package/src/shell/glass-regions.css +29 -3
  277. package/src/shell/preferences.css +6 -1
  278. package/src/shot-authoring.js +4 -7
  279. package/src/soft-shadows.js +37 -0
  280. package/src/stage-attach-frames.js +12 -12
  281. package/src/stage-canvas-rigs.jsx +3 -3
  282. package/src/stage-capture.jsx +42 -8
  283. package/src/stage-characters.jsx +22 -216
  284. package/src/stage-editor-gizmos.jsx +6 -6
  285. package/src/stage-environment.js +93 -0
  286. package/src/stage-hdr-builtins.js +107 -0
  287. package/src/stage-hdr-image.js +116 -0
  288. package/src/stage-hdr-library.js +70 -0
  289. package/src/stage-hdr-map.js +94 -0
  290. package/src/stage-hdr.js +130 -0
  291. package/src/stage-lighting.js +149 -0
  292. package/src/stage-occlusion.js +210 -0
  293. package/src/stage-sky.jsx +159 -0
  294. package/src/stage-startup-defaults.js +5 -9
  295. package/src/studio-actions.js +12 -14
  296. package/src/studio-agent-commands.js +19 -16
  297. package/src/studio-agent-motion.js +9 -9
  298. package/src/studio-agent-protocol.js +41 -71
  299. package/src/studio-app-binding.js +25 -45
  300. package/src/studio-asset-list.js +17 -0
  301. package/src/studio-contact-sheet.js +37 -5
  302. package/src/studio-elements.js +27 -7
  303. package/src/studio-entity-bounds.js +18 -0
  304. package/src/studio-error-codes.js +8 -0
  305. package/src/studio-export-framing.js +152 -0
  306. package/src/studio-lighting-check.js +103 -0
  307. package/src/studio-motion-visual.js +150 -0
  308. package/src/studio-schema-errors.js +80 -0
  309. package/src/studio-support-gap.js +74 -0
  310. package/src/styles.css +1 -19
  311. package/src/timeline-defaults.js +5 -0
  312. package/src/timeline-extent.js +8 -20
  313. package/src/tutorial-walk.js +17 -0
  314. package/src/ui-scrub.js +1 -1
  315. package/src/use-shot-camera-tracks.js +12 -0
  316. package/src/view-ghosts.js +97 -0
  317. package/src/view-ghosts.jsx +49 -0
  318. package/src/workflow/AgentPanel.jsx +47 -166
  319. package/src/workflow/AgentProgressCard.jsx +107 -0
  320. package/src/workflow/AgentReplyText.jsx +37 -0
  321. package/src/workflow/AgentTurnSteps.jsx +84 -0
  322. package/src/workflow/LoginPanel.jsx +140 -0
  323. package/src/workflow/WorkflowBuilder.jsx +7 -23
  324. package/src/workflow/agent-client.js +54 -51
  325. package/src/workflow/agent-panel.css +71 -1
  326. package/src/workflow/agent-progress-card.css +167 -0
  327. package/src/workflow/agent-progress-view.js +47 -0
  328. package/src/workflow/agent-turn-steps.css +113 -0
  329. package/src/workflow/agent-turn.js +191 -0
  330. package/src/workflow/login-client.js +34 -0
  331. package/src/workflow/motion-input.js +18 -31
  332. package/src/workflow/node-schema.js +1 -1
  333. package/src/workflow/reply-markdown.js +69 -0
  334. package/src/workflow/scene-asset-sync.js +8 -8
  335. package/tools/agent-session-stats.mjs +61 -0
  336. package/tools/dev-full.mjs +5 -56
  337. package/tools/eslint-baseline.json +12 -13
  338. package/tools/knip-baseline.json +0 -179
  339. package/tools/loc-baseline.json +31 -81
  340. package/tools/motion3/extract-body.mjs +103 -0
  341. package/tools/motion3/extract-rig.mjs +85 -0
  342. package/tools/process-supervisor.mjs +0 -88
  343. package/tools/run-tests.mjs +8 -124
  344. package/bin/agent/motion-runtime.mjs +0 -76
  345. package/dist/ardy/cskel27-rest.json +0 -557
  346. package/dist/assets/analytics-C9pMpW7s.js +0 -1
  347. package/dist/assets/app-B_2XB9rw.css +0 -1
  348. package/dist/assets/app-DAuvKPP8.js +0 -4920
  349. package/dist/assets/config-Bx7pYsD9.js +0 -1
  350. package/dist/assets/config-DeoFTYzb.css +0 -1
  351. package/dist/assets/demo-CvKuBgy5.js +0 -1
  352. package/dist/assets/scene-asset-sync-DKkpjKBV.js +0 -19
  353. package/dist/assets/scene-asset-sync-DjJ_cJ2R.css +0 -1
  354. package/dist/assets/ticket-BPk2Ni95.js +0 -1
  355. package/dist/assets/workflow-jJRBR94Z.js +0 -179
  356. package/dist/demo/walk-then-stop.npz +0 -0
  357. package/mcp/ardy-prompts.mjs +0 -218
  358. package/src/ardy/auto-fix-panel.css +0 -108
  359. package/src/ardy/auto-physics.js +0 -1194
  360. package/src/ardy/client.js +0 -153
  361. package/src/ardy/convert.js +0 -313
  362. package/src/ardy/cskel27-neutral.js +0 -39
  363. package/src/ardy/cskel27.js +0 -77
  364. package/src/ardy/export.js +0 -165
  365. package/src/ardy/fix-collisions.js +0 -2257
  366. package/src/ardy/foot-lock.js +0 -230
  367. package/src/ardy/motion-calibration.js +0 -118
  368. package/src/ardy/motion-edit.js +0 -213
  369. package/src/ardy/motion-url.js +0 -55
  370. package/src/ardy/mp4-duration.js +0 -102
  371. package/src/ardy/npz.js +0 -595
  372. package/src/ardy/physics-panel.css +0 -21
  373. package/src/ardy/physics-panel.jsx +0 -89
  374. package/src/ardy/physics-refine.js +0 -111
  375. package/src/ardy/physics-review.js +0 -567
  376. package/src/ardy/physics-temporal.js +0 -54
  377. package/src/ardy/platform-fit-panel.css +0 -64
  378. package/src/ardy/platform-fit-panel.jsx +0 -41
  379. package/src/ardy/platform-fit.js +0 -326
  380. package/src/ardy/playback.js +0 -711
  381. package/src/ardy/pose-pin.js +0 -97
  382. package/src/ardy/prompt-clips.js +0 -30
  383. package/src/ardy/retime.js +0 -211
  384. package/src/ardy/root-drop.js +0 -369
  385. package/src/ardy/timeline-resize.js +0 -13
  386. package/src/ardy/to-cskel27.js +0 -225
  387. package/src/ardy/trim.js +0 -33
  388. package/src/ardy/waypoints.js +0 -369
  389. package/src/ardy-bridge-contract.js +0 -281
  390. package/src/domains/motion/motion-video-capture.js +0 -664
  391. package/src/i2v-motion-client.js +0 -77
  392. package/src/i2v-motion-studio.jsx +0 -180
  393. package/src/line-edit.js +0 -1348
  394. package/src/motion/generation.js +0 -105
  395. package/src/motion-readiness-ui.jsx +0 -67
  396. package/src/motion-readiness.js +0 -40
  397. package/src/motion-resources.js +0 -177
  398. package/src/motion-store.js +0 -65
  399. package/src/motion-trail.js +0 -601
  400. package/src/multimodel-ingest.js +0 -394
  401. package/src/panels/PromptBlocksPanel.jsx +0 -444
  402. package/src/panels/VideoCapturePanel.jsx +0 -181
  403. package/src/pose-extract/browser.js +0 -42
  404. package/src/pose-extract/detector.js +0 -100
  405. package/src/pose-extract/fit.js +0 -227
  406. package/src/pose-extract/image-frame.js +0 -51
  407. package/src/pose-extract/index.js +0 -58
  408. package/src/pose-extract/keyframes.js +0 -74
  409. package/src/pose-extract/landmarks.js +0 -162
  410. package/src/pose-extract/mirror.js +0 -153
  411. package/src/pose-extract/take.js +0 -131
  412. package/src/pose-extract/video-frames.js +0 -91
  413. package/src/take-recipe.js +0 -165
  414. package/src/trail-key-conflicts.js +0 -39
  415. package/src/trail-pick.js +0 -59
  416. package/src/use-i2v-capture-modal.js +0 -15
  417. package/tools/ardy/BRIDGE.md +0 -37
  418. package/tools/ardy/GVHMR-NPZ.md +0 -68
  419. package/tools/ardy/README.md +0 -124
  420. package/tools/ardy/__pycache__/cclay_gvhmr_worker.cpython-313.pyc +0 -0
  421. package/tools/ardy/artifacts.mjs +0 -34
  422. package/tools/ardy/bridge.mjs +0 -1732
  423. package/tools/ardy/bvh-cskel27.mjs +0 -1265
  424. package/tools/ardy/cclay_constrained_generate.py +0 -561
  425. package/tools/ardy/cclay_gvhmr_worker.py +0 -264
  426. package/tools/ardy/cclay_motion_edit.py +0 -510
  427. package/tools/ardy/cclay_sequence_generate.py +0 -705
  428. package/tools/ardy/cclay_worker.py +0 -304
  429. package/tools/ardy/dump-npz.py +0 -205
  430. package/tools/ardy/extract-rest.mjs +0 -299
  431. package/tools/ardy/extract.mjs +0 -507
  432. package/tools/ardy/footage.mjs +0 -467
  433. package/tools/ardy/gvhmr-floor.mjs +0 -102
  434. package/tools/ardy/gvhmr-to-cskel27.mjs +0 -21
  435. package/tools/ardy/gvhmr_fastpath.py +0 -168
  436. package/tools/ardy/gvhmr_trajectory.py +0 -240
  437. package/tools/ardy/merge-text-encoder.py +0 -160
  438. package/tools/ardy/mocap-metrics.mjs +0 -200
  439. package/tools/ardy/mocap-quality-gate.mjs +0 -110
  440. package/tools/ardy/motion-stabilize.mjs +0 -348
  441. package/tools/ardy/npz.mjs +0 -414
  442. package/tools/ardy/pose-to-npz.mjs +0 -106
  443. package/tools/ardy/prompt-limits.mjs +0 -5
  444. package/tools/ardy/run-edit-on-box.sh +0 -73
  445. package/tools/ardy/run-local.mjs +0 -233
  446. package/tools/ardy/run-on-box.sh +0 -593
  447. package/tools/ardy/run-sequence-on-box.sh +0 -177
  448. package/tools/ardy/runners/gvhmr-worker.mjs +0 -206
  449. package/tools/ardy/runners/index.mjs +0 -18
  450. package/tools/ardy/runners/local.mjs +0 -455
  451. package/tools/ardy/runners/proc.mjs +0 -125
  452. package/tools/ardy/runners/remote.mjs +0 -252
  453. package/tools/ardy/setup-local.mjs +0 -189
  454. package/tools/ardy/setup-text-encoder-on-box.sh +0 -93
  455. package/tools/ardy/setup-text-encoder.py +0 -306
  456. package/tools/ardy/smpl-cskel27.mjs +0 -178
  457. package/tools/ardy/visual-qa.mjs +0 -196
  458. package/tools/ardy/vq-car.mjs +0 -52
  459. package/tools/bench/EXP3.md +0 -61
  460. package/tools/bench/cclay_bench_extract_incam.py +0 -125
  461. package/tools/bench/cclay_bench_extract_obs.py +0 -204
  462. package/tools/bench/cclay_bench_runner.py +0 -42
  463. package/tools/bench/cube-contact.mjs +0 -162
  464. package/tools/bench/exp3.mjs +0 -152
  465. package/tools/bench/extract-bench-lib.mjs +0 -216
  466. package/tools/bench/extract-bench.mjs +0 -302
  467. package/tools/bench/fal-generate.mjs +0 -88
  468. package/tools/bench/fit/README.md +0 -189
  469. package/tools/bench/fit/camera.mjs +0 -59
  470. package/tools/bench/fit/contact.mjs +0 -419
  471. package/tools/bench/fit/footlock.mjs +0 -234
  472. package/tools/bench/fit/motion.mjs +0 -85
  473. package/tools/bench/fit/pin.mjs +0 -27
  474. package/tools/bench/fit/remote.mjs +0 -105
  475. package/tools/bench/fit-bench.mjs +0 -126
  476. package/tools/bench/fit-sanity.mjs +0 -45
  477. package/tools/bench/metrics.mjs +0 -313
  478. package/tools/bench/obs/depth.mjs +0 -258
  479. package/tools/bench/obs/extrinsics.mjs +0 -175
  480. package/tools/bench/obs/fit_mannequin_betas.py +0 -340
  481. package/tools/bench/obs/ground.mjs +0 -294
  482. package/tools/bench/obs/heading.mjs +0 -151
  483. package/tools/bench/obs/ladder.mjs +0 -555
  484. package/tools/bench/obs/mannequin-betas.json +0 -124
  485. package/tools/bench/obs/remote.mjs +0 -83
  486. package/tools/bench/obs/rest_joints.py +0 -52
  487. package/tools/bench/obs/ybot-targets.mjs +0 -49
  488. package/tools/bench/obs-bench.mjs +0 -520
  489. package/tools/bench/score.mjs +0 -343
  490. package/tools/bench/summarize.mjs +0 -86
  491. package/tools/demo-worker/README.md +0 -137
  492. package/tools/demo-worker/api-client.mjs +0 -233
  493. package/tools/demo-worker/generate.mjs +0 -301
  494. package/tools/demo-worker/index.mjs +0 -466
  495. package/tools/demo-worker/sign-core.mjs +0 -112
  496. package/tools/demo-worker/sign.mjs +0 -161
  497. package/tools/gt-render/browser.mjs +0 -182
  498. package/tools/gt-render/camera-math.mjs +0 -276
  499. package/tools/gt-render/page.mjs +0 -267
  500. package/tools/gt-render/render.mjs +0 -514
  501. package/tools/gt-render/scene-box.mjs +0 -31
  502. package/tools/gt-render/take-transform.mjs +0 -87
  503. package/tools/kimodo/compare-seam.mjs +0 -108
  504. package/tools/kimodo/constraints.mjs +0 -244
  505. package/tools/kimodo/edit.mjs +0 -259
  506. package/tools/kimodo/effector-constraints.mjs +0 -200
  507. package/tools/kimodo/generate.mjs +0 -646
  508. package/tools/kimodo/local-output.mjs +0 -265
  509. package/tools/kimodo/measure-pose.mjs +0 -65
  510. package/tools/kimodo/measure-preserve.mjs +0 -899
  511. package/tools/kimodo/measure-waypoints.mjs +0 -55
  512. package/tools/kimodo/mlx-generate.py +0 -111
  513. package/tools/kimodo/pose-constraints.mjs +0 -248
  514. package/tools/kimodo/preserve-mask.mjs +0 -543
  515. package/tools/kimodo/read-npz.mjs +0 -189
  516. package/tools/kimodo/run-edit-on-box.mjs +0 -155
  517. package/tools/kimodo/run-sequence-on-box.mjs +0 -178
  518. package/tools/kimodo/runner.mjs +0 -284
  519. package/tools/kimodo/seam-batch.mjs +0 -77
  520. package/tools/kimodo/setup-local.mjs +0 -30
  521. package/tools/kimodo/setup-on-box.sh +0 -339
  522. package/tools/kimodo/soma77-to-cskel27.mjs +0 -305
  523. package/tools/morphgs/assets/gen_truth.py +0 -39
  524. package/tools/morphgs/assets/mesh_ori_rig.txt +0 -27
  525. package/tools/morphgs/assets/playback-check.mjs +0 -30
  526. package/tools/morphgs/demo-gate.sh +0 -26
  527. package/tools/morphgs/fbx2morphgs.mjs +0 -68
  528. package/tools/morphgs/morphgs-to-cskel27.mjs +0 -105
  529. package/tools/morphgs/patches/preprocess_src-none-mode.patch +0 -76
  530. package/tools/morphgs/setup-on-cluster.sh +0 -126
  531. package/tools/projflow/driver.py +0 -1069
  532. package/tools/projflow/generate.mjs +0 -805
  533. package/tools/projflow/hml22-to-cskel27.mjs +0 -735
  534. package/tools/projflow/line-edit-job.mjs +0 -547
  535. package/tools/projflow/replay.mjs +0 -452
  536. package/tools/projflow/runner.mjs +0 -269
  537. package/tools/projflow/service.mjs +0 -742
  538. package/tools/track/DESIGN.md +0 -513
  539. package/tools/track/backfill-provenance.mjs +0 -116
  540. package/tools/track/budget.mjs +0 -8
  541. package/tools/track/check-rig.mjs +0 -209
  542. package/tools/track/diagnostics.schema.json +0 -60
  543. package/tools/track/export-rig.mjs +0 -256
  544. package/tools/track/fallback.mjs +0 -7
  545. package/tools/track/fk-parity-fixture.mjs +0 -161
  546. package/tools/track/gate.mjs +0 -349
  547. package/tools/track/masks.mjs +0 -318
  548. package/tools/track/metrics.mjs +0 -201
  549. package/tools/track/publish-obs.mjs +0 -108
  550. package/tools/track/py/check_env.py +0 -61
  551. package/tools/track/py/eval_lr.py +0 -229
  552. package/tools/track/py/lr_viterbi.py +0 -294
  553. package/tools/track/py/masks.py +0 -405
  554. package/tools/track/py/objective.py +0 -382
  555. package/tools/track/py/rig.py +0 -508
  556. package/tools/track/py/scene.py +0 -326
  557. package/tools/track/py/test_joint_indices.py +0 -123
  558. package/tools/track/py/test_lr_viterbi.py +0 -195
  559. package/tools/track/py/test_masks.py +0 -229
  560. package/tools/track/py/test_rig.py +0 -288
  561. package/tools/track/py/test_scene.py +0 -354
  562. package/tools/track/py/test_track.py +0 -328
  563. package/tools/track/py/track.py +0 -411
  564. package/tools/track/remote.mjs +0 -140
  565. package/tools/track/rig-dump.mjs +0 -227
  566. package/tools/track/run-box-tests.mjs +0 -14
  567. package/tools/track/run-box.mjs +0 -168
  568. package/tools/track/setup-box.sh +0 -59
  569. package/tools/track/study-2d.mjs +0 -728
  570. /package/src/{ardy → motion}/collision-blockers.js +0 -0
  571. /package/src/{ardy → motion}/ground.js +0 -0
  572. /package/src/{ardy → motion}/ik-drag.js +0 -0
  573. /package/src/{ardy → motion}/ik-key-json.js +0 -0
  574. /package/src/{ardy → motion}/ik.js +0 -0
  575. /package/src/{ardy → motion}/physics-surface.js +0 -0
  576. /package/src/{ardy → motion}/playback-clock.js +0 -0
  577. /package/src/{ardy → motion}/range-pin.js +0 -0
@@ -1,4 +1,4 @@
1
- import { copyPhysicsKeys } from "../ardy/physics-review.js";
1
+ import { copyPhysicsKeys } from "../motion/physics-review.js";
2
2
  import { useState, useMemo, useEffect, useSyncExternalStore, useContext } from "react";
3
3
  import { AppContext } from '../app-context.js';
4
4
  import { createDocumentStore } from "../document-store.js";
@@ -13,32 +13,25 @@ import {
13
13
  saveCustomPoses,
14
14
  } from "../poses.js";
15
15
  import { createCharacterEntry, createCharacterLayer, isProxyFigure, PROXY_FIGURE_MODEL } from "../scenes.js";
16
- import { kindRefusal } from "../character-kind.js";
17
16
  import {
18
17
  DEFAULT_SUBJECT,
19
18
  DEFAULT_SUBJECT2,
20
19
  nextCharacterId,
21
20
  MAX_WAYPOINTS,
22
- MULTIMODEL_REASONS,
23
- ARDY_DURATION_MIN,
24
- TIMELINE_FPS,
25
21
  } from "../app-stage.jsx";
26
22
  import { ko, isKo } from "../locale.js";
27
- import { createIkState } from "../ardy/ik.js";
28
- import { judgeNextWaypoint } from "../ardy/waypoints.js";
23
+ import { createIkState } from "../motion/ik.js";
24
+ import { judgeNextWaypoint } from "../motion/waypoints.js";
29
25
  import { StudioProtocolError } from "../studio-agent-protocol.js";
30
26
  import { studioActionRefusal } from "../studio-actions.js";
31
27
  import { createStableItemId, removeStableItem } from "../stable-items.js";
32
28
  import { track, trackFeature } from "../analytics.js";
33
- import { requestBridgeExtract } from "../multimodel-ingest.js";
34
- import { loadMotionFromUrl } from "../ardy/npz.js";
35
- import { snapshotPlaybackBones, applyMotionFrame, restorePlaybackBones } from "../ardy/playback.js";
36
29
 
37
30
  import { shotAtFrame } from "../cuts.js";
38
31
 
39
32
  const sameCastValue = (a, b) => JSON.stringify(a) === JSON.stringify(b);
40
33
 
41
- export function createCastDomain(appContext, initial, customPoses = []) {
34
+ function createCastDomain(appContext, initial, customPoses = []) {
42
35
  const normalize = value => ({ characters: (Array.isArray(value) ? value : value.characters).map(createCharacterEntry),
43
36
  customPoses: Array.isArray(value) ? customPoses : value.customPoses ?? customPoses });
44
37
  let native = createDocumentStore({ owned: { cast: normalize(initial) } });
@@ -329,7 +322,6 @@ export function useCast(appContext) {
329
322
  // every playhead tick.
330
323
  const ghostLayers = useMemo(() => characters.flatMap((entry, index) => entry.id === activeChar.id || entry.hidden ? [] : [{
331
324
  owner: `S${index + 1}`,
332
- promptClips: entry.layer?.promptClips ?? [],
333
325
  waypointFrames: (entry.layer?.waypoints ?? []).map((waypoint) => waypoint.frame),
334
326
  }]), [characters, activeChar.id]);
335
327
 
@@ -340,7 +332,7 @@ export function useCast(appContext) {
340
332
  characters: appContext.live.characters.map((entry) => ({
341
333
  ...entry,
342
334
  layer: entry.id === activeChar.id
343
- ? { waypoints: appContext.shared.bufferRef.current.waypoints, promptClips: appContext.shared.bufferRef.current.promptClips }
335
+ ? { waypoints: appContext.shared.bufferRef.current.waypoints }
344
336
  : entry.layer,
345
337
  })),
346
338
  bufferMotion: appContext.shared.bufferRef.current.motion,
@@ -365,11 +357,7 @@ export function useCast(appContext) {
365
357
 
366
358
  const [hasCharSheet, setHasCharSheet] = useState(appContext.shared.startupStage.hasCharSheet);
367
359
 
368
- // Bumped when something outside the Inspector needs the Prompt Blocks panel
369
- // on screen — selecting or adding a block on the timeline.
370
- const [promptBlocksReveal, setPromptBlocksReveal] = useState(0);
371
-
372
- const revealPromptBlocks = () => setPromptBlocksReveal((n) => n + 1);
360
+
373
361
 
374
362
  // Root waypoints {frame, x, z, heading: null}, kept sorted by frame —
375
363
  // the fixed bridge contract rejects out-of-order or duplicate frames.
@@ -382,13 +370,6 @@ export function useCast(appContext) {
382
370
 
383
371
  const [pendingWaypointFrame, setPendingWaypointFrame] = useState(null);
384
372
 
385
- const promptClips = activeChar.layer.promptClips;
386
- const setPromptClips = value => setLayerField('promptClips', value);
387
- const editPromptClips = value => writeLayerField(domain.activeId, 'promptClips', value);
388
- function writeLayerField(characterId, key, value) {
389
- domain.write(rows => rows.map(entry => entry.id === characterId ? { ...entry, layer: { ...entry.layer,
390
- [key]: typeof value === 'function' ? value(entry.layer[key]) : value } } : entry));
391
- }
392
373
  function setLayerField(key, value) {
393
374
  const entry = domain.read().find(entry => entry.id === domain.activeId) ?? domain.read()[0];
394
375
  const next = typeof value === 'function' ? value(entry.layer[key]) : value;
@@ -396,11 +377,7 @@ export function useCast(appContext) {
396
377
  return domain.run('cast.setLayer', { characterId: entry.id, layer: { [key]: next } });
397
378
  }
398
379
 
399
- const [selectedPromptId, setSelectedPromptId] = useState(null);
400
-
401
- const [photoPoseState, setPhotoPoseState] = useState("idle");
402
-
403
- const [photoPoseError, setPhotoPoseError] = useState("");
380
+
404
381
 
405
382
  // The library is the user's own material: poses read from photographs and
406
383
  // poses saved off the rig, accumulating across sessions and projects. No
@@ -625,7 +602,6 @@ export function useCast(appContext) {
625
602
  const next = !waypointMode;
626
603
  // Both modes want the viewport pointer; the last one switched on wins,
627
604
  // the other stands down rather than fighting for pointerdown.
628
- if (next && appContext.shared.lineEditMode) appContext.shared.exitLineEditMode();
629
605
  setWaypointMode(next);
630
606
  if (!next) {
631
607
  setPendingWaypointFrame(null);
@@ -711,143 +687,13 @@ export function useCast(appContext) {
711
687
  appContext.notify(ko("Pose saved", "포즈 저장됨"));
712
688
  }
713
689
 
714
- /**
715
- * Read a body pose out of one photograph.
716
- *
717
- * A still is the degenerate footage case, so it walks the same proven path:
718
- * landmarks -> one-frame take -> applyMotionFrame -> capturePose. Posing the
719
- * rig and reading it back is what makes the result an ordinary editable pose
720
- * rather than a motion layer — the IK handles keep working on it, and the
721
- * playback bones are restored so nothing about the take survives the read.
722
- *
723
- * Depth in a single frame is inferred, not measured, so this is a starting
724
- * pose to refine, which is why it lands in the studio instead of on the
725
- * character directly.
726
- */
727
- async function posePhotoFile(file) {
728
- if (!file || photoPoseState === "running") return;
729
- // Reachable from the Inspector as well as the studio panel, and posedRig()
730
- // only answers while the studio is open — fall back to the character the
731
- // hierarchy has selected, which is the one the pose will be applied to.
732
- const rig = posedRig() ?? activeRig;
733
- let objectUrl = "";
734
- setPhotoPoseState("running");
735
- setPhotoPoseError("");
736
- try {
737
- // A capsule figure has no bones for a photo to pose.
738
- if (isProxyFigure(posingChar ?? activeChar)) throw new StudioProtocolError("TARGET_NOT_READY", kindRefusal("photoPose", isKo));
739
- if (!rig) throw new Error("rig-not-loaded");
740
- objectUrl = URL.createObjectURL(file);
741
- let bones = null;
742
- let rootY = 0;
743
- let gpuError = null;
744
- // GVHMR on the box measures the body over the whole clip,
745
- // which is more reliable than a single-frame depth estimate.
746
- // The bridge wraps the still into a second of video and runs the exact
747
- // GVHMR footage pipeline. A missing bridge or another backend is an error.
748
- try {
749
- const health = await fetch("/ardy/health", { signal: AbortSignal.timeout(2000) }).catch(() => null);
750
- if (!health?.ok) throw new Error("extract-bridge-required");
751
- const healthPayload = await health.json().catch(() => null);
752
- if (healthPayload?.extractionBackend !== "gvhmr") throw new Error("extract-backend-unsupported");
753
- const done = await requestBridgeExtract(file, {});
754
- const take = await loadMotionFromUrl(done.motionUrl);
755
- // The middle frame: the wrap's smoothing passes have settled
756
- // there, while frame 0 can still carry filter warm-up.
757
- const frame = Math.floor((take.frames - 1) / 2);
758
- const snapshot = snapshotPlaybackBones(rig);
759
- try {
760
- applyMotionFrame(rig, { ...take, anchorFrame: frame }, frame);
761
- bones = capturePose(rig);
762
- // GVHMR measured the hips' true height — a crouch is a crouch
763
- // because the hips came DOWN, not just because the knees bent.
764
- rootY = captureHipsOffset(rig);
765
- } finally {
766
- restorePlaybackBones(rig, snapshot);
767
- }
768
- } catch (error) {
769
- gpuError = error;
770
- console.warn("photo pose: GVHMR extract failed", error);
771
- }
772
- if (!bones) throw new Error(gpuError?.message || "extract-run-failed");
773
- const pose = {
774
- id: `photo_${Date.now()}`,
775
- label: isKo ? `사진 포즈 ${customPoses.length + 1}` : `Photo Pose ${customPoses.length + 1}`,
776
- prompt: "in the exact body pose shown in the reference photograph",
777
- bones,
778
- rootY,
779
- custom: true,
780
- };
781
- setStudioPick(pose.id);
782
- // The studio poses whichever character it was opened on; the Inspector
783
- // poses the selected one. Write the pose to whichever that is.
784
- const poseTargetIndex = posingIndex >= 0 ? posingIndex : activeCharIndex;
785
- // A running take drives the same bones a pose writes, so the read would
786
- // land invisibly underneath it. Applying from a photo follows the same
787
- // rule the Apply button already states: the motion goes first.
788
- const hadMotion = Boolean(appContext.shared.motion);
789
- domain.run('cast.savePose', { pose, characterId: characters[poseTargetIndex].id, clearMotion: hadMotion });
790
- setPhotoPoseState("done");
791
- // The pose is already saved and written by this point. GVHMR either
792
- // returns a measured pose or the named error above reaches the user.
793
- appContext.notify(hadMotion
794
- ? ko("Cleared the motion and posed from the photo — refine it with the handles", "모션을 지우고 사진으로 자세를 잡았어요 — 핸들로 다듬어 보세요")
795
- : ko("Pose read from the photo — refine it with the handles", "사진에서 자세를 읽었어요 — 핸들로 다듬어 보세요"));
796
- } catch (error) {
797
- const code = error?.message ?? String(error);
798
- // fitLandmarksToPose refuses a sample whose torso is not visible; that is
799
- // a photograph problem, not an engine problem, so it is named as one.
800
- const named = code.startsWith("fitLandmarksToPose:") ? "pose-partly-occluded" : code;
801
- setPhotoPoseState("error");
802
- setPhotoPoseError(MULTIMODEL_REASONS[named]?.[isKo ? 1 : 0] ?? named);
803
- } finally {
804
- if (objectUrl) URL.revokeObjectURL(objectUrl);
805
- }
806
- }
807
-
808
690
  function removePose(id) {
809
691
  domain.run('cast.removePose', { id });
810
692
  if (studioPick === id) setStudioPick(DEFAULT_POSE.id);
811
693
  }
812
694
 
813
- function addPromptClip(frame, surface = "timeline") {
814
- const before = domain.read().find(entry => entry.id === domain.activeId).layer.promptClips;
815
- const receipt = domain.run('character.addPromptBlock', { characterId: domain.activeId, frame });
816
- const clip = domain.read().find(entry => entry.id === domain.activeId).layer.promptClips.find(clip => !before.some(row => row.id === clip.id));
817
- setSelectedPromptId(clip.id);
818
- appContext.shared.setArdyDuration(Math.max(ARDY_DURATION_MIN, clip.endFrame / TIMELINE_FPS));
819
- trackFeature('prompt_block_add'); return receipt;
820
- }
821
-
822
- function changePromptClip(id, text) {
823
- domain.beginGesture();
824
- const receipt = domain.edit('character.changePromptBlock', { characterId: domain.activeId, id, text });
825
- if (id === selectedPromptId) appContext.shared.setArdyPrompt(text);
826
- return receipt;
827
- }
828
-
829
- // Quality policy: one prompt block never spans more than 5 s. Kimodo
830
- // walk-to-run sweeps (seeds 7/21/99; seam stall ratio, 1.0 = no stall)
831
- // scored 0.79 for 5 s blocks (best of the sweep), close to a seam-free
832
- // single take at 0.85; 8 s blocks collapsed to 0.32. <2 s blocks lose
833
- // about a third of their frames to the transition window, so 3-5 s is the recommended
834
- // authoring range.
835
- const PROMPT_BLOCK_MAX_FRAMES = 5 * TIMELINE_FPS;
836
-
837
- function resizePromptClip(id, edge, frame) {
838
- return domain.edit('character.resizePromptBlock', { characterId: domain.activeId, id, edge, frame });
839
- }
840
- function movePromptClip(id, frame) {
841
- return domain.edit('character.movePromptBlock', { characterId: domain.activeId, id, frame });
842
- }
843
- function removePromptClip(id) {
844
- const receipt = domain.run('character.removePromptBlock', { characterId: domain.activeId, id });
845
- if (selectedPromptId === id) setSelectedPromptId(null);
846
- return receipt;
847
- }
848
695
  function applyExternalCharacters(characters) {
849
696
  appContext.storeDomain('cast').run('cast.replace', { characters });
850
- appContext.shared.restoreMotionRefs(characters);
851
697
  }
852
698
  function publishStudioCharacters(next) {
853
699
  if (typeof next === 'function') next = next(appContext.live.characters);
@@ -857,18 +703,15 @@ export function useCast(appContext) {
857
703
  for (const entry of next) if (Object.hasOwn(entry, 'sessionMotion')) owner.publishMotion(entry.id, entry.sessionMotion);
858
704
  }
859
705
  /** The active character's layer lives in the editing buffer, and the read
860
- * model folds that buffer back over the cast. A published or restored prompt
861
- * schedule or root path has to reach it in the same tick, or the next read
862
- * would revert it. */
706
+ * model folds that buffer back over the cast. A published or restored root
707
+ * path has to reach it in the same tick, or the next read would revert it. */
863
708
  function syncStudioLayerBuffer(rows) {
864
709
  if (appContext.storeDomain('cast')) return appContext.storeDomain('cast').syncLayer();
865
710
  const layer = rows.find(entry => entry.id === appContext.shared.loadedLayerCharRef.current)?.layer;
866
711
  const changed = key => Array.isArray(layer?.[key]) && JSON.stringify(layer[key]) !== JSON.stringify(appContext.shared.bufferRef.current[key]);
867
- const clips = changed("promptClips"), path = changed("waypoints");
868
- if (!clips && !path) return;
869
- appContext.shared.bufferRef.current = { ...appContext.shared.bufferRef.current, ...(clips ? { promptClips: layer.promptClips } : {}), ...(path ? { waypoints: layer.waypoints } : {}) };
870
- if (clips) setPromptClips(layer.promptClips);
871
- if (path) setWaypoints(layer.waypoints);
712
+ if (!changed("waypoints")) return;
713
+ appContext.shared.bufferRef.current = { ...appContext.shared.bufferRef.current, waypoints: layer.waypoints };
714
+ setWaypoints(layer.waypoints);
872
715
  }
873
716
  function undoScene() {
874
717
  const receipt = appContext.bus.run('edit.undo');
@@ -914,7 +757,7 @@ export function useCast(appContext) {
914
757
  switchNativeMotionLayer(previous, entry);
915
758
  appContext.shared.loadedLayerCharRef.current = entry.id;
916
759
  domain.syncLayer();
917
- setSelectedPromptId(null); setWaypointMode(false); setActiveWaypointId(null); setPendingWaypointFrame(null);
760
+ setWaypointMode(false); setActiveWaypointId(null); setPendingWaypointFrame(null);
918
761
  }
919
762
  function createLegacyCastHandlers(finitePatch, characterForRef) {
920
763
  function replaceCharacters(next) { return domain.run('cast.replace', { characters: next }); }
@@ -953,29 +796,14 @@ export function useCast(appContext) {
953
796
  domain.run('character.remove', { characterId: character.id });
954
797
  return { id: character.id };
955
798
  }
956
- function setLivePromptBlocks(args) {
957
- if (!Array.isArray(args.blocks)) throw new Error("Invalid blocks");
958
- const stamp = Date.now();
959
- const clips = args.blocks.map((block, i) => {
960
- const startFrame = Math.round(Number(block.startFrame));
961
- const endFrame = Math.round(Number(block.endFrame));
962
- if (!Number.isFinite(startFrame) || !Number.isFinite(endFrame) || endFrame <= startFrame) {
963
- throw new Error(`Invalid frame range on block ${i + 1}`);
964
- }
965
- if (typeof block.text !== "string" || !block.text.trim()) throw new Error(`Block ${i + 1} needs text`);
966
- return { id: `prompt-${stamp}-${i}`, startFrame, endFrame, text: block.text.trim() };
967
- });
968
- domain.run('character.setPromptBlocks', { characterId: domain.activeId, blocks: clips });
969
- return { blocks: clips.length };
970
- }
971
- return { add_character: addLiveCharacter, update_character: updateLiveCharacter, remove_character: removeLiveCharacter, set_prompt_blocks: setLivePromptBlocks };
799
+ return { add_character: addLiveCharacter, update_character: updateLiveCharacter, remove_character: removeLiveCharacter };
972
800
  }
973
801
  function toggleCharacterHidden(charId) { return domain.run('character.update', { characterId: charId, patch: { hidden: castMemberOf(charId).hidden !== true } }); }
974
802
  domain.snapshotMotion = snapshotNativeMotion;
975
803
  domain.syncLayer = () => {
976
804
  const entry = domain.read().find(entry => entry.id === appContext.shared.loadedLayerCharRef.current) ?? domain.read()[0];
977
805
  appContext.shared.bufferRef.current = { ...appContext.shared.bufferRef.current, ...entry.layer };
978
- setSelectedPromptId(id => entry.layer.promptClips.some(clip => clip.id === id) ? id : null);
806
+
979
807
  setActiveWaypointId(id => entry.layer.waypoints.some(waypoint => waypoint.id === id) ? id : null);
980
808
  };
981
809
  domain.loadView = () => { appContext.shared.loadedLayerCharRef.current = domain.activeId; setActiveCharacterId(domain.activeId); };
@@ -989,8 +817,7 @@ export function useCast(appContext) {
989
817
  const shots = appContext.storeDomain('shot');
990
818
  if (!shots) return;
991
819
  const current = domain.projection(), active = current.find(entry => entry.id === domain.activeId) ?? current[0];
992
- const extent = timelineContentExtent(current, active.id, appContext.shared.bufferRef.current.motion,
993
- active.layer.promptClips, appContext.shared.motionDomain.multiModelFootage?.frames);
820
+ const extent = timelineContentExtent(current, active.id, appContext.shared.bufferRef.current.motion, null);
994
821
  domain.setTimeline(Math.max(24, timelineSpan(extent, shots.read(), shots.state().frameCount)));
995
822
  };
996
823
  domain.extendTimeline = domain.syncTimeline;
@@ -1011,14 +838,12 @@ export function useCast(appContext) {
1011
838
  spawnCharacter, charKeyToHierarchyId, charIdFromHierarchyId, activeCharacterId, setActiveCharacterId,
1012
839
  rowIdForCharIndex, activeChar, selectActiveCharacterInHierarchy, activeCharIndex, activeRig, waitForRig,
1013
840
  ghostLayers, snapshotCast, changeInspectorCharacter, hasCharSheet,
1014
- setHasCharSheet, promptBlocksReveal, setPromptBlocksReveal, revealPromptBlocks, waypointMode,
841
+ setHasCharSheet, waypointMode,
1015
842
  setWaypointMode, waypoints, setWaypoints, activeWaypointId, setActiveWaypointId, pendingWaypointFrame,
1016
- setPendingWaypointFrame, promptClips, setPromptClips, editPromptClips, selectedPromptId,
1017
- setSelectedPromptId, photoPoseState, photoPoseError, setPhotoPoseError, allPoses, selectablePoses,
843
+ setPendingWaypointFrame, allPoses, selectablePoses,
1018
844
  posingIndex, posingChar, posedRig, setPosed, rootStart, queueRootWaypointFrame, castMemberOf,
1019
845
  addCharacterWaypoint, moveCharacterWaypoint, removeCharacterWaypoint, clearCharacterWaypoints,
1020
846
  addFloorWaypoint, moveWaypoint, removeWaypoint, toggleWaypointMode, openStudio, closeStudio,
1021
- saveCurrentPose, savePose, posePhotoFile, removePose, addPromptClip, changePromptClip,
1022
- PROMPT_BLOCK_MAX_FRAMES, resizePromptClip, movePromptClip, removePromptClip,
847
+ saveCurrentPose, savePose, removePose,
1023
848
  };
1024
849
  }
@@ -1,4 +1,4 @@
1
- import { rangePinTracks } from "../../ardy/range-pin.js";
1
+ import { rangePinTracks } from "../../motion/range-pin.js";
2
2
  import { ko } from "../../locale.js";
3
3
 
4
4
  export function ensureRangePinState(state) {
@@ -0,0 +1,51 @@
1
+ // What a saved take v3 is: the motion spec, the character placement and the scene as the
2
+ // compiler saw it (motionScene boxes), never the baked Float32 arrays. Compiling is
3
+ // deterministic, so compiling the source again rebuilds the same bones: this follows the
4
+ // motion.compile install path step for step (pipeline compileSpec, then bakeTake). Searched
5
+ // open parameters are already resolved in the stored spec, so no search runs again.
6
+ import { compileSpec } from "../../motion3/pipeline.js";
7
+ import { bakeTake } from "../../motion3/take.js";
8
+ import { motionScene } from "../../motion3/scene.js";
9
+ import { skeletonFor } from "../../motion3/rigs/index.js";
10
+ import { isTakeV3 } from "../../motion3/playback.js";
11
+ import { normalizeTakeEdit } from "../../motion3/take-edit.js";
12
+ export { renderTakeEdit } from "../../motion3/take-edit.js";
13
+
14
+ const TAKE_SCHEMA = "cozyclay.take.v3";
15
+ const SPEC_SCHEMA = "cozyclay.motion-spec.v1";
16
+ const TIMELINE_FPS = 24;
17
+ const plain = value => Boolean(value) && typeof value === "object" && !Array.isArray(value);
18
+ const finite3 = value => Array.isArray(value) && value.length === 3 && value.every(Number.isFinite);
19
+
20
+ /** The JSON source of an installed take v3 (null for any other motion). Skills, anchors and
21
+ * hinges may read any scene object, so the whole compile scene is kept. */
22
+ export function takeSource(take, sceneObjects = []) {
23
+ if (!isTakeV3(take) || !plain(take.spec)) return null;
24
+ return structuredClone({ schema: TAKE_SCHEMA, rig: take.rig, spec: take.spec,
25
+ placement: { position: take.placement?.position ?? [0, 0, 0], yaw: take.placement?.yaw ?? 0 }, scene: motionScene(sceneObjects) });
26
+ }
27
+
28
+ /** A saved source (with the Studio take id it carried), checked and owned by the caller; null when it is not one. */
29
+ export function normalizeTakeSource(value) {
30
+ if (!plain(value) || value.schema !== TAKE_SCHEMA || typeof value.rig !== "string") return null;
31
+ if (!plain(value.spec) || value.spec.schema !== SPEC_SCHEMA || !Number.isFinite(value.spec.frames)) return null;
32
+ if (!plain(value.placement) || !finite3(value.placement.position) || !Number.isFinite(value.placement.yaw)) return null;
33
+ const objects = plain(value.scene?.objects) ? value.scene.objects : {}, others = plain(value.scene?.others) ? { others: value.scene.others } : {};
34
+ return structuredClone({ schema: TAKE_SCHEMA, rig: value.rig, spec: value.spec,
35
+ placement: { position: value.placement.position, yaw: value.placement.yaw }, scene: { objects, ...others },
36
+ ...(typeof value.takeId === "string" && value.takeId ? { takeId: value.takeId } : {}),
37
+ ...(normalizeTakeEdit(value.edit, value.spec.frames) ? { edit: normalizeTakeEdit(value.edit, value.spec.frames) } : {}) });
38
+ }
39
+
40
+ /** What a scene saves for a motion layer's take descriptor: its source, take id and timing edit (take-edit.js), or null. */
41
+ export const savedTakeSource = descriptor => descriptor?.source ? { ...descriptor.source, takeId: descriptor.studioTakeId, ...(descriptor.edit ? { edit: descriptor.edit } : {}) } : null;
42
+
43
+ /** Compile a source back into the installed take (with `frames`, as motion.compile installs it).
44
+ * Leniently: a field a later, stricter validator does not know never blocks loading a saved take. */
45
+ export function compileTakeSource(source) {
46
+ const sk = skeletonFor(source?.rig);
47
+ if (!sk || !plain(source.spec)) return null;
48
+ const { out } = compileSpec({ fps: TIMELINE_FPS, ...source.spec }, { sk, scene: source.scene ?? { objects: {} } }, { lenient: true });
49
+ const take = bakeTake(sk, out, source.placement, { spec: source.spec, prompt: source.spec.label ?? "" });
50
+ return { ...take, frames: take.frameCount };
51
+ }