@rig-c/create 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (555) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +163 -2
  3. package/docs/CHECKS.md +1665 -0
  4. package/docs/COLLECTIONS.md +337 -0
  5. package/docs/CRAFT.md +277 -0
  6. package/docs/INTERVIEW.md +886 -0
  7. package/docs/LESSONS.md +172 -0
  8. package/docs/PROJECT.md +2657 -0
  9. package/docs/SOURCE.md +225 -0
  10. package/package.json +44 -4
  11. package/src/agent-bounce.ts +27 -0
  12. package/src/agent-guide.ts +237 -0
  13. package/src/amend.ts +193 -0
  14. package/src/applied-review.ts +104 -0
  15. package/src/ask-coverage.ts +69 -0
  16. package/src/assemble-answers.ts +53 -0
  17. package/src/cg-gates.ts +211 -0
  18. package/src/check-reads.ts +106 -0
  19. package/src/check.ts +1059 -0
  20. package/src/checkpoint-evidence-writer.ts +125 -0
  21. package/src/checkpoint-evidence.ts +152 -0
  22. package/src/choice-writers.ts +271 -0
  23. package/src/choices.ts +378 -0
  24. package/src/cli.ts +371 -0
  25. package/src/collection-answer.ts +136 -0
  26. package/src/collection-binding-reader.ts +496 -0
  27. package/src/collection-binding.ts +478 -0
  28. package/src/collection.ts +348 -0
  29. package/src/config-inputs.ts +155 -0
  30. package/src/config-lost.ts +135 -0
  31. package/src/correction-writers.ts +207 -0
  32. package/src/corrections.ts +685 -0
  33. package/src/diff-classes.ts +219 -0
  34. package/src/diff-map.ts +248 -0
  35. package/src/direction-citation.ts +13 -0
  36. package/src/direction-writers.ts +119 -0
  37. package/src/direction.ts +266 -0
  38. package/src/drafts.ts +363 -0
  39. package/src/feedback.ts +744 -0
  40. package/src/figure-mask.ts +143 -0
  41. package/src/fix-ledger.ts +355 -0
  42. package/src/init.ts +265 -0
  43. package/src/inputs.ts +160 -0
  44. package/src/intake.ts +158 -0
  45. package/src/interview.ts +53 -0
  46. package/src/invariants.ts +132 -0
  47. package/src/job-acts.ts +80 -0
  48. package/src/job-advance.ts +65 -0
  49. package/src/job-close.ts +226 -0
  50. package/src/job-host.ts +529 -0
  51. package/src/job-outbox.ts +383 -0
  52. package/src/job-publication.ts +701 -0
  53. package/src/job-runtime.ts +99 -0
  54. package/src/job-writer.ts +123 -0
  55. package/src/meshes-bust.ts +63 -0
  56. package/src/next.ts +1506 -0
  57. package/src/overrides.ts +42 -0
  58. package/src/package-upgrades.ts +32 -0
  59. package/src/packages-upgrade-check.ts +6 -0
  60. package/src/packages-upgrade.ts +168 -0
  61. package/src/parts-act.ts +96 -0
  62. package/src/parts-check.ts +242 -0
  63. package/src/parts-review.ts +196 -0
  64. package/src/parts-sections.ts +98 -0
  65. package/src/parts-verdict-record.ts +265 -0
  66. package/src/parts-verdict.ts +33 -0
  67. package/src/pause.ts +118 -0
  68. package/src/pins-check.ts +619 -0
  69. package/src/pins.ts +17 -0
  70. package/src/plan-bar-amendments.ts +54 -0
  71. package/src/plan-history.ts +147 -0
  72. package/src/plan-writers.ts +202 -0
  73. package/src/plate-receipt.ts +110 -0
  74. package/src/pre-interview.ts +302 -0
  75. package/src/prepared-inputs.ts +113 -0
  76. package/src/progress-writers.ts +181 -0
  77. package/src/provenance.ts +301 -0
  78. package/src/record-direction-target.ts +26 -0
  79. package/src/record-input.ts +18 -0
  80. package/src/refusal-baseline.ts +55 -0
  81. package/src/refusal.ts +30 -0
  82. package/src/reopen-lapses.ts +80 -0
  83. package/src/reopen.ts +144 -0
  84. package/src/republish.ts +93 -0
  85. package/src/restart.ts +141 -0
  86. package/src/review-act-runtime.ts +16 -0
  87. package/src/review-act.ts +592 -0
  88. package/src/review-package.ts +524 -0
  89. package/src/review-read.ts +238 -0
  90. package/src/review.ts +432 -0
  91. package/src/rig-version-date.ts +22 -0
  92. package/src/rig-version.ts +1047 -0
  93. package/src/run-record.ts +232 -0
  94. package/src/scene-authority.ts +410 -0
  95. package/src/scene-writers.ts +144 -0
  96. package/src/scene.ts +284 -0
  97. package/src/setup-painting.ts +46 -0
  98. package/src/signable.ts +65 -0
  99. package/src/signoff-answers.ts +76 -0
  100. package/src/signoff-checkpoint-act.ts +95 -0
  101. package/src/signoff-target.ts +127 -0
  102. package/src/signoff.ts +331 -0
  103. package/src/split-captions.ts +154 -0
  104. package/src/stage-progress.ts +379 -0
  105. package/src/stages.ts +148 -0
  106. package/src/step-hash.ts +19 -0
  107. package/src/structure-snapshot.ts +109 -0
  108. package/src/structure.ts +166 -0
  109. package/src/templates.ts +16 -0
  110. package/src/waypoints.ts +163 -0
  111. package/templates/agent-guide.md +108 -0
  112. package/templates/collection-agent-guide.md +72 -0
  113. package/templates/collection.json +252 -0
  114. package/templates/example-chain/AGENTS.md +134 -0
  115. package/templates/example-chain/CLAUDE.md +3 -0
  116. package/templates/example-chain/README.md +13 -0
  117. package/templates/example-chain/chain.json +2869 -0
  118. package/templates/example-chain/checkpoints/0a-interview-options/AGENTS.md +134 -0
  119. package/templates/example-chain/checkpoints/0a-interview-options/CLAUDE.md +3 -0
  120. package/templates/example-chain/checkpoints/0a-interview-options/evidence/.gitkeep +0 -0
  121. package/templates/example-chain/checkpoints/0a-interview-options/evidence/approval.txt +1 -0
  122. package/templates/example-chain/checkpoints/0a-interview-options/evidence/interview/rig_type.json +59 -0
  123. package/templates/example-chain/checkpoints/0a-interview-options/evidence/split-config.json +1 -0
  124. package/templates/example-chain/checkpoints/0a-interview-options/inputs/painting.png +0 -0
  125. package/templates/example-chain/checkpoints/0a-interview-options/inputs/references/.gitkeep +0 -0
  126. package/templates/example-chain/checkpoints/0a-interview-options/package.json +9 -0
  127. package/templates/example-chain/checkpoints/0a-interview-options/project.json +295 -0
  128. package/templates/example-chain/checkpoints/0a-interview-options.json +127 -0
  129. package/templates/example-chain/checkpoints/0b-plan-pending/AGENTS.md +134 -0
  130. package/templates/example-chain/checkpoints/0b-plan-pending/CLAUDE.md +3 -0
  131. package/templates/example-chain/checkpoints/0b-plan-pending/evidence/.gitkeep +0 -0
  132. package/templates/example-chain/checkpoints/0b-plan-pending/evidence/approval.txt +1 -0
  133. package/templates/example-chain/checkpoints/0b-plan-pending/evidence/interview/assemble.json +309 -0
  134. package/templates/example-chain/checkpoints/0b-plan-pending/evidence/interview/reference.json +59 -0
  135. package/templates/example-chain/checkpoints/0b-plan-pending/evidence/interview/rig_type.json +59 -0
  136. package/templates/example-chain/checkpoints/0b-plan-pending/evidence/interview/seethrough.json +186 -0
  137. package/templates/example-chain/checkpoints/0b-plan-pending/evidence/split-config.json +1 -0
  138. package/templates/example-chain/checkpoints/0b-plan-pending/inputs/painting.png +0 -0
  139. package/templates/example-chain/checkpoints/0b-plan-pending/inputs/references/.gitkeep +0 -0
  140. package/templates/example-chain/checkpoints/0b-plan-pending/package.json +9 -0
  141. package/templates/example-chain/checkpoints/0b-plan-pending/project.json +685 -0
  142. package/templates/example-chain/checkpoints/0b-plan-pending.json +81 -0
  143. package/templates/example-chain/checkpoints/1-parts-verdict/AGENTS.md +134 -0
  144. package/templates/example-chain/checkpoints/1-parts-verdict/CLAUDE.md +3 -0
  145. package/templates/example-chain/checkpoints/1-parts-verdict/evidence/.gitkeep +0 -0
  146. package/templates/example-chain/checkpoints/1-parts-verdict/evidence/approval.txt +1 -0
  147. package/templates/example-chain/checkpoints/1-parts-verdict/evidence/interview/assemble.json +309 -0
  148. package/templates/example-chain/checkpoints/1-parts-verdict/evidence/interview/reference.json +59 -0
  149. package/templates/example-chain/checkpoints/1-parts-verdict/evidence/interview/rig_type.json +59 -0
  150. package/templates/example-chain/checkpoints/1-parts-verdict/evidence/interview/seethrough.json +186 -0
  151. package/templates/example-chain/checkpoints/1-parts-verdict/evidence/parts-check.json +127 -0
  152. package/templates/example-chain/checkpoints/1-parts-verdict/evidence/split-config.json +1 -0
  153. package/templates/example-chain/checkpoints/1-parts-verdict/inputs/painting.png +0 -0
  154. package/templates/example-chain/checkpoints/1-parts-verdict/inputs/references/.gitkeep +0 -0
  155. package/templates/example-chain/checkpoints/1-parts-verdict/package.json +9 -0
  156. package/templates/example-chain/checkpoints/1-parts-verdict/project.json +955 -0
  157. package/templates/example-chain/checkpoints/1-parts-verdict.json +204 -0
  158. package/templates/example-chain/checkpoints/2-rigging-answers/AGENTS.md +134 -0
  159. package/templates/example-chain/checkpoints/2-rigging-answers/CLAUDE.md +3 -0
  160. package/templates/example-chain/checkpoints/2-rigging-answers/evidence/.gitkeep +0 -0
  161. package/templates/example-chain/checkpoints/2-rigging-answers/evidence/approval.txt +1 -0
  162. package/templates/example-chain/checkpoints/2-rigging-answers/evidence/diff-components.json +34 -0
  163. package/templates/example-chain/checkpoints/2-rigging-answers/evidence/interview/assemble.json +309 -0
  164. package/templates/example-chain/checkpoints/2-rigging-answers/evidence/interview/bones.json +190 -0
  165. package/templates/example-chain/checkpoints/2-rigging-answers/evidence/interview/reference.json +59 -0
  166. package/templates/example-chain/checkpoints/2-rigging-answers/evidence/interview/rig_type.json +59 -0
  167. package/templates/example-chain/checkpoints/2-rigging-answers/evidence/interview/seethrough.json +186 -0
  168. package/templates/example-chain/checkpoints/2-rigging-answers/evidence/parts-check.json +127 -0
  169. package/templates/example-chain/checkpoints/2-rigging-answers/evidence/parts-review.json +88 -0
  170. package/templates/example-chain/checkpoints/2-rigging-answers/evidence/review-reads/a12dea02d32508acc99386f894af76a14f1c85f45f804db2aa6b4dea5297973f.json +59 -0
  171. package/templates/example-chain/checkpoints/2-rigging-answers/evidence/split-config.json +1 -0
  172. package/templates/example-chain/checkpoints/2-rigging-answers/evidence/structure.json +30 -0
  173. package/templates/example-chain/checkpoints/2-rigging-answers/inputs/painting.png +0 -0
  174. package/templates/example-chain/checkpoints/2-rigging-answers/inputs/references/.gitkeep +0 -0
  175. package/templates/example-chain/checkpoints/2-rigging-answers/package.json +9 -0
  176. package/templates/example-chain/checkpoints/2-rigging-answers/project.json +1198 -0
  177. package/templates/example-chain/checkpoints/2-rigging-answers.json +254 -0
  178. package/templates/example-chain/checkpoints/3-rig-review/AGENTS.md +134 -0
  179. package/templates/example-chain/checkpoints/3-rig-review/CLAUDE.md +3 -0
  180. package/templates/example-chain/checkpoints/3-rig-review/evidence/.gitkeep +0 -0
  181. package/templates/example-chain/checkpoints/3-rig-review/evidence/approval.txt +1 -0
  182. package/templates/example-chain/checkpoints/3-rig-review/evidence/diff-components.json +34 -0
  183. package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/assemble.json +309 -0
  184. package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/bones.json +190 -0
  185. package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/constraints.json +272 -0
  186. package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/meshes.json +190 -0
  187. package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/motion.json +272 -0
  188. package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/reference.json +59 -0
  189. package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/rig_type.json +59 -0
  190. package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/seethrough.json +186 -0
  191. package/templates/example-chain/checkpoints/3-rig-review/evidence/parts-check.json +127 -0
  192. package/templates/example-chain/checkpoints/3-rig-review/evidence/parts-review.json +88 -0
  193. package/templates/example-chain/checkpoints/3-rig-review/evidence/review-reads/a12dea02d32508acc99386f894af76a14f1c85f45f804db2aa6b4dea5297973f.json +59 -0
  194. package/templates/example-chain/checkpoints/3-rig-review/evidence/setup.png +0 -0
  195. package/templates/example-chain/checkpoints/3-rig-review/evidence/split-config.json +1 -0
  196. package/templates/example-chain/checkpoints/3-rig-review/evidence/structure.json +30 -0
  197. package/templates/example-chain/checkpoints/3-rig-review/evidence/v1/config.json +88 -0
  198. package/templates/example-chain/checkpoints/3-rig-review/evidence/v1/interview-requirements.json +8 -0
  199. package/templates/example-chain/checkpoints/3-rig-review/inputs/painting.png +0 -0
  200. package/templates/example-chain/checkpoints/3-rig-review/inputs/references/.gitkeep +0 -0
  201. package/templates/example-chain/checkpoints/3-rig-review/package.json +9 -0
  202. package/templates/example-chain/checkpoints/3-rig-review/project.json +1909 -0
  203. package/templates/example-chain/checkpoints/3-rig-review.json +424 -0
  204. package/templates/example-chain/checkpoints/4-direction-post/AGENTS.md +134 -0
  205. package/templates/example-chain/checkpoints/4-direction-post/CLAUDE.md +3 -0
  206. package/templates/example-chain/checkpoints/4-direction-post/evidence/.gitkeep +0 -0
  207. package/templates/example-chain/checkpoints/4-direction-post/evidence/approval.txt +1 -0
  208. package/templates/example-chain/checkpoints/4-direction-post/evidence/diff-components.json +34 -0
  209. package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/assemble.json +309 -0
  210. package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/bones.json +190 -0
  211. package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/camera_depth.json +102 -0
  212. package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/constraints.json +272 -0
  213. package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/meshes.json +190 -0
  214. package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/motion.json +272 -0
  215. package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/post_composition.json +122 -0
  216. package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/post_timing.json +102 -0
  217. package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/reference.json +59 -0
  218. package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/rig_type.json +59 -0
  219. package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/seethrough.json +186 -0
  220. package/templates/example-chain/checkpoints/4-direction-post/evidence/parts-check.json +127 -0
  221. package/templates/example-chain/checkpoints/4-direction-post/evidence/parts-review.json +88 -0
  222. package/templates/example-chain/checkpoints/4-direction-post/evidence/review-reads/a12dea02d32508acc99386f894af76a14f1c85f45f804db2aa6b4dea5297973f.json +59 -0
  223. package/templates/example-chain/checkpoints/4-direction-post/evidence/setup.png +0 -0
  224. package/templates/example-chain/checkpoints/4-direction-post/evidence/split-config.json +1 -0
  225. package/templates/example-chain/checkpoints/4-direction-post/evidence/structure.json +30 -0
  226. package/templates/example-chain/checkpoints/4-direction-post/evidence/v1/config.json +88 -0
  227. package/templates/example-chain/checkpoints/4-direction-post/evidence/v1/interview-requirements.json +8 -0
  228. package/templates/example-chain/checkpoints/4-direction-post/inputs/painting.png +0 -0
  229. package/templates/example-chain/checkpoints/4-direction-post/inputs/references/.gitkeep +0 -0
  230. package/templates/example-chain/checkpoints/4-direction-post/package.json +9 -0
  231. package/templates/example-chain/checkpoints/4-direction-post/project.json +2302 -0
  232. package/templates/example-chain/checkpoints/4-direction-post.json +456 -0
  233. package/templates/example-chain/evidence/.gitkeep +0 -0
  234. package/templates/example-chain/evidence/approval.txt +1 -0
  235. package/templates/example-chain/evidence/captions.json +101 -0
  236. package/templates/example-chain/evidence/diff-components.json +34 -0
  237. package/templates/example-chain/evidence/direction/v2.json +74 -0
  238. package/templates/example-chain/evidence/direction-input.json +74 -0
  239. package/templates/example-chain/evidence/interview/assemble.json +309 -0
  240. package/templates/example-chain/evidence/interview/bones.json +190 -0
  241. package/templates/example-chain/evidence/interview/camera_depth.json +102 -0
  242. package/templates/example-chain/evidence/interview/constraints.json +272 -0
  243. package/templates/example-chain/evidence/interview/meshes.json +190 -0
  244. package/templates/example-chain/evidence/interview/motion.json +272 -0
  245. package/templates/example-chain/evidence/interview/post_composition.json +122 -0
  246. package/templates/example-chain/evidence/interview/post_timing.json +102 -0
  247. package/templates/example-chain/evidence/interview/reference.json +59 -0
  248. package/templates/example-chain/evidence/interview/rig_type.json +59 -0
  249. package/templates/example-chain/evidence/interview/seethrough.json +186 -0
  250. package/templates/example-chain/evidence/parts-check.json +127 -0
  251. package/templates/example-chain/evidence/parts-review.json +88 -0
  252. package/templates/example-chain/evidence/review-reads/a12dea02d32508acc99386f894af76a14f1c85f45f804db2aa6b4dea5297973f.json +59 -0
  253. package/templates/example-chain/evidence/scene/s1.json +65 -0
  254. package/templates/example-chain/evidence/scene-citations.json +9 -0
  255. package/templates/example-chain/evidence/setup.png +0 -0
  256. package/templates/example-chain/evidence/split-config.json +1 -0
  257. package/templates/example-chain/evidence/structure.json +30 -0
  258. package/templates/example-chain/evidence/v1/config.json +88 -0
  259. package/templates/example-chain/evidence/v1/interview-requirements.json +8 -0
  260. package/templates/example-chain/inputs/background.png +0 -0
  261. package/templates/example-chain/inputs/painting.png +0 -0
  262. package/templates/example-chain/inputs/references/.gitkeep +0 -0
  263. package/templates/example-chain/package.json +9 -0
  264. package/templates/example-chain/project.json +2593 -0
  265. package/templates/example-diff/diff-components.json +71 -0
  266. package/templates/example-diff/recomposite_rig.png +0 -0
  267. package/templates/example-direction/approval.txt +1 -0
  268. package/templates/example-direction/derived/review/v1/out/check/build/rectangle.png +0 -0
  269. package/templates/example-direction/derived/review/v1/out/check/build/run.json +40 -0
  270. package/templates/example-direction/derived/review/v1/out/check/build/skeleton.atlas +8 -0
  271. package/templates/example-direction/derived/review/v1/out/check/build/skeleton.json +73 -0
  272. package/templates/example-direction/derived/review/v1/out/check/build/skeleton.model.json +195 -0
  273. package/templates/example-direction/evidence/direction/v2.json +69 -0
  274. package/templates/example-direction/evidence/direction/v3.json +59 -0
  275. package/templates/example-direction/evidence/images/rectangle.png +0 -0
  276. package/templates/example-direction/evidence/input.json +69 -0
  277. package/templates/example-direction/evidence/motion.json +33 -0
  278. package/templates/example-direction/evidence/patch.json +23 -0
  279. package/templates/example-direction/evidence/rig-config.json +55 -0
  280. package/templates/example-direction/evidence/still.png +0 -0
  281. package/templates/example-direction/project.json +372 -0
  282. package/templates/example-direction/reasoning.txt +1 -0
  283. package/templates/example-direction/words.txt +1 -0
  284. package/templates/example-draft/README.md +28 -0
  285. package/templates/example-draft/config.json +71 -0
  286. package/templates/example-draft/derived/drafts/lantern/config.json +71 -0
  287. package/templates/example-draft/derived/drafts/lantern/input/painting_in_rig.png +0 -0
  288. package/templates/example-draft/derived/drafts/lantern/input/parts/background.png +0 -0
  289. package/templates/example-draft/derived/drafts/lantern/input/parts/eye_l.png +0 -0
  290. package/templates/example-draft/derived/drafts/lantern/input/parts/eye_r.png +0 -0
  291. package/templates/example-draft/derived/drafts/lantern/input/parts/face.png +0 -0
  292. package/templates/example-draft/derived/drafts/lantern/input/parts/lantern.png +0 -0
  293. package/templates/example-draft/derived/drafts/lantern/input/parts/torso.png +0 -0
  294. package/templates/example-draft/derived/drafts/lantern/input/parts.json +188 -0
  295. package/templates/example-draft/derived/drafts/lantern/input/recomposite_rig.png +0 -0
  296. package/templates/example-draft/derived/drafts/lantern/interview-requirements.json +8 -0
  297. package/templates/example-draft/derived/drafts/lantern/out/check/build/run.json +40 -0
  298. package/templates/example-draft/derived/drafts/lantern/out/check/build/skeleton.atlas +28 -0
  299. package/templates/example-draft/derived/drafts/lantern/out/check/build/skeleton.json +193 -0
  300. package/templates/example-draft/derived/drafts/lantern/out/check/build/skeleton.model.json +483 -0
  301. package/templates/example-draft/derived/drafts/lantern/out/check/build/skeleton.png +0 -0
  302. package/templates/example-draft/derived/drafts/lantern/out/images/background.png +0 -0
  303. package/templates/example-draft/derived/drafts/lantern/out/images/eye_l.png +0 -0
  304. package/templates/example-draft/derived/drafts/lantern/out/images/eye_r.png +0 -0
  305. package/templates/example-draft/derived/drafts/lantern/out/images/face.png +0 -0
  306. package/templates/example-draft/derived/drafts/lantern/out/images/lantern.png +0 -0
  307. package/templates/example-draft/derived/drafts/lantern/out/images/torso.png +0 -0
  308. package/templates/example-draft/derived/drafts/lantern/out/mesh_report.json +1 -0
  309. package/templates/example-draft/derived/drafts/lantern/out/motion.json +137 -0
  310. package/templates/example-draft/derived/drafts/lantern/out/rig.json +102 -0
  311. package/templates/example-draft/derived/drafts/lantern/out/run.json +52 -0
  312. package/templates/example-draft/derived/parts/rig/painting_in_rig.png +0 -0
  313. package/templates/example-draft/derived/parts/rig/parts/background.png +0 -0
  314. package/templates/example-draft/derived/parts/rig/parts/eye_l.png +0 -0
  315. package/templates/example-draft/derived/parts/rig/parts/eye_r.png +0 -0
  316. package/templates/example-draft/derived/parts/rig/parts/face.png +0 -0
  317. package/templates/example-draft/derived/parts/rig/parts/lantern.png +0 -0
  318. package/templates/example-draft/derived/parts/rig/parts/torso.png +0 -0
  319. package/templates/example-draft/derived/parts/rig/parts.json +188 -0
  320. package/templates/example-draft/derived/parts/rig/recomposite_rig.png +0 -0
  321. package/templates/example-draft/derived/review/v1/config.json +71 -0
  322. package/templates/example-draft/derived/review/v1/interview-requirements.json +8 -0
  323. package/templates/example-draft/derived/review/v1/out/check/build/run.json +40 -0
  324. package/templates/example-draft/derived/review/v1/out/check/build/skeleton.atlas +28 -0
  325. package/templates/example-draft/derived/review/v1/out/check/build/skeleton.json +193 -0
  326. package/templates/example-draft/derived/review/v1/out/check/build/skeleton.model.json +483 -0
  327. package/templates/example-draft/derived/review/v1/out/check/build/skeleton.png +0 -0
  328. package/templates/example-draft/derived/review/v1/out/parts/background.png +0 -0
  329. package/templates/example-draft/derived/review/v1/out/parts/eye_l.png +0 -0
  330. package/templates/example-draft/derived/review/v1/out/parts/eye_r.png +0 -0
  331. package/templates/example-draft/derived/review/v1/out/parts/face.png +0 -0
  332. package/templates/example-draft/derived/review/v1/out/parts/lantern.png +0 -0
  333. package/templates/example-draft/derived/review/v1/out/parts/torso.png +0 -0
  334. package/templates/example-draft/derived/review/v1/out/parts.json +188 -0
  335. package/templates/example-draft/derived/review/v1/out/rig/images/background.png +0 -0
  336. package/templates/example-draft/derived/review/v1/out/rig/images/eye_l.png +0 -0
  337. package/templates/example-draft/derived/review/v1/out/rig/images/eye_r.png +0 -0
  338. package/templates/example-draft/derived/review/v1/out/rig/images/face.png +0 -0
  339. package/templates/example-draft/derived/review/v1/out/rig/images/lantern.png +0 -0
  340. package/templates/example-draft/derived/review/v1/out/rig/images/torso.png +0 -0
  341. package/templates/example-draft/derived/review/v1/out/rig/mesh_report.json +1 -0
  342. package/templates/example-draft/derived/review/v1/out/rig/motion.json +137 -0
  343. package/templates/example-draft/derived/review/v1/out/rig/rig.json +102 -0
  344. package/templates/example-draft/derived/review/v1/out/rig/run.json +52 -0
  345. package/templates/example-draft/derived/review/v2/config.json +71 -0
  346. package/templates/example-draft/derived/review/v2/interview-requirements.json +8 -0
  347. package/templates/example-draft/derived/review/v2/out/check/build/run.json +40 -0
  348. package/templates/example-draft/derived/review/v2/out/check/build/skeleton.atlas +28 -0
  349. package/templates/example-draft/derived/review/v2/out/check/build/skeleton.json +193 -0
  350. package/templates/example-draft/derived/review/v2/out/check/build/skeleton.model.json +483 -0
  351. package/templates/example-draft/derived/review/v2/out/check/build/skeleton.png +0 -0
  352. package/templates/example-draft/derived/review/v2/out/parts/background.png +0 -0
  353. package/templates/example-draft/derived/review/v2/out/parts/eye_l.png +0 -0
  354. package/templates/example-draft/derived/review/v2/out/parts/eye_r.png +0 -0
  355. package/templates/example-draft/derived/review/v2/out/parts/face.png +0 -0
  356. package/templates/example-draft/derived/review/v2/out/parts/lantern.png +0 -0
  357. package/templates/example-draft/derived/review/v2/out/parts/torso.png +0 -0
  358. package/templates/example-draft/derived/review/v2/out/parts.json +188 -0
  359. package/templates/example-draft/derived/review/v2/out/rig/images/background.png +0 -0
  360. package/templates/example-draft/derived/review/v2/out/rig/images/eye_l.png +0 -0
  361. package/templates/example-draft/derived/review/v2/out/rig/images/eye_r.png +0 -0
  362. package/templates/example-draft/derived/review/v2/out/rig/images/face.png +0 -0
  363. package/templates/example-draft/derived/review/v2/out/rig/images/lantern.png +0 -0
  364. package/templates/example-draft/derived/review/v2/out/rig/images/torso.png +0 -0
  365. package/templates/example-draft/derived/review/v2/out/rig/mesh_report.json +1 -0
  366. package/templates/example-draft/derived/review/v2/out/rig/motion.json +137 -0
  367. package/templates/example-draft/derived/review/v2/out/rig/rig.json +102 -0
  368. package/templates/example-draft/derived/review/v2/out/rig/run.json +52 -0
  369. package/templates/example-draft/evidence/diff-components.json +71 -0
  370. package/templates/example-draft/evidence/direction/v4.json +64 -0
  371. package/templates/example-draft/evidence/direction-input-v4.json +64 -0
  372. package/templates/example-draft/evidence/fix-ledger/lantern.json +17 -0
  373. package/templates/example-draft/evidence/parts-check.json +127 -0
  374. package/templates/example-draft/evidence/parts-review.json +88 -0
  375. package/templates/example-draft/evidence/review-reads/4ed0507381809746443021554e012032be5b5f8417da0f2e525e9b6df16e9f05.json +59 -0
  376. package/templates/example-draft/evidence/scene/s1.json +65 -0
  377. package/templates/example-draft/evidence/scene-background.png +0 -0
  378. package/templates/example-draft/evidence/scene-citations.json +9 -0
  379. package/templates/example-draft/evidence/structure-decisions.json +9 -0
  380. package/templates/example-draft/evidence/v1/interview-config.json +71 -0
  381. package/templates/example-draft/evidence/v1/interview-requirements.json +8 -0
  382. package/templates/example-draft/evidence/v1/review-config.json +71 -0
  383. package/templates/example-draft/evidence/v2/interview-config.json +71 -0
  384. package/templates/example-draft/evidence/v2/interview-requirements.json +8 -0
  385. package/templates/example-draft/evidence/v2/review-config.json +71 -0
  386. package/templates/example-draft/input/painting_in_rig.png +0 -0
  387. package/templates/example-draft/input/parts/background.png +0 -0
  388. package/templates/example-draft/input/parts/eye_l.png +0 -0
  389. package/templates/example-draft/input/parts/eye_r.png +0 -0
  390. package/templates/example-draft/input/parts/face.png +0 -0
  391. package/templates/example-draft/input/parts/lantern.png +0 -0
  392. package/templates/example-draft/input/parts/torso.png +0 -0
  393. package/templates/example-draft/input/parts.json +188 -0
  394. package/templates/example-draft/input/recomposite_rig.png +0 -0
  395. package/templates/example-draft/inputs/painting.png +0 -0
  396. package/templates/example-draft/interview-requirements.json +8 -0
  397. package/templates/example-draft/out/check/build/run.json +40 -0
  398. package/templates/example-draft/out/check/build/skeleton.atlas +28 -0
  399. package/templates/example-draft/out/check/build/skeleton.json +193 -0
  400. package/templates/example-draft/out/check/build/skeleton.model.json +483 -0
  401. package/templates/example-draft/out/check/build/skeleton.png +0 -0
  402. package/templates/example-draft/out/images/background.png +0 -0
  403. package/templates/example-draft/out/images/eye_l.png +0 -0
  404. package/templates/example-draft/out/images/eye_r.png +0 -0
  405. package/templates/example-draft/out/images/face.png +0 -0
  406. package/templates/example-draft/out/images/lantern.png +0 -0
  407. package/templates/example-draft/out/images/torso.png +0 -0
  408. package/templates/example-draft/out/mesh_report.json +1 -0
  409. package/templates/example-draft/out/motion.json +137 -0
  410. package/templates/example-draft/out/rig.json +102 -0
  411. package/templates/example-draft/out/run.json +52 -0
  412. package/templates/example-draft/outputs/v1/out/check/build/run.json +40 -0
  413. package/templates/example-draft/outputs/v1/out/check/build/skeleton.atlas +28 -0
  414. package/templates/example-draft/outputs/v1/out/check/build/skeleton.json +193 -0
  415. package/templates/example-draft/outputs/v1/out/check/build/skeleton.model.json +483 -0
  416. package/templates/example-draft/outputs/v1/out/check/build/skeleton.png +0 -0
  417. package/templates/example-draft/outputs/v1/out/painting_in_rig.png +0 -0
  418. package/templates/example-draft/outputs/v1/out/parts/background.png +0 -0
  419. package/templates/example-draft/outputs/v1/out/parts/eye_l.png +0 -0
  420. package/templates/example-draft/outputs/v1/out/parts/eye_r.png +0 -0
  421. package/templates/example-draft/outputs/v1/out/parts/face.png +0 -0
  422. package/templates/example-draft/outputs/v1/out/parts/lantern.png +0 -0
  423. package/templates/example-draft/outputs/v1/out/parts/torso.png +0 -0
  424. package/templates/example-draft/outputs/v1/out/parts.json +188 -0
  425. package/templates/example-draft/outputs/v1/out/rig/images/background.png +0 -0
  426. package/templates/example-draft/outputs/v1/out/rig/images/eye_l.png +0 -0
  427. package/templates/example-draft/outputs/v1/out/rig/images/eye_r.png +0 -0
  428. package/templates/example-draft/outputs/v1/out/rig/images/face.png +0 -0
  429. package/templates/example-draft/outputs/v1/out/rig/images/lantern.png +0 -0
  430. package/templates/example-draft/outputs/v1/out/rig/images/torso.png +0 -0
  431. package/templates/example-draft/outputs/v1/out/rig/mesh_report.json +1 -0
  432. package/templates/example-draft/outputs/v1/out/rig/motion.json +137 -0
  433. package/templates/example-draft/outputs/v1/out/rig/rig.json +102 -0
  434. package/templates/example-draft/outputs/v1/out/rig/run.json +52 -0
  435. package/templates/example-draft/outputs/v2/out/check/build/run.json +40 -0
  436. package/templates/example-draft/outputs/v2/out/check/build/skeleton.atlas +28 -0
  437. package/templates/example-draft/outputs/v2/out/check/build/skeleton.json +193 -0
  438. package/templates/example-draft/outputs/v2/out/check/build/skeleton.model.json +483 -0
  439. package/templates/example-draft/outputs/v2/out/check/build/skeleton.png +0 -0
  440. package/templates/example-draft/outputs/v2/out/painting_in_rig.png +0 -0
  441. package/templates/example-draft/outputs/v2/out/parts/background.png +0 -0
  442. package/templates/example-draft/outputs/v2/out/parts/eye_l.png +0 -0
  443. package/templates/example-draft/outputs/v2/out/parts/eye_r.png +0 -0
  444. package/templates/example-draft/outputs/v2/out/parts/face.png +0 -0
  445. package/templates/example-draft/outputs/v2/out/parts/lantern.png +0 -0
  446. package/templates/example-draft/outputs/v2/out/parts/torso.png +0 -0
  447. package/templates/example-draft/outputs/v2/out/parts.json +188 -0
  448. package/templates/example-draft/outputs/v2/out/rig/images/background.png +0 -0
  449. package/templates/example-draft/outputs/v2/out/rig/images/eye_l.png +0 -0
  450. package/templates/example-draft/outputs/v2/out/rig/images/eye_r.png +0 -0
  451. package/templates/example-draft/outputs/v2/out/rig/images/face.png +0 -0
  452. package/templates/example-draft/outputs/v2/out/rig/images/lantern.png +0 -0
  453. package/templates/example-draft/outputs/v2/out/rig/images/torso.png +0 -0
  454. package/templates/example-draft/outputs/v2/out/rig/mesh_report.json +1 -0
  455. package/templates/example-draft/outputs/v2/out/rig/motion.json +137 -0
  456. package/templates/example-draft/outputs/v2/out/rig/rig.json +102 -0
  457. package/templates/example-draft/outputs/v2/out/rig/run.json +52 -0
  458. package/templates/example-interview-choice.json +1068 -0
  459. package/templates/example-interview-options/constraint.json +376 -0
  460. package/templates/example-interview-options/example-assemble.json +376 -0
  461. package/templates/example-interview-options/example-bones.json +190 -0
  462. package/templates/example-interview-options/example-camera-depth.json +99 -0
  463. package/templates/example-interview-options/example-constraints.json +272 -0
  464. package/templates/example-interview-options/example-meshes.json +190 -0
  465. package/templates/example-interview-options/example-motion.json +272 -0
  466. package/templates/example-interview-options/example-picks.json +15 -0
  467. package/templates/example-interview-options/example-post-composition.json +110 -0
  468. package/templates/example-interview-options/example-post-timing.json +105 -0
  469. package/templates/example-interview-options/example-reference.json +63 -0
  470. package/templates/example-interview-options/example-rig-type.json +63 -0
  471. package/templates/example-interview-options/example-seethrough.json +190 -0
  472. package/templates/example-interview-options/fullscreen.json +63 -0
  473. package/templates/example-interview-options/other-explicit.json +63 -0
  474. package/templates/example-interview-options/other-pending.json +63 -0
  475. package/templates/example-interview-options/other-picks.json +16 -0
  476. package/templates/example-interview.md +213 -0
  477. package/templates/example-invariants/invariants.json +1339 -0
  478. package/templates/example-prepared/prepared.svg +1 -0
  479. package/templates/example-prepared/source.svg +1 -0
  480. package/templates/example-project.json +4259 -0
  481. package/templates/example-remesh/AGENTS.md +134 -0
  482. package/templates/example-remesh/CLAUDE.md +3 -0
  483. package/templates/example-remesh/evidence/.gitkeep +0 -0
  484. package/templates/example-remesh/evidence/approval.txt +1 -0
  485. package/templates/example-remesh/evidence/captions.json +101 -0
  486. package/templates/example-remesh/evidence/diff-components.json +34 -0
  487. package/templates/example-remesh/evidence/direction/v4.json +74 -0
  488. package/templates/example-remesh/evidence/direction/v5.json +74 -0
  489. package/templates/example-remesh/evidence/direction-input-v4.json +74 -0
  490. package/templates/example-remesh/evidence/direction-input-v5.json +74 -0
  491. package/templates/example-remesh/evidence/interview/assemble.json +309 -0
  492. package/templates/example-remesh/evidence/interview/bones.json +190 -0
  493. package/templates/example-remesh/evidence/interview/camera_depth.json +103 -0
  494. package/templates/example-remesh/evidence/interview/constraints.json +272 -0
  495. package/templates/example-remesh/evidence/interview/meshes.json +190 -0
  496. package/templates/example-remesh/evidence/interview/motion.json +272 -0
  497. package/templates/example-remesh/evidence/interview/post_composition.json +123 -0
  498. package/templates/example-remesh/evidence/interview/post_timing.json +103 -0
  499. package/templates/example-remesh/evidence/interview/reference.json +59 -0
  500. package/templates/example-remesh/evidence/interview/rig_type.json +59 -0
  501. package/templates/example-remesh/evidence/interview/seethrough.json +186 -0
  502. package/templates/example-remesh/evidence/parts-check.json +127 -0
  503. package/templates/example-remesh/evidence/parts-review.json +88 -0
  504. package/templates/example-remesh/evidence/reopen.txt +1 -0
  505. package/templates/example-remesh/evidence/review-reads/6a17db694db96f1b6049a61a017e0c8e66757b982b8851e0187e561cfcf9af68.json +59 -0
  506. package/templates/example-remesh/evidence/scene/s1.json +69 -0
  507. package/templates/example-remesh/evidence/scene-citations.json +9 -0
  508. package/templates/example-remesh/evidence/setup.png +0 -0
  509. package/templates/example-remesh/evidence/split-config.json +1 -0
  510. package/templates/example-remesh/evidence/structure.json +30 -0
  511. package/templates/example-remesh/evidence/v1/registration/at-source.json +44 -0
  512. package/templates/example-remesh/evidence/v1/registration/citations.json +68 -0
  513. package/templates/example-remesh/evidence/v1/registration/compile-report.json +368 -0
  514. package/templates/example-remesh/evidence/v1/registration/config-source.json +88 -0
  515. package/templates/example-remesh/evidence/v1/registration/config.json +88 -0
  516. package/templates/example-remesh/evidence/v1/registration/interview-requirements.json +8 -0
  517. package/templates/example-remesh/evidence/v1/registration/package-lock.json +11 -0
  518. package/templates/example-remesh/evidence/v1/registration/path-adapter.json +1 -0
  519. package/templates/example-remesh/evidence/v1/registration/rigc-run-1.json +44 -0
  520. package/templates/example-remesh/evidence/v2/registration/at-source.json +44 -0
  521. package/templates/example-remesh/evidence/v2/registration/citations.json +68 -0
  522. package/templates/example-remesh/evidence/v2/registration/compile-report.json +368 -0
  523. package/templates/example-remesh/evidence/v2/registration/config-source.json +88 -0
  524. package/templates/example-remesh/evidence/v2/registration/config.json +88 -0
  525. package/templates/example-remesh/evidence/v2/registration/interview-requirements.json +8 -0
  526. package/templates/example-remesh/evidence/v2/registration/package-lock.json +11 -0
  527. package/templates/example-remesh/evidence/v2/registration/path-adapter.json +1 -0
  528. package/templates/example-remesh/evidence/v2/registration/rigc-run-1.json +44 -0
  529. package/templates/example-remesh/evidence/v3/registration/at-source.json +44 -0
  530. package/templates/example-remesh/evidence/v3/registration/citations.json +68 -0
  531. package/templates/example-remesh/evidence/v3/registration/compile-report.json +368 -0
  532. package/templates/example-remesh/evidence/v3/registration/config-source.json +88 -0
  533. package/templates/example-remesh/evidence/v3/registration/config.json +88 -0
  534. package/templates/example-remesh/evidence/v3/registration/interview-requirements.json +8 -0
  535. package/templates/example-remesh/evidence/v3/registration/package-lock.json +11 -0
  536. package/templates/example-remesh/evidence/v3/registration/path-adapter.json +1 -0
  537. package/templates/example-remesh/evidence/v3/registration/rigc-run-1.json +44 -0
  538. package/templates/example-remesh/inputs/background.png +0 -0
  539. package/templates/example-remesh/inputs/painting.png +0 -0
  540. package/templates/example-remesh/inputs/references/.gitkeep +0 -0
  541. package/templates/example-remesh/package.json +9 -0
  542. package/templates/example-remesh/project.json +3916 -0
  543. package/templates/example-reopened/project.json +4568 -0
  544. package/templates/example-review/config.json +1 -0
  545. package/templates/example-review/out/check/build/skeleton.model.json +1 -0
  546. package/templates/example-review/out/parts/piece.svg +1 -0
  547. package/templates/example-review/out/parts.json +1 -0
  548. package/templates/example-review/out/rig/mesh_report.json +1 -0
  549. package/templates/example-review/out/rig/motion.json +1 -0
  550. package/templates/example-review/out/rig/rig.json +1 -0
  551. package/templates/example-split/captions.json +357 -0
  552. package/templates/example-split/config.json +215 -0
  553. package/templates/legacy-example-project.json +1071 -0
  554. package/templates/project.json +199 -0
  555. package/templates/shared/conventions.json +23 -0
