cozyclay 2.1.0 → 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 (583) hide show
  1. package/CHANGELOG.md +65 -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 +22 -6
  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-BlT33CGf.js → first-shot-handoff-CC4xe4HM.js} +1 -1
  33. package/dist/assets/{landing-BSesrCpL.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/llms.txt +14 -0
  40. package/dist/sw.js +3 -6
  41. package/dist/workflow/index.html +5 -4
  42. package/mcp/LIVE-PROTOCOL.md +7 -47
  43. package/mcp/README.md +16 -26
  44. package/mcp/live-hub.mjs +6 -10
  45. package/mcp/package.json +1 -3
  46. package/mcp/tool-handlers.mjs +4 -168
  47. package/package.json +3 -22
  48. package/src/App.jsx +174 -2639
  49. package/src/agent-progress.js +79 -0
  50. package/src/agent-turn-mark.js +30 -0
  51. package/src/analytics.js +1 -19
  52. package/src/app-context.js +5 -0
  53. package/src/app-stage.jsx +2 -34
  54. package/src/asset-pane.jsx +6 -5
  55. package/src/camera-block.js +21 -0
  56. package/src/camera-direction.js +120 -0
  57. package/src/character-kind.js +3 -9
  58. package/src/command-bus.js +8 -6
  59. package/src/commands/cast.js +5 -34
  60. package/src/commands/elements/character.js +1 -1
  61. package/src/commands/elements/motion.js +1 -6
  62. package/src/commands/elements/object.js +6 -2
  63. package/src/commands/elements/shot.js +4 -1
  64. package/src/commands/elements.js +38 -14
  65. package/src/commands/index.js +3 -1
  66. package/src/commands/kits.js +37 -0
  67. package/src/commands/motion-timing.js +57 -0
  68. package/src/commands/motion.js +9 -152
  69. package/src/commands/motion3-compile.js +65 -0
  70. package/src/commands/motion3.js +207 -0
  71. package/src/commands/objects.js +6 -4
  72. package/src/commands/shot.js +49 -11
  73. package/src/commands/stage.js +14 -1
  74. package/src/commands/view.js +4 -1
  75. package/src/document-mirrors.js +42 -0
  76. package/src/document-store.js +4 -0
  77. package/src/domains/cast.js +19 -194
  78. package/src/domains/motion/motion-range-pin-rules.js +1 -1
  79. package/src/domains/motion/take-source.js +51 -0
  80. package/src/domains/motion.js +60 -1838
  81. package/src/domains/scenes.js +12 -55
  82. package/src/domains/shots.js +2 -2
  83. package/src/domains/stage.js +4 -2
  84. package/src/draft-ghost.js +46 -0
  85. package/src/draft-ghost.jsx +129 -0
  86. package/src/dualview.jsx +4 -3
  87. package/src/effects/EffectsLayer.jsx +112 -0
  88. package/src/effects/effect-meshes.js +232 -0
  89. package/src/effects/effect-record.js +103 -0
  90. package/src/effects/emitter.js +59 -0
  91. package/src/effects/simulate.js +261 -0
  92. package/src/effects/state.js +59 -0
  93. package/src/execution-telemetry.js +2 -3
  94. package/src/first-success-guide.jsx +5 -5
  95. package/src/ghost-set.js +257 -0
  96. package/src/held-object-edit.jsx +113 -0
  97. package/src/held-object-pose.js +175 -0
  98. package/src/hierarchy-model.js +1 -1
  99. package/src/hierarchy-panel.jsx +1 -1
  100. package/src/imported-mesh.jsx +103 -0
  101. package/src/kits/held.js +84 -0
  102. package/src/kits/index.js +70 -0
  103. package/src/kits/smoking.js +57 -0
  104. package/src/light-blockers.js +93 -0
  105. package/src/motion/beat-board-model.js +84 -0
  106. package/src/motion/beat-board.css +124 -0
  107. package/src/motion/beat-board.jsx +59 -0
  108. package/src/motion/center-of-mass.js +66 -0
  109. package/src/motion/fix-collisions.js +850 -0
  110. package/src/motion/physics-review.js +118 -0
  111. package/src/{ardy → motion}/physics-support.js +1 -76
  112. package/src/motion/rig-snapshot.js +22 -0
  113. package/src/motion/take-segments.jsx +140 -0
  114. package/src/{ardy → motion}/timeline-coordinates.js +0 -21
  115. package/src/{ardy → motion}/timeline.css +1 -2
  116. package/src/{ardy → motion}/timeline.jsx +48 -419
  117. package/src/motion/waypoints.js +76 -0
  118. package/src/motion3/beats.js +83 -0
  119. package/src/motion3/body.js +158 -0
  120. package/src/motion3/bones.js +47 -0
  121. package/src/motion3/carried.js +47 -0
  122. package/src/motion3/compile-job.js +75 -0
  123. package/src/motion3/compile-worker.js +10 -0
  124. package/src/motion3/compiler/anchors.js +105 -0
  125. package/src/motion3/compiler/arm-orient.js +128 -0
  126. package/src/motion3/compiler/channels.js +125 -0
  127. package/src/motion3/compiler/compile.js +205 -0
  128. package/src/motion3/compiler/gait-rhythm.js +97 -0
  129. package/src/motion3/compiler/grip.js +171 -0
  130. package/src/motion3/compiler/head-steady.js +48 -0
  131. package/src/motion3/compiler/hold.js +134 -0
  132. package/src/motion3/compiler/idle.js +113 -0
  133. package/src/motion3/compiler/limbs.js +170 -0
  134. package/src/motion3/compiler/math.js +72 -0
  135. package/src/motion3/compiler/pose.js +162 -0
  136. package/src/motion3/compiler/quat.js +49 -0
  137. package/src/motion3/compiler/skeleton.js +74 -0
  138. package/src/motion3/compiler/validate-common.js +32 -0
  139. package/src/motion3/compiler/validate-goals.js +118 -0
  140. package/src/motion3/compiler/validate-objects.js +143 -0
  141. package/src/motion3/compiler/validate-parts.js +116 -0
  142. package/src/motion3/compiler/validate.js +122 -0
  143. package/src/motion3/compiler/vocab.js +73 -0
  144. package/src/motion3/compiler/walk-pelvis.js +275 -0
  145. package/src/motion3/compiler/walk.js +207 -0
  146. package/src/motion3/compiler/wrist-clamp.js +32 -0
  147. package/src/motion3/delta.js +47 -0
  148. package/src/motion3/describe.js +174 -0
  149. package/src/motion3/docs.js +27 -0
  150. package/src/motion3/edit-carry.js +21 -0
  151. package/src/motion3/fix/ease.js +16 -0
  152. package/src/motion3/fix/ground.js +37 -0
  153. package/src/motion3/fix/index.js +52 -0
  154. package/src/motion3/fix/push.js +71 -0
  155. package/src/motion3/fix/reach.js +46 -0
  156. package/src/motion3/fix/retime.js +79 -0
  157. package/src/motion3/fix/self.js +211 -0
  158. package/src/motion3/fix/slide.js +70 -0
  159. package/src/motion3/fix/turn.js +51 -0
  160. package/src/motion3/follow.js +39 -0
  161. package/src/motion3/free-motion.js +173 -0
  162. package/src/motion3/grip-choice.js +130 -0
  163. package/src/motion3/hold-plan.js +157 -0
  164. package/src/motion3/json-patch.js +77 -0
  165. package/src/motion3/key-aim.js +105 -0
  166. package/src/motion3/key-edit.js +82 -0
  167. package/src/motion3/lenient.js +127 -0
  168. package/src/motion3/object-keys.js +236 -0
  169. package/src/motion3/object-pose.js +182 -0
  170. package/src/motion3/object-tracks.js +12 -0
  171. package/src/motion3/pipeline.js +102 -0
  172. package/src/motion3/playback.js +51 -0
  173. package/src/motion3/probes.js +91 -0
  174. package/src/motion3/qa/body-checks.js +34 -0
  175. package/src/motion3/qa/check-names.js +14 -0
  176. package/src/motion3/qa/checks.js +121 -0
  177. package/src/motion3/qa/contact-checks.js +51 -0
  178. package/src/motion3/qa/explain.js +80 -0
  179. package/src/motion3/qa/fmt.js +5 -0
  180. package/src/motion3/qa/foot-checks.js +72 -0
  181. package/src/motion3/qa/geometry.js +77 -0
  182. package/src/motion3/qa/goals.js +191 -0
  183. package/src/motion3/qa/ground.js +60 -0
  184. package/src/motion3/qa/hints-contact.js +179 -0
  185. package/src/motion3/qa/hints-goal.js +160 -0
  186. package/src/motion3/qa/hints-knee.js +24 -0
  187. package/src/motion3/qa/hints-motion.js +209 -0
  188. package/src/motion3/qa/hints-object.js +91 -0
  189. package/src/motion3/qa/index.js +42 -0
  190. package/src/motion3/qa/key-checks.js +82 -0
  191. package/src/motion3/qa/near.js +96 -0
  192. package/src/motion3/qa/object-checks.js +135 -0
  193. package/src/motion3/qa/patch.js +161 -0
  194. package/src/motion3/qa/severity.js +38 -0
  195. package/src/motion3/qa/spec-checks.js +65 -0
  196. package/src/motion3/qa/style.js +218 -0
  197. package/src/motion3/qa/wrist-checks.js +69 -0
  198. package/src/motion3/qa/wrist-obs.js +60 -0
  199. package/src/motion3/refs.js +120 -0
  200. package/src/motion3/repair-tune.js +121 -0
  201. package/src/motion3/repair.js +83 -0
  202. package/src/motion3/report.js +67 -0
  203. package/src/motion3/rigs/index.js +14 -0
  204. package/src/motion3/rigs/x-bot-tpose-body.json +1 -0
  205. package/src/motion3/rigs/x-bot-tpose.json +1 -0
  206. package/src/motion3/rigs/y-bot-tpose-body.json +1 -0
  207. package/src/motion3/rigs/y-bot-tpose.json +1 -0
  208. package/src/motion3/scene.js +60 -0
  209. package/src/motion3/schema/brief.js +89 -0
  210. package/src/motion3/schema/fields.js +44 -0
  211. package/src/motion3/schema/spec-examples.js +46 -0
  212. package/src/motion3/schema/topics.js +111 -0
  213. package/src/motion3/schema/types.js +147 -0
  214. package/src/motion3/search.js +117 -0
  215. package/src/motion3/second-hand.js +112 -0
  216. package/src/motion3/skills/basic.js +82 -0
  217. package/src/motion3/skills/book.js +76 -0
  218. package/src/motion3/skills/car.js +145 -0
  219. package/src/motion3/skills/frames-auto.js +29 -0
  220. package/src/motion3/skills/index.js +83 -0
  221. package/src/motion3/skills/info.js +65 -0
  222. package/src/motion3/skills/smoke-kit.js +109 -0
  223. package/src/motion3/skills/smoke.js +160 -0
  224. package/src/motion3/spec-store.js +59 -0
  225. package/src/motion3/take-edit.js +155 -0
  226. package/src/motion3/take.js +63 -0
  227. package/src/motion3/timeline.js +127 -0
  228. package/src/motion3/views.js +121 -0
  229. package/src/motion3/walk-plan.js +119 -0
  230. package/src/object-catalog.jsx +7 -1
  231. package/src/object-colors.js +98 -0
  232. package/src/object-gizmo-parts.js +115 -0
  233. package/src/object-gizmo.jsx +37 -122
  234. package/src/object-glow.js +139 -0
  235. package/src/object-hidden.js +33 -0
  236. package/src/object-look.js +196 -0
  237. package/src/object-size.js +10 -0
  238. package/src/object-travel.js +71 -6
  239. package/src/panels/CameraPanel.jsx +7 -7
  240. package/src/panels/HdrEnvironmentControls.jsx +59 -0
  241. package/src/panels/LightPanel.jsx +25 -4
  242. package/src/panels/ObjectLookPanel.jsx +88 -0
  243. package/src/panels/PoseImagePanel.jsx +1 -1
  244. package/src/panels/PosePanel.jsx +2 -17
  245. package/src/panels/RigControlPanel.jsx +5 -53
  246. package/src/panels/SubjectBox.jsx +4 -1
  247. package/src/panels/details.css +14 -0
  248. package/src/posestudio.jsx +4 -27
  249. package/src/project-browser.jsx +3 -4
  250. package/src/project-resources.js +18 -31
  251. package/src/project.js +13 -104
  252. package/src/props.jsx +25 -280
  253. package/src/rail-dot-drag.js +23 -0
  254. package/src/render-passes.js +10 -0
  255. package/src/resource-status.jsx +1 -0
  256. package/src/result-modal.jsx +4 -19
  257. package/src/room.jsx +20 -12
  258. package/src/scene-assets.js +8 -6
  259. package/src/scene-light-place.js +72 -0
  260. package/src/scene-lights.jsx +148 -0
  261. package/src/scene-objects.js +31 -139
  262. package/src/scenes.js +15 -105
  263. package/src/semantic-edit.js +2 -5
  264. package/src/set-pieces.jsx +183 -0
  265. package/src/settings-menu.jsx +3 -11
  266. package/src/shell/BottomDock.jsx +11 -53
  267. package/src/shell/CompositionGuideButton.jsx +20 -0
  268. package/src/shell/DetailsSlot.jsx +16 -200
  269. package/src/shell/GhostsMenuGroup.jsx +74 -0
  270. package/src/shell/LibrarySlot.jsx +1 -3
  271. package/src/shell/MenuBar.jsx +3 -3
  272. package/src/shell/PreferencesDialog.jsx +15 -264
  273. package/src/shell/PreferencesSlot.jsx +2 -8
  274. package/src/shell/ShotPreviewHeader.jsx +17 -0
  275. package/src/shell/TopBar.jsx +5 -83
  276. package/src/shell/ViewportToolbar.jsx +23 -93
  277. package/src/shell/agent-glass.css +19 -6
  278. package/src/shell/details-selection.js +42 -0
  279. package/src/shell/ghosts-menu.css +22 -0
  280. package/src/shell/glass-regions.css +29 -3
  281. package/src/shell/preferences.css +6 -1
  282. package/src/shell/viewport.css +12 -0
  283. package/src/shot-authoring.js +4 -7
  284. package/src/soft-shadows.js +37 -0
  285. package/src/stage-attach-frames.js +12 -12
  286. package/src/stage-canvas-rigs.jsx +3 -3
  287. package/src/stage-capture.jsx +42 -8
  288. package/src/stage-characters.jsx +22 -216
  289. package/src/stage-editor-gizmos.jsx +6 -6
  290. package/src/stage-environment.js +93 -0
  291. package/src/stage-hdr-builtins.js +107 -0
  292. package/src/stage-hdr-image.js +116 -0
  293. package/src/stage-hdr-library.js +70 -0
  294. package/src/stage-hdr-map.js +94 -0
  295. package/src/stage-hdr.js +130 -0
  296. package/src/stage-lighting.js +149 -0
  297. package/src/stage-occlusion.js +210 -0
  298. package/src/stage-sky.jsx +159 -0
  299. package/src/stage-startup-defaults.js +5 -9
  300. package/src/studio-actions.js +12 -14
  301. package/src/studio-agent-commands.js +46 -16
  302. package/src/studio-agent-motion.js +9 -9
  303. package/src/studio-agent-protocol.js +46 -73
  304. package/src/studio-app-binding.js +29 -45
  305. package/src/studio-asset-list.js +17 -0
  306. package/src/studio-contact-sheet.js +37 -5
  307. package/src/studio-elements.js +27 -7
  308. package/src/studio-entity-bounds.js +18 -0
  309. package/src/studio-error-codes.js +8 -0
  310. package/src/studio-export-framing.js +152 -0
  311. package/src/studio-lighting-check.js +103 -0
  312. package/src/studio-motion-visual.js +150 -0
  313. package/src/studio-schema-errors.js +80 -0
  314. package/src/studio-support-gap.js +74 -0
  315. package/src/styles.css +1 -19
  316. package/src/timeline-defaults.js +5 -0
  317. package/src/timeline-extent.js +8 -20
  318. package/src/tutorial-walk.js +17 -0
  319. package/src/ui-scrub.js +1 -1
  320. package/src/use-shot-camera-tracks.js +12 -0
  321. package/src/view-ghosts.js +97 -0
  322. package/src/view-ghosts.jsx +49 -0
  323. package/src/workflow/AgentPanel.jsx +47 -166
  324. package/src/workflow/AgentProgressCard.jsx +107 -0
  325. package/src/workflow/AgentReplyText.jsx +37 -0
  326. package/src/workflow/AgentTurnSteps.jsx +84 -0
  327. package/src/workflow/LoginPanel.jsx +140 -0
  328. package/src/workflow/WorkflowBuilder.jsx +7 -23
  329. package/src/workflow/agent-client.js +54 -51
  330. package/src/workflow/agent-panel.css +71 -1
  331. package/src/workflow/agent-progress-card.css +167 -0
  332. package/src/workflow/agent-progress-view.js +47 -0
  333. package/src/workflow/agent-turn-steps.css +113 -0
  334. package/src/workflow/agent-turn.js +191 -0
  335. package/src/workflow/login-client.js +34 -0
  336. package/src/workflow/motion-input.js +18 -31
  337. package/src/workflow/node-schema.js +1 -1
  338. package/src/workflow/reply-markdown.js +69 -0
  339. package/src/workflow/scene-asset-sync.js +8 -8
  340. package/tools/agent-session-stats.mjs +61 -0
  341. package/tools/dev-full.mjs +5 -56
  342. package/tools/eslint-baseline.json +12 -13
  343. package/tools/headless-studio.mjs +85 -0
  344. package/tools/knip-baseline.json +0 -179
  345. package/tools/loc-baseline.json +33 -83
  346. package/tools/motion3/extract-body.mjs +103 -0
  347. package/tools/motion3/extract-rig.mjs +85 -0
  348. package/tools/process-supervisor.mjs +0 -88
  349. package/tools/run-tests.mjs +9 -124
  350. package/bin/agent/motion-runtime.mjs +0 -76
  351. package/dist/ardy/cskel27-rest.json +0 -557
  352. package/dist/assets/analytics-B41FmPYI.js +0 -1
  353. package/dist/assets/app-Do-Og5Pu.css +0 -1
  354. package/dist/assets/app-DwP-tl2x.js +0 -4920
  355. package/dist/assets/config-Bx7pYsD9.js +0 -1
  356. package/dist/assets/config-DeoFTYzb.css +0 -1
  357. package/dist/assets/demo-Dt0qZfS7.js +0 -1
  358. package/dist/assets/scene-asset-sync-BCWDJB1d.js +0 -19
  359. package/dist/assets/scene-asset-sync-DjJ_cJ2R.css +0 -1
  360. package/dist/assets/ticket-jqMhqL88.js +0 -1
  361. package/dist/assets/workflow-Br-K7Srs.js +0 -179
  362. package/dist/demo/walk-then-stop.npz +0 -0
  363. package/mcp/ardy-prompts.mjs +0 -218
  364. package/src/ardy/auto-fix-panel.css +0 -108
  365. package/src/ardy/auto-physics.js +0 -1194
  366. package/src/ardy/client.js +0 -153
  367. package/src/ardy/convert.js +0 -313
  368. package/src/ardy/cskel27-neutral.js +0 -39
  369. package/src/ardy/cskel27.js +0 -77
  370. package/src/ardy/export.js +0 -165
  371. package/src/ardy/fix-collisions.js +0 -2257
  372. package/src/ardy/foot-lock.js +0 -230
  373. package/src/ardy/motion-calibration.js +0 -118
  374. package/src/ardy/motion-edit.js +0 -213
  375. package/src/ardy/motion-url.js +0 -55
  376. package/src/ardy/mp4-duration.js +0 -102
  377. package/src/ardy/npz.js +0 -595
  378. package/src/ardy/physics-panel.css +0 -21
  379. package/src/ardy/physics-panel.jsx +0 -89
  380. package/src/ardy/physics-refine.js +0 -111
  381. package/src/ardy/physics-review.js +0 -567
  382. package/src/ardy/physics-temporal.js +0 -54
  383. package/src/ardy/platform-fit-panel.css +0 -64
  384. package/src/ardy/platform-fit-panel.jsx +0 -41
  385. package/src/ardy/platform-fit.js +0 -326
  386. package/src/ardy/playback.js +0 -711
  387. package/src/ardy/pose-pin.js +0 -97
  388. package/src/ardy/prompt-clips.js +0 -30
  389. package/src/ardy/retime.js +0 -211
  390. package/src/ardy/root-drop.js +0 -369
  391. package/src/ardy/timeline-resize.js +0 -13
  392. package/src/ardy/to-cskel27.js +0 -225
  393. package/src/ardy/trim.js +0 -33
  394. package/src/ardy/waypoints.js +0 -369
  395. package/src/ardy-bridge-contract.js +0 -281
  396. package/src/domains/motion/motion-video-capture.js +0 -664
  397. package/src/i2v-motion-client.js +0 -77
  398. package/src/i2v-motion-studio.jsx +0 -180
  399. package/src/line-edit.js +0 -1348
  400. package/src/motion/generation.js +0 -105
  401. package/src/motion-readiness-ui.jsx +0 -67
  402. package/src/motion-readiness.js +0 -40
  403. package/src/motion-resources.js +0 -177
  404. package/src/motion-store.js +0 -65
  405. package/src/motion-trail.js +0 -601
  406. package/src/multimodel-ingest.js +0 -394
  407. package/src/panels/PromptBlocksPanel.jsx +0 -444
  408. package/src/panels/VideoCapturePanel.jsx +0 -181
  409. package/src/pose-extract/browser.js +0 -42
  410. package/src/pose-extract/detector.js +0 -100
  411. package/src/pose-extract/fit.js +0 -227
  412. package/src/pose-extract/image-frame.js +0 -51
  413. package/src/pose-extract/index.js +0 -58
  414. package/src/pose-extract/keyframes.js +0 -74
  415. package/src/pose-extract/landmarks.js +0 -162
  416. package/src/pose-extract/mirror.js +0 -153
  417. package/src/pose-extract/take.js +0 -131
  418. package/src/pose-extract/video-frames.js +0 -91
  419. package/src/take-recipe.js +0 -165
  420. package/src/trail-key-conflicts.js +0 -39
  421. package/src/trail-pick.js +0 -59
  422. package/src/use-i2v-capture-modal.js +0 -15
  423. package/tools/ardy/BRIDGE.md +0 -37
  424. package/tools/ardy/GVHMR-NPZ.md +0 -68
  425. package/tools/ardy/README.md +0 -124
  426. package/tools/ardy/__pycache__/cclay_gvhmr_worker.cpython-313.pyc +0 -0
  427. package/tools/ardy/artifacts.mjs +0 -34
  428. package/tools/ardy/bridge.mjs +0 -1732
  429. package/tools/ardy/bvh-cskel27.mjs +0 -1265
  430. package/tools/ardy/cclay_constrained_generate.py +0 -561
  431. package/tools/ardy/cclay_gvhmr_worker.py +0 -264
  432. package/tools/ardy/cclay_motion_edit.py +0 -510
  433. package/tools/ardy/cclay_sequence_generate.py +0 -705
  434. package/tools/ardy/cclay_worker.py +0 -304
  435. package/tools/ardy/dump-npz.py +0 -205
  436. package/tools/ardy/extract-rest.mjs +0 -299
  437. package/tools/ardy/extract.mjs +0 -507
  438. package/tools/ardy/footage.mjs +0 -467
  439. package/tools/ardy/gvhmr-floor.mjs +0 -102
  440. package/tools/ardy/gvhmr-to-cskel27.mjs +0 -21
  441. package/tools/ardy/gvhmr_fastpath.py +0 -168
  442. package/tools/ardy/gvhmr_trajectory.py +0 -240
  443. package/tools/ardy/merge-text-encoder.py +0 -160
  444. package/tools/ardy/mocap-metrics.mjs +0 -200
  445. package/tools/ardy/mocap-quality-gate.mjs +0 -110
  446. package/tools/ardy/motion-stabilize.mjs +0 -348
  447. package/tools/ardy/npz.mjs +0 -414
  448. package/tools/ardy/pose-to-npz.mjs +0 -106
  449. package/tools/ardy/prompt-limits.mjs +0 -5
  450. package/tools/ardy/run-edit-on-box.sh +0 -73
  451. package/tools/ardy/run-local.mjs +0 -233
  452. package/tools/ardy/run-on-box.sh +0 -593
  453. package/tools/ardy/run-sequence-on-box.sh +0 -177
  454. package/tools/ardy/runners/gvhmr-worker.mjs +0 -206
  455. package/tools/ardy/runners/index.mjs +0 -18
  456. package/tools/ardy/runners/local.mjs +0 -455
  457. package/tools/ardy/runners/proc.mjs +0 -125
  458. package/tools/ardy/runners/remote.mjs +0 -252
  459. package/tools/ardy/setup-local.mjs +0 -189
  460. package/tools/ardy/setup-text-encoder-on-box.sh +0 -93
  461. package/tools/ardy/setup-text-encoder.py +0 -306
  462. package/tools/ardy/smpl-cskel27.mjs +0 -178
  463. package/tools/ardy/visual-qa.mjs +0 -196
  464. package/tools/ardy/vq-car.mjs +0 -52
  465. package/tools/bench/EXP3.md +0 -61
  466. package/tools/bench/cclay_bench_extract_incam.py +0 -125
  467. package/tools/bench/cclay_bench_extract_obs.py +0 -204
  468. package/tools/bench/cclay_bench_runner.py +0 -42
  469. package/tools/bench/cube-contact.mjs +0 -162
  470. package/tools/bench/exp3.mjs +0 -152
  471. package/tools/bench/extract-bench-lib.mjs +0 -216
  472. package/tools/bench/extract-bench.mjs +0 -302
  473. package/tools/bench/fal-generate.mjs +0 -88
  474. package/tools/bench/fit/README.md +0 -189
  475. package/tools/bench/fit/camera.mjs +0 -59
  476. package/tools/bench/fit/contact.mjs +0 -419
  477. package/tools/bench/fit/footlock.mjs +0 -234
  478. package/tools/bench/fit/motion.mjs +0 -85
  479. package/tools/bench/fit/pin.mjs +0 -27
  480. package/tools/bench/fit/remote.mjs +0 -105
  481. package/tools/bench/fit-bench.mjs +0 -126
  482. package/tools/bench/fit-sanity.mjs +0 -45
  483. package/tools/bench/metrics.mjs +0 -313
  484. package/tools/bench/obs/depth.mjs +0 -258
  485. package/tools/bench/obs/extrinsics.mjs +0 -175
  486. package/tools/bench/obs/fit_mannequin_betas.py +0 -340
  487. package/tools/bench/obs/ground.mjs +0 -294
  488. package/tools/bench/obs/heading.mjs +0 -151
  489. package/tools/bench/obs/ladder.mjs +0 -555
  490. package/tools/bench/obs/mannequin-betas.json +0 -124
  491. package/tools/bench/obs/remote.mjs +0 -83
  492. package/tools/bench/obs/rest_joints.py +0 -52
  493. package/tools/bench/obs/ybot-targets.mjs +0 -49
  494. package/tools/bench/obs-bench.mjs +0 -520
  495. package/tools/bench/score.mjs +0 -343
  496. package/tools/bench/summarize.mjs +0 -86
  497. package/tools/demo-worker/README.md +0 -137
  498. package/tools/demo-worker/api-client.mjs +0 -233
  499. package/tools/demo-worker/generate.mjs +0 -301
  500. package/tools/demo-worker/index.mjs +0 -466
  501. package/tools/demo-worker/sign-core.mjs +0 -112
  502. package/tools/demo-worker/sign.mjs +0 -161
  503. package/tools/gt-render/browser.mjs +0 -159
  504. package/tools/gt-render/camera-math.mjs +0 -276
  505. package/tools/gt-render/page.mjs +0 -267
  506. package/tools/gt-render/render.mjs +0 -514
  507. package/tools/gt-render/scene-box.mjs +0 -31
  508. package/tools/gt-render/take-transform.mjs +0 -87
  509. package/tools/kimodo/compare-seam.mjs +0 -108
  510. package/tools/kimodo/constraints.mjs +0 -244
  511. package/tools/kimodo/edit.mjs +0 -259
  512. package/tools/kimodo/effector-constraints.mjs +0 -200
  513. package/tools/kimodo/generate.mjs +0 -646
  514. package/tools/kimodo/local-output.mjs +0 -265
  515. package/tools/kimodo/measure-pose.mjs +0 -65
  516. package/tools/kimodo/measure-preserve.mjs +0 -899
  517. package/tools/kimodo/measure-waypoints.mjs +0 -55
  518. package/tools/kimodo/mlx-generate.py +0 -111
  519. package/tools/kimodo/pose-constraints.mjs +0 -248
  520. package/tools/kimodo/preserve-mask.mjs +0 -543
  521. package/tools/kimodo/read-npz.mjs +0 -189
  522. package/tools/kimodo/run-edit-on-box.mjs +0 -155
  523. package/tools/kimodo/run-sequence-on-box.mjs +0 -178
  524. package/tools/kimodo/runner.mjs +0 -284
  525. package/tools/kimodo/seam-batch.mjs +0 -77
  526. package/tools/kimodo/setup-local.mjs +0 -30
  527. package/tools/kimodo/setup-on-box.sh +0 -339
  528. package/tools/kimodo/soma77-to-cskel27.mjs +0 -305
  529. package/tools/morphgs/assets/gen_truth.py +0 -39
  530. package/tools/morphgs/assets/mesh_ori_rig.txt +0 -27
  531. package/tools/morphgs/assets/playback-check.mjs +0 -30
  532. package/tools/morphgs/demo-gate.sh +0 -26
  533. package/tools/morphgs/fbx2morphgs.mjs +0 -68
  534. package/tools/morphgs/morphgs-to-cskel27.mjs +0 -105
  535. package/tools/morphgs/patches/preprocess_src-none-mode.patch +0 -76
  536. package/tools/morphgs/setup-on-cluster.sh +0 -126
  537. package/tools/projflow/driver.py +0 -1069
  538. package/tools/projflow/generate.mjs +0 -805
  539. package/tools/projflow/hml22-to-cskel27.mjs +0 -735
  540. package/tools/projflow/line-edit-job.mjs +0 -547
  541. package/tools/projflow/replay.mjs +0 -452
  542. package/tools/projflow/runner.mjs +0 -269
  543. package/tools/projflow/service.mjs +0 -742
  544. package/tools/track/DESIGN.md +0 -513
  545. package/tools/track/backfill-provenance.mjs +0 -116
  546. package/tools/track/budget.mjs +0 -8
  547. package/tools/track/check-rig.mjs +0 -209
  548. package/tools/track/diagnostics.schema.json +0 -60
  549. package/tools/track/export-rig.mjs +0 -256
  550. package/tools/track/fallback.mjs +0 -7
  551. package/tools/track/fk-parity-fixture.mjs +0 -161
  552. package/tools/track/gate.mjs +0 -349
  553. package/tools/track/masks.mjs +0 -318
  554. package/tools/track/metrics.mjs +0 -201
  555. package/tools/track/publish-obs.mjs +0 -108
  556. package/tools/track/py/check_env.py +0 -61
  557. package/tools/track/py/eval_lr.py +0 -229
  558. package/tools/track/py/lr_viterbi.py +0 -294
  559. package/tools/track/py/masks.py +0 -405
  560. package/tools/track/py/objective.py +0 -382
  561. package/tools/track/py/rig.py +0 -508
  562. package/tools/track/py/scene.py +0 -326
  563. package/tools/track/py/test_joint_indices.py +0 -123
  564. package/tools/track/py/test_lr_viterbi.py +0 -195
  565. package/tools/track/py/test_masks.py +0 -229
  566. package/tools/track/py/test_rig.py +0 -288
  567. package/tools/track/py/test_scene.py +0 -354
  568. package/tools/track/py/test_track.py +0 -328
  569. package/tools/track/py/track.py +0 -411
  570. package/tools/track/remote.mjs +0 -140
  571. package/tools/track/rig-dump.mjs +0 -227
  572. package/tools/track/run-box-tests.mjs +0 -14
  573. package/tools/track/run-box.mjs +0 -168
  574. package/tools/track/setup-box.sh +0 -59
  575. package/tools/track/study-2d.mjs +0 -728
  576. /package/src/{ardy → motion}/collision-blockers.js +0 -0
  577. /package/src/{ardy → motion}/ground.js +0 -0
  578. /package/src/{ardy → motion}/ik-drag.js +0 -0
  579. /package/src/{ardy → motion}/ik-key-json.js +0 -0
  580. /package/src/{ardy → motion}/ik.js +0 -0
  581. /package/src/{ardy → motion}/physics-surface.js +0 -0
  582. /package/src/{ardy → motion}/playback-clock.js +0 -0
  583. /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
- }