You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(BG0575, CR0545): the documented verified install completes, and a release publishes the assets it verifies against
README and the website offered `SDLC_STUDIO_REQUIRE_CHECKSUM=1` with a pinned tag as the
path for a reader who will not accept an unverified download. It refused, at every version,
for everybody: both installers looked for a `.sha256` beside GitHub's GENERATED source
archive, and GitHub serves no such sidecar for any tag. The digest resolved empty, the
requirement made empty fatal, and the one command offered to that reader was the one command
guaranteed to fail. Nothing exercised it, so it was consumer-facing from the day it was
written and green the whole time.
A tagged version now prefers a release asset built from the tag and published with its digest
in the same automated step, so both halves of the pair are ours and cannot drift. GitHub's
generated archives are deliberately not verified: they are regenerated rather than published,
and a digest recorded for one can stop matching with nobody touching the tag, which reaches a
user as `Checksum mismatch` - indistinguishable from an attack.
CR0545 is the reason it is a workflow and not a command somebody runs. Everything after the
tag was un-tooled: `release_cut.py` stopped at `tag-check` and the runbook had no Release row
at all. That was paid for twice - v4.1.0 published an empty asset list, v5.0.0 was tagged with
no Release at all - and both were somebody meaning to and not doing it. `runbook.py` now
REQUIRES the Release step, so the section cannot be silently dropped the way the step was.
TWO REVIEWS, and the second one rejected this.
The plan review killed the argument this was built on. I justified publishing our own archives
by calling `git archive` deterministic; measured, the same tree yields three different digests
across three plausible invocations, so it is deterministic only with the command pinned. The
real argument is custody - bytes and digest published together, by us - and the build commands
are now pinned to the byte. That review also found the test problem I had called unsolvable was
already solved by a harness in the tree I had not looked for.
The fix review found six blocking defects, two of them mutants I had claimed were killed and
had not executed against the shipped surface:
- The AC5 test ran its OWN `git archive` and never opened the workflow, so it asserted that
git honours `--prefix` - a property of git, not of this repo - and stayed green while the
workflow drifted. It now reads the workflow's command and executes THAT.
- "Aborts before extraction" was unobservable: install.sh deletes its temp directory on exit,
so the test could not tell "never extracted" from "extracted then cleaned up". A `tar` stub
makes the ordering visible, with a positive control proving the successful path reaches it.
- "A 404 and only a 404" was false. `curl -f` exits 22 for EVERY status at or above 400, so a
403, a 429 or a CDN 503 was read as "no asset published" and silently downgraded a default
install to the unverified archive. The status is now read rather than inferred.
- The Windows control compared an uppercase digest against an uppercase digest, so `-ine` to
`-cne` would have survived the only job that checks the PowerShell half while breaking every
real verified install on Windows.
Nine mutants now execute and all nine are killed, with the unmutated suite green beside them.
The PowerShell half is NOT verified locally - `pwsh` is not on this machine - and that is
recorded in the bug rather than implied. It is covered by a green/red/404 trio in the
`windows-smoke` job, which runs `install.ps1` under real PowerShell on every push. A test
asserting over the TEXT of `install.ps1` would be a weaker claim than the criterion and is not
what shipped.
Tags before v5.0.1 have no published assets and still refuse under `REQUIRE_CHECKSUM=1`. The
fix is forward-only and says so rather than widening what counts as verified.
Also: `test_prd_cli_path` leaked the whole plan digest to stdout, so the suite's noise count
moved whenever the lessons ranking or the runbook grew - which is how adding a Release step
turned the tree red. It now captures stdout, as the test directly below it already did.
The stale disclosed-findings count in the v5.0.0 notes (38, against a page carrying 40) is
corrected here rather than left, which is why US0670 is referenced: that page is its Affects.
Refs: BG0575, CR0545, US0670
| Stamp the commit the gate passed on |`release_cut.py record-green --commit <sha> --gate <which>`| a green claim naming no gate |
80
+
| Refuse a tag the gate never covered |`release_cut.py tag-check --version <v>`| tagging on memory |
81
+
| Publish the release and its artefacts | your project's release automation, triggered by the tag | a hand-uploaded artefact, which is the step that gets skipped |
82
+
83
+
Make the publish step something the tag triggers, not a line somebody runs. Where a project offers
84
+
a verified install, the checksum a user verifies against is published by that step, so a release
85
+
that skips it leaves the documented verification broken while everything else looks fine. Two
86
+
releases shipped that way here before it was automated - one with no artefacts attached, one with
87
+
no release entry at all - and both were somebody meaning to and not doing it. The second case is
88
+
the quieter one: `skill-update` asks the forge for the LATEST RELEASE, so until the release entry
89
+
exists, every installed copy still reports the previous version and prompts nobody to upgrade. A
90
+
tag without a release is, to the update mechanism, unreleased.
**Installing in a sensitive environment?** The default install tracks `main`, which publishes no `.sha256` sidecar, so the installer warns and proceeds unverified. Pin a tagged release and make the checksum mandatory instead:
What that verifies: an archive this project built from the tag and published as a release asset, against a `.sha256` published beside it in the same step. Both halves are ours, so they cannot drift apart. Tags before v5.0.1 have no published assets and this command will refuse them rather than pretend - see [Verifying the download](docs/INSTALL.md#verifying-the-download).
0 commit comments