rig-create 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -5
- package/docs/AGENT-REFERENCE.md +62 -0
- package/docs/CHECKS.md +45 -9
- package/docs/INTERVIEW.md +19 -7
- package/docs/PROJECT.md +10 -0
- package/package.json +4 -1
- package/scripts/npm-json.ts +74 -0
- package/scripts/verify-example-seals.ts +148 -0
- package/src/agent-guide.ts +7 -4
- package/src/check.ts +7 -4
- package/src/choice-writers.ts +3 -14
- package/src/cli.ts +1 -0
- package/src/feedback.ts +3 -10
- package/src/fix-ledger.ts +1 -1
- package/src/job-acts.ts +4 -0
- package/src/job-host-state.ts +154 -0
- package/src/job-host.ts +37 -14
- package/src/job-outbox.ts +5 -3
- package/src/job-publication.ts +17 -13
- package/src/job-runtime.ts +17 -4
- package/src/next.ts +110 -24
- package/src/parts-review.ts +4 -11
- package/src/reopen.ts +72 -9
- package/src/review-act.ts +49 -14
- package/src/review-package.ts +3 -1
- package/src/rig-version.ts +219 -8
- package/src/scene-writers.ts +5 -3
- package/src/scene.ts +14 -4
- package/src/signable.ts +25 -3
- package/src/signoff-checkpoint-act.ts +2 -16
- package/src/signoff.ts +3 -15
- package/src/waypoints.ts +20 -9
- package/templates/agent-guide.md +2 -24
- package/templates/collection.json +10 -2
- package/templates/example-chain/.gitignore +6 -0
- package/templates/example-chain/.npmignore +1 -0
- package/templates/example-chain/AGENT-REFERENCE.md +62 -0
- package/templates/example-chain/AGENTS.md +4 -26
- package/templates/example-chain/README.md +1 -1
- package/templates/example-chain/chain.json +385 -319
- package/templates/example-chain/checkpoints/0a-interview-options/.gitignore +6 -0
- package/templates/example-chain/checkpoints/0a-interview-options/.npmignore +1 -0
- package/templates/example-chain/checkpoints/0a-interview-options/AGENT-REFERENCE.md +62 -0
- package/templates/example-chain/checkpoints/0a-interview-options/AGENTS.md +4 -26
- package/templates/example-chain/checkpoints/0a-interview-options/project.json +22 -5
- package/templates/example-chain/checkpoints/0a-interview-options.json +7 -3
- package/templates/example-chain/checkpoints/0b-plan-pending/.gitignore +6 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/.npmignore +1 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/AGENT-REFERENCE.md +62 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/AGENTS.md +4 -26
- package/templates/example-chain/checkpoints/0b-plan-pending/project.json +22 -5
- package/templates/example-chain/checkpoints/0b-plan-pending.json +7 -3
- package/templates/example-chain/checkpoints/1-parts-verdict/.gitignore +6 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/.npmignore +1 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/AGENT-REFERENCE.md +62 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/AGENTS.md +4 -26
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/config.json +88 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/input/painting_in_rig.png +0 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/input/parts/background.png +0 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/input/parts/eye_l.png +0 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/input/parts/eye_r.png +0 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/input/parts/face.png +0 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/input/parts/lantern.png +0 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/input/parts/torso.png +0 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/input/parts.json +188 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/input/recomposite_rig.png +0 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/interview-requirements.json +8 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/check/build/run.json +40 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/check/build/skeleton.atlas +28 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/check/build/skeleton.json +674 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/check/build/skeleton.model.json +1072 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/check/build/skeleton.png +0 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/images/background.png +0 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/images/eye_l.png +0 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/images/eye_r.png +0 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/images/face.png +0 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/images/lantern.png +0 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/images/torso.png +0 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/mesh_report.json +15 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/motion.json +137 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/rig.json +536 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/derived/drafts/chain/out/run.json +52 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/project.json +24 -7
- package/templates/example-chain/checkpoints/1-parts-verdict.json +9 -5
- package/templates/example-chain/checkpoints/2-rigging-answers/.gitignore +6 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/.npmignore +1 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/AGENT-REFERENCE.md +62 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/AGENTS.md +4 -26
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/config.json +88 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/input/painting_in_rig.png +0 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/input/parts/background.png +0 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/input/parts/eye_l.png +0 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/input/parts/eye_r.png +0 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/input/parts/face.png +0 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/input/parts/lantern.png +0 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/input/parts/torso.png +0 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/input/parts.json +188 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/input/recomposite_rig.png +0 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/interview-requirements.json +8 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/check/build/run.json +40 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/check/build/skeleton.atlas +28 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/check/build/skeleton.json +674 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/check/build/skeleton.model.json +1072 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/check/build/skeleton.png +0 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/images/background.png +0 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/images/eye_l.png +0 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/images/eye_r.png +0 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/images/face.png +0 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/images/lantern.png +0 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/images/torso.png +0 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/mesh_report.json +15 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/motion.json +137 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/rig.json +536 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/derived/drafts/chain/out/run.json +52 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/project.json +24 -7
- package/templates/example-chain/checkpoints/2-rigging-answers.json +21 -5
- package/templates/example-chain/checkpoints/3-rig-review/.gitignore +6 -0
- package/templates/example-chain/checkpoints/3-rig-review/.npmignore +1 -0
- package/templates/example-chain/checkpoints/3-rig-review/AGENT-REFERENCE.md +62 -0
- package/templates/example-chain/checkpoints/3-rig-review/AGENTS.md +4 -26
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/config.json +88 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/input/painting_in_rig.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/input/parts/background.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/input/parts/eye_l.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/input/parts/eye_r.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/input/parts/face.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/input/parts/lantern.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/input/parts/torso.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/input/parts.json +188 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/input/recomposite_rig.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/interview-requirements.json +8 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/check/build/run.json +40 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/check/build/skeleton.atlas +28 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/check/build/skeleton.json +674 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/check/build/skeleton.model.json +1072 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/check/build/skeleton.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/images/background.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/images/eye_l.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/images/eye_r.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/images/face.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/images/lantern.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/images/torso.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/mesh_report.json +15 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/motion.json +137 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/rig.json +536 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/drafts/chain/out/run.json +52 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/config.json +88 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/interview-requirements.json +8 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/check/build/run.json +40 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/check/build/skeleton.atlas +28 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/check/build/skeleton.json +674 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/check/build/skeleton.model.json +1072 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/check/build/skeleton.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/parts/background.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/parts/eye_l.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/parts/eye_r.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/parts/face.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/parts/lantern.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/parts/torso.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/parts.json +188 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/rig/images/background.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/rig/images/eye_l.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/rig/images/eye_r.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/rig/images/face.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/rig/images/lantern.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/rig/images/torso.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/rig/mesh_report.json +15 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/rig/motion.json +137 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/rig/rig.json +536 -0
- package/templates/example-chain/checkpoints/3-rig-review/derived/review/v1/out/rig/run.json +52 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/motion.json +1 -1
- package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/turn.json +108 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/check/build/run.json +40 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/check/build/skeleton.atlas +28 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/check/build/skeleton.json +674 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/check/build/skeleton.model.json +1072 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/check/build/skeleton.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/painting_in_rig.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/parts/background.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/parts/eye_l.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/parts/eye_r.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/parts/face.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/parts/lantern.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/parts/torso.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/parts.json +188 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/rig/images/background.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/rig/images/eye_l.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/rig/images/eye_r.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/rig/images/face.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/rig/images/lantern.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/rig/images/torso.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/rig/mesh_report.json +15 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/rig/motion.json +137 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/rig/rig.json +536 -0
- package/templates/example-chain/checkpoints/3-rig-review/outputs/v1/out/rig/run.json +52 -0
- package/templates/example-chain/checkpoints/3-rig-review/project.json +77 -28
- package/templates/example-chain/checkpoints/3-rig-review.json +19 -11
- package/templates/example-chain/checkpoints/4-direction-post/.gitignore +6 -0
- package/templates/example-chain/checkpoints/4-direction-post/.npmignore +1 -0
- package/templates/example-chain/checkpoints/4-direction-post/AGENT-REFERENCE.md +62 -0
- package/templates/example-chain/checkpoints/4-direction-post/AGENTS.md +4 -26
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/config.json +88 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/input/painting_in_rig.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/input/parts/background.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/input/parts/eye_l.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/input/parts/eye_r.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/input/parts/face.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/input/parts/lantern.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/input/parts/torso.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/input/parts.json +188 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/input/recomposite_rig.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/interview-requirements.json +8 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/check/build/run.json +40 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/check/build/skeleton.atlas +28 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/check/build/skeleton.json +674 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/check/build/skeleton.model.json +1072 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/check/build/skeleton.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/images/background.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/images/eye_l.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/images/eye_r.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/images/face.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/images/lantern.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/images/torso.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/mesh_report.json +15 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/motion.json +137 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/rig.json +536 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/drafts/chain/out/run.json +52 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/config.json +88 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/interview-requirements.json +8 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/check/build/run.json +40 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/check/build/skeleton.atlas +28 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/check/build/skeleton.json +674 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/check/build/skeleton.model.json +1072 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/check/build/skeleton.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/parts/background.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/parts/eye_l.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/parts/eye_r.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/parts/face.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/parts/lantern.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/parts/torso.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/parts.json +188 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/rig/images/background.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/rig/images/eye_l.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/rig/images/eye_r.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/rig/images/face.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/rig/images/lantern.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/rig/images/torso.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/rig/mesh_report.json +15 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/rig/motion.json +137 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/rig/rig.json +536 -0
- package/templates/example-chain/checkpoints/4-direction-post/derived/review/v1/out/rig/run.json +52 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/camera_depth.json +2 -2
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/motion.json +1 -1
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/post_composition.json +2 -2
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/post_timing.json +2 -2
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/turn.json +108 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/check/build/run.json +40 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/check/build/skeleton.atlas +28 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/check/build/skeleton.json +674 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/check/build/skeleton.model.json +1072 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/check/build/skeleton.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/painting_in_rig.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/parts/background.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/parts/eye_l.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/parts/eye_r.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/parts/face.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/parts/lantern.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/parts/torso.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/parts.json +188 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/rig/images/background.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/rig/images/eye_l.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/rig/images/eye_r.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/rig/images/face.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/rig/images/lantern.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/rig/images/torso.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/rig/mesh_report.json +15 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/rig/motion.json +137 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/rig/rig.json +536 -0
- package/templates/example-chain/checkpoints/4-direction-post/outputs/v1/out/rig/run.json +52 -0
- package/templates/example-chain/checkpoints/4-direction-post/project.json +106 -57
- package/templates/example-chain/checkpoints/4-direction-post.json +22 -14
- package/templates/example-chain/derived/drafts/chain/config.json +88 -0
- package/templates/example-chain/derived/drafts/chain/input/painting_in_rig.png +0 -0
- package/templates/example-chain/derived/drafts/chain/input/parts/background.png +0 -0
- package/templates/example-chain/derived/drafts/chain/input/parts/eye_l.png +0 -0
- package/templates/example-chain/derived/drafts/chain/input/parts/eye_r.png +0 -0
- package/templates/example-chain/derived/drafts/chain/input/parts/face.png +0 -0
- package/templates/example-chain/derived/drafts/chain/input/parts/lantern.png +0 -0
- package/templates/example-chain/derived/drafts/chain/input/parts/torso.png +0 -0
- package/templates/example-chain/derived/drafts/chain/input/parts.json +188 -0
- package/templates/example-chain/derived/drafts/chain/input/recomposite_rig.png +0 -0
- package/templates/example-chain/derived/drafts/chain/interview-requirements.json +8 -0
- package/templates/example-chain/derived/drafts/chain/out/check/build/run.json +40 -0
- package/templates/example-chain/derived/drafts/chain/out/check/build/skeleton.atlas +28 -0
- package/templates/example-chain/derived/drafts/chain/out/check/build/skeleton.json +674 -0
- package/templates/example-chain/derived/drafts/chain/out/check/build/skeleton.model.json +1072 -0
- package/templates/example-chain/derived/drafts/chain/out/check/build/skeleton.png +0 -0
- package/templates/example-chain/derived/drafts/chain/out/images/background.png +0 -0
- package/templates/example-chain/derived/drafts/chain/out/images/eye_l.png +0 -0
- package/templates/example-chain/derived/drafts/chain/out/images/eye_r.png +0 -0
- package/templates/example-chain/derived/drafts/chain/out/images/face.png +0 -0
- package/templates/example-chain/derived/drafts/chain/out/images/lantern.png +0 -0
- package/templates/example-chain/derived/drafts/chain/out/images/torso.png +0 -0
- package/templates/example-chain/derived/drafts/chain/out/mesh_report.json +15 -0
- package/templates/example-chain/derived/drafts/chain/out/motion.json +137 -0
- package/templates/example-chain/derived/drafts/chain/out/rig.json +536 -0
- package/templates/example-chain/derived/drafts/chain/out/run.json +52 -0
- package/templates/example-chain/derived/review/v1/config.json +88 -0
- package/templates/example-chain/derived/review/v1/interview-requirements.json +8 -0
- package/templates/example-chain/derived/review/v1/out/check/build/run.json +40 -0
- package/templates/example-chain/derived/review/v1/out/check/build/skeleton.atlas +28 -0
- package/templates/example-chain/derived/review/v1/out/check/build/skeleton.json +674 -0
- package/templates/example-chain/derived/review/v1/out/check/build/skeleton.model.json +1072 -0
- package/templates/example-chain/derived/review/v1/out/check/build/skeleton.png +0 -0
- package/templates/example-chain/derived/review/v1/out/parts/background.png +0 -0
- package/templates/example-chain/derived/review/v1/out/parts/eye_l.png +0 -0
- package/templates/example-chain/derived/review/v1/out/parts/eye_r.png +0 -0
- package/templates/example-chain/derived/review/v1/out/parts/face.png +0 -0
- package/templates/example-chain/derived/review/v1/out/parts/lantern.png +0 -0
- package/templates/example-chain/derived/review/v1/out/parts/torso.png +0 -0
- package/templates/example-chain/derived/review/v1/out/parts.json +188 -0
- package/templates/example-chain/derived/review/v1/out/rig/images/background.png +0 -0
- package/templates/example-chain/derived/review/v1/out/rig/images/eye_l.png +0 -0
- package/templates/example-chain/derived/review/v1/out/rig/images/eye_r.png +0 -0
- package/templates/example-chain/derived/review/v1/out/rig/images/face.png +0 -0
- package/templates/example-chain/derived/review/v1/out/rig/images/lantern.png +0 -0
- package/templates/example-chain/derived/review/v1/out/rig/images/torso.png +0 -0
- package/templates/example-chain/derived/review/v1/out/rig/mesh_report.json +15 -0
- package/templates/example-chain/derived/review/v1/out/rig/motion.json +137 -0
- package/templates/example-chain/derived/review/v1/out/rig/rig.json +536 -0
- package/templates/example-chain/derived/review/v1/out/rig/run.json +52 -0
- package/templates/example-chain/evidence/captions.json +1 -1
- package/templates/example-chain/evidence/direction/v2.json +1 -1
- package/templates/example-chain/evidence/direction-input.json +1 -1
- package/templates/example-chain/evidence/interview/camera_depth.json +2 -2
- package/templates/example-chain/evidence/interview/motion.json +1 -1
- package/templates/example-chain/evidence/interview/post_composition.json +2 -2
- package/templates/example-chain/evidence/interview/post_timing.json +2 -2
- package/templates/example-chain/evidence/interview/turn.json +108 -0
- package/templates/example-chain/evidence/scene/s1.json +2 -2
- package/templates/example-chain/outputs/v1/out/check/build/run.json +40 -0
- package/templates/example-chain/outputs/v1/out/check/build/skeleton.atlas +28 -0
- package/templates/example-chain/outputs/v1/out/check/build/skeleton.json +674 -0
- package/templates/example-chain/outputs/v1/out/check/build/skeleton.model.json +1072 -0
- package/templates/example-chain/outputs/v1/out/check/build/skeleton.png +0 -0
- package/templates/example-chain/outputs/v1/out/painting_in_rig.png +0 -0
- package/templates/example-chain/outputs/v1/out/parts/background.png +0 -0
- package/templates/example-chain/outputs/v1/out/parts/eye_l.png +0 -0
- package/templates/example-chain/outputs/v1/out/parts/eye_r.png +0 -0
- package/templates/example-chain/outputs/v1/out/parts/face.png +0 -0
- package/templates/example-chain/outputs/v1/out/parts/lantern.png +0 -0
- package/templates/example-chain/outputs/v1/out/parts/torso.png +0 -0
- package/templates/example-chain/outputs/v1/out/parts.json +188 -0
- package/templates/example-chain/outputs/v1/out/rig/images/background.png +0 -0
- package/templates/example-chain/outputs/v1/out/rig/images/eye_l.png +0 -0
- package/templates/example-chain/outputs/v1/out/rig/images/eye_r.png +0 -0
- package/templates/example-chain/outputs/v1/out/rig/images/face.png +0 -0
- package/templates/example-chain/outputs/v1/out/rig/images/lantern.png +0 -0
- package/templates/example-chain/outputs/v1/out/rig/images/torso.png +0 -0
- package/templates/example-chain/outputs/v1/out/rig/mesh_report.json +15 -0
- package/templates/example-chain/outputs/v1/out/rig/motion.json +137 -0
- package/templates/example-chain/outputs/v1/out/rig/rig.json +536 -0
- package/templates/example-chain/outputs/v1/out/rig/run.json +52 -0
- package/templates/example-chain/project.json +127 -78
- package/templates/example-direction/derived/review/v1/out/check/build/run.json +2 -2
- package/templates/example-draft/derived/drafts/lantern/out/check/build/run.json +2 -2
- package/templates/example-draft/derived/drafts/lantern/out/run.json +2 -2
- package/templates/example-draft/derived/review/v1/out/check/build/run.json +2 -2
- package/templates/example-draft/derived/review/v1/out/rig/run.json +2 -2
- package/templates/example-draft/derived/review/v2/out/check/build/run.json +2 -2
- package/templates/example-draft/derived/review/v2/out/rig/run.json +2 -2
- package/templates/example-draft/evidence/direction/v4.json +3 -3
- package/templates/example-draft/evidence/direction-input-v4.json +3 -3
- package/templates/example-draft/evidence/parts-review.json +1 -1
- package/templates/example-draft/evidence/review-reads/{52673b635b9cbc92da1a9e3d4c023a249bbacf79cd21b59724f03f18f8caf09b.json → 8866887a00012b5d5944b7525a478aea70931935bff35ddfcb186ffc515ef5af.json} +2 -2
- package/templates/example-draft/evidence/scene/s1.json +3 -3
- package/templates/example-draft/evidence/scene-citations.json +1 -1
- package/templates/example-draft/out/check/build/run.json +2 -2
- package/templates/example-draft/out/run.json +2 -2
- package/templates/example-draft/outputs/v1/out/check/build/run.json +2 -2
- package/templates/example-draft/outputs/v1/out/rig/run.json +2 -2
- package/templates/example-draft/outputs/v2/out/check/build/run.json +2 -2
- package/templates/example-draft/outputs/v2/out/rig/run.json +2 -2
- package/templates/example-interview-choice.json +113 -68
- package/templates/example-interview-options/constraint.json +2 -2
- package/templates/example-interview-options/example-assemble.json +2 -2
- package/templates/example-interview-options/example-bones.json +5 -5
- package/templates/example-interview-options/example-camera-depth.json +3 -3
- package/templates/example-interview-options/example-constraints.json +5 -5
- package/templates/example-interview-options/example-meshes.json +5 -5
- package/templates/example-interview-options/example-motion.json +5 -5
- package/templates/example-interview-options/example-picks.json +2 -2
- package/templates/example-interview-options/example-post-composition.json +3 -3
- package/templates/example-interview-options/example-post-timing.json +3 -3
- package/templates/example-interview-options/example-reference.json +2 -2
- package/templates/example-interview-options/example-rig-type.json +2 -2
- package/templates/example-interview-options/example-seethrough.json +2 -2
- package/templates/example-interview-options/example-turn.json +108 -0
- package/templates/example-interview-options/fullscreen.json +2 -2
- package/templates/example-interview-options/other-explicit.json +2 -2
- package/templates/example-interview-options/other-pending.json +2 -2
- package/templates/example-interview-options/other-picks.json +2 -2
- package/templates/example-invariants/invariants.json +223 -164
- package/templates/example-project.json +301 -249
- package/templates/example-remesh/.gitignore +6 -0
- package/templates/example-remesh/.npmignore +1 -0
- package/templates/example-remesh/AGENT-REFERENCE.md +62 -0
- package/templates/example-remesh/AGENTS.md +4 -26
- package/templates/example-remesh/derived/drafts/remesh/config.json +88 -0
- package/templates/example-remesh/derived/drafts/remesh/input/painting_in_rig.png +0 -0
- package/templates/example-remesh/derived/drafts/remesh/input/parts/background.png +0 -0
- package/templates/example-remesh/derived/drafts/remesh/input/parts/eye_l.png +0 -0
- package/templates/example-remesh/derived/drafts/remesh/input/parts/eye_r.png +0 -0
- package/templates/example-remesh/derived/drafts/remesh/input/parts/face.png +0 -0
- package/templates/example-remesh/derived/drafts/remesh/input/parts/lantern.png +0 -0
- package/templates/example-remesh/derived/drafts/remesh/input/parts/torso.png +0 -0
- package/templates/example-remesh/derived/drafts/remesh/input/parts.json +188 -0
- package/templates/example-remesh/derived/drafts/remesh/input/recomposite_rig.png +0 -0
- package/templates/example-remesh/derived/drafts/remesh/interview-requirements.json +8 -0
- package/templates/example-remesh/derived/drafts/remesh/out/check/build/run.json +40 -0
- package/templates/example-remesh/derived/drafts/remesh/out/check/build/skeleton.atlas +28 -0
- package/templates/example-remesh/derived/drafts/remesh/out/check/build/skeleton.json +674 -0
- package/templates/example-remesh/derived/drafts/remesh/out/check/build/skeleton.model.json +1072 -0
- package/templates/example-remesh/derived/drafts/remesh/out/check/build/skeleton.png +0 -0
- package/templates/example-remesh/derived/drafts/remesh/out/images/background.png +0 -0
- package/templates/example-remesh/derived/drafts/remesh/out/images/eye_l.png +0 -0
- package/templates/example-remesh/derived/drafts/remesh/out/images/eye_r.png +0 -0
- package/templates/example-remesh/derived/drafts/remesh/out/images/face.png +0 -0
- package/templates/example-remesh/derived/drafts/remesh/out/images/lantern.png +0 -0
- package/templates/example-remesh/derived/drafts/remesh/out/images/torso.png +0 -0
- package/templates/example-remesh/derived/drafts/remesh/out/mesh_report.json +15 -0
- package/templates/example-remesh/derived/drafts/remesh/out/motion.json +137 -0
- package/templates/example-remesh/derived/drafts/remesh/out/rig.json +536 -0
- package/templates/example-remesh/derived/drafts/remesh/out/run.json +52 -0
- package/templates/example-remesh/derived/review/v1/config.json +88 -0
- package/templates/example-remesh/derived/review/v1/interview-requirements.json +8 -0
- package/templates/example-remesh/derived/review/v1/out/check/build/run.json +44 -0
- package/templates/example-remesh/derived/review/v1/out/check/build/skeleton.atlas +28 -0
- package/templates/example-remesh/derived/review/v1/out/check/build/skeleton.json +674 -0
- package/templates/example-remesh/derived/review/v1/out/check/build/skeleton.model.json +1072 -0
- package/templates/example-remesh/derived/review/v1/out/check/build/skeleton.png +0 -0
- package/templates/example-remesh/derived/review/v1/out/painting_in_rig.png +0 -0
- package/templates/example-remesh/derived/review/v1/out/parts/background.png +0 -0
- package/templates/example-remesh/derived/review/v1/out/parts/eye_l.png +0 -0
- package/templates/example-remesh/derived/review/v1/out/parts/eye_r.png +0 -0
- package/templates/example-remesh/derived/review/v1/out/parts/face.png +0 -0
- package/templates/example-remesh/derived/review/v1/out/parts/lantern.png +0 -0
- package/templates/example-remesh/derived/review/v1/out/parts/torso.png +0 -0
- package/templates/example-remesh/derived/review/v1/out/parts.json +188 -0
- package/templates/example-remesh/derived/review/v1/out/rig/images/background.png +0 -0
- package/templates/example-remesh/derived/review/v1/out/rig/images/eye_l.png +0 -0
- package/templates/example-remesh/derived/review/v1/out/rig/images/eye_r.png +0 -0
- package/templates/example-remesh/derived/review/v1/out/rig/images/face.png +0 -0
- package/templates/example-remesh/derived/review/v1/out/rig/images/lantern.png +0 -0
- package/templates/example-remesh/derived/review/v1/out/rig/images/torso.png +0 -0
- package/templates/example-remesh/derived/review/v1/out/rig/mesh_report.json +15 -0
- package/templates/example-remesh/derived/review/v1/out/rig/motion.json +137 -0
- package/templates/example-remesh/derived/review/v1/out/rig/rig.json +536 -0
- package/templates/example-remesh/derived/review/v1/out/rig/run.json +52 -0
- package/templates/example-remesh/derived/review/v2/config.json +88 -0
- package/templates/example-remesh/derived/review/v2/interview-requirements.json +8 -0
- package/templates/example-remesh/derived/review/v2/out/check/build/run.json +44 -0
- package/templates/example-remesh/derived/review/v2/out/check/build/skeleton.atlas +28 -0
- package/templates/example-remesh/derived/review/v2/out/check/build/skeleton.json +674 -0
- package/templates/example-remesh/derived/review/v2/out/check/build/skeleton.model.json +1072 -0
- package/templates/example-remesh/derived/review/v2/out/check/build/skeleton.png +0 -0
- package/templates/example-remesh/derived/review/v2/out/painting_in_rig.png +0 -0
- package/templates/example-remesh/derived/review/v2/out/parts/background.png +0 -0
- package/templates/example-remesh/derived/review/v2/out/parts/eye_l.png +0 -0
- package/templates/example-remesh/derived/review/v2/out/parts/eye_r.png +0 -0
- package/templates/example-remesh/derived/review/v2/out/parts/face.png +0 -0
- package/templates/example-remesh/derived/review/v2/out/parts/lantern.png +0 -0
- package/templates/example-remesh/derived/review/v2/out/parts/torso.png +0 -0
- package/templates/example-remesh/derived/review/v2/out/parts.json +188 -0
- package/templates/example-remesh/derived/review/v2/out/rig/images/background.png +0 -0
- package/templates/example-remesh/derived/review/v2/out/rig/images/eye_l.png +0 -0
- package/templates/example-remesh/derived/review/v2/out/rig/images/eye_r.png +0 -0
- package/templates/example-remesh/derived/review/v2/out/rig/images/face.png +0 -0
- package/templates/example-remesh/derived/review/v2/out/rig/images/lantern.png +0 -0
- package/templates/example-remesh/derived/review/v2/out/rig/images/torso.png +0 -0
- package/templates/example-remesh/derived/review/v2/out/rig/mesh_report.json +15 -0
- package/templates/example-remesh/derived/review/v2/out/rig/motion.json +137 -0
- package/templates/example-remesh/derived/review/v2/out/rig/rig.json +536 -0
- package/templates/example-remesh/derived/review/v2/out/rig/run.json +52 -0
- package/templates/example-remesh/derived/review/v3/config.json +88 -0
- package/templates/example-remesh/derived/review/v3/interview-requirements.json +8 -0
- package/templates/example-remesh/derived/review/v3/out/check/build/run.json +44 -0
- package/templates/example-remesh/derived/review/v3/out/check/build/skeleton.atlas +28 -0
- package/templates/example-remesh/derived/review/v3/out/check/build/skeleton.json +674 -0
- package/templates/example-remesh/derived/review/v3/out/check/build/skeleton.model.json +1072 -0
- package/templates/example-remesh/derived/review/v3/out/check/build/skeleton.png +0 -0
- package/templates/example-remesh/derived/review/v3/out/painting_in_rig.png +0 -0
- package/templates/example-remesh/derived/review/v3/out/parts/background.png +0 -0
- package/templates/example-remesh/derived/review/v3/out/parts/eye_l.png +0 -0
- package/templates/example-remesh/derived/review/v3/out/parts/eye_r.png +0 -0
- package/templates/example-remesh/derived/review/v3/out/parts/face.png +0 -0
- package/templates/example-remesh/derived/review/v3/out/parts/lantern.png +0 -0
- package/templates/example-remesh/derived/review/v3/out/parts/torso.png +0 -0
- package/templates/example-remesh/derived/review/v3/out/parts.json +188 -0
- package/templates/example-remesh/derived/review/v3/out/rig/images/background.png +0 -0
- package/templates/example-remesh/derived/review/v3/out/rig/images/eye_l.png +0 -0
- package/templates/example-remesh/derived/review/v3/out/rig/images/eye_r.png +0 -0
- package/templates/example-remesh/derived/review/v3/out/rig/images/face.png +0 -0
- package/templates/example-remesh/derived/review/v3/out/rig/images/lantern.png +0 -0
- package/templates/example-remesh/derived/review/v3/out/rig/images/torso.png +0 -0
- package/templates/example-remesh/derived/review/v3/out/rig/mesh_report.json +15 -0
- package/templates/example-remesh/derived/review/v3/out/rig/motion.json +137 -0
- package/templates/example-remesh/derived/review/v3/out/rig/rig.json +536 -0
- package/templates/example-remesh/derived/review/v3/out/rig/run.json +52 -0
- package/templates/example-remesh/evidence/captions.json +1 -1
- package/templates/example-remesh/evidence/direction/v4.json +1 -1
- package/templates/example-remesh/evidence/direction/v5.json +1 -1
- package/templates/example-remesh/evidence/direction-input-v4.json +1 -1
- package/templates/example-remesh/evidence/direction-input-v5.json +1 -1
- package/templates/example-remesh/evidence/interview/assemble.json +1 -1
- package/templates/example-remesh/evidence/interview/bones.json +4 -4
- package/templates/example-remesh/evidence/interview/camera_depth.json +2 -2
- package/templates/example-remesh/evidence/interview/constraints.json +4 -4
- package/templates/example-remesh/evidence/interview/meshes.json +4 -4
- package/templates/example-remesh/evidence/interview/motion.json +4 -4
- package/templates/example-remesh/evidence/interview/post_composition.json +2 -2
- package/templates/example-remesh/evidence/interview/post_timing.json +2 -2
- package/templates/example-remesh/evidence/interview/reference.json +1 -1
- package/templates/example-remesh/evidence/interview/rig_type.json +1 -1
- package/templates/example-remesh/evidence/interview/seethrough.json +1 -1
- package/templates/example-remesh/evidence/interview/turn.json +108 -0
- package/templates/example-remesh/evidence/parts-review.json +1 -1
- package/templates/example-remesh/evidence/review-reads/{afe2522be4087f7f2fa7e97746d5f8574b0aedb474245ce2dbce0455e662f041.json → 99ade3eb19d70bd5f727138b3b4876ce86f1e1c22a59b516639bf85593996c32.json} +2 -2
- package/templates/example-remesh/evidence/scene/s1.json +2 -2
- package/templates/example-remesh/evidence/v1/registration/at-source.json +2 -2
- package/templates/example-remesh/evidence/v1/registration/rigc-run-1.json +2 -2
- package/templates/example-remesh/evidence/v2/registration/at-source.json +2 -2
- package/templates/example-remesh/evidence/v2/registration/rigc-run-1.json +2 -2
- package/templates/example-remesh/evidence/v3/registration/at-source.json +2 -2
- package/templates/example-remesh/evidence/v3/registration/rigc-run-1.json +2 -2
- package/templates/example-remesh/outputs/v1/idle/frames.json +29 -0
- package/templates/example-remesh/outputs/v1/idle/idle@1fps/contact.png +0 -0
- package/templates/example-remesh/outputs/v1/idle/idle@1fps/f0000.png +0 -0
- package/templates/example-remesh/outputs/v1/idle/idle@1fps/f0001.png +0 -0
- package/templates/example-remesh/outputs/v1/idle/idle@1fps/f0002.png +0 -0
- package/templates/example-remesh/outputs/v1/idle/idle@1fps/f0003.png +0 -0
- package/templates/example-remesh/outputs/v1/idle/idle@1fps/f0004.png +0 -0
- package/templates/example-remesh/outputs/v1/out/check/build/run.json +44 -0
- package/templates/example-remesh/outputs/v1/out/check/build/skeleton.atlas +28 -0
- package/templates/example-remesh/outputs/v1/out/check/build/skeleton.json +674 -0
- package/templates/example-remesh/outputs/v1/out/check/build/skeleton.model.json +1072 -0
- package/templates/example-remesh/outputs/v1/out/check/build/skeleton.png +0 -0
- package/templates/example-remesh/outputs/v1/out/painting_in_rig.png +0 -0
- package/templates/example-remesh/outputs/v1/out/parts/background.png +0 -0
- package/templates/example-remesh/outputs/v1/out/parts/eye_l.png +0 -0
- package/templates/example-remesh/outputs/v1/out/parts/eye_r.png +0 -0
- package/templates/example-remesh/outputs/v1/out/parts/face.png +0 -0
- package/templates/example-remesh/outputs/v1/out/parts/lantern.png +0 -0
- package/templates/example-remesh/outputs/v1/out/parts/torso.png +0 -0
- package/templates/example-remesh/outputs/v1/out/parts.json +188 -0
- package/templates/example-remesh/outputs/v1/out/rig/images/background.png +0 -0
- package/templates/example-remesh/outputs/v1/out/rig/images/eye_l.png +0 -0
- package/templates/example-remesh/outputs/v1/out/rig/images/eye_r.png +0 -0
- package/templates/example-remesh/outputs/v1/out/rig/images/face.png +0 -0
- package/templates/example-remesh/outputs/v1/out/rig/images/lantern.png +0 -0
- package/templates/example-remesh/outputs/v1/out/rig/images/torso.png +0 -0
- package/templates/example-remesh/outputs/v1/out/rig/mesh_report.json +15 -0
- package/templates/example-remesh/outputs/v1/out/rig/motion.json +137 -0
- package/templates/example-remesh/outputs/v1/out/rig/rig.json +536 -0
- package/templates/example-remesh/outputs/v1/out/rig/run.json +52 -0
- package/templates/example-remesh/outputs/v2/idle/frames.json +29 -0
- package/templates/example-remesh/outputs/v2/idle/idle@1fps/contact.png +0 -0
- package/templates/example-remesh/outputs/v2/idle/idle@1fps/f0000.png +0 -0
- package/templates/example-remesh/outputs/v2/idle/idle@1fps/f0001.png +0 -0
- package/templates/example-remesh/outputs/v2/idle/idle@1fps/f0002.png +0 -0
- package/templates/example-remesh/outputs/v2/idle/idle@1fps/f0003.png +0 -0
- package/templates/example-remesh/outputs/v2/idle/idle@1fps/f0004.png +0 -0
- package/templates/example-remesh/outputs/v2/out/check/build/run.json +44 -0
- package/templates/example-remesh/outputs/v2/out/check/build/skeleton.atlas +28 -0
- package/templates/example-remesh/outputs/v2/out/check/build/skeleton.json +674 -0
- package/templates/example-remesh/outputs/v2/out/check/build/skeleton.model.json +1072 -0
- package/templates/example-remesh/outputs/v2/out/check/build/skeleton.png +0 -0
- package/templates/example-remesh/outputs/v2/out/painting_in_rig.png +0 -0
- package/templates/example-remesh/outputs/v2/out/parts/background.png +0 -0
- package/templates/example-remesh/outputs/v2/out/parts/eye_l.png +0 -0
- package/templates/example-remesh/outputs/v2/out/parts/eye_r.png +0 -0
- package/templates/example-remesh/outputs/v2/out/parts/face.png +0 -0
- package/templates/example-remesh/outputs/v2/out/parts/lantern.png +0 -0
- package/templates/example-remesh/outputs/v2/out/parts/torso.png +0 -0
- package/templates/example-remesh/outputs/v2/out/parts.json +188 -0
- package/templates/example-remesh/outputs/v2/out/rig/images/background.png +0 -0
- package/templates/example-remesh/outputs/v2/out/rig/images/eye_l.png +0 -0
- package/templates/example-remesh/outputs/v2/out/rig/images/eye_r.png +0 -0
- package/templates/example-remesh/outputs/v2/out/rig/images/face.png +0 -0
- package/templates/example-remesh/outputs/v2/out/rig/images/lantern.png +0 -0
- package/templates/example-remesh/outputs/v2/out/rig/images/torso.png +0 -0
- package/templates/example-remesh/outputs/v2/out/rig/mesh_report.json +15 -0
- package/templates/example-remesh/outputs/v2/out/rig/motion.json +137 -0
- package/templates/example-remesh/outputs/v2/out/rig/rig.json +536 -0
- package/templates/example-remesh/outputs/v2/out/rig/run.json +52 -0
- package/templates/example-remesh/outputs/v3/idle/frames.json +29 -0
- package/templates/example-remesh/outputs/v3/idle/idle@1fps/contact.png +0 -0
- package/templates/example-remesh/outputs/v3/idle/idle@1fps/f0000.png +0 -0
- package/templates/example-remesh/outputs/v3/idle/idle@1fps/f0001.png +0 -0
- package/templates/example-remesh/outputs/v3/idle/idle@1fps/f0002.png +0 -0
- package/templates/example-remesh/outputs/v3/idle/idle@1fps/f0003.png +0 -0
- package/templates/example-remesh/outputs/v3/idle/idle@1fps/f0004.png +0 -0
- package/templates/example-remesh/outputs/v3/out/check/build/run.json +44 -0
- package/templates/example-remesh/outputs/v3/out/check/build/skeleton.atlas +28 -0
- package/templates/example-remesh/outputs/v3/out/check/build/skeleton.json +674 -0
- package/templates/example-remesh/outputs/v3/out/check/build/skeleton.model.json +1072 -0
- package/templates/example-remesh/outputs/v3/out/check/build/skeleton.png +0 -0
- package/templates/example-remesh/outputs/v3/out/painting_in_rig.png +0 -0
- package/templates/example-remesh/outputs/v3/out/parts/background.png +0 -0
- package/templates/example-remesh/outputs/v3/out/parts/eye_l.png +0 -0
- package/templates/example-remesh/outputs/v3/out/parts/eye_r.png +0 -0
- package/templates/example-remesh/outputs/v3/out/parts/face.png +0 -0
- package/templates/example-remesh/outputs/v3/out/parts/lantern.png +0 -0
- package/templates/example-remesh/outputs/v3/out/parts/torso.png +0 -0
- package/templates/example-remesh/outputs/v3/out/parts.json +188 -0
- package/templates/example-remesh/outputs/v3/out/rig/images/background.png +0 -0
- package/templates/example-remesh/outputs/v3/out/rig/images/eye_l.png +0 -0
- package/templates/example-remesh/outputs/v3/out/rig/images/eye_r.png +0 -0
- package/templates/example-remesh/outputs/v3/out/rig/images/face.png +0 -0
- package/templates/example-remesh/outputs/v3/out/rig/images/lantern.png +0 -0
- package/templates/example-remesh/outputs/v3/out/rig/images/torso.png +0 -0
- package/templates/example-remesh/outputs/v3/out/rig/mesh_report.json +15 -0
- package/templates/example-remesh/outputs/v3/out/rig/motion.json +137 -0
- package/templates/example-remesh/outputs/v3/out/rig/rig.json +536 -0
- package/templates/example-remesh/outputs/v3/out/rig/run.json +52 -0
- package/templates/example-remesh/project.json +279 -230
- package/templates/example-reopened/project.json +341 -289
- package/templates/example-split/captions.json +1 -1
- package/templates/project.json +10 -2
package/src/choice-writers.ts
CHANGED
|
@@ -2,9 +2,8 @@ import { overrideFindings } from './overrides.ts';
|
|
|
2
2
|
import { intakeItem, intakeWarnings, INTAKE_QUESTION } from './intake.ts';
|
|
3
3
|
/** Public record writers; validation precedes every project write. */
|
|
4
4
|
import { readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { assertActSubjectDeclared, decodeReviewAct, reviewActFindings, reviewActTransport, type ReviewActTransport, type InterviewPicksAct } from './review-act.ts';
|
|
5
|
+
import { acquireBoundJobWrite } from './job-writer.ts';
|
|
6
|
+
import { assertActSubjectDeclared, decodeReviewAct, fetchReviewActBytes, reviewActFindings, reviewActTransport, type ReviewActTransport, type InterviewPicksAct } from './review-act.ts';
|
|
8
7
|
import { dirname, join, resolve } from 'node:path';
|
|
9
8
|
import { isDeepStrictEqual as equal } from 'node:util';
|
|
10
9
|
import { asArray, checkProject, collectItems, collectSignoffs, isObject, loadCollection, collectionAnswer, type Item } from './check.ts';
|
|
@@ -155,17 +154,7 @@ export function interviewAnswerCommand(args: string[], now: number, hooks: Inter
|
|
|
155
154
|
const invalid = reviewActFindings(next)[0];
|
|
156
155
|
if (invalid) refuse(invalid.code,invalid.message);
|
|
157
156
|
const transport: ReviewActTransport = { ...reviewActTransport(dir, opts.one['--from-review']), kind: 'interview-picks' };
|
|
158
|
-
|
|
159
|
-
else {
|
|
160
|
-
const child = Bun.spawnSync([process.execPath, ...jobRuntimeExecArgv(), fileURLToPath(new URL('./review-act-runtime.ts', import.meta.url))], {
|
|
161
|
-
stdin: Buffer.from(JSON.stringify(transport)), stdout: 'pipe', stderr: 'pipe',
|
|
162
|
-
});
|
|
163
|
-
let response: { ok: boolean; bytes: string; code: string; message: string };
|
|
164
|
-
try { response = JSON.parse(child.stdout.toString()); }
|
|
165
|
-
catch { return refuse('REVIEW_ACT_FETCH_REFUSED', 'project.json.review_acts: fetch adapter failed; restore the live Review job'); }
|
|
166
|
-
if (!response.ok || child.exitCode) refuse(response.code, response.message);
|
|
167
|
-
fetched = response;
|
|
168
|
-
}
|
|
157
|
+
fetched = hooks.fetch ? hooks.fetch(transport) : { bytes: fetchReviewActBytes(transport) };
|
|
169
158
|
act = decodeReviewAct(fetched.bytes, 'interview-picks');
|
|
170
159
|
if (act.jobId !== transport.jobId || act.actId !== transport.actId || Date.parse(act.at) > now
|
|
171
160
|
|| act.value.questionId !== item.id) refuse('REVIEW_ACT_INVALID', `${item.path}: fetched identity, question or date differs; fetch the correct interview act`);
|
package/src/cli.ts
CHANGED
|
@@ -85,6 +85,7 @@ ${INPUT_CLI} rig-create init <dir> [--no-install] create a project
|
|
|
85
85
|
move to the next stage authorized by a live signoff
|
|
86
86
|
rig-create step-status <step> <status> --by <who> [<project dir>] [--note-file <path>]
|
|
87
87
|
record an audited forward step status
|
|
88
|
+
rig-create reopen <stage> [<project dir>] --from-review <actId>
|
|
88
89
|
rig-create reopen <stage> --by <who> [--verbatim-file <file>] [--source <text>] [<project dir>]
|
|
89
90
|
record a human backward move without deleting history
|
|
90
91
|
rig-create pause --by <who> [--verbatim-file <file>] [<project dir>]
|
package/src/feedback.ts
CHANGED
|
@@ -20,12 +20,11 @@ import { assertCorrectionApproval } from './correction-writers.ts';
|
|
|
20
20
|
*/
|
|
21
21
|
import { closeSync, fsyncSync, mkdirSync, openSync, renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
22
22
|
import { existsSync, readFileSync } from './check-reads.ts';
|
|
23
|
-
import { fileURLToPath } from 'node:url';
|
|
24
23
|
import { randomUUID } from 'node:crypto';
|
|
25
24
|
import { isDeepStrictEqual } from 'node:util';
|
|
26
|
-
import { acquireBoundJobWrite
|
|
25
|
+
import { acquireBoundJobWrite } from './job-writer.ts';
|
|
27
26
|
import { jobHash } from './job-outbox.ts';
|
|
28
|
-
import { assertReviewActSource, decodeReviewAct, reviewActFindings, reviewActPublicationWarning, reviewActStill, reviewActTransport, reviewActVerbatim, reviewActVersionHash, type FetchedReviewAct } from './review-act.ts';
|
|
27
|
+
import { assertReviewActSource, decodeReviewAct, fetchReviewActRuntime, reviewActFindings, reviewActPublicationWarning, reviewActStill, reviewActTransport, reviewActVerbatim, reviewActVersionHash, type FetchedReviewAct } from './review-act.ts';
|
|
29
28
|
import { newRefusals } from './refusal-baseline.ts';
|
|
30
29
|
import { ingestedVerdictPairFinding } from './signoff-pair.ts';
|
|
31
30
|
import { dirname, join, resolve } from 'node:path';
|
|
@@ -569,13 +568,7 @@ export function recordReviewAct(root: string, requestedVersion: number, actId: s
|
|
|
569
568
|
root = resolve(root);
|
|
570
569
|
const release = acquireBoundJobWrite(root);
|
|
571
570
|
try {
|
|
572
|
-
const
|
|
573
|
-
stdin: Buffer.from(JSON.stringify(reviewActTransport(root, actId))), stdout: 'pipe', stderr: 'pipe',
|
|
574
|
-
});
|
|
575
|
-
let response: { ok: boolean; bytes: string; stillBytes?: string; code: string; message: string };
|
|
576
|
-
try { response = JSON.parse(child.stdout.toString()); }
|
|
577
|
-
catch (error) { if (error instanceof Refusal) throw error; return refuse('REVIEW_ACT_FETCH_REFUSED', 'project.json.review_acts: fetch adapter failed; restore the live Review job'); }
|
|
578
|
-
if (!response.ok || child.exitCode !== 0) refuse(response.code, response.message);
|
|
571
|
+
const response = fetchReviewActRuntime(reviewActTransport(root, actId));
|
|
579
572
|
const act = decodeReviewAct(response.bytes);
|
|
580
573
|
const selector = act.source.selector!;
|
|
581
574
|
if (!('version' in selector) || selector.version !== requestedVersion) refuse('REVIEW_ACT_KIND_MISMATCH', 'project.json.review_acts: act names a different version; invoke review for the displayed version');
|
package/src/fix-ledger.ts
CHANGED
|
@@ -148,7 +148,7 @@ const manifestOf = (draft: JsonObject): string | undefined => {
|
|
|
148
148
|
return typeof entry?.sha256 === 'string' ? entry.sha256 : undefined;
|
|
149
149
|
};
|
|
150
150
|
|
|
151
|
-
const hasPartsReceipt = (project: JsonObject, id: string): boolean => asArray(project.review_acts)
|
|
151
|
+
export const hasPartsReceipt = (project: JsonObject, id: string): boolean => asArray(project.review_acts)
|
|
152
152
|
.some(entry => isObject(entry) && entry.kind === 'parts-verdict' && entry.draft_id === id);
|
|
153
153
|
|
|
154
154
|
/**
|
package/src/job-acts.ts
CHANGED
|
@@ -75,6 +75,10 @@ export function pendingJobActs(project: JsonObject, acts: readonly ActV3[], root
|
|
|
75
75
|
subject = `question ${act.value.questionId}`;
|
|
76
76
|
args = ['interview-answer', act.value.questionId, root];
|
|
77
77
|
break;
|
|
78
|
+
case 'reopen':
|
|
79
|
+
subject = `stage ${act.value.stage}`;
|
|
80
|
+
args = ['reopen', act.value.stage, root];
|
|
81
|
+
break;
|
|
78
82
|
case 'signoff': {
|
|
79
83
|
subject = `stage ${act.value.stage}`;
|
|
80
84
|
args = ['signoff', act.value.stage, root];
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/** Retire only a replaced project's demonstrably stopped managed host. Never edit Review's store. */
|
|
2
|
+
import { Database, constants as sqlite } from 'bun:sqlite';
|
|
3
|
+
import { randomUUID } from 'node:crypto';
|
|
4
|
+
import { lstatSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, rmdirSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { connect } from 'node:net';
|
|
7
|
+
import { jobHash, jobHostStateRoot, pendingPublications, privateJson } from './job-outbox.ts';
|
|
8
|
+
import { Refusal, refuse } from './refusal.ts';
|
|
9
|
+
|
|
10
|
+
interface StoredRoot { path: string; dev: number; ino: number }
|
|
11
|
+
interface ActiveJob { jobId: string; rootKey: string; root: StoredRoot; fingerprint: string }
|
|
12
|
+
interface Host { jobId: string; fingerprint: string; pid: number; origin: string }
|
|
13
|
+
const UUID = /^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/;
|
|
14
|
+
|
|
15
|
+
export function replacedRootRefusal(root: string, recorded?: { pid: number; origin: string }): never {
|
|
16
|
+
refuse('JOB_ROOT_REPLACED', `project.json: the retained Review host belongs to a replaced project directory at ${root}; stop the original job open host in its terminal${recorded ? ` (recorded PID ${recorded.pid}, ${recorded.origin})` : ''}, then retry rig-create job open or job reconcile. Recovery requires its recorded PID to be absent, its recorded port to refuse connections, no startup claim and no pending publication; restore missing or unsafe host metadata before retrying`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function absent(path: string): boolean {
|
|
20
|
+
try { lstatSync(path); return false; }
|
|
21
|
+
catch (error) { if ((error as NodeJS.ErrnoException).code === 'ENOENT') return true; throw error; }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function owned(path: string, directory: boolean): void {
|
|
25
|
+
const info = lstatSync(path);
|
|
26
|
+
if (info.isSymbolicLink() || !(directory ? info.isDirectory() : info.isFile())
|
|
27
|
+
|| (info.mode & 0o077) || !directory && info.nlink !== 1
|
|
28
|
+
|| process.getuid && info.uid !== process.getuid() || realpathSync(path) !== path) throw Error();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function dead(pid: number): boolean {
|
|
32
|
+
try { process.kill(pid, 0); return false; }
|
|
33
|
+
catch (error) { return (error as NodeJS.ErrnoException).code === 'ESRCH'; }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** A timeout, reset or any other network error is uncertainty, never proof of a stopped listener. */
|
|
37
|
+
export function hostPortRefuses(port: number): Promise<boolean> {
|
|
38
|
+
return new Promise(resolve => {
|
|
39
|
+
const socket = connect({ host: '127.0.0.1', port });
|
|
40
|
+
const finish = (refused: boolean) => { socket.destroy(); resolve(refused); };
|
|
41
|
+
socket.setTimeout(500, () => finish(false));
|
|
42
|
+
socket.once('connect', () => finish(false));
|
|
43
|
+
socket.once('error', error => finish((error as NodeJS.ErrnoException).code === 'ECONNREFUSED'));
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Caller holds acquireJobLock(root) through inspection, rename and host startup. */
|
|
48
|
+
export async function recoverReplacedJobHostState(
|
|
49
|
+
root: string,
|
|
50
|
+
now?: number,
|
|
51
|
+
probe: (port: number) => Promise<boolean> = hostPortRefuses,
|
|
52
|
+
): Promise<string | undefined> {
|
|
53
|
+
const state = jobHostStateRoot(root), host = join(state, 'host'), file = join(host, 'jobs.sqlite');
|
|
54
|
+
if (absent(file)) return;
|
|
55
|
+
let claim: string | undefined, archived: string | undefined;
|
|
56
|
+
let claimIdentity: { dev: number; ino: number } | undefined;
|
|
57
|
+
let recorded: Host | undefined;
|
|
58
|
+
const nonce = randomUUID();
|
|
59
|
+
try {
|
|
60
|
+
// The only private store fields consumed are the active job's identity and root identity.
|
|
61
|
+
owned(state, true); owned(host, true); owned(file, false);
|
|
62
|
+
if (['-journal', '-wal', '-shm'].some(suffix => !absent(file + suffix))) throw Error();
|
|
63
|
+
const current = lstatSync(root);
|
|
64
|
+
const rootIdentity = { path: realpathSync(root), dev: current.dev, ino: current.ino };
|
|
65
|
+
const db = new Database(file, sqlite.SQLITE_OPEN_READONLY | sqlite.SQLITE_OPEN_NOFOLLOW);
|
|
66
|
+
let jobs: ActiveJob[];
|
|
67
|
+
try {
|
|
68
|
+
jobs = db.query<{ job_id: string; root_key: string; document: string }, []>(
|
|
69
|
+
'SELECT job_id, root_key, document FROM jobs WHERE active=1',
|
|
70
|
+
).all().map(row => {
|
|
71
|
+
const data = JSON.parse(row.document) as { root: StoredRoot; fingerprint: string };
|
|
72
|
+
return { jobId: row.job_id, rootKey: row.root_key, root: data.root, fingerprint: data.fingerprint };
|
|
73
|
+
});
|
|
74
|
+
} finally { db.close(); }
|
|
75
|
+
if (!jobs.length) return;
|
|
76
|
+
for (const job of jobs) {
|
|
77
|
+
if (!job.root || job.root.path !== rootIdentity.path || !Number.isSafeInteger(job.root.dev)
|
|
78
|
+
|| job.root.dev < 0 || !Number.isSafeInteger(job.root.ino) || job.root.ino < 0) throw Error();
|
|
79
|
+
}
|
|
80
|
+
if (jobs.every(job => job.root.dev === current.dev && job.root.ino === current.ino)) return;
|
|
81
|
+
// Renaming the whole managed directory must not strand a different active incarnation.
|
|
82
|
+
if (jobs.length !== 1 || pendingPublications(root).length) throw Error();
|
|
83
|
+
const job = jobs[0]!;
|
|
84
|
+
if (!UUID.test(job.jobId) || job.fingerprint !== 'rig-create/live-review/1'
|
|
85
|
+
|| job.rootKey !== jobHash(JSON.stringify([rootIdentity.path, job.fingerprint]))) throw Error();
|
|
86
|
+
const control = join(host, 'job-ui'); owned(control, true);
|
|
87
|
+
const claimNames = () => readdirSync(control).filter(name => name.endsWith('.claim') || name.endsWith('.claiming'));
|
|
88
|
+
if (claimNames().length) throw Error();
|
|
89
|
+
// Use Review's existing startup-claim protocol, so an overlapping listener cannot adopt the old job.
|
|
90
|
+
const candidate = join(control, `job-${job.jobId}.${nonce}.claiming`);
|
|
91
|
+
mkdirSync(candidate, { mode: 0o700 }); claim = candidate;
|
|
92
|
+
const installed = lstatSync(candidate); claimIdentity = { dev: installed.dev, ino: installed.ino };
|
|
93
|
+
writeFileSync(join(candidate, `owner.${nonce}.json`), JSON.stringify({ pid: process.pid, nonce }), { mode: 0o600, flag: 'wx' });
|
|
94
|
+
const target = join(control, `job-${job.jobId}.claim`);
|
|
95
|
+
if (!absent(target)) throw Error();
|
|
96
|
+
renameSync(candidate, target); claim = target;
|
|
97
|
+
const snapshot = (): { seal: string; hosts: Host[] } => {
|
|
98
|
+
owned(state, true); owned(host, true); owned(file, false); owned(control, true);
|
|
99
|
+
const currentRoot = lstatSync(root);
|
|
100
|
+
if (currentRoot.dev !== rootIdentity.dev || currentRoot.ino !== rootIdentity.ino || realpathSync(root) !== root) throw Error();
|
|
101
|
+
if (['-journal', '-wal', '-shm'].some(suffix => !absent(file + suffix))) throw Error();
|
|
102
|
+
const claims = claimNames();
|
|
103
|
+
if (claims.length !== 1 || join(control, claims[0]!) !== claim) throw Error();
|
|
104
|
+
const names = readdirSync(control).filter(name => name.endsWith('.json')).sort();
|
|
105
|
+
if (!names.includes(`${job.jobId}.json`)) throw Error();
|
|
106
|
+
const records = names.map(name => {
|
|
107
|
+
const path = join(control, name); owned(path, false);
|
|
108
|
+
const value = privateJson(path) as Host & { schema: string };
|
|
109
|
+
if (value.schema !== 'rig-review-job-host/1' || !UUID.test(value.jobId) || name !== `${value.jobId}.json`
|
|
110
|
+
|| value.fingerprint !== job.fingerprint || !Number.isSafeInteger(value.pid) || value.pid <= 0
|
|
111
|
+
|| !/^http:\/\/127\.0\.0\.1:([1-9][0-9]{0,4})$/.test(value.origin)
|
|
112
|
+
|| Number(new URL(value.origin).port || 80) > 65535) throw Error();
|
|
113
|
+
return { path, value };
|
|
114
|
+
});
|
|
115
|
+
owned(claim!, true); owned(join(claim!, `owner.${nonce}.json`), false);
|
|
116
|
+
const paths = [root, state, host, control, file, claim!, join(claim!, `owner.${nonce}.json`), ...records.map(record => record.path)];
|
|
117
|
+
const seal = jobHash(JSON.stringify(paths.map(path => {
|
|
118
|
+
const info = lstatSync(path);
|
|
119
|
+
return [path, info.dev, info.ino, info.isFile() ? jobHash(readFileSync(path)) : null];
|
|
120
|
+
})));
|
|
121
|
+
return { seal, hosts: records.map(record => record.value) };
|
|
122
|
+
};
|
|
123
|
+
const before = snapshot();
|
|
124
|
+
recorded = before.hosts.find(record => record.jobId === job.jobId);
|
|
125
|
+
for (const record of before.hosts) {
|
|
126
|
+
if (!dead(record.pid) || !await probe(Number(new URL(record.origin).port || 80))) throw Error();
|
|
127
|
+
}
|
|
128
|
+
// No await between final identity/claim/PID recheck and rename. Keep all original state bytes.
|
|
129
|
+
if (snapshot().seal !== before.seal || before.hosts.some(record => !dead(record.pid))) throw Error();
|
|
130
|
+
const destination = `${state}.replaced-${new Date(now ?? current.mtimeMs).toISOString().replace(/[:.]/g, '-')}-${nonce}`;
|
|
131
|
+
if (!absent(destination)) throw Error();
|
|
132
|
+
renameSync(state, destination); archived = destination;
|
|
133
|
+
return destination;
|
|
134
|
+
} catch (error) {
|
|
135
|
+
if (error instanceof Refusal && error.code !== 'JOB_ROOT_REPLACED') throw error;
|
|
136
|
+
replacedRootRefusal(root, recorded);
|
|
137
|
+
} finally {
|
|
138
|
+
if (claim) {
|
|
139
|
+
const actual = archived ? join(archived, 'host', 'job-ui', claim.slice(claim.lastIndexOf('/') + 1)) : claim;
|
|
140
|
+
// This marker was created here; never remove a pre-existing Review claim or state directory.
|
|
141
|
+
try {
|
|
142
|
+
const info = lstatSync(actual);
|
|
143
|
+
if (!claimIdentity || !info.isDirectory() || info.isSymbolicLink() || info.dev !== claimIdentity.dev || info.ino !== claimIdentity.ino) throw Error();
|
|
144
|
+
const owner = join(actual, `owner.${nonce}.json`);
|
|
145
|
+
if (!absent(owner)) {
|
|
146
|
+
if (readFileSync(owner, 'utf8') !== JSON.stringify({ pid: process.pid, nonce })) throw Error();
|
|
147
|
+
rmSync(owner);
|
|
148
|
+
}
|
|
149
|
+
// rmdir refuses a competing owner's nonempty replacement.
|
|
150
|
+
rmdirSync(actual);
|
|
151
|
+
} catch { replacedRootRefusal(root, recorded); }
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
package/src/job-host.ts
CHANGED
|
@@ -2,17 +2,19 @@ import { randomUUID } from 'node:crypto';
|
|
|
2
2
|
import { readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { isDeepStrictEqual } from 'node:util';
|
|
5
|
-
import { startJobHost, type JobHostAttachFailure, type JobHostOptions, type JobHostReuseBinding, type JobOwnerHost, type JobReviewerBinding, type JobSelector, type
|
|
5
|
+
import { startJobHost, type JobHostAttachFailure, type JobHostOptions, type JobHostReuseBinding, type JobOwnerHost, type JobReviewerBinding, type JobSelector, type JobEventV3, type ActV3 } from '@rig-c/review/job-host';
|
|
6
6
|
import { asArray, checkProject, collectItems, loadCollection, isObject, type Finding } from './check.ts';
|
|
7
7
|
import { baselineOf, newFindings } from './refusal-baseline.ts';
|
|
8
8
|
import { Refusal, refuse } from './refusal.ts';
|
|
9
9
|
import { liveManifestPath, draftPublicationContext, currentJobIdentity, partsEnumerator, prepareDraftManifest, prepareLiveManifest, publicationFile, publicationSelector, readPublished, readRecordPublished } from './job-publication.ts';
|
|
10
|
-
import { acknowledgePublication, acquireJobLock, assertJobIdentity, enqueuePublication, ensureJobPrivateIgnores, failPublication, JOB_BINDING_FILE, jobHash, jobHostStateRoot, pendingPublications, privateDirectory, publicationVersionHash, readAcknowledgedPublication, readWriterBinding, reconcilePublication, writePrivateJson, isRecordResult, type PublicationResult, type JobIdentity, type PendingPublication, type WriterBinding } from './job-outbox.ts';
|
|
10
|
+
import { acknowledgePublication, acquireJobLock, assertJobIdentity, enqueuePublication, ensureJobPrivateIgnores, failPublication, JOB_BINDING_FILE, jobHash, jobHostStateRoot, pendingPublications, privateDirectory, publicationVersionHash, readAcknowledgedPublication, readWriterBinding, reconcilePublication, writePrivateJson, isRecordResult, type PublicationResult, type JobIdentity, type PendingPublication, type WriterBinding, type PublicationSubject } from './job-outbox.ts';
|
|
11
11
|
import { draftPublicationResult } from './job-writer.ts';
|
|
12
12
|
import { attachCreateJobForClose } from './job-close.ts';
|
|
13
13
|
import { pendingJobActs, type PendingJobAct } from './job-acts.ts';
|
|
14
14
|
import { checkReviewPackages } from './review-package.ts';
|
|
15
|
+
import { reviewVerdictSignable } from './signable.ts';
|
|
15
16
|
import type { JsonObject } from './templates.ts';
|
|
17
|
+
import { recoverReplacedJobHostState, replacedRootRefusal } from './job-host-state.ts';
|
|
16
18
|
|
|
17
19
|
function installBinding(root: string, binding: WriterBinding): void {
|
|
18
20
|
ensureJobPrivateIgnores(root);
|
|
@@ -79,10 +81,23 @@ export async function openCreateJob(
|
|
|
79
81
|
if (existing) assertJobIdentity(existing.identity, identity);
|
|
80
82
|
privateDirectory(identity.stateDir);
|
|
81
83
|
let writerGrant: WriterGrant | undefined;
|
|
82
|
-
const
|
|
84
|
+
const start = () => startHost({
|
|
83
85
|
...options(identity, true, undefined, grant => { writerGrant = grant; }),
|
|
84
86
|
...(existing ? { port: Number(new URL(existing.origin).port) } : {}),
|
|
85
87
|
});
|
|
88
|
+
let host: JobOwnerHost;
|
|
89
|
+
try {
|
|
90
|
+
host = await start();
|
|
91
|
+
} catch (error) {
|
|
92
|
+
if (typeof error !== 'object' || error === null || (error as { code?: unknown }).code !== 'JOB_ROOT_REPLACED') throw error;
|
|
93
|
+
if (identity.stateDir !== join(jobHostStateRoot(root), 'host') || !await recoverReplacedJobHostState(root, now)) replacedRootRefusal(root);
|
|
94
|
+
privateDirectory(identity.stateDir);
|
|
95
|
+
try { host = await start(); }
|
|
96
|
+
catch (retryError) {
|
|
97
|
+
if (typeof retryError === 'object' && retryError !== null && (retryError as { code?: unknown }).code === 'JOB_ROOT_REPLACED') replacedRootRefusal(root);
|
|
98
|
+
throw retryError;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
86
101
|
const file = join(root, 'project.json');
|
|
87
102
|
const temporary = join(root, '.rig-create-job-record.tmp');
|
|
88
103
|
try {
|
|
@@ -174,7 +189,7 @@ export async function publishPending(
|
|
|
174
189
|
const currentHash = jobHash(bytes);
|
|
175
190
|
if (currentHash !== entry.recordHash) { entry.recordHash = currentHash; delete entry.generation; }
|
|
176
191
|
const project = JSON.parse(bytes.toString('utf8'));
|
|
177
|
-
let subjects: readonly
|
|
192
|
+
let subjects: readonly PublicationSubject[];
|
|
178
193
|
if (isRecordResult(entry.result)) {
|
|
179
194
|
subjects = readRecordPublished({ root: entry.root, record: { path: 'project.json', sha256: entry.recordHash }, result: entry.result, phase: 'inventory' }).subjects;
|
|
180
195
|
} else {
|
|
@@ -216,7 +231,7 @@ export async function publishPending(
|
|
|
216
231
|
}
|
|
217
232
|
|
|
218
233
|
/** One declared subject after the ask step: asked now, asked before on this publication, or refused by Review. */
|
|
219
|
-
export type AskOutcome = { readonly subject:
|
|
234
|
+
export type AskOutcome = { readonly subject: PublicationSubject; readonly status: 'asked' | 'already' } | { readonly subject: PublicationSubject; readonly status: 'refused'; readonly code: string };
|
|
220
235
|
|
|
221
236
|
type AgentReply = { ok?: boolean; error?: { code?: string }; value?: { events?: unknown; status?: unknown; cursor?: unknown } };
|
|
222
237
|
|
|
@@ -251,10 +266,10 @@ async function* jobEvents(host: JobOwnerHost, strict = false): AsyncGenerator<Jo
|
|
|
251
266
|
}
|
|
252
267
|
|
|
253
268
|
/** The subjects already asked on this publication, from the same event reader as job acts. */
|
|
254
|
-
async function askedSubjects(host: JobOwnerHost, publicationId: string): Promise<
|
|
255
|
-
const asked:
|
|
269
|
+
async function askedSubjects(host: JobOwnerHost, publicationId: string): Promise<PublicationSubject[]> {
|
|
270
|
+
const asked: PublicationSubject[] = [];
|
|
256
271
|
for await (const event of jobEvents(host)) {
|
|
257
|
-
if (event.type === 'pending' && event.ask.publicationId === publicationId) asked.push(event.ask.subject as
|
|
272
|
+
if (event.type === 'pending' && event.ask.publicationId === publicationId) asked.push(event.ask.subject as PublicationSubject);
|
|
258
273
|
}
|
|
259
274
|
return asked;
|
|
260
275
|
}
|
|
@@ -282,7 +297,7 @@ export async function listCreateJobActs(
|
|
|
282
297
|
* publication, pending or answered, is not asked again, so a re-open never shows a second
|
|
283
298
|
* control. Asks stay limited to the declared list (`REVIEW_ACT_SUBJECT_UNDECLARED`).
|
|
284
299
|
*/
|
|
285
|
-
export async function askDeclaredSubjects(host: JobOwnerHost, publicationId: string, subjects: readonly
|
|
300
|
+
export async function askDeclaredSubjects(host: JobOwnerHost, publicationId: string, subjects: readonly PublicationSubject[]): Promise<AskOutcome[]> {
|
|
286
301
|
const before = await askedSubjects(host, publicationId);
|
|
287
302
|
const outcomes: AskOutcome[] = [];
|
|
288
303
|
for (const subject of subjects) {
|
|
@@ -298,7 +313,7 @@ export async function askDeclaredSubjects(host: JobOwnerHost, publicationId: str
|
|
|
298
313
|
return outcomes;
|
|
299
314
|
}
|
|
300
315
|
|
|
301
|
-
export function subjectLabel(subject:
|
|
316
|
+
export function subjectLabel(subject: PublicationSubject): string {
|
|
302
317
|
switch (subject.kind) {
|
|
303
318
|
case 'parts-verdict': return `parts-verdict ${subject.draftId}`;
|
|
304
319
|
case 'checkpoint': return `checkpoint ${subject.checkpointId}`;
|
|
@@ -325,11 +340,16 @@ export function refuseAskOutcomes(outcomes: readonly AskOutcome[]): void {
|
|
|
325
340
|
refuse('JOB_ASK_REFUSED', `project.json: the publication is acknowledged but review refused the ask for ${named}; restore the published record bytes and run rig-create job open to ask again`);
|
|
326
341
|
}
|
|
327
342
|
|
|
328
|
-
export async function reconcileCreateJob(root: string, publish: (entry: PendingPublication) => Promise<unknown> = publishPending): Promise<number> {
|
|
343
|
+
export async function reconcileCreateJob(root: string, publish: (entry: PendingPublication) => Promise<unknown> = publishPending, now?: number): Promise<number> {
|
|
344
|
+
root = realpathSync(root);
|
|
329
345
|
const release = acquireJobLock(root)!;
|
|
330
346
|
let outcomes: AskOutcome[];
|
|
331
347
|
let count: number;
|
|
332
|
-
try {
|
|
348
|
+
try {
|
|
349
|
+
const binding = readWriterBinding(root);
|
|
350
|
+
if (!binding || binding.identity.stateDir === join(jobHostStateRoot(root), 'host')) await recoverReplacedJobHostState(root, now);
|
|
351
|
+
({ count, outcomes } = await reconcileLocked(root, publish));
|
|
352
|
+
}
|
|
333
353
|
finally { release(); }
|
|
334
354
|
refuseAskOutcomes(outcomes);
|
|
335
355
|
return count;
|
|
@@ -482,13 +502,16 @@ export async function openDraftPublication(root: string, host: JobOwnerHost, now
|
|
|
482
502
|
? headSelector
|
|
483
503
|
: undefined);
|
|
484
504
|
const warnings: Finding[] = [];
|
|
505
|
+
const project = JSON.parse(bytes.toString('utf8')) as JsonObject;
|
|
485
506
|
const draftContext = targetSelector?.kind === 'draft'
|
|
486
|
-
? draftPublicationContext(root,
|
|
507
|
+
? draftPublicationContext(root, project, targetSelector.id, warnings)
|
|
487
508
|
: undefined;
|
|
488
509
|
// Re-publish an older post head that still declares a sign-off or checkpoint:
|
|
489
510
|
// either pending ask would prevent the legacy direction panel from rendering.
|
|
490
511
|
const currentSubjects = draftContext?.subjects ?? (targetSelector?.kind === 'post'
|
|
491
|
-
?
|
|
512
|
+
? (reviewVerdictSignable(project, targetSelector.version, 'direction-review')
|
|
513
|
+
? [{ kind: 'review-verdict' as const, stage: 'direction-review' as const }]
|
|
514
|
+
: [])
|
|
492
515
|
: undefined);
|
|
493
516
|
const reuseHead = Boolean(head && headSelector && source?.projectHash === jobHash(bytes) && (
|
|
494
517
|
targetSelector === undefined || isDeepStrictEqual(headSelector, targetSelector)
|
package/src/job-outbox.ts
CHANGED
|
@@ -4,7 +4,9 @@ import { existsSync, JOB_PRIVATE_DIRECTORY, lstatSync, readFileSync, readdirSync
|
|
|
4
4
|
import { basename, dirname, join, resolve } from 'node:path';
|
|
5
5
|
import { tmpdir } from 'node:os';
|
|
6
6
|
import { isDeepStrictEqual } from 'node:util';
|
|
7
|
-
import type { JobPublishRequest, JobReviewerBinding, JobSubject, RecordResult } from '@rig-c/review/job-host';
|
|
7
|
+
import type { JobPublishRequest, JobReviewerBinding, JobSubject, RecordSubject, RecordResult } from '@rig-c/review/job-host';
|
|
8
|
+
|
|
9
|
+
export type PublicationSubject = JobSubject | RecordSubject;
|
|
8
10
|
import { refuse } from './refusal.ts';
|
|
9
11
|
|
|
10
12
|
export const JOB_BINDING_FILE = '.rig-create-review-binding.json';
|
|
@@ -342,7 +344,7 @@ export interface AcknowledgedPublication {
|
|
|
342
344
|
result: PendingPublication['result'];
|
|
343
345
|
versionHash: string;
|
|
344
346
|
/** The subjects the published context declared. Receipts written before they were retained omit it. */
|
|
345
|
-
subjects?: readonly
|
|
347
|
+
subjects?: readonly PublicationSubject[];
|
|
346
348
|
}
|
|
347
349
|
|
|
348
350
|
function acknowledgedPath(root: string, jobId: string, publicationId: string): string {
|
|
@@ -350,7 +352,7 @@ function acknowledgedPath(root: string, jobId: string, publicationId: string): s
|
|
|
350
352
|
}
|
|
351
353
|
|
|
352
354
|
/** Persist the version identity before the pending publication is removed. */
|
|
353
|
-
export function acknowledgePublication(entry: PendingPublication, publicationId: string, generation: number, requestId: string, subjects?: readonly
|
|
355
|
+
export function acknowledgePublication(entry: PendingPublication, publicationId: string, generation: number, requestId: string, subjects?: readonly PublicationSubject[]): void {
|
|
354
356
|
if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(publicationId) || !Number.isSafeInteger(generation) || generation < 0 || !entry.versionHash) {
|
|
355
357
|
refuse('JOB_OUTBOX_INVALID', 'project.json: publication acknowledgment lacks its identity; reconcile the original pending publication');
|
|
356
358
|
}
|
package/src/job-publication.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { checkInputs } from './inputs.ts';
|
|
2
2
|
import { pngDimensions } from './scene.ts';
|
|
3
|
-
import {
|
|
3
|
+
import { hasPartsReceipt } from './fix-ledger.ts';
|
|
4
4
|
import { renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
5
5
|
import { existsSync, lstatSync, readFileSync, realpathSync } from './check-reads.ts';
|
|
6
6
|
import { dirname, join, relative, resolve } from 'node:path';
|
|
7
7
|
import { isDeepStrictEqual } from 'node:util';
|
|
8
8
|
import { partsFileReferences } from '@rig-c/parts/src/parts.ts';
|
|
9
9
|
import partsPackage from '@rig-c/parts/package.json';
|
|
10
|
-
import { JOB_ACT_SCHEMA, JOB_API_SCHEMA, type JobPublicationReader, type JobPublishedContext, type JobSelector, type JobRecordSignoffStage } from '@rig-c/review/job-host';
|
|
10
|
+
import { JOB_ACT_SCHEMA, JOB_API_SCHEMA, type JobPublicationReader, type JobPublishedContext, type JobSelector, type JobRecordSignoffStage, type RecordPlanSubject } from '@rig-c/review/job-host';
|
|
11
11
|
import { stepHash } from './step-hash.ts';
|
|
12
12
|
import { checkpointEvidenceContext, type CheckpointEvidence } from './checkpoint-evidence.ts';
|
|
13
13
|
import { locateParts, PARTS_PACKAGE } from './parts-sections.ts';
|
|
@@ -24,10 +24,10 @@ import {
|
|
|
24
24
|
import { optionContextFiles, optionFile, validateContext } from './choices.ts';
|
|
25
25
|
import { hasStageOrder, interviewStageOfGuide, stageOfStep, stepCoveredByApproval } from './stages.ts';
|
|
26
26
|
import { selectAnswerHashes } from './signoff-answers.ts';
|
|
27
|
-
import { assertInterviewRecordSignable, packageSignSubjects, stageSignable } from './signable.ts';
|
|
28
|
-
import { collectReopens, liveSignoff } from './reopen.ts';
|
|
27
|
+
import { assertInterviewRecordSignable, checkpointSignable, packageSignSubjects, reviewVerdictSignable, stageSignable } from './signable.ts';
|
|
28
|
+
import { collectReopens, directionReviewClosed, liveSignoff } from './reopen.ts';
|
|
29
29
|
import { acceptedReviewVerdict } from './review.ts';
|
|
30
|
-
import { requireRecordDirectionTarget } from './record-direction-target.ts';
|
|
30
|
+
import { recordDirectionTarget, requireRecordDirectionTarget } from './record-direction-target.ts';
|
|
31
31
|
import { latestPartsApproval, riggingContext } from './structure.ts';
|
|
32
32
|
import { jobHash, pendingPublications, isRecordResult, type JobIdentity } from './job-outbox.ts';
|
|
33
33
|
import { Refusal, refuse } from './refusal.ts';
|
|
@@ -57,8 +57,6 @@ type RecordContextBase = {
|
|
|
57
57
|
readonly files: JobPublishedContext['files'];
|
|
58
58
|
};
|
|
59
59
|
type RecordSignoffStage = JobRecordSignoffStage;
|
|
60
|
-
type RecordPlanSubject = { readonly kind: 'checkpoint'; readonly checkpointId: string }
|
|
61
|
-
| { readonly kind: 'signoff'; readonly stage: RecordSignoffStage };
|
|
62
60
|
export type RecordOptionContext = RecordContextBase & {
|
|
63
61
|
readonly plan: null;
|
|
64
62
|
readonly subjects: readonly [{ readonly kind: 'interview-picks'; readonly questionId: string; readonly setId: string }];
|
|
@@ -285,7 +283,9 @@ export function readRecordPublished({ root, record, result, phase, parts: sealed
|
|
|
285
283
|
label = `option-set ${result.questionId} / ${result.setId}`;
|
|
286
284
|
} else if (result.kind === 'plan') {
|
|
287
285
|
if (!plan) throw Error('the requested plan is absent');
|
|
288
|
-
|
|
286
|
+
const reopenDirection = stage === 'direction-review' && directionReviewClosed(project)
|
|
287
|
+
&& recordDirectionTarget(project, now) === null;
|
|
288
|
+
if (stage === 'direction-review' && !reopenDirection) {
|
|
289
289
|
const reopens = collectReopens(project, []);
|
|
290
290
|
const post = asArray(project.versions).filter(isObject).filter(version => version.kind === 'post'
|
|
291
291
|
&& liveSignoff(reopens, 'post', Date.parse(String(version.at)))).at(-1);
|
|
@@ -297,7 +297,7 @@ export function readRecordPublished({ root, record, result, phase, parts: sealed
|
|
|
297
297
|
requireRecordDirectionTarget(project, now);
|
|
298
298
|
}
|
|
299
299
|
const covered = steps.filter(step => stepCoveredByApproval(project, step, stage));
|
|
300
|
-
const signable = stage !== null && ['interview', 'plan-approved', 'rigging-interview', 'post-interview', 'direction-review'].includes(stage)
|
|
300
|
+
const signable = !reopenDirection && stage !== null && ['interview', 'plan-approved', 'rigging-interview', 'post-interview', 'direction-review'].includes(stage)
|
|
301
301
|
&& (stage !== 'interview' || interviewSignoff) && stageSignable(project, stage);
|
|
302
302
|
if (signable && stage === 'direction-review' && steps.length === 0) throw Error('direction-review record sign-off needs displayed plan steps');
|
|
303
303
|
const emptyPost = stage === 'post-interview' && !steps.some(step => step.phase === 'post') && postNotPassed({ items });
|
|
@@ -311,9 +311,10 @@ export function readRecordPublished({ root, record, result, phase, parts: sealed
|
|
|
311
311
|
}
|
|
312
312
|
subjects = steps.filter(step => {
|
|
313
313
|
if (step.status !== 'at-checkpoint' || (step.phase !== 'rig' && step.phase !== 'post') || stageOfStep(step.phase, String(step.id)) !== stage) return false;
|
|
314
|
-
return
|
|
314
|
+
return checkpointSignable(project, stage, String(step.id), now);
|
|
315
315
|
}).map(step => ({ kind: 'checkpoint' as const, checkpointId: String(step.id) }));
|
|
316
316
|
if (signable) subjects = [...subjects, { kind: 'signoff', stage: stage as RecordSignoffStage }];
|
|
317
|
+
if (reopenDirection) subjects = [{ kind: 'reopen', stage: 'direction-review' }];
|
|
317
318
|
label = `plan / ${stage}`;
|
|
318
319
|
} else throw Error('unknown record result');
|
|
319
320
|
// Detect record changes during closure reads as well as changes before entry.
|
|
@@ -513,9 +514,12 @@ export const readPublished: JobPublicationReader = async ({ root, record, result
|
|
|
513
514
|
}
|
|
514
515
|
const plan = project.plan as JsonObject | undefined;
|
|
515
516
|
const steps = Array.isArray(plan?.steps) ? plan.steps as JsonObject[] : [];
|
|
516
|
-
const
|
|
517
|
+
const reviewStage = selector.kind === 'post' ? 'direction-review' as const : 'rig-review' as const;
|
|
518
|
+
const subjects: JobPublishedContext['subjects'] = [
|
|
519
|
+
...(reviewVerdictSignable(project, selector.version, reviewStage) ? [{ kind: 'review-verdict' as const, stage: reviewStage }] : []),
|
|
517
520
|
// The legacy direction panel accepts only the verdict on a post publication.
|
|
518
|
-
...(selector.kind === 'post' ? [] : packageSignSubjects(project, effectiveStage(root, project), selector, steps.length))
|
|
521
|
+
...(selector.kind === 'post' ? [] : packageSignSubjects(project, effectiveStage(root, project), selector, steps.length)),
|
|
522
|
+
];
|
|
519
523
|
return {
|
|
520
524
|
selector, plan: { steps: steps.map(step => ({ id: String(step.id), hash: stepHash(step) })) },
|
|
521
525
|
parts: { enumeratorVersion: partsEnumerator.version, manifest: { path: manifestPath, sha256: jobHash(manifest) }, images },
|
|
@@ -576,7 +580,7 @@ export function draftPublishedContext(root: string, project: JsonObject, id: str
|
|
|
576
580
|
const plan = project.plan as JsonObject | undefined;
|
|
577
581
|
return { selector: { kind: 'draft', id }, plan: plan ? { steps: (plan.steps as JsonObject[] ?? []).map(step => ({ id: String(step.id), hash: stepHash(step) })) } : null,
|
|
578
582
|
parts: { enumeratorVersion: partsEnumerator.version, manifest: { path: manifestPath, sha256: jobHash(manifest) }, images },
|
|
579
|
-
subjects: [{ kind: 'parts-verdict', draftId: id }],
|
|
583
|
+
subjects: hasPartsReceipt(project, id) ? [] : [{ kind: 'parts-verdict', draftId: id }],
|
|
580
584
|
partIds: (JSON.parse(manifest.toString('utf8')).parts as { name: string }[]).map(part => part.name), files };
|
|
581
585
|
}
|
|
582
586
|
|
package/src/job-runtime.ts
CHANGED
|
@@ -5,6 +5,16 @@ import { askOutcomeLines, assertRequestedDraft, assertRequestedRig, closeCreateJ
|
|
|
5
5
|
import { failPublication, pendingPublications, reconcilePublication } from './job-outbox.ts';
|
|
6
6
|
import { jobActsText } from './job-acts.ts';
|
|
7
7
|
import { Refusal, refuse } from './refusal.ts';
|
|
8
|
+
import { replacedRootRefusal } from './job-host-state.ts';
|
|
9
|
+
|
|
10
|
+
/** Preserve this known producer refusal without printing an uncontrolled producer message. */
|
|
11
|
+
export function publicationFailure(error: unknown, root: string): Refusal | undefined {
|
|
12
|
+
if (error instanceof Refusal) return error;
|
|
13
|
+
if (typeof error === 'object' && error !== null && (error as { code?: unknown }).code === 'JOB_ROOT_REPLACED') {
|
|
14
|
+
try { replacedRootRefusal(root); } catch (failure) { return failure as Refusal; }
|
|
15
|
+
}
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
8
18
|
|
|
9
19
|
async function run(): Promise<void> {
|
|
10
20
|
const input = JSON.parse(readFileSync(0, 'utf8')) as { root: string; id?: string; reviewer?: string; role?: 'owner' | 'delegate'; draft?: string; rig?: string; question?: string; plan?: boolean; now: number; json?: boolean };
|
|
@@ -16,7 +26,8 @@ async function run(): Promise<void> {
|
|
|
16
26
|
let outcomes: AskOutcome[] = [];
|
|
17
27
|
try { await reconcilePublication(root, entry, async item => { outcomes = await publishPending(item); }); }
|
|
18
28
|
catch (error) {
|
|
19
|
-
const
|
|
29
|
+
const named = publicationFailure(error, root);
|
|
30
|
+
const failure = named ? { code: named.code, message: named.message }
|
|
20
31
|
: { code: 'JOB_PUBLISH_PENDING', message: 'project.json: host publication failed; restore the bound host before rig-create job reconcile' };
|
|
21
32
|
failPublication(root, entry, failure);
|
|
22
33
|
throw new Refusal('JOB_PUBLISH_PENDING', 'project.json: committed publication is pending; run rig-create job reconcile');
|
|
@@ -31,7 +42,7 @@ async function run(): Promise<void> {
|
|
|
31
42
|
console.log(input.json ? JSON.stringify(result) : jobActsText(result));
|
|
32
43
|
break;
|
|
33
44
|
}
|
|
34
|
-
case 'reconcile': console.log(`job: reconciled ${await reconcileCreateJob(root)} publication(s)`); break;
|
|
45
|
+
case 'reconcile': console.log(`job: reconciled ${await reconcileCreateJob(root, undefined, input.now)} publication(s)`); break;
|
|
35
46
|
case 'close': await closeCreateJob(root); console.log('job: closed'); break;
|
|
36
47
|
case 'open': {
|
|
37
48
|
if (!input.reviewer || !input.role) refuse('JOB_BINDING_INVALID', 'project.json: job open needs --reviewer and --role owner|delegate');
|
|
@@ -64,7 +75,8 @@ async function run(): Promise<void> {
|
|
|
64
75
|
host.stop();
|
|
65
76
|
throw error;
|
|
66
77
|
}
|
|
67
|
-
|
|
78
|
+
const named = publicationFailure(error, root);
|
|
79
|
+
console.error(named ? `${named.code}: ${named.message}` : 'JOB_PUBLISH_PENDING: project.json: draft publication failed; run rig-create job reconcile');
|
|
68
80
|
process.exitCode = 1;
|
|
69
81
|
}
|
|
70
82
|
if (host.reused || stopping) {
|
|
@@ -93,7 +105,8 @@ if (import.meta.main) {
|
|
|
93
105
|
try { await run(); }
|
|
94
106
|
catch (error) {
|
|
95
107
|
// Unexpected errors may embed producer input. Only controlled refusals leave this process.
|
|
96
|
-
|
|
108
|
+
const named = publicationFailure(error, 'the requested project directory');
|
|
109
|
+
console.error(named ? `${named.code}: ${named.message}` : 'JOB_PUBLISH_PENDING: project.json: publication operation failed; run rig-create job reconcile');
|
|
97
110
|
process.exitCode = 1;
|
|
98
111
|
}
|
|
99
112
|
}
|