(motir-core) The sandbox digest table is transcribed BY HAND every release — the lane already computes the exact markdown rows and writes them somewhere only a human can reach
Repo: motir-core. One PR. Every cli-v* release leaves packages/cli/sandbox/README.md stale until somebody notices and retypes nine digests. The data is not missing — the lane already computes it and prints it to a job summary, which is the one place a repository cannot read.
The step that never runs
.github/workflows/release-sandbox.yml's own procedure, step 4:
this workflow builds, smoke-tests, publishes, then pulls each image back by digest; copy its digest table into the sandbox README.
And .github/workflows/sandbox-images.yml:296 already emits exactly the rows the README needs:
echo "| \`${IMAGE}:${name}\` | \`${digest}\` |" >> "$GITHUB_STEP_SUMMARY"
So a machine resolves the digests, formats them as the target markdown, and writes them to a page a person has to open and copy from.
It has been carded once per release, and it still lapsed
| release | how the table got recorded |
|---|---|
cli-v0.1.0 | MOTIR-1883 — a card, 13 comments |
cli-v0.1.1 | MOTIR-2133 — a card, 14 comments |
cli-v0.2.0 | recorded |
cli-v0.3.0 | lapsed — caught only because someone asked whether the sandbox needed updating; PR #2043 |
Four releases, and the recurring cost is a card, a branch, a PR and a review for information the build already had. The failure mode is not "someone was careless" — it is a handoff from a machine to a human across a boundary the machine could have crossed itself.
What stale costs: the table exists so a BYOK user can pin the exact image a run happened in. Stale, it hands them the previous release's digests — the pin still resolves, so nothing errors; they simply get the wrong image, quietly.
Do this
Make the lane write the section it already renders. Shape is open, but two properties are not:
- The digests come from the REGISTRY, read anonymously — the existing
Verify the published images pull ANONYMOUSLYjob already does this, and MOTIR-2220 is on record that the run's job summary is not the authority. Whatever writes the file must use the same source, not a value carried forward from the build. - The two invariants stay CHECKED, not asserted in prose. The section claims (a) each moving
:<profile>resolves to the same manifest as its:<profile>-<version>twin, and (b) every digest differs from the previous release's row. Both are currently verified by hand at transcription time. Automating the table without automating its checks would replace a slow honest process with a fast one that cannot fail.
Two plausible mechanisms, either acceptable: the lane opens a PR against main with the new section prepended, or it commits directly on the tag's merge base. A PR is likelier to fit the repo's manual-merge convention.
Acceptance criteria
- A
cli-v*tag results in the README's § Published images carrying a section for that version without a human editing the file — demonstrated on a real or dry-run release, with the produced diff attached to this card. - The digests written are the ones GHCR returns to an ANONYMOUS pull, and a deliberately wrong digest fails the lane rather than being written.
- Both invariants above are asserted by the lane. Proven falsifiable: a forced same-digest case (or a stubbed one) must FAIL, not warn.
- The previous release's section is demoted to history in the shape the file already uses for
cli-v0.1.1— the sections accumulate, they are not replaced. - If the lane opens a PR, a release with nothing to change opens no PR — a no-op release must not leave an empty pull request behind every time.
Out of scope
The npm side (release-cli.yml), which records nothing in-repo and needs no equivalent. And the decision about what the sandbox README says — this card changes who writes the table, not its content or shape.
Context refs
.github/workflows/release-sandbox.yml— the lane and its manual step 4..github/workflows/sandbox-images.yml— around line 296, where the rows are already formatted.packages/cli/sandbox/README.md§ Published images — the target, and the per-release shape to preserve.- MOTIR-2220 — read the digest from the registry, not the job summary.
- PR #2043 — the
cli-v0.3.0transcription done by hand, i.e. the diff this lane should have produced.