Release Acceptance Guide¶
Use this guide when the question is whether one capstone candidate is reviewable and safe to rehearse locally. The route produces no remote publication and no host installation.
The contract in one diagram¶
flowchart LR
policy["package policy"] --> dist["dist: candidate + checksum"]
dist --> verify["verify-dist: existing-byte checks"]
verify --> install["install-rehearsal: contained mapping twice"]
install --> accept["accept-release: one digest-bound record"]
accept -.not included.-> publish["remote publication"]
Each target has one responsibility:
| Target | May create candidate bytes? | Requires an existing candidate? | Main result |
|---|---|---|---|
dist |
yes | no | archive and SHA-256 sidecar |
verify-dist |
no | yes | candidate acceptance report |
install-rehearsal |
no | yes, already accepted | installed-tree and convergence report |
accept-release |
no | yes, already accepted and rehearsed | bounded release acceptance record |
release-selftest |
creates isolated test specimens | no | acceptance and rejection test results |
release-check |
composes producer and consumer routes | no | locally accepted candidate |
verify-dist, install-rehearsal, and accept-release never invoke the compiler or archive
producer. That separation lets a reviewer inspect failed bytes without replacing them.
Read the governed policies first¶
Before running a target, inspect:
release/package-policy.tsvrelease/install-policy.tsv
The package policy declares archive path, source path, and mode. It selects four payloads
explicitly, so dependency files in build/bin/ cannot enter merely because they share a
directory with executables.
The install policy maps archive paths to logical destinations:
usr/local/bin/
usr/local/include/deep-dive-make-capstone/
usr/local/libexec/deep-dive-make-capstone/
Those paths are materialized below a repository-owned install root. The rehearsal does not
write to host /usr/local.
Produce one candidate¶
From capstone/:
The candidate packet appears below the repository root:
artifacts/release/reproducible-research/deep-dive-make/
└── candidate/
├── deep-dive-make-capstone.tar.gz
└── deep-dive-make-capstone.tar.gz.sha256
Inspect before accepting:
tar -tvzf \
../../../../artifacts/release/reproducible-research/deep-dive-make/candidate/deep-dive-make-capstone.tar.gz
Expected regular files:
deep-dive-make-capstone/app
deep-dive-make-capstone/bin/dyn1
deep-dive-make-capstone/bin/dyn2
deep-dive-make-capstone/include/dynamic.h
scripts/mkdist.py fixes member order, timestamps, ownership, modes, and gzip header
metadata. It writes through a sibling candidate and atomically replaces the public
pathname only after archive creation succeeds.
Verify existing bytes¶
Run:
This gate checks:
- sidecar filename and SHA-256 digest
- exact member equality with package policy
- traversal and absolute-path rejection
- regular-file-only member types
- declared modes
- normalized ownership and modification time
Evidence:
To prove verification is consumer-only:
The second command must pass using the preserved candidate while app, all, and build/
remain absent.
Rehearse contained installation¶
After verify-dist passes:
The rehearsal:
- confirms the acceptance report names the candidate digest
- rechecks archive policy
- rejects symbolic-link ancestors and unowned destination files
- reads payloads without extracting the whole archive
- writes governed files atomically below the install root
- applies the mapping twice
- compares relative paths, modes, and SHA-256 values
Evidence:
artifacts/release/reproducible-research/deep-dive-make/
├── install-root/
│ └── usr/local/
└── evidence/
└── install-acceptance.json
The route proves one contained mapping and rerun convergence. It does not claim package manager ownership, rollback, uninstall, upgrade migration, or privileged host installation.
Bind the local acceptance decision¶
Run:
The target refuses to compose reports that name different candidate bytes. On success it writes:
Read the record carefully. It states:
- the candidate filename and SHA-256 digest
- candidate contract passed
- contained install passed
- install convergence passed
- scope is internal capstone transfer and install rehearsal
- remote publication was not attempted
That last field prevents a local green route from being mistaken for a deployed release.
Run the complete local route¶
This composes:
- runtime product tests
- build-system selftest
- ten release acceptance and rejection tests
- candidate and checksum production
- consumer-only candidate verification
- contained install rehearsal
- digest-bound acceptance
Use release-check when you need the whole local claim. Use the narrower targets while
diagnosing one boundary.
Study rejection paths¶
Run:
The tests use repository artifacts/ for isolated work and prove rejection of:
- candidate bytes changed after checksum creation
- undeclared archive members
- traversal paths
- mode drift
- symbolic-link destination ancestors
- unowned destination files
- mismatched candidate and install reports
They also prove filename-neutral archive bytes and install convergence across complete invocations.
A rejection is successful proof when it blocks the next trust transition for the expected reason.
Review the scripts by responsibility¶
| File | Responsibility |
|---|---|
scripts/release_policy.py |
parse and validate package and install policies |
scripts/mkdist.py |
create deterministic candidate bytes |
scripts/write_release_checksum.py |
bind a SHA-256 sidecar to the candidate filename |
scripts/verify_release_candidate.py |
verify existing identity and archive policy |
scripts/rehearse_release_install.py |
prove contained, convergent installation |
scripts/write_release_acceptance.py |
compose reports that name the same digest |
tests/test_release_candidate.py |
prove archive acceptance and rejection gates |
tests/test_release_install.py |
prove reproducibility and destination behavior |
The scripts are separate because production, verification, installation, and acceptance have different trust roles.
Stop at the supported claim¶
After gmake release-check, you may claim:
- one internal-transfer candidate was produced from governed members
- its exact bytes and archive contract passed
- its install mapping remained contained and converged
- controlled malformed candidates and destinations were rejected
- all acceptance evidence names the same digest
You may not claim:
- source authenticity from an external trust anchor
- signature authorization
- public package completeness
- remote registry publication
- transactional system installation
Those exclusions are part of the release contract, not missing polish.