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,165 +0,0 @@
1
- /* ======================== take recipes (contract C9) ========================
2
- * A take is a RECIPE, not a result: seed + prompt blocks + the line edits that
3
- * were pulled on top of it. Determinism on the box (re-chain diff = 0 bitwise)
4
- * is what makes that true — given the recipe the same take can be rebuilt at
5
- * any time, which is the whole reason regenerate/extend no longer destroys the
6
- * refinements the artist spent their afternoon on.
7
- *
8
- * recipe = {
9
- * seed: 1234, // ALWAYS a concrete integer, never null
10
- * blocks: [{ prompt, duration }],// ordered; a single-prompt take = length 1
11
- * lineEdits: [ <C6 payload WITHOUT sourceMotion> ], // application order
12
- * }
13
- *
14
- * THE SEED RULE, and why it lives here. A recipe with no seed cannot replay,
15
- * so no request that CREATES a take may omit one. When the artist leaves the
16
- * seed field empty the app rolls one, SENDS it, and records it — rolling it
17
- * here rather than letting the box pick silently is the difference between a
18
- * take you can rebuild and a take you can only remember.
19
- *
20
- * This file is deliberately React-free and side-effect-free: every function is
21
- * a pure value transform, so test/verify-take-recipe.mjs can pin the whole
22
- * contract in plain node without a DOM. Recipes come out DEEP FROZEN — the
23
- * one invariant that keeps "the recipe travels with the motionUrl" honest is
24
- * that no later edit can reach back and rewrite a version that is already on
25
- * the strip. */
26
-
27
- /** C10's cap on a replay array. The bridge refuses more, and the app must not
28
- * discover that by being refused. */
29
- export const RECIPE_MAX_LINE_EDITS = 16;
30
-
31
- /** C12's cap on the version strip. The bridge's motion allowlist holds 64, so
32
- * 20 checkpoints are all still loadable when the oldest is dropped. */
33
- export const TAKE_VERSIONS_MAX = 20;
34
-
35
- /** Every key a C6 lineEdit payload may carry into a C10 replay entry, minus
36
- * sourceMotion (replay rebinds that to the freshly generated take). `seed` is
37
- * C10's optional per-entry seed and is the only field the app ADDS: it is the
38
- * seed that was actually sent with the edit, so a replay reproduces the edit
39
- * bit for bit instead of re-rolling it.
40
- *
41
- * `pins3d` is the second gesture's payload and rides the SAME list: a replayed
42
- * pin needs no camera and no polyline, and because the whitelist is a
43
- * whitelist, omitting it would have made a pinned edit vanish from its own
44
- * take's recipe silently — the take would regenerate without the refinement and
45
- * nothing would say why. */
46
- const REPLAY_KEYS = ["track", "frameRange", "points2d", "pins3d", "camera", "prompt", "seed"];
47
-
48
- function deepFreeze(value) {
49
- if (value === null || typeof value !== "object" || Object.isFrozen(value)) return value;
50
- Object.freeze(value);
51
- for (const entry of Array.isArray(value) ? value : Object.values(value)) deepFreeze(entry);
52
- return value;
53
- }
54
-
55
- /** Roll a seed the way the seed rule demands. `random` is injectable so tests
56
- * can pin the arithmetic instead of sampling it. */
57
- export function rollSeed(max, random = Math.random) {
58
- if (!Number.isInteger(max) || max <= 0) throw new Error(`rollSeed needs a positive integer max, got ${max}`);
59
- return Math.floor(random() * max);
60
- }
61
-
62
- /** The seed a request will actually carry. `typed` is the artist's raw field
63
- * value (empty string = "you pick"); a typed seed is NEVER overwritten, and an
64
- * empty one is rolled here so the same integer can be both sent and recorded.
65
- * Returns an integer, always — this is the function every take-creating call
66
- * site goes through. */
67
- export function resolveSeed(typed, max, random = Math.random) {
68
- const text = typeof typed === "string" ? typed.trim() : typed;
69
- if (text === "" || text === null || text === undefined) return rollSeed(max, random);
70
- const value = Number(text);
71
- if (!Number.isInteger(value) || value < 0 || value > max) {
72
- throw new Error(`seed must be an integer in 0..${max}, got ${typed}`);
73
- }
74
- return value;
75
- }
76
-
77
- /** The prompt blocks a request actually asked for. A segments body (chained
78
- * blocks) contributes one block per segment on the WIRE clock it was built
79
- * against; anything else is the single prompt+duration pair the bridge was
80
- * handed. Durations come out in seconds either way, because that is the one
81
- * frame-rate-free number in the request. */
82
- export function blocksFromRequest(body, fps) {
83
- if (!body || typeof body !== "object") throw new Error("blocksFromRequest needs a request body");
84
- if (!(fps > 0)) throw new Error(`blocksFromRequest needs a positive fps, got ${fps}`);
85
- const basePrompt = typeof body.prompt === "string" ? body.prompt : "";
86
- if (Array.isArray(body.segments) && body.segments.length > 0) {
87
- return body.segments.map((segment) => ({
88
- prompt: (typeof segment.prompt === "string" && segment.prompt) || basePrompt,
89
- duration: Math.max(0, (segment.endFrame - segment.startFrame) / fps),
90
- }));
91
- }
92
- return [{ prompt: basePrompt, duration: Number(body.duration) || 0 }];
93
- }
94
-
95
- /** A recipe for a take that was just generated. `lineEdits` defaults to empty —
96
- * a plain generate has none — but a regeneration that CARRIED `replay` starts
97
- * life with exactly the edits the box re-applied, because those edits are in
98
- * the resulting npz and dropping them here would make the NEXT regeneration
99
- * lose them. */
100
- export function freshRecipe({ seed, blocks, lineEdits = [] }) {
101
- if (!Number.isInteger(seed)) throw new Error(`a recipe needs a concrete integer seed, got ${seed}`);
102
- if (!Array.isArray(blocks) || blocks.length === 0) throw new Error("a recipe needs at least one block");
103
- return deepFreeze({
104
- seed,
105
- blocks: blocks.map((block) => ({ prompt: String(block.prompt ?? ""), duration: Number(block.duration) || 0 })),
106
- lineEdits: lineEdits.map(stripSourceMotion),
107
- });
108
- }
109
-
110
- /** A C6 payload reduced to what a C10 replay entry may carry: sourceMotion is
111
- * dropped (replay rebinds it), unknown keys are dropped with it, and absent
112
- * optional keys stay absent rather than becoming undefined on the wire. */
113
- export function stripSourceMotion(payload) {
114
- if (!payload || typeof payload !== "object") throw new Error("a line edit payload is required");
115
- const entry = {};
116
- for (const key of REPLAY_KEYS) {
117
- if (payload[key] !== undefined) entry[key] = payload[key];
118
- }
119
- if (!entry.track) throw new Error("a line edit payload must name a track");
120
- return deepFreeze(entry);
121
- }
122
-
123
- /** Push a successful line edit onto the take's recipe. Returns a NEW recipe;
124
- * the input is never touched, which is what lets an old version keep the
125
- * recipe it was saved with after the artist edits from it. */
126
- export function withLineEdit(recipe, payload) {
127
- if (!recipe) throw new Error("withLineEdit needs a recipe to extend");
128
- return deepFreeze({
129
- seed: recipe.seed,
130
- blocks: recipe.blocks.map((block) => ({ ...block })),
131
- lineEdits: [...recipe.lineEdits, stripSourceMotion(payload)],
132
- });
133
- }
134
-
135
- /** The C10 `replay` array for this recipe, or [] when there is nothing to
136
- * replay. TRUNCATION KEEPS THE PREFIX, not the tail: entry i was authored on
137
- * top of entries 0..i-1, so the first N edits are the only slice that is
138
- * self-consistent. Dropping the newest work is the honest failure here, and
139
- * the caller surfaces it (replayTruncated) rather than silently shipping 16. */
140
- export function replayPayload(recipe) {
141
- if (!recipe || !Array.isArray(recipe.lineEdits) || recipe.lineEdits.length === 0) return [];
142
- return recipe.lineEdits.slice(0, RECIPE_MAX_LINE_EDITS).map(stripSourceMotion);
143
- }
144
-
145
- /** True when this recipe carries more edits than one replay request can hold. */
146
- export function replayTruncated(recipe) {
147
- return (recipe?.lineEdits?.length ?? 0) > RECIPE_MAX_LINE_EDITS;
148
- }
149
-
150
- /** Append a checkpoint to the version strip, oldest dropped past the cap.
151
- * Re-pushing a motionUrl that is already on the strip is a no-op: loading an
152
- * old version must not clone it onto the top, and a retried delivery must not
153
- * either. */
154
- export function pushTakeVersion(versions, entry, cap = TAKE_VERSIONS_MAX) {
155
- const list = Array.isArray(versions) ? versions : [];
156
- if (!entry?.motionUrl) throw new Error("a take version needs a motionUrl");
157
- if (list.some((item) => item.motionUrl === entry.motionUrl)) return list;
158
- const next = [...list, Object.freeze({
159
- motionUrl: entry.motionUrl,
160
- recipe: entry.recipe ?? null,
161
- savedAt: Number.isFinite(entry.savedAt) ? entry.savedAt : Date.now(),
162
- label: typeof entry.label === "string" ? entry.label : "",
163
- })];
164
- return next.length > cap ? next.slice(next.length - cap) : next;
165
- }
@@ -1,39 +0,0 @@
1
- const CHAIN_BY_EFFECTOR = Object.freeze({
2
- LeftHand: "leftHand",
3
- RightHand: "rightHand",
4
- LeftFoot: "leftFoot",
5
- RightFoot: "rightFoot",
6
- });
7
- const EFFECTOR_BY_CHAIN = Object.freeze({
8
- leftHand: "LeftHand",
9
- rightHand: "RightHand",
10
- leftFoot: "LeftFoot",
11
- rightFoot: "RightFoot",
12
- });
13
-
14
- function trackIds(track) {
15
- const id = typeof track === "string" ? track : track?.id ?? track?.joint ?? track?.effector;
16
- const chain = typeof track === "object" ? track?.chain : null;
17
- return new Set([id, chain, CHAIN_BY_EFFECTOR[id], EFFECTOR_BY_CHAIN[id]].filter(Boolean));
18
- }
19
-
20
- function entryFor(entries, id) {
21
- return typeof entries?.get === "function" ? entries.get(id) : entries?.[id];
22
- }
23
-
24
- /** Return absolute IK-key frames that can override a trail edit. */
25
- export function findAbsoluteIkKeyConflicts({ keys, track, startFrame, endFrame }) {
26
- const ids = trackIds(track);
27
- const frames = [];
28
- for (const [frame, entries] of keys ?? []) {
29
- if (frame < startFrame || frame >= endFrame) continue;
30
- for (const id of ids) {
31
- const key = entryFor(entries, id);
32
- if (key && key.baseQ == null) {
33
- frames.push(frame);
34
- break;
35
- }
36
- }
37
- }
38
- return [...new Set(frames)].sort((a, b) => a - b);
39
- }
package/src/trail-pick.js DELETED
@@ -1,59 +0,0 @@
1
- /** Pure picking for motion-trail pointer rays. */
2
-
3
- const FRAME_PENALTY = 0.001;
4
- const TIE_DISTANCE = 0.01;
5
- const MIN_FRAME_WINDOW = 12;
6
-
7
- /** Pick the trail track/frame intended by a ray near the current playhead. */
8
- export function pickTrailPoint({
9
- tracks,
10
- playheadFrame,
11
- falloffFrames,
12
- rayOrigin,
13
- rayDirection,
14
- maxDistance,
15
- }) {
16
- if (!Array.isArray(tracks) || !rayOrigin || !rayDirection) return null;
17
- const directionLength = Math.hypot(rayDirection.x, rayDirection.y, rayDirection.z);
18
- if (!Number.isFinite(directionLength) || directionLength === 0) return null;
19
- const dx = rayDirection.x / directionLength;
20
- const dy = rayDirection.y / directionLength;
21
- const dz = rayDirection.z / directionLength;
22
- const center = Number.isFinite(playheadFrame) ? playheadFrame : 0;
23
- const radius = Math.max(2 * (Number.isFinite(falloffFrames) ? falloffFrames : 0), MIN_FRAME_WINDOW);
24
- const limit = Number.isFinite(maxDistance) ? maxDistance : 0;
25
- let best = null;
26
-
27
- for (const track of tracks) {
28
- const points = track?.flat;
29
- if (!track?.id || !points || points.length < 3) continue;
30
- const firstFrame = Math.max(0, Math.ceil(center - radius));
31
- const lastFrame = Math.min(Math.floor(points.length / 3) - 1, Math.floor(center + radius));
32
- for (let frame = firstFrame; frame <= lastFrame; frame += 1) {
33
- const offset = frame * 3;
34
- const px = points[offset] - rayOrigin.x;
35
- const py = points[offset + 1] - rayOrigin.y;
36
- const pz = points[offset + 2] - rayOrigin.z;
37
- const depth = px * dx + py * dy + pz * dz;
38
- if (depth < 0) continue;
39
- const ox = px - depth * dx;
40
- const oy = py - depth * dy;
41
- const oz = pz - depth * dz;
42
- const distance = Math.hypot(ox, oy, oz);
43
- if (distance > limit) continue;
44
- const score = distance + Math.abs(frame - center) * FRAME_PENALTY;
45
- const scoreDelta = score - (best?.score ?? Infinity);
46
- if (
47
- !best
48
- || scoreDelta < -TIE_DISTANCE
49
- || (Math.abs(scoreDelta) <= TIE_DISTANCE && (
50
- depth < best.depth
51
- || (depth === best.depth && score < best.score)
52
- ))
53
- ) {
54
- best = { track: track.id, grabFrame: frame, score, depth };
55
- }
56
- }
57
- }
58
- return best ? { track: best.track, grabFrame: best.grabFrame } : null;
59
- }
@@ -1,15 +0,0 @@
1
- import { useState } from "react";
2
-
3
- export function useI2vCaptureModal() {
4
- const [i2vMotionEnabled, setI2vMotionEnabled] = useState(false);
5
- const [i2vMotionMode, setI2vMotionMode] = useState("interpolate");
6
- const [i2vMotionCameraUnlocked, setI2vMotionCameraUnlocked] = useState(false);
7
- return {
8
- i2vMotionEnabled,
9
- setI2vMotionEnabled,
10
- i2vMotionMode,
11
- setI2vMotionMode,
12
- i2vMotionCameraUnlocked,
13
- setI2vMotionCameraUnlocked,
14
- };
15
- }
@@ -1,37 +0,0 @@
1
- # Motion bridge (`tools/ardy/bridge.mjs`)
2
-
3
- This is the loopback HTTP sidecar used by the Studio. It keeps the historical
4
- `/ardy/*` route names so saved projects and motion URLs remain readable, but
5
- the local Studio uses Kimodo for authored generation and GVHMR for video mocap
6
- extraction. Legacy ARDY local/remote selection and its setup scripts are no
7
- longer part of the bridge launch path.
8
-
9
- Run it directly when debugging:
10
-
11
- ```bash
12
- CCLAY_KIMODO_HOST=user@gpu-box node tools/ardy/bridge.mjs --port 5181
13
- ```
14
-
15
- The sidecar owns health, base-listing, generation, footage download,
16
- video-to-motion extraction, and allowlisted motion delivery. It binds to
17
- `127.0.0.1`; the Vite dev server proxies only those API routes while serving
18
- `public/ardy/` assets itself.
19
-
20
- Kimodo settings:
21
-
22
- | Variable | Default | Purpose |
23
- | --- | --- | --- |
24
- | `CCLAY_KIMODO_HOST` | required | SSH destination for the generation host |
25
- | `CCLAY_KIMODO_REPO` | `$HOME/kimodo` | Kimodo checkout on that host |
26
- | `CCLAY_KIMODO_MODEL` | `Kimodo-SOMA-RP-v1.1` | model identifier |
27
- | `COZYCLAY_BRIDGE_PORT` | `5181` | loopback listen port |
28
-
29
- Video mocap extraction requires `CCLAY_EXTRACT_BACKEND=gvhmr` (the default).
30
- Any other backend or `CCLAY_EXTRACT_CMD` makes `/ardy/extract` return the named
31
- `extract-backend-unsupported` error. Set `CCLAY_EXTRACT_HOST` (or
32
- `CCLAY_ARDY_HOST`) to the GPU host that has the GVHMR checkout and virtualenv.
33
- The GVHMR detector is fixed to palette segmentation for the coloured mannequin;
34
- `CCLAY_EXTRACT_DETECTOR` cannot switch it to YOLO or auto.
35
-
36
- The wire path stays `/ardy` for backward compatibility; this does not
37
- re-enable the removed ARDY backend.
@@ -1,68 +0,0 @@
1
- # GVHMR extraction npz contract (box runner → CozyClay)
2
-
3
- Written by `cclay_gvhmr_extract.py` (lives in the GVHMR checkout on the GPU
4
- box, `~/cclay-ingest/GVHMR`), read by `tools/ardy/extract.mjs` when
5
- `CCLAY_EXTRACT_BACKEND=gvhmr`.
6
-
7
- All arrays float32 unless noted. World frame: metres, Y-up, gravity-aligned;
8
- pelvis XZ of frame 0 at the origin, the clip's lowest body vertex at Y=0,
9
- the body facing +Z at frame 0 (GVHMR's own "ayfz" normalisation).
10
-
11
- | member | shape | meaning |
12
- |---------------------|--------------|---------|
13
- | `fps` | int32 scalar | source video rate |
14
- | `positions` | [T, 22, 3] | SMPL body joints 0..21 in the world frame (legacy; the positions lift reads this) |
15
- | `contact` | [T, 6] | GVHMR static-contact logits (order as the model emits) |
16
- | `smpl_joints` | [T, 24, 3] | SMPL joints 0..23 (22 body + L/R hand) in the world frame, from the neutral SMPL J-regressor |
17
- | `smpl_global_orient`| [T, 3] | axis-angle (rad) of the pelvis in the world frame |
18
- | `smpl_body_pose` | [T, 23, 3] | axis-angle (rad) LOCAL rotation of SMPL joints 1..23 relative to their SMPL parent, standard SMPL kinematic tree |
19
- | `smpl_transl` | [T, 3] | pelvis position in the world frame, i.e. equal to `smpl_joints[:, 0]` |
20
- | `smpl_betas` | [10] | mean shape over the clip |
21
- | `smpl_rest_joints` | [24, 3] | SMPL joints of the ZERO pose for `smpl_betas` (pelvis at origin): the source rest skeleton the rotations are relative to |
22
-
23
- SMPL joint order (parents in brackets):
24
- ```
25
- 0 pelvis(-) 1 L_hip(0) 2 R_hip(0) 3 spine1(0)
26
- 4 L_knee(1) 5 R_knee(2) 6 spine2(3) 7 L_ankle(4)
27
- 8 R_ankle(5) 9 spine3(6) 10 L_foot(7) 11 R_foot(8)
28
- 12 neck(9) 13 L_collar(9) 14 R_collar(9) 15 head(12)
29
- 16 L_shoulder(13) 17 R_shoulder(14) 18 L_elbow(16) 19 R_elbow(17)
30
- 20 L_wrist(18) 21 R_wrist(19) 22 L_hand(20) 23 R_hand(21)
31
- ```
32
-
33
- Rotation convention: SMPL global rotation of joint j is
34
- `G_j = G_parent(j) · R(body_pose[j-1])`, with `G_0 = R(global_orient)`, and
35
- joint positions are `P_j = P_parent + G_parent · (rest_j - rest_parent)`.
36
- The world frame's normalisation (heading, floor) has ALREADY been folded into
37
- `global_orient`/`transl`, so FK from these arrays reproduces `smpl_joints`
38
- exactly (up to float32). The SMPL zero pose is NOT a T-pose: the upper arm
39
- rests ~11° below horizontal and the collar points ~58° up. Retarget visible
40
- limb rest-pose differences, but keep the target rig's pelvis/spine/neck/head
41
- bind shape. SMPL's J-regressor joints form an internal torso S-curve and put
42
- the head joint forward inside the skull; aiming the target bones at those
43
- positions visibly hunches an otherwise upright character.
44
-
45
- ## Repeatable QA loop
46
-
47
- Convert the raw runner archive, gate the retarget math, then capture the same
48
- sampled frames from the front and side on both shipped bodies:
49
-
50
- ```bash
51
- node tools/ardy/gvhmr-to-cskel27.mjs /path/to/gvhmr.npz public/demo/qa-gvhmr.npz
52
- # For takes extracted from CozyClay-rendered clips, use --bone-scale 1.
53
- node --test test/smpl-cskel27.test.mjs
54
-
55
- # Keep `npm run dev:ui -- --host 127.0.0.1 --port 5180` running separately.
56
- for model in x-bot-tpose y-bot-tpose; do
57
- for view in front side; do
58
- QA_URL='http://127.0.0.1:5180/app/?motion=/demo/qa-gvhmr.npz' \
59
- MODEL="$model" VIEW="$view" FRAMES=0,60,120,180,240,300 \
60
- OUT="/tmp/gvhmr-qa/$model" npm run qa:browser -- node test/qa-screenshot-browser.mjs
61
- done
62
- done
63
- ```
64
-
65
- Review the captures against video frames at the same timestamps. Do not accept
66
- a take unless the test passes, upright samples retain the character's bind
67
- torso/neck silhouette, performed bends remain present, and neither body shows
68
- detached joints. Remove the temporary `public/demo/qa-gvhmr.npz` afterwards.
@@ -1,124 +0,0 @@
1
- # Motion bridge support files
2
-
3
- The local Studio uses Kimodo for authored motion generation. Video mocap
4
- extraction is a separate path and uses GVHMR as its only backend. The bridge
5
- entry point remains at `tools/ardy/bridge.mjs` for compatibility with the
6
- existing `/ardy/*` browser protocol and stored motion URLs; the name is a
7
- wire-format path, not a selectable backend.
8
-
9
- ## Local development
10
-
11
- ```bash
12
- CCLAY_KIMODO_HOST=user@gpu-box npm run dev
13
- ```
14
-
15
- Install the Kimodo host once with `npm run kimodo:setup`. To run the UI without
16
- any sidecar, use `npm run dev:ui`; the seeded motion and all staging, camera,
17
- IK, and playback features still work.
18
-
19
- The bridge accepts `COZYCLAY_BRIDGE_PORT` (or `--port`) and binds loopback
20
- only. Kimodo connection settings are `CCLAY_KIMODO_HOST`,
21
- `CCLAY_KIMODO_REPO`, and `CCLAY_KIMODO_MODEL`.
22
-
23
- ## Shared utilities
24
-
25
- `npz.mjs`, `artifacts.mjs`, `footage.mjs`, `extract.mjs`, and the files under
26
- `src/ardy/` provide the common motion archive, ingest, conversion, IK, and
27
- playback contracts used by both generated and imported takes. They are not an
28
- ARDY runtime installation.
29
-
30
- The hosted demo worker still has a separately managed local runner for its
31
- queue jobs; that deployment path is intentionally independent of the local
32
- Studio selector.
33
-
34
- ## GVHMR extraction (required backend)
35
-
36
- `CCLAY_EXTRACT_BACKEND` defaults to `gvhmr`, and GVHMR is the only supported
37
- video mocap backend. The bridge rejects another backend value or a custom
38
- `CCLAY_EXTRACT_CMD` with `extract-backend-unsupported`; the Studio also refuses
39
- to extract until the local GPU bridge reports GVHMR. There is no browser
40
- MediaPipe fallback for video or photo mocap.
41
-
42
- GVHMR's subject detector is fixed to the `palette` segmentation path for
43
- CozyClay's coloured mannequin. `CCLAY_EXTRACT_DETECTOR` is retained for
44
- deployment compatibility but cannot switch the detector to YOLO or auto.
45
-
46
- `CCLAY_EXTRACT_KEYPOINTS` picks the 2D joint source: `vitpose`, `palette`,
47
- `hybrid`, or `auto` (default, which is `hybrid` on a palette clip). Hybrid is
48
- palette joints for the body and ViTPose for the five face points, measured on
49
- the v15 bat-swagger clip (#380): ViTPose body joints jitter 29 px/f² frame to
50
- frame on the flat-shaded mannequin (ankle confidence 0.30) where the palette's
51
- overlap/axis joints jitter 8; but the palette pins every face point to the
52
- head centroid and GVHMR then reads a head that never turns (root travel 6.3 →
53
- 2.9 m), so the face stays ViTPose (travel 6.1 m, arm swing 0.84 m). Shoulders
54
- from ViTPose wreck the arms (wrist-above-shoulder 93 % → 12 %). Where the
55
- render lost a limb part (a prop repainting the hand) the joint comes from the
56
- surviving part's axis end. The runner side lives in
57
- `~/cclay-ingest/GVHMR/cclay_gvhmr_extract.py` on the box (`hybrid_kp2d`).
58
-
59
- With GVHMR enabled, extraction uses one serial SSH worker.
60
- It deploys the repo-owned worker, preparation and trajectory Python modules into a content-addressed
61
- remote `/tmp/cozyclay-gvhmr-worker-*` directory and imports the existing
62
- `~/cclay-ingest/GVHMR/cclay_gvhmr_extract.py`. The original runner and model
63
- checkpoints are not overwritten. The host needs its existing GVHMR venv
64
- (validated with PyTorch 2.3.0+cu121 on an RTX 3070 8 GB).
65
-
66
- ViTPose/HMR2 share identical decoded crops. Complete checkpoint coverage is
67
- checked before accepting skipped random initialization; memory mapping falls
68
- back for legacy checkpoint formats. Their models stay on **CPU** between jobs,
69
- moving to CUDA one at a time. The tracker is new for every clip. Precision,
70
- flip testing, batch sizes, camera settings and neural motion prediction
71
- are unchanged by acceleration. The optional trajectory stage below intentionally
72
- changes accepted vertical trajectories. There is no cached motion-result shortcut.
73
-
74
- Concurrent extraction returns `extract-worker-busy`. Disconnect, timeout or
75
- bridge shutdown terminates the owned worker; it also exits after ten idle
76
- minutes. Restart the bridge after upgrading upstream code. Checkpoint
77
- size/mtime changes invalidate cached preprocessing models. The final `done`
78
- event includes stage timing, cache hits and PyTorch GPU-memory metrics.
79
- Palette takes also include `performance.segmentation`: detected and missing
80
- frames, dropout gaps, mask coverage quantiles, per-frame coverage, and HSV hue
81
- error (median/P95/max). These values come from the detector's own mask; older
82
- bridges without the instrumentation omit this optional report rather than
83
- reporting a clean zero-valued take.
84
-
85
- Rollback: launch the bridge with `CCLAY_GVHMR_WORKER=0` to use the original
86
- GVHMR one-shot command. Other extraction backends and `CCLAY_EXTRACT_CMD` stay
87
- unsupported so a misconfigured bridge fails explicitly.
88
- CPU lifecycle tests run in `npm test`; `test/qa-gvhmr-speed.py` performs real
89
- GPU raw-output/preprocessing equality checks, and `test/qa-gvhmr-bridge.mjs`
90
- compares original/cold/warm HTTP extraction including retargeted NPZ arrays.
91
-
92
- ## GVHMR delayed-descent recovery
93
-
94
- The worker now defaults to observation-anchored vertical recovery for static
95
- camera footage. It requires a confident, large image-space descent, a stable
96
- observed landing, and delayed world-space descent. If the world endpoint never
97
- settles before the clip ends, a persistent observed landing plateau and camera
98
- scale recover its height instead; short or moving landings remain unchanged.
99
- It keeps frame count, timestamps, joint
100
- rotations and XZ travel; it does not classify a particular action such as bowing.
101
- An actual-time, segment-mass COM gravity curve is used only when it agrees with
102
- the observed motion. Disagreement keeps observation-based timing and is reported
103
- as `mode: observed-timing`, not as a physically verified flight.
104
-
105
- After retargeting, a root-only safety pass measures both shipped character skins
106
- with Studio's playback transforms and prevents floor penetration throughout a
107
- take with an accepted descent, including initial standing frames. Observation-derived endpoints are calibrated upward
108
- to measured skin clearance before residual floor safety, with the datum change
109
- distributed over the descent; after landing each pose uses its own clearance
110
- instead of retaining an unnecessary constant lift. Elevated landings are not forced down to the floor.
111
- It does not run AutoPhysics or create IK edits.
112
- This is not full human-scene reconstruction: moving cameras and ambiguous
113
- landings are skipped, and existing articulation errors can still cause small
114
- post-landing height variation. Metadata is in `done.performance.trajectory`,
115
- including rejected spans, gravity fit, timing and per-model floor clearance.
116
-
117
- Set `CCLAY_GVHMR_TRAJECTORY=0` and restart the bridge for legacy motion with
118
- acceleration retained. `CCLAY_GVHMR_WORKER=0` disables both stages. Previously
119
- extracted takes are not rewritten; re-extract the source to use the improvement.
120
- See `test/GVHMR-TRAJECTORY-QA.md` for actual source/Studio comparisons and limits.
121
- The follow-up failure, fix checklist and actual user-clip QA are recorded in
122
- `test/GVHMR-FOLLOWUP-QA.md`. The Studio extraction receipt now distinguishes
123
- applied recovery from rejected/disabled recovery and reports authored scene Y
124
- offsets. Playback uses elapsed time rather than one frame per delayed timer.
@@ -1,34 +0,0 @@
1
- import { chmodSync, lstatSync, mkdirSync, mkdtempSync, rmSync } from "node:fs";
2
- import { dirname, join } from "node:path";
3
-
4
- /**
5
- * Creates a mode-0700 request directory beneath a mode-0700 artifact root.
6
- * The atomic mkdtemp allocation makes artifact names unguessable; exclusive
7
- * ownership prevents a local peer from planting a symlink for a later write.
8
- */
9
- export function createPrivateArtifactDir(parentDir, label) {
10
- mkdirSync(parentDir, { recursive: true, mode: 0o700 });
11
- if (lstatSync(parentDir).isSymbolicLink()) {
12
- throw new Error(`artifact root must not be a symlink: ${parentDir}`);
13
- }
14
- chmodSync(parentDir, 0o700);
15
- const requestDir = mkdtempSync(join(parentDir, `${label}-`));
16
- chmodSync(requestDir, 0o700);
17
- return requestDir;
18
- }
19
-
20
- /** Removes a failed request's private artifacts without following contents. */
21
- export function removePrivateArtifactDir(path) {
22
- rmSync(path, { recursive: true, force: true, maxRetries: 3 });
23
- }
24
-
25
- /** Drop one allowlist id and remove its request directory only after every
26
- * sibling artifact from that same request has also expired. */
27
- export function evictPrivateArtifact(allowlist, id) {
28
- const evictedPath = allowlist.get(id);
29
- allowlist.delete(id);
30
- if (!evictedPath) return;
31
- const artifactDir = dirname(evictedPath);
32
- const siblingRemains = [...allowlist.values()].some((path) => dirname(path) === artifactDir);
33
- if (!siblingRemains) removePrivateArtifactDir(artifactDir);
34
- }