@rig-c/create 0.0.0-stage → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +169 -2
- package/docs/CHECKS.md +1682 -0
- package/docs/COLLECTIONS.md +337 -0
- package/docs/CRAFT.md +277 -0
- package/docs/INTERVIEW.md +886 -0
- package/docs/LESSONS.md +172 -0
- package/docs/PROJECT.md +2657 -0
- package/docs/SOURCE.md +225 -0
- package/package.json +44 -4
- package/src/agent-bounce.ts +27 -0
- package/src/agent-guide.ts +237 -0
- package/src/amend.ts +193 -0
- package/src/applied-review.ts +104 -0
- package/src/ask-coverage.ts +69 -0
- package/src/assemble-answers.ts +53 -0
- package/src/cg-gates.ts +211 -0
- package/src/check-reads.ts +106 -0
- package/src/check.ts +1059 -0
- package/src/checkpoint-evidence-writer.ts +125 -0
- package/src/checkpoint-evidence.ts +152 -0
- package/src/choice-writers.ts +271 -0
- package/src/choices.ts +378 -0
- package/src/cli.ts +371 -0
- package/src/collection-answer.ts +136 -0
- package/src/collection-binding-reader.ts +496 -0
- package/src/collection-binding.ts +478 -0
- package/src/collection.ts +348 -0
- package/src/config-inputs.ts +155 -0
- package/src/config-lost.ts +135 -0
- package/src/correction-writers.ts +207 -0
- package/src/corrections.ts +685 -0
- package/src/diff-classes.ts +219 -0
- package/src/diff-map.ts +248 -0
- package/src/direction-citation.ts +13 -0
- package/src/direction-writers.ts +119 -0
- package/src/direction.ts +266 -0
- package/src/drafts.ts +363 -0
- package/src/feedback.ts +744 -0
- package/src/figure-mask.ts +143 -0
- package/src/fix-ledger.ts +355 -0
- package/src/init.ts +265 -0
- package/src/inputs.ts +160 -0
- package/src/intake.ts +158 -0
- package/src/interview.ts +53 -0
- package/src/invariants.ts +132 -0
- package/src/job-acts.ts +80 -0
- package/src/job-advance.ts +65 -0
- package/src/job-close.ts +226 -0
- package/src/job-host.ts +529 -0
- package/src/job-outbox.ts +383 -0
- package/src/job-publication.ts +701 -0
- package/src/job-runtime.ts +99 -0
- package/src/job-writer.ts +123 -0
- package/src/meshes-bust.ts +63 -0
- package/src/next.ts +1506 -0
- package/src/overrides.ts +42 -0
- package/src/package-upgrades.ts +32 -0
- package/src/packages-upgrade-check.ts +6 -0
- package/src/packages-upgrade.ts +168 -0
- package/src/parts-act.ts +96 -0
- package/src/parts-check.ts +242 -0
- package/src/parts-review.ts +196 -0
- package/src/parts-sections.ts +98 -0
- package/src/parts-verdict-record.ts +265 -0
- package/src/parts-verdict.ts +33 -0
- package/src/pause.ts +118 -0
- package/src/pins-check.ts +619 -0
- package/src/pins.ts +17 -0
- package/src/plan-bar-amendments.ts +54 -0
- package/src/plan-history.ts +147 -0
- package/src/plan-writers.ts +202 -0
- package/src/plate-receipt.ts +110 -0
- package/src/pre-interview.ts +302 -0
- package/src/prepared-inputs.ts +113 -0
- package/src/progress-writers.ts +181 -0
- package/src/provenance.ts +301 -0
- package/src/record-direction-target.ts +26 -0
- package/src/record-input.ts +18 -0
- package/src/refusal-baseline.ts +55 -0
- package/src/refusal.ts +30 -0
- package/src/reopen-lapses.ts +80 -0
- package/src/reopen.ts +144 -0
- package/src/republish.ts +93 -0
- package/src/restart.ts +141 -0
- package/src/review-act-runtime.ts +16 -0
- package/src/review-act.ts +592 -0
- package/src/review-package.ts +524 -0
- package/src/review-read.ts +238 -0
- package/src/review.ts +432 -0
- package/src/rig-version-date.ts +22 -0
- package/src/rig-version.ts +1047 -0
- package/src/run-record.ts +232 -0
- package/src/scene-authority.ts +410 -0
- package/src/scene-writers.ts +144 -0
- package/src/scene.ts +284 -0
- package/src/setup-painting.ts +46 -0
- package/src/signable.ts +65 -0
- package/src/signoff-answers.ts +76 -0
- package/src/signoff-checkpoint-act.ts +95 -0
- package/src/signoff-target.ts +127 -0
- package/src/signoff.ts +331 -0
- package/src/split-captions.ts +154 -0
- package/src/stage-progress.ts +379 -0
- package/src/stages.ts +148 -0
- package/src/step-hash.ts +19 -0
- package/src/structure-snapshot.ts +109 -0
- package/src/structure.ts +166 -0
- package/src/templates.ts +16 -0
- package/src/waypoints.ts +163 -0
- package/templates/agent-guide.md +108 -0
- package/templates/collection-agent-guide.md +72 -0
- package/templates/collection.json +252 -0
- package/templates/example-chain/AGENTS.md +134 -0
- package/templates/example-chain/CLAUDE.md +3 -0
- package/templates/example-chain/README.md +13 -0
- package/templates/example-chain/chain.json +2869 -0
- package/templates/example-chain/checkpoints/0a-interview-options/AGENTS.md +134 -0
- package/templates/example-chain/checkpoints/0a-interview-options/CLAUDE.md +3 -0
- package/templates/example-chain/checkpoints/0a-interview-options/evidence/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/0a-interview-options/evidence/approval.txt +1 -0
- package/templates/example-chain/checkpoints/0a-interview-options/evidence/interview/rig_type.json +59 -0
- package/templates/example-chain/checkpoints/0a-interview-options/evidence/split-config.json +1 -0
- package/templates/example-chain/checkpoints/0a-interview-options/inputs/painting.png +0 -0
- package/templates/example-chain/checkpoints/0a-interview-options/inputs/references/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/0a-interview-options/package.json +9 -0
- package/templates/example-chain/checkpoints/0a-interview-options/project.json +295 -0
- package/templates/example-chain/checkpoints/0a-interview-options.json +127 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/AGENTS.md +134 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/CLAUDE.md +3 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/evidence/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/evidence/approval.txt +1 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/evidence/interview/assemble.json +309 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/evidence/interview/reference.json +59 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/evidence/interview/rig_type.json +59 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/evidence/interview/seethrough.json +186 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/evidence/split-config.json +1 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/inputs/painting.png +0 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/inputs/references/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/package.json +9 -0
- package/templates/example-chain/checkpoints/0b-plan-pending/project.json +685 -0
- package/templates/example-chain/checkpoints/0b-plan-pending.json +81 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/AGENTS.md +134 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/CLAUDE.md +3 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/evidence/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/evidence/approval.txt +1 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/evidence/interview/assemble.json +309 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/evidence/interview/reference.json +59 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/evidence/interview/rig_type.json +59 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/evidence/interview/seethrough.json +186 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/evidence/parts-check.json +127 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/evidence/split-config.json +1 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/inputs/painting.png +0 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/inputs/references/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/package.json +9 -0
- package/templates/example-chain/checkpoints/1-parts-verdict/project.json +955 -0
- package/templates/example-chain/checkpoints/1-parts-verdict.json +204 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/AGENTS.md +134 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/CLAUDE.md +3 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/approval.txt +1 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/diff-components.json +34 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/interview/assemble.json +309 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/interview/bones.json +190 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/interview/reference.json +59 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/interview/rig_type.json +59 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/interview/seethrough.json +186 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/parts-check.json +127 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/parts-review.json +88 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/review-reads/a12dea02d32508acc99386f894af76a14f1c85f45f804db2aa6b4dea5297973f.json +59 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/split-config.json +1 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/evidence/structure.json +30 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/inputs/painting.png +0 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/inputs/references/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/package.json +9 -0
- package/templates/example-chain/checkpoints/2-rigging-answers/project.json +1198 -0
- package/templates/example-chain/checkpoints/2-rigging-answers.json +254 -0
- package/templates/example-chain/checkpoints/3-rig-review/AGENTS.md +134 -0
- package/templates/example-chain/checkpoints/3-rig-review/CLAUDE.md +3 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/approval.txt +1 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/diff-components.json +34 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/assemble.json +309 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/bones.json +190 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/constraints.json +272 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/meshes.json +190 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/motion.json +272 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/reference.json +59 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/rig_type.json +59 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/interview/seethrough.json +186 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/parts-check.json +127 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/parts-review.json +88 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/review-reads/a12dea02d32508acc99386f894af76a14f1c85f45f804db2aa6b4dea5297973f.json +59 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/setup.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/split-config.json +1 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/structure.json +30 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/v1/config.json +88 -0
- package/templates/example-chain/checkpoints/3-rig-review/evidence/v1/interview-requirements.json +8 -0
- package/templates/example-chain/checkpoints/3-rig-review/inputs/painting.png +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/inputs/references/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/3-rig-review/package.json +9 -0
- package/templates/example-chain/checkpoints/3-rig-review/project.json +1909 -0
- package/templates/example-chain/checkpoints/3-rig-review.json +424 -0
- package/templates/example-chain/checkpoints/4-direction-post/AGENTS.md +134 -0
- package/templates/example-chain/checkpoints/4-direction-post/CLAUDE.md +3 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/approval.txt +1 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/diff-components.json +34 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/assemble.json +309 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/bones.json +190 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/camera_depth.json +102 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/constraints.json +272 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/meshes.json +190 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/motion.json +272 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/post_composition.json +122 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/post_timing.json +102 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/reference.json +59 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/rig_type.json +59 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/interview/seethrough.json +186 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/parts-check.json +127 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/parts-review.json +88 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/review-reads/a12dea02d32508acc99386f894af76a14f1c85f45f804db2aa6b4dea5297973f.json +59 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/setup.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/split-config.json +1 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/structure.json +30 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/v1/config.json +88 -0
- package/templates/example-chain/checkpoints/4-direction-post/evidence/v1/interview-requirements.json +8 -0
- package/templates/example-chain/checkpoints/4-direction-post/inputs/painting.png +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/inputs/references/.gitkeep +0 -0
- package/templates/example-chain/checkpoints/4-direction-post/package.json +9 -0
- package/templates/example-chain/checkpoints/4-direction-post/project.json +2302 -0
- package/templates/example-chain/checkpoints/4-direction-post.json +456 -0
- package/templates/example-chain/evidence/.gitkeep +0 -0
- package/templates/example-chain/evidence/approval.txt +1 -0
- package/templates/example-chain/evidence/captions.json +101 -0
- package/templates/example-chain/evidence/diff-components.json +34 -0
- package/templates/example-chain/evidence/direction/v2.json +74 -0
- package/templates/example-chain/evidence/direction-input.json +74 -0
- package/templates/example-chain/evidence/interview/assemble.json +309 -0
- package/templates/example-chain/evidence/interview/bones.json +190 -0
- package/templates/example-chain/evidence/interview/camera_depth.json +102 -0
- package/templates/example-chain/evidence/interview/constraints.json +272 -0
- package/templates/example-chain/evidence/interview/meshes.json +190 -0
- package/templates/example-chain/evidence/interview/motion.json +272 -0
- package/templates/example-chain/evidence/interview/post_composition.json +122 -0
- package/templates/example-chain/evidence/interview/post_timing.json +102 -0
- package/templates/example-chain/evidence/interview/reference.json +59 -0
- package/templates/example-chain/evidence/interview/rig_type.json +59 -0
- package/templates/example-chain/evidence/interview/seethrough.json +186 -0
- package/templates/example-chain/evidence/parts-check.json +127 -0
- package/templates/example-chain/evidence/parts-review.json +88 -0
- package/templates/example-chain/evidence/review-reads/a12dea02d32508acc99386f894af76a14f1c85f45f804db2aa6b4dea5297973f.json +59 -0
- package/templates/example-chain/evidence/scene/s1.json +65 -0
- package/templates/example-chain/evidence/scene-citations.json +9 -0
- package/templates/example-chain/evidence/setup.png +0 -0
- package/templates/example-chain/evidence/split-config.json +1 -0
- package/templates/example-chain/evidence/structure.json +30 -0
- package/templates/example-chain/evidence/v1/config.json +88 -0
- package/templates/example-chain/evidence/v1/interview-requirements.json +8 -0
- package/templates/example-chain/inputs/background.png +0 -0
- package/templates/example-chain/inputs/painting.png +0 -0
- package/templates/example-chain/inputs/references/.gitkeep +0 -0
- package/templates/example-chain/package.json +9 -0
- package/templates/example-chain/project.json +2593 -0
- package/templates/example-diff/diff-components.json +71 -0
- package/templates/example-diff/recomposite_rig.png +0 -0
- package/templates/example-direction/approval.txt +1 -0
- package/templates/example-direction/derived/review/v1/out/check/build/rectangle.png +0 -0
- package/templates/example-direction/derived/review/v1/out/check/build/run.json +40 -0
- package/templates/example-direction/derived/review/v1/out/check/build/skeleton.atlas +8 -0
- package/templates/example-direction/derived/review/v1/out/check/build/skeleton.json +73 -0
- package/templates/example-direction/derived/review/v1/out/check/build/skeleton.model.json +195 -0
- package/templates/example-direction/evidence/direction/v2.json +69 -0
- package/templates/example-direction/evidence/direction/v3.json +59 -0
- package/templates/example-direction/evidence/images/rectangle.png +0 -0
- package/templates/example-direction/evidence/input.json +69 -0
- package/templates/example-direction/evidence/motion.json +33 -0
- package/templates/example-direction/evidence/patch.json +23 -0
- package/templates/example-direction/evidence/rig-config.json +55 -0
- package/templates/example-direction/evidence/still.png +0 -0
- package/templates/example-direction/project.json +372 -0
- package/templates/example-direction/reasoning.txt +1 -0
- package/templates/example-direction/words.txt +1 -0
- package/templates/example-draft/README.md +28 -0
- package/templates/example-draft/config.json +71 -0
- package/templates/example-draft/derived/drafts/lantern/config.json +71 -0
- package/templates/example-draft/derived/drafts/lantern/input/painting_in_rig.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/input/parts/background.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/input/parts/eye_l.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/input/parts/eye_r.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/input/parts/face.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/input/parts/lantern.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/input/parts/torso.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/input/parts.json +188 -0
- package/templates/example-draft/derived/drafts/lantern/input/recomposite_rig.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/interview-requirements.json +8 -0
- package/templates/example-draft/derived/drafts/lantern/out/check/build/run.json +40 -0
- package/templates/example-draft/derived/drafts/lantern/out/check/build/skeleton.atlas +28 -0
- package/templates/example-draft/derived/drafts/lantern/out/check/build/skeleton.json +193 -0
- package/templates/example-draft/derived/drafts/lantern/out/check/build/skeleton.model.json +483 -0
- package/templates/example-draft/derived/drafts/lantern/out/check/build/skeleton.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/out/images/background.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/out/images/eye_l.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/out/images/eye_r.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/out/images/face.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/out/images/lantern.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/out/images/torso.png +0 -0
- package/templates/example-draft/derived/drafts/lantern/out/mesh_report.json +1 -0
- package/templates/example-draft/derived/drafts/lantern/out/motion.json +137 -0
- package/templates/example-draft/derived/drafts/lantern/out/rig.json +102 -0
- package/templates/example-draft/derived/drafts/lantern/out/run.json +52 -0
- package/templates/example-draft/derived/parts/rig/painting_in_rig.png +0 -0
- package/templates/example-draft/derived/parts/rig/parts/background.png +0 -0
- package/templates/example-draft/derived/parts/rig/parts/eye_l.png +0 -0
- package/templates/example-draft/derived/parts/rig/parts/eye_r.png +0 -0
- package/templates/example-draft/derived/parts/rig/parts/face.png +0 -0
- package/templates/example-draft/derived/parts/rig/parts/lantern.png +0 -0
- package/templates/example-draft/derived/parts/rig/parts/torso.png +0 -0
- package/templates/example-draft/derived/parts/rig/parts.json +188 -0
- package/templates/example-draft/derived/parts/rig/recomposite_rig.png +0 -0
- package/templates/example-draft/derived/review/v1/config.json +71 -0
- package/templates/example-draft/derived/review/v1/interview-requirements.json +8 -0
- package/templates/example-draft/derived/review/v1/out/check/build/run.json +40 -0
- package/templates/example-draft/derived/review/v1/out/check/build/skeleton.atlas +28 -0
- package/templates/example-draft/derived/review/v1/out/check/build/skeleton.json +193 -0
- package/templates/example-draft/derived/review/v1/out/check/build/skeleton.model.json +483 -0
- package/templates/example-draft/derived/review/v1/out/check/build/skeleton.png +0 -0
- package/templates/example-draft/derived/review/v1/out/parts/background.png +0 -0
- package/templates/example-draft/derived/review/v1/out/parts/eye_l.png +0 -0
- package/templates/example-draft/derived/review/v1/out/parts/eye_r.png +0 -0
- package/templates/example-draft/derived/review/v1/out/parts/face.png +0 -0
- package/templates/example-draft/derived/review/v1/out/parts/lantern.png +0 -0
- package/templates/example-draft/derived/review/v1/out/parts/torso.png +0 -0
- package/templates/example-draft/derived/review/v1/out/parts.json +188 -0
- package/templates/example-draft/derived/review/v1/out/rig/images/background.png +0 -0
- package/templates/example-draft/derived/review/v1/out/rig/images/eye_l.png +0 -0
- package/templates/example-draft/derived/review/v1/out/rig/images/eye_r.png +0 -0
- package/templates/example-draft/derived/review/v1/out/rig/images/face.png +0 -0
- package/templates/example-draft/derived/review/v1/out/rig/images/lantern.png +0 -0
- package/templates/example-draft/derived/review/v1/out/rig/images/torso.png +0 -0
- package/templates/example-draft/derived/review/v1/out/rig/mesh_report.json +1 -0
- package/templates/example-draft/derived/review/v1/out/rig/motion.json +137 -0
- package/templates/example-draft/derived/review/v1/out/rig/rig.json +102 -0
- package/templates/example-draft/derived/review/v1/out/rig/run.json +52 -0
- package/templates/example-draft/derived/review/v2/config.json +71 -0
- package/templates/example-draft/derived/review/v2/interview-requirements.json +8 -0
- package/templates/example-draft/derived/review/v2/out/check/build/run.json +40 -0
- package/templates/example-draft/derived/review/v2/out/check/build/skeleton.atlas +28 -0
- package/templates/example-draft/derived/review/v2/out/check/build/skeleton.json +193 -0
- package/templates/example-draft/derived/review/v2/out/check/build/skeleton.model.json +483 -0
- package/templates/example-draft/derived/review/v2/out/check/build/skeleton.png +0 -0
- package/templates/example-draft/derived/review/v2/out/parts/background.png +0 -0
- package/templates/example-draft/derived/review/v2/out/parts/eye_l.png +0 -0
- package/templates/example-draft/derived/review/v2/out/parts/eye_r.png +0 -0
- package/templates/example-draft/derived/review/v2/out/parts/face.png +0 -0
- package/templates/example-draft/derived/review/v2/out/parts/lantern.png +0 -0
- package/templates/example-draft/derived/review/v2/out/parts/torso.png +0 -0
- package/templates/example-draft/derived/review/v2/out/parts.json +188 -0
- package/templates/example-draft/derived/review/v2/out/rig/images/background.png +0 -0
- package/templates/example-draft/derived/review/v2/out/rig/images/eye_l.png +0 -0
- package/templates/example-draft/derived/review/v2/out/rig/images/eye_r.png +0 -0
- package/templates/example-draft/derived/review/v2/out/rig/images/face.png +0 -0
- package/templates/example-draft/derived/review/v2/out/rig/images/lantern.png +0 -0
- package/templates/example-draft/derived/review/v2/out/rig/images/torso.png +0 -0
- package/templates/example-draft/derived/review/v2/out/rig/mesh_report.json +1 -0
- package/templates/example-draft/derived/review/v2/out/rig/motion.json +137 -0
- package/templates/example-draft/derived/review/v2/out/rig/rig.json +102 -0
- package/templates/example-draft/derived/review/v2/out/rig/run.json +52 -0
- package/templates/example-draft/evidence/diff-components.json +71 -0
- package/templates/example-draft/evidence/direction/v4.json +64 -0
- package/templates/example-draft/evidence/direction-input-v4.json +64 -0
- package/templates/example-draft/evidence/fix-ledger/lantern.json +17 -0
- package/templates/example-draft/evidence/parts-check.json +127 -0
- package/templates/example-draft/evidence/parts-review.json +88 -0
- package/templates/example-draft/evidence/review-reads/4ed0507381809746443021554e012032be5b5f8417da0f2e525e9b6df16e9f05.json +59 -0
- package/templates/example-draft/evidence/scene/s1.json +65 -0
- package/templates/example-draft/evidence/scene-background.png +0 -0
- package/templates/example-draft/evidence/scene-citations.json +9 -0
- package/templates/example-draft/evidence/structure-decisions.json +9 -0
- package/templates/example-draft/evidence/v1/interview-config.json +71 -0
- package/templates/example-draft/evidence/v1/interview-requirements.json +8 -0
- package/templates/example-draft/evidence/v1/review-config.json +71 -0
- package/templates/example-draft/evidence/v2/interview-config.json +71 -0
- package/templates/example-draft/evidence/v2/interview-requirements.json +8 -0
- package/templates/example-draft/evidence/v2/review-config.json +71 -0
- package/templates/example-draft/input/painting_in_rig.png +0 -0
- package/templates/example-draft/input/parts/background.png +0 -0
- package/templates/example-draft/input/parts/eye_l.png +0 -0
- package/templates/example-draft/input/parts/eye_r.png +0 -0
- package/templates/example-draft/input/parts/face.png +0 -0
- package/templates/example-draft/input/parts/lantern.png +0 -0
- package/templates/example-draft/input/parts/torso.png +0 -0
- package/templates/example-draft/input/parts.json +188 -0
- package/templates/example-draft/input/recomposite_rig.png +0 -0
- package/templates/example-draft/inputs/painting.png +0 -0
- package/templates/example-draft/interview-requirements.json +8 -0
- package/templates/example-draft/out/check/build/run.json +40 -0
- package/templates/example-draft/out/check/build/skeleton.atlas +28 -0
- package/templates/example-draft/out/check/build/skeleton.json +193 -0
- package/templates/example-draft/out/check/build/skeleton.model.json +483 -0
- package/templates/example-draft/out/check/build/skeleton.png +0 -0
- package/templates/example-draft/out/images/background.png +0 -0
- package/templates/example-draft/out/images/eye_l.png +0 -0
- package/templates/example-draft/out/images/eye_r.png +0 -0
- package/templates/example-draft/out/images/face.png +0 -0
- package/templates/example-draft/out/images/lantern.png +0 -0
- package/templates/example-draft/out/images/torso.png +0 -0
- package/templates/example-draft/out/mesh_report.json +1 -0
- package/templates/example-draft/out/motion.json +137 -0
- package/templates/example-draft/out/rig.json +102 -0
- package/templates/example-draft/out/run.json +52 -0
- package/templates/example-draft/outputs/v1/out/check/build/run.json +40 -0
- package/templates/example-draft/outputs/v1/out/check/build/skeleton.atlas +28 -0
- package/templates/example-draft/outputs/v1/out/check/build/skeleton.json +193 -0
- package/templates/example-draft/outputs/v1/out/check/build/skeleton.model.json +483 -0
- package/templates/example-draft/outputs/v1/out/check/build/skeleton.png +0 -0
- package/templates/example-draft/outputs/v1/out/painting_in_rig.png +0 -0
- package/templates/example-draft/outputs/v1/out/parts/background.png +0 -0
- package/templates/example-draft/outputs/v1/out/parts/eye_l.png +0 -0
- package/templates/example-draft/outputs/v1/out/parts/eye_r.png +0 -0
- package/templates/example-draft/outputs/v1/out/parts/face.png +0 -0
- package/templates/example-draft/outputs/v1/out/parts/lantern.png +0 -0
- package/templates/example-draft/outputs/v1/out/parts/torso.png +0 -0
- package/templates/example-draft/outputs/v1/out/parts.json +188 -0
- package/templates/example-draft/outputs/v1/out/rig/images/background.png +0 -0
- package/templates/example-draft/outputs/v1/out/rig/images/eye_l.png +0 -0
- package/templates/example-draft/outputs/v1/out/rig/images/eye_r.png +0 -0
- package/templates/example-draft/outputs/v1/out/rig/images/face.png +0 -0
- package/templates/example-draft/outputs/v1/out/rig/images/lantern.png +0 -0
- package/templates/example-draft/outputs/v1/out/rig/images/torso.png +0 -0
- package/templates/example-draft/outputs/v1/out/rig/mesh_report.json +1 -0
- package/templates/example-draft/outputs/v1/out/rig/motion.json +137 -0
- package/templates/example-draft/outputs/v1/out/rig/rig.json +102 -0
- package/templates/example-draft/outputs/v1/out/rig/run.json +52 -0
- package/templates/example-draft/outputs/v2/out/check/build/run.json +40 -0
- package/templates/example-draft/outputs/v2/out/check/build/skeleton.atlas +28 -0
- package/templates/example-draft/outputs/v2/out/check/build/skeleton.json +193 -0
- package/templates/example-draft/outputs/v2/out/check/build/skeleton.model.json +483 -0
- package/templates/example-draft/outputs/v2/out/check/build/skeleton.png +0 -0
- package/templates/example-draft/outputs/v2/out/painting_in_rig.png +0 -0
- package/templates/example-draft/outputs/v2/out/parts/background.png +0 -0
- package/templates/example-draft/outputs/v2/out/parts/eye_l.png +0 -0
- package/templates/example-draft/outputs/v2/out/parts/eye_r.png +0 -0
- package/templates/example-draft/outputs/v2/out/parts/face.png +0 -0
- package/templates/example-draft/outputs/v2/out/parts/lantern.png +0 -0
- package/templates/example-draft/outputs/v2/out/parts/torso.png +0 -0
- package/templates/example-draft/outputs/v2/out/parts.json +188 -0
- package/templates/example-draft/outputs/v2/out/rig/images/background.png +0 -0
- package/templates/example-draft/outputs/v2/out/rig/images/eye_l.png +0 -0
- package/templates/example-draft/outputs/v2/out/rig/images/eye_r.png +0 -0
- package/templates/example-draft/outputs/v2/out/rig/images/face.png +0 -0
- package/templates/example-draft/outputs/v2/out/rig/images/lantern.png +0 -0
- package/templates/example-draft/outputs/v2/out/rig/images/torso.png +0 -0
- package/templates/example-draft/outputs/v2/out/rig/mesh_report.json +1 -0
- package/templates/example-draft/outputs/v2/out/rig/motion.json +137 -0
- package/templates/example-draft/outputs/v2/out/rig/rig.json +102 -0
- package/templates/example-draft/outputs/v2/out/rig/run.json +52 -0
- package/templates/example-interview-choice.json +1068 -0
- package/templates/example-interview-options/constraint.json +376 -0
- package/templates/example-interview-options/example-assemble.json +376 -0
- package/templates/example-interview-options/example-bones.json +190 -0
- package/templates/example-interview-options/example-camera-depth.json +99 -0
- package/templates/example-interview-options/example-constraints.json +272 -0
- package/templates/example-interview-options/example-meshes.json +190 -0
- package/templates/example-interview-options/example-motion.json +272 -0
- package/templates/example-interview-options/example-picks.json +15 -0
- package/templates/example-interview-options/example-post-composition.json +110 -0
- package/templates/example-interview-options/example-post-timing.json +105 -0
- package/templates/example-interview-options/example-reference.json +63 -0
- package/templates/example-interview-options/example-rig-type.json +63 -0
- package/templates/example-interview-options/example-seethrough.json +190 -0
- package/templates/example-interview-options/fullscreen.json +63 -0
- package/templates/example-interview-options/other-explicit.json +63 -0
- package/templates/example-interview-options/other-pending.json +63 -0
- package/templates/example-interview-options/other-picks.json +16 -0
- package/templates/example-interview.md +213 -0
- package/templates/example-invariants/invariants.json +1339 -0
- package/templates/example-prepared/prepared.svg +1 -0
- package/templates/example-prepared/source.svg +1 -0
- package/templates/example-project.json +4259 -0
- package/templates/example-remesh/AGENTS.md +134 -0
- package/templates/example-remesh/CLAUDE.md +3 -0
- package/templates/example-remesh/evidence/.gitkeep +0 -0
- package/templates/example-remesh/evidence/approval.txt +1 -0
- package/templates/example-remesh/evidence/captions.json +101 -0
- package/templates/example-remesh/evidence/diff-components.json +34 -0
- package/templates/example-remesh/evidence/direction/v4.json +74 -0
- package/templates/example-remesh/evidence/direction/v5.json +74 -0
- package/templates/example-remesh/evidence/direction-input-v4.json +74 -0
- package/templates/example-remesh/evidence/direction-input-v5.json +74 -0
- package/templates/example-remesh/evidence/interview/assemble.json +309 -0
- package/templates/example-remesh/evidence/interview/bones.json +190 -0
- package/templates/example-remesh/evidence/interview/camera_depth.json +103 -0
- package/templates/example-remesh/evidence/interview/constraints.json +272 -0
- package/templates/example-remesh/evidence/interview/meshes.json +190 -0
- package/templates/example-remesh/evidence/interview/motion.json +272 -0
- package/templates/example-remesh/evidence/interview/post_composition.json +123 -0
- package/templates/example-remesh/evidence/interview/post_timing.json +103 -0
- package/templates/example-remesh/evidence/interview/reference.json +59 -0
- package/templates/example-remesh/evidence/interview/rig_type.json +59 -0
- package/templates/example-remesh/evidence/interview/seethrough.json +186 -0
- package/templates/example-remesh/evidence/parts-check.json +127 -0
- package/templates/example-remesh/evidence/parts-review.json +88 -0
- package/templates/example-remesh/evidence/reopen.txt +1 -0
- package/templates/example-remesh/evidence/review-reads/6a17db694db96f1b6049a61a017e0c8e66757b982b8851e0187e561cfcf9af68.json +59 -0
- package/templates/example-remesh/evidence/scene/s1.json +69 -0
- package/templates/example-remesh/evidence/scene-citations.json +9 -0
- package/templates/example-remesh/evidence/setup.png +0 -0
- package/templates/example-remesh/evidence/split-config.json +1 -0
- package/templates/example-remesh/evidence/structure.json +30 -0
- package/templates/example-remesh/evidence/v1/registration/at-source.json +44 -0
- package/templates/example-remesh/evidence/v1/registration/citations.json +68 -0
- package/templates/example-remesh/evidence/v1/registration/compile-report.json +368 -0
- package/templates/example-remesh/evidence/v1/registration/config-source.json +88 -0
- package/templates/example-remesh/evidence/v1/registration/config.json +88 -0
- package/templates/example-remesh/evidence/v1/registration/interview-requirements.json +8 -0
- package/templates/example-remesh/evidence/v1/registration/package-lock.json +11 -0
- package/templates/example-remesh/evidence/v1/registration/path-adapter.json +1 -0
- package/templates/example-remesh/evidence/v1/registration/rigc-run-1.json +44 -0
- package/templates/example-remesh/evidence/v2/registration/at-source.json +44 -0
- package/templates/example-remesh/evidence/v2/registration/citations.json +68 -0
- package/templates/example-remesh/evidence/v2/registration/compile-report.json +368 -0
- package/templates/example-remesh/evidence/v2/registration/config-source.json +88 -0
- package/templates/example-remesh/evidence/v2/registration/config.json +88 -0
- package/templates/example-remesh/evidence/v2/registration/interview-requirements.json +8 -0
- package/templates/example-remesh/evidence/v2/registration/package-lock.json +11 -0
- package/templates/example-remesh/evidence/v2/registration/path-adapter.json +1 -0
- package/templates/example-remesh/evidence/v2/registration/rigc-run-1.json +44 -0
- package/templates/example-remesh/evidence/v3/registration/at-source.json +44 -0
- package/templates/example-remesh/evidence/v3/registration/citations.json +68 -0
- package/templates/example-remesh/evidence/v3/registration/compile-report.json +368 -0
- package/templates/example-remesh/evidence/v3/registration/config-source.json +88 -0
- package/templates/example-remesh/evidence/v3/registration/config.json +88 -0
- package/templates/example-remesh/evidence/v3/registration/interview-requirements.json +8 -0
- package/templates/example-remesh/evidence/v3/registration/package-lock.json +11 -0
- package/templates/example-remesh/evidence/v3/registration/path-adapter.json +1 -0
- package/templates/example-remesh/evidence/v3/registration/rigc-run-1.json +44 -0
- package/templates/example-remesh/inputs/background.png +0 -0
- package/templates/example-remesh/inputs/painting.png +0 -0
- package/templates/example-remesh/inputs/references/.gitkeep +0 -0
- package/templates/example-remesh/package.json +9 -0
- package/templates/example-remesh/project.json +3916 -0
- package/templates/example-reopened/project.json +4568 -0
- package/templates/example-review/config.json +1 -0
- package/templates/example-review/out/check/build/skeleton.model.json +1 -0
- package/templates/example-review/out/parts/piece.svg +1 -0
- package/templates/example-review/out/parts.json +1 -0
- package/templates/example-review/out/rig/mesh_report.json +1 -0
- package/templates/example-review/out/rig/motion.json +1 -0
- package/templates/example-review/out/rig/rig.json +1 -0
- package/templates/example-split/captions.json +357 -0
- package/templates/example-split/config.json +215 -0
- package/templates/legacy-example-project.json +1071 -0
- package/templates/project.json +199 -0
- package/templates/shared/conventions.json +23 -0
package/src/reopen.ts
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { writeFileSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
|
|
4
|
+
import { asArray, asString, isObject, type Finding } from './check.ts';
|
|
5
|
+
import { collectAmendments } from './amend.ts';
|
|
6
|
+
import { readProject } from './feedback.ts';
|
|
7
|
+
import { readVerbatim } from './record-input.ts';
|
|
8
|
+
import { refuse, USAGE_EXIT } from './refusal.ts';
|
|
9
|
+
import { newRefusals } from './refusal-baseline.ts';
|
|
10
|
+
import { stageIndex, stageOfStep, STAGE_VALUES } from './stages.ts';
|
|
11
|
+
import type { JsonObject } from './templates.ts';
|
|
12
|
+
|
|
13
|
+
export interface Reopen {
|
|
14
|
+
readonly stage: string;
|
|
15
|
+
readonly at: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Validate history before using it as authority. Invalid entries supersede nothing. */
|
|
19
|
+
export function collectReopens(project: JsonObject, refusals: Finding[]): Reopen[] {
|
|
20
|
+
const out: Reopen[] = [];
|
|
21
|
+
const push = (code: string, path: string, why: string): void => {
|
|
22
|
+
refusals.push({ code, path, message: `${path}: ${why}; record a human reopen to a previously reached stage` });
|
|
23
|
+
};
|
|
24
|
+
if (project.reopens !== undefined && !Array.isArray(project.reopens)) {
|
|
25
|
+
push('REOPEN_MALFORMED', 'reopens', 'must be a list');
|
|
26
|
+
return out;
|
|
27
|
+
}
|
|
28
|
+
for (const [index, raw] of asArray(project.reopens).entries()) {
|
|
29
|
+
const path = `reopens[${index}]`;
|
|
30
|
+
if (!isObject(raw) || ['stage', 'from_stage', 'by', 'at', 'verbatim'].some(k => asString(raw[k]) === null)
|
|
31
|
+
|| !Number.isFinite(Date.parse(raw.at as string)) || (raw.source !== undefined && typeof raw.source !== 'string')) {
|
|
32
|
+
push('REOPEN_MALFORMED', path, 'needs stage, from_stage, by, a valid at, verbatim and optional text source');
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if ((raw.by as string).toLowerCase() === 'agent') {
|
|
36
|
+
push('SIGNOFF_NOT_HUMAN', path, 'signed by agent');
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (!Array.isArray(raw.steps_before) || raw.steps_before.some(s => !isObject(s) || typeof s.id !== 'string'
|
|
40
|
+
|| (s.status !== undefined && (typeof s.status !== 'string' || !['pending', 'in-progress', 'at-checkpoint', 'done'].includes(s.status))))) {
|
|
41
|
+
push('REOPEN_MALFORMED', path, 'steps_before must snapshot step ids and original statuses');
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const stage = raw.stage as string;
|
|
45
|
+
if (stageIndex(stage) < 0 || stage === 'accepted') {
|
|
46
|
+
push('REOPEN_STAGE_UNKNOWN', path, `target ${stage} is not a reopenable stage`);
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const fromStage = raw.from_stage as string;
|
|
50
|
+
if (!STAGE_VALUES.includes(fromStage)) {
|
|
51
|
+
push('REOPEN_MALFORMED', `${path}.from_stage`, 'must be a known project stage');
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const at = Date.parse(raw.at as string);
|
|
55
|
+
if (stageIndex(stage) > reachedIndex(project, at, fromStage)) {
|
|
56
|
+
push('REOPEN_NOT_PASSED', path, `target ${stage} was not reached at ${String(raw.at)}`);
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
out.push({ stage, at });
|
|
60
|
+
}
|
|
61
|
+
return [...out, ...collectAmendments(project, refusals)];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Historical stages and dated builds witness reach even after stage has moved back. */
|
|
65
|
+
function reachedIndex(project: JsonObject, at: number, fromStage: string): number {
|
|
66
|
+
let reached = stageIndex(fromStage);
|
|
67
|
+
for (const raw of asArray(project.signoffs)) {
|
|
68
|
+
if (!isObject(raw) || typeof raw.by !== 'string' || raw.by.toLowerCase() === 'agent'
|
|
69
|
+
|| typeof raw.verbatim !== 'string' || typeof raw.at !== 'string' || !(Date.parse(raw.at) <= at)) continue;
|
|
70
|
+
reached = Math.max(reached, stageIndex(asString(raw.stage) ?? ''));
|
|
71
|
+
}
|
|
72
|
+
for (const raw of asArray(project.versions)) {
|
|
73
|
+
if (!isObject(raw) || typeof raw.at !== 'string' || !(Date.parse(raw.at) <= at)) continue;
|
|
74
|
+
if (raw.kind === 'rig') reached = Math.max(reached, stageIndex('rigging'));
|
|
75
|
+
if (raw.kind === 'post') reached = Math.max(reached, stageIndex('post'));
|
|
76
|
+
}
|
|
77
|
+
return reached;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Each reopen invalidates its suffix; a later, narrower reopen cannot resurrect an earlier suffix. */
|
|
81
|
+
export function reopenTime(reopens: readonly Reopen[], stage: string): number {
|
|
82
|
+
return Math.max(-Infinity, ...reopens.filter(r => stageIndex(r.stage) <= stageIndex(stage)).map(r => r.at));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** The `reopens[]` index of a validated reopen, matched by its stage and time. */
|
|
86
|
+
export function reopenIndex(project: JsonObject, reopen: Reopen): number {
|
|
87
|
+
return asArray(project.reopens).findIndex(r => isObject(r) && r.stage === reopen.stage && Date.parse(asString(r.at) ?? '') === reopen.at);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function liveSignoff(reopens: readonly Reopen[], stage: string, at: number): boolean {
|
|
91
|
+
const since = reopenTime(reopens, stage);
|
|
92
|
+
return since === -Infinity || at > since;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export const REOPEN_HELP = `reopen:
|
|
96
|
+
<stage> [<project dir>] record a human backward move and set project.stage
|
|
97
|
+
--by <who> human signer (agent is refused)
|
|
98
|
+
--verbatim-file <file> unchanged UTF-8 words, or - for stdin (default)
|
|
99
|
+
--source <text> optional origin of the words, separate from verbatim
|
|
100
|
+
--json print the reopen record
|
|
101
|
+
The clock supplies at; sign-offs and versions remain history.`;
|
|
102
|
+
|
|
103
|
+
export function reopenCommand(args: string[], now: number): { stdout: string; exit: number } {
|
|
104
|
+
const opts: Record<string, string> = {};
|
|
105
|
+
const positional: string[] = [];
|
|
106
|
+
let json = false;
|
|
107
|
+
for (let i = 0; i < args.length; i++) {
|
|
108
|
+
const arg = args[i] as string;
|
|
109
|
+
if (arg === '--json') json = true;
|
|
110
|
+
else if (['--by', '--verbatim-file', '--source'].includes(arg)) {
|
|
111
|
+
const value = args[++i];
|
|
112
|
+
if (arg in opts || value === undefined || value === '') refuse('REOPEN_OPTION_INVALID', `reopens: ${arg} needs one non-empty value; supply it once`, USAGE_EXIT);
|
|
113
|
+
opts[arg] = value;
|
|
114
|
+
} else if (arg.startsWith('-')) refuse('UNKNOWN_OPTION', `reopens: unsupported ${arg}; see reopen help`, USAGE_EXIT);
|
|
115
|
+
else positional.push(arg);
|
|
116
|
+
}
|
|
117
|
+
if (positional.length < 1 || positional.length > 2 || opts['--by'] === undefined) refuse('REOPEN_OPTION_INVALID', 'reopens: supply a stage, --by and one optional project directory', USAGE_EXIT);
|
|
118
|
+
const dir = resolve(positional[1] ?? process.cwd());
|
|
119
|
+
const { file, project } = readProject(dir);
|
|
120
|
+
const before = structuredClone(project);
|
|
121
|
+
const steps = asArray(isObject(project.plan) ? project.plan.steps : undefined);
|
|
122
|
+
if (steps.some(s => !isObject(s) || typeof s.id !== 'string' || (s.phase !== 'rig' && s.phase !== 'post'))) {
|
|
123
|
+
refuse('REOPEN_MALFORMED', 'plan.steps: each step needs id and phase; restore the plan before reopening');
|
|
124
|
+
}
|
|
125
|
+
const affected = steps.filter((s): s is JsonObject => isObject(s)
|
|
126
|
+
&& stageIndex(stageOfStep(s.phase as 'rig' | 'post', s.id as string)) >= stageIndex(positional[0] as string));
|
|
127
|
+
const entry: JsonObject = { from_stage: project.stage ?? null, steps_before: affected.map(s => ({ id: s.id as string, ...(s.status === undefined ? {} : { status: s.status }) })), stage: positional[0] as string, by: opts['--by'], at: new Date(now).toISOString(), verbatim: '' };
|
|
128
|
+
if (opts['--source'] !== undefined) entry.source = opts['--source'];
|
|
129
|
+
const refusals: Finding[] = [];
|
|
130
|
+
// Validate against the original reached stage before moving it backwards.
|
|
131
|
+
const candidate = { ...project, reopens: [...asArray(project.reopens), entry] };
|
|
132
|
+
if (project.reopens !== undefined && !Array.isArray(project.reopens)) collectReopens(project, refusals);
|
|
133
|
+
collectReopens(candidate, refusals);
|
|
134
|
+
const first = refusals[0];
|
|
135
|
+
if (first !== undefined) refuse(first.code, first.message);
|
|
136
|
+
entry.verbatim = readVerbatim(opts['--verbatim-file'] ?? '-');
|
|
137
|
+
for (const step of affected) step.status = 'pending';
|
|
138
|
+
project.reopens = candidate.reopens;
|
|
139
|
+
project.stage = entry.stage;
|
|
140
|
+
const rejected = newRefusals(dir, before, project, { now })[0];
|
|
141
|
+
if (rejected !== undefined) refuse(rejected.code, rejected.message);
|
|
142
|
+
writeFileSync(file, `${JSON.stringify(project, null, 2)}\n`);
|
|
143
|
+
return { stdout: json ? JSON.stringify(entry, null, 2) : `reopen: ${String(entry.stage)} by ${String(entry.by)} at ${String(entry.at)}`, exit: 0 };
|
|
144
|
+
}
|
package/src/republish.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/** Add a publication generation without rebuilding any rig artifact. */
|
|
2
|
+
import { closeSync, fchmodSync, openSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
5
|
+
import { asArray, checkProject, isObject } from './check.ts';
|
|
6
|
+
import { publicationFile, liveManifestPath, originalPaintingReference, prepareLiveManifest, checkPublicationGenerations, sealedScene } from './job-publication.ts';
|
|
7
|
+
import { assertRequestedRig } from './job-host.ts';
|
|
8
|
+
import { acquireBoundJobWrite, prepareVersionIntent, publishCommittedVersion } from './job-writer.ts';
|
|
9
|
+
import { cancelUncommittedIntent, jobHash, type PendingPublication } from './job-outbox.ts';
|
|
10
|
+
import { baselineOf, newFindings } from './refusal-baseline.ts';
|
|
11
|
+
import { refuse } from './refusal.ts';
|
|
12
|
+
import type { Finding } from './check.ts';
|
|
13
|
+
import type { JsonObject } from './templates.ts';
|
|
14
|
+
|
|
15
|
+
export function republishCommand(args: string[], now: number): { stdout: string; exit: number } {
|
|
16
|
+
const positional: string[] = []; let reason: string | undefined;
|
|
17
|
+
for (let i = 0; i < args.length; i++) {
|
|
18
|
+
if (args[i] === '--reason' && reason === undefined) reason = args[++i];
|
|
19
|
+
else if (args[i]!.startsWith('-')) refuse('PUBLICATION_GENERATION_INVALID', 'project.json: use republish <rig> [<dir>] --reason <words>');
|
|
20
|
+
else positional.push(args[i]!);
|
|
21
|
+
}
|
|
22
|
+
const n = Number(positional[0]?.replace(/^v/, ''));
|
|
23
|
+
if (!Number.isSafeInteger(n) || n < 1 || positional.length > 2 || !reason?.trim()) refuse('PUBLICATION_GENERATION_INVALID', 'project.json: use republish <rig> [<dir>] --reason <words>');
|
|
24
|
+
const root = realpathSync(positional[1] ?? process.cwd());
|
|
25
|
+
const lock = join(root, '.republish.lock');
|
|
26
|
+
let fd: number;
|
|
27
|
+
try { fd = openSync(lock, 'wx'); } catch { refuse('PUBLICATION_GENERATION_INVALID', 'project.json: another republish writer holds the lock; wait and retry'); }
|
|
28
|
+
let release = () => {}; let staged = false; let committed = false; let intent: PendingPublication | null = null;
|
|
29
|
+
const path = `review-live-v${n}-g2.json`;
|
|
30
|
+
try {
|
|
31
|
+
release = acquireBoundJobWrite(root);
|
|
32
|
+
const original = publicationFile(root, 'project.json');
|
|
33
|
+
const project = JSON.parse(original.toString('utf8')) as JsonObject;
|
|
34
|
+
assertRequestedRig(root, String(n));
|
|
35
|
+
const version = asArray(project.versions).filter(isObject).find(v => v.n === n)!;
|
|
36
|
+
liveManifestPath(root, project, n);
|
|
37
|
+
if (version.publication_generations !== undefined) refuse('PUBLICATION_GENERATION_DUPLICATE', `versions[v${n}].publication_generations: a publication generation already exists; reopen it with job open --rig ${n}`);
|
|
38
|
+
if (version.kind !== 'post' && (!Array.isArray(project.inputs) || project.inputs.length === 0)) refuse('PUBLICATION_PAINTING_MISSING', `versions[v${n}]: no inputs[0] original painting is declared; register it with input add before republishing`);
|
|
39
|
+
const reference = version.kind === 'post' ? null : originalPaintingReference(root, project, n);
|
|
40
|
+
const legacyPath = `review-live-v${n}.json`;
|
|
41
|
+
const old = publicationFile(root, legacyPath);
|
|
42
|
+
const manifest = JSON.parse(old.toString('utf8')) as JsonObject;
|
|
43
|
+
if (version.kind !== 'post' && Array.isArray(manifest.references) && manifest.references.length) refuse('PUBLICATION_GENERATION_DUPLICATE', `versions[v${n}]: the publication already carries a reference; reopen it with job open --rig ${n}`);
|
|
44
|
+
// Check the exact immutable legacy shape through the original publisher.
|
|
45
|
+
prepareLiveManifest(root, project, n);
|
|
46
|
+
let scene: string | undefined;
|
|
47
|
+
const sources = new Map<string, string>();
|
|
48
|
+
if (version.kind === 'post') {
|
|
49
|
+
const directionPath = `evidence/direction/v${n}.json`;
|
|
50
|
+
const directionBytes = publicationFile(root, directionPath);
|
|
51
|
+
const direction = JSON.parse(directionBytes.toString('utf8')) as JsonObject;
|
|
52
|
+
if (direction.schema !== 'rig-create/direction@2' || !isObject(direction.scene)) refuse('PUBLICATION_GENERATION_INVALID', `${directionPath}: post generation requires direction@2 and its committed scene; retain the existing publication for a scene-less post`);
|
|
53
|
+
if (manifest.scene !== undefined) refuse('PUBLICATION_GENERATION_DUPLICATE', `${legacyPath}: the publication already carries a scene; reopen it with job open --rig ${n}`);
|
|
54
|
+
const sealed = sealedScene(root, project, directionPath, direction)!;
|
|
55
|
+
scene = sealed.path;
|
|
56
|
+
const binding = (version.provenance as JsonObject).direction as JsonObject;
|
|
57
|
+
if (binding.path !== directionPath || binding.sha256 !== jobHash(directionBytes) || direction.scene.sha256 !== sealed.sha256) refuse('PUBLICATION_GENERATION_INVALID', `${directionPath}: publication sources changed during republish; restore the frozen direction and scene bytes`);
|
|
58
|
+
sources.set(directionPath, String(binding.sha256));
|
|
59
|
+
sources.set(scene, sealed.sha256);
|
|
60
|
+
for (const plate of sealed.plates) sources.set(plate.path, plate.sha256);
|
|
61
|
+
}
|
|
62
|
+
const before = baselineOf(checkProject(root, project, { now, readOnly: true }));
|
|
63
|
+
const bytes = Buffer.from(`${JSON.stringify({ ...manifest, revision: `v${n}-g2`, ...(scene ? { scene } : { references: [reference] }) }, null, 2)}\n`);
|
|
64
|
+
const next = structuredClone(project);
|
|
65
|
+
const target = asArray(next.versions).filter(isObject).find(v => v.n === n)!;
|
|
66
|
+
target.publication_generations = [{ generation: 2, supersedes: { generation: 1, path: legacyPath, sha256: jobHash(old) },
|
|
67
|
+
manifest: { path, sha256: jobHash(bytes) }, at: new Date(now).toISOString(), reason }];
|
|
68
|
+
try { writeFileSync(join(root, path), bytes, { flag: 'wx' }); staged = true; }
|
|
69
|
+
catch { refuse('PUBLICATION_GENERATION_INVALID', `versions[v${n}]: ${path} already exists or is unwritable; preserve existing generations and restore writable storage`); }
|
|
70
|
+
const findings: Finding[] = [];
|
|
71
|
+
checkPublicationGenerations(root, next, findings);
|
|
72
|
+
findings.push(...newFindings(before, checkProject(root, next, { now, readOnly: true }).refusals));
|
|
73
|
+
if (findings[0]) refuse(findings[0].code, findings[0].message);
|
|
74
|
+
if (!publicationFile(root, 'project.json').equals(original) || !publicationFile(root, legacyPath).equals(old) ||
|
|
75
|
+
(reference !== null && !isDeepStrictEqual(originalPaintingReference(root, project, n), reference)) ||
|
|
76
|
+
[...sources].some(([path, sha256]) => jobHash(publicationFile(root, path)) !== sha256)) refuse('PUBLICATION_GENERATION_INVALID', 'project.json: source changed during republish; freeze the record and publication sources and retry');
|
|
77
|
+
const record = Buffer.from(`${JSON.stringify(next, null, 2)}\n`);
|
|
78
|
+
intent = prepareVersionIntent(root, record, n);
|
|
79
|
+
fchmodSync(fd, statSync(join(root, 'project.json')).mode);
|
|
80
|
+
writeFileSync(fd, record);
|
|
81
|
+
renameSync(lock, join(root, 'project.json')); committed = true;
|
|
82
|
+
publishCommittedVersion(root, n);
|
|
83
|
+
return { stdout: `republish: ${version.kind === 'post' ? 'post' : 'rig'} v${n} generation 2 recorded (${path})`, exit: 0 };
|
|
84
|
+
} finally {
|
|
85
|
+
closeSync(fd);
|
|
86
|
+
if (!committed) {
|
|
87
|
+
cancelUncommittedIntent(root, intent);
|
|
88
|
+
if (staged) rmSync(join(root, path));
|
|
89
|
+
rmSync(lock, { force: true });
|
|
90
|
+
}
|
|
91
|
+
release();
|
|
92
|
+
}
|
|
93
|
+
}
|
package/src/restart.ts
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `restart`: start a project's record again at v1 through a writer (create#285). The fresh record is
|
|
3
|
+
* the one init writes. It keeps the inputs, re-validated by the input writer's checks, and the fix
|
|
4
|
+
* ledger, because owner feedback belongs to the project, not to a version. create does not keep the
|
|
5
|
+
* earlier project.json; git history holds it, and restarts[] names its sha256. That holds only when
|
|
6
|
+
* project.json is committed, so restart refuses before it writes unless project.json is tracked and
|
|
7
|
+
* byte-identical to its HEAD version (create#304).
|
|
8
|
+
*/
|
|
9
|
+
import { createHash } from 'node:crypto';
|
|
10
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
11
|
+
import { join, resolve } from 'node:path';
|
|
12
|
+
import { asArray, checkProject, isObject, PROJECT_SCHEMA, type Finding } from './check.ts';
|
|
13
|
+
import { ledgerRows, writeRecord } from './fix-ledger.ts';
|
|
14
|
+
import { freshProjectRecord, run } from './init.ts';
|
|
15
|
+
import { checkInputs } from './inputs.ts';
|
|
16
|
+
import { acquireBoundJobWrite } from './job-writer.ts';
|
|
17
|
+
import { readVerbatim } from './record-input.ts';
|
|
18
|
+
import { refuse, USAGE_EXIT } from './refusal.ts';
|
|
19
|
+
import { baselineOf, newFindings } from './refusal-baseline.ts';
|
|
20
|
+
import type { Json, JsonObject } from './templates.ts';
|
|
21
|
+
|
|
22
|
+
export const RESTART_HELP = `restart:
|
|
23
|
+
[<dir>] --by <human> --reason-file <file> [--json]
|
|
24
|
+
Replace project.json with the record init writes: the template's stage, no versions, drafts,
|
|
25
|
+
signoffs, plan, answers or review acts. Keeps name, title, painting, same_artwork, inputs[] (each file must
|
|
26
|
+
still match its sha256) and fix_ledger with every row, and appends restarts[] { at, by, reason,
|
|
27
|
+
previous_record_sha256 }. git history holds the earlier record, so restart refuses unless
|
|
28
|
+
project.json is committed: tracked and byte-identical to HEAD. A kept part set (inputs under
|
|
29
|
+
<set>/parts/*.png or <set>/parts.json) keeps <set>/parts.json and its rig: rig.json and
|
|
30
|
+
mesh_report.json, at <set>/rig/ or <set>/.`;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The bytes of `<dir>/project.json` at HEAD, refusing unless the folder is in a git work tree and the
|
|
34
|
+
* file is committed there byte for byte: restart drops the earlier record, so git history must hold it.
|
|
35
|
+
*/
|
|
36
|
+
export function committedRecord(dir: string, file: string): Buffer {
|
|
37
|
+
const remedy = 'commit project.json, then restart';
|
|
38
|
+
const inside = run(['git', 'rev-parse', '--is-inside-work-tree'], dir);
|
|
39
|
+
if (!inside.ok || inside.out !== 'true') {
|
|
40
|
+
refuse('RESTART_NOT_IN_GIT', `${file}: the folder is not inside a git work tree, so git history cannot hold the record restart replaces; put the project under git, ${remedy}`);
|
|
41
|
+
}
|
|
42
|
+
const prefix = run(['git', 'rev-parse', '--show-prefix'], dir);
|
|
43
|
+
if (!prefix.ok) refuse('RESTART_NOT_IN_GIT', `${file}: git cannot resolve the folder's path in its work tree (${prefix.out}); ${remedy}`);
|
|
44
|
+
const path = `${prefix.out}project.json`;
|
|
45
|
+
const head = Bun.spawnSync(['git', 'show', `HEAD:${path}`], { cwd: dir, stdout: 'pipe', stderr: 'pipe' });
|
|
46
|
+
if (head.exitCode !== 0) {
|
|
47
|
+
const tracked = run(['git', 'ls-files', '--error-unmatch', '--', 'project.json'], dir).ok;
|
|
48
|
+
refuse('RESTART_RECORD_UNCOMMITTED', `${file}: ${tracked ? 'is staged but was never committed' : 'is untracked'}, so git history does not hold the record restart replaces; ${remedy}`);
|
|
49
|
+
}
|
|
50
|
+
const bytes = Buffer.from(head.stdout);
|
|
51
|
+
if (!readFileSync(file).equals(bytes)) {
|
|
52
|
+
refuse('RESTART_RECORD_UNCOMMITTED', `${file}: differs from HEAD:${path} (uncommitted changes), so git history does not hold the record restart replaces; ${remedy}`);
|
|
53
|
+
}
|
|
54
|
+
return bytes;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Kept part sets missing their manifest, their rig or their PNGs, by set root. */
|
|
58
|
+
export function partSetGaps(inputs: Json | undefined): string[] {
|
|
59
|
+
const paths = new Set(asArray(inputs).filter(isObject).map(input => input.path).filter((path): path is string => typeof path === 'string'));
|
|
60
|
+
const roots = new Set<string>();
|
|
61
|
+
for (const path of paths) {
|
|
62
|
+
const set = /^(?:(.*)\/)?parts\/[^/]+\.png$/i.exec(path) ?? /^(?:(.*)\/)?parts\.json$/.exec(path);
|
|
63
|
+
if (set) roots.add(set[1] ?? '');
|
|
64
|
+
}
|
|
65
|
+
const gaps: string[] = [];
|
|
66
|
+
for (const root of [...roots].sort()) {
|
|
67
|
+
const at = (name: string): string => (root === '' ? name : `${root}/${name}`);
|
|
68
|
+
const missing: string[] = [];
|
|
69
|
+
if (!paths.has(at('parts.json'))) missing.push(at('parts.json'));
|
|
70
|
+
if (![...paths].some(path => path.startsWith(at('parts/')) && /\.png$/i.test(path))) missing.push(at('parts/*.png'));
|
|
71
|
+
const rig = ['rig/', ''].find(prefix => paths.has(at(`${prefix}rig.json`)) && paths.has(at(`${prefix}mesh_report.json`)));
|
|
72
|
+
if (rig === undefined) missing.push(`${at('rig/rig.json')} and ${at('rig/mesh_report.json')} (or ${at('rig.json')} and ${at('mesh_report.json')})`);
|
|
73
|
+
if (missing.length) gaps.push(`${root === '' ? '(project root)' : root}: ${missing.join(', ')}`);
|
|
74
|
+
}
|
|
75
|
+
return gaps;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function restartCommand(args: string[], now: number): { stdout: string; exit: number } {
|
|
79
|
+
const opts: Record<string, string> = {};
|
|
80
|
+
const positional: string[] = [];
|
|
81
|
+
let json = false;
|
|
82
|
+
for (let i = 0; i < args.length; i++) {
|
|
83
|
+
const arg = args[i]!;
|
|
84
|
+
if (arg === '--json') json = true;
|
|
85
|
+
else if (arg === '--by' || arg === '--reason-file') {
|
|
86
|
+
const value = args[++i];
|
|
87
|
+
if (value === undefined || value.startsWith('--') || value.trim() === '' || opts[arg] !== undefined) refuse('RESTART_USAGE', `restart: ${arg} needs one value; see restart help`, USAGE_EXIT);
|
|
88
|
+
opts[arg] = value;
|
|
89
|
+
} else if (arg.startsWith('-')) refuse('RESTART_USAGE', `restart: unsupported ${arg}; see restart help`, USAGE_EXIT);
|
|
90
|
+
else positional.push(arg);
|
|
91
|
+
}
|
|
92
|
+
if (positional.length > 1 || opts['--by'] === undefined || opts['--reason-file'] === undefined) refuse('RESTART_USAGE', RESTART_HELP, USAGE_EXIT);
|
|
93
|
+
if (opts['--by'].toLowerCase() === 'agent') refuse('SIGNOFF_NOT_HUMAN', 'restarts[].by: restart by agent; a person orders a restart');
|
|
94
|
+
const reason = readVerbatim(opts['--reason-file']).trim();
|
|
95
|
+
if (!reason) refuse('RESTART_USAGE', 'restarts[].reason: the reason file is empty; say why the record restarts', USAGE_EXIT);
|
|
96
|
+
const dir = resolve(positional[0] ?? process.cwd());
|
|
97
|
+
const file = join(dir, 'project.json');
|
|
98
|
+
const notProject = (why: string): never => refuse('RESTART_NOT_A_PROJECT', `${file}: ${why}; restart runs on a create project folder`);
|
|
99
|
+
if (!existsSync(file)) notProject('does not exist');
|
|
100
|
+
const committed = committedRecord(dir, file);
|
|
101
|
+
const release = acquireBoundJobWrite(dir);
|
|
102
|
+
try {
|
|
103
|
+
const original = readFileSync(file);
|
|
104
|
+
if (!original.equals(committed)) refuse('RESTART_SOURCE_CHANGED', 'project.json: changed while restart was validating; retry against the current record');
|
|
105
|
+
let project: JsonObject;
|
|
106
|
+
try {
|
|
107
|
+
const parsed: unknown = JSON.parse(original.toString('utf8'));
|
|
108
|
+
if (!isObject(parsed as Json) || (parsed as JsonObject).schema !== PROJECT_SCHEMA) throw new Error('schema');
|
|
109
|
+
project = parsed as JsonObject;
|
|
110
|
+
} catch { return notProject(`is not a ${PROJECT_SCHEMA} record`); }
|
|
111
|
+
const inputs = { dir, project, refusals: [] as Finding[], warnings: [] as Finding[] };
|
|
112
|
+
checkInputs(inputs);
|
|
113
|
+
const input = inputs.refusals[0] ?? inputs.warnings[0];
|
|
114
|
+
if (input !== undefined) refuse('RESTART_INPUT_INVALID', `${input.path}: ${input.code}: ${input.message}; a restart keeps only inputs the input writer would record, so restore the file or register it again with input add`);
|
|
115
|
+
const gaps = partSetGaps(project.inputs);
|
|
116
|
+
if (gaps.length) refuse('RESTART_PART_SET_INCOMPLETE', `inputs: a kept part set needs its parts.json and its rig with its PNGs, missing ${gaps.join('; ')}; register the missing files with input add, or stop keeping the set`);
|
|
117
|
+
const candidate = freshProjectRecord(typeof project.name === 'string' ? project.name : '', now);
|
|
118
|
+
if (project.name !== undefined) candidate.name = project.name;
|
|
119
|
+
if (project.title !== undefined) candidate.title = project.title;
|
|
120
|
+
if (project.painting !== undefined) candidate.painting = project.painting;
|
|
121
|
+
if (project.same_artwork !== undefined) candidate.same_artwork = project.same_artwork;
|
|
122
|
+
candidate.inputs = project.inputs ?? [];
|
|
123
|
+
candidate.fix_ledger = project.fix_ledger ?? [];
|
|
124
|
+
const entry: JsonObject = { at: new Date(now).toISOString(), by: opts['--by'], reason, previous_record_sha256: createHash('sha256').update(original).digest('hex') };
|
|
125
|
+
candidate.restarts = [...asArray(project.restarts), entry];
|
|
126
|
+
const ledger: Finding[] = [];
|
|
127
|
+
ledgerRows(candidate, ledger, now);
|
|
128
|
+
if (ledger[0] !== undefined) refuse(ledger[0].code, `${ledger[0].message}; a restart keeps every ledger row as written`);
|
|
129
|
+
// The restarted record carries exactly what a fresh init record carries (its open interview) and nothing from the retired one.
|
|
130
|
+
const fresh = checkProject(dir, freshProjectRecord(String(candidate.name ?? ''), now), { now });
|
|
131
|
+
const rejected = newFindings(baselineOf(fresh), checkProject(dir, structuredClone(candidate), { now }).refusals)[0];
|
|
132
|
+
if (rejected !== undefined) refuse(rejected.code, rejected.message);
|
|
133
|
+
writeRecord(file, original, candidate, 'restart');
|
|
134
|
+
const rows = asArray(candidate.fix_ledger).length;
|
|
135
|
+
return {
|
|
136
|
+
stdout: json ? JSON.stringify(entry, null, 2)
|
|
137
|
+
: `restart: project record restarted at stage ${String(candidate.stage)}; kept ${asArray(candidate.inputs).length} input(s) and ${rows} ledger row(s); the earlier record (sha256 ${String(entry.previous_record_sha256)}) is in git history`,
|
|
138
|
+
exit: 0,
|
|
139
|
+
};
|
|
140
|
+
} finally { release(); }
|
|
141
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Private stdin/stdout adapter for the synchronous review writer. */
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { fetchReviewAct, type ReviewActTransport } from './review-act.ts';
|
|
4
|
+
import { Refusal } from './refusal.ts';
|
|
5
|
+
|
|
6
|
+
if (import.meta.main) {
|
|
7
|
+
try {
|
|
8
|
+
const input = JSON.parse(readFileSync(0, 'utf8')) as ReviewActTransport;
|
|
9
|
+
const fetched = await fetchReviewAct(input);
|
|
10
|
+
process.stdout.write(JSON.stringify({ ok: true, bytes: fetched.bytes, stillBytes: fetched.stillBytes }));
|
|
11
|
+
} catch (error) {
|
|
12
|
+
process.stdout.write(JSON.stringify({ ok: false, code: error instanceof Refusal ? error.code : 'REVIEW_ACT_FETCH_REFUSED',
|
|
13
|
+
message: error instanceof Refusal ? error.message : 'project.json.review_acts: fetch failed; restore the live Review job' }));
|
|
14
|
+
process.exitCode = 1;
|
|
15
|
+
}
|
|
16
|
+
}
|