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
@@ -0,0 +1,77 @@
1
+ // Collision proxies for motion QA: body capsules on Mixamo joints, scene objects as oriented
2
+ // boxes (base pivot = bottom centre, CozyClay convention), the head as the measured ellipsoid.
3
+ import { add, sub, scale, dot, len, apply, T, clamp } from "../compiler/math.js";
4
+ import { bonePoint } from "../compiler/skeleton.js";
5
+
6
+ // [part, from joint, to joint, radius m]. Radii are fitted to the X/Y Bot skin.
7
+ export const CAPSULES = [
8
+ ["torso_lo", "Spine", "Spine2", 0.12], ["torso_hi", "Spine2", "Neck", 0.105], ["hips", "LeftUpLeg", "RightUpLeg", 0.095],
9
+ ["neck", "Neck", "Head", 0.055],
10
+ ...["Left", "Right"].flatMap(S => {
11
+ const k = S === "Left" ? "l" : "r";
12
+ return [[`thigh_${k}`, `${S}UpLeg`, `${S}Leg`, 0.07], [`shin_${k}`, `${S}Leg`, `${S}Foot`, 0.05],
13
+ [`uarm_${k}`, `${S}Arm`, `${S}ForeArm`, 0.042], [`farm_${k}`, `${S}ForeArm`, `${S}Hand`, 0.033],
14
+ [`hand_${k}`, `${S}Hand`, `${S}HandMiddle3`, 0.022]];
15
+ }),
16
+ ];
17
+
18
+ export const segPoints = (a, b, n = 9) => Array.from({ length: n }, (_, i) => add(a, scale(sub(b, a), i / (n - 1))));
19
+
20
+ /** Signed distance from p to a box (negative inside). */
21
+ export function sdBox(p, box) {
22
+ const q = apply(T(box.R), sub(p, box.pos));
23
+ const c = [0, box.half[1], 0];
24
+ const d = [Math.abs(q[0] - c[0]) - box.half[0], Math.abs(q[1] - c[1]) - box.half[1], Math.abs(q[2] - c[2]) - box.half[2]];
25
+ const outside = len([Math.max(d[0], 0), Math.max(d[1], 0), Math.max(d[2], 0)]);
26
+ return outside + Math.min(Math.max(d[0], d[1], d[2]), 0);
27
+ }
28
+
29
+ export function segDist(p1, q1, p2, q2) {
30
+ let best = Infinity;
31
+ const d2 = sub(q2, p2), dd = dot(d2, d2);
32
+ for (const a of segPoints(p1, q1)) {
33
+ const u = dd < 1e-12 ? 0 : clamp(dot(sub(a, p2), d2) / dd, 0, 1);
34
+ best = Math.min(best, len(sub(a, add(p2, scale(d2, u)))));
35
+ }
36
+ return best;
37
+ }
38
+
39
+ /** Depth (m) of point p inside the head ellipsoid, negative when outside. */
40
+ export function headDepth(sk, s, p) {
41
+ const c = bonePoint(s, sk.index.Head, sk.landmarks.headCentre), R = s.R[sk.index.Head];
42
+ const q = apply(T(R), sub(p, c)), r = sk.landmarks.headRadii;
43
+ const v = len([q[0] / r[0], q[1] / r[1], q[2] / r[2]]);
44
+ return (1 - v) * Math.min(...r);
45
+ }
46
+
47
+ /** The rig's standing ankle height (m): where foot_* stands a flat foot on the floor (X Bot 0.087, Y Bot 0.105). */
48
+ export const ankleY = sk => Math.round(sk.restWorldPos[sk.index.LeftFoot][1] * 1000) / 1000;
49
+
50
+ /** A point `drop` m straight below bone b's joint at bind, carried by b (the joint itself when 0). */
51
+ const below = (sk, s, b, drop) => (drop ? bonePoint(s, b, apply(T(sk.restWorldRot[b]), [0, -drop, 0])) : s.P[b]);
52
+
53
+ /**
54
+ * Sole points carried by a foot, on the skin's sole (the surface verify_result's floor measure
55
+ * reads): heel 4.5 cm behind and 0.5 cm above the bottom of the ankle at bind; ball under the
56
+ * ToeBase joint at the toe pad; tip at the front edge. The rig's sole landmark says how far the
57
+ * skin lies below the joints (X Bot: on the ball joint; Y Bot: 3.3 cm under it).
58
+ */
59
+ export function solePoints(sk, s, side) {
60
+ const I = sk.index, P = sk.restWorldPos, drop = sk.landmarks.sole ?? {};
61
+ const foot = I[`${side}Foot`], toe = I[`${side}ToeBase`], toeEnd = I[`${side}Toe_End`] ?? toe;
62
+ const heelRest = [P[foot][0], 0.005, P[foot][2] - 0.045];
63
+ const heelLocal = apply(T(sk.restWorldRot[foot]), sub(heelRest, P[foot]));
64
+ return { heel: bonePoint(s, foot, heelLocal), ball: below(sk, s, toe, drop.ball), tip: below(sk, s, toeEnd, drop.tip) };
65
+ }
66
+
67
+ /** Outward unit normal of a box at p (the nearest face from inside, the closest direction from outside). */
68
+ export function boxNormal(p, box) {
69
+ const q = apply(T(box.R), sub(p, box.pos));
70
+ q[1] -= box.half[1];
71
+ const d = q.map((v, i) => Math.abs(v) - box.half[i]);
72
+ let n;
73
+ if (Math.max(...d) < 0) { const i = d.indexOf(Math.max(...d)); n = [0, 0, 0]; n[i] = Math.sign(q[i]) || 1; }
74
+ else n = q.map((v, i) => (d[i] > 0 ? Math.sign(v) * d[i] : 0));
75
+ const l = len(n);
76
+ return apply(box.R, l > 1e-12 ? scale(n, 1 / l) : [0, 1, 0]);
77
+ }
@@ -0,0 +1,191 @@
1
+ // Goals (C8): what the motion must achieve, measured on the compiled frames. A goal names one
2
+ // predicate and the frames it must hold on (at: an absolute frame or [f0, f1]):
3
+ // near: [a, b] refDistance(a, b) <= tol (default 0.05 m)
4
+ // above: [a, b] a.y - b.y >= by (default 0 m)
5
+ // moved: ref an object's point (default its base) is at least by (default 0.05 m) from
6
+ // where the scene put it; any other point ref (prop:, joint:, landmark:, anchor:)
7
+ // gets at least by from where it was at at[0]: one value, its farthest frame
8
+ // still: ref the point stays within tol (default 0.01 m) of the same home moved measures
9
+ // from (an object: where the scene put it; any other point: where it is at at[0])
10
+ // speed: ref the point's speed (central difference, m/s) is at least by (no default)
11
+ // mode "all" (every frame of at; the default, except speed) or "any" (one frame; speed's default).
12
+ // after / before: "<goal name>" cut at to the frames after (before) the first frame the named goal
13
+ // holds, so an event the agent did not place on a frame can still order two goals ("the can moves
14
+ // after the kick"). A named goal that never holds, or holds too late, leaves no frames: the goal
15
+ // fails with value and at null and one GOAL issue (value 0.01) at at[0]; the named goal's own GOAL
16
+ // group carries the measure. Each goal answers one result { name, kind, ok, value, at, need }: for
17
+ // "all" the frame closest to failing (or the worst failure), for "any" the best frame. A failed goal
18
+ // adds GOAL issues (value = the shortfall, limit 0): "all" one per failing frame, so the group's
19
+ // count and first..last show how much of at fails and the search (search.js) sees progress; "any"
20
+ // one, at the best frame. Issue frames index out.frames (out.f0 + i); goals[].at and every frame in
21
+ // a message are absolute.
22
+ import { refPoint, refDistance } from "../refs.js";
23
+ import { partsOf } from "../object-pose.js";
24
+ import { add, apply, len, sub } from "../compiler/math.js";
25
+ import { m3 } from "./fmt.js";
26
+
27
+ /** The goal predicates, one per goal. */
28
+ export const GOAL_KINDS = ["near", "above", "moved", "still", "speed"];
29
+ const DEFAULT_NEED = { near: 0.05, above: 0, moved: 0.05, still: 0.01 };
30
+ /** Predicates met at value <= need (tol); the others are met at value >= need (by). */
31
+ const AT_MOST = new Set(["near", "still"]);
32
+ /** Predicates on one point ref (the others take [ref, ref]). */
33
+ export const ONE_REF = new Set(["moved", "still", "speed"]);
34
+
35
+ /** The predicates goal g names (validation wants exactly one). */
36
+ export const goalKinds = g => GOAL_KINDS.filter(k => g?.[k] !== undefined);
37
+ /** A goal's name: its own, else its place in spec.goals ("goals[1]", which groupKey keeps apart). */
38
+ export const goalName = (g, i) => g.name ?? `goals[${i}]`;
39
+ /** The bound: tol for near and still, by for above, moved and speed. */
40
+ export const goalNeed = (g, kind) => (AT_MOST.has(kind) ? g.tol : g.by) ?? DEFAULT_NEED[kind];
41
+ /** "all" or "any": the goal's own, else any for speed (a speed is reached) and all for the rest. */
42
+ const goalMode = (g, kind) => g.mode ?? (kind === "speed" ? "any" : "all");
43
+
44
+ /** moved and still measure the named point of an object ref (its base when none is named), any other ref as it is. */
45
+ export const movedRef = ref => (!ref.startsWith("object:") || /\.(center|top|base)$/.test(ref) ? ref : `${ref}.base`);
46
+
47
+ /** Where the scene put the point of a moved object ref: the same AABB point refs.js answers, from the scene boxes. */
48
+ function scenePoint(scene, ref) {
49
+ const [, id, which] = /^object:(.+)\.(center|top|base)$/s.exec(movedRef(ref)) ?? [];
50
+ const boxes = partsOf(scene, id).map(p => scene.objects[p]);
51
+ if (!boxes.length) return null;
52
+ const lo = [Infinity, Infinity, Infinity], hi = [-Infinity, -Infinity, -Infinity];
53
+ for (const b of boxes) for (const x of [-1, 1]) for (const y of [0, 2]) for (const z of [-1, 1]) {
54
+ const p = add(b.pos, apply(b.R, [x * b.half[0], y * b.half[1], z * b.half[2]]));
55
+ for (let i = 0; i < 3; i++) { lo[i] = Math.min(lo[i], p[i]); hi[i] = Math.max(hi[i], p[i]); }
56
+ }
57
+ const c = [(lo[0] + hi[0]) / 2, (lo[1] + hi[1]) / 2, (lo[2] + hi[2]) / 2];
58
+ return which === "top" ? [c[0], hi[1], c[2]] : which === "base" ? [c[0], lo[1], c[2]] : c;
59
+ }
60
+
61
+ /** The point ref of a moved or still goal. */
62
+ const homeRef = g => g.moved ?? g.still;
63
+
64
+ /** Where a moved or still goal measures from: an object's point where the scene put it, any other point where it is at `from` (default at[0]). */
65
+ export const movedHome = (out, g, from = Array.isArray(g.at) ? g.at[0] : g.at) => (homeRef(g).startsWith("object:") ? scenePoint(out.ctx.scene, homeRef(g)) : refPoint(out, from, homeRef(g)));
66
+
67
+ /** The speed of point ref at absolute frame f (m/s): central difference, one-sided at the window's edges; null when unknown. */
68
+ function speedAt(out, ref, f) {
69
+ const p = refPoint(out, f, ref), fps = out.fps ?? 24;
70
+ if (!p) return null;
71
+ const a = refPoint(out, f - 1, ref), b = refPoint(out, f + 1, ref);
72
+ if (a && b) return (len(sub(b, a)) * fps) / 2;
73
+ const q = a ?? b;
74
+ return q ? len(sub(p, q)) * fps : null;
75
+ }
76
+
77
+ /** The measured value of goal g at absolute frame f (metres, m/s for speed), or null when a ref is unknown there. */
78
+ function measure(out, g, kind, f, home) {
79
+ if (kind === "near") return refDistance(out, f, g.near[0], g.near[1]);
80
+ if (kind === "above") {
81
+ const a = refPoint(out, f, g.above[0]), b = refPoint(out, f, g.above[1]);
82
+ return a && b ? a[1] - b[1] : null;
83
+ }
84
+ if (kind === "speed") return speedAt(out, g.speed, f);
85
+ const p = home && refPoint(out, f, movedRef(homeRef(g)));
86
+ return p ? len(sub(p, home)) : null;
87
+ }
88
+
89
+ /** How far value v is from meeting the bound (> 0 fails). */
90
+ const shortOf = (kind, v, need) => (AT_MOST.has(kind) ? v - need : need - v);
91
+ const round4 = x => Math.max(1e-4, Math.round(x * 1e4) / 1e4);
92
+
93
+ /** The measured frames of goal g over [a, b]: [{ f, v, short }], and the frame its point is measured from (a point's moved or still). */
94
+ function rowsOf(X, g, kind, a, b) {
95
+ const need = goalNeed(g, kind), point = (kind === "moved" || kind === "still") && !homeRef(g).startsWith("object:");
96
+ // a point is measured from where it is at the window's first frame (outside a windowed trial compile: unknown, so nothing is measured)
97
+ const home = kind === "moved" || kind === "still" ? movedHome(X.out, g, a) : null, rows = [];
98
+ for (let f = Math.max(a, X.f0); f <= Math.min(b, X.last); f++) {
99
+ const v = measure(X.out, g, kind, f, home);
100
+ if (v !== null) rows.push({ f, v, short: shortOf(kind, v, need) });
101
+ }
102
+ return { rows, from: point ? a : undefined };
103
+ }
104
+
105
+ /**
106
+ * The first frame goal j holds (its own window, cut by its own after/before): a frame, null when
107
+ * it never holds there (or sits in an after/before loop), undefined when no frame of it is measured
108
+ * (a windowed trial compile that does not reach it).
109
+ */
110
+ function eventOf(X, j) {
111
+ if (X.events.has(j)) return X.events.get(j);
112
+ if (X.visiting.has(j)) return null;
113
+ X.visiting.add(j);
114
+ const g = X.goals[j], kind = goalKinds(g)[0], w = kind && windowOf(X, j);
115
+ let e;
116
+ if (w && !w.wait) {
117
+ const { rows } = rowsOf(X, g, kind, w.a, w.b);
118
+ e = rows.length ? (rows.find(r => r.short <= 0)?.f ?? null) : undefined;
119
+ } else e = w?.wait ? null : undefined;
120
+ X.visiting.delete(j);
121
+ X.events.set(j, e);
122
+ return e;
123
+ }
124
+
125
+ /** The frames goal i measures: at cut by after and before ({ a, b }), or { wait } when that leaves none, or { skip } when unknown here. */
126
+ function windowOf(X, i) {
127
+ const g = X.goals[i];
128
+ let [a, b] = Array.isArray(g.at) ? g.at : [g.at, g.at];
129
+ for (const side of ["after", "before"]) {
130
+ if (g[side] === undefined) continue;
131
+ const j = X.names.get(g[side]);
132
+ if (j === undefined || j === i) return { wait: `${side} "${g[side]}" names no other goal` };
133
+ const e = eventOf(X, j);
134
+ if (e === undefined) return { skip: true };
135
+ if (e === null) return { wait: `waits for "${g[side]}" (${side}), which never holds` };
136
+ if (side === "after") a = Math.max(a, e + 1); else b = Math.min(b, e - 1);
137
+ if (a > b) return { wait: `no frames left ${side} "${g[side]}" (it holds first at f${e}; at is f${Array.isArray(g.at) ? `${g.at[0]}-f${g.at[1]}` : g.at})` };
138
+ }
139
+ return { a, b };
140
+ }
141
+
142
+ function message(name, kind, row, need, any, from) {
143
+ const where = any ? `f${row.f}, the best of f${any[0]}-f${any[1]}` : `f${row.f}`;
144
+ if (kind === "near") return `${name}: ${m3(row.v)} m at ${where} (needs <= ${need})`;
145
+ if (kind === "above") return `${name}: ${m3(row.v)} m above at ${where} (needs >= ${need})`;
146
+ if (kind === "speed") return `${name}: ${m3(row.v)} m/s at ${where} (needs >= ${need})`;
147
+ if (kind === "still") return `${name}: ${m3(row.v)} m from ${from === undefined ? "its scene pose" : `f${from}`} at ${where} (needs <= ${need})`;
148
+ return `${name}: moved ${m3(row.v)} m${from === undefined ? "" : ` from f${from}`} at ${where} (needs >= ${need})`;
149
+ }
150
+
151
+ /** The frames goal i measures in compile result out (after/before applied): { a, b } | { wait } | { skip } (hints-goal.js). */
152
+ export function goalWindow(out, goals, i) {
153
+ const f0 = out.f0 ?? 0, names = new Map(goals.map((g, j) => [goalName(g, j), j]));
154
+ return windowOf({ out, goals, names, f0, last: f0 + (out.frames?.length ?? 0) - 1, events: new Map(), visiting: new Set() }, i);
155
+ }
156
+
157
+ /**
158
+ * goalChecks(out, goals) -> { issues, results }
159
+ * @param {object} out compileMotion result (refs.js reads it)
160
+ * @param {object[]} goals spec.goals
161
+ * @returns {{ issues: object[], results: { name: string, kind: string, ok: boolean, value: number|null, at: number|null, need: number }[] }}
162
+ */
163
+ export function goalChecks(out, goals) {
164
+ const issues = [], results = [], f0 = out.f0 ?? 0;
165
+ const X = { out, goals, names: new Map(goals.map((g, j) => [goalName(g, j), j])), f0, last: f0 + (out.frames?.length ?? 0) - 1, events: new Map(), visiting: new Set() };
166
+ goals.forEach((g, i) => {
167
+ const kind = goalKinds(g)[0];
168
+ if (!kind) return;
169
+ const name = goalName(g, i), need = goalNeed(g, kind), w = windowOf(X, i), at0 = Array.isArray(g.at) ? g.at[0] : g.at;
170
+ if (w.skip) return;
171
+ if (w.wait) {
172
+ results.push({ name, kind, ok: false, value: null, at: null, need });
173
+ if (at0 >= f0 && at0 <= X.last) issues.push({ kind: "GOAL", msg: `${name}: ${w.wait}`, frame: at0 - f0, value: 0.01, limit: 0 });
174
+ return;
175
+ }
176
+ let { rows, from } = rowsOf(X, g, kind, w.a, w.b);
177
+ // a windowed trial compile (search.js) may not reach at; those frames cannot change there
178
+ if (!rows.length) return;
179
+ // a point's moved is one value: the farthest it gets from where it was at at[0]
180
+ if (kind === "moved" && from !== undefined) rows = [rows.reduce((p, r) => (r.v > p.v ? r : p))];
181
+ const any = goalMode(g, kind) === "any", cut = Array.isArray(g.at) ? w.a !== w.b : false;
182
+ const pick = rows.reduce((p, r) => ((any ? r.short < p.short : r.short > p.short) ? r : p));
183
+ const ok = pick.short <= 0;
184
+ results.push({ name, kind, ok, value: m3(pick.v), at: pick.f, need });
185
+ if (ok) return;
186
+ for (const r of any ? [pick] : rows.filter(r => r.short > 0)) {
187
+ issues.push({ kind: "GOAL", msg: message(name, kind, r, need, any && cut ? [w.a, w.b] : null, from), frame: r.f - f0, value: round4(r.short), limit: 0 });
188
+ }
189
+ });
190
+ return { issues, results };
191
+ }
@@ -0,0 +1,60 @@
1
+ // The ground under a foot: the floor (y 0) or the top of a scene obstacle the sole stands on.
2
+ // Every ground measurement reads sole heights from here: QA's air runs, FLOAT and balance
3
+ // (style.js), SLIDE (checks.js), the timeline's planted runs, and the fixes that keep to QA's
4
+ // planted definition (fix/slide.js, fix/turn.js). A foot on a box top is then on the ground as one
5
+ // on the floor is. Session 68d305dc: a foot on a 0.7 m cube read as "no foot on the ground"
6
+ // (FLOAT n57), and naming the cube in checks.supports did not clear it (a support rests the hips).
7
+ // The obstacles are out.objectsAt(i): carried and follow objects are not ground, a hinge is at its
8
+ // turned pose. GROUND (a sole under the floor) and fix.ground stay on the floor.
9
+ import { T, apply, sub, len } from "../compiler/math.js";
10
+ import { solePoints } from "./geometry.js";
11
+
12
+ /** A top up to this far (m) above a sole point is still the ground under it: a sole sunk into a top stands on it. */
13
+ const SINK = 0.05;
14
+
15
+ const prepared = new WeakMap();
16
+
17
+ /** The obstacle boxes of one frame's map, with what the vertical-line test needs. */
18
+ function boxesOf(objs) {
19
+ let list = prepared.get(objs);
20
+ if (!list) {
21
+ list = Object.values(objs).filter(box => box.half && !box.ignore).map(box => {
22
+ const RT = T(box.R), c = [box.pos[0] + box.R[0][1] * box.half[1], box.pos[1] + box.R[1][1] * box.half[1], box.pos[2] + box.R[2][1] * box.half[1]];
23
+ return { RT, c, half: box.half, up: [box.R[1][0], box.R[1][1], box.R[1][2]], r: len(box.half) };
24
+ });
25
+ prepared.set(objs, list);
26
+ }
27
+ return list;
28
+ }
29
+
30
+ /** Height of the box's top on the vertical line through p (any rotation), or null when the line misses it. */
31
+ function topOver(b, p) {
32
+ if (Math.hypot(p[0] - b.c[0], p[2] - b.c[2]) > b.r) return null;
33
+ const q = apply(b.RT, sub(p, b.c));
34
+ let lo = -Infinity, hi = Infinity;
35
+ for (let k = 0; k < 3; k++) {
36
+ const d = b.up[k], h = b.half[k];
37
+ if (Math.abs(d) < 1e-9) { if (Math.abs(q[k]) > h) return null; continue; }
38
+ const t1 = (-h - q[k]) / d, t2 = (h - q[k]) / d;
39
+ lo = Math.max(lo, Math.min(t1, t2));
40
+ hi = Math.min(hi, Math.max(t1, t2));
41
+ }
42
+ return lo <= hi ? p[1] + hi : null;
43
+ }
44
+
45
+ /** World height of the ground under point p at frame index i of out (out.frames[i]). */
46
+ export function groundY(out, i, p) {
47
+ let g = 0;
48
+ for (const b of boxesOf(out.objectsAt(i))) {
49
+ const top = topOver(b, p);
50
+ if (top !== null && top <= p[1] + SINK && top > g) g = top;
51
+ }
52
+ return g;
53
+ }
54
+
55
+ /** solePoints of frame index i with y the height above the ground under each point (x, z are world). */
56
+ export function groundSole(out, i, side) {
57
+ const sp = solePoints(out.ctx.sk, out.frames[i].s, side);
58
+ for (const key of ["heel", "ball", "tip"]) sp[key] = [sp[key][0], sp[key][1] - groundY(out, i, sp[key]), sp[key][2]];
59
+ return sp;
60
+ }
@@ -0,0 +1,179 @@
1
+ // Hints for contact-type issues: a body part inside a box, the floor, the head, the torso or the
2
+ // other limb. Each answers a world move (direction x amount) for whatever drives that part.
3
+ import { add, sub, scale, norm, dot, len, clamp, apply, ry, T } from "../compiler/math.js";
4
+ import { bonePoint } from "../compiler/skeleton.js";
5
+ import { CAPSULES, segPoints, sdBox, boxNormal, headDepth, segDist, solePoints, ankleY } from "./geometry.js";
6
+ import { vec, m3 } from "./fmt.js";
7
+ import { kneeFoldHint, kneeWhy } from "./hints-knee.js";
8
+ import { objectFrame } from "../compiler/anchors.js";
9
+ import { bodyFor, bodyNormal, limbDepth } from "../body.js";
10
+ import { footProbes, footDepths } from "./foot-checks.js";
11
+
12
+ const MARGIN = 0.003;
13
+ /** The most a foot hint lifts a foot over a body it went into through a side (a stair riser); higher, it backs out. */
14
+ const LIFT_MAX = 0.25;
15
+ const sideOf = name => (/(^|_)l$|^Left/.test(name) ? "l" : /(^|_)r$|^Right/.test(name) ? "r" : null);
16
+
17
+ /** fix (qa/patch.js) moving anchor `name` of hand k by a world delta at f: its own point, in the frame that point is written in. */
18
+ function anchorFix(X, name, f, delta, k) {
19
+ const a = X.spec.anchors?.[name], path = field => `/anchors/${name}/${field}`;
20
+ if (a?.kind === "world") return { path: path("p"), delta };
21
+ if (a?.kind === "body") return { path: path("p"), delta: apply(ry(-(X.fr(f).c.yaw ?? 0)), delta) };
22
+ if (["bone", "segment", "prop"].includes(a?.kind)) return { path: path("offset"), delta };
23
+ if (a?.kind !== "object") return undefined;
24
+ // local is in the object's axes where that hand's target read it (anchors.js objectFrame)
25
+ const fr = X.fr(f), o = objectFrame(X.out.ctx, a, name, { ...fr, diag: { ...fr.diag, frame: f } }, k);
26
+ return { path: path("local"), delta: apply(T(o.R), delta) };
27
+ }
28
+
29
+ /** cause + hint (+ fix, qa/patch.js) for moving a body part (capsule name, prop_<name>, hand_<k>) by `delta` at frame f. */
30
+ export function moveHint(X, part, f, delta, why = "") {
31
+ const prop = /^prop_(.+)$/.exec(part);
32
+ const k = prop ? X.spec.props?.[prop[1]]?.hand : sideOf(part);
33
+ let label, cause, fix, shown = delta;
34
+ if (/^(hand|farm|uarm)_/.test(part) || prop) {
35
+ const d = X.hand(k, f);
36
+ label = d.label;
37
+ fix = d.anchor ? anchorFix(X, d.anchor, f, delta, k) : d.ch === `hand_${k}` ? { channel: d.ch, f, delta } : undefined;
38
+ // an object anchor moves its point on the object (local, in the object's axes), never the object
39
+ const on = d.anchor && X.spec.anchors[d.anchor]?.kind === "object" ? X.spec.anchors[d.anchor].object : null;
40
+ if (on && fix) { label = `anchors.${d.anchor}.local (a point on ${on}, in ${on}'s axes; ${on} stays)`; shown = fix.delta; }
41
+ cause = d.anchor ? `anchor ${d.anchor}${d.fit !== null ? ` (fits[${d.fit}])` : ""} via ${X.cause(d.ch, f)}` : X.cause(d.ch, f);
42
+ } else if (/^(shin|foot|sole)_/.test(part)) { label = `foot_${k}`; cause = X.cause(label, f); fix = { channel: label, f, delta }; }
43
+ // a body held since its key (it breathes and sways there, compiler/idle.js): move what placed it (patch.js hold)
44
+ else { label = "root"; cause = X.cause("root", f); fix = { channel: "root", f, delta, ...(/^root held since /.test(cause) ? { hold: true } : {}) }; }
45
+ // a key the walk generator wrote: the agent changes the walk, not the key
46
+ const walk = / (walk|walkTo) /.test(` ${cause}`) && /step|start|end/.test(cause);
47
+ if (walk && !/^anchor/.test(label)) return { cause, hint: `walk path: ${label} needs ${vec(delta)} m at f${f}${why}; change that walk's heading/turnDistance/step (or give one a { range: [lo, hi] })` };
48
+ return { cause, hint: `${label}: move ${vec(shown)} m at f${f}${why}`, fix };
49
+ }
50
+
51
+ const capsule = name => CAPSULES.find(c => c[0] === name);
52
+
53
+ /** Deepest point of a capsule in a box at frame f and the box's outward normal there. */
54
+ function deepest(X, f, part, box) {
55
+ const [, a, b] = capsule(part), { s } = X.fr(f);
56
+ const pts = segPoints(s.P[X.I[a]], s.P[X.I[b]]), ds = pts.map(p => sdBox(p, box)), m = Math.min(...ds);
57
+ return { p: pts[ds.indexOf(m)], n: boxNormal(pts[ds.indexOf(m)], box), d: m };
58
+ }
59
+
60
+ function boxHint(X, g, part, id, need) {
61
+ const f = g.worstFrame, box = X.out.objectsAt(X.rel(f))[id];
62
+ if (!box || !capsule(part)) return null;
63
+ const { n } = deepest(X, f, part, box);
64
+ return moveHint(X, part, f, scale(n, need), ` (out of ${id})`);
65
+ }
66
+
67
+ /**
68
+ * A foot in a box (foot-checks.js): through a side face (a toe swung into a stair's riser) the foot rises over the
69
+ * box's top by what its deepest probe lacks, with the way straight out of that side as the other choice; through
70
+ * the top face (a sole sunk in a step) it comes out along that face.
71
+ */
72
+ function footHint(X, g, part, id) {
73
+ const f = g.worstFrame, box = X.out.objectsAt(X.rel(f))[id];
74
+ if (!box) return null;
75
+ const probes = footProbes(X.sk, X.fr(f).s, part.endsWith("_l") ? "Left" : "Right"), d = footDepths(probes, box), need = g.worst - g.limit + MARGIN;
76
+ if (!(d.side > 0)) return d.topAt ? moveHint(X, part, f, scale(boxNormal(d.topAt, box), need), ` (out of ${id}'s top)`) : null;
77
+ const under = p => 2 * box.half[1] - apply(T(box.R), sub(p, box.pos))[1];
78
+ const rise = Math.max(...probes.filter(p => sdBox(p, box) < 0).map(under)) + MARGIN, out = scale(boxNormal(d.sideAt, box), need);
79
+ // a step's riser is cleared by lifting the swing; a panel the foot kicks or a wall is left the way the foot came
80
+ if (rise > LIFT_MAX) return moveHint(X, part, f, out, ` (out of ${id}'s side)`);
81
+ const r = moveHint(X, part, f, apply(box.R, [0, rise, 0]), ` (over ${id}'s top; its ${g.worst.toFixed(3)} m is through a side)`);
82
+ r.hint += /^walk path/.test(r.hint) ? "; a higher lift raises the swing" : `; or move ${vec(out)} m out of that side`;
83
+ return r;
84
+ }
85
+
86
+ function towardFrom(X, g, part, from, need, what) {
87
+ return moveHint(X, part, g.worstFrame, scale(norm(from), need), ` (away from the ${what})`);
88
+ }
89
+
90
+ /** Probe points of a hand or prop at frame f (as the FACE/BODY checks probe them). */
91
+ function probes(X, f, nm) {
92
+ const { s, diag } = X.fr(f), I = X.I;
93
+ if (nm.startsWith("hand_")) { const S = nm.endsWith("l") ? "Left" : "Right"; return segPoints(s.P[I[`${S}Hand`]], s.P[I[`${S}HandMiddle3`]], 5); }
94
+ return Object.entries(diag.props?.[nm.slice(5)] ?? {}).filter(([k, p]) => Array.isArray(p) && k !== "origin").map(([, p]) => p);
95
+ }
96
+
97
+ export const contactHints = {
98
+ COLLIDE(X, g) {
99
+ const [, part, id] = /^(\S+) x (.+)$/.exec(g.subject) ?? [];
100
+ if (/^foot_[lr]$/.test(part ?? "")) return footHint(X, g, part, id);
101
+ const r = boxHint(X, g, part, id, g.worst - g.limit + MARGIN);
102
+ if (r && /^(hand|farm)_/.test(part) && !X.spec.fix?.penetration && g.worst - g.limit <= 0.05) {
103
+ r.hint += "; or fix.penetration: 0.02 pushes shallow hand hits out";
104
+ if (X.spec.fix !== false) r.fix = { path: "/fix/penetration", value: 0.02 };
105
+ }
106
+ return r;
107
+ },
108
+ CLEARANCE(X, g) {
109
+ const k = (X.spec.checks?.clearance ?? []).find(c => g.subject.startsWith(`${c.name}:`));
110
+ return k && boxHint(X, g, k.part, k.object, k.min - g.worst + MARGIN);
111
+ },
112
+ GROUND(X, g) {
113
+ const k = g.subject.startsWith("Left") ? "l" : "r", f = g.worstFrame, c = X.fr(f).c, fold = X.fr(f).diag[`leg_fold_${k}`];
114
+ // the knee on its stop left the ankle under its target (compiler/limbs.js): raising the foot folds it further, the root comes up
115
+ if (fold) return kneeFoldHint(X, k, f, kneeWhy("the sole is in the floor because the knee is on its stop: ", fold), c[`foot_${k}`]);
116
+ const pitch = c[`fpitch_${k}`] ? `, or less fpitch_${k} (now ${m3(c[`fpitch_${k}`])} deg; + lifts the heel)` : "";
117
+ return { cause: X.cause(`foot_${k}`, f), hint: `foot_${k}: raise ${m3(g.worst + 0.001)} m at f${f} (foot_* is the ankle; it stands ${ankleY(X.sk)} m above the floor)${pitch}`,
118
+ fix: { channel: `foot_${k}`, f, delta: [0, g.worst + 0.001, 0] } };
119
+ },
120
+ FACE(X, g) {
121
+ const nm = g.subject.replace(/ into head$/, ""), f = g.worstFrame, { s } = X.fr(f);
122
+ const c = bonePoint(s, X.I.Head, X.sk.landmarks.headCentre);
123
+ const p = probes(X, f, nm).reduce((best, q) => (headDepth(X.sk, s, q) > headDepth(X.sk, s, best) ? q : best));
124
+ return towardFrom(X, g, nm, sub(p, c), g.worst - g.limit + MARGIN, "head");
125
+ },
126
+ BODY(X, g) {
127
+ const [, nm, part] = /^(\S+) into (\S+)$/.exec(g.subject) ?? [];
128
+ const cap = capsule(part), f = g.worstFrame, { s } = X.fr(f);
129
+ // an arm on the fitted skin (body-checks.js): the hand target moves out along the skin where it goes deepest;
130
+ // an upper arm or forearm says so, since turning its elbow (elbow_<k>) away from the body may do instead
131
+ const limb = /^(hand|farm|uarm)_([lr])$/.exec(nm ?? ""), body = limb && bodyFor(X.sk);
132
+ if (body) {
133
+ const bone = X.I[`${limb[2] === "l" ? "Left" : "Right"}${{ hand: "Hand", farm: "ForeArm", uarm: "Arm" }[limb[1]]}`], hit = limbDepth(body, X.sk, s, bone);
134
+ const out = hit.p && bodyNormal(body, s, hit.p, body.skip.get(bone));
135
+ if (out) {
136
+ const r = moveHint(X, nm, f, scale(out, g.worst - g.limit + MARGIN), ` (out of the ${part})`);
137
+ if (limb[1] !== "hand") r.hint += `; or turn elbow_${limb[2]} away from the ${part}`;
138
+ return r;
139
+ }
140
+ }
141
+ if (!cap) return null;
142
+ const A = s.P[X.I[cap[1]]], B = s.P[X.I[cap[2]]], ab = sub(B, A);
143
+ const axis = p => add(A, scale(ab, clamp(dot(sub(p, A), ab) / dot(ab, ab), 0, 1)));
144
+ const p = probes(X, f, nm).reduce((best, q) => (len(sub(q, axis(q))) < len(sub(best, axis(best))) ? q : best));
145
+ return towardFrom(X, g, nm, sub(p, axis(p)), g.worst - g.limit + MARGIN, "torso");
146
+ },
147
+ SELF(X, g) {
148
+ const f = g.worstFrame, { s } = X.fr(f), P = s.P, I = X.I;
149
+ if (g.subject === "hands overlap") {
150
+ const d = norm(sub(P[I.LeftHand], P[I.RightHand])), need = (g.worst - g.limit + MARGIN) / 2;
151
+ const r = moveHint(X, "hand_l", f, scale(d, need));
152
+ return { cause: r.cause, hint: `${r.hint}; and ${moveHint(X, "hand_r", f, scale(d, -need)).hint}`, fix: moveHint(X, "hand_l", f, scale(d, 2 * need)).fix };
153
+ }
154
+ const shins = g.subject === "shins touch", min = shins ? 0.1 : 0.135;
155
+ const [a, b] = shins ? ["Leg", "Foot"] : ["UpLeg", "Leg"];
156
+ const gap = segDist(P[I[`Left${a}`]], P[I[`Left${b}`]], P[I[`Right${a}`]], P[I[`Right${b}`]]);
157
+ const d = sub(P[I[`Left${b}`]], P[I[`Right${b}`]]); d[1] = 0;
158
+ const need = (min - gap + MARGIN) / 2, dir = norm(d);
159
+ return { cause: X.cause("foot_l", f), hint: `foot_l: move ${vec(scale(dir, need))} m and foot_r ${vec(scale(dir, -need))} m at f${f} (${shins ? "shins" : "thighs"} ${m3(gap)} m apart, need ${min}); or spread knee_l/knee_r`,
160
+ fix: { channel: "foot_l", f, delta: scale(dir, 2 * need) } };
161
+ },
162
+ OBJECT(X, g) {
163
+ const [, id, oid] = /^(\S+) into (.+)$/.exec(g.subject) ?? [];
164
+ const ch = X.spec.objects?.[id]?.channel;
165
+ if (!ch) return null;
166
+ const at = f => X.out.baked[ch]?.[f] ?? 0, clean = g.first > 0 ? at(g.first - 1) : at(0);
167
+ return { cause: X.cause(ch, g.worstFrame), hint: `${ch}: keep it within ${m3(clean)} deg (it reaches ${m3(at(g.worstFrame))} at f${g.worstFrame}, ${m3(g.worst)} m into ${oid}), or move ${oid}`,
168
+ fix: { channel: ch, f: g.worstFrame, value: clean } };
169
+ },
170
+ BALANCE(X, g) {
171
+ const f = g.worstFrame, { s } = X.fr(f), P = s.P, I = X.I;
172
+ if (g.subject === "no foot on the ground") return { cause: X.cause("root", f), hint: `at f${f} lower foot_l or foot_r onto the ground, the floor or the top of an object under it (the ankle stands ${ankleY(X.sk)} m above it), or declare checks.supports for the seat the hips rest on` };
173
+ const com = scale(["Hips", "Spine1", "Spine2", "Head"].reduce((acc, j) => add(acc, P[I[j]]), [0, 0, 0]), 0.25);
174
+ const feet = ["Left", "Right"].flatMap(S => Object.values(solePoints(X.sk, s, S)));
175
+ const xs = feet.map(p => p[0]), zs = feet.map(p => p[2]), mg = 0.08 - 0.01;
176
+ const to = [clamp(com[0], Math.min(...xs) - mg, Math.max(...xs) + mg), com[1], clamp(com[2], Math.min(...zs) - mg, Math.max(...zs) + mg)];
177
+ return { cause: X.cause("root", f), hint: `root: move ${vec(sub(to, com))} m at f${f} (centre of mass over the feet), or step a foot under it`, fix: { channel: "root", f, delta: sub(to, com) } };
178
+ },
179
+ };