rig-create 0.0.0-stage → 1.0.1
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.
- package/LICENSE +21 -0
- package/README.md +169 -2
- package/docs/CHECKS.md +1682 -0
- package/docs/COLLECTIONS.md +337 -0
- package/docs/CRAFT.md +277 -0
- package/docs/INTERVIEW.md +886 -0
- package/docs/LESSONS.md +172 -0
- package/docs/PROJECT.md +2657 -0
- package/docs/SOURCE.md +225 -0
- package/package.json +44 -4
- package/src/agent-bounce.ts +27 -0
- package/src/agent-guide.ts +237 -0
- package/src/amend.ts +193 -0
- package/src/applied-review.ts +104 -0
- package/src/ask-coverage.ts +69 -0
- package/src/assemble-answers.ts +53 -0
- package/src/cg-gates.ts +211 -0
- package/src/check-reads.ts +106 -0
- package/src/check.ts +1059 -0
- package/src/checkpoint-evidence-writer.ts +125 -0
- package/src/checkpoint-evidence.ts +152 -0
- package/src/choice-writers.ts +271 -0
- package/src/choices.ts +378 -0
- package/src/cli.ts +371 -0
- package/src/collection-answer.ts +136 -0
- package/src/collection-binding-reader.ts +496 -0
- package/src/collection-binding.ts +478 -0
- package/src/collection.ts +348 -0
- package/src/config-inputs.ts +155 -0
- package/src/config-lost.ts +135 -0
- package/src/correction-writers.ts +207 -0
- package/src/corrections.ts +685 -0
- package/src/diff-classes.ts +219 -0
- package/src/diff-map.ts +248 -0
- package/src/direction-citation.ts +13 -0
- package/src/direction-writers.ts +119 -0
- package/src/direction.ts +266 -0
- package/src/drafts.ts +363 -0
- package/src/feedback.ts +744 -0
- package/src/figure-mask.ts +143 -0
- package/src/fix-ledger.ts +355 -0
- package/src/init.ts +265 -0
- package/src/inputs.ts +160 -0
- package/src/intake.ts +158 -0
- package/src/interview.ts +53 -0
- package/src/invariants.ts +132 -0
- package/src/job-acts.ts +80 -0
- package/src/job-advance.ts +65 -0
- package/src/job-close.ts +226 -0
- package/src/job-host.ts +529 -0
- package/src/job-outbox.ts +383 -0
- package/src/job-publication.ts +701 -0
- package/src/job-runtime.ts +99 -0
- package/src/job-writer.ts +123 -0
- package/src/meshes-bust.ts +63 -0
- package/src/next.ts +1506 -0
- package/src/overrides.ts +42 -0
- package/src/package-upgrades.ts +32 -0
- package/src/packages-upgrade-check.ts +6 -0
- package/src/packages-upgrade.ts +168 -0
- package/src/parts-act.ts +96 -0
- package/src/parts-check.ts +242 -0
- package/src/parts-review.ts +196 -0
- package/src/parts-sections.ts +98 -0
- package/src/parts-verdict-record.ts +265 -0
- package/src/parts-verdict.ts +33 -0
- package/src/pause.ts +118 -0
- package/src/pins-check.ts +619 -0
- package/src/pins.ts +17 -0
- package/src/plan-bar-amendments.ts +54 -0
- package/src/plan-history.ts +147 -0
- package/src/plan-writers.ts +202 -0
- package/src/plate-receipt.ts +110 -0
- package/src/pre-interview.ts +302 -0
- package/src/prepared-inputs.ts +113 -0
- package/src/progress-writers.ts +181 -0
- package/src/provenance.ts +301 -0
- package/src/record-direction-target.ts +26 -0
- package/src/record-input.ts +18 -0
- package/src/refusal-baseline.ts +55 -0
- package/src/refusal.ts +30 -0
- package/src/reopen-lapses.ts +80 -0
- package/src/reopen.ts +144 -0
- package/src/republish.ts +93 -0
- package/src/restart.ts +141 -0
- package/src/review-act-runtime.ts +16 -0
- package/src/review-act.ts +592 -0
- package/src/review-package.ts +524 -0
- package/src/review-read.ts +238 -0
- package/src/review.ts +432 -0
- package/src/rig-version-date.ts +22 -0
- package/src/rig-version.ts +1047 -0
- package/src/run-record.ts +232 -0
- package/src/scene-authority.ts +410 -0
- package/src/scene-writers.ts +144 -0
- package/src/scene.ts +284 -0
- package/src/setup-painting.ts +46 -0
- package/src/signable.ts +65 -0
- package/src/signoff-answers.ts +76 -0
- package/src/signoff-checkpoint-act.ts +95 -0
- package/src/signoff-target.ts +127 -0
- package/src/signoff.ts +331 -0
- package/src/split-captions.ts +154 -0
- package/src/stage-progress.ts +379 -0
- package/src/stages.ts +148 -0
- package/src/step-hash.ts +19 -0
- package/src/structure-snapshot.ts +109 -0
- package/src/structure.ts +166 -0
- package/src/templates.ts +16 -0
- package/src/waypoints.ts +163 -0
- package/templates/agent-guide.md +108 -0
- package/templates/collection-agent-guide.md +72 -0
- package/templates/collection.json +252 -0
- package/templates/example-chain/AGENTS.md +134 -0
- package/templates/example-chain/CLAUDE.md +3 -0
- package/templates/example-chain/README.md +13 -0
- package/templates/example-chain/chain.json +2869 -0
- package/templates/example-chain/checkpoints/0a-interview-options/AGENTS.md +134 -0
- package/templates/example-chain/checkpoints/0a-interview-options/CLAUDE.md +3 -0
- package/templates/example-chain/checkpoints/0a-interview-options/evidence/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/0a-interview-options/evidence/approval.txt +1 -0
- package/templates/example-chain/checkpoints/0a-interview-options/evidence/interview/rig_type.json +59 -0
- package/templates/example-chain/checkpoints/0a-interview-options/evidence/split-config.json +1 -0
- package/templates/example-chain/checkpoints/0a-interview-options/inputs/painting.png +0 -0
- package/templates/example-chain/checkpoints/0a-interview-options/inputs/references/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/0a-interview-options/package.json +9 -0
- package/templates/example-chain/checkpoints/0a-interview-options/project.json +295 -0
- package/templates/example-chain/checkpoints/0a-interview-options.json +127 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/AGENTS.md +134 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/CLAUDE.md +3 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/evidence/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/evidence/approval.txt +1 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/evidence/interview/assemble.json +309 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/evidence/interview/reference.json +59 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/evidence/interview/rig_type.json +59 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/evidence/interview/seethrough.json +186 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/evidence/split-config.json +1 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/inputs/painting.png +0 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/inputs/references/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/package.json +9 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/project.json +685 -0
- package/templates/example-chain/checkpoints/0b-plan-pending.json +81 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/AGENTS.md +134 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/CLAUDE.md +3 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/evidence/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/evidence/approval.txt +1 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/evidence/interview/assemble.json +309 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/evidence/interview/reference.json +59 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/evidence/interview/rig_type.json +59 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/evidence/interview/seethrough.json +186 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/evidence/parts-check.json +127 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/evidence/split-config.json +1 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/inputs/painting.png +0 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/inputs/references/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/package.json +9 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/project.json +955 -0
- package/templates/example-chain/checkpoints/1-parts-verdict.json +204 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/AGENTS.md +134 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/CLAUDE.md +3 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/approval.txt +1 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/diff-components.json +34 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/interview/assemble.json +309 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/interview/bones.json +190 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/interview/reference.json +59 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/interview/rig_type.json +59 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/interview/seethrough.json +186 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/parts-check.json +127 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/parts-review.json +88 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/review-reads/a12dea02d32508acc99386f894af76a14f1c85f45f804db2aa6b4dea5297973f.json +59 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/split-config.json +1 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/structure.json +30 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/inputs/painting.png +0 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/inputs/references/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/package.json +9 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/project.json +1198 -0
- package/templates/example-chain/checkpoints/2-rigging-answers.json +254 -0
- package/templates/example-chain/checkpoints/3-rig-review/AGENTS.md +134 -0
- package/templates/example-chain/checkpoints/3-rig-review/CLAUDE.md +3 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/approval.txt +1 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/diff-components.json +34 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/assemble.json +309 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/bones.json +190 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/constraints.json +272 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/meshes.json +190 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/motion.json +272 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/reference.json +59 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/rig_type.json +59 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/seethrough.json +186 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/parts-check.json +127 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/parts-review.json +88 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/review-reads/a12dea02d32508acc99386f894af76a14f1c85f45f804db2aa6b4dea5297973f.json +59 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/setup.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/split-config.json +1 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/structure.json +30 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/v1/config.json +88 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/v1/interview-requirements.json +8 -0
- package/templates/example-chain/checkpoints/3-rig-review/inputs/painting.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/inputs/references/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/package.json +9 -0
- package/templates/example-chain/checkpoints/3-rig-review/project.json +1909 -0
- package/templates/example-chain/checkpoints/3-rig-review.json +424 -0
- package/templates/example-chain/checkpoints/4-direction-post/AGENTS.md +134 -0
- package/templates/example-chain/checkpoints/4-direction-post/CLAUDE.md +3 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/approval.txt +1 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/diff-components.json +34 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/assemble.json +309 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/bones.json +190 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/camera_depth.json +102 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/constraints.json +272 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/meshes.json +190 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/motion.json +272 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/post_composition.json +122 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/post_timing.json +102 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/reference.json +59 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/rig_type.json +59 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/seethrough.json +186 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/parts-check.json +127 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/parts-review.json +88 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/review-reads/a12dea02d32508acc99386f894af76a14f1c85f45f804db2aa6b4dea5297973f.json +59 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/setup.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/split-config.json +1 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/structure.json +30 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/v1/config.json +88 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/v1/interview-requirements.json +8 -0
- package/templates/example-chain/checkpoints/4-direction-post/inputs/painting.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/inputs/references/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/package.json +9 -0
- package/templates/example-chain/checkpoints/4-direction-post/project.json +2302 -0
- package/templates/example-chain/checkpoints/4-direction-post.json +456 -0
- package/templates/example-chain/evidence/.gitkeep +0 -0
- package/templates/example-chain/evidence/approval.txt +1 -0
- package/templates/example-chain/evidence/captions.json +101 -0
- package/templates/example-chain/evidence/diff-components.json +34 -0
- package/templates/example-chain/evidence/direction/v2.json +74 -0
- package/templates/example-chain/evidence/direction-input.json +74 -0
- package/templates/example-chain/evidence/interview/assemble.json +309 -0
- package/templates/example-chain/evidence/interview/bones.json +190 -0
- package/templates/example-chain/evidence/interview/camera_depth.json +102 -0
- package/templates/example-chain/evidence/interview/constraints.json +272 -0
- package/templates/example-chain/evidence/interview/meshes.json +190 -0
- package/templates/example-chain/evidence/interview/motion.json +272 -0
- package/templates/example-chain/evidence/interview/post_composition.json +122 -0
- package/templates/example-chain/evidence/interview/post_timing.json +102 -0
- package/templates/example-chain/evidence/interview/reference.json +59 -0
- package/templates/example-chain/evidence/interview/rig_type.json +59 -0
- package/templates/example-chain/evidence/interview/seethrough.json +186 -0
- package/templates/example-chain/evidence/parts-check.json +127 -0
- package/templates/example-chain/evidence/parts-review.json +88 -0
- package/templates/example-chain/evidence/review-reads/a12dea02d32508acc99386f894af76a14f1c85f45f804db2aa6b4dea5297973f.json +59 -0
- package/templates/example-chain/evidence/scene/s1.json +65 -0
- package/templates/example-chain/evidence/scene-citations.json +9 -0
- package/templates/example-chain/evidence/setup.png +0 -0
- package/templates/example-chain/evidence/split-config.json +1 -0
- package/templates/example-chain/evidence/structure.json +30 -0
- package/templates/example-chain/evidence/v1/config.json +88 -0
- package/templates/example-chain/evidence/v1/interview-requirements.json +8 -0
- package/templates/example-chain/inputs/background.png +0 -0
- package/templates/example-chain/inputs/painting.png +0 -0
- package/templates/example-chain/inputs/references/.gitkeep +0 -0
- package/templates/example-chain/package.json +9 -0
- package/templates/example-chain/project.json +2593 -0
- package/templates/example-diff/diff-components.json +71 -0
- package/templates/example-diff/recomposite_rig.png +0 -0
- package/templates/example-direction/approval.txt +1 -0
- package/templates/example-direction/derived/review/v1/out/check/build/rectangle.png +0 -0
- package/templates/example-direction/derived/review/v1/out/check/build/run.json +40 -0
- package/templates/example-direction/derived/review/v1/out/check/build/skeleton.atlas +8 -0
- package/templates/example-direction/derived/review/v1/out/check/build/skeleton.json +73 -0
- package/templates/example-direction/derived/review/v1/out/check/build/skeleton.model.json +195 -0
- package/templates/example-direction/evidence/direction/v2.json +69 -0
- package/templates/example-direction/evidence/direction/v3.json +59 -0
- package/templates/example-direction/evidence/images/rectangle.png +0 -0
- package/templates/example-direction/evidence/input.json +69 -0
- package/templates/example-direction/evidence/motion.json +33 -0
- package/templates/example-direction/evidence/patch.json +23 -0
- package/templates/example-direction/evidence/rig-config.json +55 -0
- package/templates/example-direction/evidence/still.png +0 -0
- package/templates/example-direction/project.json +372 -0
- package/templates/example-direction/reasoning.txt +1 -0
- package/templates/example-direction/words.txt +1 -0
- package/templates/example-draft/README.md +28 -0
- package/templates/example-draft/config.json +71 -0
- package/templates/example-draft/derived/drafts/lantern/config.json +71 -0
- package/templates/example-draft/derived/drafts/lantern/input/painting_in_rig.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/input/parts/background.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/input/parts/eye_l.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/input/parts/eye_r.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/input/parts/face.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/input/parts/lantern.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/input/parts/torso.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/input/parts.json +188 -0
- package/templates/example-draft/derived/drafts/lantern/input/recomposite_rig.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/interview-requirements.json +8 -0
- package/templates/example-draft/derived/drafts/lantern/out/check/build/run.json +40 -0
- package/templates/example-draft/derived/drafts/lantern/out/check/build/skeleton.atlas +28 -0
- package/templates/example-draft/derived/drafts/lantern/out/check/build/skeleton.json +193 -0
- package/templates/example-draft/derived/drafts/lantern/out/check/build/skeleton.model.json +483 -0
- package/templates/example-draft/derived/drafts/lantern/out/check/build/skeleton.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/out/images/background.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/out/images/eye_l.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/out/images/eye_r.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/out/images/face.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/out/images/lantern.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/out/images/torso.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/out/mesh_report.json +1 -0
- package/templates/example-draft/derived/drafts/lantern/out/motion.json +137 -0
- package/templates/example-draft/derived/drafts/lantern/out/rig.json +102 -0
- package/templates/example-draft/derived/drafts/lantern/out/run.json +52 -0
- package/templates/example-draft/derived/parts/rig/painting_in_rig.png +0 -0
- package/templates/example-draft/derived/parts/rig/parts/background.png +0 -0
- package/templates/example-draft/derived/parts/rig/parts/eye_l.png +0 -0
- package/templates/example-draft/derived/parts/rig/parts/eye_r.png +0 -0
- package/templates/example-draft/derived/parts/rig/parts/face.png +0 -0
- package/templates/example-draft/derived/parts/rig/parts/lantern.png +0 -0
- package/templates/example-draft/derived/parts/rig/parts/torso.png +0 -0
- package/templates/example-draft/derived/parts/rig/parts.json +188 -0
- package/templates/example-draft/derived/parts/rig/recomposite_rig.png +0 -0
- package/templates/example-draft/derived/review/v1/config.json +71 -0
- package/templates/example-draft/derived/review/v1/interview-requirements.json +8 -0
- package/templates/example-draft/derived/review/v1/out/check/build/run.json +40 -0
- package/templates/example-draft/derived/review/v1/out/check/build/skeleton.atlas +28 -0
- package/templates/example-draft/derived/review/v1/out/check/build/skeleton.json +193 -0
- package/templates/example-draft/derived/review/v1/out/check/build/skeleton.model.json +483 -0
- package/templates/example-draft/derived/review/v1/out/check/build/skeleton.png +0 -0
- package/templates/example-draft/derived/review/v1/out/parts/background.png +0 -0
- package/templates/example-draft/derived/review/v1/out/parts/eye_l.png +0 -0
- package/templates/example-draft/derived/review/v1/out/parts/eye_r.png +0 -0
- package/templates/example-draft/derived/review/v1/out/parts/face.png +0 -0
- package/templates/example-draft/derived/review/v1/out/parts/lantern.png +0 -0
- package/templates/example-draft/derived/review/v1/out/parts/torso.png +0 -0
- package/templates/example-draft/derived/review/v1/out/parts.json +188 -0
- package/templates/example-draft/derived/review/v1/out/rig/images/background.png +0 -0
- package/templates/example-draft/derived/review/v1/out/rig/images/eye_l.png +0 -0
- package/templates/example-draft/derived/review/v1/out/rig/images/eye_r.png +0 -0
- package/templates/example-draft/derived/review/v1/out/rig/images/face.png +0 -0
- package/templates/example-draft/derived/review/v1/out/rig/images/lantern.png +0 -0
- package/templates/example-draft/derived/review/v1/out/rig/images/torso.png +0 -0
- package/templates/example-draft/derived/review/v1/out/rig/mesh_report.json +1 -0
- package/templates/example-draft/derived/review/v1/out/rig/motion.json +137 -0
- package/templates/example-draft/derived/review/v1/out/rig/rig.json +102 -0
- package/templates/example-draft/derived/review/v1/out/rig/run.json +52 -0
- package/templates/example-draft/derived/review/v2/config.json +71 -0
- package/templates/example-draft/derived/review/v2/interview-requirements.json +8 -0
- package/templates/example-draft/derived/review/v2/out/check/build/run.json +40 -0
- package/templates/example-draft/derived/review/v2/out/check/build/skeleton.atlas +28 -0
- package/templates/example-draft/derived/review/v2/out/check/build/skeleton.json +193 -0
- package/templates/example-draft/derived/review/v2/out/check/build/skeleton.model.json +483 -0
- package/templates/example-draft/derived/review/v2/out/check/build/skeleton.png +0 -0
- package/templates/example-draft/derived/review/v2/out/parts/background.png +0 -0
- package/templates/example-draft/derived/review/v2/out/parts/eye_l.png +0 -0
- package/templates/example-draft/derived/review/v2/out/parts/eye_r.png +0 -0
- package/templates/example-draft/derived/review/v2/out/parts/face.png +0 -0
- package/templates/example-draft/derived/review/v2/out/parts/lantern.png +0 -0
- package/templates/example-draft/derived/review/v2/out/parts/torso.png +0 -0
- package/templates/example-draft/derived/review/v2/out/parts.json +188 -0
- package/templates/example-draft/derived/review/v2/out/rig/images/background.png +0 -0
- package/templates/example-draft/derived/review/v2/out/rig/images/eye_l.png +0 -0
- package/templates/example-draft/derived/review/v2/out/rig/images/eye_r.png +0 -0
- package/templates/example-draft/derived/review/v2/out/rig/images/face.png +0 -0
- package/templates/example-draft/derived/review/v2/out/rig/images/lantern.png +0 -0
- package/templates/example-draft/derived/review/v2/out/rig/images/torso.png +0 -0
- package/templates/example-draft/derived/review/v2/out/rig/mesh_report.json +1 -0
- package/templates/example-draft/derived/review/v2/out/rig/motion.json +137 -0
- package/templates/example-draft/derived/review/v2/out/rig/rig.json +102 -0
- package/templates/example-draft/derived/review/v2/out/rig/run.json +52 -0
- package/templates/example-draft/evidence/diff-components.json +71 -0
- package/templates/example-draft/evidence/direction/v4.json +64 -0
- package/templates/example-draft/evidence/direction-input-v4.json +64 -0
- package/templates/example-draft/evidence/fix-ledger/lantern.json +17 -0
- package/templates/example-draft/evidence/parts-check.json +127 -0
- package/templates/example-draft/evidence/parts-review.json +88 -0
- package/templates/example-draft/evidence/review-reads/4ed0507381809746443021554e012032be5b5f8417da0f2e525e9b6df16e9f05.json +59 -0
- package/templates/example-draft/evidence/scene/s1.json +65 -0
- package/templates/example-draft/evidence/scene-background.png +0 -0
- package/templates/example-draft/evidence/scene-citations.json +9 -0
- package/templates/example-draft/evidence/structure-decisions.json +9 -0
- package/templates/example-draft/evidence/v1/interview-config.json +71 -0
- package/templates/example-draft/evidence/v1/interview-requirements.json +8 -0
- package/templates/example-draft/evidence/v1/review-config.json +71 -0
- package/templates/example-draft/evidence/v2/interview-config.json +71 -0
- package/templates/example-draft/evidence/v2/interview-requirements.json +8 -0
- package/templates/example-draft/evidence/v2/review-config.json +71 -0
- package/templates/example-draft/input/painting_in_rig.png +0 -0
- package/templates/example-draft/input/parts/background.png +0 -0
- package/templates/example-draft/input/parts/eye_l.png +0 -0
- package/templates/example-draft/input/parts/eye_r.png +0 -0
- package/templates/example-draft/input/parts/face.png +0 -0
- package/templates/example-draft/input/parts/lantern.png +0 -0
- package/templates/example-draft/input/parts/torso.png +0 -0
- package/templates/example-draft/input/parts.json +188 -0
- package/templates/example-draft/input/recomposite_rig.png +0 -0
- package/templates/example-draft/inputs/painting.png +0 -0
- package/templates/example-draft/interview-requirements.json +8 -0
- package/templates/example-draft/out/check/build/run.json +40 -0
- package/templates/example-draft/out/check/build/skeleton.atlas +28 -0
- package/templates/example-draft/out/check/build/skeleton.json +193 -0
- package/templates/example-draft/out/check/build/skeleton.model.json +483 -0
- package/templates/example-draft/out/check/build/skeleton.png +0 -0
- package/templates/example-draft/out/images/background.png +0 -0
- package/templates/example-draft/out/images/eye_l.png +0 -0
- package/templates/example-draft/out/images/eye_r.png +0 -0
- package/templates/example-draft/out/images/face.png +0 -0
- package/templates/example-draft/out/images/lantern.png +0 -0
- package/templates/example-draft/out/images/torso.png +0 -0
- package/templates/example-draft/out/mesh_report.json +1 -0
- package/templates/example-draft/out/motion.json +137 -0
- package/templates/example-draft/out/rig.json +102 -0
- package/templates/example-draft/out/run.json +52 -0
- package/templates/example-draft/outputs/v1/out/check/build/run.json +40 -0
- package/templates/example-draft/outputs/v1/out/check/build/skeleton.atlas +28 -0
- package/templates/example-draft/outputs/v1/out/check/build/skeleton.json +193 -0
- package/templates/example-draft/outputs/v1/out/check/build/skeleton.model.json +483 -0
- package/templates/example-draft/outputs/v1/out/check/build/skeleton.png +0 -0
- package/templates/example-draft/outputs/v1/out/painting_in_rig.png +0 -0
- package/templates/example-draft/outputs/v1/out/parts/background.png +0 -0
- package/templates/example-draft/outputs/v1/out/parts/eye_l.png +0 -0
- package/templates/example-draft/outputs/v1/out/parts/eye_r.png +0 -0
- package/templates/example-draft/outputs/v1/out/parts/face.png +0 -0
- package/templates/example-draft/outputs/v1/out/parts/lantern.png +0 -0
- package/templates/example-draft/outputs/v1/out/parts/torso.png +0 -0
- package/templates/example-draft/outputs/v1/out/parts.json +188 -0
- package/templates/example-draft/outputs/v1/out/rig/images/background.png +0 -0
- package/templates/example-draft/outputs/v1/out/rig/images/eye_l.png +0 -0
- package/templates/example-draft/outputs/v1/out/rig/images/eye_r.png +0 -0
- package/templates/example-draft/outputs/v1/out/rig/images/face.png +0 -0
- package/templates/example-draft/outputs/v1/out/rig/images/lantern.png +0 -0
- package/templates/example-draft/outputs/v1/out/rig/images/torso.png +0 -0
- package/templates/example-draft/outputs/v1/out/rig/mesh_report.json +1 -0
- package/templates/example-draft/outputs/v1/out/rig/motion.json +137 -0
- package/templates/example-draft/outputs/v1/out/rig/rig.json +102 -0
- package/templates/example-draft/outputs/v1/out/rig/run.json +52 -0
- package/templates/example-draft/outputs/v2/out/check/build/run.json +40 -0
- package/templates/example-draft/outputs/v2/out/check/build/skeleton.atlas +28 -0
- package/templates/example-draft/outputs/v2/out/check/build/skeleton.json +193 -0
- package/templates/example-draft/outputs/v2/out/check/build/skeleton.model.json +483 -0
- package/templates/example-draft/outputs/v2/out/check/build/skeleton.png +0 -0
- package/templates/example-draft/outputs/v2/out/painting_in_rig.png +0 -0
- package/templates/example-draft/outputs/v2/out/parts/background.png +0 -0
- package/templates/example-draft/outputs/v2/out/parts/eye_l.png +0 -0
- package/templates/example-draft/outputs/v2/out/parts/eye_r.png +0 -0
- package/templates/example-draft/outputs/v2/out/parts/face.png +0 -0
- package/templates/example-draft/outputs/v2/out/parts/lantern.png +0 -0
- package/templates/example-draft/outputs/v2/out/parts/torso.png +0 -0
- package/templates/example-draft/outputs/v2/out/parts.json +188 -0
- package/templates/example-draft/outputs/v2/out/rig/images/background.png +0 -0
- package/templates/example-draft/outputs/v2/out/rig/images/eye_l.png +0 -0
- package/templates/example-draft/outputs/v2/out/rig/images/eye_r.png +0 -0
- package/templates/example-draft/outputs/v2/out/rig/images/face.png +0 -0
- package/templates/example-draft/outputs/v2/out/rig/images/lantern.png +0 -0
- package/templates/example-draft/outputs/v2/out/rig/images/torso.png +0 -0
- package/templates/example-draft/outputs/v2/out/rig/mesh_report.json +1 -0
- package/templates/example-draft/outputs/v2/out/rig/motion.json +137 -0
- package/templates/example-draft/outputs/v2/out/rig/rig.json +102 -0
- package/templates/example-draft/outputs/v2/out/rig/run.json +52 -0
- package/templates/example-interview-choice.json +1068 -0
- package/templates/example-interview-options/constraint.json +376 -0
- package/templates/example-interview-options/example-assemble.json +376 -0
- package/templates/example-interview-options/example-bones.json +190 -0
- package/templates/example-interview-options/example-camera-depth.json +99 -0
- package/templates/example-interview-options/example-constraints.json +272 -0
- package/templates/example-interview-options/example-meshes.json +190 -0
- package/templates/example-interview-options/example-motion.json +272 -0
- package/templates/example-interview-options/example-picks.json +15 -0
- package/templates/example-interview-options/example-post-composition.json +110 -0
- package/templates/example-interview-options/example-post-timing.json +105 -0
- package/templates/example-interview-options/example-reference.json +63 -0
- package/templates/example-interview-options/example-rig-type.json +63 -0
- package/templates/example-interview-options/example-seethrough.json +190 -0
- package/templates/example-interview-options/fullscreen.json +63 -0
- package/templates/example-interview-options/other-explicit.json +63 -0
- package/templates/example-interview-options/other-pending.json +63 -0
- package/templates/example-interview-options/other-picks.json +16 -0
- package/templates/example-interview.md +213 -0
- package/templates/example-invariants/invariants.json +1339 -0
- package/templates/example-prepared/prepared.svg +1 -0
- package/templates/example-prepared/source.svg +1 -0
- package/templates/example-project.json +4259 -0
- package/templates/example-remesh/AGENTS.md +134 -0
- package/templates/example-remesh/CLAUDE.md +3 -0
- package/templates/example-remesh/evidence/.gitkeep +0 -0
- package/templates/example-remesh/evidence/approval.txt +1 -0
- package/templates/example-remesh/evidence/captions.json +101 -0
- package/templates/example-remesh/evidence/diff-components.json +34 -0
- package/templates/example-remesh/evidence/direction/v4.json +74 -0
- package/templates/example-remesh/evidence/direction/v5.json +74 -0
- package/templates/example-remesh/evidence/direction-input-v4.json +74 -0
- package/templates/example-remesh/evidence/direction-input-v5.json +74 -0
- package/templates/example-remesh/evidence/interview/assemble.json +309 -0
- package/templates/example-remesh/evidence/interview/bones.json +190 -0
- package/templates/example-remesh/evidence/interview/camera_depth.json +103 -0
- package/templates/example-remesh/evidence/interview/constraints.json +272 -0
- package/templates/example-remesh/evidence/interview/meshes.json +190 -0
- package/templates/example-remesh/evidence/interview/motion.json +272 -0
- package/templates/example-remesh/evidence/interview/post_composition.json +123 -0
- package/templates/example-remesh/evidence/interview/post_timing.json +103 -0
- package/templates/example-remesh/evidence/interview/reference.json +59 -0
- package/templates/example-remesh/evidence/interview/rig_type.json +59 -0
- package/templates/example-remesh/evidence/interview/seethrough.json +186 -0
- package/templates/example-remesh/evidence/parts-check.json +127 -0
- package/templates/example-remesh/evidence/parts-review.json +88 -0
- package/templates/example-remesh/evidence/reopen.txt +1 -0
- package/templates/example-remesh/evidence/review-reads/6a17db694db96f1b6049a61a017e0c8e66757b982b8851e0187e561cfcf9af68.json +59 -0
- package/templates/example-remesh/evidence/scene/s1.json +69 -0
- package/templates/example-remesh/evidence/scene-citations.json +9 -0
- package/templates/example-remesh/evidence/setup.png +0 -0
- package/templates/example-remesh/evidence/split-config.json +1 -0
- package/templates/example-remesh/evidence/structure.json +30 -0
- package/templates/example-remesh/evidence/v1/registration/at-source.json +44 -0
- package/templates/example-remesh/evidence/v1/registration/citations.json +68 -0
- package/templates/example-remesh/evidence/v1/registration/compile-report.json +368 -0
- package/templates/example-remesh/evidence/v1/registration/config-source.json +88 -0
- package/templates/example-remesh/evidence/v1/registration/config.json +88 -0
- package/templates/example-remesh/evidence/v1/registration/interview-requirements.json +8 -0
- package/templates/example-remesh/evidence/v1/registration/package-lock.json +11 -0
- package/templates/example-remesh/evidence/v1/registration/path-adapter.json +1 -0
- package/templates/example-remesh/evidence/v1/registration/rigc-run-1.json +44 -0
- package/templates/example-remesh/evidence/v2/registration/at-source.json +44 -0
- package/templates/example-remesh/evidence/v2/registration/citations.json +68 -0
- package/templates/example-remesh/evidence/v2/registration/compile-report.json +368 -0
- package/templates/example-remesh/evidence/v2/registration/config-source.json +88 -0
- package/templates/example-remesh/evidence/v2/registration/config.json +88 -0
- package/templates/example-remesh/evidence/v2/registration/interview-requirements.json +8 -0
- package/templates/example-remesh/evidence/v2/registration/package-lock.json +11 -0
- package/templates/example-remesh/evidence/v2/registration/path-adapter.json +1 -0
- package/templates/example-remesh/evidence/v2/registration/rigc-run-1.json +44 -0
- package/templates/example-remesh/evidence/v3/registration/at-source.json +44 -0
- package/templates/example-remesh/evidence/v3/registration/citations.json +68 -0
- package/templates/example-remesh/evidence/v3/registration/compile-report.json +368 -0
- package/templates/example-remesh/evidence/v3/registration/config-source.json +88 -0
- package/templates/example-remesh/evidence/v3/registration/config.json +88 -0
- package/templates/example-remesh/evidence/v3/registration/interview-requirements.json +8 -0
- package/templates/example-remesh/evidence/v3/registration/package-lock.json +11 -0
- package/templates/example-remesh/evidence/v3/registration/path-adapter.json +1 -0
- package/templates/example-remesh/evidence/v3/registration/rigc-run-1.json +44 -0
- package/templates/example-remesh/inputs/background.png +0 -0
- package/templates/example-remesh/inputs/painting.png +0 -0
- package/templates/example-remesh/inputs/references/.gitkeep +0 -0
- package/templates/example-remesh/package.json +9 -0
- package/templates/example-remesh/project.json +3916 -0
- package/templates/example-reopened/project.json +4568 -0
- package/templates/example-review/config.json +1 -0
- package/templates/example-review/out/check/build/skeleton.model.json +1 -0
- package/templates/example-review/out/parts/piece.svg +1 -0
- package/templates/example-review/out/parts.json +1 -0
- package/templates/example-review/out/rig/mesh_report.json +1 -0
- package/templates/example-review/out/rig/motion.json +1 -0
- package/templates/example-review/out/rig/rig.json +1 -0
- package/templates/example-split/captions.json +357 -0
- package/templates/example-split/config.json +215 -0
- package/templates/legacy-example-project.json +1071 -0
- package/templates/project.json +199 -0
- package/templates/shared/conventions.json +23 -0
package/src/direction.ts
ADDED
|
@@ -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
|
+
}
|