@rig-c/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/docs/PROJECT.md
ADDED
|
@@ -0,0 +1,2657 @@
|
|
|
1
|
+
# A project
|
|
2
|
+
|
|
3
|
+
One painting in, one rig (and the takes made from it) out. Each rig is a
|
|
4
|
+
**project**: a folder of its own that holds the painting, the user's direction,
|
|
5
|
+
the plan the user signed, every version shown and every verdict given. Without
|
|
6
|
+
it, the story of a rig is split across a chat thread, a scratch folder and
|
|
7
|
+
someone's memory, and every resume re-reads context and re-guesses.
|
|
8
|
+
|
|
9
|
+
A project's `project.json` is **the only place a decision is recorded**. Chat
|
|
10
|
+
is not a record: a decision made in chat is copied here, verbatim, with who said
|
|
11
|
+
it and when.
|
|
12
|
+
|
|
13
|
+
The field set is **v0** — `"schema": "rig-create/project@0"` — and is expected
|
|
14
|
+
to change while the structure is piloted by hand. The `@0` is there so a reader
|
|
15
|
+
of a record can tell which shape it follows once the shape moves; a validator
|
|
16
|
+
and a migration come with the first shape change, not before. The empty
|
|
17
|
+
skeleton is [../templates/project.json](../templates/project.json); a filled
|
|
18
|
+
record is [../templates/example-project.json](../templates/example-project.json).
|
|
19
|
+
Its sign-offs are fixture sign-offs, not a person's approval; see
|
|
20
|
+
[../templates/example-draft/README.md](../templates/example-draft/README.md).
|
|
21
|
+
|
|
22
|
+
## Layout
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
<project>/
|
|
26
|
+
project.json the decision record: interview, plan, split, stage, sign-offs, versions
|
|
27
|
+
AGENTS.md the agent guide: the order, and which installed docs to read; CLAUDE.md imports it
|
|
28
|
+
inputs/ immutable: the painting, the user's references
|
|
29
|
+
references/
|
|
30
|
+
evidence/v<N>/ what a verdict rested on: crops, sheets, check tables
|
|
31
|
+
derived/ regenerable intermediates (ignored by git)
|
|
32
|
+
outputs/v<N>/ skeleton, atlas, takes (ignored by git)
|
|
33
|
+
scratch/ anything; deletable any time (ignored by git)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
A project is its own git repository, so the history of its decisions is its
|
|
37
|
+
`git log`. A collection member is the exception: it lives in its collection's
|
|
38
|
+
repository, which holds its history ([COLLECTIONS.md § Making one](COLLECTIONS.md#making-one)). `rig-create init <dir>` writes the layout above, a `.gitignore`
|
|
39
|
+
for the untracked folders, a `package.json` pinning the rig-c packages, and a
|
|
40
|
+
first commit.
|
|
41
|
+
|
|
42
|
+
## Data is split by lifetime
|
|
43
|
+
|
|
44
|
+
Rigging derives far more data than it ships. Sorting every file by how long it
|
|
45
|
+
must live keeps the record small and makes "can I delete this?" a question the
|
|
46
|
+
folder answers.
|
|
47
|
+
|
|
48
|
+
| Folder | Lifetime | Tracked | Rule |
|
|
49
|
+
| --- | --- | --- | --- |
|
|
50
|
+
| `project.json` | forever | yes | The only place a decision is recorded. |
|
|
51
|
+
| `inputs/` | forever, never edited | yes | Every file has its sha256 in `project.json` `inputs[]`. A changed input is a new file with a new name, not an edit — otherwise a verdict given on the old file cannot be re-read. |
|
|
52
|
+
| `evidence/v<N>/` | forever | yes | The crop, sheet or table a bounce or an acceptance rested on, for the version it judged. If it is not here, the verdict cannot be re-read later. Keep each file small; a larger review image stays where it is and is listed in `versions[].evidence` with its path and sha256. |
|
|
53
|
+
| `derived/` | until regenerated | no | Depth maps, masks, layers, configs, frames. Every file (or folder) is listed in `derived[]` with the command and the input hashes that made it. Something that cannot be listed that way is either an input or scratch. |
|
|
54
|
+
| `outputs/v<N>/` | until discarded | no | One folder per version that was shown to anyone, frozen when shown. Hashes go into `versions[].outputs`. If the user keeps finals elsewhere, `archive` records where. |
|
|
55
|
+
| `scratch/` | none | no | Anything. Deleting it must never lose information; if it would, the file belongs in `evidence/` or `derived/`. |
|
|
56
|
+
|
|
57
|
+
## Stages
|
|
58
|
+
|
|
59
|
+
`interview` → `plan-approved` → `parts` → `parts-review` → `rigging-interview` → `rigging` →
|
|
60
|
+
`rig-review` → `post-interview` → `post` → `direction-review` → `accepted`,
|
|
61
|
+
plus `paused`.
|
|
62
|
+
|
|
63
|
+
**A stage moves only on a human `signoffs[]` entry**: the stage it closes, who,
|
|
64
|
+
when, and the words used. A plan checkpoint is signed the same way, with
|
|
65
|
+
`checkpoint` naming the plan step. An agent may draft, propose, build and
|
|
66
|
+
measure in any stage; it may not move `stage` forward or pass a checkpoint by
|
|
67
|
+
itself. Reason: the stages exist to put a person's eyes before each piece of
|
|
68
|
+
work that is expensive to redo; an agent that could advance them would be
|
|
69
|
+
grading its own work.
|
|
70
|
+
|
|
71
|
+
A project is *in* a stage while that stage's work happens; the sign-off named
|
|
72
|
+
in the last column ends it and moves the project to the next. The order and
|
|
73
|
+
which stages end on a sign-off are written once, in `src/stages.ts`;
|
|
74
|
+
`rig-create interview --check` refuses a stage moved past a missing sign-off
|
|
75
|
+
([CHECKS.md](CHECKS.md)).
|
|
76
|
+
|
|
77
|
+
| Stage | User step | What happens | Ends with |
|
|
78
|
+
| --- | --- | --- | --- |
|
|
79
|
+
| `interview` | 1 | Framing and source/parts guides (the later rig guides wait for rigging-interview) ([INTERVIEW.md](INTERVIEW.md)): the user's sentences, a delegation ("auto"), or not applicable — never left for the agent to fill. | The user signs `{ "stage": "interview" }`. |
|
|
80
|
+
| `plan-approved` | 1 | The parts steps (`phase: "rig"`) are drafted from the guides, with the agent's decision written on every delegated item. The user sets each step's checkpoint and signs. | `{ "stage": "plan-approved" }`. |
|
|
81
|
+
| `parts` | 1 | The rig steps that make the parts run: `seethrough` and `assemble`. At a step whose checkpoint is on, work stops until `{ "stage": "parts", "checkpoint": "<step id>" }` is signed (the split, [below](#split-approval-is-a-plan-checkpoint)). Only a labelled draft may contain proposed bones/weights for mesh/chest inspection; production rigging remains forbidden. | Every step it runs is `done`, `assemble`'s bar including the parts check passing on the assembled parts. |
|
|
82
|
+
| `parts-review` | 1 | **The parts are reviewed before any production rig is built** ([below](#the-parts-are-reviewed-before-rigging)): the user looks at the assembled parts in rig-review's parts view. A bounce is fixed here, in `parts`. | `{ "stage": "parts-review" }`, signed by a person, carrying the approved parts verdict as `evidence`. |
|
|
83
|
+
| `rigging-interview` | 2 | Ask bones, meshes, constraints and motion while viewing the approved parts and structure; draft their rigging plan. | The human signs `rigging-interview`, binding accepted parts and structure. |
|
|
84
|
+
| `rigging` | 3 | The remaining rig steps run in order (`bones`, `meshes`, `constraints`, `motion`); each config section cites its guide (`versions[].provenance`). At a step whose checkpoint is on, work stops until `{ "stage": "rigging", "checkpoint": "<step id>" }` is signed. It does not start without the `parts-review` sign-off (`PARTS_REVIEW_UNSIGNED`), nor on a verdict that is missing, not approved or no longer the parts on disk (`PARTS_VERDICT_*`). | The last rig step's bar is met. |
|
|
85
|
+
| `rig-review` | 1 → 3 | **First review, on a still frame**: the rig alone, fixed camera, no post-production — seams, cuts, physics and motion played in place. Feedback is recorded verbatim with `on_items`; a bounce makes a new rig version. | The user accepts one rig version: an `accepted` verdict with `review: "rig-review"` on it, resting on its still frame, and `{ "stage": "rig-review" }` signed ([below](#the-rig-review-rests-on-a-still-frame)). |
|
|
86
|
+
| `post-interview` | 2 | The post items (camera and 2.5D, timing, composition) are asked, and the post steps (`phase: "post"`) drafted from them. | The user signs `{ "stage": "post-interview" }` — guides and post steps together. |
|
|
87
|
+
| `post` | 2 | Post-production on the accepted rig version (`versions[].kind: "post"`, `rig_version` naming it); post tooling asks `rig-create handoff` first ([below](#the-hand-off-to-post-production)). | The last post step's bar is met. |
|
|
88
|
+
| `direction-review` | 2 → 3 | **Second review, direction**: camera, depth, timing, framing. Same feedback rule. | The user accepts one post version. |
|
|
89
|
+
| `accepted` | — | Done. If finals go somewhere else, `archive` says where. | — |
|
|
90
|
+
| `paused` | — | Work stopped by a human sign-off, entered and left through `pause` and `resume` ([below](#pausing-and-resuming)). While paused it is checked as the first stage whose sign-off is missing; `resume` returns it to the stage it was paused from. | — |
|
|
91
|
+
|
|
92
|
+
**Why two reviews.** The rig is reviewed first on a still frame with a fixed
|
|
93
|
+
camera — the rig alone — so a seam cannot hide behind a camera move, and a
|
|
94
|
+
depth complaint cannot bounce a correct rig. `post-interview` mirrors
|
|
95
|
+
`interview`: post guides are asked only once the rig they apply to is accepted,
|
|
96
|
+
so they are not asked about a rig that may still change. A rig change after
|
|
97
|
+
`rig-review` means a new rig version and a new first review, and the post
|
|
98
|
+
version built on the old rig is redone on the new one.
|
|
99
|
+
|
|
100
|
+
### Refusals a record already carries
|
|
101
|
+
|
|
102
|
+
A writer validates its whole candidate with `checkProject` and refuses only a
|
|
103
|
+
refusal the record as read did not already carry. The baseline is that check at
|
|
104
|
+
write time and is never stored. Findings match by code and path with
|
|
105
|
+
multiplicity, so a carried code at a new path is new, and the refusal names only
|
|
106
|
+
the new code. `reopen`, `signoff`, `step-status`, `pause`, `resume`, `amend` and
|
|
107
|
+
`draft-rig` and `review` follow this rule; the interview, plan, scene, direction, correction,
|
|
108
|
+
`rig-version`, `version config-lost` and `version outputs-lost` writers already did. Each writer's own
|
|
109
|
+
pre-checks are unchanged (`signoff` still refuses a carried lag, and a carried
|
|
110
|
+
`GUIDE_CHANGED_UNSIGNED` on a step it covers), and `check` still reports every
|
|
111
|
+
carried refusal.
|
|
112
|
+
`advance` still needs 0 refusals: it is the stage boundary. A check that stops
|
|
113
|
+
early (an unreadable record, `SCHEMA_UNKNOWN`, `STAGE_UNKNOWN`) read nothing
|
|
114
|
+
after that point, so it gives no baseline to any writer above: each one refuses
|
|
115
|
+
on such a record, and a pending answer's stored `refusal_baseline` does not
|
|
116
|
+
stand in for it.
|
|
117
|
+
|
|
118
|
+
### Recording forward progress
|
|
119
|
+
|
|
120
|
+
```sh
|
|
121
|
+
rig-create advance <stage> [<project dir>] [--json]
|
|
122
|
+
rig-create advance parts-review --parts-check evidence/parts-check.json --parts <assembled dir>
|
|
123
|
+
rig-create step-status <step> <status> --by <who> [<project dir>] [--note-file <path>] [--json]
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
`signoff` records approval, then `advance` records the move that approval
|
|
127
|
+
authorizes. The move's authority is the person's stage-level signature, so
|
|
128
|
+
`advance` takes no `--by` or words of its own (`ADVANCE_WORDS_REMOVED`): its
|
|
129
|
+
entry names the signature it rests on. The stage level signature closes its
|
|
130
|
+
named stage. `plan-approved` authorizes `parts`
|
|
131
|
+
for both the split-interview order and the legacy order that includes parts.
|
|
132
|
+
Only an already-passed pre-parts project keeps the historical route to rigging.
|
|
133
|
+
The legacy order omits `rigging-interview`; explicit adoption adds it.
|
|
134
|
+
A bar stage advances once every step it runs is done, using the preceding
|
|
135
|
+
stage-level signature as authority. All post items marked not applicable
|
|
136
|
+
allow `post-interview` to advance directly to `accepted`.
|
|
137
|
+
|
|
138
|
+
Arrival at `rigging-interview` or `post-interview` permits only the target
|
|
139
|
+
interview's silent-item `INTERVIEW_INCOMPLETE` findings, counted by code and
|
|
140
|
+
item path, so its answers can be recorded there. The ordinary check still
|
|
141
|
+
reports them, and approval or departure requires the answers.
|
|
142
|
+
|
|
143
|
+
The move from `parts` to `parts-review` also takes `--parts-check <report>
|
|
144
|
+
--parts <assembled dir>`, both project-relative: the `parts-check.json` that
|
|
145
|
+
`rig-parts check-parts` wrote for the assembled parts, retained in the project
|
|
146
|
+
the way the parts verdict is, and the root it was run on. Both are required on
|
|
147
|
+
that move and refused on any other. The report must pass (`exit_code` 0, no
|
|
148
|
+
`refusals`) and match the parts on disk at the move. Its HOLE rows, defect
|
|
149
|
+
classes parts cannot measure yet, are printed one named line each and stored;
|
|
150
|
+
a HOLE is not a pass and does not block (CHECKS.md § Parts-stage check at the
|
|
151
|
+
parts → parts-review move).
|
|
152
|
+
|
|
153
|
+
`advances[]` retains `{ stage, from_stage, at, source?,
|
|
154
|
+
steps_before, signoff, signoffs_before, order, post_not_passed, parts_check? }`,
|
|
155
|
+
with `parts_check { path, sha256, spec, parts, exit_code, holes, reported }` on
|
|
156
|
+
a `parts` → `parts-review` move, copied from the report and bound by its sha256. The clock supplies `at`,
|
|
157
|
+
and `signoff` is the stable `{ stage, checkpoint, at }` identity of the human approval the move rests on.
|
|
158
|
+
Entries written before advance stopped taking words also carry the mover's `by` and UTF-8 `verbatim`;
|
|
159
|
+
they stay valid when both are strings and `by` is not `agent`.
|
|
160
|
+
`steps_before` retains each step id, required phase and original status so a historical bar exit still requires completed work after replanning.
|
|
161
|
+
`signoffs_before` preserves the approval identities present at the move,
|
|
162
|
+
including tied timestamps. Reordering signatures preserves these references. `order` retains `legacy`, `split` or `pre-parts` so later
|
|
163
|
+
adoption preserves historical moves. `post_not_passed` captures whether every
|
|
164
|
+
post item was not applicable at the move. A historical post-interview to
|
|
165
|
+
accepted skip reads this boolean snapshot, so reopening and later applicable
|
|
166
|
+
post answers preserve the earlier authorized move. The current frontier still
|
|
167
|
+
uses current post answers. Forward history grants no reopen cutoff.
|
|
168
|
+
Earlier plan re-signatures do not revoke later approvals. Among live approvals,
|
|
169
|
+
the furthest closing stage supplies the frontier, using its latest signature
|
|
170
|
+
by time and then array position. Reopen and amendment rules still invalidate
|
|
171
|
+
approvals. An earlier re-signature leaves the later live stage target unchanged.
|
|
172
|
+
|
|
173
|
+
From `STAGE_PROGRESS_SINCE`, stage must match the latest stage-changing advance or reopen (or the initial stage without either). A mismatch is dated by the later of that move and the latest live signature at the furthest stage before the current one, so a hand move made before the contract stays a WARN after later sign-offs. An advance retains the stable signature that authorized it at that time, so later same-stage re-signatures preserve that move.
|
|
174
|
+
|
|
175
|
+
The checker pins both lag and skip from `STAGE_PROGRESS_SINCE`, dated by the
|
|
176
|
+
authorizing stage-level signature. Earlier readable dates WARN with the same codes. An unreadable frontier
|
|
177
|
+
date refuses with `STAGE_SIGNOFF_DATE_INVALID`. New advance writes enforce
|
|
178
|
+
lag and skip independently of signature age. Signoff retains its existing conditional, scoped candidate checks.
|
|
179
|
+
Its additional progress guard rejects a pre-existing refusal-level lag and
|
|
180
|
+
new candidate progress refusals. It permits only the lag introduced by its own
|
|
181
|
+
new frontier signature, awaiting the separate advance writer. Legacy WARN lag
|
|
182
|
+
remains permitted at signoff. A target can move only one ordered stage at a
|
|
183
|
+
time, including a permitted bar exit or the declared no-post route.
|
|
184
|
+
|
|
185
|
+
`step-status` runs in the step's execution stage and records one transition
|
|
186
|
+
through `pending` (also the absent status), `in-progress`, `at-checkpoint`,
|
|
187
|
+
then `done`. On an amended project the execution stage may also be the check's
|
|
188
|
+
`effective_stage` (Forward amendments), so the reset steps can be redone while
|
|
189
|
+
the stored stage is retained. On a legacy-order project whose plan was approved before
|
|
190
|
+
`PARTS_REVIEW_SINCE`, rig steps also run in `rigging`. That route grants no
|
|
191
|
+
authority of its own: the writer's candidate check still refuses a started
|
|
192
|
+
step without a live covering stage-level approval (`STEP_RUN_UNAPPROVED`), and
|
|
193
|
+
a `plan-approved` checkpoint signature is refused (`SIGNOFF_UNKNOWN_CHECKPOINT`). Each step's `status_history[]` retains
|
|
194
|
+
`{ from_status, status, by, at, checkpoint_required, signoff }`.
|
|
195
|
+
`--note-file <path>` optionally retains verbatim UTF-8 text as `note` and its byte
|
|
196
|
+
sha256 as `note_sha256`. The readable file must contain 1–1,000 bytes and no
|
|
197
|
+
control characters except newline. Both keys are absent without the flag; the
|
|
198
|
+
check refuses incomplete pairs or mismatched hashes. Notes do not change signed
|
|
199
|
+
step content.
|
|
200
|
+
`checkpoint_required` snapshots the resolved boolean requirement at that event.
|
|
201
|
+
History validates that snapshot when checking a done entry. Reopening and
|
|
202
|
+
replanning a checkpoint preserve earlier completion history. The current
|
|
203
|
+
writer still requires a live checkpoint signature whenever the current
|
|
204
|
+
checkpoint is enabled. Its `signoff` uses the same stable
|
|
205
|
+
identity object or null. A checkpointed `done` references
|
|
206
|
+
the latest matching live human checkpoint signature. Other transitions have
|
|
207
|
+
`signoff` null. Existing status-only history remains readable. Status and its
|
|
208
|
+
history stay outside the signed plan hash. Reopen continues to reset steps.
|
|
209
|
+
History must link: each advance or reopen leaves from the stage the previous
|
|
210
|
+
move reached (starting at `interview`), and each status entry starts from the
|
|
211
|
+
previous entry's status, or `pending` first and after a reopen or amendment
|
|
212
|
+
reset; the last entry matches `status`. A reopen's `steps_before` holds each
|
|
213
|
+
step's chained status at the reopen. Breaks are `STAGE_MOVE_UNLINKED`,
|
|
214
|
+
`STEP_STATUS_UNLINKED` and `REOPEN_STEP_UNLINKED`, dated by
|
|
215
|
+
`PROGRESS_HISTORY_SINCE` (CHECKS.md).
|
|
216
|
+
Both writers reconcile `stage_values` with the applicable order and run the
|
|
217
|
+
same complete `checkProject` candidate validation before writing. Refused
|
|
218
|
+
writes leave `project.json` byte-identical. Neither writer runs a producer.
|
|
219
|
+
|
|
220
|
+
### Pausing and resuming
|
|
221
|
+
|
|
222
|
+
```sh
|
|
223
|
+
rig-create signoff paused --by <who> --verbatim-file words.txt [<project dir>]
|
|
224
|
+
rig-create pause --by <who> [--verbatim-file <file>] [--source <text>] [<project dir>] [--json]
|
|
225
|
+
rig-create resume <stage> --by <who> [--verbatim-file <file>] [--source <text>] [<project dir>] [--json]
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
A person stops the work by signing `paused`; `pause` then sets `stage` to
|
|
229
|
+
`paused`. It needs a human `{ "stage": "paused" }` sign-off dated at or after
|
|
230
|
+
the latest recorded move, so a second pause needs a new signature. `resume`
|
|
231
|
+
sets `stage` back to the stage the project was paused from, and refuses any
|
|
232
|
+
other target (`RESUME_STAGE_MISMATCH`). A project paused by hand before the
|
|
233
|
+
writer existed resumes at the stage its latest recorded move reached. Pausing
|
|
234
|
+
a paused project, resuming one that is not paused, and pausing at `accepted`
|
|
235
|
+
are refused by name. A reopen may also leave `paused`, as before.
|
|
236
|
+
|
|
237
|
+
Both append to `pauses[]`: `{ from_stage, stage: "paused", by, at, verbatim,
|
|
238
|
+
source?, signoff }` for a pause, with `signoff` the stable `{ stage,
|
|
239
|
+
checkpoint, at }` identity of the paused sign-off, and `{ from_stage:
|
|
240
|
+
"paused", stage, by, at, verbatim, source? }` for a resume. The clock
|
|
241
|
+
supplies `at`. The history is kept apart from `advances[]` and `reopens[]`,
|
|
242
|
+
so their linkage (`STAGE_MOVE_UNLINKED`) and the rule that `stage` equals the
|
|
243
|
+
latest recorded move read the same records as before: after a resume the
|
|
244
|
+
latest advance or reopen still names the stage, and a hand move to any other
|
|
245
|
+
stage is still `STAGE_SKIPPED`. The check validates the shape of each entry
|
|
246
|
+
(`PAUSE_MALFORMED`). Both writers run the complete `checkProject` candidate
|
|
247
|
+
validation before writing and replace `project.json` in one rename; refused
|
|
248
|
+
writes leave it byte-identical.
|
|
249
|
+
|
|
250
|
+
### Reopening a passed stage
|
|
251
|
+
|
|
252
|
+
```sh
|
|
253
|
+
rig-create reopen <stage> --by <who> [--verbatim-file <file>] [--source <text>] [<project dir>] [--json]
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
A human may return to a previously reached stage without deleting signatures.
|
|
257
|
+
`reopen` appends `reopens[]` and sets `stage` to its target in the same validated
|
|
258
|
+
write. This backward move is the exception to `signoff`'s record-only writer:
|
|
259
|
+
leaving the old forward stage would require signatures the reopen supersedes.
|
|
260
|
+
The target is in the stage order, excluding `paused` and `accepted`, and no
|
|
261
|
+
later than the furthest stage evidenced by the current stage, historical human
|
|
262
|
+
sign-offs or dated rig/post versions. No producer is run.
|
|
263
|
+
|
|
264
|
+
Each entry is `{ stage, from_stage, by, at, verbatim, source?, steps_before }`. `at` comes
|
|
265
|
+
from the clock; words come unchanged from UTF-8 file or stdin (omitted or `-`).
|
|
266
|
+
`--source` separately records where the words came from. `from_stage` records
|
|
267
|
+
where the project stood when the reopen was written. Each entry's eligibility
|
|
268
|
+
uses its own `from_stage` and historical evidence dated no later than that entry,
|
|
269
|
+
so later backward moves neither erase nor manufacture its reach. An agent cannot sign.
|
|
270
|
+
`steps_before` snapshots `{ id, status }` for every plan step running in the
|
|
271
|
+
target stage or later, preserving an absent status by omitting it. Those steps
|
|
272
|
+
are reset to `pending`; their other fields stay unchanged. Status is outside
|
|
273
|
+
`step_hashes`, so existing plan hashes still verify. The append, resets and
|
|
274
|
+
stage move happen together, or the file is unchanged on refusal. Before writing,
|
|
275
|
+
the command runs the complete project check against the candidate record and
|
|
276
|
+
the existing project files; any refusal leaves the original bytes unchanged.
|
|
277
|
+
|
|
278
|
+
For each stage, a sign-off is live only if dated strictly after every reopen
|
|
279
|
+
whose target is that stage or earlier. Checkpoints follow the same rule;
|
|
280
|
+
undated entries cannot outrank a reopen. A second reopen advances that cutoff
|
|
281
|
+
without restoring signatures invalidated by an earlier, wider reopen. All
|
|
282
|
+
signatures remain in place, structurally checked as history. Advancing again
|
|
283
|
+
requires live signatures under the existing stage/checkpoint rules. A newly
|
|
284
|
+
run step without them is still refused; there is no execution exemption.
|
|
285
|
+
|
|
286
|
+
Accepted historical rig versions remain accepted as history. If the reopen
|
|
287
|
+
covers rig-review, a live hand-off requires a rig version built after it;
|
|
288
|
+
a new verdict on an old build cannot revive that build. Historical post
|
|
289
|
+
versions keep their original basis; new post work requires the live rig.
|
|
290
|
+
Reopening only post work preserves the unaffected rig acceptance.
|
|
291
|
+
|
|
292
|
+
### Forward amendments
|
|
293
|
+
|
|
294
|
+
Raise a correction against an artifact and its owning stage with the public
|
|
295
|
+
writer. The stage is chosen explicitly by the person recording the correction.
|
|
296
|
+
|
|
297
|
+
```sh
|
|
298
|
+
rig-create amend parts --kind part --target panel --change inputs/replacement.svg \
|
|
299
|
+
--by owner --verbatim-file correction.txt
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
`amendments[]` retains `{ target, by, at, verbatim, source?, changes }`.
|
|
303
|
+
`target` contains `{ stage, kind, id }`, where `kind` is `part`, `config-field`,
|
|
304
|
+
`motion-track` or `interview-answer`. `id` names the artifact, config pointer,
|
|
305
|
+
track or answer path. Any ordered non-terminal stage may own a target.
|
|
306
|
+
`changes` contains `{ path, sha256 }` for every repeated `--change` file.
|
|
307
|
+
The writer reads and hashes those files under the project. These are declared
|
|
308
|
+
new inputs retained as historical byte identities. Checking history validates
|
|
309
|
+
their shape and does not require the mutable working files to retain those
|
|
310
|
+
bytes forever. `at` comes from the clock, and UTF-8 words are retained unchanged.
|
|
311
|
+
An agent signer is refused. Optional `--source` records the origin separately.
|
|
312
|
+
|
|
313
|
+
An amendment invalidates every approval at its owning stage or later, using
|
|
314
|
+
the same stage/time cutoff as `reopen`. The reason for each is exactly
|
|
315
|
+
`no binding proves independence`, with the fixed gap row below. Upstream means
|
|
316
|
+
every ordered stage preceding the amended stage. Its live approvals remain
|
|
317
|
+
live and its plan-step states are preserved. There is no additional unrelated
|
|
318
|
+
category. A downstream approval cannot stay live on this contract.
|
|
319
|
+
|
|
320
|
+
| Approval kind | Missing proof from the step-0 census |
|
|
321
|
+
| --- | --- |
|
|
322
|
+
| `interview` | G1, approved answer and input set |
|
|
323
|
+
| `plan-approved` | G2, answer contents and consumed inputs |
|
|
324
|
+
| `parts` checkpoint | G3, executed inputs and checked outputs |
|
|
325
|
+
| `parts-review` | G5, comparison inputs and rendered-stack input binding |
|
|
326
|
+
| `rigging-interview` | G2, answer contents and consumed inputs |
|
|
327
|
+
| `rigging` checkpoint | G3, executed inputs and checked outputs |
|
|
328
|
+
| `rig-review` signature or accepted verdict | G7, review target and evidence |
|
|
329
|
+
| `post-interview` | G2, answer contents and consumed inputs |
|
|
330
|
+
| `post` checkpoint | G3, executed inputs and checked outputs |
|
|
331
|
+
| `direction-review` signature or accepted verdict | G7, review target and evidence |
|
|
332
|
+
| An explicitly recorded `accepted` stage signature | G9, acceptance input closure |
|
|
333
|
+
|
|
334
|
+
The fixed table is `AMENDMENT_APPROVAL_GAPS` in `src/amend.ts`. The remaining
|
|
335
|
+
census rows cover producer derivation (G4), approval granularity (G6), field
|
|
336
|
+
consumption (G8), build closure (G9) and opaque producer resolvers (G10).
|
|
337
|
+
This table identifies missing proof for the approval kind. It does not assert
|
|
338
|
+
that one gap alone suffices to prove independence.
|
|
339
|
+
|
|
340
|
+
The extension point is `keepByBinding()` and the report field is
|
|
341
|
+
`keep_by_binding`. It ships as an empty list. Later binding cards may place an
|
|
342
|
+
approval there with the binding that proves its independence. Until then the
|
|
343
|
+
amendment's stage and downstream approvals all lapse.
|
|
344
|
+
|
|
345
|
+
`interview --check` adds `amendments[]` only on amended records. Each entry
|
|
346
|
+
names the target, every invalidated signature and accepted verdict by record
|
|
347
|
+
path, its stage/checkpoint, reason and gap, the still-live upstream approvals,
|
|
348
|
+
and the empty keep-by-binding list. A new signature remains a separate act
|
|
349
|
+
from the lapsed historical one. Multiple amendments and reopens accumulate
|
|
350
|
+
cutoffs, so a narrower amendment cannot revive an earlier invalidation.
|
|
351
|
+
|
|
352
|
+
The writer leaves `project.stage` in place, sets plan steps running at or after
|
|
353
|
+
the amended stage to `pending`, and retains all previous approvals and versions.
|
|
354
|
+
The check's `effective_stage` is the first unfinished stage while re-approval
|
|
355
|
+
is pending, bounded by the stored stage. While it differs from the stored
|
|
356
|
+
stage, the check still refuses a stage that differs from its latest recorded
|
|
357
|
+
move (`STAGE_SKIPPED`, same dating), but skips the signature window
|
|
358
|
+
(`STAGE_LAGGING` and the window's `STAGE_SKIPPED`). The stored stage stays
|
|
359
|
+
while its approvals lapse, so the window would refuse every amended record,
|
|
360
|
+
the amend writer's own candidate included. Judging the window against
|
|
361
|
+
`effective_stage` instead fails too: that stage passes unfinished bars before
|
|
362
|
+
the amended stage, which the window stops at. Re-sign the lapsed approvals and meet
|
|
363
|
+
the affected steps' bars in order. `step-status` runs a reset step when its
|
|
364
|
+
execution stage is the stored stage or the `effective_stage`, which it reads from
|
|
365
|
+
the same complete check, so the bars are met in order without moving `stage`.
|
|
366
|
+
`effective_stage` comes from the recorded signatures and step statuses; it is not
|
|
367
|
+
stored, because each re-signature or finished bar moves it. Once every lapsed
|
|
368
|
+
approval is re-signed and every bar is met, `effective_stage` equals the stored
|
|
369
|
+
stage again and the signature window applies as before; no `advance` is needed
|
|
370
|
+
when the stored stage was already reached. Existing upstream approvals need no re-sign.
|
|
371
|
+
A rig covered by the cutoff needs a new build and acceptance before handoff.
|
|
372
|
+
The writer runs the same complete candidate check before writing. Any refusal
|
|
373
|
+
leaves `project.json` byte-identical. Existing records and `reopen` output retain
|
|
374
|
+
their existing shape when no amendment is present.
|
|
375
|
+
|
|
376
|
+
### The parts are reviewed before rigging
|
|
377
|
+
|
|
378
|
+
`parts-review [<project>] --draft <id> --from-review-cli --by <name>
|
|
379
|
+
[--json] -- <rig-review parts arguments>` records an independent parts verdict
|
|
380
|
+
through `rig-review parts <arguments> --format json`. Put create's flags before
|
|
381
|
+
`--`. The remaining arguments, including `--verdict`, are opaque strings passed
|
|
382
|
+
to review in the project directory. They must be project-relative and stay
|
|
383
|
+
inside the project. create reads only stdout and never opens the saved verdict
|
|
384
|
+
named by those arguments. A failed CLI call refuses with its diagnostic.
|
|
385
|
+
|
|
386
|
+
Exact stdout bytes are retained at `evidence/review-reads/<sha256>.json`.
|
|
387
|
+
The ordered `review_acts` list holds both routes. A CLI receipt uses schema
|
|
388
|
+
`rig-create/parts-verdict-cli@1`, `kind: "parts-verdict"`, `route: "cli"`,
|
|
389
|
+
`draft_id`, `argv`, `evidence: {path, sha256}`, `tool: {name, version}`,
|
|
390
|
+
`status`, `flagged`, `noted`, `by` and `at`. Names retain their response order
|
|
391
|
+
and spelling. Notes remain verbatim in the retained response. `--by` identifies
|
|
392
|
+
the human because the CLI response supplies no reviewer. Approved, pending and
|
|
393
|
+
changes-requested responses can all be recorded. Recording identical bytes
|
|
394
|
+
for the same draft again preserves the record byte for byte. Different bytes
|
|
395
|
+
append, and the last receipt for that draft is current across both routes.
|
|
396
|
+
A current changes-requested receipt refuses `signoff --draft` until a newer
|
|
397
|
+
approved receipt exists. This does not itself sign or move a stage.
|
|
398
|
+
|
|
399
|
+
The writer and check compare the CLI source hash multiset with the draft's
|
|
400
|
+
recorded parts and output hashes. Every reviewed hash must be recorded and
|
|
401
|
+
every part must be reviewed. Outputs absent from the response are optional.
|
|
402
|
+
The painting declared by the draft's hash-bound `parts.json` is excluded on
|
|
403
|
+
both sides, including repeated occurrences of its hash. Response paths are
|
|
404
|
+
never resolved. Check reads the retained stdout, verifies its hash and copied
|
|
405
|
+
receipt fields, and repeats this draft binding without querying the saved
|
|
406
|
+
verdict. Signatures before `PARTS_VERDICT_LATEST_SINCE` warn for a current
|
|
407
|
+
changes-requested receipt, while signatures from that date refuse.
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
A defect in the parts — a part with nothing painted under its occluder, a
|
|
411
|
+
boundary between two parts nobody composed — is cheapest to fix before a bone
|
|
412
|
+
is placed on it. Found at `rig-review`, every build in between was spent on
|
|
413
|
+
parts that were already wrong, and the fix goes back through the split and
|
|
414
|
+
every step after it. So the steps that make the parts (`seethrough`,
|
|
415
|
+
`assemble`) run in their own stage, `parts`, and a person looks at the
|
|
416
|
+
assembled parts before `rigging` starts.
|
|
417
|
+
|
|
418
|
+
- **`parts` ends on its bar**: the parts check's gates pass on the assembled
|
|
419
|
+
parts, recorded as `assemble`'s bar met (`status: "done"`). Coverage under
|
|
420
|
+
occluders joins this bar from rig-c/parts#998 once it ships; until then the
|
|
421
|
+
bar is the parts check as it is. A project past `parts` with one of its steps
|
|
422
|
+
not `done` is refused (`PARTS_BAR_UNMET`). The move to `parts-review` binds
|
|
423
|
+
the passing `rig-parts check-parts` report for the assembled parts
|
|
424
|
+
(`advances[].parts_check`, § Recording forward progress); its HOLE lines
|
|
425
|
+
reach the person at `parts-review` and are recorded on the move.
|
|
426
|
+
- **`parts-review` ends on a human sign-off**, `{ "stage": "parts-review",
|
|
427
|
+
"checkpoint": null }`, given in rig-review's parts view. Without it the stage
|
|
428
|
+
does not move to `rigging`, and no `rigging` step runs
|
|
429
|
+
(`PARTS_REVIEW_UNSIGNED`). An agent's entry does not count.
|
|
430
|
+
- **The sign-off carries the verdict it rests on**: `"evidence": { "kind":
|
|
431
|
+
"parts-verdict", "path": "<the file>", "sha256": "<its sha256>" }`, where
|
|
432
|
+
`path` is relative to the project and names the file rig-review's parts view
|
|
433
|
+
wrote (`rig-review parts`; by default `parts-review.json` beside
|
|
434
|
+
`parts.json`, or wherever `--verdict` put it). Write it to a tracked path,
|
|
435
|
+
`--verdict evidence/parts-review.json`, so the sign-off's evidence survives a
|
|
436
|
+
clone: `derived/`, where the parts are assembled, is not in git. The check
|
|
437
|
+
reads exactly that file, never a default location. Rigging is refused, each case by name
|
|
438
|
+
([CHECKS.md § Refusals](CHECKS.md#refusals)), unless the verdict is the
|
|
439
|
+
`rig-review-parts-verdict/1` or `rig-review-parts-verdict/2` schema in `parts` mode (an `atlas` verdict is
|
|
440
|
+
informational and never gates), its `status` is `approved`, and every file
|
|
441
|
+
in its `source.files[]` is on disk with the bytes and sha256 it was reviewed
|
|
442
|
+
with. A part added, removed or repainted after the sign-off is a new review:
|
|
443
|
+
the user reviews again and signs again, with the new verdict as evidence.
|
|
444
|
+
The latest `parts-review` sign-off is the one read. **The parts themselves
|
|
445
|
+
must be on disk to rig**: on a fresh clone, re-assemble them before rigging
|
|
446
|
+
continues. The verdict gates rigging only until a rig version is accepted at
|
|
447
|
+
`rig-review`: from then on it is not read, and a part changed after that is a
|
|
448
|
+
new rig version, refused as `RIG_VERSION_UNACCEPTED` until it is reviewed.
|
|
449
|
+
|
|
450
|
+
Both schemas take the same approval, mode, evidence SHA-256, source path,
|
|
451
|
+
byte-count and source SHA-256 checks. The schema allowlist is closed: `/3`
|
|
452
|
+
and any other value refuse `PARTS_VERDICT_SCHEMA_UNKNOWN`. The signoff writer
|
|
453
|
+
calls this reader before writing; the difference-map reader receives only
|
|
454
|
+
its successfully checked `parts.json` path. These readers do not need new
|
|
455
|
+
fields (`tests/parts-verdict-v2.test.ts`).
|
|
456
|
+
|
|
457
|
+
**Fields added by `/2`.** The schema-final review writer at
|
|
458
|
+
[`07c07d254725c97cfc63aa7b028cb8ef8ccf9045`](https://github.com/rig-c/review/blob/07c07d254725c97cfc63aa7b028cb8ef8ccf9045/src/parts-view.ts)
|
|
459
|
+
adds `comments[]`; its complete nested shape comes from
|
|
460
|
+
[`PartsComment`](https://github.com/rig-c/review/blob/07c07d254725c97cfc63aa7b028cb8ef8ccf9045/src/parts-comment.ts).
|
|
461
|
+
All fields below are explicitly ignored **for create's gate**, retained
|
|
462
|
+
unchanged in the verdict file and covered by `evidence.sha256`. create
|
|
463
|
+
neither copies nor rewrites them into `project.json`, and does not open crop
|
|
464
|
+
paths or require the review machine's crop state. Review owns comment
|
|
465
|
+
validation and crop generation; an approved verdict may include comments.
|
|
466
|
+
|
|
467
|
+
| New field paths | Why create does not interpret them |
|
|
468
|
+
| --- | --- |
|
|
469
|
+
| `comments` (including an empty list), `comments[].schema`, `.id`, `.summary` | Reviewer annotations, not a second approval status. The gate reads the producer's top-level `status`. |
|
|
470
|
+
| `comments[].part`, `.imageHash`, `.sourceHash` | Comment-specific identities owned by review. The gate binds all original source bytes through `source.files[]` and `source.sha256`, regardless of comments. |
|
|
471
|
+
| `comments[].imageRegion.{x,y,width,height}`, `.rigRegion.{x,y,width,height}` | Native and placed annotation coordinates; create consumes no region measurement and must not rederive it. |
|
|
472
|
+
| `comments[].view.camera.zoom`, `.camera.center.{x,y}`, `.camera.viewport.{width,height}` | Primary viewport camera, used to replay the review view, not to approve parts. All camera paths in this row are under `comments[].view`. |
|
|
473
|
+
| `comments[].view.cameraSync`, `.referenceCamera` (nullable), `.referenceCamera.zoom`, `.referenceCamera.center.{x,y}`, `.referenceCamera.viewport.{width,height}` | Reference viewport replay and synchronization; no camera consumer in this gate. |
|
|
474
|
+
| `comments[].view.{background,alpha,footprints,mesh}` | Display toggles, not part outcomes or producer measurements. |
|
|
475
|
+
| `comments[].crop.{path,sha256,width,height,png}` | Viewport crop metadata and inline PNG, owned by review; not the assembly source inventory. |
|
|
476
|
+
| `comments[].nativeCrop` (nullable in the type), `.nativeCrop.{path,sha256,width,height}` | Review-generated native crop evidence, not a replacement for the original part image. create binds the original bytes without regenerating a crop. |
|
|
477
|
+
|
|
478
|
+
`tests/fixtures/rig-review-parts-verdict-2/README.md` records the exact producer
|
|
479
|
+
head and reproducible command. Its empty-comment and pointed-comment verdicts
|
|
480
|
+
are unedited writer output. `tests/parts-verdict-v2.test.ts` exercises both
|
|
481
|
+
through `signoffCommand` then `checkProject`, tests comment-byte binding and
|
|
482
|
+
operation without external crop state, and applies source/mode refusal
|
|
483
|
+
controls to both schema versions. Existing `/1` fixture bytes are unchanged.
|
|
484
|
+
|
|
485
|
+
- **The project record carries an agent-authored whole-figure difference map**
|
|
486
|
+
at `project.json.diff_map`, while the `parts-review` sign-off records only the
|
|
487
|
+
person's approval (`draft_id`, `evidence`, `structure`, `verbatim`).
|
|
488
|
+
Generate the report with the installed `rig-parts diff-components --out` on
|
|
489
|
+
the assembled stack and the painting in the same native canvas, then record
|
|
490
|
+
the agent's component classifications with `rig-create diff-classes`. create
|
|
491
|
+
reads the report and binds its exact bytes by SHA-256.
|
|
492
|
+
|
|
493
|
+
```json
|
|
494
|
+
"diff_map": {
|
|
495
|
+
"by": "agent",
|
|
496
|
+
"at": "2026-11-09T00:00:50.000Z",
|
|
497
|
+
"report": { "path": "evidence/diff-components.json", "sha256": "<report sha256>" },
|
|
498
|
+
"components": [ { "id": "<report component id>", "status": "in-painting", "why": "<what was observed>" } ]
|
|
499
|
+
}
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
```sh
|
|
503
|
+
rig-create diff-classes --diff-report evidence/diff-components.json --component 'p10-n3=in-painting:the painting contains this edge' --by agent
|
|
504
|
+
rig-create signoff parts-review --by user --draft <id> --structure-file evidence/structure-decisions.json --verbatim-file approval.txt
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
The `diff-classes` writer hashes the report and validates the entire map
|
|
508
|
+
before recording anything (`by` must be `agent`, refused otherwise with
|
|
509
|
+
`DIFF_MAP_NOT_AGENT`). Repeat `--component <id>=<status>:<why>` for every
|
|
510
|
+
component. The first `=` and first following `:` separate fields, so `why` may
|
|
511
|
+
contain colons. Every report id must appear exactly once, with no extra ids.
|
|
512
|
+
Status is `in-painting`, `fixed` or `left`, and every status requires a
|
|
513
|
+
nonempty `why`. For a large report, run `rig-create diff-classes --diff-report <path>`
|
|
514
|
+
without `--triage-file`, `--component` or `--by` first: in read-only mode it
|
|
515
|
+
prints JSON rows with deterministic ids, derived keys, member ids and counts,
|
|
516
|
+
pixel-count ranges and uncovered-fraction ranges. Keys use the exact sorted
|
|
517
|
+
border-part set and coverage band. Covered and uncovered bands have fractions
|
|
518
|
+
0 and 1; mixed bands are [0,0.25), [0.25,0.50), [0.50,0.75), [0.75,1).
|
|
519
|
+
This caps mixed spread below 0.25 without combining different border sets.
|
|
520
|
+
create groups producer fields; it never measures image pixels.
|
|
521
|
+
|
|
522
|
+
Supply `--triage-file triage.json` to `diff-classes --diff-report <path> --by agent`
|
|
523
|
+
instead of component flags:
|
|
524
|
+
`{"classes":{"<derived id>":{"status":"left","why":"covered edge observed in the painting"}},"components":{}}`.
|
|
525
|
+
Each decision contains only status and why; the writer derives the key and full
|
|
526
|
+
member list. A class reason must name at least one exact border part or its
|
|
527
|
+
coverage band (for example `mixed:0.25-0.50`). Inspect the images before deciding.
|
|
528
|
+
Components needing individual judgment can instead use the `components` map,
|
|
529
|
+
keyed by report id with the same status/why fields. Do not overlap decisions.
|
|
530
|
+
The file cannot be combined with component flags and requires a diff report.
|
|
531
|
+
|
|
532
|
+
The optional `diff_map.classes` list retains `{id, key, status, why, members}`;
|
|
533
|
+
each expanded component also retains `class_id`. Check re-derives each full
|
|
534
|
+
class and requires disjoint members and identical expanded status and why.
|
|
535
|
+
Per-component records remain compatible and do not acquire class requirements.
|
|
536
|
+
|
|
537
|
+
A report with no components needs only `--diff-report <path> --by agent`. Its spec must be
|
|
538
|
+
`rig-parts-diff-components/1`, `definition.floor_px` at most 2 and
|
|
539
|
+
`definition.threshold` at most 40. The stack is derived from the verdict's
|
|
540
|
+
covered `parts.json`, resolved relative to that verdict (or the latest draft
|
|
541
|
+
before sign-off). For its directory D, build writes `D/recomposite_rig.png`,
|
|
542
|
+
while standalone assemble writes `D/../render/recomposite_rig.png` only when D
|
|
543
|
+
is named `rig`. Exactly one candidate must exist and hash to the report's
|
|
544
|
+
`stack.sha256`. Neither or both candidates refuse rigging. create never
|
|
545
|
+
computes the map or runs the producer's `--verify`. This uses the latest
|
|
546
|
+
sign-off and the same rigging gate and acceptance boundary as the parts
|
|
547
|
+
verdict above. From `DIFF_MAP_SINCE` (2026-11-06T00:00:00Z), a missing map
|
|
548
|
+
refuses writing the sign-off and rigging. An earlier sign-off without one gets
|
|
549
|
+
only `DIFF_MAP_PREDATES`. From `DIFF_MAP_AGENT_SINCE` (2026-11-09T00:00:00Z),
|
|
550
|
+
`signoff parts-review` refuses `--diff-report`, `--triage-file` and
|
|
551
|
+
`--component` (`SIGNOFF_DIFF_MAP_REMOVED`), and a `parts-review` sign-off dated
|
|
552
|
+
from that boundary carrying `diff_map` is refused (`SIGNOFF_DIFF_MAP_REMOVED`);
|
|
553
|
+
an earlier `parts-review` sign-off carrying `diff_map` emits a
|
|
554
|
+
`DIFF_MAP_ON_SIGNOFF_LEGACY` warning and its map is still checked in full.
|
|
555
|
+
|
|
556
|
+
The filled example's report and stack are synthetic, with two listed
|
|
557
|
+
components. `bun scripts/generate-example-diff.ts <fresh scratch directory>`
|
|
558
|
+
regenerates them through the installed parts CLI and the `diff-classes` and
|
|
559
|
+
`signoff` writers. Add `--check` to reproduce the shipped report, stack and
|
|
560
|
+
inline record bytes.
|
|
561
|
+
- **A project that passed `plan-approved` before these two stages existed**
|
|
562
|
+
(its first `plan-approved` sign-off is dated before 2026-11-04, the
|
|
563
|
+
`PARTS_REVIEW_SINCE` in `src/stages.ts`) is not given a sign-off nobody made.
|
|
564
|
+
The check reports it as a warning naming the project
|
|
565
|
+
(`PARTS_REVIEW_PREDATES_STAGE`): its parts were not reviewed before rigging.
|
|
566
|
+
Its `assemble` checkpoint, signed then as `rigging`, still counts. The date
|
|
567
|
+
is read from that sign-off because signing `plan-approved` is the dated,
|
|
568
|
+
human act that moved the project past where the two stages now stand.
|
|
569
|
+
|
|
570
|
+
### The rig review rests on a still frame
|
|
571
|
+
|
|
572
|
+
The rig is accepted at `rig-review` by **one verdict on one version**: a
|
|
573
|
+
human `verdicts[]` entry with `"review": "rig-review"` and `"verdict":
|
|
574
|
+
"accepted"` on a `kind: "rig"` version. The `{ "stage": "rig-review" }`
|
|
575
|
+
sign-off moves the stage; the verdict names the version. They are the same
|
|
576
|
+
act and are written in the same turn (the sign-off has no version field
|
|
577
|
+
because the verdict already carries `by`, `at` and `verbatim` on the version
|
|
578
|
+
it is about — a second copy would be a second place for one decision).
|
|
579
|
+
|
|
580
|
+
That acceptance rests on a **still-frame record** in the same version's
|
|
581
|
+
`evidence[]`:
|
|
582
|
+
|
|
583
|
+
```json
|
|
584
|
+
{ "kind": "still", "path": "evidence/v2/still-frame.png", "sha256": "…", "camera": "fixed", "frame": 2, "what": "the rig at the fixed camera, posed 2 s into the loop" }
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
| Field | Holds |
|
|
588
|
+
| --- | --- |
|
|
589
|
+
| `kind` | `"still"` — what marks this entry as the rig review's frame; other evidence entries may leave `kind` out |
|
|
590
|
+
| `path`, `sha256` | the image under `evidence/v<N>/` and its 64-hex sha256 |
|
|
591
|
+
| `camera` | `"fixed"`: no camera move, no parallax, no post-production; any other value is not a still frame |
|
|
592
|
+
| `frame` | `"setup"` for the renderer's setup pose, or the time in seconds into the motion the rig is posed at. `0` is the motion's start, which is not the setup pose when the idle rests off it (a breath track whose `base` equals its `amp` passes through setup mid-loop) |
|
|
593
|
+
| `what` | what it shows, in words |
|
|
594
|
+
|
|
595
|
+
This repository does not render the still: rig-c/core and rig-c/review render,
|
|
596
|
+
the `review <version> --from-review <actId>` writer fetches the
|
|
597
|
+
raw act bytes and PNG through the live job API. The writer preserves the act bytes under
|
|
598
|
+
`evidence/v<N>/`, binds them in `review_acts` by sha256 and verifies the PNG
|
|
599
|
+
before recording it. Missing or mismatched PNGs refuse without changing
|
|
600
|
+
`project.json`. Numeric frames record the animation name in `what`;
|
|
601
|
+
no new record field or dated contract is introduced. An acceptance with no such record is refused
|
|
602
|
+
(`RIG_ACCEPTED_WITHOUT_STILL`, [CHECKS.md](CHECKS.md)); a bounce needs none to
|
|
603
|
+
be recorded, though what it rested on still goes in `evidence/`.
|
|
604
|
+
|
|
605
|
+
**A rig changed after `rig-review`** is a new rig version, and the project is
|
|
606
|
+
back at `rig-review` for it: past that stage, the latest rig version must carry
|
|
607
|
+
its own acceptance (`RIG_VERSION_UNACCEPTED`). Once it is accepted, the post
|
|
608
|
+
version built on the old rig is redone on the new one — the current (latest)
|
|
609
|
+
post version naming an older accepted rig is refused (`POST_ON_SUPERSEDED_RIG`);
|
|
610
|
+
earlier post versions are history and are left as they are. This is a refusal,
|
|
611
|
+
not a warning: a direction review of a take built on a rig the user has since
|
|
612
|
+
replaced would accept something that no longer matches the rig.
|
|
613
|
+
|
|
614
|
+
### The hand-off to post-production
|
|
615
|
+
|
|
616
|
+
```
|
|
617
|
+
rig-create handoff [<project dir>] [--rig <n>] [--json]
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
Post-production tooling runs this before it runs. It exits `0` and prints the
|
|
621
|
+
one rig version post work may run on — the latest accepted rig version, with
|
|
622
|
+
its acceptance and its still frame — and exits `1` with a named refusal when
|
|
623
|
+
there is none: no `rig-review` sign-off (`RIG_REVIEW_UNSIGNED`), no accepted
|
|
624
|
+
rig version or a newer rig version not yet reviewed (`RIG_VERSION_UNACCEPTED`),
|
|
625
|
+
an acceptance with no still frame (`RIG_ACCEPTED_WITHOUT_STILL`). With
|
|
626
|
+
`--rig <n>` it also refuses when `<n>` is not that version
|
|
627
|
+
(`POST_ON_UNACCEPTED_RIG`, `POST_ON_SUPERSEDED_RIG`). The `n` it prints is what
|
|
628
|
+
the post version's `rig_version` holds. It reads the record and writes nothing.
|
|
629
|
+
|
|
630
|
+
**When post is not passed.** If every post item is answered *not applicable* in
|
|
631
|
+
`post-interview` (a collection member whose composition belongs to the
|
|
632
|
+
collection, for example), the sign-off of `post-interview` says so and the
|
|
633
|
+
project moves from there to `accepted`.
|
|
634
|
+
|
|
635
|
+
### Split approval is a plan checkpoint
|
|
636
|
+
|
|
637
|
+
The split — which parts the painting becomes — is the decision most often sent
|
|
638
|
+
back, so it is shown to the user as a labelled image before the rest of the rig
|
|
639
|
+
is built. It is a **checkpoint on the `assemble` step**, not a stage of its own:
|
|
640
|
+
a stage and a checkpoint are the same act (a human signature before the next
|
|
641
|
+
piece of work runs), so keeping both would record one approval in two places,
|
|
642
|
+
and the plan lets the user stop at any waypoint, not only the split. The split's
|
|
643
|
+
data (proposal image under `evidence/split/`, parts, labels) lives in `split`;
|
|
644
|
+
its approval is the `signoffs[]` entry with `"stage": "parts", "checkpoint": "assemble"`. This checkpoint has no
|
|
645
|
+
default: the user turns it on or off, or delegates it, like every other.
|
|
646
|
+
|
|
647
|
+
### Generated split captions
|
|
648
|
+
|
|
649
|
+
```sh
|
|
650
|
+
rig-create split-captions [<project dir|project.json>] [--config <file>]
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
The command prints `rig-create/split-captions@0` JSON to stdout. A directory
|
|
654
|
+
uses its `project.json`, and the default is the current directory. Config
|
|
655
|
+
paths are relative to the project record's directory, defaulting to
|
|
656
|
+
`config.json`. Redirect the result into the proposal's evidence directory.
|
|
657
|
+
|
|
658
|
+
`inputs` records the project and config paths and SHA-256 of their exact bytes.
|
|
659
|
+
`config[]` carries each top-level setting's `path`, structured `value` and
|
|
660
|
+
machine-generated `text` (`path = JSON(value)`), including the assembly scale,
|
|
661
|
+
plan, limb routes and bone bindings. `parts[]` preserves `split.parts` order
|
|
662
|
+
and carries each `name`, `label` and generated `text` (`JSON(name) = JSON(label)`).
|
|
663
|
+
A sheet renderer can use those strings directly. Every caption comes from the
|
|
664
|
+
input data. Config annotations (`note`, `*_note`, `x-*`) are omitted, preserving
|
|
665
|
+
exact-name map keys, including limb names, turn depth part names and depth
|
|
666
|
+
source-layer names. `split.parts.note` is excluded.
|
|
667
|
+
|
|
668
|
+
The installed parts parser validates complete rig configs through its full
|
|
669
|
+
config door, and incomplete configs through its early `assemble` door, which
|
|
670
|
+
checks the split's settings and reads bones with declared limbs. The output
|
|
671
|
+
records declarations. Pixel assembly, rendered scale and motion acceptance
|
|
672
|
+
require their own evidence. Exit 1 names an unreadable or malformed input,
|
|
673
|
+
unknown project schema, malformed or duplicate split name, invalid label, or
|
|
674
|
+
parts config refusal. Usage errors exit 2. Refusals produce no caption stdout.
|
|
675
|
+
|
|
676
|
+
The worked list is [example-split/captions.json](../templates/example-split/captions.json),
|
|
677
|
+
generated with the existing filled record and a synthetic config. Regenerate it
|
|
678
|
+
from the repository root with
|
|
679
|
+
|
|
680
|
+
```sh
|
|
681
|
+
bun src/cli.ts split-captions templates/example-project.json --config example-split/config.json > templates/example-split/captions.json
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
[example-split/config.json](../templates/example-split/config.json) supplies
|
|
685
|
+
synthetic config bytes because the filled record's historical config paths
|
|
686
|
+
have no corresponding files. Its scale, coordinates, source tags, bindings and
|
|
687
|
+
empty motion tracks are test inputs. The painting, split layers and rig output
|
|
688
|
+
remain unverified by this caption fixture.
|
|
689
|
+
|
|
690
|
+
## The plan
|
|
691
|
+
|
|
692
|
+
The plan lives in `project.json` `plan`, not in a separate file: `project.json`
|
|
693
|
+
is already the only place a decision is recorded and the first thing a resuming
|
|
694
|
+
agent reads, and a second file is one a resume can skip.
|
|
695
|
+
|
|
696
|
+
```json
|
|
697
|
+
"plan": {
|
|
698
|
+
"drafted_by": "agent",
|
|
699
|
+
"drafted_at": "2026-11-10T15:30:00Z",
|
|
700
|
+
"steps": [
|
|
701
|
+
{
|
|
702
|
+
"id": "assemble",
|
|
703
|
+
"phase": "rig",
|
|
704
|
+
"order": 2,
|
|
705
|
+
"does": "Turn layers into parts, in draw order; propose the split as an image, one label per part",
|
|
706
|
+
"produces": "config assemble; split.proposal_image, split.parts[]",
|
|
707
|
+
"rests_on": ["assemble", "constraints"],
|
|
708
|
+
"bar": "Every part the assemble guide names exists; every part has one label; the setup-pose recomposite matches the painting",
|
|
709
|
+
"checkpoint_proposed": true,
|
|
710
|
+
"checkpoint": { "delegated": false, "by": "user", "at": "2026-11-10T16:00:00Z", "verbatim": "yes, show me", "value": true },
|
|
711
|
+
"status": "pending"
|
|
712
|
+
}
|
|
713
|
+
],
|
|
714
|
+
"replaced": [
|
|
715
|
+
{
|
|
716
|
+
"step": {
|
|
717
|
+
"id": "camera",
|
|
718
|
+
"phase": "post",
|
|
719
|
+
"order": 1,
|
|
720
|
+
"does": "Keep a fixed frame.",
|
|
721
|
+
"produces": "A fixed camera track.",
|
|
722
|
+
"rests_on": ["camera_depth"],
|
|
723
|
+
"bar": "The approved rig stays within the frame.",
|
|
724
|
+
"checkpoint_proposed": false,
|
|
725
|
+
"checkpoint": null,
|
|
726
|
+
"status": "pending"
|
|
727
|
+
},
|
|
728
|
+
"sha256": "1f42b6a62120e479ea30aeb08244d5c35b8b4c3ec803f079489047d9e8f4bd61",
|
|
729
|
+
"action": "removed",
|
|
730
|
+
"at": "2026-11-10T15:30:00Z",
|
|
731
|
+
"by": "agent"
|
|
732
|
+
}
|
|
733
|
+
]
|
|
734
|
+
}
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
Draft steps with `rig-create plan add|revise|remove <id> [<project dir>]
|
|
738
|
+
--by <drafter>`. Its `--help` lists their field flags. Draft dates follow the
|
|
739
|
+
existing [phase-date contract](#explicit-adoption-of-the-split-interview),
|
|
740
|
+
using both previous and resulting approval ownership on revision, with
|
|
741
|
+
`drafted_by` updated only alongside `drafted_at`. Every write refuses
|
|
742
|
+
additional checker findings counted by code and path before changing the file. Reopen live covering plan
|
|
743
|
+
approvals first. Completed work, including completion retained by reopen,
|
|
744
|
+
requires removal and a new id. Revise/remove append the full previous step
|
|
745
|
+
to optional `replaced[]`, with its existing `stepHash`, action, ISO date and
|
|
746
|
+
drafter. Entries retain write order, nondecreasing dates and unique
|
|
747
|
+
`step.id` / `at` identities. Reopened signatures may resolve hashes and
|
|
748
|
+
checkpoints against history. Live approvals bind current steps.
|
|
749
|
+
|
|
750
|
+
- **Rig steps follow the waypoints**: one step per waypoint the plan passes, in
|
|
751
|
+
pipeline order, with the step's `id` equal to the waypoint's. The last rig
|
|
752
|
+
step also renders the still-frame check for `rig-review`. **Post steps**
|
|
753
|
+
(`phase: "post"`) are added in `post-interview`, one per post item passed.
|
|
754
|
+
- **`rests_on` names the answers a step is built on** — waypoint ids, framing
|
|
755
|
+
ids (`rig_type`, `reference`) or post item ids; at least one. A step no answer
|
|
756
|
+
covers is not allowed: ask for the sentence first
|
|
757
|
+
([INTERVIEW.md § Questions outside this set](INTERVIEW.md#questions-outside-this-set)).
|
|
758
|
+
A step resting on a delegation is legal; the delegation is read from the
|
|
759
|
+
guide, not restated here.
|
|
760
|
+
- **`checkpoint`** takes the answer shape from INTERVIEW.md: the user's `true` /
|
|
761
|
+
`false` as `value`, or delegated. The drafter may fill `checkpoint_proposed`;
|
|
762
|
+
only the user (or a delegation) fills `checkpoint`.
|
|
763
|
+
- **`bar`** is what *done* is measured by for that step, written before the
|
|
764
|
+
step runs. A sentence that names a part, effect or extent is a bar line
|
|
765
|
+
([INTERVIEW.md § Direction is taken in sentences](INTERVIEW.md#direction-is-taken-in-sentences)).
|
|
766
|
+
- **`status`**: `pending` → `in-progress` → `at-checkpoint` (waiting for a
|
|
767
|
+
sign-off) → `done`.
|
|
768
|
+
- A changed guide — including one added from polish feedback — sends every step
|
|
769
|
+
that rests on it back for a new sign-off by its step-specific approval stage before it runs.
|
|
770
|
+
- **Provenance**: each version built from a config records, per config
|
|
771
|
+
section, the guide sentence or delegation each entry follows
|
|
772
|
+
(`versions[].provenance`, [INTERVIEW.md § Provenance](INTERVIEW.md#provenance-every-config-section-cites-its-guide)).
|
|
773
|
+
An entry with no citation is removed or cited before the version is shown.
|
|
774
|
+
|
|
775
|
+
## Recording a sign-off
|
|
776
|
+
|
|
777
|
+
```sh
|
|
778
|
+
rig-create signoff <stage> --from-review <actId> [<project dir>] [--json]
|
|
779
|
+
rig-create signoff <stage> --by <who> [--steps <id,id,...>] [--verbatim-file <file>] [<project dir>] [--json]
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
The `signoff` command appends `signoffs[]` and leaves `project.stage` unchanged. `at`
|
|
783
|
+
comes from the clock. There is no `--at` option. The user's UTF-8 words come
|
|
784
|
+
from the file, or stdin when omitted or `-`, preserving BOM, spaces, CRLFs and
|
|
785
|
+
final newlines. Invalid UTF-8 is refused because a JSON string cannot retain
|
|
786
|
+
its original bytes.
|
|
787
|
+
|
|
788
|
+
`--from-review <actId>` without `--checkpoint` is the review tool's stage
|
|
789
|
+
sign-off route (with `--checkpoint <id>` it records a passed checkpoint act
|
|
790
|
+
instead; see CHECKS.md). It fetches the person's
|
|
791
|
+
finalized `signoff` act through the live job writer binding, the way
|
|
792
|
+
`review --from-review` and `interview-answer --from-review` do, and validates
|
|
793
|
+
it with the same decoder the check runs on the retained act bytes. The act
|
|
794
|
+
supplies the stage (it must be the one named), the words, the person (`by` is
|
|
795
|
+
`user` for the job owner, `delegate` otherwise) and `at`; `--by`,
|
|
796
|
+
`--verbatim-file` and `--steps` are refused with it on both routes
|
|
797
|
+
(`SIGNOFF_OPTION_INVALID`). For `plan-approved`, `rigging-interview` and
|
|
798
|
+
`post-interview` the act's `source.plan` must list the current `plan.steps`
|
|
799
|
+
ids and step hashes in order, or the write refuses `REVIEW_ACT_SOURCE_STALE`;
|
|
800
|
+
coverage and `step_hashes` then follow the writer's usual rules. For
|
|
801
|
+
`rig-review` and `direction-review` the act's `source.selector` names the
|
|
802
|
+
version the person was shown (a `rig` version, or a `post` version), and that
|
|
803
|
+
version is the signature's `target`; `--version` may only repeat it. A missing
|
|
804
|
+
or other-kind selector, or a different `--version`, refuses
|
|
805
|
+
`REVIEW_ACT_TARGET_MISMATCH`. The signature
|
|
806
|
+
names its act in `source` (`review act <jobId>/<actId>`), and `review_acts[]`
|
|
807
|
+
retains `{ kind: "signoff", jobId, actId, stage, bytes, sha256, version_hash }`.
|
|
808
|
+
Replaying the same act returns the recorded signature unchanged.
|
|
809
|
+
|
|
810
|
+
For new-order `plan-approved`, coverage is the parts steps; `rigging-interview` covers the remaining rig steps. Legacy `plan-approved` covers every rig step. For `post-interview`, it is
|
|
811
|
+
every post step. `--steps` narrows coverage within that phase and stores the
|
|
812
|
+
covered ids in `steps[]`. Execution stages accept `--checkpoint <step id>`
|
|
813
|
+
when that step runs in the
|
|
814
|
+
named stage and its recorded checkpoint is enabled. This records
|
|
815
|
+
`checkpoint: <step id>`, without `steps` or `step_hashes`. It cannot be combined
|
|
816
|
+
with `--steps`.
|
|
817
|
+
|
|
818
|
+
`parts-review` requires `--evidence <verdict path>`. The command stores
|
|
819
|
+
`{ kind: "parts-verdict", path, sha256 }`, resolving filesystem links,
|
|
820
|
+
normalising the path to project-relative POSIX form and hashing the file. The existing parts-verdict reader validates
|
|
821
|
+
approval, shape and source freshness before anything is written. Other stages
|
|
822
|
+
refuse `--evidence`.
|
|
823
|
+
|
|
824
|
+
Only `plan-approved`, `rigging-interview` and `post-interview` accept `--steps`. Stage movement
|
|
825
|
+
remains a separate act read by the check.
|
|
826
|
+
|
|
827
|
+
Each covered step needs a boolean `checkpoint_proposed`. A null checkpoint
|
|
828
|
+
becomes `{ delegated: false, by, at, verbatim, value: checkpoint_proposed }`.
|
|
829
|
+
Existing user answers and decided delegations stay as recorded. An undecided
|
|
830
|
+
delegation, malformed checkpoint or unknown step refuses the whole command
|
|
831
|
+
before the file is written.
|
|
832
|
+
|
|
833
|
+
Each plan signature also records `step_hashes`, mapping covered step ids to
|
|
834
|
+
SHA-256 of UTF-8 JSON with object keys recursively sorted and array order
|
|
835
|
+
preserved. The fields are `id`, `phase`, `order`, `does`, `produces`,
|
|
836
|
+
`rests_on`, `bar`, `checkpoint_proposed` and `checkpoint`, after filling the
|
|
837
|
+
checkpoint. Absent fields are omitted. `status` and other fields are excluded.
|
|
838
|
+
The shared implementation is `src/step-hash.ts`.
|
|
839
|
+
|
|
840
|
+
The four answer approvals (`interview`, `plan-approved`, `rigging-interview`,
|
|
841
|
+
`post-interview`) also record `answer_hashes`, mapping item ids to SHA-256 of
|
|
842
|
+
UTF-8 `JSON.stringify(sorted({ raw, resolved }))`: the local answer object
|
|
843
|
+
and the answer resolved through collection inheritance (or null). Object keys
|
|
844
|
+
are recursively sorted; array order is preserved. Both objects exclude
|
|
845
|
+
`history`, `prompts`, `config`, `text`, `source` and `required_for`.
|
|
846
|
+
The interview approves answers and delegations without `agent_decision`; plan
|
|
847
|
+
approvals also bind the decisions their covered steps rest on.
|
|
848
|
+
The writer captures every currently answered interview item, or the union of
|
|
849
|
+
`rests_on` in its covered steps; an unanswered step basis refuses the write.
|
|
850
|
+
An honestly empty set records `{}`. When every post item is N/A and there are
|
|
851
|
+
no post steps, the user still signs post-interview with `steps: []` and bindings
|
|
852
|
+
for every N/A post answer. Interview completeness requires a map,
|
|
853
|
+
without comparing its keys to today's answered items or their dates.
|
|
854
|
+
The latest live interview signature replaces the whole earlier interview map,
|
|
855
|
+
so omitted unanswered items lose approval and earlier interview bindings are superseded.
|
|
856
|
+
Plan-stage signatures supersede earlier bindings per item within the same stage,
|
|
857
|
+
while completeness still follows each signature's own covered steps.
|
|
858
|
+
Only live approvals are checked, using the same reopen and amendment liveness
|
|
859
|
+
as other approvals. A changed or removed bound item refuses
|
|
860
|
+
`SIGNOFF_ANSWERS_STALE`; an absent or incomplete map refuses
|
|
861
|
+
`SIGNOFF_ANSWERS_MISSING` from `SIGNOFF_ANSWERS_SINCE = 2026-11-06T00:00:00Z`,
|
|
862
|
+
and earlier signatures receive one `SIGNOFF_ANSWERS_MISSING_LEGACY` warning.
|
|
863
|
+
These bindings do not preserve approvals during amendments: G2 lapse behavior
|
|
864
|
+
and `keep_by_binding: []` remain unchanged until G8 is implemented.
|
|
865
|
+
|
|
866
|
+
|
|
867
|
+
`review` accepts `--verbatim-file <file>` (or `-` for stdin) instead of
|
|
868
|
+
`--verbatim`, and `--at <timestamp>` instead of the clock. Repeatable
|
|
869
|
+
`--answers-feedback <version>:<verdict-index>` appends references to the
|
|
870
|
+
reviewed version's `answers_feedback`. Each reference must identify an
|
|
871
|
+
existing verdict of an earlier version and must not duplicate an existing or
|
|
872
|
+
new reference. Both writers refuse `by: agent` case-insensitively.
|
|
873
|
+
|
|
874
|
+
## Versions
|
|
875
|
+
|
|
876
|
+
A reopen preserves every version and verdict; a rebuild is a new numbered
|
|
877
|
+
version, never an overwrite of an accepted historical build.
|
|
878
|
+
|
|
879
|
+
After a human bounce, `next` reads check's `FEEDBACK_OPEN` finding and names
|
|
880
|
+
the agent rebuild instead of asking for another verdict or sign-off on the
|
|
881
|
+
bounced version. `rig-version` and `direction write` / `direction patch`
|
|
882
|
+
accept repeatable `--answers <version>:<verdict-index>` options, recording
|
|
883
|
+
those entries in the new version's `answers_feedback`. Each entry must name
|
|
884
|
+
an earlier human bounced verdict and must occur only once. Without the needed
|
|
885
|
+
entries the writer refuses `FEEDBACK_UNANSWERED`, leaving `project.json`
|
|
886
|
+
byte-identical. Existing historical references and `review --answers-feedback`
|
|
887
|
+
keep their earlier target rules: any existing verdict on an earlier version.
|
|
888
|
+
After rebuilding, `next` requests the new version's review; no stage or
|
|
889
|
+
human approval is supplied by answering feedback.
|
|
890
|
+
|
|
891
|
+
A rig version's provenance config, review package and accepted parts must identify the same build.
|
|
892
|
+
|
|
893
|
+
Every build shown to anyone is a `versions[]` entry, numbered in order across
|
|
894
|
+
both kinds:
|
|
895
|
+
|
|
896
|
+
| Field | Holds |
|
|
897
|
+
| --- | --- |
|
|
898
|
+
| `n` | the version number, `1, 2, …` |
|
|
899
|
+
| `original_n` | on pre-interview versions only, the unchanged source id as a number, string or `null`; non-null ids are unique |
|
|
900
|
+
| `config_lost` | on pre-interview versions only, `{ note, source }` with nonempty strings when the build config did not survive; cannot accompany `provenance.config` or authorize post work |
|
|
901
|
+
| `outputs_lost` | on pre-interview versions only, `{ note, source, recorded? }` with nonempty strings and missing `recorded: [{ path, sha256 }]` bindings disjoint from surviving `outputs` (or `{ note, source }` beside `outputs: []`) when frozen outputs did not survive; cannot authorize post work |
|
|
902
|
+
| `kind` | `rig` or `post` |
|
|
903
|
+
| `rig_version` | for a post version, the `n` of the accepted rig it is built on (accepted before the post version's `at`); `null` for a rig version |
|
|
904
|
+
| `at`, `built_by`, `built_with` | when, which agent or tool, and the package versions used (`{ "@rig-c/parts": "…", "@rig-c/core": "…" }`) |
|
|
905
|
+
| `review_origin` | null for a build made without review feedback, otherwise the applied-round record below |
|
|
906
|
+
| `answers_feedback` | the verdicts this version answers: `[{ "version", "verdict" }]` (version number and index into its `verdicts[]`); empty for a first version |
|
|
907
|
+
| `changed` | what changed from the previous version of the same kind, in a sentence |
|
|
908
|
+
| `outputs` | `outputs/v<N>/` files with sha256 and size, frozen when shown |
|
|
909
|
+
| `evidence` | `evidence/v<N>/` files with sha256 and what each shows; on a rig version accepted at `rig-review`, one is the still-frame record (`kind: "still"`, `camera: "fixed"`, `frame`) |
|
|
910
|
+
| `provenance` | the config this version was built from and, per section, its citations |
|
|
911
|
+
| `verdicts` | what people said: `by`, `at`, `review`, `verdict` (`accepted`, `bounced`, `provisional`), `verbatim`, `source`, `on_items[]` |
|
|
912
|
+
|
|
913
|
+
A provenance citation may add `asks: ["<ask id>", …]`, naming the
|
|
914
|
+
canonical asks its guide records in `answer.asks`. For example,
|
|
915
|
+
`{ "entry": "torso", "guide": "meshes", "asks": ["bend"], "quote": "The coat is one piece" }`
|
|
916
|
+
cites the user-answered bend ask. A delegated density citation uses
|
|
917
|
+
`{ "entry": "density", "guide": "meshes", "asks": ["density"], "delegated": true }`
|
|
918
|
+
and needs that answer's decided `agent_decision`. Each named ask's coverage
|
|
919
|
+
and supporting quote or decision must come from the same answer, including
|
|
920
|
+
answers preserved in history. A user ask requires a quote and cannot be
|
|
921
|
+
claimed as delegated. Missing ids on a guide with per-ask coverage warn.
|
|
922
|
+
|
|
923
|
+
A verdict item with `answer_was: "delegated"` may add `ask: "<ask id>"`.
|
|
924
|
+
The ask must be recorded as delegated in a current or historical answer.
|
|
925
|
+
`rig-create review … --item meshes:delegated --ask meshes=density` writes
|
|
926
|
+
that field. `--ask` is optional, accepts one ask per named item, and is for
|
|
927
|
+
delegated feedback. Missing it on a guide with per-ask coverage warns.
|
|
928
|
+
Guides without per-ask coverage gain no finding when these fields are absent.
|
|
929
|
+
|
|
930
|
+
`provisional` is a verdict given before the person has seen everything they
|
|
931
|
+
want to see — it holds a place and is replaced, never a basis for moving a
|
|
932
|
+
stage.
|
|
933
|
+
|
|
934
|
+
### Registering a frozen rig build
|
|
935
|
+
|
|
936
|
+
Use `rig-version` to bring separately located frozen producer outputs into one
|
|
937
|
+
numbered version. This is a registration operation. Build, registration and
|
|
938
|
+
acceptance have separate dates and writers.
|
|
939
|
+
|
|
940
|
+
```sh
|
|
941
|
+
rig-create rig-version 3 . \
|
|
942
|
+
--parts frozen/assembly/rig --rig frozen/out/rig --build frozen/out/build \
|
|
943
|
+
--idle frozen/render --config frozen/config.json \
|
|
944
|
+
--path-adapter frozen/path-adapter.json --compile-report frozen/build-report.json \
|
|
945
|
+
--toolchain-lock frozen/package-lock.json \
|
|
946
|
+
--at-source frozen/dated-record.json --at-pointer /finished_at --by agent \
|
|
947
|
+
--citations frozen/section-citations.json
|
|
948
|
+
```
|
|
949
|
+
|
|
950
|
+
Source arguments resolve against the project directory. Absolute arguments may
|
|
951
|
+
name external frozen inputs. The writer retains copies under
|
|
952
|
+
`evidence/v<N>/registration/` and binds their exact bytes by SHA-256. The project
|
|
953
|
+
record refers to those retained paths, including the lock and cited date record.
|
|
954
|
+
|
|
955
|
+
`built_with` comes from the declared npm v3 lock's
|
|
956
|
+
`packages["node_modules/@rig-c/parts"].version` and corresponding core entry.
|
|
957
|
+
`registration.toolchain` is `{kind:"npm-lock-v3",source:{path,sha256,bytes}}`.
|
|
958
|
+
The `--toolchain-lock` argument explicitly declares the run-to-toolchain
|
|
959
|
+
association. This declaration establishes which frozen lock the registrant
|
|
960
|
+
selected. Producer-owned run attestation, including versions, start/finish and
|
|
961
|
+
output hashes, is tracked in parts#1165 and core#1718. A future source kind can
|
|
962
|
+
be added when that producer interface lands. Current readers support
|
|
963
|
+
`npm-lock-v3` only. Wrapper receipts and toolchain summary files supply no
|
|
964
|
+
registration contract.
|
|
965
|
+
|
|
966
|
+
Repeatable `--run-record <file>` binds at most one producer `run.json` per
|
|
967
|
+
spec beside `--toolchain-lock`, recorded in the order given as
|
|
968
|
+
`registration.runs: [{spec,source:{path,sha256,bytes}}]`. The dispatcher in
|
|
969
|
+
`src/run-record.ts` accepts `rig-run/1` (`@rig-c/parts` `rig` or `assemble`) and
|
|
970
|
+
`rigc-run/1` (`@rig-c/core` or its `rig-c` alias, `build`, with required `rig` and `motion` input roles and
|
|
971
|
+
optional `manifest` and `cuts` sorted in that role order and UTF-16 code-unit
|
|
972
|
+
path order), validating only the published keys, key order and types without
|
|
973
|
+
re-running or recomputing producer measurements. `interview --check` re-reads
|
|
974
|
+
each bound record and refuses a byte/SHA-256 mismatch
|
|
975
|
+
(`RUN_RECORD_HASH_MISMATCH`), an unknown spec (`RUN_RECORD_SPEC_UNKNOWN`), a
|
|
976
|
+
missing or malformed input role (`RUN_RECORD_ROLE_INVALID`) or a malformed
|
|
977
|
+
shape (`RUN_RECORD_MALFORMED`). Lock-only `frozen-rig/1` versions without
|
|
978
|
+
`registration.runs` WARN before `RUN_RECORD_SINCE = 2026-11-08T00:00:00Z` (by
|
|
979
|
+
`registration.at`) and refuse from `RUN_RECORD_SINCE` onward under
|
|
980
|
+
`RUN_RECORD_REQUIRED`.
|
|
981
|
+
|
|
982
|
+
`at_source` is `{path,sha256,bytes,pointer}`. The nonempty RFC 6901 JSON pointer
|
|
983
|
+
selects an explicit UTC ISO timestamp ending `Z` or `+00:00`, including fractional
|
|
984
|
+
seconds. `at` preserves that exact string and `at_basis` is `"not-after"`.
|
|
985
|
+
The registrant declares that the build had finished by that cited instant.
|
|
986
|
+
The clock supplies `registration.at`. A cited bound at or before a reopen
|
|
987
|
+
covering `rig-review`, as of registration, refuses the write. A later bound is
|
|
988
|
+
admitted with its retained citation for review. A reopen after registration
|
|
989
|
+
preserves the historical record and the existing liveness rules supersede it.
|
|
990
|
+
Acceptance dates remain on verdicts written through the review and signoff flow.
|
|
991
|
+
|
|
992
|
+
The copied rig, motion and model use producer specs `rigc-rig/1`,
|
|
993
|
+
`rigc-motion/1` and `rigc-compiled/3`. The producer's compile document must
|
|
994
|
+
be a successful `build-report/1`. Idle
|
|
995
|
+
evidence is a public `rigc render` directory with `frames.json`, spec
|
|
996
|
+
`rigc-frames/1`, and an `idle` set. The writer binds that manifest and every
|
|
997
|
+
copied frame and diagnostic file. It preserves the producer's fps, viewport,
|
|
998
|
+
skin and preroll declarations, including optional-field absence. A directory
|
|
999
|
+
containing only images and a wrapper receipt needs a public producer re-render.
|
|
1000
|
+
|
|
1001
|
+
The copied output layout is `outputs/v<N>/out/parts.json`, `out/parts/`,
|
|
1002
|
+
`out/rig/`, `out/check/build/` and `outputs/v<N>/idle/`. Every copied output
|
|
1003
|
+
gets its actual `path`, `sha256` and `bytes` in `versions[].outputs`.
|
|
1004
|
+
`registration.copied` records file and byte totals. Sources are rechecked after
|
|
1005
|
+
copying, and the copy is byte-verified before registration. The normal
|
|
1006
|
+
`review-package` materializer then creates `derived/review/v<N>/`, using the
|
|
1007
|
+
same accepted-parts and config identity checks as its standalone command.
|
|
1008
|
+
|
|
1009
|
+
The retained original config and adapter are bound as `registration.config_source`
|
|
1010
|
+
and `registration.path_adapter`. Registrations using pointer adaptation declare
|
|
1011
|
+
`registration.path_adapter.format` as `json-pointer/1`. Removing an adapter row
|
|
1012
|
+
keeps that contract active. These registrations also bind the original
|
|
1013
|
+
and runtime requirements as `registration.requirements_source` and
|
|
1014
|
+
`registration.requirements`. Each absolute config value requires an exact
|
|
1015
|
+
adapter row `{at:".section.field",before,after}` matching its runtime `after`
|
|
1016
|
+
value, and relative `config` or `requirements` asset references use explicit
|
|
1017
|
+
`{doc:"config"|"requirements",pointer,before,after}` rows (recorded in the
|
|
1018
|
+
retained `path-adapter.json`). The writer retains the original `config` and
|
|
1019
|
+
`requirements` byte-identical, copies every referenced asset (`assemble.take`,
|
|
1020
|
+
`assemble.editor_receipts`, `assemble.cuts`, `limbs`, `depth`,
|
|
1021
|
+
`setup_painting.figure_mask` and `setup_painting.backdrop`) to literal
|
|
1022
|
+
in-package paths (`no ..`, `no :`), verifies declared `sha256` digests before
|
|
1023
|
+
copying, and checks that the runtime `config.json` and `requirements.json`
|
|
1024
|
+
equal the retained sources after applying only the declared `path_adapter`
|
|
1025
|
+
substitutions. Registrations without pointer adaptation retain their original
|
|
1026
|
+
implicit take and editor-receipt relocation, permit unused legacy adapter rows
|
|
1027
|
+
and do not require source-only relative assets or a backdrop that their writer
|
|
1028
|
+
did not retain. Missing mappings, unlisted runtime differences, escaping
|
|
1029
|
+
references, symlinks, hash mismatches and incompatible file or directory
|
|
1030
|
+
collisions refuse. Identical file bytes may share a target, including an
|
|
1031
|
+
explicit image inside a named plate directory. Producer
|
|
1032
|
+
outputs retain their original bytes. Packaging relocates the config's and
|
|
1033
|
+
requirements' named inputs without rerunning producer measurements.
|
|
1034
|
+
|
|
1035
|
+
Optional `--citations` reads an agent-authored map of the existing
|
|
1036
|
+
`provenance.sections` shape. The writer retains that map and binds the adapted
|
|
1037
|
+
config under `provenance.config`. Omission records an empty section map. The
|
|
1038
|
+
writer runs the full check on the candidate record and refuses any refusal it
|
|
1039
|
+
adds, so every applicable config section needs its citation at registration.
|
|
1040
|
+
|
|
1041
|
+
`registration.kind` is `"frozen-rig/1"`. The registration validator is shared
|
|
1042
|
+
with `interview --check` and opts in only versions carrying `registration`.
|
|
1043
|
+
Existing versions keep their contract, so this additive writer adds no SINCE
|
|
1044
|
+
constant. When `n > maxRegistered + 1`, every skipped number `K` between the
|
|
1045
|
+
previous highest registered version and `n` must already have at least one
|
|
1046
|
+
unregistered destination directory (`outputs/v<K>`,
|
|
1047
|
+
`evidence/v<K>/registration` or `derived/review/v<K>`) present on disk at
|
|
1048
|
+
registration (re-verified before rename); the writer records the admission
|
|
1049
|
+
receipt `registration.skipped` as `[{n:K,destinations}]`, and `interview --check`
|
|
1050
|
+
validates that receipt (`prevMax + 1 .. n - 1`, unregistered numbers and
|
|
1051
|
+
nonempty canonical destination paths) without re-statting historical directories
|
|
1052
|
+
after archival or in retained closures. Unexplained empty gaps, occupied
|
|
1053
|
+
destinations on `n` itself, registered numbers in `skipped` and non-directory or
|
|
1054
|
+
symlinked destination paths at registration refuse. Versions that advance by one
|
|
1055
|
+
(`n === maxRegistered + 1`) omit `registration.skipped`. The writer validates
|
|
1056
|
+
its registration and normal
|
|
1057
|
+
package identity,
|
|
1058
|
+
checks that project bytes are unchanged during copying, then atomically records
|
|
1059
|
+
the new version. A refused write preserves project bytes and removes its newly
|
|
1060
|
+
created outputs, retained inputs and review package. Retry uses the same next
|
|
1061
|
+
number after a refusal. A successful version remains frozen.
|
|
1062
|
+
|
|
1063
|
+
Registration leaves stage, signoffs and verdicts intact. The human review uses
|
|
1064
|
+
the emitted review package, existing review/signoff writers record the result,
|
|
1065
|
+
and `advance` performs the authorized forward move. The synthetic public-render
|
|
1066
|
+
fixture and its producer commands are documented in
|
|
1067
|
+
[tests/fixtures/rig-registration](../tests/fixtures/rig-registration/README.md).
|
|
1068
|
+
|
|
1069
|
+
### Migrating work done before the interview
|
|
1070
|
+
|
|
1071
|
+
Keep `kind: "rig"` or `"post"` and add `pre_interview: true`. The flag records
|
|
1072
|
+
when the work was made while preserving which review judges it and which rig
|
|
1073
|
+
post work rests on. These versions need no `provenance`. Create-built versions
|
|
1074
|
+
continue to cite their interview and retain the user's words in verdicts.
|
|
1075
|
+
|
|
1076
|
+
A pre-interview verdict has create's `by`, valid `at`, `review`, `verdict`,
|
|
1077
|
+
`source` and `on_items[]`. When the words survive, keep them in `verbatim`.
|
|
1078
|
+
When only someone's record of the user survives, set `verbatim: null`, state
|
|
1079
|
+
that it is a record in `note`, put the record there and name its `source`.
|
|
1080
|
+
The check requires the note and source. A summary never becomes an interview
|
|
1081
|
+
quotation. Historical `not-asked` items remain in the verdict without invented
|
|
1082
|
+
`additions[]` in today's guide. Current answers and sign-offs are still checked.
|
|
1083
|
+
|
|
1084
|
+
Keep the complete original verdict array unchanged in `original_verdicts` on
|
|
1085
|
+
the version. Its entries occupy the same indices in `verdicts[]`, each copied
|
|
1086
|
+
unchanged into `as_recorded` beside the converted fields. The check compares
|
|
1087
|
+
all fields and the array order, including repeated verdicts. Further reviews
|
|
1088
|
+
may be appended without `as_recorded`. The original `verdict` string maps by
|
|
1089
|
+
this exact table, also exported as `PRE_INTERVIEW_VERDICTS`.
|
|
1090
|
+
|
|
1091
|
+
| Original `verdict` | Create `verdict` |
|
|
1092
|
+
| --- | --- |
|
|
1093
|
+
| `accepted`, `Accepted` | `accepted` |
|
|
1094
|
+
| `accepted (sent to owner)`, `Accepted (sent to owner)` | `accepted` |
|
|
1095
|
+
| `bounced`, `Bounced` | `bounced` |
|
|
1096
|
+
| `provisional`, `Provisional` | `provisional` |
|
|
1097
|
+
| `accepted (HQ-provisional, sent to owner)` | `provisional` — the reviewer marked “HQ-provisional”, org HQ ruling 2026-11-06 |
|
|
1098
|
+
| `accepted-provisional` | `provisional` — the reviewer marked “provisional”, org HQ ruling 2026-11-06 |
|
|
1099
|
+
| `ok for now, polish wanted` | `accepted`, polish in `on_items[]` — owner 2026-11-03, “`<pilot>`도 여기까지 OK” and “일단 여기까지는 OK”; org HQ ruling 2026-11-06 |
|
|
1100
|
+
| `close, polish wanted` | `provisional`, polish as its open item — owner 2026-11-03, “`<pilot>` 많이 좋아졌다. 조금만 더 다듬으면 되겠어”; org HQ ruling 2026-11-06 |
|
|
1101
|
+
|
|
1102
|
+
An unlisted string is refused as `PRE_INTERVIEW_VERDICT_UNKNOWN`. Preserve it
|
|
1103
|
+
and obtain an explicit mapping before extending the table. A converted value
|
|
1104
|
+
that disagrees with the table is `PRE_INTERVIEW_VERDICT_MISMATCH`.
|
|
1105
|
+
|
|
1106
|
+
Every historical version lists its frozen `outputs[]` with project-relative
|
|
1107
|
+
`path`, `sha256` and `bytes`. The check reads every file and compares its hash
|
|
1108
|
+
and size. If frozen outputs did not survive, declare
|
|
1109
|
+
`outputs_lost: { note, source, recorded }` via
|
|
1110
|
+
`rig-create version outputs-lost <n> --note <text> --source <text>`, keeping any
|
|
1111
|
+
outputs still readable with their recorded sha256 in `outputs` (`outputs: []` when
|
|
1112
|
+
none survived) and moving the missing ones into `recorded: [{ path, sha256 }]`
|
|
1113
|
+
alongside what was lost and the source record that says so. Both
|
|
1114
|
+
`note` and `source` must be nonempty strings. Earlier `{ note, source }`
|
|
1115
|
+
declarations beside `outputs: []` without `recorded` remain valid, so no contract
|
|
1116
|
+
date is added. A loss declaration without `recorded` beside nonempty `outputs`,
|
|
1117
|
+
a `recorded` entry overlapping `outputs` or readable on disk, or `outputs_lost`
|
|
1118
|
+
on a create-built version is refused (`PRE_INTERVIEW_OUTPUTS_LOST_MALFORMED`). If
|
|
1119
|
+
no output is lost (every recorded output is readable on disk with its sha256),
|
|
1120
|
+
the writer refuses (`OUTPUTS_LOST_HAS_OUTPUTS`) and names the readable outputs.
|
|
1121
|
+
Handoff refuses a selected rig with `outputs_lost`
|
|
1122
|
+
as `PRE_INTERVIEW_OUTPUTS_LOST`, and post records cannot use it as their rig
|
|
1123
|
+
basis (`POST_ON_UNACCEPTED_RIG`). All
|
|
1124
|
+
pre-interview versions precede the first create-built version, with positive,
|
|
1125
|
+
strictly increasing `n` across the combined history.
|
|
1126
|
+
|
|
1127
|
+
For a lost build config, first recover the producer version from that version's
|
|
1128
|
+
own source record and put it in `built_with["@rig-c/parts"]`. A version's
|
|
1129
|
+
producer is recorded from its own source record, never inferred from neighbours.
|
|
1130
|
+
A producer older than 2.4.0 receives `CG_GATES_PREDATE` on a CG rig.
|
|
1131
|
+
If the config did not survive, declare `config_lost: { note, source }` with
|
|
1132
|
+
nonempty strings explaining the loss and naming its source. This requires
|
|
1133
|
+
`pre_interview: true` and absent or null `provenance.config`. A CG rig receives
|
|
1134
|
+
`CG_GATES_CONFIG_LOST` instead of `CG_GATES_UNREAD`, preserving the check exit
|
|
1135
|
+
when the rest of the record passes. A known old producer and a declared config
|
|
1136
|
+
loss receive both warnings. The declaration is also available when the source
|
|
1137
|
+
names no producer version. Handoff refuses a selected rig with this declaration
|
|
1138
|
+
as `PRE_INTERVIEW_CONFIG_LOST`; post records cannot use it as their rig basis.
|
|
1139
|
+
Build and accept a new rig with its retained config before post work.
|
|
1140
|
+
|
|
1141
|
+
An accepted pre-interview rig with surviving outputs and no config loss still
|
|
1142
|
+
authorizes post work. Its human
|
|
1143
|
+
`rig-review` verdict, valid acceptance time, still-frame record and
|
|
1144
|
+
`rig-review` sign-off remain required. `handoff` reports `pre_interview` in
|
|
1145
|
+
JSON and prints that status and the verdict's source in text. It also lists
|
|
1146
|
+
the note and source of historical output losses, and refuses a selected rig
|
|
1147
|
+
whose outputs were lost. A later rig
|
|
1148
|
+
requires its own acceptance and supersedes the older rig in the usual way.
|
|
1149
|
+
Other checks, including the CG gates where applicable, continue to run.
|
|
1150
|
+
|
|
1151
|
+
For an in-flight consumer project keeping history under `x-pre_create.versions`,
|
|
1152
|
+
perform the following migration on its own decision record.
|
|
1153
|
+
|
|
1154
|
+
1. Preserve the original array and frozen outputs before editing. For each
|
|
1155
|
+
version, recover its complete original verdict array from the existing
|
|
1156
|
+
`as_recorded` entries or the source record. Keep that array in
|
|
1157
|
+
`original_verdicts` and retain each full entry as `as_recorded` at the same
|
|
1158
|
+
index. Do not replace a missing original with a reconstructed quote.
|
|
1159
|
+
2. Move the historical entries into `versions[]`, keeping `kind` and adding
|
|
1160
|
+
`pre_interview: true`. Put them before the create-built entries, preserve
|
|
1161
|
+
a copy of the source id in `original_n` (number, string or `null`). Assign
|
|
1162
|
+
positive, strictly increasing `n` in record order. Non-null `original_n`
|
|
1163
|
+
values must be unique; multiple nulls are allowed. Rewrite `answers_feedback`
|
|
1164
|
+
version references and post `rig_version` references to the new `n`.
|
|
1165
|
+
Create-built versions carry no `original_n`.
|
|
1166
|
+
Every migrated rig version must retain a readable `at` from its build record;
|
|
1167
|
+
if no date can be recovered, stop the migration rather than inventing one
|
|
1168
|
+
(`RIG_VERSION_AT_INVALID`).
|
|
1169
|
+
Remove the moved `x-pre_create.versions` array. A nonempty array left there
|
|
1170
|
+
produces the `PRE_INTERVIEW_UNMIGRATED` warning while migration is pending.
|
|
1171
|
+
It preserves the existing check exit code. Migrated records are checked
|
|
1172
|
+
with the refusals described above.
|
|
1173
|
+
3. Fill create-shaped verdict fields from known records, using the mapping
|
|
1174
|
+
table, stating their source and recording summaries as `verbatim: null`
|
|
1175
|
+
with `note`. Preserve carried `on_items[]` and map them to the interview's
|
|
1176
|
+
item ids. Recover dates from dated evidence without inventing them.
|
|
1177
|
+
4. First record any producer version named by each version's own source in
|
|
1178
|
+
`built_with`; never infer it from neighbouring versions. Restore the build
|
|
1179
|
+
config and its provenance binding if it survived. Otherwise declare
|
|
1180
|
+
`config_lost: { note, source }` explaining the loss and its source; this
|
|
1181
|
+
version cannot authorize post work. `rig-create version config-lost <n> --note <text> --source <text>`
|
|
1182
|
+
writes this declaration.
|
|
1183
|
+
Restore each frozen output and record its actual `path`, `sha256` and
|
|
1184
|
+
`bytes`. When some or all frozen outputs did not survive, declare `outputs_lost`
|
|
1185
|
+
with the known loss in `note` and its record in `source`;
|
|
1186
|
+
`rig-create version outputs-lost <n> --note <text> --source <text>` keeps
|
|
1187
|
+
any readable outputs in `outputs` (`outputs: []` when none survived) and
|
|
1188
|
+
moves the missing `{ path, sha256 }` bindings into
|
|
1189
|
+
`outputs_lost.recorded`. Check that all
|
|
1190
|
+
`answers_feedback` and `rig_version` references use the new `n`, including
|
|
1191
|
+
references from create-built entries. Retain acceptance stills and genuine
|
|
1192
|
+
stage sign-offs. The flag
|
|
1193
|
+
supplies no missing review evidence or sign-off.
|
|
1194
|
+
5. On the first create-built version, list the earlier feedback it answers in
|
|
1195
|
+
`answers_feedback`, including carried items where relevant. The existing
|
|
1196
|
+
`review --answers-feedback <version>:<verdict-index>` writer can append
|
|
1197
|
+
these references. Keep that version's provenance and interview words.
|
|
1198
|
+
6. Run `rig-create interview --check <project dir> --json`, resolve the named
|
|
1199
|
+
refusals and inspect `rig-create handoff <project dir> --json` before post
|
|
1200
|
+
work. The synthetic [migration fixture](../tests/data/pre-interview.json)
|
|
1201
|
+
contains one bounced rig and one accepted rig carrying a timing item.
|
|
1202
|
+
|
|
1203
|
+
## The record, field by field
|
|
1204
|
+
|
|
1205
|
+
Top-level fields of `project.json`:
|
|
1206
|
+
|
|
1207
|
+
| Field | Holds |
|
|
1208
|
+
| --- | --- |
|
|
1209
|
+
| `schema` | `rig-create/project@0` |
|
|
1210
|
+
| `name` | the folder name; a short identifier |
|
|
1211
|
+
| `title` | the human title of the painting or rig |
|
|
1212
|
+
| `stage`, `stage_values` | the current stage and the list it comes from |
|
|
1213
|
+
| `signoffs[]` | every human signature: `stage`, `checkpoint` (step id or `null`), `by`, `at`, `verbatim`; plan signatures add `steps[]` naming covered steps and `step_hashes` binding their approval fields. `by` names whose decision is recorded, including their delegated instruction written by an agent, and `by: "agent"` remains refused (`SIGNOFF_NOT_HUMAN`). |
|
|
1214
|
+
| `interview` | `question_set` (the prompt set and package version the waypoints were read from), `held`, `date`, `interviewer`, `respondent`, `framing[]` (`id`, `text`, `source`, `required_for`, `answer`, `history[]`), `waypoints[]` (`id`, `config[]`, `prompts[]` of `id`/`text`/`source`/`required_for`, `guide`, `history[]`), `post` (`held`, `date`, `items[]` shaped like waypoints with `guide`) — answer shapes in [INTERVIEW.md](INTERVIEW.md) |
|
|
1215
|
+
| `plan` | `drafted_by`, `drafted_at`, current unique `steps[]`, optional append-only `replaced[]` — above |
|
|
1216
|
+
| `plan.replaced[]` | full previous `step`, `sha256` from `stepHash(step)`, `action` (`revised` or `removed`), ISO `at`, drafter `by`, identified by `step.id` plus `at`, in nondecreasing date and write order |
|
|
1217
|
+
| `split` | the `assemble` checkpoint's data: `label_values`, `proposal_image`, `proposed_by`, `proposed_at`, `parts[]` (`name`, `label`, `note`) |
|
|
1218
|
+
| `inputs[]` | `path`, `sha256`, `bytes`, `origin` (where the file came from, in words), `at` (writer timestamp) |
|
|
1219
|
+
| `derived[]` | `path`, `what`, `command`, `inputs[]` (`path`, `sha256`), `bytes` |
|
|
1220
|
+
| `versions[]` | above |
|
|
1221
|
+
| `archive` | `null`, or `{ "where", "at", "by" }` if the finals were moved out of the project |
|
|
1222
|
+
| `collection_binding` | optional on collection members: `{ "path", "sha256", "spec": "rig-create/collection-binding@1", "collection_sha256" }` binding a project-relative snapshot of `../../collection.json` so retained checks and model-free record publication run without reading outside the member root |
|
|
1223
|
+
| `notes[]` | free text that is not a decision; anything that is one goes in the field it belongs to |
|
|
1224
|
+
|
|
1225
|
+
## How an agent resumes a project
|
|
1226
|
+
|
|
1227
|
+
1. Read `project.json` — nothing else first. `stage`, the last `signoffs[]`
|
|
1228
|
+
entry, the first `plan.steps[]` entry not `done` and the last `versions[]`
|
|
1229
|
+
entry say where it stands. For a collection member, read the collection's
|
|
1230
|
+
`collection.json` next ([COLLECTIONS.md](COLLECTIONS.md)): its stage and
|
|
1231
|
+
`plan.order` say whether this member may run now, and its interview holds
|
|
1232
|
+
every answer marked `inherited`.
|
|
1233
|
+
2. If the interview has a `null` answer or the plan is unsigned, that is the
|
|
1234
|
+
next work, and it is the user's to answer; do not fill it from the image.
|
|
1235
|
+
3. If the last version was bounced, its verdict's `verbatim`, its `on_items`
|
|
1236
|
+
and the files in its `evidence` are the brief. Open the evidence; do not
|
|
1237
|
+
reconstruct the reason from chat. Feedback with `answer_was: "not-asked"`
|
|
1238
|
+
becomes a guide sentence at its waypoint before the next version is built.
|
|
1239
|
+
4. Check `inputs[]` hashes against `inputs/` before using them.
|
|
1240
|
+
5. Reuse `derived/` only through `derived[]`: an entry whose input hashes no
|
|
1241
|
+
longer match is stale — regenerate it with its recorded command.
|
|
1242
|
+
6. When a new version is shown to anyone: freeze `outputs/v<N>/`, hash it, add
|
|
1243
|
+
the `versions[]` entry and its evidence in the same turn.
|
|
1244
|
+
|
|
1245
|
+
### Registering immutable inputs
|
|
1246
|
+
|
|
1247
|
+
```sh
|
|
1248
|
+
rig-create input add inputs/source.png [<project dir>] --origin "synthetic source exported by the painting tool" [--painting [--projects-root <dir>] [--same-artwork-reason <file>]] [--json]
|
|
1249
|
+
```
|
|
1250
|
+
|
|
1251
|
+
Run from the project, or pass its directory after the source path. The writer
|
|
1252
|
+
appends `{path, sha256, bytes, origin, at}` using the file's raw bytes and the
|
|
1253
|
+
current UTC timestamp. `--json` prints that record. It refuses an escaping or
|
|
1254
|
+
missing source, an already registered path, and changed bytes under a
|
|
1255
|
+
registered name. Add `--painting` to declare this registered input's path as
|
|
1256
|
+
`project.painting`. Each project has one declaration. A second declaration
|
|
1257
|
+
refuses with `INPUT_PAINTING_EXISTS`, preserving the original painting and reason.
|
|
1258
|
+
Only `init --painting` and `input add --painting` compare the declared file
|
|
1259
|
+
against sibling inputs. They refuse with `INIT_ARTWORK_EXISTS` when a
|
|
1260
|
+
`project.json` directly under `--projects-root` (default the project's parent
|
|
1261
|
+
folder) has an input with the same sha256, unless `--same-artwork-reason <file>`
|
|
1262
|
+
is given. This records `same_artwork: { reason, at, projects }`, preserving any
|
|
1263
|
+
previously recorded reason. Both artwork options require `--painting`.
|
|
1264
|
+
Plain `input add` accepts identical inputs across sibling projects. Older
|
|
1265
|
+
records may omit `painting`. Position, name and file type never declare it.
|
|
1266
|
+
The shared checker refuses `INPUT_PAINTING_INVALID` when a declaration is not
|
|
1267
|
+
the path of a registered input. Restart validates and preserves the declaration.
|
|
1268
|
+
A changed source needs a new file with a new name. A refused write leaves
|
|
1269
|
+
`project.json` byte-identical. The shared checker checks complete records against their retained files. Incomplete
|
|
1270
|
+
writer metadata is `INPUT_WRITER_MISSING`, dated by `inputs[].at` from
|
|
1271
|
+
`INPUT_WRITER_SINCE`. Earlier or unreadably dated entries WARN and retain their
|
|
1272
|
+
original history.
|
|
1273
|
+
|
|
1274
|
+
## Prepared inputs and agent-found bounces
|
|
1275
|
+
|
|
1276
|
+
`rig-create derived add [<project dir>] --source inputs/source.svg --file derived/prepared.svg --operation "external scale and white composite"`
|
|
1277
|
+
records work already performed by another tool. It appends one `derived[]`
|
|
1278
|
+
entry; it transforms no pixels and changes no sign-off or stage. `derived add`
|
|
1279
|
+
is used instead of `prepare` because the operation has already run elsewhere.
|
|
1280
|
+
Both files must exist, have distinct project-relative paths, and be readable.
|
|
1281
|
+
Neither may be `project.json`: appending the record would change its own hash.
|
|
1282
|
+
The command measures both sha256s before writing anything:
|
|
1283
|
+
|
|
1284
|
+
```json
|
|
1285
|
+
{
|
|
1286
|
+
"kind": "prepared-input",
|
|
1287
|
+
"source": { "path": "inputs/source.svg", "sha256": "<64 hex digits>" },
|
|
1288
|
+
"path": "derived/prepared.svg",
|
|
1289
|
+
"sha256": "<64 hex digits>",
|
|
1290
|
+
"operation": "external scale and white composite"
|
|
1291
|
+
}
|
|
1292
|
+
```
|
|
1293
|
+
|
|
1294
|
+
`interview --check` requires the source and verifies its hash. A missing source
|
|
1295
|
+
or changed bytes in either present file are refused by name. A missing result
|
|
1296
|
+
warns with its file name and recorded operation, so a fresh clone passes while
|
|
1297
|
+
regenerable intermediates are absent. Only entries tagged `kind: "prepared-input"` use this contract; older
|
|
1298
|
+
untagged intermediates and projects with no `derived[]` entries keep passing.
|
|
1299
|
+
Restore derived files with the recorded operation when needed. The recorded
|
|
1300
|
+
hashes describe the bytes that must return.
|
|
1301
|
+
For a producer plate, supply `--source` for both its painting and uploaded mask,
|
|
1302
|
+
`--file` for its output, and `--receipt` for its `rig-parts-plate-receipt/1` JSON.
|
|
1303
|
+
The optional `receipt` records `{ path, sha256, spec }` from raw bytes. Its file
|
|
1304
|
+
must stay inside the project with no symlink components. Receipt paths resolve
|
|
1305
|
+
relative to the receipt directory. The checker compares declared paths and hashes
|
|
1306
|
+
to the derived sources and output, without repeating producer measurements.
|
|
1307
|
+
A retained scene registration identifies a derived plate. Its earliest scene
|
|
1308
|
+
`at` dates missing-receipt warnings or refusals under `PLATE_RECEIPT_SINCE`.
|
|
1309
|
+
|
|
1310
|
+
The filled example ships synthetic SVG bytes under
|
|
1311
|
+
[example-prepared](../templates/example-prepared/); copy `source.svg` to
|
|
1312
|
+
`inputs/preparation-source.svg` and `prepared.svg` to `derived/prepared.svg`
|
|
1313
|
+
when materializing its prepared-input record. These fixtures demonstrate
|
|
1314
|
+
recording, not a claim that the tool performed or verified pixel processing.
|
|
1315
|
+
|
|
1316
|
+
Busy-ground figure masks have a coverage gap: foreground subtraction excludes
|
|
1317
|
+
character pixels under that plane, so `SETUP_MATCHES_PAINTING` can pass with
|
|
1318
|
+
parts missing there. Keep the [default recipe](CHECKS.md#busy-ground-figure-masks).
|
|
1319
|
+
A character-plate matte can include inpaint fill as figure;
|
|
1320
|
+
[#113](https://github.com/rig-c/create/issues/113) tracks that upstream plate-making
|
|
1321
|
+
problem.
|
|
1322
|
+
|
|
1323
|
+
An agent rejecting its own route mid-step records it in that guide's
|
|
1324
|
+
`history[]`, separately from human `versions[].verdicts[]`:
|
|
1325
|
+
|
|
1326
|
+
```json
|
|
1327
|
+
{
|
|
1328
|
+
"at": "2026-11-11T08:00:00Z",
|
|
1329
|
+
"bounce": {
|
|
1330
|
+
"cause": "agent",
|
|
1331
|
+
"failed": "The first split merged the eyelids into the face",
|
|
1332
|
+
"bar": "Blink needs the eyelids as their own layers",
|
|
1333
|
+
"replacement": "Run a head pass as well as the full pass"
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
```
|
|
1337
|
+
|
|
1338
|
+
`failed`, `bar`, and `replacement` are non-empty text: what failed, against
|
|
1339
|
+
which bar, and what replaced it. This record does not grant a new user choice
|
|
1340
|
+
or sign-off and does not create a human review verdict. The check reads local
|
|
1341
|
+
histories and the collection histories an inherited answer cites. Compatibility
|
|
1342
|
+
is per history entry's own `at`, not the project's age: malformed bounces before
|
|
1343
|
+
`AGENT_BOUNCE_SINCE` (`2026-11-05T00:00:00Z`), or with no readable date, warn
|
|
1344
|
+
with the new shape. Malformed bounces on or after it are refused.
|
|
1345
|
+
|
|
1346
|
+
### The package handed to rig review
|
|
1347
|
+
|
|
1348
|
+
Before showing a create-built rig version, run from the project directory:
|
|
1349
|
+
|
|
1350
|
+
```sh
|
|
1351
|
+
rig-create review-package 1 --config evidence/v1/config.json --from outputs/v1/out
|
|
1352
|
+
```
|
|
1353
|
+
|
|
1354
|
+
The source paths are explicit, project-relative inputs. The command copies the
|
|
1355
|
+
config unchanged and the build's `parts.json`, `parts/`, `rig/`, and
|
|
1356
|
+
`check/build/` into `derived/review/v1/`, with the config at `config.json` and
|
|
1357
|
+
the build files under `out/`. Every config-relative file named by the installed loader is copied at its relative path and included in the frozen inventory, including nested requirements, animations and a file-based control skeleton. The source build must include `rig/rig.json`,
|
|
1358
|
+
`rig/motion.json`, `rig/mesh_report.json` and
|
|
1359
|
+
`check/build/skeleton.model.json`. Copies preserve the package when the build
|
|
1360
|
+
directory is cleaned. The packager also retains `setup_painting.figure_mask.path` from the frozen requirements at its requirements-relative path, verifies its declared SHA-256, and records its package binding. Each copied file is hashed. The command writes no new
|
|
1361
|
+
build and moves no stage.
|
|
1362
|
+
|
|
1363
|
+
A config's named files are bound build inputs in versions and drafts, with draft inputs recorded separately as optional `config_inputs` path/raw-sha256 bindings while `files` remains outputs. A draft's named input binds at its project path wherever it sits inside the project, and is not copied into `derived/drafts/<id>`; only the draft's config, parts and outputs live under that root. A named input outside the root is a project input, not a regenerable draft artifact, so its absence refuses rather than warning `DRAFT_RIG_UNAVAILABLE`. A named input that is a directory, such as a See-through occluder plate named by `assemble.occluders[i].plate`, binds its producer's `receipt.json` — as `{path: <dir>/receipt.json, sha256, directory: <dir>, spec}` in a draft's `config_inputs`, and by copying and hashing `<dir>/receipt.json` in `review-package` — where `spec` is the installed parts' `PLATE_RECEIPT_SPEC` and the receipt must declare it; the receipt binds the plate's unreferenced sibling images, which create does not copy, hash or re-verify (any sibling explicitly declared as its own config input, such as `assemble.occluders[i].image`, is copied and hashed as that independent input).
|
|
1364
|
+
|
|
1365
|
+
The version's `review_package` field records `config` (`path`, `sha256`),
|
|
1366
|
+
`from` (the declared build directory), `files` (sorted package-relative
|
|
1367
|
+
`{path, sha256}` entries, including the copied config), and `open`:
|
|
1368
|
+
|
|
1369
|
+
```json
|
|
1370
|
+
{"open":"rig-review open 'derived/review/v1/out'"}
|
|
1371
|
+
```
|
|
1372
|
+
|
|
1373
|
+
Run that open command from the project directory. Review recognizes `out/`
|
|
1374
|
+
as a build root, opens its `check/` package and discovers the config beside
|
|
1375
|
+
the build root. The installed review package documents this discovery under
|
|
1376
|
+
*Producer handoff* in `docs/REVIEW_PACKAGE.md`. Its handoff hash identifies
|
|
1377
|
+
the exact copied config. The hash check binds the copies to this version's
|
|
1378
|
+
recorded input snapshot. The producer baseline in review determines whether
|
|
1379
|
+
those inputs reproduce the inspected rig.
|
|
1380
|
+
|
|
1381
|
+
`interview --check` warns with the package command when a rig version has no
|
|
1382
|
+
recorded package or when a recorded package is absent after a fresh clone.
|
|
1383
|
+
A present package must match the complete recorded file list and hashes.
|
|
1384
|
+
Regenerate a missing package from its recorded sources. If an existing
|
|
1385
|
+
package differs, the writer refuses replacement so the frozen copy can be
|
|
1386
|
+
inspected. A new build shown to the user gets a new version and package.
|
|
1387
|
+
Post versions go to direction review, outside this package contract.
|
|
1388
|
+
Pre-interview versions retain their existing history and output checks and
|
|
1389
|
+
are exempt from review-package warnings.
|
|
1390
|
+
|
|
1391
|
+
The filled example ships synthetic producer bytes under
|
|
1392
|
+
`templates/example-review/`. Its two `review_package` records are generated
|
|
1393
|
+
by `bun scripts/generate-example-review.ts <fresh scratch project>`. Add
|
|
1394
|
+
`--check` to verify that generation reproduces the shipped record bytes.
|
|
1395
|
+
The script runs the public `review-package` command for both rig versions.
|
|
1396
|
+
`reviewExampleFiles()` in `tests/review-fixture.ts` maps those bytes to the
|
|
1397
|
+
declared sources and package destinations, and both example fixture helpers
|
|
1398
|
+
materialize them. The regression test generates two fresh projects and
|
|
1399
|
+
compares every record and file byte before checking the filled example with
|
|
1400
|
+
zero refusals and zero warnings.
|
|
1401
|
+
|
|
1402
|
+
Apply results return in review feedback as `feedback[].context.applied`.
|
|
1403
|
+
Keep the JSON written by `rig-review feedback` in the project and record one
|
|
1404
|
+
applied round on the next version as `review_origin`:
|
|
1405
|
+
|
|
1406
|
+
```json
|
|
1407
|
+
{
|
|
1408
|
+
"feedback": { "path": "evidence/review-feedback.json", "sha256": "<file SHA-256>" },
|
|
1409
|
+
"source_version": 1,
|
|
1410
|
+
"feedback_id": "<feedback item id>",
|
|
1411
|
+
"applied": { "schema": "rig-review-applied/1", "...": "complete context.applied object" }
|
|
1412
|
+
}
|
|
1413
|
+
```
|
|
1414
|
+
|
|
1415
|
+
The containing version is the next-version link. `source_version` names the
|
|
1416
|
+
immediately preceding version of the same kind. Copy the selected item's
|
|
1417
|
+
complete non-null `context.applied` into `applied`, preserving every field.
|
|
1418
|
+
A build made without feedback records `review_origin: null`, including the
|
|
1419
|
+
filled example. This declaration is independent of human `answers_feedback`.
|
|
1420
|
+
|
|
1421
|
+
The check binds the feedback's bytes, selected item and applied result to the
|
|
1422
|
+
source package's config, handoff files and inspected compiled model. In the
|
|
1423
|
+
released folder adapter, `reviewedSource.rig` identifies that compiled model
|
|
1424
|
+
and `motion` is null; producer rig and motion hashes live in `handoff.files`.
|
|
1425
|
+
The retained feedback is a single-build `rig-review-session/1` export.
|
|
1426
|
+
Record the resulting version's outputs, hashes and provenance and write its
|
|
1427
|
+
review package as usual. This chain records the applied result and the next
|
|
1428
|
+
build's declared origin. Create does not execute the Apply or build.
|
|
1429
|
+
|
|
1430
|
+
A missing declaration on a version dated before
|
|
1431
|
+
`APPLIED_REVIEW_SINCE = 2026-11-06T00:00:00Z`, or without a readable date,
|
|
1432
|
+
warns to preserve in-flight history. From that boundary it is refused.
|
|
1433
|
+
Pre-interview versions retain their historical contract.
|
|
1434
|
+
|
|
1435
|
+
## Per-ask guide coverage
|
|
1436
|
+
|
|
1437
|
+
Rig waypoint guides carry `asks: [{ "id": "tracks", "state": "user" },
|
|
1438
|
+
{ "id": "extent", "state": "delegated" }, …]`, naming each applicable ask
|
|
1439
|
+
in `src/waypoints.ts`. A user entry points to the guide's existing `verbatim`
|
|
1440
|
+
and `value`; it is a recorded interpretation, not automatic proof that prose
|
|
1441
|
+
answers a question. A delegated entry records an explicit hand-off in those
|
|
1442
|
+
words and uses the guide's `agent_decision`. Its free-text `covers` still names
|
|
1443
|
+
the delegated remainder; its `value` and `reasoning` are written before approval.
|
|
1444
|
+
Whole-guide delegations list every ask as delegated. Not-applicable waypoints
|
|
1445
|
+
need no coverage. `states` and `transitions` apply only to `fullscreen.game_logic`; `tracks`
|
|
1446
|
+
and `blink` apply to other rig types. Post items are outside this contract.
|
|
1447
|
+
|
|
1448
|
+
The independent `ASK_COVERAGE_SINCE = 2026-11-05T00:00:00Z` boundary reads the
|
|
1449
|
+
resolved guide's own `at`, including inherited guides. An older or undated guide
|
|
1450
|
+
with no `asks` is warned about, preserving its exit code. An explicitly recorded
|
|
1451
|
+
list is checked regardless of age. Missing, unknown, duplicate or invalid entries
|
|
1452
|
+
must be fixed; free-text `agent_decision.covers` alone is not per-ask coverage.
|
|
1453
|
+
|
|
1454
|
+
|
|
1455
|
+
## Explicit adoption of the split interview
|
|
1456
|
+
|
|
1457
|
+
`interview.order: { "spec": "rig-create/stage-order@1", "adopted_at": "<clock ISO date>" }`
|
|
1458
|
+
is the only order switch. A date does not establish which contract was used.
|
|
1459
|
+
`init` writes this metadata. An old record keeps its old checks and gets one
|
|
1460
|
+
`STAGE_ORDER_LEGACY` warning: its old rig guides are historical answers, never
|
|
1461
|
+
certification that they were asked after parts. No signature, checkpoint hash
|
|
1462
|
+
or old version is rewritten. To adopt, preserve the old rig guides whole in
|
|
1463
|
+
that question's `history[]`, ask fresh answers against accepted parts, re-sign
|
|
1464
|
+
`interview` after adopting to approve the changed interview, and record the first
|
|
1465
|
+
human `signoff rigging-interview`. That writer records adoption
|
|
1466
|
+
and the live parts/structure context. Stage movement remains a separate human
|
|
1467
|
+
act, as for existing forward sign-offs. The filled legacy example is frozen in
|
|
1468
|
+
`templates/legacy-example-project.json`. Read under the current 2.16.0 pin it warns with that order warning plus
|
|
1469
|
+
`QUESTION_SET_STALE`, because its frozen question set remains at 2.14.1, and it is refused by the build-identity gate
|
|
1470
|
+
(`REVIEW_PACKAGE_CONFIG_MISMATCH` and `REVIEW_PACKAGE_PARTS_MISMATCH` on v1 and v2, plus
|
|
1471
|
+
`REVIEW_PACKAGE_PART_FILE_MISMATCH` for each of three approved part images missing per version), because its versions, dated after
|
|
1472
|
+
`BUILD_IDENTITY_SINCE`, claim configs and parts their review packages do not carry. Its rig-review and direction-review signatures also postdate `SIGNOFF_TARGET_SINCE` and lack targets, so each refuses `SIGNOFF_TARGET_MISSING`. Its interview, two plan-approved and post-interview signatures also lack answer bindings and each refuses `SIGNOFF_ANSWERS_MISSING`. Its bytes stay frozen.
|
|
1473
|
+
The new `example-project.json` is a synthetic new-order narrative at 0/0.
|
|
1474
|
+
|
|
1475
|
+
Framing and source (`seethrough`, `assemble`) are the first interview. A
|
|
1476
|
+
`plan-approved` signature covers only those parts steps in new-order records.
|
|
1477
|
+
The later `rigging-interview` covers `bones`, `meshes`, `constraints`, `motion`.
|
|
1478
|
+
Keep `phase: "rig"`; approval is resolved by step, not phase alone. Legacy
|
|
1479
|
+
`plan-approved` retains its old all-rig-step coverage. Post approval is unchanged.
|
|
1480
|
+
`plan.drafted_at` dates the parts plan; `plan.rigging_drafted_at` dates the later
|
|
1481
|
+
rigging plan, so drafting it does not invalidate the earlier parts signature.
|
|
1482
|
+
Each plan signature hashes only its covered steps. `--steps` cannot cross
|
|
1483
|
+
approval ownership. Pending later steps/answers may remain unfilled before their
|
|
1484
|
+
interview; production execution still requires its proper human approval.
|
|
1485
|
+
|
|
1486
|
+
The hand pass is the correction loop of `rig-review`, including rig and
|
|
1487
|
+
animation inspection, described corrections and direct edits. It adds no stage
|
|
1488
|
+
or acceptance authority. Existing `review_origin`/applied-review chains retain
|
|
1489
|
+
producer feedback; `review_origin: null` remains legal for a first rig. A
|
|
1490
|
+
separate choice-answer schema and correction-path union are subsequent cards.
|
|
1491
|
+
|
|
1492
|
+
## Labelled draft rigs and structure decisions
|
|
1493
|
+
|
|
1494
|
+
After assemble, `parts`/`parts-review` may use a proposed draft to inspect meshes
|
|
1495
|
+
and refine chest structure before asking the production rigging plan. The
|
|
1496
|
+
draft's proposed bones and weights are not the person's rigging answers.
|
|
1497
|
+
|
|
1498
|
+
```sh
|
|
1499
|
+
rig-create draft-rig <id> [<dir>] --config <path> --from <output dir> [--parts <dir>] [--json]
|
|
1500
|
+
rig-create structure-snapshot [<dir>] --draft <id> --verdict <path> --out <path>
|
|
1501
|
+
rig-create signoff parts-review --by <who> --evidence <path> --diff-report <path> --component '<id>=<status>:<why>' --draft <id> --structure-file <path> --verbatim-file <file>
|
|
1502
|
+
```
|
|
1503
|
+
|
|
1504
|
+
The recorder reads existing output; it runs no producer or review command.
|
|
1505
|
+
It appends `drafts[]` with `{ id, kind: "draft-rig", at, producer: {name,version},
|
|
1506
|
+
config: {path,sha256}, parts: {path,files:[{path,sha256}]}, files:[{path,sha256}] }`.
|
|
1507
|
+
`parts.files` binds `parts.json`, `parts/*` and the raster `parts.json` itself
|
|
1508
|
+
declares under `painting_in_rig`; an undeclared file is not bound, and a draft
|
|
1509
|
+
recorded before the declared raster was bound warns `DRAFT_DECLARED_FILE_UNBOUND`.
|
|
1510
|
+
`producer` is the `package` of the `rig-run/1` `run.json` parts writes beside
|
|
1511
|
+
`rig.json` (`<out>/run.json`, or `<root>/rig/run.json` in a build root), which
|
|
1512
|
+
`files` already binds; a malformed or other-spec stamp refuses under its
|
|
1513
|
+
`RUN_RECORD_*` code. Without one, `producer` is the installed `@rig-c/parts` and
|
|
1514
|
+
the check warns `DRAFT_PRODUCER_ASSUMED`; a recorded producer that disagrees with
|
|
1515
|
+
its bound stamp warns `DRAFT_PRODUCER_MISMATCH`.
|
|
1516
|
+
All files must resolve under `derived/drafts/<id>/`. Standalone `rig --out`
|
|
1517
|
+
requires explicit `--parts`; only an unambiguous build root containing
|
|
1518
|
+
`parts.json`, `parts/` and `rig/` supplies those inputs implicitly. Ambiguous
|
|
1519
|
+
layouts refuse, and new registrations require exactly one stack candidate at
|
|
1520
|
+
`D/recomposite_rig.png` or, when the recorded parts directory D is named `rig`,
|
|
1521
|
+
`D/../render/recomposite_rig.png`; missing or ambiguous candidates refuse with
|
|
1522
|
+
`DRAFT_RIG_STACK`, remedied by re-running `rig-parts build` into the draft output
|
|
1523
|
+
or keeping assemble's `render/` beside `rig/`. Symlinks out of the root and changes to present recorded input bytes refuse.
|
|
1524
|
+
Absent ignored draft files warn as `DRAFT_RIG_UNAVAILABLE`, including after a
|
|
1525
|
+
clone; they do not invalidate an accepted record. Present files still verify
|
|
1526
|
+
even when another file is absent.
|
|
1527
|
+
These are **create-owned artifact identities**. The config/output association
|
|
1528
|
+
is a declaration, not measured reproducibility or producer provenance. There
|
|
1529
|
+
is no retained producer handoff file here: review constructs its own live
|
|
1530
|
+
handoff when it opens the draft.
|
|
1531
|
+
|
|
1532
|
+
Drafts allocate no production version number. A declared draft, reserved draft
|
|
1533
|
+
path or registered draft artifact cannot be reviewed, packaged or handed off
|
|
1534
|
+
as a `versions[]` rig. A separately authorised production build gets its own
|
|
1535
|
+
output root and numbered version. This checks declared artifact identity;
|
|
1536
|
+
it does not claim to recognise untracked byte copies after their identity is
|
|
1537
|
+
stripped. Identical model hashes alone are not blacklisted.
|
|
1538
|
+
|
|
1539
|
+
`--structure-file` retains a declaration snapshot approved by the human parts
|
|
1540
|
+
sign-off, not a fabricated review export. `structure-snapshot` writes it:
|
|
1541
|
+
|
|
1542
|
+
```json
|
|
1543
|
+
{
|
|
1544
|
+
"schema": "rig-create/structure-decisions@0",
|
|
1545
|
+
"draft_id": "sample",
|
|
1546
|
+
"config": { "path": "derived/drafts/sample/config.json", "sha256": "<config hash>" },
|
|
1547
|
+
"entries": [ { "path": "/meshes/torso", "value": { "contour": { "regions": [] } } } ]
|
|
1548
|
+
}
|
|
1549
|
+
```
|
|
1550
|
+
|
|
1551
|
+
Each entry is the complete exact `meshes.<part>` declaration, including
|
|
1552
|
+
`contour.bust` or `contour.regions` where present. Paths use JSON Pointer
|
|
1553
|
+
escaping. Explicit `entries: []` is legal when no declarations are carried.
|
|
1554
|
+
|
|
1555
|
+
A production config may differ from this snapshot only when a live (not
|
|
1556
|
+
reopened) `rigging-interview` sign-off with `checkpoint: null` follows that
|
|
1557
|
+
parts-review sign-off, and `interview.waypoints[meshes].guide.at` is strictly
|
|
1558
|
+
after parts-review and no later than the rigging-interview sign-off. The
|
|
1559
|
+
interview approval must already exist at the version's build time. Otherwise,
|
|
1560
|
+
answer the rigging meshes guide, or renew parts-review.
|
|
1561
|
+
|
|
1562
|
+
`rig-version` computes `versions[n].provenance.structure_delta` from the
|
|
1563
|
+
retained snapshot and config: an ordered list of `{entry, snapshot, version}`,
|
|
1564
|
+
where `entry` is the snapshot JSON Pointer and the other fields are complete
|
|
1565
|
+
declarations (`version: null` means absent). It omits the field when unchanged.
|
|
1566
|
+
The check recomputes it and refuses `STRUCTURE_DELTA_MISMATCH` on disagreement.
|
|
1567
|
+
`interview --check` and `next` WARN `STRUCTURE_DELTA_REVIEW` with the entry count;
|
|
1568
|
+
the rig-review verdict and sign-off cover changed structure. No producer
|
|
1569
|
+
measurement or new review act is introduced.
|
|
1570
|
+
|
|
1571
|
+
|
|
1572
|
+
The parts verdict names no per-declaration approval: an approved verdict
|
|
1573
|
+
approves the reviewed draft. So `structure-snapshot` copies `draft_id` and the
|
|
1574
|
+
draft's own `config: {path, sha256}` binding, and writes one entry per key of
|
|
1575
|
+
that config's `meshes`, in the config's key order, each value copied exactly.
|
|
1576
|
+
A config without `meshes` gives `entries: []`. It computes no mesh. It reads
|
|
1577
|
+
`--verdict` with the parts-review sign-off's own reader, so a verdict that is
|
|
1578
|
+
not approved refuses `PARTS_VERDICT_NOT_APPROVED`, and a changes-requested
|
|
1579
|
+
review gives no snapshot. The verdict must also review that draft's parts: both
|
|
1580
|
+
writers and the check match its `source.files[]` against the draft's
|
|
1581
|
+
`parts.files[]` and `files[]` by sha256, never by path, leaving out only the
|
|
1582
|
+
declared `painting_in_rig` raster. Every verdict file must be one of the
|
|
1583
|
+
draft's, and every `parts.files[]` entry must be in the verdict; any other
|
|
1584
|
+
difference is refused as `PARTS_VERDICT_DRAFT_MISMATCH`. A parts view that
|
|
1585
|
+
shows meshes also lists `rig.json`, `mesh_report.json` and the mesh rasters,
|
|
1586
|
+
which the draft binds in `files[]`; an output the verdict does not list is not
|
|
1587
|
+
missing, since a parts-only view lists none. It refuses an unknown draft
|
|
1588
|
+
(`STRUCTURE_SNAPSHOT_DRAFT_UNKNOWN`), a draft config whose bytes changed since
|
|
1589
|
+
the draft was recorded (`STRUCTURE_SNAPSHOT_CONFIG_CHANGED`), and an `--out`
|
|
1590
|
+
that is not a literal project path (`STRUCTURE_SNAPSHOT_OUT_INVALID`), is under
|
|
1591
|
+
an ignored root (`STRUCTURE_SNAPSHOT_OUT_IGNORED`) or already holds different
|
|
1592
|
+
bytes (`STRUCTURE_SNAPSHOT_OUT_EXISTS`). The candidate is validated with the
|
|
1593
|
+
rules the check applies to a signed snapshot before any byte is written, and a
|
|
1594
|
+
refusal leaves no new or changed file. An `--out` that already holds the same
|
|
1595
|
+
bytes is left as it is and the command succeeds. It writes only `--out`, never
|
|
1596
|
+
`project.json`; `signoff parts-review --draft <id> --structure-file <path>`
|
|
1597
|
+
then binds the file.
|
|
1598
|
+
The snapshot must live outside ignored roots, such as `evidence/`; the writer
|
|
1599
|
+
refuses paths or aliases into ignored storage. The writer hashes the retained
|
|
1600
|
+
file and checks its config/declaration identity when the draft config is
|
|
1601
|
+
available. A clone still checks the snapshot hash/schema and its recorded
|
|
1602
|
+
config identity, without requiring absent regenerable draft artifacts. It
|
|
1603
|
+
stores `draft_id` and `structure:{path,sha256}` on the parts-review sign-off.
|
|
1604
|
+
It does not apply patches or measure geometry. The later interview reads this
|
|
1605
|
+
human-approved snapshot instead of re-asking its structure as a guess.
|
|
1606
|
+
`signoff rigging-interview` resolves its `accepted_parts:{signoff_at,evidence}`
|
|
1607
|
+
and `structure` from the live human parts review and stores a shared
|
|
1608
|
+
`interview.rigging_context`, outside the answer union. Fresh rig guides must
|
|
1609
|
+
follow that approval and precede their rigging signature. Contradictory retained
|
|
1610
|
+
production config declarations require renewed approval rather than a silent
|
|
1611
|
+
override. Each production version uses the latest structure approval live at
|
|
1612
|
+
its build date, with reopen supersession evaluated at that same date; a later
|
|
1613
|
+
approval does not impose its declarations on old versions. Both new-order writers validate the full candidate before writing.
|
|
1614
|
+
|
|
1615
|
+
Mesh sign-off UI evidence from review#365 is optional in this contract, not a
|
|
1616
|
+
shipped-capability claim or mandatory gate. Review/producer owners validate the
|
|
1617
|
+
actual editors and mesh rendering. Create's synthetic tests prove record
|
|
1618
|
+
binding and refusals, not the physical correctness of a chest rebuild.
|
|
1619
|
+
|
|
1620
|
+
The synthetic new-order record and draft declaration files reproduce with
|
|
1621
|
+
`bun scripts/generate-example-order.ts <fresh scratch dir> --check`. The frozen
|
|
1622
|
+
legacy record is byte-preserved; generated evidence is never hand-written.
|
|
1623
|
+
|
|
1624
|
+
The [synthetic bound chain](../templates/example-chain/README.md) carries one
|
|
1625
|
+
project from its labelled draft and approved parts through a packaged rig,
|
|
1626
|
+
rig-review, signed post interview, authored direction and direction-review.
|
|
1627
|
+
`bun scripts/generate-example-chain.ts <fresh scratch dir> --check` reproduces
|
|
1628
|
+
it. The public writers record signoffs, rig/post review verdicts, the review
|
|
1629
|
+
package, immutable input inventory and authored direction. The parts verdict
|
|
1630
|
+
is a synthetic review-tool export from `tests/parts-package.ts`, recorded as a producer step.
|
|
1631
|
+
`chain.json` names seed declarations covering forward stage movement,
|
|
1632
|
+
`plan.steps (setup and status progress)` with `split.parts`, the rig-version
|
|
1633
|
+
declaration. Its source inventory is written by `input add`. Each seed
|
|
1634
|
+
declares its consuming command and records that command's step index. Status progress is forward-only,
|
|
1635
|
+
and signed plan fields stay bound. Post steps are added after rig-review,
|
|
1636
|
+
before the post-interview options.
|
|
1637
|
+
The direction binds that package's compiled model, built from the approved
|
|
1638
|
+
parts. Its comparison report records the identical painting and assembly.
|
|
1639
|
+
The retained setup still is the assembly recomposite. Rendered motion and
|
|
1640
|
+
camera behaviour require separate producer validation.
|
|
1641
|
+
|
|
1642
|
+
## Correction paths: described and made
|
|
1643
|
+
|
|
1644
|
+
A correction lives in project-level `corrections[]`, including at `parts-review`
|
|
1645
|
+
before a production version exists. Adopt explicitly with `correction --adopt`;
|
|
1646
|
+
this writes `corrections_contract: {schema: "rig-create/corrections@1", adopted_at}`.
|
|
1647
|
+
No stage or interview-order schema changes. New projects and the filled example
|
|
1648
|
+
adopt it with an empty list. Older records get `CORRECTION_PATH_LEGACY` without
|
|
1649
|
+
inventing corrections, rewriting dates, or changing their existing origins.
|
|
1650
|
+
|
|
1651
|
+
Every record has `schema: "rig-create/correction@1"` (or `@2` for authored
|
|
1652
|
+
direction descriptions and made direction patches), `id`, `path`, `by`, `at`,
|
|
1653
|
+
`verbatim`, optional text `source`, `stage`, `on`, `artifact`, `outcome` and
|
|
1654
|
+
`resolves`. `path` is `described` or `made`. The stage is `parts-review`,
|
|
1655
|
+
`rig-review` or `direction-review`. `on` is the source identity; `outcome:null`
|
|
1656
|
+
means open. A closure sets outcome once and adds `closure:{by:"agent",at,reasoning}`
|
|
1657
|
+
with create's clock. That note is an agent declaration, never a human quote or
|
|
1658
|
+
acceptance. `resolves:null` or an earlier correction id records an append-only
|
|
1659
|
+
replacement; the predecessor remains history and is discharged only by a
|
|
1660
|
+
completed valid replacement.
|
|
1661
|
+
|
|
1662
|
+
- `described` uses `artifact:{kind:"description"}` and unchanged human words.
|
|
1663
|
+
- A made preview uses `artifact:{kind:"config-patch",patch:{path,sha256},
|
|
1664
|
+
state:"preview/pending",feedback:null}`. Its raw file hash is its own identity;
|
|
1665
|
+
it makes no claim about review's `patchSha256`.
|
|
1666
|
+
- A made session uses `artifact:{kind:"config-patch",state:"preview/pending",
|
|
1667
|
+
feedback:{file:{path,sha256},item_id}}`. The patch is the selected session
|
|
1668
|
+
item's `context.applied.patch`. With a bound result and passing producer
|
|
1669
|
+
summary, closure changes state to `applied-and-checked`. An optional retained
|
|
1670
|
+
preview `patch` must be parsed-deep-equal to the embedded patch. Create retains
|
|
1671
|
+
`applied.patchSha256` as review's claim and never recomputes it.
|
|
1672
|
+
- Other made operations use `{kind:"unsupported",operation,reason,files,
|
|
1673
|
+
producer_schema}`. `operation` is `mesh-delta`, `retarget`, `keyed-animation`
|
|
1674
|
+
or `other`. For example, `rig-review-applied/3` is a mesh delta, not a config
|
|
1675
|
+
patch. Its opaque producer evidence is retained; completion stays pending.
|
|
1676
|
+
|
|
1677
|
+
The pinned patch is exactly `rig-review-config-patch/1` with the five keys
|
|
1678
|
+
`schema`, `config_sha256`, `ops`, `producer:{name,version}`, `op:{cmd,args}`.
|
|
1679
|
+
`ops` contains 1–256 add/replace `{op,path,value,name?}` or remove `{op,path,name?}`
|
|
1680
|
+
operations, with nonempty RFC 6901 pointers and the published non-path flag
|
|
1681
|
+
allowlist. The session is `rig-review-session/1`, the checked patch Apply is
|
|
1682
|
+
`rig-review-applied/2` and its summary is `rig-review-check-summary/1`. Source
|
|
1683
|
+
config, inspected model and handoff input hashes bind to the source. Summary
|
|
1684
|
+
`pass:true`, `exitCode:0`, `gate:true`, a nonempty line and at least one `PASS`
|
|
1685
|
+
bar are required. A named `FAIL` or a status outside parts 2.16.0's
|
|
1686
|
+
`PASS | FAIL | SKIP | WARN | CLEAR | REPORTED | UNCLASSIFIED` set refuses.
|
|
1687
|
+
A bar named skipped by the producer line cannot be `PASS` in the map.
|
|
1688
|
+
Report-only SKIPs may be absent from that line. All accepted statuses remain
|
|
1689
|
+
verbatim by name. Resolution reasoning and text output state the PASS count,
|
|
1690
|
+
every non-PASS name/status and the retained producer line. The
|
|
1691
|
+
outcome's retained compiled-model SHA must equal `applied.modelHash`. A built
|
|
1692
|
+
preview or unknown/failed check cannot claim checked completion. Optional
|
|
1693
|
+
published route/files/environment context is retained. Optional `stageInputHash`
|
|
1694
|
+
must be a 64-lowercase-hex SHA-256, accepted as recorded; create cannot re-derive it from the package.
|
|
1695
|
+
Summary `source` may be absent or `remesh`, `retune`, or `check`, under the same producer-summary gates. No patch application,
|
|
1696
|
+
producer measurement, build or diff is recomputed by create.
|
|
1697
|
+
|
|
1698
|
+
@1 identities are `{kind:"rig"|"post",n,config:{path,sha256},model:{path,sha256}}`,
|
|
1699
|
+
`{kind:"parts",manifest:{path,sha256},files:[{path,sha256}]}`, or
|
|
1700
|
+
`{kind:"draft",id,config,parts,model}` (parts is `{manifest,files}`).
|
|
1701
|
+
A rig binds to its version's provenance config and frozen review package model.
|
|
1702
|
+
An @1 post binds config to `provenance.config`, and model to one declared retained
|
|
1703
|
+
output explicitly selected by `--model-file`; it is output identity only,
|
|
1704
|
+
without a parts, rig or CG claim. `config-patch/1` is rig/draft-only: a direct
|
|
1705
|
+
post edit is unsupported. A described post closure requires changed output bytes
|
|
1706
|
+
under @1, or a different bound direction document hash under @2.
|
|
1707
|
+
Parts identities retain a complete sorted parts.json + parts/ file inventory.
|
|
1708
|
+
Draft identities match the labelled draft inventory, including a retained
|
|
1709
|
+
compiled model when that reviewed identity is selected. Missing regenerable
|
|
1710
|
+
files never count as correction completion: retain source and result bytes.
|
|
1711
|
+
Paths must be literal project-relative regular files without symlink traversal;
|
|
1712
|
+
patch/session evidence belongs in tracked evidence. Outputs and draft files
|
|
1713
|
+
must survive handoff/clone when used to close a correction.
|
|
1714
|
+
|
|
1715
|
+
An ordinary correction may name the historical version actually inspected.
|
|
1716
|
+
An explicit `resolves` replacement must name the latest source at its capture
|
|
1717
|
+
time; a future source timestamp always refuses.
|
|
1718
|
+
|
|
1719
|
+
A result must be distinct, later and changed. Version and draft times bind the
|
|
1720
|
+
ordering; for raw parts, create's later closure records the declared response
|
|
1721
|
+
and changed inventory without inventing a producer timestamp. A rig-version
|
|
1722
|
+
made result retains the existing matching `review_origin` chain, including its
|
|
1723
|
+
immediate-predecessor constraint. A first rig may still have `review_origin:null`;
|
|
1724
|
+
no fake preceding rig is made for stage-1 corrections. `on_items` still names
|
|
1725
|
+
interview answers and `answers_feedback` still links verdicts; neither is an
|
|
1726
|
+
operation inventory. A correction does not supply a missing guide citation.
|
|
1727
|
+
|
|
1728
|
+
```sh
|
|
1729
|
+
rig-create correction --adopt <dir>
|
|
1730
|
+
rig-create correction record <dir> --id refine --path described --stage rig-review \
|
|
1731
|
+
--version 1 --by reviewer --verbatim-file words.txt
|
|
1732
|
+
rig-create correction record <dir> --id tune --path made --stage rig-review \
|
|
1733
|
+
--version 1 --by user --patch-file evidence/patch.json --verbatim-file words.txt
|
|
1734
|
+
rig-create correction record <dir> --id applied --path made --stage rig-review \
|
|
1735
|
+
--version 1 --by user --feedback-file evidence/session.json --item change-1
|
|
1736
|
+
rig-create correction resolve tune <dir> --version 2 --by agent --reasoning-file reasoning.txt \
|
|
1737
|
+
--applied-feedback evidence/session.json --feedback-id change-1
|
|
1738
|
+
```
|
|
1739
|
+
|
|
1740
|
+
Use `--draft <id>` or `--parts-file <retained parts identity JSON>` instead of
|
|
1741
|
+
`--version`; post versions require `--model-file`. `--resolves <id>` appends a
|
|
1742
|
+
replacement. A made record requires `--by user`; its clock is create's ingest
|
|
1743
|
+
time. A session item supplies its exact summary as verbatim, otherwise use
|
|
1744
|
+
`--verbatim-file`. Review does not invoke create or write project.json. There
|
|
1745
|
+
is no new review correction-export schema and no `--correction-file`.
|
|
1746
|
+
Record, resolve and check share validation; writes use a same-directory temporary
|
|
1747
|
+
file and atomic rename. Refusals leave project.json byte-identical. Unrelated
|
|
1748
|
+
pre-existing interview holes do not prevent capture, but a writer cannot add a
|
|
1749
|
+
new refusal or bypass correction validation.
|
|
1750
|
+
|
|
1751
|
+
Stage-1 corrections use parts/drafts outside versions. The parts-review signoff
|
|
1752
|
+
must approve the corrected draft and structure snapshot (or a draft using the
|
|
1753
|
+
corrected parts inventory). Production versions still compare mesh declarations
|
|
1754
|
+
to that snapshot. Structure changes after approval require the existing reopen
|
|
1755
|
+
and fresh snapshot, never a correction override.
|
|
1756
|
+
|
|
1757
|
+
A valid reopen supersedes the same stage suffix as signoffs: entries at or
|
|
1758
|
+
before its epoch remain history. A narrower later reopen cannot resurrect an
|
|
1759
|
+
earlier suffix. Recording under a live scoped approval requires reopening first;
|
|
1760
|
+
corrections do not move stages or sign plan steps themselves.
|
|
1761
|
+
|
|
1762
|
+
| State | check | approval / handoff | reopen | provenance | structure | CG |
|
|
1763
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
1764
|
+
| described-open | pending/WARN | pending; attempted approval refuses | pass history | pending response, no citation authority | pass existing checks | pass existing checks |
|
|
1765
|
+
| described-linked | pass declared linkage | pass correction gate only | pass history | pass linkage, citations still required | pass if snapshot matches, else refuse | pass if ordinary gates pass, else refuse |
|
|
1766
|
+
| made preview/pending | pending/WARN | pending; attempted approval refuses | pass history | pending | pass current snapshot only | pass current config only |
|
|
1767
|
+
| made applied-and-checked | pass exact result binding | pass correction gate only | pass history | pass linkage, not a replacement citation | pass if snapshot matches | pass if ordinary gates pass |
|
|
1768
|
+
| invalid checked claim | refuse | refuse | no authority | refuse claimed linkage | mismatch refuses | no fabricated gate pass |
|
|
1769
|
+
| unsupported | pending/WARN | pending; attempted approval refuses | pass history | pending opaque evidence | pass existing checks | pass existing checks |
|
|
1770
|
+
| stage-1 parts/draft overlay | pass retained identity; absent closure bytes refuse | pending until corrected draft/parts is approved | parts-review suffix | identity only | pass approved corrected snapshot | pass / not applicable to parts |
|
|
1771
|
+
| rig-version overlay | pass source/result hashes | pending until correction and normal review complete | rig-review suffix | existing citations required | existing snapshot comparison | normal gates required |
|
|
1772
|
+
| direction-review post overlay | pass retained declared output | pending until changed output and normal review complete | direction-review suffix | post citations still required | no new rig claim | no new CG claim |
|
|
1773
|
+
| validly superseded overlay | pass history validation | pass exclusion from current obligations | pass only for valid human reopen | historical only | historical context | existing historical gates remain |
|
|
1774
|
+
|
|
1775
|
+
The overlays combine with path state; refuse overrides pending, which overrides
|
|
1776
|
+
pass. A pass never waives existing gates or manufactures acceptance.
|
|
1777
|
+
|
|
1778
|
+
The small consumer fixture is `tests/fixtures/correction-path/`, generated through
|
|
1779
|
+
writers by `scripts/generate-correction-fixture.ts <fresh dir> [--check]` before
|
|
1780
|
+
full-example integration. Its checked positive is explicitly **synthetic
|
|
1781
|
+
shape-only**, not a measured producer-gate result; see its README. Every retained
|
|
1782
|
+
file uses its real byte hash. The frozen legacy example's exact warning set is
|
|
1783
|
+
`QUESTION_SET_STALE`, `STAGE_ORDER_LEGACY`, `CHOICE_ANSWERS_LEGACY`,
|
|
1784
|
+
`CORRECTION_PATH_LEGACY`, and it is refused by the build-identity gate and by
|
|
1785
|
+
`SIGNOFF_TARGET_MISSING` twice and `SIGNOFF_ANSWERS_MISSING` four times as described above; the current filled example stays at 0/0.
|
|
1786
|
+
|
|
1787
|
+
### Masked part-image repaints
|
|
1788
|
+
|
|
1789
|
+
When `assemble` levers are exhausted and one part image needs a bounded hand pass
|
|
1790
|
+
before `parts rig`, record the edit as a `made` correction at `parts-review` on
|
|
1791
|
+
the parent draft before registering the rebuilt draft:
|
|
1792
|
+
|
|
1793
|
+
```sh
|
|
1794
|
+
rig-create correction record <dir> --id repaint-topwear --path made --stage parts-review \
|
|
1795
|
+
--draft <parent-id> --part topwear --part-image-file evidence/topwear-after.png \
|
|
1796
|
+
--mask-file evidence/topwear-mask.png --tool "gemini-image-probe r5 + mask composite with tone match"
|
|
1797
|
+
```
|
|
1798
|
+
|
|
1799
|
+
The record carries `by: "agent"`, `verbatim: null`, and
|
|
1800
|
+
`artifact: { kind: "part-image", draft, part, before, after, mask, tool }`, where
|
|
1801
|
+
`before`, `after` and `mask` are `{ path, sha256 }` bindings and `tool` is free
|
|
1802
|
+
text naming the lever used. Its `on` (and an explicit `outcome`) is the draft
|
|
1803
|
+
identity `{ kind: "draft", id, config, parts, model: null }`: a part-image edit
|
|
1804
|
+
changes one part file, so it binds the draft's parts manifest and parts files and
|
|
1805
|
+
no compiled model, and the parent draft may be one recorded from a standalone
|
|
1806
|
+
`parts rig` output with no `skeleton.model.json`. Whether a later draft changed
|
|
1807
|
+
is read from its parts inventory. A part-image record that bound a model is
|
|
1808
|
+
still read, and its model must match the draft. Other draft corrections (`described`, a config
|
|
1809
|
+
patch Apply) still bind the draft's one retained compiled model. Both the writer and `check` decode the PNGs and
|
|
1810
|
+
refuse when `before` is not the parent draft's bound `<parts.path>/parts/<part>.png`
|
|
1811
|
+
or `after` makes no change (`CORRECTION_PART_IMAGE_BEFORE`), when `mask` or
|
|
1812
|
+
`after` dimensions differ from `before` (`CORRECTION_PART_IMAGE_MASK_SIZE`), when
|
|
1813
|
+
`after` differs from `before` outside `mask` (`CORRECTION_PART_IMAGE_OUTSIDE_MASK`),
|
|
1814
|
+
or when `after` increases alpha at any pixel (`CORRECTION_PART_IMAGE_ADDED_ALPHA`).
|
|
1815
|
+
A later `draft-rig` (new id) whose bound `<parts.path>/parts/<part>.png` matches
|
|
1816
|
+
`after.sha256` resolves the correction automatically (or explicitly via
|
|
1817
|
+
`correction resolve --draft <new-id> --by agent --reasoning-file <file>`). A draft
|
|
1818
|
+
whose bound `parts/<part>.png` matches a `part-image` correction's `after.sha256`
|
|
1819
|
+
whose correction is withdrawn, superseded, dated after the draft, or on another
|
|
1820
|
+
part/draft refuses as `DRAFT_PART_REPAINT_UNRECORDED`.
|
|
1821
|
+
|
|
1822
|
+
### Authored camera direction (create#92)
|
|
1823
|
+
|
|
1824
|
+
Create owns the authored camera and timing document, not depth or `config.turn`.
|
|
1825
|
+
Review previews through the published `@rig-c/play` runtime (review README,
|
|
1826
|
+
*delivery flow*); create renders nothing. A document is authored data, not proof
|
|
1827
|
+
of a rendered take, seamless looping, source-animation extent, or a parts gate.
|
|
1828
|
+
|
|
1829
|
+
Adopt with `rig-create direction --adopt <dir>`. It writes
|
|
1830
|
+
`direction_contract:{schema:"rig-create/direction-contract@1",adopted_at,
|
|
1831
|
+
grandfathered_posts}`. The sorted, unique post numbers are existing posts at
|
|
1832
|
+
adoption. They remain exempt from a missing direction document; explicit
|
|
1833
|
+
bindings are always checked. There is no date switch and no new legacy warning.
|
|
1834
|
+
Do not change that list to exempt new work. Existing correction@1 records are
|
|
1835
|
+
not migrated or rewritten.
|
|
1836
|
+
|
|
1837
|
+
```sh
|
|
1838
|
+
rig-create direction write 5 <dir> --file evidence/authored-direction.json --rig 2
|
|
1839
|
+
rig-create direction check 5 <dir> --json
|
|
1840
|
+
```
|
|
1841
|
+
|
|
1842
|
+
The writer registers a new post version and never overwrites a previous one.
|
|
1843
|
+
The exact input bytes become `evidence/direction/v5.json`, schema
|
|
1844
|
+
`rig-create/direction@1`. `provenance.config`, `provenance.direction`, and one
|
|
1845
|
+
`outputs[]` entry all bind that same `{path,sha256}`. It is a direction output,
|
|
1846
|
+
not a compiled model or movie. `provenance.sections.camera` and `.timing` carry
|
|
1847
|
+
the same citations as the document. Metadata, rig bindings and citations are
|
|
1848
|
+
not additional executable config sections. Setup-painting requirements apply
|
|
1849
|
+
to existing build configs as before, not to this camera document.
|
|
1850
|
+
|
|
1851
|
+
The closed document has precisely:
|
|
1852
|
+
|
|
1853
|
+
| Field | Closed contents |
|
|
1854
|
+
| --- | --- |
|
|
1855
|
+
| `schema` | `rig-create/direction@1` |
|
|
1856
|
+
| `rig` | `{version,model:{path,sha256}}`; accepted rig's review-package compiled model, never config-only identity |
|
|
1857
|
+
| `take` | `{duration,loop}`; positive finite seconds and boolean |
|
|
1858
|
+
| `camera` | `{space:"rig-world-y-up",keys:[{time,box:{x,y,width,height},easing}]}` |
|
|
1859
|
+
| `timing` | `{keys:[{time,source_time,easing}]}` |
|
|
1860
|
+
| `citations` | `{camera,timing}`; each `{guide,asks,quote}` or `{guide,asks,delegated:true}` |
|
|
1861
|
+
|
|
1862
|
+
The model path is
|
|
1863
|
+
`derived/review/v<R>/out/check/build/skeleton.model.json`; its exact bytes must
|
|
1864
|
+
match the corresponding review-package inventory SHA. A new write needs the
|
|
1865
|
+
latest live accepted rig and existing handoff still/signature gates. Missing
|
|
1866
|
+
model bytes refuse; create never regenerates them. A post's `rig_version` must
|
|
1867
|
+
match `rig.version`. Historical documents may retain their historical rig;
|
|
1868
|
+
current authoring and direction approval cannot use a superseded rig.
|
|
1869
|
+
|
|
1870
|
+
Boxes describe the visible rectangle in rig world coordinates, Y up. Coordinates
|
|
1871
|
+
are finite and sizes positive. A preview contains the box at its aspect ratio
|
|
1872
|
+
(letterbox; do not silently crop). Camera keys number 1–256, start at zero,
|
|
1873
|
+
strictly increase and stay in `[0,duration]`; the final box holds through the
|
|
1874
|
+
end. Timing keys number 2–256, start at zero and end at `duration`; their take
|
|
1875
|
+
times strictly increase, while finite nonnegative `source_time` is nondecreasing
|
|
1876
|
+
and permits holds. It maps take seconds to source-animation seconds, without
|
|
1877
|
+
FPS inference or a source-clip-duration claim. `loop` repeats the take clock.
|
|
1878
|
+
|
|
1879
|
+
Easing is exactly `linear`, `hold`, or `smoothstep`, attached to the segment
|
|
1880
|
+
starting at the key. `smoothstep(u)=u*u*(3-2*u)` with normalized segment time;
|
|
1881
|
+
interpolate box components/source time with that factor. The final key's easing
|
|
1882
|
+
has no effect. No arbitrary easing, pan/zoom alternative, audio, depth, tilt,
|
|
1883
|
+
turn, frame-index inference or extension fields exist in @1.
|
|
1884
|
+
|
|
1885
|
+
Citations name the actual questions `camera_depth` and `post_timing`, each with
|
|
1886
|
+
`asks:[guide]`. `camera` and `timing` are executable plan step ids, not question
|
|
1887
|
+
ids. Quotes are exact stored verbatim/additions fragments, including historical
|
|
1888
|
+
or inherited answers; delegation uses the existing decided-delegation rules.
|
|
1889
|
+
A new write additionally requires a live post-interview approval covering both
|
|
1890
|
+
steps with matching `step_hashes`, and resolved current per-ask selections.
|
|
1891
|
+
Pending auto/Other responses cannot produce a document. A camera marked not
|
|
1892
|
+
applicable can supply a single fixed-box key only when its retained verbatim
|
|
1893
|
+
is cited and the approved post plan still supplies camera/timing; timing must
|
|
1894
|
+
be applicable. All-post-not-applicable skips post entirely. Prose is never
|
|
1895
|
+
parsed into authored key values.
|
|
1896
|
+
|
|
1897
|
+
Writers validate the prospective record and every owned finding before writing,
|
|
1898
|
+
retain unrelated pre-existing holes by code/path multiset, and reject concurrent
|
|
1899
|
+
source changes. Documents are immutable; `project.json` is the commit point.
|
|
1900
|
+
A lock, staged files, snapshot rechecks and rollback protect a failed publish.
|
|
1901
|
+
This is not an atomic multi-file filesystem transaction. A refused write leaves
|
|
1902
|
+
the record and previously published artifacts byte-identical. Source documents
|
|
1903
|
+
and patches are literal retained POSIX paths below the selected project, without
|
|
1904
|
+
symlinks, traversal or ignored roots. Only the explicitly bound compiled-model
|
|
1905
|
+
path above is allowed in regenerable `derived/`. Clone it when using this gate.
|
|
1906
|
+
The scene's idle frames are the one path admitted under `outputs/`: a post on
|
|
1907
|
+
rig `vN` reads `outputs/vN/idle/frames.json` only with the path and sha256 of
|
|
1908
|
+
`versions[vN].registration.idle`, and any other file under `outputs/vN/idle/`
|
|
1909
|
+
only with a `versions[vN].outputs` binding. The bytes stay where `rig-version`
|
|
1910
|
+
froze them; no second copy is retained. Present bytes are verified on every
|
|
1911
|
+
write and check. Absent bytes refuse, as the registration check refuses absent
|
|
1912
|
+
frozen outputs, so restore `outputs/vN/` before writing or checking the post.
|
|
1913
|
+
|
|
1914
|
+
### Review reads; create ingests direction patches
|
|
1915
|
+
|
|
1916
|
+
Review receives a user-designated project root and post number `N`. It reads
|
|
1917
|
+
that version's `provenance.direction`, then exactly
|
|
1918
|
+
`evidence/direction/v<N>.json` as `rig-create/direction@1`, validating raw SHA,
|
|
1919
|
+
version/path binding and rig model SHA. `readDirection(dir,project,N)` is the
|
|
1920
|
+
create reader; `direction check N --json` exposes a checked read. Review never
|
|
1921
|
+
writes `project.json` or invokes create. Review 1.6.0 has no authored camera
|
|
1922
|
+
consumer; review#373 consumes this contract after it lands. No camera Apply
|
|
1923
|
+
capability is claimed for that installation.
|
|
1924
|
+
|
|
1925
|
+
This is a planned contract. No review version produces it today: the direction
|
|
1926
|
+
producer is review#373, which is parked, and its result will arrive as a job act
|
|
1927
|
+
(create#271). The planned patch is a closed `rig-review-direction-patch/1` with exactly
|
|
1928
|
+
`{schema,source_post,rig_model_sha256,direction_sha256,replace}`. `replace` holds
|
|
1929
|
+
one or more of `camera`, `timing`, `take`, replacing whole typed sections only.
|
|
1930
|
+
The source is the current post, and both base hashes must match. Unknown keys,
|
|
1931
|
+
arbitrary pointers and a semantic no-op refuse. Binding/citation changes need
|
|
1932
|
+
new answer/authoring work, not a patch. The patch's own identity is the raw hash
|
|
1933
|
+
of its retained bytes, not a review canonicalization claim.
|
|
1934
|
+
|
|
1935
|
+
```sh
|
|
1936
|
+
rig-create correction record <dir> --id framing --path made --stage direction-review \
|
|
1937
|
+
--version 5 --direction-patch-file evidence/direction-patch.json \
|
|
1938
|
+
--by user --verbatim-file correction-words.txt
|
|
1939
|
+
rig-create direction patch 6 <dir> --patch-file evidence/direction-patch.json
|
|
1940
|
+
rig-create correction resolve framing <dir> --version 6 --by agent \
|
|
1941
|
+
--reasoning-file resolution.txt
|
|
1942
|
+
```
|
|
1943
|
+
|
|
1944
|
+
The patch writer creates a later immutable document/post and records
|
|
1945
|
+
`direction_origin:{source_post,patch:{path,sha256},result:{path,sha256}}` on the
|
|
1946
|
+
version. Capture retains the human words separately; no words are invented from
|
|
1947
|
+
the patch. Review may label export plus create ingestion “Apply”, but cannot
|
|
1948
|
+
claim ingestion or checked completion itself. `rig-review-applied/2` is never
|
|
1949
|
+
used as a direction result or proof.
|
|
1950
|
+
|
|
1951
|
+
Authored-direction descriptions and `direction-patch` use
|
|
1952
|
+
`rig-create/correction@2`. Other correction records remain
|
|
1953
|
+
`rig-create/correction@1`, with existing config-patch and unsupported behavior.
|
|
1954
|
+
The made patch artifact is
|
|
1955
|
+
`{kind:"direction-patch",patch:{path,sha256},state:"preview/pending"|
|
|
1956
|
+
"applied-and-checked",result:null|{path,sha256}}`. Its exact post source/outcome
|
|
1957
|
+
identity is `{kind:"post",n,config,model,direction:{path,sha256}}`; config binds
|
|
1958
|
+
the direction file, model binds the source rig's compiled model, and direction
|
|
1959
|
+
matches `provenance.direction`. This identity is not accepted by @1.
|
|
1960
|
+
|
|
1961
|
+
A pending record has no outcome/result and cannot approve. On agent resolution,
|
|
1962
|
+
create checks its own patch/base/result and `direction_origin`, not an external
|
|
1963
|
+
producer report. The outcome is a later post on exactly the same rig model,
|
|
1964
|
+
with changed direction bytes and the typed replacements actually present.
|
|
1965
|
+
Same-document, cross-kind, changed-rig or unrelated authored output pairs
|
|
1966
|
+
refuse for made patches.
|
|
1967
|
+
|
|
1968
|
+
A described request at direction-review on a post with authored direction
|
|
1969
|
+
also binds this exact identity, using `artifact:{kind:"description"}`. Record it
|
|
1970
|
+
with `--version`; an optional `--model-file` must name the source rig's compiled
|
|
1971
|
+
model. Selecting the direction JSON as model refuses before writing. Resolve
|
|
1972
|
+
it to a later authored post with a different bound direction document hash
|
|
1973
|
+
through `correction resolve --version`. This includes a later accepted rig
|
|
1974
|
+
because direction@1 embeds `rig.model`. The agent's closure reasoning carries
|
|
1975
|
+
the semantic claim that the request was met. No patch or `direction_origin`
|
|
1976
|
+
is required for a described request. Both source and outcome use
|
|
1977
|
+
`validateDirectionIdentity`. An existing @1 description cannot resolve with
|
|
1978
|
+
the direction document named as model. Capture a new @2 described record to
|
|
1979
|
+
close that legacy request.
|
|
1980
|
+
|
|
1981
|
+
`DESCRIBED_DIRECTION_SINCE = 2026-11-06T00:00:00Z` dates existing @1 authored
|
|
1982
|
+
direction descriptions by their original `at`. Earlier records receive
|
|
1983
|
+
`DESCRIBED_DIRECTION_LEGACY`; contemporary records receive
|
|
1984
|
+
`DESCRIBED_DIRECTION_REQUIRED`. Preserve history and capture the next request
|
|
1985
|
+
through the writer. Posts without authored `provenance.direction` keep their
|
|
1986
|
+
existing @1 declared-output identity. Rig, draft and parts identities are
|
|
1987
|
+
unchanged. Unsupported operations remain pending.
|
|
1988
|
+
|
|
1989
|
+
`checkProject`, direction signoff and the acceptance writer all check the
|
|
1990
|
+
relevant document. Handoff stays rig-only to bootstrap authoring. Review-package
|
|
1991
|
+
stays rig-only and cannot rebind a model already cited by a direction document.
|
|
1992
|
+
Reopen rules, historical evidence, human signoff and agent closure remain
|
|
1993
|
+
separate gates.
|
|
1994
|
+
|
|
1995
|
+
The generated geometric example is `templates/example-direction/`, including a
|
|
1996
|
+
small staged project, exact input/result documents, a review-format patch and
|
|
1997
|
+
@2 correction. It uses invented sentences shaped like a pilot interview, not
|
|
1998
|
+
pilot words or assets. Reproduce with
|
|
1999
|
+
`bun scripts/generate-direction-fixture.ts <fresh-dir> --check`. It demonstrates
|
|
2000
|
+
writer/contract behavior with a real installed `rigc build` of a public rectangle
|
|
2001
|
+
probe. Its compiled local yaw slider is readable by review's `discoverTurnDials`
|
|
2002
|
+
(`src/turn-pad.ts`, revision `c3e571db1878093b183c282b56f5eb846c1d742b`),
|
|
2003
|
+
using core 3.2.1's `RigSliderConstraint` (`src/rig.ts`). The compiled model has
|
|
2004
|
+
no authored camera capability; camera requests in the direction documents are
|
|
2005
|
+
unsupported playback requests, not evidence of camera rendering or Apply.
|
|
2006
|
+
The installed core-only build reports `A00_ROUNDTRIP_PARSE` as SKIP; this is
|
|
2007
|
+
not a spine-core round-trip or a rendered-take claim. Recompute every recorded
|
|
2008
|
+
file hash with `bun scripts/check-direction-fixture-hashes.ts`; entries of a
|
|
2009
|
+
producer run stamp (`rigc-run/1`, `rig-run/1`) resolve against the stamp's own
|
|
2010
|
+
directory.
|
|
2011
|
+
The main filled project remains the separate zero-refusal/zero-warning example.
|
|
2012
|
+
|
|
2013
|
+
## Advisory intake reports
|
|
2014
|
+
|
|
2015
|
+
`project.intake` is optional (`spec: "rig-create/intake@1"`). In `parts`, after
|
|
2016
|
+
a full run exists, retain the parts `head-crop-preflight` JSON and record it:
|
|
2017
|
+
|
|
2018
|
+
```sh
|
|
2019
|
+
rig-create intake-report . --id crop-1 --report evidence/preflight.json --sha256 <raw-sha256> --parts-version 2.16.0 --by agent
|
|
2020
|
+
rig-create intake .
|
|
2021
|
+
```
|
|
2022
|
+
|
|
2023
|
+
This reads producer bytes and never runs a producer or verifies its pixels.
|
|
2024
|
+
`reports[]` is append-only. Each entry keeps its id, by/at, a report binding
|
|
2025
|
+
(path, raw sha256, spec, head_box, source_canvas, run_canvas), `measurement`
|
|
2026
|
+
(the report's own fields copied exactly), `prediction` (`hit` or `no-hit`),
|
|
2027
|
+
and the declared `parts_version`. Version is outside the authenticated v1
|
|
2028
|
+
report, which does not emit a version. Correct a report with a new retained
|
|
2029
|
+
path/id and `--supersedes <earlier-id>`; do not replace its bytes or history.
|
|
2030
|
+
The writer validates before writing and leaves project bytes unchanged on
|
|
2031
|
+
invalid input. Copied fields are checked against the bound report, never
|
|
2032
|
+
against a fresh computation.
|
|
2033
|
+
|
|
2034
|
+
A HIT is any reported `layers[].sides.top_px`, `left_px` or `right_px` > 0.
|
|
2035
|
+
Keep the per-tag counts, including zero rows and separate `bottom_px`.
|
|
2036
|
+
Corners count on two sides; summed edges are incidences, not unique pixels.
|
|
2037
|
+
Preflight counts native full-run alpha > 8 **before ghost cleanup** and
|
|
2038
|
+
retains registration and canvas identity. `ASSEMBLE_CROP_CLIPPED` counts
|
|
2039
|
+
alpha ≥ 128 **after ghost cleanup**; it is a separate instrument. Never
|
|
2040
|
+
compare or substitute their numbers. Intake only stores the preflight
|
|
2041
|
+
instrument; downstream outcome labels stay in evidence receipts, not an
|
|
2042
|
+
in-project label ledger. Missing labels remain unknown, never negative.
|
|
2043
|
+
|
|
2044
|
+
Everything about persisted intake is advisory: HIT, absent choice, malformed
|
|
2045
|
+
record or unavailable report bytes cannot refuse signoff, acceptance or
|
|
2046
|
+
handoff. A retrospective over three pilots fired on all three; only one had
|
|
2047
|
+
a labelled positive and none a labelled negative. This shows firing, not
|
|
2048
|
+
ability to discriminate. The threshold stays > 0; it is not an approval gate.
|
|
2049
|
+
The filled example does not adopt intake and keeps zero warnings.
|
|
2050
|
+
|
|
2051
|
+
Colour-adjacent ground and ground enclosed between strands are
|
|
2052
|
+
**known-not-predicted** notes in the guide/intake output only (two rounds of
|
|
2053
|
+
a model sweep on a pilot did not separate them), with no threshold or warning.
|
|
2054
|
+
Silhouette stepping, source-vs-final alpha classes, patchwork runs and
|
|
2055
|
+
versioned dark retention need post-assemble outputs and are excluded.
|
|
2056
|
+
|
|
2057
|
+
### Targets of review signatures
|
|
2058
|
+
|
|
2059
|
+
`signoff rig-review` and `signoff direction-review` accept `--version <n>`.
|
|
2060
|
+
Without it, exactly one candidate must exist. Candidates are versions of the
|
|
2061
|
+
review's kind with an accepted verdict and no live same-stage signature
|
|
2062
|
+
already targeting them. A refusal lists candidates without a recency preference.
|
|
2063
|
+
An explicit version must exist with the right kind and an accepted verdict.
|
|
2064
|
+
A rig version that a reopen or amendment of `rig-review` or an earlier stage
|
|
2065
|
+
made history is no candidate. When that leaves no live rig version accepted,
|
|
2066
|
+
`signoff rig-review` refuses before it writes (`RIG_VERSION_UNACCEPTED`),
|
|
2067
|
+
naming the lapsed acceptance and its `reopens[]` or `amendments[]` entry;
|
|
2068
|
+
register a new rig version and accept it first. A signature recorded before
|
|
2069
|
+
this refusal existed is not refused at `rig-review`: `advance` and `handoff`
|
|
2070
|
+
stop on it with the same code.
|
|
2071
|
+
|
|
2072
|
+
Each signature records `target.version` and `target.verdict`, the literal
|
|
2073
|
+
`versions[i].verdicts[j]` path of the accepted verdict. A rig review adds
|
|
2074
|
+
`target.review_package = {path: "versions[i].review_package", sha256}`. Its hash
|
|
2075
|
+
is SHA-256 of UTF-8 `JSON.stringify(sorted({config, files}))` from the inline
|
|
2076
|
+
package record. Keys sort recursively, arrays retain order, and `from` and
|
|
2077
|
+
`open` are excluded. Package checks still resolve the retained files on disk.
|
|
2078
|
+
|
|
2079
|
+
An adopted authored direction adds `target.direction = {path, sha256}` from
|
|
2080
|
+
the version's `provenance.direction` and the retained document bytes. A post
|
|
2081
|
+
without an adopted document instead adds `target.post_config`, copied from
|
|
2082
|
+
`provenance.config`. Exactly one is present. The latter is compared with the
|
|
2083
|
+
version's current binding, while existing provenance checks own file reads.
|
|
2084
|
+
Writers validate targets before writing. Refusals leave project.json identical.
|
|
2085
|
+
|
|
2086
|
+
From `SIGNOFF_TARGET_SINCE = 2026-11-06T00:00:00Z`, missing and stale targets
|
|
2087
|
+
refuse as `SIGNOFF_TARGET_MISSING` and `SIGNOFF_TARGET_STALE`. Earlier signatures
|
|
2088
|
+
receive one corresponding `_LEGACY` warning each. Amendment lapse rules continue
|
|
2089
|
+
to apply to these approvals.
|
|
2090
|
+
|
|
2091
|
+
Pre-interview rig versions bind `target.outputs = {path: "versions[i].outputs",
|
|
2092
|
+
sha256}` using SHA-256 of UTF-8 `JSON.stringify(sorted(outputs))`. A declared
|
|
2093
|
+
`outputs_lost` refuses signing because nothing survives to bind. Any target has
|
|
2094
|
+
exactly one of `review_package`, `outputs`, `direction` or `post_config`.
|
|
2095
|
+
The operative verdict is the last human, non-provisional verdict for that
|
|
2096
|
+
review stage. It must be accepted, and the target must name that exact verdict.
|
|
2097
|
+
A later human bounce makes the earlier bound acceptance stale.
|
|
2098
|
+
|
|
2099
|
+
|
|
2100
|
+
## Scene composition and direction@2
|
|
2101
|
+
|
|
2102
|
+
`scene write --rig <R> --background <path> [--foreground <path>]
|
|
2103
|
+
[--background-rect x,y,w,h] [--foreground-rect x,y,w,h]
|
|
2104
|
+
--citations-file <file> [<dir>]` derives the latest accepted rig,
|
|
2105
|
+
live rig-review signoff target, compiled model and stage. It appends
|
|
2106
|
+
`scenes[]` entries `{n,path,sha256,at,by}` and immutable
|
|
2107
|
+
`evidence/scene/s<N>.json` documents with schema `rig-create/scene@1`.
|
|
2108
|
+
New entries record `by:"agent"`. A typed `--by` is refused: human authority
|
|
2109
|
+
comes from the current ingested `post_composition` Review choice or its decided
|
|
2110
|
+
delegation. Earlier human-authored scenes retain their existing validation;
|
|
2111
|
+
no contract date or additional historical warning is introduced.
|
|
2112
|
+
The project append commits the scene. Unreferenced files are ignored.
|
|
2113
|
+
The latest entry is current. Existing documents stay byte-identical.
|
|
2114
|
+
|
|
2115
|
+
The closed document contains `schema`, `n`, `rig`, `frame`, `plates`, `layers`.
|
|
2116
|
+
`rig` contains `version`, `acceptance`, `model` and `animation`.
|
|
2117
|
+
`acceptance` retains `signoff:{stage:"rig-review",checkpoint:null,at}`,
|
|
2118
|
+
`verdict` and `review_package:{path,sha256}` from the live signoff target.
|
|
2119
|
+
`model` is the accepted package's compiled `{path,sha256}` binding.
|
|
2120
|
+
The writer selects `animation.name:"idle"`. `animation.frames` is present
|
|
2121
|
+
exactly when the version declares `registration.idle`, and equals that binding.
|
|
2122
|
+
Each SHA-256 binds raw file bytes.
|
|
2123
|
+
|
|
2124
|
+
`frame.space` is `rig-world-y-up`. `frame.stage` copies the compiled model's
|
|
2125
|
+
stage field for field. Plate `rect:{x,y,width,height}` uses rig world units
|
|
2126
|
+
and its bottom-left corner. The selected `value` (or delegated decision value)
|
|
2127
|
+
must contain `scene:{background:{path,rect},foreground?:{path,rect}}`. The writer
|
|
2128
|
+
derives omitted rect flags from that exact map; supplied roles, paths and rects
|
|
2129
|
+
must match it exactly. It never infers placement from prose, a singleton input
|
|
2130
|
+
or the stage. Rects may extend past the stage and require uniform scale within
|
|
2131
|
+
relative 1e-9. Exact choice equality applies even within that scaling tolerance. Plate `width` and `height`
|
|
2132
|
+
come from PNG IHDR. Declare one background and at most one foreground, with
|
|
2133
|
+
distinct paths and hashes. `layers` is `["background","rig"]` or
|
|
2134
|
+
`["background","rig","foreground"]` accordingly. A declared foreground
|
|
2135
|
+
is validated fully.
|
|
2136
|
+
|
|
2137
|
+
The citations file is a map of the declared roles to
|
|
2138
|
+
`{guide:"post_composition",asks:["post_composition"],quote:"recorded words"}`
|
|
2139
|
+
or the same citation with `delegated:true` replacing `quote`.
|
|
2140
|
+
Each plate stores this human designation, its path, sha256, pixel size, rect,
|
|
2141
|
+
and `registered:{kind:"input"|"derived",ref:"inputs[i]"|"derived[i]"}`.
|
|
2142
|
+
Inputs must match by path and hash. A derived registration requires every
|
|
2143
|
+
`prepared-input` source/sources hop to match by path and hash and terminate
|
|
2144
|
+
in registered inputs. Missing result hashes and cycles refuse.
|
|
2145
|
+
Register a plate with `input add` before `scene write` names it. New agent
|
|
2146
|
+
scenes require input-writer metadata `{path,sha256,bytes,origin,at}` for raw input
|
|
2147
|
+
candidates, or a bound `rig-parts-plate-receipt/1` for derived candidates. A
|
|
2148
|
+
legacy input must be registered under a new source name with
|
|
2149
|
+
`input add <path> --origin …`, then selected through Review. Missing, stale or
|
|
2150
|
+
mismatched authority refuses before the project append. Quotes must cite the
|
|
2151
|
+
current ingested answer; historical answers remain available to historical
|
|
2152
|
+
scene readers. Composite preview presentation remains tracked in
|
|
2153
|
+
[Review #482](https://github.com/rig-c/review/issues/482); writer/checker success
|
|
2154
|
+
is not visual acceptance.
|
|
2155
|
+
|
|
2156
|
+
`rig-create/direction@2` keeps @1's camera, timing, take and citations and adds
|
|
2157
|
+
required `scene:{n,path,sha256}` equal to a committed scene entry. Its rig and
|
|
2158
|
+
model equal the scene's. Camera boxes and plates share rig-world-y-up units.
|
|
2159
|
+
Current authoring and the current live post must cite the latest scene.
|
|
2160
|
+
With no live post, no scene is current.
|
|
2161
|
+
SCENE_RIG_STALE, lapsed-signoff SCENE_ACCEPTANCE_STALE and
|
|
2162
|
+
DIRECTION_SCENE_STALE share one currentness gate. Every committed scene
|
|
2163
|
+
retains its historical human acceptance and matching review-package identity,
|
|
2164
|
+
plus all schema, file, model, animation, frame, plate, registration and citation
|
|
2165
|
+
checks. Reopening preserves these historical records. The next accepted rig
|
|
2166
|
+
gets a new scene number.
|
|
2167
|
+
Post identity gains `scene:{path,sha256}`. Patches retain their existing
|
|
2168
|
+
whole-section schema, so a scene change is a new post.
|
|
2169
|
+
|
|
2170
|
+
Existing direction-contract@1 adoption is preserved. Grandfathered posts
|
|
2171
|
+
need no document and bypass both direction schemas. Historical @1 documents
|
|
2172
|
+
remain readable. Earlier @1 posts warn with DIRECTION_SCENE_REQUIRED.
|
|
2173
|
+
Posts from DIRECTION_SCENE_SINCE require @2. The parent finalizes the one
|
|
2174
|
+
exported cutoff to the implementation's UTC landing day before merge and
|
|
2175
|
+
checks every live pilot for new same-day refusals.
|
|
2176
|
+
|
|
2177
|
+
### Scene option context
|
|
2178
|
+
|
|
2179
|
+
A post option set takes one of two contexts: the rig kind
|
|
2180
|
+
(docs/INTERVIEW.md) or the scene kind. This section is the scene kind's
|
|
2181
|
+
contract.
|
|
2182
|
+
|
|
2183
|
+
1. **Entries.** `project.scenes[]` is append-only. Each entry is exactly
|
|
2184
|
+
`{n,path,sha256,at,by}`: `n` counts from 1 in array order, `path` is
|
|
2185
|
+
`evidence/scene/s<n>.json`, `sha256` is the SHA-256 of the file's raw bytes
|
|
2186
|
+
in lowercase hex, `at` is a UTC ISO time ending in `Z`, and `by` is `agent`
|
|
2187
|
+
for new scenes or a retained human identifier for historical scenes. The documents are immutable `rig-create/scene@1`.
|
|
2188
|
+
2. **Reference.** The context is `{kind:"scene",scene:{n,path,sha256}}`: the
|
|
2189
|
+
entry without `at` and `by`.
|
|
2190
|
+
3. **Selection.** At an instant *t*, the candidate is the last `scenes[]`
|
|
2191
|
+
entry whose `at` ≤ *t*. Earlier entries are never selected.
|
|
2192
|
+
4. **Currentness.** The candidate applies only if it is current at *t*.
|
|
2193
|
+
Its document must match `sha256`, carry the entry's `n` and have the closed
|
|
2194
|
+
scene@1 shape. Then the scene currentness gate (`SCENE_RIG_STALE`,
|
|
2195
|
+
`SCENE_ACCEPTANCE_STALE`) runs on the records dated at or before *t*:
|
|
2196
|
+
`signoffs[]`, `versions[]` and their `verdicts[]`, `reopens[]` and
|
|
2197
|
+
`amendments[]`. Undated entries are left out.
|
|
2198
|
+
- `rig.version` is the latest live accepted rig, and no live rig version
|
|
2199
|
+
has a higher `n`.
|
|
2200
|
+
- `rig.acceptance` equals the latest live rig-review signoff
|
|
2201
|
+
(`checkpoint:null`) whose target names that version: its
|
|
2202
|
+
`{stage,checkpoint,at}`, `verdict` and `review_package`.
|
|
2203
|
+
|
|
2204
|
+
No live post is needed. When the gate fails, the set takes the rig kind
|
|
2205
|
+
exactly as if no scene existed, so a scene built on an earlier rig never
|
|
2206
|
+
anchors a post set. The rig kind keeps its own refusals: with no live
|
|
2207
|
+
accepted rig and live rig-review signoff at *t*, for example after a
|
|
2208
|
+
rig-review reopen, it refuses `INTERVIEW_OPTIONS_STALE`. An unreadable,
|
|
2209
|
+
changed or malformed candidate refuses `INTERVIEW_OPTIONS_STALE` instead
|
|
2210
|
+
of falling back.
|
|
2211
|
+
|
|
2212
|
+
The closed scene@1 shape in this rule is exactly the structure below.
|
|
2213
|
+
"Closed" means the listed keys must be present, optional keys may be
|
|
2214
|
+
present, and no other key is allowed. A text value is a string with
|
|
2215
|
+
non-blank content. A count is a positive safe integer. A hash is 64
|
|
2216
|
+
lowercase hex digits. A path is a relative `/`-separated text with no empty,
|
|
2217
|
+
`.` or `..` segment, no leading `/`, no backslash and no drive prefix. A box is
|
|
2218
|
+
closed `{x,y,width,height}` with number values. A binding is closed
|
|
2219
|
+
`{path,sha256}`.
|
|
2220
|
+
|
|
2221
|
+
| Object | Keys (optional in brackets) | Values |
|
|
2222
|
+
| --- | --- | --- |
|
|
2223
|
+
| document | `schema`, `n`, `rig`, `frame`, `plates`, `layers` | `schema` is `rig-create/scene@1`; `n` is a count; `plates` is a list; `layers` is a list of strings |
|
|
2224
|
+
| `rig` | `version`, `acceptance`, `model`, `animation` | `version` is a count; `model` is a binding |
|
|
2225
|
+
| `rig.animation` | `name`, [`frames`] | `name` is text; `frames` is a binding |
|
|
2226
|
+
| `rig.acceptance` | `signoff`, `verdict`, `review_package` | `verdict` matches `versions[<i>].verdicts[<j>]`; `review_package` is a closed `{path,sha256}` with text path and a hash |
|
|
2227
|
+
| `rig.acceptance.signoff` | `stage`, `checkpoint`, `at` | `rig-review`, `null`, and a readable date text |
|
|
2228
|
+
| `frame` | `space`, `stage` | `space` is `rig-world-y-up`; `stage` is a box |
|
|
2229
|
+
| each plate | `role`, `path`, `sha256`, `width`, `height`, `rect`, `registered`, [`citation`] | `role` is `background` or `foreground`; `path` is a path; `sha256` is a hash; `width` and `height` are counts; `rect` is a box; `registered` is closed `{kind,ref}` with `kind` `input` or `derived` and text `ref` |
|
|
2230
|
+
| `citation` | any of `guide`, `asks`, `quote`, `delegated` | a string, a list of strings, a string, and a boolean |
|
|
2231
|
+
|
|
2232
|
+
A plate's file bytes, PNG size, registration chain, rect scale and
|
|
2233
|
+
citation wording, the layer order and the role count are validated when
|
|
2234
|
+
the scene is written and in the full scene check above. They are not part of
|
|
2235
|
+
this option-context gate, so a reader of option contexts doesn't have to
|
|
2236
|
+
reproduce them.
|
|
2237
|
+
5. **Freshness.** These rules apply to the rig and scene kinds alike.
|
|
2238
|
+
- The context is recomputed at `drafted_at` and again at the selection or
|
|
2239
|
+
decision time, and both must equal `set.context` exactly. A writer uses
|
|
2240
|
+
now. `check` uses the answer's or decision's `at`, and `drafted_at` for a
|
|
2241
|
+
pending set. A later scene, or a later live rig version, makes a
|
|
2242
|
+
scene-kind set `INTERVIEW_OPTIONS_STALE`.
|
|
2243
|
+
- A rig-kind set is recomputed with `scenes[]` ignored, so no scene makes
|
|
2244
|
+
it stale.
|
|
2245
|
+
- A reopen or amendment of a stage at or before the set's stage, dated
|
|
2246
|
+
after `drafted_at` and at or before that time, refuses
|
|
2247
|
+
`INTERVIEW_OPTIONS_STALE`.
|
|
2248
|
+
- The file at `scene.path` must be a literal project-relative regular file
|
|
2249
|
+
whose raw bytes match `scene.sha256`.
|
|
2250
|
+
6. **Contract date.** A scene-kind set drafted before
|
|
2251
|
+
`SCENE_CONTEXT_SINCE = 2026-11-08T00:00:00Z` that is stale only under
|
|
2252
|
+
rule 4 is checked under the rule of its day, where the latest scene
|
|
2253
|
+
applied whether current or not. It warns `INTERVIEW_OPTIONS_SCENE_LEGACY`.
|
|
2254
|
+
|
|
2255
|
+
### Publication and review read boundary
|
|
2256
|
+
|
|
2257
|
+
Publication (#184) retains and raw-byte-seals the scene document, its model,
|
|
2258
|
+
plates and optional frames as `files[]` rows using the scene's hashes.
|
|
2259
|
+
Every texture page needed by the model is retained and sealed through the
|
|
2260
|
+
existing review-package inventory or published files[]. The scene adds no
|
|
2261
|
+
page field or second hash domain. Parts keep their manifest and image seals.
|
|
2262
|
+
`projectHash` seals raw project.json bytes in rig-review-job-source/2.
|
|
2263
|
+
|
|
2264
|
+
Review selects the scene from the retained project, an option context or
|
|
2265
|
+
direction document and resolves it against that publication's retained
|
|
2266
|
+
project root. Every dependency is read from that same snapshot.
|
|
2267
|
+
The files[] inventory does not select a scene.
|
|
2268
|
+
|
|
2269
|
+
For viewport `(vx,vy,vw,vh)` and scale `s`, Canvas projects a plate by its top
|
|
2270
|
+
edge. Destination left is `(rect.x-vx)*s`, top is
|
|
2271
|
+
`(vy+vh-rect.y-rect.height)*s`, width is `rect.width*s`, height is
|
|
2272
|
+
`rect.height*s`. Foreground is optional. Review #482 owns that consumer
|
|
2273
|
+
change and the inspection camera default. Create performs no rendering.
|
|
2274
|
+
|
|
2275
|
+
## Corrections through Review feedback
|
|
2276
|
+
|
|
2277
|
+
For config corrections, `--feedback-file`, `--applied-feedback` and
|
|
2278
|
+
`--patch-file` now take the Review package argument to `rig-review feedback`,
|
|
2279
|
+
with `--item` or `--feedback-id` selecting the saved item. create passes that
|
|
2280
|
+
argument unchanged from the project directory and records the CLI argv.
|
|
2281
|
+
`--patch-file` selects the patch embedded in that applied item. A downloaded
|
|
2282
|
+
preview patch that Review has never applied has no API source. For example,
|
|
2283
|
+
a proposed config-patch JSON with no saved applied item must first be applied
|
|
2284
|
+
and submitted through Review before create can record it.
|
|
2285
|
+
|
|
2286
|
+
create stores the exact stdout at `evidence/review-reads/<sha256>.json`.
|
|
2287
|
+
The correction artifact's `review_read` contains `route: "cli"`, `argv`,
|
|
2288
|
+
`stdout: {path, sha256}` and `tool: {name, version}`. The `feedback.file`
|
|
2289
|
+
binding names those same stdout bytes. A version's `review_origin` uses
|
|
2290
|
+
`review_read` and `feedback` with the same bindings. `check` consumes these
|
|
2291
|
+
stored responses and does not invoke Review. Records before
|
|
2292
|
+
`REVIEW_READ_SINCE` without a receipt get `REVIEW_READ_LEGACY` and preserve
|
|
2293
|
+
their history without opening producer-saved session or patch files.
|
|
2294
|
+
|
|
2295
|
+
The field inventory used synthetic declared applied/2 through Review's
|
|
2296
|
+
browserless session PUT. Producer Apply was outside this inventory. The inventory confirmed
|
|
2297
|
+
`patch`, `patchSha256`, `configHash`, `modelHash`, `check` and `files` survive
|
|
2298
|
+
`feedback --format json`.
|
|
2299
|
+
|
|
2300
|
+
### Recording interview picks from a standing job
|
|
2301
|
+
|
|
2302
|
+
Use `interview-answer <question> [<project>] --from-review <actId>` after the
|
|
2303
|
+
human finalizes an `interview-picks` act in the standing Review job. The writer
|
|
2304
|
+
fetches through its private sibling capability, binds the displayed option set
|
|
2305
|
+
by ID and SHA-256, and retains the immutable API act bytes in `review_acts`.
|
|
2306
|
+
An identical act can be replayed without adding a second answer. A changed act
|
|
2307
|
+
with the same identity refuses. `--why-file` still supplies the exact reason
|
|
2308
|
+
for a member override. The removed `--picks-file` flag refuses with
|
|
2309
|
+
`INTERVIEW_PICKS_FILE_REMOVED`. Earlier answers remain valid.
|
|
2310
|
+
|
|
2311
|
+
## Model-free record publication
|
|
2312
|
+
|
|
2313
|
+
`readRecordPublished({root, record, result, phase})` in `job-publication.ts`
|
|
2314
|
+
implements create's local boundary for review#561 CP1. `record` binds the
|
|
2315
|
+
literal `project.json` path and its raw-byte `sha256`. `result` is either
|
|
2316
|
+
`{kind: 'option-set', questionId, setId}` or `{kind: 'plan'}`. Reader `phase`
|
|
2317
|
+
is `'inventory' | 'retained'`. A retained request also passes `parts`, the
|
|
2318
|
+
identity the inventory phase returned. The optional second argument is the check
|
|
2319
|
+
instant in epoch milliseconds, defaulting to the current clock.
|
|
2320
|
+
|
|
2321
|
+
The return value has exactly `{label, parts, inputs, files, plan, subjects}`. An
|
|
2322
|
+
option context has `plan: null` and exactly the requested
|
|
2323
|
+
`{kind: 'interview-picks', questionId, setId}` subject. A plan context has
|
|
2324
|
+
ordered `{id, hash}` step identities and eligible
|
|
2325
|
+
`{kind: 'checkpoint', checkpointId}` or `{kind: 'signoff', stage}` subjects.
|
|
2326
|
+
Subject key order follows these declarations. Identifiers must fit the
|
|
2327
|
+
review record-id domain of 1–128 ASCII letters, digits, dots, underscores
|
|
2328
|
+
and hyphens, starting with a letter or digit. The reader identity is
|
|
2329
|
+
`rig-create/publication-reader/2`. Create's current live host stays in
|
|
2330
|
+
`package-only` mode while installed Review 2.8.0 exports the public
|
|
2331
|
+
record-mode V3 symbols and types.
|
|
2332
|
+
|
|
2333
|
+
Eligibility comes from the one `checkProject` call with `readOnly: true`.
|
|
2334
|
+
Its effective stage must match the requested option set's stage. Plan
|
|
2335
|
+
signoffs are offered only for an unsigned effective `plan-approved`,
|
|
2336
|
+
`rigging-interview` or `post-interview` stage that closes by signoff.
|
|
2337
|
+
Checkpoint subjects require an enabled at-checkpoint step in the effective
|
|
2338
|
+
execution stage. An empty subject list permits plan inspection. Warnings
|
|
2339
|
+
remain eligible, and publication HOLEs refuse publication.
|
|
2340
|
+
|
|
2341
|
+
`inputs` projects every declared input to `{path, sha256}` in project-input
|
|
2342
|
+
order and rehashes its bytes. `files` seals the record, inputs and selected
|
|
2343
|
+
option/context evidence, and every project file the check read. Plans include
|
|
2344
|
+
current answer evidence for every displayed step's declared basis and retained
|
|
2345
|
+
parts/structure approval evidence. Signoff eligibility uses the existing answer-selection and
|
|
2346
|
+
rigging-context readers. Plan step hashes use `stepHash`.
|
|
2347
|
+
|
|
2348
|
+
Every path is literal and project-relative. Duplicate declarations within
|
|
2349
|
+
a list and conflicting hashes for a path refuse. Identical references share
|
|
2350
|
+
one file row. The file list is unique by path and sorted by JavaScript
|
|
2351
|
+
string comparison. Both phases verify closure bytes before the official
|
|
2352
|
+
check and write nothing, create no lock and perform no intent recovery.
|
|
2353
|
+
Default `checkProject` calls keep their existing recovery behavior.
|
|
2354
|
+
|
|
2355
|
+
The check's reads come from `checkProject(..., { recordReads: true })`: the
|
|
2356
|
+
check modules read project files only through the recorded reader in
|
|
2357
|
+
`src/check-reads.ts`, which returns each file the check opened, stat'ed,
|
|
2358
|
+
resolved or listed as `{path, sha256}`. The job's private outbox and
|
|
2359
|
+
`node_modules/` are not record files and are not recorded. A retained root
|
|
2360
|
+
holding exactly `files` therefore gives the check the same bytes, and the
|
|
2361
|
+
retained phase returns the inventory phase's context. A test-only strict mode
|
|
2362
|
+
(`tests/strict-reads.ts`) throws `CHECK_READ_UNRECORDED` when a check module
|
|
2363
|
+
reads a project file around the recorder; every committed example runs
|
|
2364
|
+
through it.
|
|
2365
|
+
|
|
2366
|
+
The check's waypoints come from the `@rig-c/parts` it loads, which no
|
|
2367
|
+
project file seals. `parts` is that package's `{name, version, integrity}`:
|
|
2368
|
+
the installed version and the integrity that `bun.lock` and
|
|
2369
|
+
`package-lock.json` beside the install record for it, each lockfile that
|
|
2370
|
+
exists. Only the parts entry is read, never a whole-lockfile hash, so an
|
|
2371
|
+
unrelated dependency bump leaves the closure valid. A missing or
|
|
2372
|
+
disagreeing entry refuses `JOB_RECORD_PARTS_LOCK_MISSING`. In the retained
|
|
2373
|
+
phase the reader compares the sealed identity with the host's parts, the
|
|
2374
|
+
ones the retained check loads, before it seals the closure files. A difference refuses
|
|
2375
|
+
`JOB_RECORD_PARTS_MISMATCH`, naming both versions; the remedy is to rebuild
|
|
2376
|
+
the project on the host's parts or to run the check where the sealed
|
|
2377
|
+
version is installed.
|
|
2378
|
+
|
|
2379
|
+
After its seals pass, a retained-root check refusal produces
|
|
2380
|
+
`JOB_RECORD_CLOSURE_INCOMPLETE`, carrying structured `details` containing
|
|
2381
|
+
only the check's finding codes and record paths. It fires only when the
|
|
2382
|
+
retained root lacks or changed a closure file. An option-set request for a
|
|
2383
|
+
question with no pending set refuses `JOB_RECORD_SUBJECT_INVALID` in both
|
|
2384
|
+
phases.
|
|
2385
|
+
Collection members bind their collection interview closure into a
|
|
2386
|
+
project-relative artifact with
|
|
2387
|
+
`rig-create collection-binding [<member dir>] [--out <path>]` (default
|
|
2388
|
+
`evidence/collection-binding.json`) and record `collection_binding` in
|
|
2389
|
+
`project.json` (`{ path, sha256, spec: "rig-create/collection-binding@1", collection_sha256 }`).
|
|
2390
|
+
The binding file seals the raw `../../collection.json` `sha256`, the full
|
|
2391
|
+
collection `interview` (`questions`, `framing`, `waypoints` and `post.items`,
|
|
2392
|
+
preserving `history[]` so `basis: "overridden"` checks verify
|
|
2393
|
+
`collection_answer_at` in isolated retained roots), and the member's resolved
|
|
2394
|
+
`inherited_answers`. A member without a valid, up-to-date `collection_binding`
|
|
2395
|
+
refuses with `JOB_RECORD_COLLECTION_EXTERNAL`.
|
|
2396
|
+
|
|
2397
|
+
|
|
2398
|
+
## Parts-review receipt selection (create#267)
|
|
2399
|
+
|
|
2400
|
+
This section supersedes earlier saved-verdict command examples and evidence
|
|
2401
|
+
requirements in this document.
|
|
2402
|
+
|
|
2403
|
+
`signoff parts-review --draft <id>` and `structure-snapshot --draft <id>`
|
|
2404
|
+
select the latest parts-verdict receipt for that draft in `review_acts` ledger
|
|
2405
|
+
order. Both CLI-read and act receipts participate. The response retained by
|
|
2406
|
+
`parts-review` is hash-bound and validated through the same reader in the
|
|
2407
|
+
writers and check. The signoff retains its selected response binding and spec.
|
|
2408
|
+
A later response does not replace that historical binding. The existing latest
|
|
2409
|
+
changes-requested gate still applies. The removed `--evidence` and `--verdict`
|
|
2410
|
+
flags exit 2 with `PARTS_VERDICT_FILE_ROUTE_REMOVED` before writing.
|
|
2411
|
+
|
|
2412
|
+
Signatures before `PARTS_VERDICT_RECEIPT_SINCE` retain their legacy file
|
|
2413
|
+
bindings and WARN with `PARTS_VERDICT_FILE_LEGACY`. Check never opens their
|
|
2414
|
+
review-saved files. New signatures require a recorded API receipt.
|
|
2415
|
+
|
|
2416
|
+
The downstream review-package identity gate uses the selected draft's manifest
|
|
2417
|
+
and image bindings. Opaque CLI source paths cannot suppress this comparison.
|
|
2418
|
+
A mismatched accepted image retains `REVIEW_PACKAGE_PART_FILE_MISMATCH`.
|
|
2419
|
+
Historical saved-file approvals WARN and skip this unavailable comparison.
|
|
2420
|
+
|
|
2421
|
+
Historical response checks keep the existing `DRAFT_RIG_UNAVAILABLE` warning
|
|
2422
|
+
when ignored draft artifacts cannot be read. The retained API response remains
|
|
2423
|
+
hash- and spec-checked. New writers require the source bytes before recording.
|
|
2424
|
+
The examples query the pinned Review CLI, so a Review pin bump regenerates
|
|
2425
|
+
these responses and their dependent example bindings.
|
|
2426
|
+
|
|
2427
|
+
## One artwork, one project, and the fix ledger (create#285)
|
|
2428
|
+
|
|
2429
|
+
One artwork is one project for its whole life. A new project is for a different
|
|
2430
|
+
painting or a different rig kind. A redo, a new source ladder, new seeds, a new
|
|
2431
|
+
tool version or a new parts route is a new version in the same project. Only
|
|
2432
|
+
recorded drafts and versions count as versions; any other build is an
|
|
2433
|
+
experiment.
|
|
2434
|
+
|
|
2435
|
+
`rig-create init <dir> --painting <file> --origin <words>` copies the painting
|
|
2436
|
+
into `inputs/`, registers it as the first input and declares its path in
|
|
2437
|
+
`project.painting`. It refuses with
|
|
2438
|
+
`INIT_ARTWORK_EXISTS` when a `project.json` directly under `--projects-root`
|
|
2439
|
+
(default: the new project's parent folder) has an input with the same sha256.
|
|
2440
|
+
`--same-artwork-reason <file>` allows it, and the new record keeps
|
|
2441
|
+
`same_artwork: { reason, at, projects }`. init without `--painting` is unchanged.
|
|
2442
|
+
|
|
2443
|
+
The fix ledger lives in `project.json.fix_ledger`, so a restart or a new build
|
|
2444
|
+
cannot drop an accepted fix unnoticed. `ledger add <id> --by <who> --check <check
|
|
2445
|
+
id> --bar <text> --note <ref> --verbatim-file <file>` records one owner fix:
|
|
2446
|
+
the note it answers (`corrections[<id>]` or `versions[v<n>].verdicts[<i>]`),
|
|
2447
|
+
the owner's words quoted from it, an opaque check id and the bar.
|
|
2448
|
+
`ledger retire <id> --by <who> --reason-file <file>` retires it with a reason.
|
|
2449
|
+
A retired row stays in the ledger.
|
|
2450
|
+
|
|
2451
|
+
The pixel checks are the project's own script. create binds its report and does
|
|
2452
|
+
not run or reproduce a check. A draft is recorded with
|
|
2453
|
+
`draft-rig ... --ledger-report <file>`, a `rig-create/fix-ledger-report@1`
|
|
2454
|
+
report:
|
|
2455
|
+
|
|
2456
|
+
```
|
|
2457
|
+
{"schema": "rig-create/fix-ledger-report@1",
|
|
2458
|
+
"build": {"dir": "<as given>", "manifest_sha256": "<sha256 of the build's parts.json>"},
|
|
2459
|
+
"script_sha256": "<sha256 of the check script>",
|
|
2460
|
+
"rows": [{"id": "T1", "result": "pass|fail|unmeasurable", "measured": 3, "bar": "<text>", "reason": null}]}
|
|
2461
|
+
```
|
|
2462
|
+
|
|
2463
|
+
The report stays under the project outside ignored roots, for example
|
|
2464
|
+
`evidence/fix-ledger/`. Build identity is `build.manifest_sha256` against the
|
|
2465
|
+
draft's bound `parts.json`; `build.dir` is not identity. Extra keys in a row
|
|
2466
|
+
are allowed. The draft records `ledger_report { path, sha256, spec }`,
|
|
2467
|
+
`fixes_against`, `fixes` and, when given, `known_regressions [{ id, reason }]`:
|
|
2468
|
+
|
|
2469
|
+
- The report must cover every live row (`DRAFT_LEDGER_INCOMPLETE`).
|
|
2470
|
+
- A row the previous draft passed must pass again. `fail`, `unmeasurable` or a
|
|
2471
|
+
missing row is a regression (`DRAFT_LEDGER_REGRESSION`), unless
|
|
2472
|
+
`--known-regression <row id>=<reason file>` names it. A known regression
|
|
2473
|
+
stays owed: the next draft passes that row or records it as a known
|
|
2474
|
+
regression again, with its own reason.
|
|
2475
|
+
- `fixes` lists the live rows this report passes that the last draft a person
|
|
2476
|
+
saw did not. That draft is the latest earlier one with a parts-review
|
|
2477
|
+
receipt, else the previous draft.
|
|
2478
|
+
|
|
2479
|
+
The filled example records the v1 bounce's lantern fix as row `T1` and a later
|
|
2480
|
+
draft, `lantern`, with a synthetic passing report
|
|
2481
|
+
(`templates/example-draft/evidence/fix-ledger/lantern.json`, written by
|
|
2482
|
+
`scripts/example-ledger.ts` through `generate-example-order.ts`).
|
|
2483
|
+
|
|
2484
|
+
`rig-create restart [<dir>] --by <human> --reason-file <file>` starts the record
|
|
2485
|
+
again at v1 when the owner orders it. It writes the record `init` writes, with
|
|
2486
|
+
no versions, drafts, signoffs, plan, answers or review acts. It keeps the name,
|
|
2487
|
+
title, `painting`, `same_artwork`, `inputs[]` and `fix_ledger` with every row, and appends
|
|
2488
|
+
`restarts[] { at, by, reason, previous_record_sha256 }`. create does not keep
|
|
2489
|
+
the earlier `project.json`; git history holds it, so restart refuses before it
|
|
2490
|
+
writes unless `project.json` is committed: tracked and byte-identical to its
|
|
2491
|
+
version at HEAD. create's writers don't commit, so commit `project.json`, then
|
|
2492
|
+
restart. Before writing, restart also re-validates every input with the input writer's checks. A kept part set
|
|
2493
|
+
(inputs under `<set>/parts/*.png` or `<set>/parts.json`) must keep its
|
|
2494
|
+
`parts.json`, its PNGs and its rig (`rig.json` and `mesh_report.json`). The
|
|
2495
|
+
first draft after a restart has no predecessor, but it covers the whole
|
|
2496
|
+
ledger, so the inherited fixes are checked on day one. A restarted record
|
|
2497
|
+
checks the same as a fresh `init` record: the same codes, which include the
|
|
2498
|
+
open interview's `INTERVIEW_INCOMPLETE` refusals, and 0 warnings. Codes are in
|
|
2499
|
+
[CHECKS.md § Fix ledger, ledger reports and restarts](CHECKS.md#fix-ledger-ledger-reports-and-restarts-create285).
|
|
2500
|
+
|
|
2501
|
+
## Deriving the next moves: `rig-create next` (create#329)
|
|
2502
|
+
|
|
2503
|
+
`rig-create next [<project dir>] [--json]` is a read-only command that derives
|
|
2504
|
+
the project's next moves and whose they are from `project.json`:
|
|
2505
|
+
|
|
2506
|
+
- **Derived, never guessed.** Each item comes from a record field: `stage` and
|
|
2507
|
+
its exit requirement, open `plan.steps[]` and their `status`, lapsed
|
|
2508
|
+
approvals (`reopens[]` and `amendments[]` lapse lists), pending review jobs
|
|
2509
|
+
and `review_acts[]`, bound inputs and drafts, and the current `check`
|
|
2510
|
+
findings. Each item names the `field` it came from and what the record
|
|
2511
|
+
`awaits`. When required authored input is not yet in `project.json`, the item
|
|
2512
|
+
names the missing record field in `unanswered_by_record` and does not guess.
|
|
2513
|
+
- **Role ownership.** Every move names `role`:
|
|
2514
|
+
- `agent`: a complete, runnable `rig-create` command the agent may run now.
|
|
2515
|
+
- `producer`: a command of a pinned package (`rig-parts`, `rigc`).
|
|
2516
|
+
- `human`: a person's act collected through the review tool (`review_act`),
|
|
2517
|
+
with `command: null` and never a `--by user` writer.
|
|
2518
|
+
- **Refusals come first.** When `check` reports refusals (or publication holes),
|
|
2519
|
+
`next` lists each in `refusals[]` with its `CHECKS.md` remedy (`fix`) before
|
|
2520
|
+
any forward move. A project with a blocking refusal has `moves: []` and
|
|
2521
|
+
`awaits: []`.
|
|
2522
|
+
- **Rigging plan before sign-off.** At `rigging-interview`, when no rig step
|
|
2523
|
+
belongs to that approval stage, `next` lists `plan add <id> <dir> --by agent
|
|
2524
|
+
--phase rig …` for each answered guide without a step (bones, meshes,
|
|
2525
|
+
constraints, motion). The agent supplies the authored plan fields; these
|
|
2526
|
+
steps must be approved at `rigging-interview`. The human sign-off stays
|
|
2527
|
+
unanswered by record until the plan steps exist.
|
|
2528
|
+
- **Read-only and deterministic.** `project.json` and the project tree remain
|
|
2529
|
+
byte-identical. An `accepted` project with no lapsed approvals reports
|
|
2530
|
+
`accepted: true`, `moves: []` and exits `0`.
|
|
2531
|
+
|
|
2532
|
+
`--json` emits a `rig-create/next@1` document:
|
|
2533
|
+
|
|
2534
|
+
```json
|
|
2535
|
+
{
|
|
2536
|
+
"schema": "rig-create/next@1",
|
|
2537
|
+
"project_id": "<project.name>",
|
|
2538
|
+
"stage": "<project.stage>",
|
|
2539
|
+
"effective_stage": "<check effective_stage>",
|
|
2540
|
+
"accepted": false,
|
|
2541
|
+
"refusals": [
|
|
2542
|
+
{
|
|
2543
|
+
"code": "<CHECK_CODE>",
|
|
2544
|
+
"field": "<record path>",
|
|
2545
|
+
"message": "<finding message>",
|
|
2546
|
+
"fix": "<CHECKS.md remedy>"
|
|
2547
|
+
}
|
|
2548
|
+
],
|
|
2549
|
+
"awaits": ["<awaited record target>"],
|
|
2550
|
+
"moves": [
|
|
2551
|
+
{
|
|
2552
|
+
"role": "agent|producer|human",
|
|
2553
|
+
"field": "<source record field>",
|
|
2554
|
+
"awaits": "<awaited record target>",
|
|
2555
|
+
"command": "<complete runnable command or null>",
|
|
2556
|
+
"act": "<description of the move or review-tool act>",
|
|
2557
|
+
"review_act": {
|
|
2558
|
+
"kind": "parts-verdict|interview-picks|review-verdict|signoff|signoff-checkpoint",
|
|
2559
|
+
"stage": "<stage>"
|
|
2560
|
+
},
|
|
2561
|
+
"lapse": {
|
|
2562
|
+
"code": "REOPEN_SIGNOFF_LAPSED|REOPEN_VERDICT_LAPSED|AMENDED_STEP",
|
|
2563
|
+
"source_field": "reopens[0]",
|
|
2564
|
+
"target_field": "signoffs[2]",
|
|
2565
|
+
"message": "<warning message>"
|
|
2566
|
+
},
|
|
2567
|
+
"unanswered_by_record": "<missing record field when not derivable>"
|
|
2568
|
+
}
|
|
2569
|
+
]
|
|
2570
|
+
}
|
|
2571
|
+
```
|
|
2572
|
+
|
|
2573
|
+
|
|
2574
|
+
### Operator withdrawal of an execution checkpoint
|
|
2575
|
+
|
|
2576
|
+
`plan checkpoint-withdraw <id> [<project dir>] --by <operator>
|
|
2577
|
+
--reason-file <file> --quote-file <file>` appends one optional
|
|
2578
|
+
`plan.checkpoint_withdrawals[]` entry. Each entry has schema
|
|
2579
|
+
`rig-create/checkpoint-withdrawal@1`, the complete original `step`, its `sha256`
|
|
2580
|
+
from stepHash, its per-id replacement `generation`, `by`, `at`, `reason` and
|
|
2581
|
+
`verbatim`. Both input files are strict UTF-8 and retain their exact text.
|
|
2582
|
+
The operation requires an enabled unfinished checkpoint in the current execution
|
|
2583
|
+
stage. Identical retry inputs preserve project bytes. Conflicting retries refuse.
|
|
2584
|
+
|
|
2585
|
+
The original step, checkpoint decision, proposal, approval hashes and signatures
|
|
2586
|
+
remain unchanged. A withdrawal supplies operator policy without creating a human
|
|
2587
|
+
act or signature. Only an exact step hash and replacement generation match makes
|
|
2588
|
+
the effective requirement false. A later revision or re-enabled decision needs
|
|
2589
|
+
its own policy. Old journal entries and event-time status snapshots remain
|
|
2590
|
+
history. Absence of the optional journal preserves existing behavior.
|
|
2591
|
+
|
|
2592
|
+
|
|
2593
|
+
### Operator amendment of an execution bar
|
|
2594
|
+
|
|
2595
|
+
`plan bar-amend <id> [<project dir>] --by <operator> --reason-file <file>
|
|
2596
|
+
--quote-file <file> --bar-file <file>` appends an optional
|
|
2597
|
+
`plan.bar_amendments[]` entry with exactly these fields:
|
|
2598
|
+
|
|
2599
|
+
```json
|
|
2600
|
+
{
|
|
2601
|
+
"schema": "rig-create/bar-amendment@1",
|
|
2602
|
+
"step": { "id": "geometry", "phase": "rig", "bar": "Original source-bound bar.", "status": "pending" },
|
|
2603
|
+
"sha256": "<original stepHash>",
|
|
2604
|
+
"generation": 0,
|
|
2605
|
+
"amended_bar": "<exact bar-file text>",
|
|
2606
|
+
"by": "<operator>",
|
|
2607
|
+
"at": "<ISO timestamp>",
|
|
2608
|
+
"reason": "<exact reason-file text>",
|
|
2609
|
+
"verbatim": "<exact quote-file text>"
|
|
2610
|
+
}
|
|
2611
|
+
```
|
|
2612
|
+
|
|
2613
|
+
`step` retains the complete original object; the shape above abbreviates its fields.
|
|
2614
|
+
`generation` counts retained replacements for that step id. The amendment applies
|
|
2615
|
+
only to the exact current original hash and generation. A later revision does
|
|
2616
|
+
not inherit it, even when the original text is restored. Historical amendments
|
|
2617
|
+
remain bound to their retained original version. A malformed journal grants no
|
|
2618
|
+
partial policy and refuses check; a future entry is invalid at check's instant.
|
|
2619
|
+
Absence of this optional journal preserves existing behavior.
|
|
2620
|
+
|
|
2621
|
+
This operation requires one unfinished step in its current execution stage and
|
|
2622
|
+
nonempty strict UTF-8 input files. The files retain BOMs, whitespace and final
|
|
2623
|
+
newlines. Their contents are checked before and within the bound-job and plan
|
|
2624
|
+
locks and again before commit. Identical retry inputs preserve project bytes,
|
|
2625
|
+
inode and modification times; changed inputs for an already-bound amendment
|
|
2626
|
+
refuse. The original step, every approval hash and signature, checkpoint policy,
|
|
2627
|
+
and historical act receipt remain unchanged. Normal signed-step revision guards
|
|
2628
|
+
still apply.
|
|
2629
|
+
|
|
2630
|
+
The operator records an explicitly authorized quoted policy here, without a new
|
|
2631
|
+
human act or signature. This authority is specific to bar amendment; it does not
|
|
2632
|
+
permit other human decisions outside Review. The effective bar supplies the
|
|
2633
|
+
existing warning-only appearance wording lint. Create does not interpret English
|
|
2634
|
+
bar text as an automatic producer measurement or proof of completion. Normal
|
|
2635
|
+
done, next and advance retain their existing checks and producer-report contracts.
|
|
2636
|
+
|
|
2637
|
+
## Updating a project's release pins
|
|
2638
|
+
|
|
2639
|
+
Run `rig-create packages upgrade [dir] --by <operator>` before opening a record
|
|
2640
|
+
ask on a host whose parts release differs from the project's. The writer moves
|
|
2641
|
+
`dependencies` for core, parts and review to Create's release pins, using a
|
|
2642
|
+
staged `bun install --ignore-scripts`. No manual `bun add` is needed. The
|
|
2643
|
+
record publication contract compares parts only; core and review still move
|
|
2644
|
+
with Create's complete release pin set. Missing pins are recorded as `null`.
|
|
2645
|
+
|
|
2646
|
+
The writer appends `package_upgrades[]`, with `by`, `at`, `packages` (each entry
|
|
2647
|
+
has `name`, `from`, `to`) and `lock_sha256` (the installed lockfile's sha256).
|
|
2648
|
+
It preserves literal manifest and record bytes outside those fields. The
|
|
2649
|
+
lockfile and install are regenerated; lifecycle scripts are not executed.
|
|
2650
|
+
It never downgrades, and refuses an already-current manifest. Local and
|
|
2651
|
+
workspace dependencies are refused because staging would change their base.
|
|
2652
|
+
|
|
2653
|
+
The same project check runs in fresh processes before and after the install
|
|
2654
|
+
swap, avoiding cached parts modules. Added or changed refusals abort the move;
|
|
2655
|
+
the record, manifest, lockfile and original install are restored. Complete
|
|
2656
|
+
this command before another process reads or writes the project. This is an
|
|
2657
|
+
operator pin migration, not a review verdict or stage transition.
|