@rig-c/create 1.0.2 → 1.1.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 (629) hide show
  1. package/README.md +21 -5
  2. package/docs/AGENT-REFERENCE.md +62 -0
  3. package/docs/CHECKS.md +45 -9
  4. package/docs/INTERVIEW.md +19 -7
  5. package/docs/PROJECT.md +10 -0
  6. package/package.json +4 -1
  7. package/scripts/npm-json.ts +74 -0
  8. package/scripts/verify-example-seals.ts +148 -0
  9. package/src/agent-guide.ts +7 -4
  10. package/src/check.ts +7 -4
  11. package/src/choice-writers.ts +3 -14
  12. package/src/cli.ts +1 -0
  13. package/src/feedback.ts +3 -10
  14. package/src/fix-ledger.ts +1 -1
  15. package/src/job-acts.ts +4 -0
  16. package/src/job-host-state.ts +154 -0
  17. package/src/job-host.ts +37 -14
  18. package/src/job-outbox.ts +5 -3
  19. package/src/job-publication.ts +17 -13
  20. package/src/job-runtime.ts +17 -4
  21. package/src/next.ts +110 -24
  22. package/src/parts-review.ts +4 -11
  23. package/src/reopen.ts +72 -9
  24. package/src/review-act.ts +49 -14
  25. package/src/review-package.ts +3 -1
  26. package/src/rig-version.ts +219 -8
  27. package/src/scene-writers.ts +5 -3
  28. package/src/scene.ts +14 -4
  29. package/src/signable.ts +25 -3
  30. package/src/signoff-checkpoint-act.ts +2 -16
  31. package/src/signoff.ts +3 -15
  32. package/src/waypoints.ts +20 -9
  33. package/templates/agent-guide.md +2 -24
  34. package/templates/collection.json +10 -2
  35. package/templates/example-chain/.gitignore +6 -0
  36. package/templates/example-chain/.npmignore +1 -0
  37. package/templates/example-chain/AGENT-REFERENCE.md +62 -0
  38. package/templates/example-chain/AGENTS.md +4 -26
  39. package/templates/example-chain/README.md +1 -1
  40. package/templates/example-chain/chain.json +385 -319
  41. package/templates/example-chain/checkpoints/0a-interview-options/.gitignore +6 -0
  42. package/templates/example-chain/checkpoints/0a-interview-options/.npmignore +1 -0
  43. package/templates/example-chain/checkpoints/0a-interview-options/AGENT-REFERENCE.md +62 -0
  44. package/templates/example-chain/checkpoints/0a-interview-options/AGENTS.md +4 -26
  45. package/templates/example-chain/checkpoints/0a-interview-options/project.json +22 -5
  46. package/templates/example-chain/checkpoints/0a-interview-options.json +7 -3
  47. package/templates/example-chain/checkpoints/0b-plan-pending/.gitignore +6 -0
  48. package/templates/example-chain/checkpoints/0b-plan-pending/.npmignore +1 -0
  49. package/templates/example-chain/checkpoints/0b-plan-pending/AGENT-REFERENCE.md +62 -0
  50. package/templates/example-chain/checkpoints/0b-plan-pending/AGENTS.md +4 -26
  51. package/templates/example-chain/checkpoints/0b-plan-pending/project.json +22 -5
  52. package/templates/example-chain/checkpoints/0b-plan-pending.json +7 -3
  53. package/templates/example-chain/checkpoints/1-parts-verdict/.gitignore +6 -0
  54. package/templates/example-chain/checkpoints/1-parts-verdict/.npmignore +1 -0
  55. package/templates/example-chain/checkpoints/1-parts-verdict/AGENT-REFERENCE.md +62 -0
  56. package/templates/example-chain/checkpoints/1-parts-verdict/AGENTS.md +4 -26
  57. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/config.json +88 -0
  58. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/input/painting_in_rig.png +0 -0
  59. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/input/parts/background.png +0 -0
  60. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/input/parts/eye_l.png +0 -0
  61. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/input/parts/eye_r.png +0 -0
  62. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/input/parts/face.png +0 -0
  63. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/input/parts/lantern.png +0 -0
  64. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/input/parts/torso.png +0 -0
  65. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/input/parts.json +188 -0
  66. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/input/recomposite_rig.png +0 -0
  67. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/interview-requirements.json +8 -0
  68. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/check/build/run.json +40 -0
  69. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/check/build/skeleton.atlas +28 -0
  70. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/check/build/skeleton.json +674 -0
  71. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/check/build/skeleton.model.json +1072 -0
  72. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/check/build/skeleton.png +0 -0
  73. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/images/background.png +0 -0
  74. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/images/eye_l.png +0 -0
  75. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/images/eye_r.png +0 -0
  76. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/images/face.png +0 -0
  77. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/images/lantern.png +0 -0
  78. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/images/torso.png +0 -0
  79. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/mesh_report.json +15 -0
  80. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/motion.json +137 -0
  81. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/rig.json +536 -0
  82. package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/run.json +52 -0
  83. package/templates/example-chain/checkpoints/1-parts-verdict/project.json +24 -7
  84. package/templates/example-chain/checkpoints/1-parts-verdict.json +9 -5
  85. package/templates/example-chain/checkpoints/2-rigging-answers/.gitignore +6 -0
  86. package/templates/example-chain/checkpoints/2-rigging-answers/.npmignore +1 -0
  87. package/templates/example-chain/checkpoints/2-rigging-answers/AGENT-REFERENCE.md +62 -0
  88. package/templates/example-chain/checkpoints/2-rigging-answers/AGENTS.md +4 -26
  89. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/config.json +88 -0
  90. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/input/painting_in_rig.png +0 -0
  91. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/input/parts/background.png +0 -0
  92. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/input/parts/eye_l.png +0 -0
  93. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/input/parts/eye_r.png +0 -0
  94. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/input/parts/face.png +0 -0
  95. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/input/parts/lantern.png +0 -0
  96. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/input/parts/torso.png +0 -0
  97. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/input/parts.json +188 -0
  98. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/input/recomposite_rig.png +0 -0
  99. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/interview-requirements.json +8 -0
  100. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/check/build/run.json +40 -0
  101. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/check/build/skeleton.atlas +28 -0
  102. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/check/build/skeleton.json +674 -0
  103. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/check/build/skeleton.model.json +1072 -0
  104. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/check/build/skeleton.png +0 -0
  105. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/images/background.png +0 -0
  106. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/images/eye_l.png +0 -0
  107. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/images/eye_r.png +0 -0
  108. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/images/face.png +0 -0
  109. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/images/lantern.png +0 -0
  110. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/images/torso.png +0 -0
  111. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/mesh_report.json +15 -0
  112. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/motion.json +137 -0
  113. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/rig.json +536 -0
  114. package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/run.json +52 -0
  115. package/templates/example-chain/checkpoints/2-rigging-answers/project.json +24 -7
  116. package/templates/example-chain/checkpoints/2-rigging-answers.json +21 -5
  117. package/templates/example-chain/checkpoints/3-rig-review/.gitignore +6 -0
  118. package/templates/example-chain/checkpoints/3-rig-review/.npmignore +1 -0
  119. package/templates/example-chain/checkpoints/3-rig-review/AGENT-REFERENCE.md +62 -0
  120. package/templates/example-chain/checkpoints/3-rig-review/AGENTS.md +4 -26
  121. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/config.json +88 -0
  122. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/input/painting_in_rig.png +0 -0
  123. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/input/parts/background.png +0 -0
  124. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/input/parts/eye_l.png +0 -0
  125. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/input/parts/eye_r.png +0 -0
  126. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/input/parts/face.png +0 -0
  127. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/input/parts/lantern.png +0 -0
  128. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/input/parts/torso.png +0 -0
  129. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/input/parts.json +188 -0
  130. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/input/recomposite_rig.png +0 -0
  131. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/interview-requirements.json +8 -0
  132. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/check/build/run.json +40 -0
  133. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/check/build/skeleton.atlas +28 -0
  134. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/check/build/skeleton.json +674 -0
  135. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/check/build/skeleton.model.json +1072 -0
  136. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/check/build/skeleton.png +0 -0
  137. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/images/background.png +0 -0
  138. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/images/eye_l.png +0 -0
  139. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/images/eye_r.png +0 -0
  140. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/images/face.png +0 -0
  141. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/images/lantern.png +0 -0
  142. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/images/torso.png +0 -0
  143. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/mesh_report.json +15 -0
  144. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/motion.json +137 -0
  145. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/rig.json +536 -0
  146. package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/run.json +52 -0
  147. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/config.json +88 -0
  148. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/interview-requirements.json +8 -0
  149. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/check/build/run.json +40 -0
  150. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/check/build/skeleton.atlas +28 -0
  151. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/check/build/skeleton.json +674 -0
  152. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/check/build/skeleton.model.json +1072 -0
  153. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/check/build/skeleton.png +0 -0
  154. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/parts/background.png +0 -0
  155. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/parts/eye_l.png +0 -0
  156. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/parts/eye_r.png +0 -0
  157. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/parts/face.png +0 -0
  158. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/parts/lantern.png +0 -0
  159. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/parts/torso.png +0 -0
  160. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/parts.json +188 -0
  161. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/rig/images/background.png +0 -0
  162. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/rig/images/eye_l.png +0 -0
  163. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/rig/images/eye_r.png +0 -0
  164. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/rig/images/face.png +0 -0
  165. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/rig/images/lantern.png +0 -0
  166. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/rig/images/torso.png +0 -0
  167. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/rig/mesh_report.json +15 -0
  168. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/rig/motion.json +137 -0
  169. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/rig/rig.json +536 -0
  170. package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/rig/run.json +52 -0
  171. package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/motion.json +1 -1
  172. package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/turn.json +108 -0
  173. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/check/build/run.json +40 -0
  174. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/check/build/skeleton.atlas +28 -0
  175. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/check/build/skeleton.json +674 -0
  176. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/check/build/skeleton.model.json +1072 -0
  177. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/check/build/skeleton.png +0 -0
  178. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/painting_in_rig.png +0 -0
  179. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/parts/background.png +0 -0
  180. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/parts/eye_l.png +0 -0
  181. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/parts/eye_r.png +0 -0
  182. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/parts/face.png +0 -0
  183. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/parts/lantern.png +0 -0
  184. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/parts/torso.png +0 -0
  185. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/parts.json +188 -0
  186. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/rig/images/background.png +0 -0
  187. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/rig/images/eye_l.png +0 -0
  188. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/rig/images/eye_r.png +0 -0
  189. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/rig/images/face.png +0 -0
  190. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/rig/images/lantern.png +0 -0
  191. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/rig/images/torso.png +0 -0
  192. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/rig/mesh_report.json +15 -0
  193. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/rig/motion.json +137 -0
  194. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/rig/rig.json +536 -0
  195. package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/rig/run.json +52 -0
  196. package/templates/example-chain/checkpoints/3-rig-review/project.json +77 -28
  197. package/templates/example-chain/checkpoints/3-rig-review.json +19 -11
  198. package/templates/example-chain/checkpoints/4-direction-post/.gitignore +6 -0
  199. package/templates/example-chain/checkpoints/4-direction-post/.npmignore +1 -0
  200. package/templates/example-chain/checkpoints/4-direction-post/AGENT-REFERENCE.md +62 -0
  201. package/templates/example-chain/checkpoints/4-direction-post/AGENTS.md +4 -26
  202. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/config.json +88 -0
  203. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/input/painting_in_rig.png +0 -0
  204. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/input/parts/background.png +0 -0
  205. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/input/parts/eye_l.png +0 -0
  206. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/input/parts/eye_r.png +0 -0
  207. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/input/parts/face.png +0 -0
  208. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/input/parts/lantern.png +0 -0
  209. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/input/parts/torso.png +0 -0
  210. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/input/parts.json +188 -0
  211. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/input/recomposite_rig.png +0 -0
  212. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/interview-requirements.json +8 -0
  213. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/check/build/run.json +40 -0
  214. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/check/build/skeleton.atlas +28 -0
  215. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/check/build/skeleton.json +674 -0
  216. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/check/build/skeleton.model.json +1072 -0
  217. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/check/build/skeleton.png +0 -0
  218. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/images/background.png +0 -0
  219. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/images/eye_l.png +0 -0
  220. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/images/eye_r.png +0 -0
  221. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/images/face.png +0 -0
  222. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/images/lantern.png +0 -0
  223. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/images/torso.png +0 -0
  224. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/mesh_report.json +15 -0
  225. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/motion.json +137 -0
  226. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/rig.json +536 -0
  227. package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/run.json +52 -0
  228. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/config.json +88 -0
  229. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/interview-requirements.json +8 -0
  230. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/check/build/run.json +40 -0
  231. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/check/build/skeleton.atlas +28 -0
  232. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/check/build/skeleton.json +674 -0
  233. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/check/build/skeleton.model.json +1072 -0
  234. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/check/build/skeleton.png +0 -0
  235. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/parts/background.png +0 -0
  236. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/parts/eye_l.png +0 -0
  237. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/parts/eye_r.png +0 -0
  238. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/parts/face.png +0 -0
  239. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/parts/lantern.png +0 -0
  240. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/parts/torso.png +0 -0
  241. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/parts.json +188 -0
  242. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/rig/images/background.png +0 -0
  243. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/rig/images/eye_l.png +0 -0
  244. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/rig/images/eye_r.png +0 -0
  245. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/rig/images/face.png +0 -0
  246. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/rig/images/lantern.png +0 -0
  247. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/rig/images/torso.png +0 -0
  248. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/rig/mesh_report.json +15 -0
  249. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/rig/motion.json +137 -0
  250. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/rig/rig.json +536 -0
  251. package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/rig/run.json +52 -0
  252. package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/camera_depth.json +2 -2
  253. package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/motion.json +1 -1
  254. package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/post_composition.json +2 -2
  255. package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/post_timing.json +2 -2
  256. package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/turn.json +108 -0
  257. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/check/build/run.json +40 -0
  258. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/check/build/skeleton.atlas +28 -0
  259. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/check/build/skeleton.json +674 -0
  260. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/check/build/skeleton.model.json +1072 -0
  261. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/check/build/skeleton.png +0 -0
  262. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/painting_in_rig.png +0 -0
  263. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/parts/background.png +0 -0
  264. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/parts/eye_l.png +0 -0
  265. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/parts/eye_r.png +0 -0
  266. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/parts/face.png +0 -0
  267. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/parts/lantern.png +0 -0
  268. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/parts/torso.png +0 -0
  269. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/parts.json +188 -0
  270. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/rig/images/background.png +0 -0
  271. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/rig/images/eye_l.png +0 -0
  272. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/rig/images/eye_r.png +0 -0
  273. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/rig/images/face.png +0 -0
  274. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/rig/images/lantern.png +0 -0
  275. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/rig/images/torso.png +0 -0
  276. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/rig/mesh_report.json +15 -0
  277. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/rig/motion.json +137 -0
  278. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/rig/rig.json +536 -0
  279. package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/rig/run.json +52 -0
  280. package/templates/example-chain/checkpoints/4-direction-post/project.json +106 -57
  281. package/templates/example-chain/checkpoints/4-direction-post.json +22 -14
  282. package/templates/example-chain/derived/drafts/chain/config.json +88 -0
  283. package/templates/example-chain/derived/drafts/chain/input/painting_in_rig.png +0 -0
  284. package/templates/example-chain/derived/drafts/chain/input/parts/background.png +0 -0
  285. package/templates/example-chain/derived/drafts/chain/input/parts/eye_l.png +0 -0
  286. package/templates/example-chain/derived/drafts/chain/input/parts/eye_r.png +0 -0
  287. package/templates/example-chain/derived/drafts/chain/input/parts/face.png +0 -0
  288. package/templates/example-chain/derived/drafts/chain/input/parts/lantern.png +0 -0
  289. package/templates/example-chain/derived/drafts/chain/input/parts/torso.png +0 -0
  290. package/templates/example-chain/derived/drafts/chain/input/parts.json +188 -0
  291. package/templates/example-chain/derived/drafts/chain/input/recomposite_rig.png +0 -0
  292. package/templates/example-chain/derived/drafts/chain/interview-requirements.json +8 -0
  293. package/templates/example-chain/derived/drafts/chain/out/check/build/run.json +40 -0
  294. package/templates/example-chain/derived/drafts/chain/out/check/build/skeleton.atlas +28 -0
  295. package/templates/example-chain/derived/drafts/chain/out/check/build/skeleton.json +674 -0
  296. package/templates/example-chain/derived/drafts/chain/out/check/build/skeleton.model.json +1072 -0
  297. package/templates/example-chain/derived/drafts/chain/out/check/build/skeleton.png +0 -0
  298. package/templates/example-chain/derived/drafts/chain/out/images/background.png +0 -0
  299. package/templates/example-chain/derived/drafts/chain/out/images/eye_l.png +0 -0
  300. package/templates/example-chain/derived/drafts/chain/out/images/eye_r.png +0 -0
  301. package/templates/example-chain/derived/drafts/chain/out/images/face.png +0 -0
  302. package/templates/example-chain/derived/drafts/chain/out/images/lantern.png +0 -0
  303. package/templates/example-chain/derived/drafts/chain/out/images/torso.png +0 -0
  304. package/templates/example-chain/derived/drafts/chain/out/mesh_report.json +15 -0
  305. package/templates/example-chain/derived/drafts/chain/out/motion.json +137 -0
  306. package/templates/example-chain/derived/drafts/chain/out/rig.json +536 -0
  307. package/templates/example-chain/derived/drafts/chain/out/run.json +52 -0
  308. package/templates/example-chain/derived/review/v1/config.json +88 -0
  309. package/templates/example-chain/derived/review/v1/interview-requirements.json +8 -0
  310. package/templates/example-chain/derived/review/v1/out/check/build/run.json +40 -0
  311. package/templates/example-chain/derived/review/v1/out/check/build/skeleton.atlas +28 -0
  312. package/templates/example-chain/derived/review/v1/out/check/build/skeleton.json +674 -0
  313. package/templates/example-chain/derived/review/v1/out/check/build/skeleton.model.json +1072 -0
  314. package/templates/example-chain/derived/review/v1/out/check/build/skeleton.png +0 -0
  315. package/templates/example-chain/derived/review/v1/out/parts/background.png +0 -0
  316. package/templates/example-chain/derived/review/v1/out/parts/eye_l.png +0 -0
  317. package/templates/example-chain/derived/review/v1/out/parts/eye_r.png +0 -0
  318. package/templates/example-chain/derived/review/v1/out/parts/face.png +0 -0
  319. package/templates/example-chain/derived/review/v1/out/parts/lantern.png +0 -0
  320. package/templates/example-chain/derived/review/v1/out/parts/torso.png +0 -0
  321. package/templates/example-chain/derived/review/v1/out/parts.json +188 -0
  322. package/templates/example-chain/derived/review/v1/out/rig/images/background.png +0 -0
  323. package/templates/example-chain/derived/review/v1/out/rig/images/eye_l.png +0 -0
  324. package/templates/example-chain/derived/review/v1/out/rig/images/eye_r.png +0 -0
  325. package/templates/example-chain/derived/review/v1/out/rig/images/face.png +0 -0
  326. package/templates/example-chain/derived/review/v1/out/rig/images/lantern.png +0 -0
  327. package/templates/example-chain/derived/review/v1/out/rig/images/torso.png +0 -0
  328. package/templates/example-chain/derived/review/v1/out/rig/mesh_report.json +15 -0
  329. package/templates/example-chain/derived/review/v1/out/rig/motion.json +137 -0
  330. package/templates/example-chain/derived/review/v1/out/rig/rig.json +536 -0
  331. package/templates/example-chain/derived/review/v1/out/rig/run.json +52 -0
  332. package/templates/example-chain/evidence/captions.json +1 -1
  333. package/templates/example-chain/evidence/direction/v2.json +1 -1
  334. package/templates/example-chain/evidence/direction-input.json +1 -1
  335. package/templates/example-chain/evidence/interview/camera_depth.json +2 -2
  336. package/templates/example-chain/evidence/interview/motion.json +1 -1
  337. package/templates/example-chain/evidence/interview/post_composition.json +2 -2
  338. package/templates/example-chain/evidence/interview/post_timing.json +2 -2
  339. package/templates/example-chain/evidence/interview/turn.json +108 -0
  340. package/templates/example-chain/evidence/scene/s1.json +2 -2
  341. package/templates/example-chain/outputs/v1/out/check/build/run.json +40 -0
  342. package/templates/example-chain/outputs/v1/out/check/build/skeleton.atlas +28 -0
  343. package/templates/example-chain/outputs/v1/out/check/build/skeleton.json +674 -0
  344. package/templates/example-chain/outputs/v1/out/check/build/skeleton.model.json +1072 -0
  345. package/templates/example-chain/outputs/v1/out/check/build/skeleton.png +0 -0
  346. package/templates/example-chain/outputs/v1/out/painting_in_rig.png +0 -0
  347. package/templates/example-chain/outputs/v1/out/parts/background.png +0 -0
  348. package/templates/example-chain/outputs/v1/out/parts/eye_l.png +0 -0
  349. package/templates/example-chain/outputs/v1/out/parts/eye_r.png +0 -0
  350. package/templates/example-chain/outputs/v1/out/parts/face.png +0 -0
  351. package/templates/example-chain/outputs/v1/out/parts/lantern.png +0 -0
  352. package/templates/example-chain/outputs/v1/out/parts/torso.png +0 -0
  353. package/templates/example-chain/outputs/v1/out/parts.json +188 -0
  354. package/templates/example-chain/outputs/v1/out/rig/images/background.png +0 -0
  355. package/templates/example-chain/outputs/v1/out/rig/images/eye_l.png +0 -0
  356. package/templates/example-chain/outputs/v1/out/rig/images/eye_r.png +0 -0
  357. package/templates/example-chain/outputs/v1/out/rig/images/face.png +0 -0
  358. package/templates/example-chain/outputs/v1/out/rig/images/lantern.png +0 -0
  359. package/templates/example-chain/outputs/v1/out/rig/images/torso.png +0 -0
  360. package/templates/example-chain/outputs/v1/out/rig/mesh_report.json +15 -0
  361. package/templates/example-chain/outputs/v1/out/rig/motion.json +137 -0
  362. package/templates/example-chain/outputs/v1/out/rig/rig.json +536 -0
  363. package/templates/example-chain/outputs/v1/out/rig/run.json +52 -0
  364. package/templates/example-chain/project.json +127 -78
  365. package/templates/example-direction/derived/review/v1/out/check/build/run.json +2 -2
  366. package/templates/example-draft/derived/drafts/lantern/out/check/build/run.json +2 -2
  367. package/templates/example-draft/derived/drafts/lantern/out/run.json +2 -2
  368. package/templates/example-draft/derived/review/v1/out/check/build/run.json +2 -2
  369. package/templates/example-draft/derived/review/v1/out/rig/run.json +2 -2
  370. package/templates/example-draft/derived/review/v2/out/check/build/run.json +2 -2
  371. package/templates/example-draft/derived/review/v2/out/rig/run.json +2 -2
  372. package/templates/example-draft/evidence/direction/v4.json +3 -3
  373. package/templates/example-draft/evidence/direction-input-v4.json +3 -3
  374. package/templates/example-draft/evidence/parts-review.json +1 -1
  375. package/templates/example-draft/evidence/review-reads/{52673b635b9cbc92da1a9e3d4c023a249bbacf79cd21b59724f03f18f8caf09b.json → 8866887a00012b5d5944b7525a478aea70931935bff35ddfcb186ffc515ef5af.json} +2 -2
  376. package/templates/example-draft/evidence/scene/s1.json +3 -3
  377. package/templates/example-draft/evidence/scene-citations.json +1 -1
  378. package/templates/example-draft/out/check/build/run.json +2 -2
  379. package/templates/example-draft/out/run.json +2 -2
  380. package/templates/example-draft/outputs/v1/out/check/build/run.json +2 -2
  381. package/templates/example-draft/outputs/v1/out/rig/run.json +2 -2
  382. package/templates/example-draft/outputs/v2/out/check/build/run.json +2 -2
  383. package/templates/example-draft/outputs/v2/out/rig/run.json +2 -2
  384. package/templates/example-interview-choice.json +113 -68
  385. package/templates/example-interview-options/constraint.json +2 -2
  386. package/templates/example-interview-options/example-assemble.json +2 -2
  387. package/templates/example-interview-options/example-bones.json +5 -5
  388. package/templates/example-interview-options/example-camera-depth.json +3 -3
  389. package/templates/example-interview-options/example-constraints.json +5 -5
  390. package/templates/example-interview-options/example-meshes.json +5 -5
  391. package/templates/example-interview-options/example-motion.json +5 -5
  392. package/templates/example-interview-options/example-picks.json +2 -2
  393. package/templates/example-interview-options/example-post-composition.json +3 -3
  394. package/templates/example-interview-options/example-post-timing.json +3 -3
  395. package/templates/example-interview-options/example-reference.json +2 -2
  396. package/templates/example-interview-options/example-rig-type.json +2 -2
  397. package/templates/example-interview-options/example-seethrough.json +2 -2
  398. package/templates/example-interview-options/example-turn.json +108 -0
  399. package/templates/example-interview-options/fullscreen.json +2 -2
  400. package/templates/example-interview-options/other-explicit.json +2 -2
  401. package/templates/example-interview-options/other-pending.json +2 -2
  402. package/templates/example-interview-options/other-picks.json +2 -2
  403. package/templates/example-invariants/invariants.json +223 -164
  404. package/templates/example-project.json +301 -249
  405. package/templates/example-remesh/.gitignore +6 -0
  406. package/templates/example-remesh/.npmignore +1 -0
  407. package/templates/example-remesh/AGENT-REFERENCE.md +62 -0
  408. package/templates/example-remesh/AGENTS.md +4 -26
  409. package/templates/example-remesh/derived/drafts/remesh/config.json +88 -0
  410. package/templates/example-remesh/derived/drafts/remesh/input/painting_in_rig.png +0 -0
  411. package/templates/example-remesh/derived/drafts/remesh/input/parts/background.png +0 -0
  412. package/templates/example-remesh/derived/drafts/remesh/input/parts/eye_l.png +0 -0
  413. package/templates/example-remesh/derived/drafts/remesh/input/parts/eye_r.png +0 -0
  414. package/templates/example-remesh/derived/drafts/remesh/input/parts/face.png +0 -0
  415. package/templates/example-remesh/derived/drafts/remesh/input/parts/lantern.png +0 -0
  416. package/templates/example-remesh/derived/drafts/remesh/input/parts/torso.png +0 -0
  417. package/templates/example-remesh/derived/drafts/remesh/input/parts.json +188 -0
  418. package/templates/example-remesh/derived/drafts/remesh/input/recomposite_rig.png +0 -0
  419. package/templates/example-remesh/derived/drafts/remesh/interview-requirements.json +8 -0
  420. package/templates/example-remesh/derived/drafts/remesh/out/check/build/run.json +40 -0
  421. package/templates/example-remesh/derived/drafts/remesh/out/check/build/skeleton.atlas +28 -0
  422. package/templates/example-remesh/derived/drafts/remesh/out/check/build/skeleton.json +674 -0
  423. package/templates/example-remesh/derived/drafts/remesh/out/check/build/skeleton.model.json +1072 -0
  424. package/templates/example-remesh/derived/drafts/remesh/out/check/build/skeleton.png +0 -0
  425. package/templates/example-remesh/derived/drafts/remesh/out/images/background.png +0 -0
  426. package/templates/example-remesh/derived/drafts/remesh/out/images/eye_l.png +0 -0
  427. package/templates/example-remesh/derived/drafts/remesh/out/images/eye_r.png +0 -0
  428. package/templates/example-remesh/derived/drafts/remesh/out/images/face.png +0 -0
  429. package/templates/example-remesh/derived/drafts/remesh/out/images/lantern.png +0 -0
  430. package/templates/example-remesh/derived/drafts/remesh/out/images/torso.png +0 -0
  431. package/templates/example-remesh/derived/drafts/remesh/out/mesh_report.json +15 -0
  432. package/templates/example-remesh/derived/drafts/remesh/out/motion.json +137 -0
  433. package/templates/example-remesh/derived/drafts/remesh/out/rig.json +536 -0
  434. package/templates/example-remesh/derived/drafts/remesh/out/run.json +52 -0
  435. package/templates/example-remesh/derived/review/v1/config.json +88 -0
  436. package/templates/example-remesh/derived/review/v1/interview-requirements.json +8 -0
  437. package/templates/example-remesh/derived/review/v1/out/check/build/run.json +44 -0
  438. package/templates/example-remesh/derived/review/v1/out/check/build/skeleton.atlas +28 -0
  439. package/templates/example-remesh/derived/review/v1/out/check/build/skeleton.json +674 -0
  440. package/templates/example-remesh/derived/review/v1/out/check/build/skeleton.model.json +1072 -0
  441. package/templates/example-remesh/derived/review/v1/out/check/build/skeleton.png +0 -0
  442. package/templates/example-remesh/derived/review/v1/out/painting_in_rig.png +0 -0
  443. package/templates/example-remesh/derived/review/v1/out/parts/background.png +0 -0
  444. package/templates/example-remesh/derived/review/v1/out/parts/eye_l.png +0 -0
  445. package/templates/example-remesh/derived/review/v1/out/parts/eye_r.png +0 -0
  446. package/templates/example-remesh/derived/review/v1/out/parts/face.png +0 -0
  447. package/templates/example-remesh/derived/review/v1/out/parts/lantern.png +0 -0
  448. package/templates/example-remesh/derived/review/v1/out/parts/torso.png +0 -0
  449. package/templates/example-remesh/derived/review/v1/out/parts.json +188 -0
  450. package/templates/example-remesh/derived/review/v1/out/rig/images/background.png +0 -0
  451. package/templates/example-remesh/derived/review/v1/out/rig/images/eye_l.png +0 -0
  452. package/templates/example-remesh/derived/review/v1/out/rig/images/eye_r.png +0 -0
  453. package/templates/example-remesh/derived/review/v1/out/rig/images/face.png +0 -0
  454. package/templates/example-remesh/derived/review/v1/out/rig/images/lantern.png +0 -0
  455. package/templates/example-remesh/derived/review/v1/out/rig/images/torso.png +0 -0
  456. package/templates/example-remesh/derived/review/v1/out/rig/mesh_report.json +15 -0
  457. package/templates/example-remesh/derived/review/v1/out/rig/motion.json +137 -0
  458. package/templates/example-remesh/derived/review/v1/out/rig/rig.json +536 -0
  459. package/templates/example-remesh/derived/review/v1/out/rig/run.json +52 -0
  460. package/templates/example-remesh/derived/review/v2/config.json +88 -0
  461. package/templates/example-remesh/derived/review/v2/interview-requirements.json +8 -0
  462. package/templates/example-remesh/derived/review/v2/out/check/build/run.json +44 -0
  463. package/templates/example-remesh/derived/review/v2/out/check/build/skeleton.atlas +28 -0
  464. package/templates/example-remesh/derived/review/v2/out/check/build/skeleton.json +674 -0
  465. package/templates/example-remesh/derived/review/v2/out/check/build/skeleton.model.json +1072 -0
  466. package/templates/example-remesh/derived/review/v2/out/check/build/skeleton.png +0 -0
  467. package/templates/example-remesh/derived/review/v2/out/painting_in_rig.png +0 -0
  468. package/templates/example-remesh/derived/review/v2/out/parts/background.png +0 -0
  469. package/templates/example-remesh/derived/review/v2/out/parts/eye_l.png +0 -0
  470. package/templates/example-remesh/derived/review/v2/out/parts/eye_r.png +0 -0
  471. package/templates/example-remesh/derived/review/v2/out/parts/face.png +0 -0
  472. package/templates/example-remesh/derived/review/v2/out/parts/lantern.png +0 -0
  473. package/templates/example-remesh/derived/review/v2/out/parts/torso.png +0 -0
  474. package/templates/example-remesh/derived/review/v2/out/parts.json +188 -0
  475. package/templates/example-remesh/derived/review/v2/out/rig/images/background.png +0 -0
  476. package/templates/example-remesh/derived/review/v2/out/rig/images/eye_l.png +0 -0
  477. package/templates/example-remesh/derived/review/v2/out/rig/images/eye_r.png +0 -0
  478. package/templates/example-remesh/derived/review/v2/out/rig/images/face.png +0 -0
  479. package/templates/example-remesh/derived/review/v2/out/rig/images/lantern.png +0 -0
  480. package/templates/example-remesh/derived/review/v2/out/rig/images/torso.png +0 -0
  481. package/templates/example-remesh/derived/review/v2/out/rig/mesh_report.json +15 -0
  482. package/templates/example-remesh/derived/review/v2/out/rig/motion.json +137 -0
  483. package/templates/example-remesh/derived/review/v2/out/rig/rig.json +536 -0
  484. package/templates/example-remesh/derived/review/v2/out/rig/run.json +52 -0
  485. package/templates/example-remesh/derived/review/v3/config.json +88 -0
  486. package/templates/example-remesh/derived/review/v3/interview-requirements.json +8 -0
  487. package/templates/example-remesh/derived/review/v3/out/check/build/run.json +44 -0
  488. package/templates/example-remesh/derived/review/v3/out/check/build/skeleton.atlas +28 -0
  489. package/templates/example-remesh/derived/review/v3/out/check/build/skeleton.json +674 -0
  490. package/templates/example-remesh/derived/review/v3/out/check/build/skeleton.model.json +1072 -0
  491. package/templates/example-remesh/derived/review/v3/out/check/build/skeleton.png +0 -0
  492. package/templates/example-remesh/derived/review/v3/out/painting_in_rig.png +0 -0
  493. package/templates/example-remesh/derived/review/v3/out/parts/background.png +0 -0
  494. package/templates/example-remesh/derived/review/v3/out/parts/eye_l.png +0 -0
  495. package/templates/example-remesh/derived/review/v3/out/parts/eye_r.png +0 -0
  496. package/templates/example-remesh/derived/review/v3/out/parts/face.png +0 -0
  497. package/templates/example-remesh/derived/review/v3/out/parts/lantern.png +0 -0
  498. package/templates/example-remesh/derived/review/v3/out/parts/torso.png +0 -0
  499. package/templates/example-remesh/derived/review/v3/out/parts.json +188 -0
  500. package/templates/example-remesh/derived/review/v3/out/rig/images/background.png +0 -0
  501. package/templates/example-remesh/derived/review/v3/out/rig/images/eye_l.png +0 -0
  502. package/templates/example-remesh/derived/review/v3/out/rig/images/eye_r.png +0 -0
  503. package/templates/example-remesh/derived/review/v3/out/rig/images/face.png +0 -0
  504. package/templates/example-remesh/derived/review/v3/out/rig/images/lantern.png +0 -0
  505. package/templates/example-remesh/derived/review/v3/out/rig/images/torso.png +0 -0
  506. package/templates/example-remesh/derived/review/v3/out/rig/mesh_report.json +15 -0
  507. package/templates/example-remesh/derived/review/v3/out/rig/motion.json +137 -0
  508. package/templates/example-remesh/derived/review/v3/out/rig/rig.json +536 -0
  509. package/templates/example-remesh/derived/review/v3/out/rig/run.json +52 -0
  510. package/templates/example-remesh/evidence/captions.json +1 -1
  511. package/templates/example-remesh/evidence/direction/v4.json +1 -1
  512. package/templates/example-remesh/evidence/direction/v5.json +1 -1
  513. package/templates/example-remesh/evidence/direction-input-v4.json +1 -1
  514. package/templates/example-remesh/evidence/direction-input-v5.json +1 -1
  515. package/templates/example-remesh/evidence/interview/assemble.json +1 -1
  516. package/templates/example-remesh/evidence/interview/bones.json +4 -4
  517. package/templates/example-remesh/evidence/interview/camera_depth.json +2 -2
  518. package/templates/example-remesh/evidence/interview/constraints.json +4 -4
  519. package/templates/example-remesh/evidence/interview/meshes.json +4 -4
  520. package/templates/example-remesh/evidence/interview/motion.json +4 -4
  521. package/templates/example-remesh/evidence/interview/post_composition.json +2 -2
  522. package/templates/example-remesh/evidence/interview/post_timing.json +2 -2
  523. package/templates/example-remesh/evidence/interview/reference.json +1 -1
  524. package/templates/example-remesh/evidence/interview/rig_type.json +1 -1
  525. package/templates/example-remesh/evidence/interview/seethrough.json +1 -1
  526. package/templates/example-remesh/evidence/interview/turn.json +108 -0
  527. package/templates/example-remesh/evidence/parts-review.json +1 -1
  528. package/templates/example-remesh/evidence/review-reads/{afe2522be4087f7f2fa7e97746d5f8574b0aedb474245ce2dbce0455e662f041.json → 99ade3eb19d70bd5f727138b3b4876ce86f1e1c22a59b516639bf85593996c32.json} +2 -2
  529. package/templates/example-remesh/evidence/scene/s1.json +2 -2
  530. package/templates/example-remesh/evidence/v1/registration/at-source.json +2 -2
  531. package/templates/example-remesh/evidence/v1/registration/rigc-run-1.json +2 -2
  532. package/templates/example-remesh/evidence/v2/registration/at-source.json +2 -2
  533. package/templates/example-remesh/evidence/v2/registration/rigc-run-1.json +2 -2
  534. package/templates/example-remesh/evidence/v3/registration/at-source.json +2 -2
  535. package/templates/example-remesh/evidence/v3/registration/rigc-run-1.json +2 -2
  536. package/templates/example-remesh/outputs/v1/idle/frames.json +29 -0
  537. package/templates/example-remesh/outputs/v1/idle/idle@1fps/contact.png +0 -0
  538. package/templates/example-remesh/outputs/v1/idle/idle@1fps/f0000.png +0 -0
  539. package/templates/example-remesh/outputs/v1/idle/idle@1fps/f0001.png +0 -0
  540. package/templates/example-remesh/outputs/v1/idle/idle@1fps/f0002.png +0 -0
  541. package/templates/example-remesh/outputs/v1/idle/idle@1fps/f0003.png +0 -0
  542. package/templates/example-remesh/outputs/v1/idle/idle@1fps/f0004.png +0 -0
  543. package/templates/example-remesh/outputs/v1/out/check/build/run.json +44 -0
  544. package/templates/example-remesh/outputs/v1/out/check/build/skeleton.atlas +28 -0
  545. package/templates/example-remesh/outputs/v1/out/check/build/skeleton.json +674 -0
  546. package/templates/example-remesh/outputs/v1/out/check/build/skeleton.model.json +1072 -0
  547. package/templates/example-remesh/outputs/v1/out/check/build/skeleton.png +0 -0
  548. package/templates/example-remesh/outputs/v1/out/painting_in_rig.png +0 -0
  549. package/templates/example-remesh/outputs/v1/out/parts/background.png +0 -0
  550. package/templates/example-remesh/outputs/v1/out/parts/eye_l.png +0 -0
  551. package/templates/example-remesh/outputs/v1/out/parts/eye_r.png +0 -0
  552. package/templates/example-remesh/outputs/v1/out/parts/face.png +0 -0
  553. package/templates/example-remesh/outputs/v1/out/parts/lantern.png +0 -0
  554. package/templates/example-remesh/outputs/v1/out/parts/torso.png +0 -0
  555. package/templates/example-remesh/outputs/v1/out/parts.json +188 -0
  556. package/templates/example-remesh/outputs/v1/out/rig/images/background.png +0 -0
  557. package/templates/example-remesh/outputs/v1/out/rig/images/eye_l.png +0 -0
  558. package/templates/example-remesh/outputs/v1/out/rig/images/eye_r.png +0 -0
  559. package/templates/example-remesh/outputs/v1/out/rig/images/face.png +0 -0
  560. package/templates/example-remesh/outputs/v1/out/rig/images/lantern.png +0 -0
  561. package/templates/example-remesh/outputs/v1/out/rig/images/torso.png +0 -0
  562. package/templates/example-remesh/outputs/v1/out/rig/mesh_report.json +15 -0
  563. package/templates/example-remesh/outputs/v1/out/rig/motion.json +137 -0
  564. package/templates/example-remesh/outputs/v1/out/rig/rig.json +536 -0
  565. package/templates/example-remesh/outputs/v1/out/rig/run.json +52 -0
  566. package/templates/example-remesh/outputs/v2/idle/frames.json +29 -0
  567. package/templates/example-remesh/outputs/v2/idle/idle@1fps/contact.png +0 -0
  568. package/templates/example-remesh/outputs/v2/idle/idle@1fps/f0000.png +0 -0
  569. package/templates/example-remesh/outputs/v2/idle/idle@1fps/f0001.png +0 -0
  570. package/templates/example-remesh/outputs/v2/idle/idle@1fps/f0002.png +0 -0
  571. package/templates/example-remesh/outputs/v2/idle/idle@1fps/f0003.png +0 -0
  572. package/templates/example-remesh/outputs/v2/idle/idle@1fps/f0004.png +0 -0
  573. package/templates/example-remesh/outputs/v2/out/check/build/run.json +44 -0
  574. package/templates/example-remesh/outputs/v2/out/check/build/skeleton.atlas +28 -0
  575. package/templates/example-remesh/outputs/v2/out/check/build/skeleton.json +674 -0
  576. package/templates/example-remesh/outputs/v2/out/check/build/skeleton.model.json +1072 -0
  577. package/templates/example-remesh/outputs/v2/out/check/build/skeleton.png +0 -0
  578. package/templates/example-remesh/outputs/v2/out/painting_in_rig.png +0 -0
  579. package/templates/example-remesh/outputs/v2/out/parts/background.png +0 -0
  580. package/templates/example-remesh/outputs/v2/out/parts/eye_l.png +0 -0
  581. package/templates/example-remesh/outputs/v2/out/parts/eye_r.png +0 -0
  582. package/templates/example-remesh/outputs/v2/out/parts/face.png +0 -0
  583. package/templates/example-remesh/outputs/v2/out/parts/lantern.png +0 -0
  584. package/templates/example-remesh/outputs/v2/out/parts/torso.png +0 -0
  585. package/templates/example-remesh/outputs/v2/out/parts.json +188 -0
  586. package/templates/example-remesh/outputs/v2/out/rig/images/background.png +0 -0
  587. package/templates/example-remesh/outputs/v2/out/rig/images/eye_l.png +0 -0
  588. package/templates/example-remesh/outputs/v2/out/rig/images/eye_r.png +0 -0
  589. package/templates/example-remesh/outputs/v2/out/rig/images/face.png +0 -0
  590. package/templates/example-remesh/outputs/v2/out/rig/images/lantern.png +0 -0
  591. package/templates/example-remesh/outputs/v2/out/rig/images/torso.png +0 -0
  592. package/templates/example-remesh/outputs/v2/out/rig/mesh_report.json +15 -0
  593. package/templates/example-remesh/outputs/v2/out/rig/motion.json +137 -0
  594. package/templates/example-remesh/outputs/v2/out/rig/rig.json +536 -0
  595. package/templates/example-remesh/outputs/v2/out/rig/run.json +52 -0
  596. package/templates/example-remesh/outputs/v3/idle/frames.json +29 -0
  597. package/templates/example-remesh/outputs/v3/idle/idle@1fps/contact.png +0 -0
  598. package/templates/example-remesh/outputs/v3/idle/idle@1fps/f0000.png +0 -0
  599. package/templates/example-remesh/outputs/v3/idle/idle@1fps/f0001.png +0 -0
  600. package/templates/example-remesh/outputs/v3/idle/idle@1fps/f0002.png +0 -0
  601. package/templates/example-remesh/outputs/v3/idle/idle@1fps/f0003.png +0 -0
  602. package/templates/example-remesh/outputs/v3/idle/idle@1fps/f0004.png +0 -0
  603. package/templates/example-remesh/outputs/v3/out/check/build/run.json +44 -0
  604. package/templates/example-remesh/outputs/v3/out/check/build/skeleton.atlas +28 -0
  605. package/templates/example-remesh/outputs/v3/out/check/build/skeleton.json +674 -0
  606. package/templates/example-remesh/outputs/v3/out/check/build/skeleton.model.json +1072 -0
  607. package/templates/example-remesh/outputs/v3/out/check/build/skeleton.png +0 -0
  608. package/templates/example-remesh/outputs/v3/out/painting_in_rig.png +0 -0
  609. package/templates/example-remesh/outputs/v3/out/parts/background.png +0 -0
  610. package/templates/example-remesh/outputs/v3/out/parts/eye_l.png +0 -0
  611. package/templates/example-remesh/outputs/v3/out/parts/eye_r.png +0 -0
  612. package/templates/example-remesh/outputs/v3/out/parts/face.png +0 -0
  613. package/templates/example-remesh/outputs/v3/out/parts/lantern.png +0 -0
  614. package/templates/example-remesh/outputs/v3/out/parts/torso.png +0 -0
  615. package/templates/example-remesh/outputs/v3/out/parts.json +188 -0
  616. package/templates/example-remesh/outputs/v3/out/rig/images/background.png +0 -0
  617. package/templates/example-remesh/outputs/v3/out/rig/images/eye_l.png +0 -0
  618. package/templates/example-remesh/outputs/v3/out/rig/images/eye_r.png +0 -0
  619. package/templates/example-remesh/outputs/v3/out/rig/images/face.png +0 -0
  620. package/templates/example-remesh/outputs/v3/out/rig/images/lantern.png +0 -0
  621. package/templates/example-remesh/outputs/v3/out/rig/images/torso.png +0 -0
  622. package/templates/example-remesh/outputs/v3/out/rig/mesh_report.json +15 -0
  623. package/templates/example-remesh/outputs/v3/out/rig/motion.json +137 -0
  624. package/templates/example-remesh/outputs/v3/out/rig/rig.json +536 -0
  625. package/templates/example-remesh/outputs/v3/out/rig/run.json +52 -0
  626. package/templates/example-remesh/project.json +279 -230
  627. package/templates/example-reopened/project.json +341 -289
  628. package/templates/example-split/captions.json +1 -1
  629. package/templates/project.json +10 -2