@@ -0,0 +1,266 @@
1
+ import { SceneError, committedScene, readScene, validateSceneCurrent } from './scene.ts';
2
+ import { fixedNotApplicableCamera } from './direction-citation.ts';
3
+ /** Create owns these authored camera/timing bytes. No renderer or external producer runs here. */
4
+ import { createHash } from 'node:crypto';
5
+ import { lstatSync, readFileSync, realpathSync } from './check-reads.ts';
6
+ import { isAbsolute, join } from 'node:path';
7
+ import { isDeepStrictEqual as equal } from 'node:util';
8
+ import { asArray, collectItems, collectSignoffs, isDecision, isObject, loadCollection, type Ctx, type Finding } from './check.ts';
9
+ import { optionFile, selection, validateChoice } from './choices.ts';
10
+ import { checkEntry } from './provenance.ts';
11
+ import { collectReopens, liveSignoff } from './reopen.ts';
12
+ import { refuse } from './refusal.ts';
13
+ import { latestAccepted, readVersions } from './review.ts';
14
+ import { stepHash } from './step-hash.ts';
15
+ import { structurePathIsIgnored } from './structure.ts';
16
+ import type { Json, JsonObject } from './templates.ts';
17
+
18
+ export const DIRECTION_SPEC = 'rig-create/direction@1';
19
+ export const DIRECTION_SCENE_SPEC = 'rig-create/direction@2';
20
+ /** Landing day at 00:00Z; earlier direction@1 posts WARN. */
21
+ export const DIRECTION_SCENE_SINCE = '2026-11-08T00:00:00Z';
22
+ export const DIRECTION_CONTRACT = 'rig-create/direction-contract@1';
23
+ export const DIRECTION_PATCH_SPEC = 'rig-review-direction-patch/1';
24
+ export const DIRECTION_CORRECTION_SPEC = 'rig-create/correction@2';
25
+ export const directionHash = (bytes: Uint8Array): string => createHash('sha256').update(bytes).digest('hex');
26
+ export const directionPath = (n: number): string => `evidence/direction/v${n}.json`;
27
+ export const objects = (v: Json | undefined): JsonObject[] => asArray(v).filter(isObject);
28
+ export const hex = (v: unknown): v is string => typeof v === 'string' && /^[a-f0-9]{64}$/.test(v);
29
+ export const closed = (v: unknown, required: string[], optional: string[] = []): v is JsonObject => isObject(v as Json) && required.every(k => k in (v as JsonObject)) && Object.keys(v as JsonObject).every(k => required.includes(k) || optional.includes(k));
30
+ const positiveInt = (v: unknown): v is number => Number.isSafeInteger(v) && Number(v) > 0;
31
+ const finite = (v: unknown): v is number => typeof v === 'number' && Number.isFinite(v);
32
+ export class DirectionError extends Error { constructor(readonly code: string, readonly path: string, why: string) { super(`${path}: ${why}; retain the source bytes, correct this record and retry direction check`); } }
33
+ export function directionFail(code: string, path: string, why: string): never { throw new DirectionError(code, path, why); }
34
+ export function directionFinding(e: DirectionError): Finding { return { code: e.code, path: e.path, message: e.message }; }
35
+ export function directionBytes(dir: string, path: string): Buffer { return retainedBytes(dir, path, false); }
36
+ function retainedBytes(dir: string, path: string, boundOutput: boolean): Buffer {
37
+ try {
38
+ if (isAbsolute(path) || path.includes('\\') || path.split('/').some(p => !p || p === '.' || p === '..') || !boundOutput && structurePathIsIgnored(dir, path) && !/^derived\/review\/v[1-9][0-9]*\/out\/check\/build\/skeleton\.model\.json$/.test(path)) throw Error('literal retained POSIX path required');
39
+ let current = realpathSync(dir);
40
+ for (const [i, segment] of path.split('/').entries()) {
41
+ current = join(current, segment); const stat = lstatSync(current);
42
+ if (stat.isSymbolicLink() || (i === path.split('/').length - 1 ? !stat.isFile() : !stat.isDirectory())) throw Error('symlink or nonregular file');
43
+ }
44
+ return readFileSync(current);
45
+ } catch (e) { return directionFail('DIRECTION_FILE', path, e instanceof Error ? e.message : String(e)); }
46
+ }
47
+ /** A rig version's idle render, which lives under ignored outputs/. */
48
+ export const directionIdlePath = (path: string): boolean => /^outputs\/v[1-9][0-9]*\/idle\//.test(path);
49
+ /**
50
+ * Read a rig version's idle render only through the record that binds it (create#297): frames.json through
51
+ * versions[vN].registration.idle, every other idle file through versions[vN].outputs, where vN is the post's rig.
52
+ * The bytes stay where rig-version froze them. A missing file refuses, as the registration check refuses it.
53
+ */
54
+ export function directionIdleBytes(dir: string, project: JsonObject, rig: number, binding: JsonObject): Buffer {
55
+ const path = String(binding.path);
56
+ if (!directionIdlePath(path)) directionFail('DIRECTION_FILE', path, 'literal retained POSIX path required');
57
+ const owner = Number(/^outputs\/v([1-9][0-9]*)\/idle\//.exec(path)?.[1]);
58
+ if (owner !== rig) directionFail('DIRECTION_IDLE_VERSION', path, `idle frames under outputs/v${owner}/ belong to rig v${owner}, not the post's rig v${rig}`);
59
+ const version = objects(project.versions).filter(v => v.kind === 'rig' && v.n === rig);
60
+ const registration = version.length === 1 && isObject(version[0]!.registration) ? version[0]!.registration : undefined;
61
+ const bound = path === `outputs/v${rig}/idle/frames.json` ? [registration?.idle] : asArray(version.length === 1 ? version[0]!.outputs : undefined);
62
+ if (!bound.some(b => isObject(b) && b.path === path && b.sha256 === binding.sha256)) directionFail('DIRECTION_IDLE_UNBOUND', path, `versions[v${rig}] does not bind this path and sha256 (frames.json in registration.idle, other idle files in outputs)`);
63
+ const bytes = retainedBytes(dir, path, true);
64
+ if (directionHash(bytes) !== binding.sha256) directionFail('DIRECTION_IDLE_HASH', path, `bytes differ from the sha256 versions[v${rig}] binds`);
65
+ return bytes;
66
+ }
67
+ export function directionBinding(dir: string, path: string): JsonObject { return { path, sha256: directionHash(directionBytes(dir, path)) }; }
68
+ export function boundDirectionBytes(dir: string, binding: Json | undefined): Buffer {
69
+ if (!closed(binding, ['path', 'sha256']) || typeof binding.path !== 'string' || !hex(binding.sha256)) directionFail('DIRECTION_SCHEMA', 'direction.binding', 'expected {path,sha256}');
70
+ const bytes = directionBytes(dir, binding.path as string);
71
+ if (directionHash(bytes) !== binding.sha256) directionFail('DIRECTION_HASH', String(binding.path), 'bytes differ from declared SHA256');
72
+ return bytes;
73
+ }
74
+ export function directionJson(bytes: Uint8Array, path: string): JsonObject {
75
+ try { const v: Json = JSON.parse(Buffer.from(bytes).toString('utf8')); if (!isObject(v)) throw Error('object required'); return v; }
76
+ catch { return directionFail('DIRECTION_SCHEMA', path, 'JSON object required'); }
77
+ }
78
+ export function directionVersion(project: JsonObject, n: Json | undefined): JsonObject {
79
+ const found = objects(project.versions).filter(v => v.n === n);
80
+ if (!positiveInt(n) || found.length !== 1) directionFail('DIRECTION_VERSION', 'versions', 'post version must exist uniquely');
81
+ return found[0] as JsonObject;
82
+ }
83
+ export function directionContract(project: JsonObject, now: number): JsonObject | null {
84
+ const value = project.direction_contract;
85
+ if (value === undefined) return null;
86
+ if (!closed(value, ['schema', 'adopted_at', 'grandfathered_posts']) || value.schema !== DIRECTION_CONTRACT || typeof value.adopted_at !== 'string' || !/Z$/.test(value.adopted_at) || !Number.isFinite(Date.parse(value.adopted_at)) || Date.parse(value.adopted_at) > now || !Array.isArray(value.grandfathered_posts) || value.grandfathered_posts.some((n,i,a) => !positiveInt(n) || i > 0 && Number(a[i-1]) >= Number(n))) directionFail('DIRECTION_CONTRACT_INVALID', 'direction_contract', 'invalid explicit adoption');
87
+ for (const n of value.grandfathered_posts as Json[]) {
88
+ const v = objects(project.versions).filter(v => v.n === n);
89
+ if (v.length !== 1 || v[0]?.kind !== 'post' || typeof v[0].at !== 'string' || Date.parse(v[0].at) > Date.parse(String(value.adopted_at))) directionFail('DIRECTION_CONTRACT_INVALID', 'direction_contract.grandfathered_posts', 'grandfathered posts must be existing pre-adoption posts');
90
+ }
91
+ return value;
92
+ }
93
+ export function validateDirectionShape(doc: JsonObject, path = 'direction'): void {
94
+ const bad = (why: string): never => directionFail('DIRECTION_SCHEMA', path, why);
95
+ const scene = doc.schema === DIRECTION_SCENE_SPEC;
96
+ if (!closed(doc, ['schema','rig','take','camera','timing','citations', ...(scene ? ['scene'] : [])]) || ![DIRECTION_SPEC, DIRECTION_SCENE_SPEC].includes(String(doc.schema))) bad('expected closed direction@1 or direction@2');
97
+ if (scene && (!closed(doc.scene, ['n', 'path', 'sha256']) || !positiveInt(doc.scene.n) || typeof doc.scene.path !== 'string' || !hex(doc.scene.sha256))) bad('scene requires n, path and raw-byte sha256');
98
+ if (!closed(doc.rig, ['version','model']) || !positiveInt(doc.rig.version) || !closed(doc.rig.model,['path','sha256']) || typeof doc.rig.model.path !== 'string' || !hex(doc.rig.model.sha256)) bad('rig needs version and model file binding');
99
+ if (!closed(doc.take,['duration','loop']) || !finite(doc.take.duration) || doc.take.duration <= 0 || typeof doc.take.loop !== 'boolean') bad('take duration must be positive finite seconds and loop boolean');
100
+ const duration = (doc.take as JsonObject).duration as number;
101
+ for (const section of ['camera','timing'] as const) {
102
+ const value = doc[section];
103
+ if (!closed(value, section === 'camera' ? ['space','keys'] : ['keys']) || section === 'camera' && value.space !== 'rig-world-y-up' || !Array.isArray(value.keys) || value.keys.length < (section === 'camera' ? 1 : 2) || value.keys.length > 256) bad(`${section}: invalid space/keys count`);
104
+ const keys = (value as JsonObject).keys as Json[];
105
+ let previous = -Infinity; let source = -Infinity;
106
+ for (const [i, key] of keys.entries()) {
107
+ if (!closed(key, section === 'camera' ? ['time','box','easing'] : ['time','source_time','easing']) || !finite(key.time) || !['linear','hold','smoothstep'].includes(String(key.easing))) bad(`${section}.keys[${i}]: invalid typed key/easing`);
108
+ const k = key as JsonObject; const t = k.time as number;
109
+ if (t < 0 || t > duration || i === 0 && t !== 0 || section === 'timing' && i === keys.length - 1 && t !== duration) directionFail('DIRECTION_KEY_OUTSIDE_TAKE', `${path}.${section}.keys[${i}]`, 'keys must start at zero, stay inside take; timing ends at duration');
110
+ if (t <= previous) directionFail('DIRECTION_TIME_NON_MONOTONIC', `${path}.${section}.keys[${i}]`, 'take times must strictly increase');
111
+ previous = t;
112
+ if (section === 'camera') {
113
+ const box = k.box;
114
+ if (!closed(box,['x','y','width','height']) || !Object.values(box).every(finite) || Number(box.width) <= 0 || Number(box.height) <= 0) bad('box needs finite x/y and positive width/height');
115
+ } else {
116
+ if (!finite(k.source_time) || k.source_time < 0) bad('source_time must be finite nonnegative seconds');
117
+ if (Number(k.source_time) < source) directionFail('DIRECTION_TIME_NON_MONOTONIC', `${path}.timing.keys[${i}]`, 'source times cannot decrease');
118
+ source = Number(k.source_time);
119
+ }
120
+ }
121
+ }
122
+ if (!closed(doc.citations,['camera','timing'])) bad('citations requires camera/timing');
123
+ for (const [section, guide] of [['camera','camera_depth'],['timing','post_timing']]) {
124
+ const citation = (doc.citations as JsonObject)[section as string];
125
+ if (!(closed(citation,['guide','asks','quote']) && typeof citation.quote === 'string' && citation.quote.length > 0 || closed(citation,['guide','asks','delegated']) && citation.delegated === true) || citation.guide !== guide || !equal(citation.asks,[guide])) bad('citation needs exact guide/ask and quote or delegated:true');
126
+ }
127
+ }
128
+ /** Validate citations through the existing provenance reader, including history and inheritance. */
129
+ export function validateDirectionCitations(dir: string, project: JsonObject, doc: JsonObject, current = false): void {
130
+ const collection = loadCollection(dir); const items = collectItems(project,{collection});
131
+ const refusals: Finding[] = []; const ctx: Ctx = { dir,project,collection,items,refusals,warnings:[],signoffs:[],steps:[],stage:String(project.stage),effectiveStage:String(project.stage),predatesPartsReview:null };
132
+ for (const section of ['camera','timing']) {
133
+ const citation = (doc.citations as JsonObject)[section] as JsonObject;
134
+ const item = items.find(i => i.id === citation.guide);
135
+ const fixedNotApplicable = fixedNotApplicableCamera(section, item, citation, doc);
136
+ if (!fixedNotApplicable) checkEntry(ctx,'post',`direction.citations.${section}`,citation);
137
+ const currentAnswer=item && (item.state.state==='user'||item.state.state==='delegated')?item.state.answer:null;
138
+ if(current && currentAnswer && objects(currentAnswer.asks).some(a=>a.state==='other-pending' || a.state==='delegated' && !isDecision(currentAnswer.agent_decision))) directionFail('DIRECTION_CITATION',`direction.citations.${section}`,'current per-ask selection is pending');
139
+ if(current && item && (item.state.state === 'user' || item.state.state === 'delegated') && item.state.answer.choice !== undefined){
140
+ try{
141
+ validateChoice(dir,project,item,item.state.answer);
142
+ const choice=item.state.answer.choice as JsonObject;const set=optionFile(dir,choice.set).set;const selected=selection(set,choice);
143
+ if(selected.pending.length || selected.autos.length && !isObject(item.state.answer.agent_decision))throw Error('per-ask response is pending');
144
+ }catch(e){directionFail('DIRECTION_CITATION',`direction.citations.${section}`,e instanceof Error?e.message:String(e));}
145
+ }
146
+ if (current && item && (item.state.state === 'delegated' && !item.state.decided || !['user','delegated'].includes(item.state.state) && !fixedNotApplicable)) directionFail('DIRECTION_CITATION', `direction.citations.${section}`, 'answer is not a current user or decided delegation');
147
+ }
148
+ if (refusals[0]) directionFail('DIRECTION_CITATION',refusals[0].path,refusals[0].message);
149
+ if (!current) return;
150
+ const reopens = collectReopens(project,[]);
151
+ const steps = objects(isObject(project.plan) ? project.plan.steps : undefined);
152
+ for (const id of ['camera','timing']) {
153
+ const matches = steps.filter(s => s.id === id && s.phase === 'post');
154
+ const state=items.find(i=>i.id===(id==='camera'?'camera_depth':'post_timing'))?.state;
155
+ const answer=state&&(state.state==='user'||state.state==='delegated'||state.state==='not_applicable')?state.answer:null;
156
+ const times=answer?[answer.at,isObject(answer.agent_decision)?answer.agent_decision.at:undefined,...objects(answer.additions).map(a=>a.at)].filter((v):v is string=>typeof v==='string').map(Date.parse):[];
157
+ if (matches.length !== 1 || !collectSignoffs(project,[]).some(s => s.stage === 'post-interview' && s.checkpoint === null && liveSignoff(reopens,s.stage,s.at) && (s.steps === null || s.steps.includes(id)) && isObject(s.record.step_hashes) && s.record.step_hashes[id] === stepHash(matches[0] as JsonObject) && times.every(t=>Number.isFinite(t)&&t<=s.at))) directionFail('DIRECTION_CITATION',`plan.steps[${id}]`,'live post-interview approval and matching step hash required');
158
+ }
159
+ }
160
+ export function validateDirectionRig(dir: string, project: JsonObject, doc: JsonObject, current: boolean): void {
161
+ const binding = doc.rig as JsonObject;
162
+ const found = objects(project.versions).filter(v => v.n === binding.version && v.kind === 'rig');
163
+ const v = found[0]; const pkg = v?.review_package;
164
+ const model = binding.model as JsonObject;
165
+ const target = `derived/review/v${String(binding.version)}/out/check/build/skeleton.model.json`;
166
+ if (found.length !== 1 || !isObject(pkg) || !objects(pkg.files).some(f => f.path === 'out/check/build/skeleton.model.json' && f.sha256 === model.sha256) || model.path !== target) directionFail('DIRECTION_RIG_UNKNOWN','direction.rig','unknown review-package compiled model identity');
167
+ boundDirectionBytes(dir,model);
168
+ const versions = readVersions(project); const accepted = latestAccepted(versions);
169
+ const source = versions.rigs.find(r => r.n === binding.version);
170
+ if (!source?.accepted || current && (accepted?.n !== binding.version || versions.rigs.some(r => r.live && r.n > Number(binding.version)))) directionFail('DIRECTION_RIG_STALE','direction.rig','current authoring requires latest accepted live rig');
171
+ }
172
+ /** Currentness is shared with scene authoring; historical documents retain their seals. */
173
+ export function validateDirectionScene(dir: string, project: JsonObject, doc: JsonObject, current = false, snapshots?: Map<string, Buffer>): void {
174
+ if (doc.schema !== DIRECTION_SCENE_SPEC) return;
175
+ try {
176
+ const reference = doc.scene as JsonObject;
177
+ const rig = doc.rig as JsonObject;
178
+ // The post's own read of the scene's idle frames comes first: it is the one ignored path direction accepts.
179
+ const committed = committedScene(dir, project, reference, snapshots);
180
+ const frames = isObject(committed.rig) && isObject(committed.rig.animation) ? committed.rig.animation.frames : undefined;
181
+ if (closed(frames, ['path', 'sha256']) && typeof frames.path === 'string' && frames.path.startsWith('outputs/')) directionIdleBytes(dir, project, Number(rig.version), frames);
182
+ const scene = readScene(dir, project, reference, snapshots);
183
+ const sceneRig = scene.rig as JsonObject;
184
+ if (rig.version !== sceneRig.version || !equal(rig.model, sceneRig.model)) directionFail('DIRECTION_SCENE_MISMATCH', 'direction.scene', 'direction rig and model must equal the scene rig and model');
185
+ validateSceneCurrent(project, sceneRig, current, reference);
186
+ } catch (error) {
187
+ if (error instanceof SceneError) directionFail(error.code, error.path, error.message);
188
+ throw error;
189
+ }
190
+ }
191
+ export function requireDirectionScene(doc: JsonObject, at: number, path: string): void {
192
+ if (at >= Date.parse(DIRECTION_SCENE_SINCE) && doc.schema !== DIRECTION_SCENE_SPEC) directionFail('DIRECTION_SCENE_REQUIRED', path, 'run scene write and bind that scene in a direction@2 document');
193
+ }
194
+ export function readDirection(dir: string, project: JsonObject, n: Json | undefined, current = false): JsonObject {
195
+ const v = directionVersion(project,n); const prov = v.provenance;
196
+ if (v.kind !== 'post') directionFail('DIRECTION_VERSION',`versions[v${String(n)}]`,'direction belongs to a post version');
197
+ if (!isObject(prov) || !isObject(prov.direction)) directionFail('DIRECTION_DOCUMENT_REQUIRED',`versions[v${String(n)}].provenance.direction`,'retain a direction document for this post');
198
+ const binding = prov.direction;
199
+ if (binding.path !== directionPath(Number(n))) directionFail('DIRECTION_VERSION',`versions[v${String(n)}].provenance.direction`,'document path must name its post version');
200
+ const doc = directionJson(boundDirectionBytes(dir,binding),String(binding.path)); validateDirectionShape(doc,String(binding.path));
201
+ if (!equal(prov.config,binding) || !objects(v.outputs).some(o=>equal(o,binding))) directionFail('DIRECTION_VERSION',`versions[v${String(n)}].provenance`,'config and declared output must bind the direction document');
202
+ if ((doc.rig as JsonObject).version !== v.rig_version) directionFail('DIRECTION_RIG_STALE',`versions[v${String(n)}].rig_version`,'document and post bind different rigs');
203
+ if (!isObject(prov.sections) || !['camera','timing'].every(section => {const entries=objects((prov.sections as JsonObject)[section]);return entries.length === 1 && equal(entries[0],{entry:section,...((doc.citations as JsonObject)[section] as JsonObject)});})) directionFail('DIRECTION_CITATION',`versions[v${String(n)}].provenance.sections`,'version citations must match authored document citations');
204
+ requireDirectionScene(doc, Date.parse(String(v.at)), `versions[v${String(n)}].provenance.direction`);
205
+ validateDirectionScene(dir, project, doc, current);
206
+ validateDirectionRig(dir,project,doc,current); validateDirectionCitations(dir,project,doc,current);
207
+ return doc;
208
+ }
209
+ export function checkDirections(ctx: {dir:string;project:JsonObject;refusals:Finding[];warnings?:Finding[]}, now: number, selected?: number, currentOverride?: boolean): void {
210
+ try {
211
+ const contract = directionContract(ctx.project, now);
212
+ const posts = objects(ctx.project.versions).filter(v=>v.kind==='post');
213
+ const reopens = collectReopens(ctx.project,[]);
214
+ const latest = Math.max(0,...posts.filter(v=>liveSignoff(reopens,'post',Date.parse(String(v.at)))).map(v=>Number(v.n)));
215
+ for (const v of posts) {
216
+ if (selected !== undefined && v.n !== selected) continue;
217
+ const explicit = isObject(v.provenance) && v.provenance.direction !== undefined;
218
+ if (contract && (contract.grandfathered_posts as Json[]).includes(v.n as number)) continue;
219
+ if (!explicit && !contract && Date.parse(String(v.at)) < Date.parse(DIRECTION_SCENE_SINCE)) continue;
220
+ try {
221
+ if (!explicit && Date.parse(String(v.at)) >= Date.parse(DIRECTION_SCENE_SINCE)) directionFail('DIRECTION_SCENE_REQUIRED', `versions[v${String(v.n)}].provenance.direction`, 'run scene write and retain a direction@2 document');
222
+ const doc = readDirection(ctx.dir,ctx.project,v.n,currentOverride ?? v.n===latest);
223
+ if (doc.schema === DIRECTION_SPEC) ctx.warnings?.push({code:'DIRECTION_SCENE_REQUIRED',path:`versions[v${String(v.n)}].provenance.direction`,message:`versions[v${String(v.n)}].provenance.direction: historical direction@1 predates ${DIRECTION_SCENE_SINCE}; run scene write and author direction@2 for the next post`});
224
+ }
225
+ catch(e) { if (!(e instanceof DirectionError)) throw e; ctx.refusals.push(directionFinding(e)); }
226
+ }
227
+ } catch(e) { if (!(e instanceof DirectionError)) throw e; ctx.refusals.push(directionFinding(e)); }
228
+ }
229
+ export function assertDirectionApproval(dir:string,project:JsonObject,stage:string,now:number,n?:number):void {
230
+ if(stage!=='direction-review')return;
231
+ const latestPost=Math.max(0,...objects(project.versions).filter(v=>v.kind==='post' && liveSignoff(collectReopens(project,[]),'post',Date.parse(String(v.at)))).map(v=>Number(v.n)));
232
+ const refusals:Finding[]=[];checkDirections({dir,project,refusals},now,n??latestPost,true);
233
+ const first=refusals[0];if(first)refuse(first.code,first.message);
234
+ if(n!==undefined){const latest=Math.max(0,...objects(project.versions).filter(v=>v.kind==='post' && liveSignoff(collectReopens(project,[]),'post',Date.parse(String(v.at)))).map(v=>Number(v.n)));if(n!==latest && (project.direction_contract!==undefined || objects(project.versions).some(v=>isObject(v.provenance)&&v.provenance.direction!==undefined)))refuse('DIRECTION_VERSION','versions: accept only the current post version; select the current post');}
235
+ }
236
+ export function directionPostIdentity(dir:string,project:JsonObject,n:Json|undefined):JsonObject {
237
+ const doc=readDirection(dir,project,n);const v=directionVersion(project,n);const prov=v.provenance as JsonObject;
238
+ const scene = doc.scene as JsonObject | undefined;
239
+ return {kind:'post',n:n as number,config:prov.config as JsonObject,model:(doc.rig as JsonObject).model as JsonObject,direction:prov.direction as JsonObject,...(scene ? {scene:{path:scene.path!,sha256:scene.sha256!}} : {})};
240
+ }
241
+ export function validateDirectionIdentity(dir:string,project:JsonObject,identity:JsonObject):void {
242
+ if(!closed(identity,['kind','n','config','model','direction'],['scene']) || identity.kind!=='post' || !equal(identity,directionPostIdentity(dir,project,identity.n)))directionFail('DIRECTION_CORRECTION_OUTCOME','corrections.identity','expected exact bound direction post identity');
243
+ }
244
+ export function patchDirection(project:JsonObject,source:JsonObject,patch:JsonObject):JsonObject {
245
+ if(!closed(patch,['schema','source_post','rig_model_sha256','direction_sha256','replace']) || patch.schema!==DIRECTION_PATCH_SPEC || !positiveInt(patch.source_post) || !hex(patch.rig_model_sha256) || !hex(patch.direction_sha256) || !closed(patch.replace,[],['camera','timing','take']) || Object.keys(patch.replace).length===0)directionFail('DIRECTION_PATCH','direction.patch','expected closed direction-patch/1 and typed whole replacements');
246
+ const v=directionVersion(project,patch.source_post);const prov=v.provenance;
247
+ if(v.kind!=='post' || !isObject(prov) || !isObject(prov.direction) || prov.direction.sha256!==patch.direction_sha256 || ((source.rig as JsonObject).model as JsonObject).sha256!==patch.rig_model_sha256)directionFail('DIRECTION_PATCH','direction.patch','patch base post/document/model do not match');
248
+ const result=structuredClone(source);for(const[k,value]of Object.entries(patch.replace))result[k]=value;
249
+ validateDirectionShape(result);
250
+ if(equal(result,source))directionFail('DIRECTION_PATCH','direction.patch','no-op replacements are refused');
251
+ return result;
252
+ }
253
+ /** Closure revalidates create-owned authoring, never an external producer measurement. */
254
+ export function validateDirectionOutcome(dir:string,project:JsonObject,record:JsonObject,artifact:JsonObject):void {
255
+ if(!closed(artifact,['kind','patch','state','result']) || artifact.kind!=='direction-patch' || !['preview/pending','applied-and-checked'].includes(String(artifact.state)))directionFail('DIRECTION_CORRECTION_OUTCOME','corrections.artifact','invalid direction artifact');
256
+ if(!isObject(record.on))directionFail('DIRECTION_CORRECTION_OUTCOME','corrections.on','post identity required');
257
+ validateDirectionIdentity(dir,project,record.on);
258
+ const patch=directionJson(boundDirectionBytes(dir,artifact.patch),'direction.patch');
259
+ if(patch.source_post!==record.on.n)directionFail('DIRECTION_PATCH','corrections.on','patch source differs from captured post');
260
+ const source=readDirection(dir,project,record.on.n);const expected=patchDirection(project,source,patch);
261
+ if(record.outcome===null){if(artifact.state!=='preview/pending' || artifact.result!==null)directionFail('DIRECTION_CORRECTION_OUTCOME','corrections.artifact','pending record cannot claim a result');return;}
262
+ if(!isObject(record.outcome) || artifact.state!=='applied-and-checked')directionFail('DIRECTION_CORRECTION_OUTCOME','corrections.outcome','closure requires a checked direction result');
263
+ validateDirectionIdentity(dir,project,record.outcome);
264
+ const outcome=record.outcome;const v=directionVersion(project,outcome.n);const origin=v.direction_origin;
265
+ if(Number(outcome.n)<=Number(record.on.n) || !equal(outcome.scene,record.on.scene) || !equal(outcome.model,record.on.model) || !equal(artifact.result,outcome.direction) || equal(record.on.direction,outcome.direction) || !closed(origin,['source_post','patch','result']) || origin.source_post!==record.on.n || !equal(origin.patch,artifact.patch) || !equal(origin.result,artifact.result) || !equal(readDirection(dir,project,outcome.n),expected))directionFail('DIRECTION_CORRECTION_OUTCOME','corrections.outcome','result must be produced from this exact patch/base on the same rig');
266
+ }