Skip to content
Back to skills

Edda Release

CSecurity

Release Edda across crates.io, GitHub assets, install.sh, and Homebrew without channel drift

  • 36 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 20, 2026
ai-agentspythonrustgoshellbashdockergitapi

Works with

  • cli
  • api

Security analysis

C71/100
  • criticalPipes output to a shell interpreter
  • mediumUses curl or wget to download content
  • criticalDownloads and executes remote scripts — classic supply chain attack

Pro scans all 4 files and shows the line behind each finding

Scanned September 20, 2026

npx -y skills add fagemx/edda --skill edda-release --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Edda Release?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Edda Release
[![Security: C — Skills Directory](https://www.skillsdirectory.com/api/skills/fagemx-edda-release/badge)](https://www.skillsdirectory.com/skills/fagemx-edda-release)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: edda-release
description: "Release Edda across crates.io, GitHub assets, install.sh, and Homebrew without channel drift"
---

# Edda Release

You are Edda's release operator. A release is complete only when every install
path advertised in `README.md` gives users the intended version and its
release-critical commands. A GitHub Release alone is not success.

Since GH-648 (PR #847) the repository automates crates.io publication inside
`.github/workflows/release.yml`: pushing the `v<VERSION>` tag makes CI publish
every workspace crate in dependency order, verify registry provenance against
the tag SHA, and only then create the GitHub Release. The workflow, not this
skill, owns two distribution invariants: both Linux architectures build inside
an Ubuntu 22.04 userspace and reject requirements above `GLIBC_2.35`, and every
checksum sidecar is one exact ASCII line ending in LF. This skill explains and
re-verifies those gates; prose is never a substitute for enforcing them in CI.
Your job shifts from uploading crates to proving the release **before** the tag
push and proving the public channels **after** CI is green.

## Usage

```text
edda-release preflight <version>
edda-release publish <version>
edda-release verify <version>
edda-release recover <version>
```

Parse `args` as an operation plus a bare semantic version such as `0.4.1`.
Reject a leading `v` in the version argument; derive the tag as `v<version>`.

- `preflight`: read-only release readiness and exact-SHA package proof
- `publish`: run the preflight, push the tag, watch CI, then prove every
  advertised channel
- `verify`: read-only public consumer canaries and parity report
- `recover`: inspect a partial release, then resume only missing safe steps

If the operation or version is missing, ask for it. Never guess a version.

## Version selection — preserve runway before 1.0

Edda uses this operator-approved slow pre-1.0 cadence:

- Default compatible fixes and features to the next patch release: after
  `0.6.0`, prefer `0.6.1`, `0.6.2`, and so on.
- Use a new `0.x` minor only for a named cohesive milestone or an intentional
  breaking public CLI, config, ledger, or migration contract. A `feat:` commit
  alone does not force a minor bump.
- `1.0.0` requires an explicit operator decision that the supported CLI/API,
  stored-data migration policy, compatibility floor, and all advertised install
  channels are stable enough to carry a long-lived compatibility promise.
- After 1.0, return to ordinary SemVer: compatible features bump minor and
  breaking changes bump major.

Before proposing a number, read the release range:

```bash
git tag --sort=-version:refname | head -5
git log --oneline "v<PREVIOUS>..origin/main"
```

The operator still names the release version. Surface a mismatch with this
policy, but never silently substitute another number and never infer a bump
from Conventional Commit prefixes alone.

## Non-negotiable invariant

The public contract is the `README.md` Install section. At present it advertises
four surfaces: `install.sh`, Homebrew, crates.io, and GitHub release assets.
Treat any version or behavior mismatch among them as a release blocker.

For crates.io, “published” means all publishable workspace crates at the exact
version are visible, unyanked, carry the frozen tag SHA in
`.cargo_vcs_info.json`, and a plain unversioned `cargo install edda` works.

The crates.io-before-GitHub-Release ordering is enforced by CI: the
`create-release` job runs `python3 scripts/publish-crates.py verify --tag` and
fails unless every publishable crate exists unyanked at the tag version. Do not
re-implement that gate manually — verify it ran.

## Authority boundary

- `preflight` and `verify` are read-only except for disposable build/canary
  directories.
- An explicit `publish <version>` request authorizes pushing the
  `v<VERSION>` tag — which triggers CI publication to crates.io and the
  release workflow — plus the follow-up public canaries.
- It does not authorize yanking a crate, deleting or replacing a tag/release,
  force-pushing, editing or creating repository secrets, copying credentials,
  or merging a PR. Ask separately before any of those actions.
- Never print or read credential contents. Check only whether the
  `CARGO_REGISTRY_TOKEN` secret is configured and whether Cargo authentication
  is available locally.

## Common ground truth

### Step 1: Read repository policy and distribution reality

Read `AGENTS.md` and `.claude/CLAUDE.md` completely, then inspect the actual
install promises and release automation:

```bash
rg -n "cargo install|brew install|releases|install.sh" README.md
git status --short --branch
git fetch origin main --tags
git rev-parse HEAD
git ls-remote --tags origin \
  "refs/tags/v<VERSION>" "refs/tags/v<VERSION>^{}"
gh release view "v<VERSION>" --repo fagemx/edda
gh api repos/fagemx/edda/releases/latest --jq .tag_name
gh secret list --repo fagemx/edda
```

`gh secret list` must show `CARGO_REGISTRY_TOKEN`. Without that secret,
`prepare-crates` skips crates publication **and** every downstream GitHub
Release job while the workflow run still looks green — a silent no-op release.
Treat an absent secret as BLOCKED before pushing anything.

Preserve unrelated changes. Release from a clean commit on current `origin/main`
unless the operator explicitly names another full SHA. For an annotated tag,
the first `ls-remote` hash is the **tag object**, not the release commit; the
receipt's Tag SHA is the peeled `^{}` / `git rev-list -n 1` commit.

### Step 2: Freeze version, SHA, docs, and verification evidence

Require all workspace packages, `Cargo.lock`, `CHANGELOG.md`, and the CLI docs
to describe the same version. `release.yml` extracts release notes from a
CHANGELOG heading that starts exactly with `## [<VERSION>]` — a missing section
fails `create-release` after publication and cannot be repaired without moving
the tag, so it must exist before the push.

```bash
rg -n '^version = "' Cargo.toml          # workspace version == <VERSION>
rg -n "^## \[<VERSION>\]" CHANGELOG.md    # release-notes section exists
<EDDA_BIN> --version                     # must be the just-bumped version
rg -n '^> Documented for edda ' docs/reference/cli.md
EDDA_BIN=<EDDA_BIN> bash scripts/check-cli-docs.sh
```

- `check-cli-docs.sh` (GH-650/GH-795) is the CLI reference drift gate: it
  verifies the documented major/minor version, every verb, and every long flag
  in `docs/reference/cli.md` against the built binary. Build `<EDDA_BIN>` **after**
  the version bump from the candidate commit; a warm binary from the previous
  release can pass the verb/flag checks while hiding a stale `Documented for
  edda 0.x` heading. The old `check_cli_reference.py` no longer exists.
- Package-version parity against the tag is enforced mechanically by
  `publish-crates.py plan` in Step 3, once the local tag exists.
Version bump checklist (every release — do this before the CHANGELOG edit):

```bash
rg -n '^version = "' Cargo.toml                 # workspace version -> <VERSION>
rg '"<OLD>"' crates/*/Cargo.toml                # internal dependency pins
sed -i 's/"<OLD>"/"<VERSION>"/g' crates/*/Cargo.toml
cargo update -w                                  # fails until every pin matches
```

Crate manifests pin internal dependencies with explicit versions, so bumping
only the workspace version makes `cargo update -w` fail with "candidate
versions found which didn't match". Update every pin, resync the lock, and
move the `[Unreleased]` CHANGELOG entries into a `## [<VERSION>] - <date>`
section (release.yml's awk extracts exactly that heading for release notes).

An empty `[Unreleased]` is not evidence that there is nothing to release. When
`git log v<PREVIOUS>..HEAD` is non-empty, reconstruct release notes from the
whole frozen range, group user-visible changes under Added/Changed/Fixed/Docs,
and cross-check every summarized GH/PR reference against the commit subjects.
Empty notes with a non-empty release range are BLOCKED until reconciled.

- Follow the L0/L1/L2 verification ladder in `.claude/CLAUDE.md`. Reuse a valid
  L1 receipt and exact-head CI for the frozen full SHA. Do not rerun the full
  workspace merely to feel safer; run only uncovered focused checks and state
  why.

### Step 3: Commit the prep, prove packaging, then carry it through the ruleset-gated PR

Two ordering facts the flow depends on: `cargo package` refuses a dirty tree
(commit the prep first, then package from the clean release commit), and
`main` is protected by the repository ruleset (`Protect main`: pull-request
rule + required `CI Gate`); the SHA-pinned independent verdict is additionally
bound by `scripts/merge-reviewed-pr.sh`. Direct pushes are declined, so the
prep travels on a branch.

```bash
git checkout -b chore/release-prep-v<VERSION>
git commit -m "chore(release): prepare v<VERSION>"    # hooks run L0
cargo package --workspace --locked --no-verify
cargo publish --dry-run --workspace --locked          # must reach "Uploading edda"
python .claude/skills/edda-release/scripts/test_crates_release_plan.py
python .claude/skills/edda-release/scripts/crates_release_plan.py \
  --version <VERSION> --package-dir target/package --expected-sha <FULL_SHA>
```

The skill-local helper proves each generated `.crate` carries the clean release
commit in `.cargo_vcs_info.json`. Later, `publish-crates.py plan --tag` proves
tag shape, package-version parity, metadata, and dependency order; neither
proof substitutes for the other.

Run repository-root `REVIEW.md` top to bottom for the prep PR. It and
`.claude/CLAUDE.md` exclusively own issue/spec acceptance, Decision lines,
reviewer independence, gate selection, §7 comments, response rounds, and merge
authority; do not restate or weaken those rules here. After the final
current-head §7 LGTM is visible, settle its union and run the merge check:

```bash
edda review deliver --pr <PR> --sha <FULL_SHA>
sh scripts/merge-reviewed-pr.sh <PR>             # check only
# only with explicit operator merge authority:
sh scripts/merge-reviewed-pr.sh <PR> --merge
```

Use a freshly built `edda` that contains the current `review deliver` surface;
a stale global binary fails closed with an unknown-subcommand or unreadable
union. Record `<EDDA_BIN> --version` and put its directory first on `PATH` for
the merge helper when necessary.

After merge, freeze the squash/merge commit and wait for that exact `main` push
CI to go green. That run is the tag target's receipt. If `origin/main` advances
again, do not silently include the later commits or move the frozen target:
keep the reviewed SHA only when it is still an ancestor and the release scope
was already frozen; otherwise ask the operator.

Create the annotated tag locally, then run the plan gate **inside a detached tag
worktree**. This avoids failure when the primary checkout has advanced beyond
the frozen tag. The gate requires HEAD to equal the tag commit on a clean tree,
validates the tag shape, and prints dependency-first order (`python` instead of
`python3` on Windows):

```bash
git fetch origin main --tags
git merge-base --is-ancestor <FULL_SHA> origin/main
git tag -a "v<VERSION>" <FULL_SHA> -m "Release v<VERSION>"
git rev-list -n 1 "v<VERSION>"                  # receipt SHA
git worktree add --detach <TEMP_WORKTREE> "v<VERSION>"
(
  cd <TEMP_WORKTREE>
  python3 scripts/publish-crates.py plan --tag "v<VERSION>"
  python3 scripts/publish-crates-test.py
)
```

Use the detached worktree for later `publish-crates.py verify` too. Use its
default `target/`; do not invent timestamped Cargo target lanes.

`preflight` stops here and reports evidence. Remove only the exact disposable
worktree after verifying its resolved path.

## Operation: publish

### Step 1: Push the tag — the single mutation point

The tag push is what publishes crates.io. Everything before it (preflight) is
the only chance to catch package defects; publication itself is irreversible.

```bash
git push origin "refs/tags/v<VERSION>"
gh run list --workflow release.yml --branch "v<VERSION>" --limit 5
gh run watch <RUN_ID> --exit-status
```

### Step 2: Verify every CI job did its job

Require all five logical stages green — currently nine concrete jobs because
`build-linux-release` and `build-non-linux-release` expand to five legs total.
A green aggregate with a skipped required stage or leg is BLOCKED. Read
`conclusion` and each job result; do not
classify arbitrary warning/error-looking lines from `gh run watch` output as a
workflow failure:

```bash
gh run view <RUN_ID> --json conclusion,jobs \
  --jq '.conclusion, (.jobs[] | [.name,.conclusion] | @tsv)'
```

| Stage | Requirement |
|---|---|
| `prepare-crates` | `enabled=true` (secret present); tag/plan validation passed |
| `publish-crates` | `SUCCESS: all <N> workspace versions verified` |
| `create-release` | parity gate `verify --tag` passed; draft release created from the CHANGELOG section |
| `build-linux-release` + `build-non-linux-release` (5 jobs total) | every platform leg green; Linux x86_64/aarch64 built in Ubuntu 22.04, ABI cap and critical CLI canaries passed; all five archives + `.sha256` uploaded to the draft |
| `publish-release` | exact 10-asset set, no empty assets, each checksum sidecar is exact ASCII+LF and matches its archive, native binary canary without credentials (version core after stripping the optional build identity suffix), release published `--latest` |

Never repair a failed run by moving the tag.

### Step 3: Prove the README Cargo path

Use a fresh Cargo home and install root. Run exactly the public command without
`--version`, `--git`, `--path`, or `--locked`:

```text
cargo install edda --root <FRESH_ROOT>
<FRESH_ROOT>/bin/edda --version
<FRESH_ROOT>/bin/edda dispatch --help
<FRESH_ROOT>/bin/edda verdict --help
```

The version core must equal `<VERSION>`; a registry build may legitimately
print an optional identity suffix such as `(unknown)`. On Windows, retry once
with `--jobs 1` only when rustc itself exits with an OS crash/resource signature such as
`0xc0000005`. A Rust compiler diagnostic, test failure, missing native library,
or wrong CLI behavior is a product failure and must not be relabeled flaky.

Do not declare DONE until this unversioned install canary passes.

### Step 4: Prove install.sh and Homebrew

Run the one-line installer twice in disposable directories: once pinned and
once through its default “latest” path. The option is `--to`, not `--prefix`.
The installer supports Linux/macOS shells, not Windows MINGW; on a Windows
workstation use Ubuntu WSL and perform install plus all canaries in the same
invocation so a WSL restart cannot clear `/tmp` between steps.

```bash
curl -sSf https://raw.githubusercontent.com/fagemx/edda/v<VERSION>/install.sh \
  | sh -s -- --version v<VERSION> --to <PINNED_DIR>/bin
<PINNED_DIR>/bin/edda --version
<PINNED_DIR>/bin/edda dispatch --help
<PINNED_DIR>/bin/edda verdict --help
curl -sSf https://raw.githubusercontent.com/fagemx/edda/main/install.sh \
  | sh -s -- --to <LATEST_DIR>/bin
<LATEST_DIR>/bin/edda --version
<LATEST_DIR>/bin/edda dispatch --help
<LATEST_DIR>/bin/edda verdict --help
```

Both binaries must report the intended version. The release-asset compatibility
baseline is Ubuntu 22.04: CI builds both Linux architectures inside that
userspace and rejects a highest `readelf --version-info` requirement above
`GLIBC_2.35`. Post-publication verification must still download the public
asset, run it on Ubuntu 22.04, and report its observed highest `GLIBC_x.y`;
checking the build directory or trusting the runner label is insufficient. An
asset that fails there is a product failure, never an environmental retry.

Download all ten public assets and run GNU `sha256sum -c` against every
sidecar. A sidecar containing CRLF, a missing final LF, extra lines, a non-ASCII
payload, or anything other than `<64 lowercase hex><two spaces><archive>\n` is
a distribution failure even when the digest value itself is correct.

After crates.io publication is verified, generate the Homebrew formula from the
immutable crates.io source package. The generator downloads and hashes the
`.crate` itself and emits a source-build formula; do not point Linuxbrew back at
a GitHub binary built on `ubuntu-latest`, because its glibc floor can exceed the
Homebrew host's:

```bash
sh scripts/test-update-homebrew.sh
./scripts/update-homebrew.sh <VERSION> <HOME_BREW_TAP_CHECKOUT>
brew audit --strict fagemx/tap/edda
brew install fagemx/tap/edda       # required before reinstall in a fresh verifier
edda --version
edda dispatch --help
edda verdict --help
brew reinstall fagemx/tap/edda
brew test fagemx/tap/edda
```

The generated formula must use the static crates.io `.crate` URL and declare
`pkgconf`/Rust build dependencies plus `openssl@3`; the crates.io API redirect
may return HTTP 403 to Homebrew curl, so do not replace the static URL with
`/api/v1/crates/.../download`.

On Windows, the official disposable `homebrew/brew:latest` Docker image is a
valid Linuxbrew verifier. Tap the **remote public tap**, pin its Git HEAD in the
receipt, and run strict audit, install, reinstall, both CLI help canaries, and
`brew test` in one container:

```bash
docker run --rm homebrew/brew:latest bash -lc '
  set -euo pipefail
  brew tap fagemx/tap
  brew audit --strict fagemx/tap/edda
  brew install fagemx/tap/edda
  edda --version && edda dispatch --help >/dev/null && edda verdict --help >/dev/null
  brew reinstall fagemx/tap/edda
  brew test fagemx/tap/edda
'
```

A local formula mount is suitable while iterating but is not the final
public-channel proof.

Commit and push the tap formula only after its diff names the intended static
crates.io URL, source hash, and build dependencies. If neither a native
macOS/Linux verifier nor the official Docker verifier is available, report
`DONE_WITH_CONCERNS` with the missing public canary.

### Step 5: Record the release receipt

Pin every claim to the tag's full SHA. Use this exact output structure:

```markdown
## Edda Release v<VERSION>

Status: DONE | DONE_WITH_CONCERNS | BLOCKED
Tag SHA: <40-hex>

| Surface | Evidence | Result |
|---|---|---|
| Workspace packages | <N>, version parity (plan ORDER) | PASS/FAIL |
| Preflight package proof | dry-run publish + local provenance SHA | PASS/FAIL |
| Release workflow | run URL, 5 stages / 9 concrete jobs green, none required skipped | PASS/FAIL |
| crates.io | <N> visible and unyanked | PASS/FAIL |
| crates.io provenance | CI VERIFIED lines / verify --tag SHA match | PASS/FAIL |
| cargo install edda | resolved version + critical help canaries | PASS/FAIL |
| GitHub Release | latest endpoint == tag, 10 assets, checksums, native canary | PASS/FAIL |
| install.sh | pinned + latest version canaries | PASS/FAIL |
| Linux asset ABI | documented/minimum baseline + observed glibc floor | PASS/FAIL/NOT RUN |
| Homebrew | remote tap commit + strict audit/install/reinstall/test canaries | PASS/FAIL/NOT RUN |

Failures/retries: <exact command, classification, result>
Remaining action: <none or one concrete next action>
```

Persist the receipt on the release tracking issue (or the strongest PR-visible
carrier when no release issue exists), then write an `edda note` containing the
status, tag commit, workflow run, tap commit, and remaining action. A chat-only
receipt is not durable evidence.

## Operation: verify

Run the public half of the workflow without changing remote state:

1. From the tag worktree, `python3 scripts/publish-crates.py verify --tag
   "v<VERSION>"` — read-only all-crate registry and provenance proof.
2. Repeat the fresh unversioned Cargo canary.
3. Inspect the exact GitHub Actions run (five stages / nine concrete jobs, none
   required skipped), release assets, and checksums; require
   `gh api repos/fagemx/edda/releases/latest --jq .tag_name` to equal the tag.
4. Repeat pinned/latest `install.sh` and Homebrew canaries.
5. Emit the release receipt. Do not say DONE when any README channel is stale.

## Operation: recover

First inventory immutable public state; do not repeat successful mutations.
CI publication is idempotent — `publish-crates.py publish` prints `NO-OP` for
every already-verified crate — so resuming is usually just rerunning failed
jobs:

```bash
git ls-remote --tags origin \
  "refs/tags/v<VERSION>" "refs/tags/v<VERSION>^{}"
gh run list --workflow release.yml --branch "v<VERSION>" --limit 5
gh run view <RUN_ID> --json jobs,conclusion
gh release view "v<VERSION>" --repo fagemx/edda --json isDraft,assets
gh api repos/fagemx/edda/releases/latest --jq .tag_name
# from the detached tag worktree:
python3 scripts/publish-crates.py verify --tag "v<VERSION>"
```

Use the decision table below, then resume at the earliest missing safe step.

| Observed state | Action |
|---|---|
| No tag pushed, nothing published | Return to preflight |
| `prepare-crates` reports `enabled=false` | BLOCKED until the operator configures `CARGO_REGISTRY_TOKEN`, then rerun the whole run (`gh run rerun <id>` without `--failed` — nothing failed; downstream jobs were skipped) |
| Tag pushed, run failed at `publish-crates` | Rerun failed jobs (`gh run rerun <id> --failed`); verified crates are NO-OP |
| Run failed at `create-release` (parity) | Inspect registry with `verify --tag`; rerun only after the cause is gone |
| Run failed at `create-release` (CHANGELOG section missing) | BLOCKED; repair means a new commit and tag — operator decision, never move the tag |
| Run failed at `build-linux-release`/`build-non-linux-release`/`publish-release` | Rerun failed jobs; draft uploads are clobber-safe and re-verified |
| Registry provenance differs from tag SHA | BLOCKED; do not yank or move tag without operator decision |
| Public release exists but a channel is stale | Repair that channel without changing immutable crate/tag identity |

Registry propagation is handled inside `publish-crates.py` (bounded retries and
a 12 × 10 s per-crate poll), so a missing-crate failure there is real, not
lag. After three failures with the same stable cause, stop and report
`BLOCKED` with the exact attempts.

## Anti-patterns

1. **GitHub-only success**: assets existing does not satisfy `cargo install edda`.
2. **Push tag, then hope**: preflight is the only gate before an irreversible
   publication; CI publishes and verifies, but a bad package at the tag is
   unfixable without a new release identity.
3. **Skipped-jobs green run**: `prepare-crates` with no token skips publication
   and the release silently; a green run means nothing unless every job ran.
4. **Publish from a moving checkout**: publication happens in CI from the tag;
   local re-verification only from the exact detached tag worktree.
5. **Root crate only**: all publishable workspace crates must reach crates.io in
   dependency order — enforced by `publish-crates.py` and the parity gate.
6. **Local artifact trust**: verify downloaded registry provenance and public
   install behavior, not only `target/release/edda`.
7. **Retry laundering**: distinguish registry delay or rustc OS crash from a
   deterministic product/compiler failure.
8. **Credential improvisation**: never echo tokens or edit repository secrets
   without explicit authorization.
9. **Destructive recovery**: never yank, delete, recreate, or force-move public
   release identity as an automatic recovery step.
10. **Manual publication drift**: do not run `cargo publish` locally; CI owns
    ordering, provenance, and verification. Local helpers only prove packaging
    and verify public state.
11. **Bump the workspace version only**: crate manifests pin internal
    dependencies explicitly; an unmatched pin fails `cargo update -w` at prep
    time — catch it there, not at the tag.
12. **Package a dirty tree**: `cargo package` and `cargo publish --dry-run`
    refuse uncommitted changes; commit the prep, then prove packaging from the
    clean release commit.
13. **Assume a direct push to main**: the ruleset declines it; budget the prep
    PR, its PR-visible review round, `review deliver`, and merge-gate check into
    the release timeline.
14. **Race toward 1.0**: do not bump `0.x` minor merely because the range
    contains `feat:` commits. Default to patch; reserve minor for a named
    milestone/breaking contract and 1.0 for an explicit stability decision.
15. **Empty Unreleased means empty release**: a non-empty tag range with an
    empty `[Unreleased]` requires reconstructed, cross-checked notes.
16. **Stale warm CLI binary**: the CLI-doc gate must use a binary built after
    the version bump; otherwise the documented-version mismatch stays hidden.
17. **Tag object equals release SHA**: annotated tags have a tag-object hash and
    a peeled commit hash. Receipts and provenance use the peeled commit.
18. **Tag from a checkout that moved**: freeze the reviewed merge SHA and use a
    detached tag worktree; never retarget silently when main advances.
19. **Watch-log diagnosis**: trust run/job conclusions and required success
    markers, not an alarming tail line from `gh run watch`.
20. **Newest-runner Linux means portable Linux**: the host CPU label does not
    define the userspace. Keep both Linux builds in the Ubuntu 22.04 container,
    enforce the `GLIBC_2.35` cap before upload, and run the downloaded asset on
    that baseline after publication.
21. **Fresh `brew reinstall`**: install first, then reinstall; final proof reads
    the remote tap, not only a locally mounted formula.
22. **Normalize checksum files only in the verifier**: accepting CRLF by
    stripping `\r` hides a broken public sidecar. Producers emit ASCII+LF and
    `publish-release` rejects any other byte shape before publishing.

## References

- crates.io publication mechanics: `references/crates-io.md`
- release automation: `.github/workflows/release.yml` (five stages, nine concrete jobs, tag-triggered)
- publication dry-run gate: `.github/workflows/publish-crates-check.yml`
- publish plan/publish/verify script: `scripts/publish-crates.py` (+ its test
  `scripts/publish-crates-test.py`)
- consumer promises: `README.md`
- Homebrew formula generator and regression: `scripts/update-homebrew.sh`,
  `scripts/test-update-homebrew.sh`
- CLI reference drift gate: `scripts/check-cli-docs.sh` (GH-650/GH-795)
- verification ladder and build lanes: `.claude/CLAUDE.md`

Files in this skill

  • SKILL.md25.8 KB
  • references/crates-io.md7.2 KB
  • scripts/crates_release_plan.py14.7 KB
  • scripts/test_crates_release_plan.py4.4 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.