@@ -8,7 +8,7 @@ import { partsFileReferences } from '@rig-c/parts/src/parts.ts';
8
8
  import { tmpdir } from 'node:os';
9
9
  import { dirname, isAbsolute, join, posix, relative, resolve, sep, win32 } from 'node:path';
10
10
  import { isDeepStrictEqual } from 'node:util';
11
- import { asArray, checkProject, isObject, type Finding } from './check.ts';
11
+ import { asArray, checkProject, collectItems, isObject, type Finding } from './check.ts';
12
12
  import { literalFile } from './choices.ts';
13
13
  import { configInputReferences } from './config-inputs.ts';
14
14
  import { parseFeedbackAnswers, readProject } from './feedback.ts';
@@ -18,7 +18,9 @@ import { collectReopens, reopenTime } from './reopen.ts';
18
18
  import { prepareRigReviewPackage } from './review-package.ts';
19
19
  import { rigVersionDateFinding } from './rig-version-date.ts';
20
20
  import { checkRegisteredRuns, RUN_RECORD_SINCE, RunRecordError, validateRunRecord, type RunSpec } from './run-record.ts';
21
- import { approvedStructureDelta, structurePathIsIgnored } from './structure.ts';
21
+ import { approvedStructureDelta, latestPartsApproval, structurePathIsIgnored } from './structure.ts';
22
+ import { stageOfStep } from './stages.ts';
23
+ import { HEAD_TURN_SINCE } from './waypoints.ts';
22
24
  import type { Json, JsonObject } from './templates.ts';
23
25
 
24
26
  const sha = (bytes: Buffer): string => createHash('sha256').update(bytes).digest('hex');
@@ -38,6 +40,9 @@ const RESERVED_REGISTRATION_NAMES = new Set([
38
40
  'package-lock.json',
39
41
  'path-adapter.json',
40
42
  'citations.json',
43
+ 'depth-manifest.json',
44
+ 'depth-report.json',
45
+ 'depth-source-parts.json',
41
46
  ]);
42
47
  function isValidAdaptedTarget(target: string): boolean {
43
48
  return literal(target)
@@ -389,13 +394,137 @@ function collectRequirementsAssetRefs(requirements: JsonObject, portableRequirem
389
394
  return refs;
390
395
  }
391
396
 
392
- /** Only explicitly registered versions opt in. Older version contracts are unchanged. */
393
- export function rigRegistrationFindings(dir: string, project: JsonObject, warnings: Finding[] = []): Finding[] {
397
+ /** A declared depth/turn config is the existing registration's depth input branch. */
398
+ function usesDepth(config: JsonObject): boolean {
399
+ const turn = isObject(config.turn) ? config.turn : {};
400
+ const body = isObject(turn.body) ? turn.body : {};
401
+ return isObject(config.depth) || [turn.roles, body.roles].some(roles => isObject(roles) && Object.keys(roles).length > 0);
402
+ }
403
+
404
+ /** Reads only producer declarations and bytes, never producer measurements. */
405
+ function depthBindingFindings(dir: string, version: JsonObject, config: JsonObject, record: JsonObject | undefined, warnings: Finding[]): Finding[] {
406
+ if (!usesDepth(config) && record?.depth === undefined) return [];
407
+ const path = `versions[v${String(version.n)}].registration.depth`;
394
408
  const findings: Finding[] = [];
409
+ const missing = (why: string): void => {
410
+ const finding = { code: 'RIG_DEPTH_BINDING_MISSING', path, message: `${path}: ${why}; retain rig's depth_sheets.json and, for per-part maps, --depth-manifest and parts' depth-report.json when registering a new rig version` };
411
+ (typeof version.at === 'string' && Date.parse(version.at) < Date.parse(HEAD_TURN_SINCE) ? warnings : findings).push(finding);
412
+ };
413
+ const depth = record?.depth;
414
+ if (!isObject(depth)) { missing('no producer depth binding'); return findings; }
415
+ if (!isObject(depth.sheets) || depth.route === 'per-part' && (!isObject(depth.manifest) || !isObject(depth.report))) {
416
+ missing('incomplete producer depth binding'); return findings;
417
+ }
418
+ try {
419
+ if (depth.route !== 'per-part' && depth.route !== 'per-layer') throw Error('expected per-part or per-layer route');
420
+ if (depth.route === 'per-layer' && (depth.manifest !== undefined || depth.report !== undefined)) throw Error('per-part reports require the per-part route');
421
+ const read = (binding: Json | undefined, spec: string, output = false): JsonObject => {
422
+ const inventory = asArray(output ? version.outputs : record?.files).filter(isObject);
423
+ if (!isObject(binding) || !inventory.some(row => row.path === binding.path && row.sha256 === binding.sha256)) throw Error('depth file is absent from the retained inventory');
424
+ const doc: Json = JSON.parse(bytesAt(dir, binding, output).toString('utf8'));
425
+ if (!isObject(doc) || doc.spec !== spec || !Array.isArray(doc.parts)) throw Error(`expected ${spec} with parts[]`);
426
+ return doc;
427
+ };
428
+ const digest = (value: Json | undefined, field: string): string => {
429
+ if (typeof value !== 'string' || !/^[a-f0-9]{64}$/.test(value)) throw Error(`${field}: expected producer SHA-256`);
430
+ return value;
431
+ };
432
+ const namedRows = (value: Json | undefined, label: string): JsonObject[] => {
433
+ if (!Array.isArray(value) || value.length === 0 || value.some(row => !isObject(row) || typeof row.part !== 'string' || !row.part)) throw Error(`${label}: expected nonempty named parts[]`);
434
+ const rows = value as JsonObject[];
435
+ if (new Set(rows.map(row => row.part)).size !== rows.length) throw Error(`${label}: duplicate part`);
436
+ return rows;
437
+ };
438
+ const outputRoot = `outputs/v${String(version.n)}/out`;
439
+ const outputs = asArray(version.outputs).filter(isObject);
440
+ const outputBytes = (path: string): Buffer => {
441
+ const binding = outputs.find(row => row.path === path);
442
+ if (!binding) throw Error(`${path}: absent from retained outputs`);
443
+ return bytesAt(dir, binding, true);
444
+ };
445
+ const parts: Json = JSON.parse(outputBytes(`${outputRoot}/parts.json`).toString('utf8'));
446
+ if (!isObject(parts) || !Array.isArray(parts.parts)) throw Error('retained assembled parts.json has no parts[]');
447
+ const mappedParts = parts.parts.filter(isObject);
448
+ const sourceList = (raw: Json | undefined, label: string): JsonObject[] => {
449
+ if (!Array.isArray(raw) || raw.length === 0 || raw.some(row => !isObject(row))) throw Error(`${label}: expected depth sources[]`);
450
+ const rows = raw as JsonObject[];
451
+ for (const row of rows) {
452
+ digest(row.sha256, `${label}.sha256`);
453
+ if (typeof row.from !== 'string' || !row.from || typeof row.image !== 'string' || !literal(row.image)
454
+ || !Array.isArray(row.crop) || row.crop.length !== 4 || row.crop.some(v => typeof v !== 'number' || !Number.isFinite(v))) throw Error(`${label}: invalid declared depth source`);
455
+ }
456
+ return rows;
457
+ };
458
+ const sheets = namedRows(read(depth.sheets, 'rig-parts-depth-sheets/1', true).parts, 'rig sheets');
459
+ for (const row of sheets) {
460
+ const ref = row.depth;
461
+ if (!isObject(ref) || typeof ref.image !== 'string' || !literal(ref.image) || ref.image.includes('/')
462
+ || !['white', 'black'].includes(String(ref.near)) || typeof ref.zScale !== 'number' || !(ref.zScale > 0) || !Number.isFinite(ref.zScale)
463
+ || !Array.isArray(row.size) || row.size.length !== 2 || row.size.some(v => typeof v !== 'number' || !Number.isSafeInteger(v) || v < 1)) throw Error('invalid consumed sheet metadata');
464
+ const sources = sourceList(ref.sources, 'rig sheet sources');
465
+ // Rig may pad/crop a sheet. Its declared source provenance must still match
466
+ // an assembled part; comparing the padded sheet hash to apply's would be wrong.
467
+ if (!mappedParts.some(part => isObject(part.depth) && part.depth.near === ref.near && part.depth.zScale === ref.zScale
468
+ && isDeepStrictEqual(sourceList(part.depth.sources, 'assembled sheet sources'), sources))) throw Error('rig sheet sources do not bind the retained assembled parts');
469
+ outputBytes(`${outputRoot}/rig/images/${ref.image}`);
470
+ }
471
+ if (depth.route === 'per-part') {
472
+ const manifest = read(depth.manifest, 'rig-parts-depth-inputs/1');
473
+ const report = read(depth.report, 'rig-parts-depth-report/1');
474
+ for (const field of ['partsSha256', 'recipeSha256'] as const) {
475
+ if (digest(report[field], `report.${field}`) !== digest(manifest[field], `manifest.${field}`)) throw Error(`producer ${field} declarations disagree`);
476
+ }
477
+ digest(report.rigConfigSha256, 'report.rigConfigSha256');
478
+ if (digest(report.manifestSha256, 'report.manifestSha256') !== (depth.manifest as JsonObject).sha256) throw Error('producer report does not bind the retained prepare manifest');
479
+ if (depth.source_parts !== undefined) {
480
+ const binding = depth.source_parts;
481
+ if (!isObject(binding) || !asArray(record?.files).filter(isObject).some(f => f.path === binding.path && f.sha256 === binding.sha256)
482
+ || digest(binding.sha256, 'source parts') !== manifest.partsSha256) throw Error('prepare manifest does not bind the retained source parts');
483
+ bytesAt(dir, binding);
484
+ }
485
+ const prepared = namedRows(manifest.parts, 'prepared parts');
486
+ const applied = namedRows(report.parts, 'applied parts');
487
+ if (!isDeepStrictEqual(prepared.map(row => row.part).sort(), applied.map(row => row.part).sort())) throw Error('prepare/apply part sets disagree');
488
+ for (const row of applied) {
489
+ const input = prepared.find(p => p.part === row.part)!;
490
+ const part = mappedParts.find(p => p.name === row.part);
491
+ if (!part || !isObject(part.depth) || typeof part.name !== 'string' || !literal(part.name) || part.name.includes('/')
492
+ || typeof part.depth.image !== 'string' || !literal(part.depth.image) || part.depth.image.includes('/')) throw Error('report part has no retained assembled depth declaration');
493
+ const partDepth = part.depth;
494
+ for (const field of ['sourceSha256', 'inputSha256'] as const) {
495
+ if (digest(row[field], `report.${field}`) !== digest(input[field], `manifest.${field}`)) throw Error(`producer ${field} declarations disagree`);
496
+ }
497
+ if (digest(row.sourceSha256, 'report.sourceSha256') !== sha(outputBytes(`${outputRoot}/parts/${part.name}.png`))) throw Error('applied part art differs from the retained assembled part');
498
+ if (digest(row.sheetSha256, 'report.sheetSha256') !== sha(outputBytes(`${outputRoot}/parts/${partDepth.image}`))) throw Error('applied sheet differs from the retained assembled sheet');
499
+ const map = digest(row.mapSha256, 'report.mapSha256');
500
+ const sources = sourceList(partDepth.sources, 'applied sheet sources');
501
+ if (!sources.some(source => source.sha256 === map && source.from === part.from)) throw Error('applied map hash is absent from the assembled depth sources');
502
+ if (row.near !== partDepth.near || row.zScale !== partDepth.zScale) throw Error('applied depth units disagree with the assembled declaration');
503
+ if (!sheets.some(sheet => isObject(sheet.depth) && isDeepStrictEqual(sheet.depth.sources, sources)
504
+ && sheet.depth.near === partDepth.near && sheet.depth.zScale === partDepth.zScale)) throw Error('rig consumed no sheet from the reported applied part');
505
+ }
506
+ }
507
+ } catch (error) {
508
+ findings.push({ code: 'RIG_DEPTH_BINDING_INVALID', path, message: `${path}: ${String(error)}; restore the exact producer files or register a new rig version` });
509
+ }
510
+ return findings;
511
+ }
512
+
513
+ /** Only explicitly registered versions opt in. Older version contracts are unchanged. */
514
+ export function rigRegistrationFindings(dir: string, project: JsonObject, warnings: Finding[] = [], collection: JsonObject | null = null): Finding[] {
515
+ const findings: Finding[] = depthPlanFindings(project, warnings, collection);
395
516
  const allVersions = asArray(project.versions).filter(isObject);
396
517
  const registeredNumbers = new Set(allVersions.map(v => v.n).filter((n): n is number => typeof n === 'number' && Number.isSafeInteger(n)));
397
518
  for (const [index, version] of allVersions.entries()) {
398
- if (version.registration === undefined) continue;
519
+ if (version.registration === undefined) {
520
+ if (version.kind === 'rig' && version.pre_interview !== true && isObject(version.provenance)) {
521
+ try {
522
+ const config: Json = JSON.parse(bytesAt(dir, version.provenance.config).toString('utf8'));
523
+ if (isObject(config)) findings.push(...depthBindingFindings(dir, version, config, undefined, warnings));
524
+ } catch { /* Existing provenance checks own unreadable config evidence. */ }
525
+ }
526
+ continue;
527
+ }
399
528
  const path = `versions[v${String(version.n)}]`;
400
529
  const add = (code: string, field: string, why: string): void => { findings.push({ code, path: `${path}.${field}`, message: `${path}.${field}: ${why}; restore the retained registration inputs or register a new rig version` }); };
401
530
  const record = version.registration;
@@ -457,6 +586,7 @@ export function rigRegistrationFindings(dir: string, project: JsonObject, warnin
457
586
  const configSourceRaw = JSON.parse(bytesAt(dir, record.config_source).toString()) as Json;
458
587
  const portable = JSON.parse(bytesAt(dir, config).toString()) as Json;
459
588
  if (!isObject(configSourceRaw) || !isObject(portable)) throw Error('config-source and portable config must be JSON objects');
589
+ findings.push(...depthBindingFindings(dir, version, configSourceRaw, record, warnings));
460
590
  const checkPortable = (value: Json, document: string, requirementsDocument = false, location: string[] = []): void => {
461
591
  if (typeof value === 'string' && absolute(value)) {
462
592
  const field = `${document}#/${location.map(escapePointerToken).join('/')}`;
@@ -635,7 +765,7 @@ export function rigRegistrationFindings(dir: string, project: JsonObject, warnin
635
765
 
636
766
  export const RIG_VERSION_HELP = `rig-version <n> [<dir>] --parts <dir> --rig <dir> --build <dir> --idle <render dir>
637
767
  --config <file> --path-adapter <file> --compile-report <file> --toolchain-lock <package-lock.json>
638
- --at-source <dated JSON file> --at-pointer </pointer> --by <registrant> [--run-record <run.json>]... [--citations <sections JSON>] [--json]
768
+ --at-source <dated JSON file> --at-pointer </pointer> --by <registrant> [--run-record <run.json>]... [--citations <sections JSON>] [--depth-manifest <prepare manifest>] [--json]
639
769
  Copy and hash frozen producer outputs. Retain an explicitly declared npm lock, producer run records and UTC not-after date.
640
770
  Idle requires rigc render's frames.json. No build, acceptance or stage advance runs.
641
771
  Repeat --answers <version>:<verdict> to answer earlier human bounced feedback.
@@ -648,7 +778,7 @@ export function rigVersionCommand(args: string[], now: number): { stdout: string
648
778
  const options: Record<string, string> = {};
649
779
  const runRecords: string[] = [];
650
780
  const answerValues: string[] = [];
651
- const flags = ['--parts', '--rig', '--build', '--idle', '--config', '--path-adapter', '--compile-report', '--toolchain-lock', '--at-source', '--at-pointer', '--by', '--citations'];
781
+ const flags = ['--parts', '--rig', '--build', '--idle', '--config', '--path-adapter', '--compile-report', '--toolchain-lock', '--at-source', '--at-pointer', '--by', '--citations', '--depth-manifest'];
652
782
  let json = false;
653
783
  for (let i = 0; i < args.length; i++) {
654
784
  const arg = args[i]!;
@@ -669,7 +799,7 @@ export function rigVersionCommand(args: string[], now: number): { stdout: string
669
799
  else positional.push(arg);
670
800
  }
671
801
  const n = Number(positional[0]?.replace(/^v/, ''));
672
- if (!Number.isSafeInteger(n) || n < 1 || positional.length > 2 || flags.filter(f => f !== '--citations').some(f => !options[f])) refuse('RIG_REGISTRATION_USAGE', RIG_VERSION_HELP, USAGE_EXIT);
802
+ if (!Number.isSafeInteger(n) || n < 1 || positional.length > 2 || flags.filter(f => f !== '--citations' && f !== '--depth-manifest').some(f => !options[f])) refuse('RIG_REGISTRATION_USAGE', RIG_VERSION_HELP, USAGE_EXIT);
673
803
  const dir = realpathSync(resolve(positional[1] ?? process.cwd()));
674
804
  let { file, project } = readProject(dir);
675
805
  let original = readFileSync(file);
@@ -973,6 +1103,27 @@ export function rigVersionCommand(args: string[], now: number): { stdout: string
973
1103
  const partsDir = resolve(dir, options['--parts']!);
974
1104
  copyTree(join(partsDir, 'parts.json'), `${out}/out/parts.json`, true);
975
1105
  copyTree(join(partsDir, 'parts'), `${out}/out/parts`, true);
1106
+ // Keep the producer's complete depth reports in this same frozen registration.
1107
+ // The config.depth image references above still use the ordinary path adapter.
1108
+ let depthBinding: JsonObject | undefined;
1109
+ const depthReport = join(partsDir, 'depth-report.json');
1110
+ if (usesDepth(config) || options['--depth-manifest'] || existsSync(depthReport)) {
1111
+ const perPart = options['--depth-manifest'] !== undefined || existsSync(depthReport) || !isObject(config.depth);
1112
+ const sheets = join(dir, out, 'out/rig/depth_sheets.json');
1113
+ // Rig files are copied below; bind the exact frozen source now.
1114
+ const sourceSheets = resolve(dir, options['--rig']!, 'depth_sheets.json');
1115
+ depthBinding = { route: perPart ? 'per-part' : 'per-layer' };
1116
+ const approval = latestPartsApproval(project, Date.parse(String(at)));
1117
+ const draft = asArray(project.drafts).filter(isObject).find(d => d.id === approval?.draft_id);
1118
+ if (perPart && approval && isObject(draft?.parts) && typeof draft.parts.path === 'string') {
1119
+ const originalParts = resolve(dir, draft.parts.path, 'parts.json');
1120
+ if (!existsSync(originalParts)) fail('RIG_DEPTH_BINDING_MISSING', `versions[v${n}].registration.depth.source_parts`, 'restore the accepted assembled parts manifest before registering the depth-enriched version');
1121
+ depthBinding.source_parts = retain(`${evidence}/depth-source-parts.json`, sourceBytes(originalParts));
1122
+ }
1123
+ if (existsSync(sourceSheets)) depthBinding.sheets = { path: relative(dir, sheets).split(sep).join('/'), sha256: sha(sourceBytes(sourceSheets)) };
1124
+ if (options['--depth-manifest']) depthBinding.manifest = input('--depth-manifest', 'depth-manifest.json');
1125
+ if (existsSync(depthReport)) depthBinding.report = retain(`${evidence}/depth-report.json`, sourceBytes(depthReport));
1126
+ }
976
1127
  const partReferences = partsFileReferences(partsDir);
977
1128
  for (const reference of partReferences) {
978
1129
  const target = `${out}/out/${reference.path}`;
@@ -1005,6 +1156,7 @@ export function rigVersionCommand(args: string[], now: number): { stdout: string
1005
1156
  changed: 'Registered frozen producer outputs', provenance: { config: configBinding, sections, ...(structureChanges.length ? { structure_delta: structureChanges } : {}) },
1006
1157
  registration: { kind: 'frozen-rig/1', at: registrationAt, toolchain: { kind: 'npm-lock-v3', source: toolchain },
1007
1158
  ...(runs.length ? { runs } : {}),
1159
+ ...(depthBinding ? { depth: depthBinding } : {}),
1008
1160
  ...(skipped.length ? { skipped } : {}),
1009
1161
  files: retained, config_source: configSource,
1010
1162
  ...(requirementsSourceBinding ? { requirements_source: requirementsSourceBinding } : {}),
@@ -1012,6 +1164,8 @@ export function rigVersionCommand(args: string[], now: number): { stdout: string
1012
1164
  path_adapter: { ...adapterBinding, ...(pointerAdapted ? { format: 'json-pointer/1' } : {}) }, idle, compile,
1013
1165
  copied: { files: outputFiles.length, bytes: outputFiles.reduce((total, f) => total + Number(f.bytes), 0) } } };
1014
1166
  const candidate = { ...project, versions: [...project.versions, version] };
1167
+ const depthProblem = depthBindingFindings(dir, { ...version, at: new Date(now).toISOString() }, config, version.registration as JsonObject, [])[0];
1168
+ if (depthProblem) refuse(depthProblem.code, depthProblem.message);
1015
1169
  const problem = rigRegistrationFindings(dir, candidate)[0];
1016
1170
  if (problem) refuse(problem.code, problem.message);
1017
1171
  created.push(join(dir, pkg));
@@ -1045,3 +1199,60 @@ export function rigVersionCommand(args: string[], now: number): { stdout: string
1045
1199
  releasePublication();
1046
1200
  }
1047
1201
  }
1202
+
1203
+ /** The optional plan step consumes approved parts before the ordinary rig step. */
1204
+ export function depthPlanMoves(project: JsonObject, collection: JsonObject | null = null): { role: 'agent'; field: string; awaits: string; command: null; act: string }[] {
1205
+ const { answer, mode } = depthAnswer(project, collection);
1206
+ if (mode !== 'depth') return [];
1207
+ const answerAt = typeof answer.at === 'string' ? Date.parse(answer.at) : -Infinity;
1208
+ const rig = asArray(project.versions).filter(isObject).find(v => v.kind === 'rig' && typeof v.at === 'string' && Date.parse(v.at) >= answerAt && isObject(v.registration) && isObject(v.registration.depth));
1209
+ if (rig) return [];
1210
+ const steps = ["Record the chosen depth route and reason in the turn plan step text. Default per-part sequence: rig-parts depth-prepare --parts <accepted assembled parts> --config <depth recipe> --out <inference directory>",
1211
+ "Run the supplied depth model on each prepared image; retain raw rig-parts-map/1 maps (face normals, scalar depth for other parts).",
1212
+ "rig-parts depth-apply --parts <accepted assembled parts> --manifest <inference/manifest.json> --config <depth recipe> --rig-config <config.json> --out <mapped directory>; then rig-parts rig --parts <mapped directory> --config <mapped/config.json> --out <rig directory>. Register with rig-version --parts <mapped directory> --rig <rig directory> --config <mapped/config.json> --depth-manifest <inference/manifest.json>."];
1213
+ return steps.map((act, i) => ({ role: 'agent', field: `plan.steps[turn].moves[${i}]`, awaits: 'versions[].registration.depth', command: null, act }));
1214
+ }
1215
+
1216
+ function depthAnswer(project: JsonObject, collection: JsonObject | null = null): { answer: JsonObject; mode: Json | undefined } {
1217
+ const item = collectItems(project, { collection }).find(item => item.id === 'turn');
1218
+ const answer = item?.state.state === 'user' || item?.state.state === 'delegated' ? item.state.answer : {};
1219
+ const decision = answer.delegated === true && isObject(answer.agent_decision) ? answer.agent_decision.value : answer.value;
1220
+ return { answer, mode: isObject(decision) ? decision.mode : undefined };
1221
+ }
1222
+
1223
+ /** The optional depth step is drafted before its rigging-interview approval, just like the other rig steps. */
1224
+ export function depthPlanFindings(project: JsonObject, warnings: Finding[], collection: JsonObject | null = null): Finding[] {
1225
+ const { answer, mode } = depthAnswer(project, collection);
1226
+ if (mode !== 'depth') return [];
1227
+ const answerAt = typeof answer.at === 'string' ? Date.parse(answer.at) : NaN;
1228
+ const approved = asArray(project.signoffs).filter(isObject).some(s => s.stage === 'rigging-interview' && (s.checkpoint ?? null) === null && Date.parse(String(s.at)) >= answerAt);
1229
+ if (!approved && !['rigging', 'rig-review', 'post-interview', 'post', 'direction-review', 'accepted'].includes(String(project.stage))) return [];
1230
+ const plan = isObject(project.plan) ? project.plan : {};
1231
+ const steps = asArray(plan.steps).filter(isObject);
1232
+ const depth = steps.find(s => s.id === 'turn' && s.phase === 'rig' && asArray(s.rests_on).includes('turn'));
1233
+ if (depth && steps.filter(s => s !== depth && s.phase === 'rig' && stageOfStep('rig', String(s.id)) === 'rigging').every(s => Number(depth.order) < Number(s.order))) return [];
1234
+ const path = 'plan.steps[turn]';
1235
+ const finding = { code: 'RIG_DEPTH_PLAN_MISSING', path, message: `${path}: a depth turn needs a rig-phase depth step resting on turn, ordered before the rig steps; draft it with plan add turn and approve it at rigging-interview before running rig` };
1236
+ if (answerAt < Date.parse(HEAD_TURN_SINCE)) { warnings.push(finding); return []; }
1237
+ return [finding];
1238
+ }
1239
+
1240
+ /** Depth-apply may enrich only depth declarations; accepted art/geometry/measurements stay identical. */
1241
+ export function registeredDepthPartsMatch(dir: string, version: JsonObject, acceptedSha256: string, packagedSha256: string): boolean {
1242
+ try {
1243
+ const record = version.registration;
1244
+ if (!isObject(record) || !isObject(record.depth) || record.depth.route !== 'per-part' || !isObject(record.depth.source_parts)
1245
+ || record.depth.source_parts.sha256 !== acceptedSha256) return false;
1246
+ const binding = asArray(version.outputs).filter(isObject).find(f => f.path === `outputs/v${String(version.n)}/out/parts.json` && f.sha256 === packagedSha256);
1247
+ if (!binding) return false;
1248
+ const config: Json = JSON.parse(bytesAt(dir, record.config_source).toString('utf8'));
1249
+ if (!isObject(config) || depthBindingFindings(dir, version, config, record, []).length > 0) return false;
1250
+ const withoutDepth = (bytes: Buffer): JsonObject => {
1251
+ const doc: Json = JSON.parse(bytes.toString('utf8'));
1252
+ if (!isObject(doc) || !Array.isArray(doc.parts) || doc.parts.some(p => !isObject(p))) throw Error('invalid parts manifest');
1253
+ for (const part of doc.parts as JsonObject[]) delete part.depth;
1254
+ return doc;
1255
+ };
1256
+ return isDeepStrictEqual(withoutDepth(bytesAt(dir, record.depth.source_parts)), withoutDepth(bytesAt(dir, binding, true)));
1257
+ } catch { return false; }
1258
+ }
@@ -10,13 +10,15 @@ import { SCENE_CHOICE_MISMATCH, resolveAgentCitationSpec } from './scene-authori
10
10
  import { SCENE_SPEC, SceneError, checkScenes, plateRegistration, pngDimensions, sceneBytes, sceneEntries, sceneFail, scenePath, sceneRig, validateScene } from './scene.ts';
11
11
  import type { JsonObject } from './templates.ts';
12
12
 
13
- export const SCENE_HELP = `scene write --rig <R> --background <path> [--foreground <path>]
13
+ export const SCENE_HELP = `scene write --rig <R> --background <path> [--foreground <path>] [--animation <name>]
14
14
  [--background-rect x,y,w,h] [--foreground-rect x,y,w,h]
15
15
  --citations-file <retained project-relative JSON> [<dir>]
16
16
  Retain citations inside the project, for example evidence/scene-src/citations.json; absolute paths are refused.
17
17
  Citations are a role map {background: citation, foreground?: citation}.
18
18
  Each citation names post_composition, asks:["post_composition"], and quote or delegated:true.
19
19
  Paths and rects must match the current ingested post_composition choice.
20
+ Animation defaults to idle and must name a clip in the accepted bound model.
21
+ Only idle binds registration.idle frames; other clips omit optional frames.
20
22
  Records by:agent; typed --by is refused. Earlier human scenes remain readable.
21
23
  Appends evidence/scene/s<N>.json and scenes[]; stage stays unchanged.`;
22
24
  export interface SceneWriteHooks { beforeCommit?: () => void; }
@@ -31,7 +33,7 @@ function writeScene(args: string[], now: number, hooks: SceneWriteHooks): { stdo
31
33
  if (args[0] !== 'write') usage();
32
34
  for (let index = 1; index < args.length; index++) {
33
35
  const arg = args[index]!;
34
- if (['--rig', '--background', '--foreground', '--background-rect', '--foreground-rect', '--citations-file', '--by'].includes(arg)) {
36
+ if (['--rig', '--background', '--foreground', '--background-rect', '--foreground-rect', '--citations-file', '--animation', '--by'].includes(arg)) {
35
37
  const value = args[++index];
36
38
  if (!value || value.startsWith('--') || opts[arg] !== undefined) usage();
37
39
  opts[arg] = value;
@@ -62,7 +64,7 @@ function writeScene(args: string[], now: number, hooks: SceneWriteHooks): { stdo
62
64
  try {
63
65
  const entries = sceneEntries(project);
64
66
  const n = entries.length + 1;
65
- const binding = sceneRig(dir, project, Number(opts['--rig']), snapshots);
67
+ const binding = sceneRig(dir, project, Number(opts['--rig']), snapshots, opts['--animation']);
66
68
  const citationsBytes = sceneBytes(dir, opts['--citations-file']!, 'SCENE_CITATION_MISSING', snapshots);
67
69
  let citations: JsonObject;
68
70
  try { citations = JSON.parse(citationsBytes.toString('utf8')) as JsonObject; }
package/src/scene.ts CHANGED
@@ -175,7 +175,17 @@ function modelForRig(dir: string, version: JsonObject, snapshots?: Map<string, B
175
175
  const binding = { path, sha256: row.sha256 };
176
176
  return { binding, model: json(boundBytes(dir, binding, 'SCENE_MODEL_MISMATCH', snapshots), path) };
177
177
  }
178
- export function sceneRig(dir: string, project: JsonObject, n: number, snapshots?: Map<string, Buffer>): { rig: JsonObject; stage: JsonObject } {
178
+ /** New non-idle scenes omit frames. Retain the old reader's exact idle binding as legacy metadata. */
179
+ function validateSceneAnimation(model: JsonObject, animation: JsonObject, registration: JsonObject): void {
180
+ if (!objects(model.animations).some(value => value.name === animation.name)) sceneFail('SCENE_ANIMATION_MISSING', 'scene.rig.animation.name', 'choose an animation named by the bound model', 'pass --animation with a name from the accepted model and run scene write');
181
+ if (registration.idle !== undefined && !sceneBinding(registration.idle)) sceneFail('SCENE_MALFORMED', 'scene.rig.animation.frames', 'registration.idle must be a frames binding');
182
+ if (animation.name === 'idle') {
183
+ if (!equal(animation.frames, registration.idle)) sceneFail('SCENE_MALFORMED', 'scene.rig.animation.frames', 'idle frames must be present exactly when registration.idle exists and equal that binding');
184
+ } else if (animation.frames !== undefined && !equal(animation.frames, registration.idle)) {
185
+ sceneFail('SCENE_ANIMATION_FRAMES_UNBOUND', 'scene.rig.animation.frames', 'frames differ from the only legacy binding, registration.idle', 'omit frames for a non-idle animation and record a new scene with scene write --animation <name>');
186
+ }
187
+ }
188
+ export function sceneRig(dir: string, project: JsonObject, n: number, snapshots?: Map<string, Buffer>, animation = 'idle'): { rig: JsonObject; stage: JsonObject } {
179
189
  const { version } = rigVersion(project, n);
180
190
  const reopens = collectReopens(project, []);
181
191
  const signature = collectSignoffs(project, []).filter(value => value.stage === 'rig-review' && value.checkpoint === null && liveSignoff(reopens, value.stage, value.at)
@@ -185,7 +195,8 @@ export function sceneRig(dir: string, project: JsonObject, n: number, snapshots?
185
195
  const { binding, model } = modelForRig(dir, version, snapshots);
186
196
  const registration = isObject(version.registration) ? version.registration : {};
187
197
  const rig: JsonObject = { version: n, acceptance: { signoff: { stage: 'rig-review', checkpoint: null, at: signature.record.at! }, verdict: target.verdict!, review_package: target.review_package! },
188
- model: binding, animation: { name: 'idle', ...(registration.idle === undefined ? {} : { frames: registration.idle }) } };
198
+ model: binding, animation: { name: animation, ...(animation !== 'idle' || registration.idle === undefined ? {} : { frames: registration.idle }) } };
199
+ validateSceneAnimation(model, rig.animation as JsonObject, registration);
189
200
  validateSceneCurrent(project, rig, true);
190
201
  if (model.stage === null || model.stage === undefined) sceneFail('SCENE_STAGE_MISSING', String(binding.path), 'compile a model with a stage box');
191
202
  return { rig, stage: model.stage as JsonObject };
@@ -218,9 +229,8 @@ export function validateScene(dir: string, project: JsonObject, doc: JsonObject,
218
229
  const { binding, model } = modelForRig(dir, version, snapshots);
219
230
  if (!equal(rig.model, binding)) sceneFail('SCENE_MODEL_MISMATCH', 'scene.rig.model', 'use the accepted package model path and hash');
220
231
  const animation = rig.animation as JsonObject;
221
- if (!objects(model.animations).some(value => value.name === animation.name)) sceneFail('SCENE_ANIMATION_MISSING', 'scene.rig.animation.name', 'choose an animation named by the model');
222
232
  const registration = isObject(version.registration) ? version.registration : {};
223
- if (registration.idle !== undefined && !sceneBinding(registration.idle) || !equal(animation.frames, registration.idle)) sceneFail('SCENE_MALFORMED', 'scene.rig.animation.frames', 'frames must be present exactly when registration.idle exists and equal that binding');
233
+ validateSceneAnimation(model, animation, registration);
224
234
  if (isObject(animation.frames)) boundBytes(dir, animation.frames, 'SCENE_FILE_CHANGED', snapshots);
225
235
  if (model.stage === null || model.stage === undefined) sceneFail('SCENE_STAGE_MISSING', String(binding.path), 'compile a model with a stage box');
226
236
  if (!boxShape(model.stage) || !Object.values(model.stage).every(finite) || Number(model.stage.width) <= 0 || Number(model.stage.height) <= 0) sceneFail('SCENE_MALFORMED', `${String(binding.path)}.stage`, 'the model stage must be a finite positive box');
package/src/signable.ts CHANGED
@@ -8,6 +8,7 @@ import { JOB_PLAN_BOUND_SIGNOFF_STAGES, type JobSelector, type JobSubject } from
8
8
  import { asArray, collectSignoffs, isObject, type CheckReport } from './check.ts';
9
9
  import { refuse } from './refusal.ts';
10
10
  import { collectReopens, liveSignoff } from './reopen.ts';
11
+ import { acceptedReviewVerdict } from './review.ts';
11
12
  import { SIGNOFF_TARGET_KINDS } from './review-act.ts';
12
13
  import { STAGES, stageOfStep } from './stages.ts';
13
14
  import type { JsonObject } from './templates.ts';
@@ -27,7 +28,7 @@ export function assertInterviewRecordSignable(project: JsonObject, report: Check
27
28
  }
28
29
 
29
30
  /** Why `signoff <stage> --checkpoint <id>` refuses the step, or null when it can sign it. */
30
- export function checkpointProblem(project: JsonObject, stage: string, id: string): string | null {
31
+ export function checkpointProblem(project: JsonObject, stage: string, id: string, now = Infinity): string | null {
31
32
  const spec = STAGES.find(spec => spec.id === stage);
32
33
  const matches = asArray(isObject(project.plan) ? project.plan.steps : undefined)
33
34
  .filter((step): step is JsonObject => isObject(step) && step.id === id);
@@ -35,7 +36,28 @@ export function checkpointProblem(project: JsonObject, stage: string, id: string
35
36
  if (matches.length !== 1 || spec?.phase === undefined || step.phase !== spec.phase || stageOfStep(spec.phase, id) !== stage) {
36
37
  return `${id}: no unique step runs in stage ${stage}`;
37
38
  }
38
- return checkpointRequired(project, step) ? null : `${id}: checkpoint must be enabled before it can be signed`;
39
+ return checkpointRequired(project, step, now) ? null : `${id}: checkpoint must be enabled before it can be signed`;
40
+ }
41
+
42
+ /** An enabled, unwithdrawn checkpoint in `stage` that has no live checkpoint signature yet. */
43
+ export function checkpointSignable(project: JsonObject, stage: string | null, id: string, now = Infinity): boolean {
44
+ if (stage === null || checkpointProblem(project, stage, id, now) !== null) return false;
45
+ const reopens = collectReopens(project, []);
46
+ return !collectSignoffs(project, []).some(signature => signature.stage === stage && signature.checkpoint === id
47
+ && liveSignoff(reopens, signature.stage, signature.at));
48
+ }
49
+
50
+ /** Whether the displayed version still needs a live accepted review verdict for `stage`. */
51
+ export function reviewVerdictSignable(project: JsonObject, n: number, stage: 'rig-review' | 'direction-review'): boolean {
52
+ const version = asArray(project.versions).filter(isObject).find(v => v.n === n);
53
+ if (!version) return true;
54
+ const index = acceptedReviewVerdict(version, stage);
55
+ const verdict = index >= 0 ? asArray(version.verdicts)[index] : undefined;
56
+ if (!isObject(verdict)) return true;
57
+ const reopens = collectReopens(project, []);
58
+ const versionAt = Date.parse(String(version.at));
59
+ return (Number.isFinite(versionAt) && !liveSignoff(reopens, stage === 'direction-review' ? 'post' : 'rig-review', versionAt))
60
+ || !liveSignoff(reopens, stage, Date.parse(String(verdict.at)));
39
61
  }
40
62
 
41
63
  /** A stage closed by a sign-off that has no live stage-level signature yet. */
@@ -56,7 +78,7 @@ export function stageSignable(project: JsonObject, stage: string | null): boolea
56
78
  export function packageSignSubjects(project: JsonObject, stage: string | null, selector: JobSelector, planSteps: number): JobSubject[] {
57
79
  if (stage === null) return [];
58
80
  const subjects: JobSubject[] = asArray(isObject(project.plan) ? project.plan.steps : undefined)
59
- .filter((step): step is JsonObject => isObject(step) && typeof step.id === 'string' && checkpointProblem(project, stage, step.id) === null)
81
+ .filter((step): step is JsonObject => isObject(step) && typeof step.id === 'string' && checkpointSignable(project, stage, step.id))
60
82
  .map(step => ({ kind: 'checkpoint', checkpointId: String(step.id) }));
61
83
  const target = SIGNOFF_TARGET_KINDS[stage];
62
84
  if (stageSignable(project, stage) && (target === undefined || selector.kind === target)
@@ -2,13 +2,11 @@
2
2
  import { randomUUID } from 'node:crypto';
3
3
  import { readFileSync, renameSync, writeFileSync } from 'node:fs';
4
4
  import { dirname, join } from 'node:path';
5
- import { fileURLToPath } from 'node:url';
6
5
  import { isDeepStrictEqual } from 'node:util';
7
6
  import { asArray, isObject } from './check.ts';
8
7
  import { jobHash } from './job-outbox.ts';
9
- import { jobRuntimeExecArgv } from './job-writer.ts';
10
8
  import { refuse } from './refusal.ts';
11
- import { assertActSubjectDeclared, checkpointActSignoff, decodeReviewAct, reviewActFindings, reviewActTransport, type CheckpointAct, type ReviewActTransport } from './review-act.ts';
9
+ import { assertActSubjectDeclared, checkpointActSignoff, decodeReviewAct, fetchReviewActBytes, reviewActFindings, reviewActTransport, type CheckpointAct, type ReviewActTransport } from './review-act.ts';
12
10
  import { stepHash } from './step-hash.ts';
13
11
  import { readCheckpointEvidence } from './checkpoint-evidence.ts';
14
12
  import type { JsonObject } from './templates.ts';
@@ -29,24 +27,12 @@ export interface CheckpointIngest {
29
27
  replay?: JsonObject;
30
28
  }
31
29
 
32
- function fetchBytes(transport: ReviewActTransport, hooks: SignoffHooks): string {
33
- if (hooks.fetch) return hooks.fetch(transport).bytes;
34
- const child = Bun.spawnSync([process.execPath, ...jobRuntimeExecArgv(), fileURLToPath(new URL('./review-act-runtime.ts', import.meta.url))], {
35
- stdin: Buffer.from(JSON.stringify(transport)), stdout: 'pipe', stderr: 'pipe',
36
- });
37
- let response: { ok: boolean; bytes: string; code: string; message: string };
38
- try { response = JSON.parse(child.stdout.toString()); }
39
- catch { return refuse('REVIEW_ACT_FETCH_REFUSED', 'project.json.review_acts: fetch adapter failed; restore the live Review job'); }
40
- if (!response.ok || child.exitCode) refuse(response.code, response.message);
41
- return response.bytes;
42
- }
43
-
44
30
  /** Fetches, decodes and binds the act to the `--checkpoint` step the command already accepted. */
45
31
  export function ingestCheckpointAct(dir: string, project: JsonObject, actId: string, checkpointId: string, now: number, hooks: SignoffHooks): CheckpointIngest {
46
32
  const invalid = reviewActFindings(project)[0];
47
33
  if (invalid) refuse(invalid.code, invalid.message);
48
34
  const transport: ReviewActTransport = { ...reviewActTransport(dir, actId), kind: 'checkpoint' };
49
- const bytes = fetchBytes(transport, hooks);
35
+ const bytes = hooks.fetch ? hooks.fetch(transport).bytes : fetchReviewActBytes(transport);
50
36
  const act = decodeReviewAct(bytes, 'checkpoint');
51
37
  if (act.jobId !== transport.jobId || act.actId !== transport.actId || Date.parse(act.at) > now) {
52
38
  refuse('REVIEW_ACT_INVALID', `signoffs.checkpoint ${checkpointId}: fetched act identity or date differs from the request; fetch the checkpoint act again`);
package/src/signoff.ts CHANGED
@@ -6,13 +6,12 @@ import { assertDirectionApproval } from './direction.ts';
6
6
  import { assertCorrectionApproval } from './correction-writers.ts';
7
7
  import { createHash } from 'node:crypto';
8
8
  import { readFileSync, realpathSync, writeFileSync } from 'node:fs';
9
- import { acquireBoundJobWrite, jobRuntimeExecArgv } from './job-writer.ts';
9
+ import { acquireBoundJobWrite } from './job-writer.ts';
10
10
  import { assertInterviewRecordSignable, checkpointProblem } from './signable.ts';
11
11
  import { checkpointReceipt, commitIngestedSignoff, ingestCheckpointAct, type CheckpointIngest, type SignoffHooks } from './signoff-checkpoint-act.ts';
12
12
  import { isAbsolute, relative, resolve, sep } from 'node:path';
13
- import { fileURLToPath } from 'node:url';
14
13
  import { jobHash } from './job-outbox.ts';
15
- import { assertActSubjectDeclared, decodeReviewAct, isRecordDirectionSignoff, isRecordInterviewSignoff, recordSignoffActVersion, PLAN_BOUND_SIGNOFF_STAGES, reviewActFindings, reviewActSignoff, reviewActTransport, SIGNOFF_TARGET_KINDS, signoffActIdentity, signoffActVersion, type ReviewActTransport, type SignoffAct } from './review-act.ts';
14
+ import { assertActSubjectDeclared, decodeReviewAct, fetchReviewActBytes, isRecordDirectionSignoff, isRecordInterviewSignoff, recordSignoffActVersion, PLAN_BOUND_SIGNOFF_STAGES, reviewActFindings, reviewActSignoff, reviewActTransport, SIGNOFF_TARGET_KINDS, signoffActIdentity, signoffActVersion, type ReviewActTransport, type SignoffAct } from './review-act.ts';
16
15
 
17
16
  import { asArray, checkProject, classify, collectItems, collectSignoffs, isObject, loadCollection, postNotPassed, type Finding } from './check.ts';
18
17
  import { checkDiffMap } from './diff-map.ts';
@@ -52,18 +51,7 @@ function fetchSignoffAct(dir: string, stage: string, actId: string, now: number,
52
51
  const invalid = reviewActFindings(readProject(dir).project)[0];
53
52
  if (invalid) refuse(invalid.code, invalid.message);
54
53
  const transport: ReviewActTransport = { ...reviewActTransport(dir, actId), kind: 'signoff' };
55
- let bytes: string;
56
- if (hooks.fetch) bytes = hooks.fetch(transport).bytes;
57
- else {
58
- const child = Bun.spawnSync([process.execPath, ...jobRuntimeExecArgv(), fileURLToPath(new URL('./review-act-runtime.ts', import.meta.url))], {
59
- stdin: Buffer.from(JSON.stringify(transport)), stdout: 'pipe', stderr: 'pipe',
60
- });
61
- let response: { ok: boolean; bytes: string; code: string; message: string };
62
- try { response = JSON.parse(child.stdout.toString()); }
63
- catch { return refuse('REVIEW_ACT_FETCH_REFUSED', 'project.json.review_acts: fetch adapter failed; restore the live Review job'); }
64
- if (!response.ok || child.exitCode) refuse(response.code, response.message);
65
- bytes = response.bytes;
66
- }
54
+ const bytes = hooks.fetch ? hooks.fetch(transport).bytes : fetchReviewActBytes(transport);
67
55
  const act = decodeReviewAct(bytes, 'signoff');
68
56
  if (act.jobId !== transport.jobId || act.actId !== transport.actId || Date.parse(act.at) > now) {
69
57
  refuse('REVIEW_ACT_INVALID', 'project.json.review_acts: fetched signoff identity or date differs from the request; fetch the correct signoff act');
package/src/waypoints.ts CHANGED
@@ -17,7 +17,6 @@ export type Placement =
17
17
  | { readonly kind: 'none'; readonly why: string };
18
18
 
19
19
  const wp = (waypoint: string): Placement => ({ kind: 'waypoint', waypoint });
20
- const post = (item: string): Placement => ({ kind: 'post', item });
21
20
  const none = (why: string): Placement => ({ kind: 'none', why });
22
21
 
23
22
  export const SECTION_PLACEMENT: Readonly<Record<string, Placement>> = {
@@ -33,8 +32,8 @@ export const SECTION_PLACEMENT: Readonly<Record<string, Placement>> = {
33
32
  stops: wp('constraints'),
34
33
  cloth: wp('constraints'),
35
34
  motion: wp('motion'),
36
- turn: post('camera_depth'),
37
- depth: post('camera_depth'),
35
+ turn: wp('turn'),
36
+ depth: wp('turn'),
38
37
  key: none('a name'),
39
38
  generation: none('a record of a run'),
40
39
  proposed_rig_scale: none('a value the tool proposes'),
@@ -49,17 +48,16 @@ export const SECTION_PLACEMENT: Readonly<Record<string, Placement>> = {
49
48
  };
50
49
 
51
50
  /** Pipeline order of the rig waypoints; a waypoint not listed here sorts last, by name. */
52
- export const WAYPOINT_ORDER: readonly string[] = ['seethrough', 'assemble', 'bones', 'meshes', 'constraints', 'motion'];
51
+ export const WAYPOINT_ORDER: readonly string[] = ['seethrough', 'assemble', 'bones', 'meshes', 'constraints', 'turn', 'motion'];
53
52
 
54
53
  /** The framing questions asked before the waypoints (INTERVIEW.md F1, F2). */
55
54
  export const FRAMING_IDS: readonly string[] = ['rig_type', 'reference'];
56
55
 
57
56
  /**
58
57
  * Post items with no config section of their own (INTERVIEW.md § Post-production).
59
- * `camera_depth` is not listed: it is derived from the `turn` and `depth`
60
- * sections through the table above.
58
+ * Camera framing remains post; rig depth and turn are asked before rigging.
61
59
  */
62
- export const SECTIONLESS_POST_ITEMS: readonly string[] = ['post_timing', 'post_composition'];
60
+ export const SECTIONLESS_POST_ITEMS: readonly string[] = ['camera_depth', 'post_timing', 'post_composition'];
63
61
 
64
62
  export interface DerivedWaypoint {
65
63
  readonly id: string;
@@ -86,12 +84,13 @@ function byOrder(a: string, b: string): number {
86
84
  }
87
85
 
88
86
  /** Places every section parts has; the result is what a project's interview is checked against. */
89
- export function deriveWaypoints(sections: readonly string[]): DerivedSet {
87
+ export function deriveWaypoints(sections: readonly string[], turnInterview = true): DerivedSet {
90
88
  const waypoints = new Map<string, string[]>();
91
89
  const items = new Map<string, string[]>();
92
90
  const unplaced: string[] = [];
93
91
  for (const section of sections) {
94
- const placement = SECTION_PLACEMENT[section];
92
+ const placement = !turnInterview && (section === 'turn' || section === 'depth')
93
+ ? { kind: 'post' as const, item: 'camera_depth' } : SECTION_PLACEMENT[section];
95
94
  if (placement === undefined) {
96
95
  unplaced.push(section);
97
96
  } else if (placement.kind === 'waypoint') {
@@ -117,6 +116,17 @@ export interface WaypointAsk {
117
116
  readonly required_for?: 'fullscreen.game_logic' | 'other';
118
117
  }
119
118
 
119
+ /** New depth obligations are dated by the rig build; old fixed-view records retain their mapping. */
120
+ export const TURN_QUESTION_SPEC = 'rig-create/turn-question@1';
121
+ export const HEAD_TURN_SINCE = '2026-11-14T00:00:00Z';
122
+ export const TURN_QUESTION = 'Should this rig keep the painted view, or turn its head with depth?';
123
+ export const TURN_OPTIONS = [
124
+ { id: 'fixed', kind: 'value', label: 'Fixed view', effect: 'Keep the painted view.', fragment: { mode: 'fixed' } },
125
+ { id: 'turn', kind: 'value', label: 'Head turn', effect: 'The head turns with depth, like the head-turn demo.', fragment: { mode: 'depth' } },
126
+ { id: 'other', kind: 'other', label: 'Other', effect: 'Describe the view you want.' },
127
+ { id: 'auto', kind: 'auto', label: 'Let the agent decide', effect: 'The agent records its decision before approval.' },
128
+ ] as const;
129
+
120
130
  export const WAYPOINT_ASKS: Readonly<Record<string, readonly WaypointAsk[]>> = {
121
131
  seethrough: [
122
132
  { id: 'layers', text: 'What must the layer split keep together or apart?' },
@@ -134,6 +144,7 @@ export const WAYPOINT_ASKS: Readonly<Record<string, readonly WaypointAsk[]>> = {
134
144
  { id: 'occluders', text: 'What is kept under occluders?' },
135
145
  { id: 'outfits', text: 'Which outfit sets exist?' },
136
146
  ],
147
+ turn: [{ id: 'view', text: TURN_QUESTION }],
137
148
  bones: [
138
149
  { id: 'chains', text: 'Which parts get chains or stay rigid?' },
139
150
  { id: 'placement', text: 'Where do bones sit?' },