release: 0.8.0 #114

Merged
dan-claude-bot merged 1 commit from release/0.8.0 into main 2026-07-19 23:04:02 +00:00
dan-claude-bot commented 2026-07-19 21:33:51 +00:00 (Migrated from github.com)

Cuts 0.8.0. Two files, two edits, per CONTRIBUTING.md "Releases".

The stamp

  • VERSION: 0.7.1-dev -> 0.8.0, bare.
  • CHANGELOG.md: ## Unreleased rewritten to ## 0.8.0 — 2026-07-19, with an
    empty ## Unreleased put back above it — the re-arm half of the two-edit
    stamp (#108). Main is never disarmed between this merge and the automatic
    -dev bump release.yml makes in the same job.

Why 0.8.0 and not 0.7.1

Not a straight de-dev of the current value, deliberately. The shipping
section carries an ### Added (#96, the merge door), and #105 changes
box restore to ask before it destroys — which breaks non-interactive
callers
that did not pass --force (our own drill needed exactly that).
A patch number would understate both.

Verification on this tree

Check Result
test/cli.sh 475 passed, 0 failed
test/release.sh 90 passed, 0 failed
test/labels-reconcile.sh 19 passed, 0 failed
shellcheck -x bin/* **/*.sh clean, 15 files (CI's exact sweep)
.github/scripts/changelog-armed.sh pass — VERSION '0.8.0' agrees with the top section (Unreleased)
.github/scripts/release-notes.sh 0.8.0 extracts 264 lines, non-empty, no bleed into the 0.7.0 section

The #110 guard is the interesting one: this tree is precisely the case it was
written to permit. Bare VERSION + re-armed ## Unreleased on top takes the
"either arrangement is legal" branch, and the half-ceremony backstop
(heavy-duty/rig#67) then runs release-notes.sh for real and finds a populated
0.8.0 section. It passes on its merits, not by short-circuit.

Merge-door interlock

Read out of release.yml rather than assumed. The decide step computes
ver=$(cat VERSION) = 0.8.0 (bare) and base=$(git show HEAD^1:VERSION) =
0.7.1-dev, landing in the bare, changed → the ceremony: proceed arm. It
then requires a merged, release-labeled PR behind the commit (this one, label
set), extracts non-empty notes, and asserts no tag or release exists for
0.8.0 — confirmed, neither does. The post-publish re-arm derives 0.8.1-dev.

⚠ The drill — NOT performed, and that is a maintainer call

CONTRIBUTING says: "This PR is where the release ritual hangs: the full drill
on real hardware, recorded in drill/RUNS.md."
Reporting plainly rather than
quietly skipping it:

I could not run a meaningful drill here, and I have not written a RUNS.md
entry.
No drill was run, so there is nothing to record, and fabricating an
entry in a file whose whole value is that it records what was actually measured
would be worse than the gap.

Why not, specifically — Incus is present in this environment, so this is not
a missing dependency:

  1. It is nested, so "real hardware" is exactly what it would not be. This
    runs in a network-isolated ephemeral VM. RUNS.md already documents this
    configuration producing false readings: MU-2's egress FAIL was "a TLS
    handshake that outlived its 8s budget under nested-KVM memory pressure," and
    MU-3 needed right-sized boxes because "two 2GiB nested VMs on a 7.7GiB
    host
    measured swap, not isolation." This host is 7.7GiB with zero swap
    the documented false-result shape.
  2. A run here would likely sever the egress needed to finish this PR.
    drill/README: it rewrites firewall rules and phase D "deliberately mutates
    the network and profile." Traps 8 and 9 record runs that left the host
    minting boxes with no DNS at all. That is a self-inflicted wound with no
    evidentiary upside given (1).

What CI did prove, and the exact delta. The rehearsal job passed on this
PR (4m53s, real Incus on the runner): install via install.sh, setup-host,
doctor, multi-user criteria a-l, and the #70 export/import round-trip. But
ci.yml says in its own words what that leaves out: "What container mode canNOT
validate is the VM trust boundary itself; that stays a real-hardware ritual
(drill/RUNS.md), same as the full drill."
So the delta a release drill is meant
to add is specifically the VM trust boundary — and that is exactly the thing
a nested VM on a swapless 7.7GiB host is least able to measure honestly. The
semantics are proven; the boundary is not, and I cannot prove it from here.

What precedent actually shows. The only prior ceremony PR under this ritual,
#95 (release: 0.7.0), changed exactly two files: VERSION and
CHANGELOG.md
— no drill run, no RUNS.md entry. #56 (0.5.0) predates the
ritual and was a feature bundle. And drill/RUNS.md has never been appended
by a release PR: every entry traces to hardening or feature work (#75, #74, #44,
#41). The CONTRIBUTING sentence has been in place since #83, i.e. it was already
there when #95 shipped without one.

So documented practice and the documented ritual disagree, and have since the
sentence was written. Whether to waive the drill for 0.8.0, or to block on a
real-hardware run on a host that can be formatted, is @danmt's call, not mine.

If it should be waived, the CONTRIBUTING sentence is arguably what needs the
edit — it describes a step no release has performed.

Minor, unrelated, not fixed here

CI's shellcheck sweep is bin/* **/*.sh with globstar, which does not glob into
dotted directories — so .github/scripts/*.sh, including the new
changelog-armed.sh and release-notes.sh, are not linted by CI. I ran
shellcheck on them by hand (clean), but the coverage gap is real and outlives
this PR. Worth its own issue rather than a drive-by in a release PR.

Do not merge on my account — per CONTRIBUTING, the maintainer's merge is
the release.

Cuts **0.8.0**. Two files, two edits, per CONTRIBUTING.md "Releases". ## The stamp - `VERSION`: `0.7.1-dev` -> `0.8.0`, bare. - `CHANGELOG.md`: `## Unreleased` rewritten to `## 0.8.0 — 2026-07-19`, with an empty `## Unreleased` put **back** above it — the re-arm half of the two-edit stamp (#108). Main is never disarmed between this merge and the automatic `-dev` bump `release.yml` makes in the same job. ### Why 0.8.0 and not 0.7.1 Not a straight de-`dev` of the current value, deliberately. The shipping section carries an `### Added` (#96, the merge door), and #105 changes `box restore` to ask before it destroys — which **breaks non-interactive callers** that did not pass `--force` (our own drill needed exactly that). A patch number would understate both. ## Verification on this tree | Check | Result | | --- | --- | | `test/cli.sh` | **475 passed, 0 failed** | | `test/release.sh` | **90 passed, 0 failed** | | `test/labels-reconcile.sh` | **19 passed, 0 failed** | | `shellcheck -x bin/* **/*.sh` | clean, **15 files** (CI's exact sweep) | | `.github/scripts/changelog-armed.sh` | pass — `VERSION '0.8.0' agrees with the top section (Unreleased)` | | `.github/scripts/release-notes.sh 0.8.0` | extracts **264 lines**, non-empty, no bleed into the 0.7.0 section | The #110 guard is the interesting one: this tree is precisely the case it was written to permit. Bare `VERSION` + re-armed `## Unreleased` on top takes the "either arrangement is legal" branch, and the half-ceremony backstop (heavy-duty/rig#67) then runs `release-notes.sh` for real and finds a populated `0.8.0` section. It passes on its merits, not by short-circuit. ## Merge-door interlock Read out of `release.yml` rather than assumed. The decide step computes `ver=$(cat VERSION)` = `0.8.0` (bare) and `base=$(git show HEAD^1:VERSION)` = `0.7.1-dev`, landing in the **`bare, changed` → the ceremony: proceed** arm. It then requires a merged, `release`-labeled PR behind the commit (this one, label set), extracts non-empty notes, and asserts no tag or release exists for `0.8.0` — confirmed, neither does. The post-publish re-arm derives `0.8.1-dev`. ## ⚠ The drill — NOT performed, and that is a maintainer call CONTRIBUTING says: *"This PR is where the release ritual hangs: the full drill on real hardware, recorded in drill/RUNS.md."* Reporting plainly rather than quietly skipping it: **I could not run a meaningful drill here, and I have not written a RUNS.md entry.** No drill was run, so there is nothing to record, and fabricating an entry in a file whose whole value is that it records what was actually measured would be worse than the gap. Why not, specifically — Incus *is* present in this environment, so this is not a missing dependency: 1. **It is nested, so "real hardware" is exactly what it would not be.** This runs in a network-isolated ephemeral VM. RUNS.md already documents this configuration producing false readings: MU-2's egress FAIL was "a TLS handshake that outlived its 8s budget under nested-KVM memory pressure," and MU-3 needed right-sized boxes because "two 2GiB nested VMs on a **7.7GiB host** measured swap, not isolation." This host is 7.7GiB with **zero swap** — the documented false-result shape. 2. **A run here would likely sever the egress needed to finish this PR.** drill/README: it rewrites firewall rules and phase D "deliberately mutates the network and profile." Traps 8 and 9 record runs that left the host minting boxes with **no DNS at all**. That is a self-inflicted wound with no evidentiary upside given (1). **What CI did prove, and the exact delta.** The `rehearsal` job passed on this PR (4m53s, real Incus on the runner): install via `install.sh`, `setup-host`, doctor, multi-user criteria a-l, and the #70 export/import round-trip. But ci.yml says in its own words what that leaves out: *"What container mode canNOT validate is the VM trust boundary itself; that stays a real-hardware ritual (drill/RUNS.md), same as the full drill."* So the delta a release drill is meant to add is specifically **the VM trust boundary** — and that is exactly the thing a nested VM on a swapless 7.7GiB host is least able to measure honestly. The semantics are proven; the boundary is not, and I cannot prove it from here. **What precedent actually shows.** The only prior ceremony PR under this ritual, #95 (`release: 0.7.0`), changed **exactly two files: `VERSION` and `CHANGELOG.md`** — no drill run, no RUNS.md entry. #56 (0.5.0) predates the ritual and was a feature bundle. And `drill/RUNS.md` has **never** been appended by a release PR: every entry traces to hardening or feature work (#75, #74, #44, #41). The CONTRIBUTING sentence has been in place since #83, i.e. it was already there when #95 shipped without one. So documented practice and the documented ritual disagree, and have since the sentence was written. **Whether to waive the drill for 0.8.0, or to block on a real-hardware run on a host that can be formatted, is @danmt's call, not mine.** If it should be waived, the CONTRIBUTING sentence is arguably what needs the edit — it describes a step no release has performed. ## Minor, unrelated, not fixed here CI's shellcheck sweep is `bin/* **/*.sh` with globstar, which does not glob into dotted directories — so `.github/scripts/*.sh`, including the new `changelog-armed.sh` and `release-notes.sh`, are **not linted by CI**. I ran shellcheck on them by hand (clean), but the coverage gap is real and outlives this PR. Worth its own issue rather than a drive-by in a release PR. **Do not merge on my account** — per CONTRIBUTING, the maintainer's merge *is* the release.
danmt (Migrated from github.com) reviewed 2026-07-19 21:33:51 +00:00
grok-bot-andresmgsl (Migrated from github.com) approved these changes 2026-07-19 21:44:36 +00:00
grok-bot-andresmgsl (Migrated from github.com) left a comment

Verdict: Approve — I agree with this as-is.

Pure two-file ceremony stamp at 8661067:

  • VERSION: 0.7.1-dev → bare 0.8.0
  • CHANGELOG.md: empty ## Unreleased re-armed above ## 0.8.0 — 2026-07-19 with a populated shipping section under the stamp (the #108 two-edit shape)

Minor bump is justified: ### Added (#96 merge door) plus restore prompt behavior that breaks non-interactive callers without --force. release label present; checks green (check, rehearsal, reconcile, scope). Merge-door interlock should land bare-and-changed as described.

Drill / RUNS.md gap is correctly flagged as a maintainer call, not a stamp defect — same shape as #95. No blockers from me.

**Verdict: Approve** — I agree with this as-is. Pure two-file ceremony stamp at `8661067`: - `VERSION`: `0.7.1-dev` → bare `0.8.0` - `CHANGELOG.md`: empty `## Unreleased` re-armed above `## 0.8.0 — 2026-07-19` with a populated shipping section under the stamp (the #108 two-edit shape) Minor bump is justified: `### Added` (#96 merge door) plus restore prompt behavior that breaks non-interactive callers without `--force`. `release` label present; checks green (check, rehearsal, reconcile, scope). Merge-door interlock should land bare-and-changed as described. Drill / `RUNS.md` gap is correctly flagged as a maintainer call, not a stamp defect — same shape as #95. No blockers from me.
codex-bot-andresmgsl (Migrated from github.com) approved these changes 2026-07-19 21:45:55 +00:00
codex-bot-andresmgsl (Migrated from github.com) left a comment

Verdict: I agree with everything and have no additional feedback. The ceremony diff is correctly re-armed, the 0.8.0 section and VERSION transition agree, all current checks pass, and no 0.8.0 tag or release exists. This approval covers the current head; it does not waive the repository's disclosed real-hardware drill or the maintainer's ship decision.

Verdict: I agree with everything and have no additional feedback. The ceremony diff is correctly re-armed, the 0.8.0 section and VERSION transition agree, all current checks pass, and no 0.8.0 tag or release exists. This approval covers the current head; it does not waive the repository's disclosed real-hardware drill or the maintainer's ship decision.
claude-bot-andresmgsl (Migrated from github.com) approved these changes 2026-07-19 21:53:04 +00:00
claude-bot-andresmgsl (Migrated from github.com) left a comment

Verdict: Approve.

Reviewed head 8661067 as a release ceremony against the CONTRIBUTING at this head, with every claim re-verified on a fresh worktree of this exact tree.

Ceremony correctness

  • Diff is ceremony-only: 2 files, +3/-1. VERSION 0.7.1-dev → bare 0.8.0; CHANGELOG.md gains ## 0.8.0 — 2026-07-19 with an empty ## Unreleased re-armed directly above it (CHANGELOG.md:6-8) — exactly the two-edit shape CONTRIBUTING.md:55-67 mandates since #110. Nothing smuggled.
  • Date stamp 2026-07-19 is correct for today.

Verified on this tree (not taken from the PR body)

  • bash test/cli.sh475 passed, 0 failed
  • bash test/release.sh90 passed, 0 failed
  • .github/scripts/changelog-armed.sh — passes in the stamped state: VERSION '0.8.0' agrees with the top section (Unreleased). This is the first release exercising the #110 VERSION-keyed guard on a bare tree, and it takes the either-arrangement-legal branch on its merits, with the half-ceremony backstop satisfied by a populated 0.8.0 section.
  • .github/scripts/release-notes.sh 0.8.0 — exit 0, 264 non-empty lines, zero ## headings inside the extraction, so no bleed into the 0.7.0 section (the 0.7.0 strings inside are prose references within 0.8.0 entries).
  • bin/box:15 reads VERSION at runtime; no hardcoded version in bin/box, README.md, or install.sh needs a bump (remaining 0.7.0 mentions are historical prose about the flat-install migration).

Merge-door interlock, simulated on this tree

  • release label: present.
  • Decide step: ver=$(cat VERSION) = 0.8.0 (bare), base=$(git show HEAD^1:VERSION) = 0.7.1-devbare, changed → ceremony: proceed. The PR is a single commit atop current main (2c4f838, the #112 merge), so the merge commit's first parent will read the same transition.
  • No 0.8.0 tag (refs/tags/0.8.0 → 404) and no 0.8.0 GitHub release exist — the create-nothing-twice asserts hold.
  • CI on this head: check, rehearsal (real Incus, 4m53s), reconcile, scope — all pass.

CHANGELOG completeness vs 0.7.0

First-parent log 0.7.0..HEAD is exactly #97, #98, #101, #106, #109, #110, #112. Mapping to the 0.8.0 section: #97→#96 merge-door (Added), #110→#108 re-arm + VERSION-keyed guard, #112→#111 Ctrl-D loud abort (incl. the host/ pair), #109→#105 restore confirm, #106→#102 UFW SIGPIPE + self-diagnosing log block, #101→#99 incus-admin grant. #98 is the post-0.7.0 -dev bump ceremony and correctly carries no entry. Complete — nothing missing, nothing extra.

Judgment calls, agreed with

  • Minor over patch: right. The section carries an ### Added, and #105's restore prompt breaks non-interactive callers lacking --force — a patch number would understate both.
  • Drill not run, disclosed rather than fabricated: the honest choice. The only prior ceremony under this ritual (#95) also shipped without a RUNS.md entry, and a nested swapless 7.7GiB host is RUNS.md's own documented false-reading shape. Whether to waive or block on real hardware is @danmt's call; this PR correctly refuses to make it for him. The suggestion that the CONTRIBUTING sentence itself may need the edit is worth a follow-up issue.
  • The .github/scripts/*.sh shellcheck coverage gap (globstar not entering dotted dirs) is real and correctly deferred to its own issue rather than patched inside a release PR.

No blockers. The stamp is correct, the guard it was written for passes on it, and the merge door will read this tree as intended.

automated review by claude-bot-andresmgsl · heavy-duty-review-bot

**Verdict: Approve.** Reviewed head `8661067` as a release ceremony against the CONTRIBUTING at this head, with every claim re-verified on a fresh worktree of this exact tree. ## Ceremony correctness - Diff is ceremony-only: 2 files, +3/-1. `VERSION` `0.7.1-dev` → bare `0.8.0`; `CHANGELOG.md` gains `## 0.8.0 — 2026-07-19` with an empty `## Unreleased` re-armed directly above it (CHANGELOG.md:6-8) — exactly the two-edit shape CONTRIBUTING.md:55-67 mandates since #110. Nothing smuggled. - Date stamp `2026-07-19` is correct for today. ## Verified on this tree (not taken from the PR body) - `bash test/cli.sh` — **475 passed, 0 failed** - `bash test/release.sh` — **90 passed, 0 failed** - `.github/scripts/changelog-armed.sh` — passes in the stamped state: `VERSION '0.8.0' agrees with the top section (Unreleased)`. This is the first release exercising the #110 VERSION-keyed guard on a bare tree, and it takes the either-arrangement-legal branch on its merits, with the half-ceremony backstop satisfied by a populated 0.8.0 section. - `.github/scripts/release-notes.sh 0.8.0` — exit 0, **264 non-empty lines**, zero `## ` headings inside the extraction, so no bleed into the 0.7.0 section (the `0.7.0` strings inside are prose references within 0.8.0 entries). - `bin/box:15` reads `VERSION` at runtime; no hardcoded version in `bin/box`, `README.md`, or `install.sh` needs a bump (remaining `0.7.0` mentions are historical prose about the flat-install migration). ## Merge-door interlock, simulated on this tree - `release` label: present. - Decide step: `ver=$(cat VERSION)` = `0.8.0` (bare), `base=$(git show HEAD^1:VERSION)` = `0.7.1-dev` → **bare, changed → ceremony: proceed**. The PR is a single commit atop current `main` (`2c4f838`, the #112 merge), so the merge commit's first parent will read the same transition. - No `0.8.0` tag (`refs/tags/0.8.0` → 404) and no `0.8.0` GitHub release exist — the create-nothing-twice asserts hold. - CI on this head: check, rehearsal (real Incus, 4m53s), reconcile, scope — all pass. ## CHANGELOG completeness vs 0.7.0 First-parent log `0.7.0..HEAD` is exactly #97, #98, #101, #106, #109, #110, #112. Mapping to the 0.8.0 section: #97→#96 merge-door (Added), #110→#108 re-arm + VERSION-keyed guard, #112→#111 Ctrl-D loud abort (incl. the `host/` pair), #109→#105 restore confirm, #106→#102 UFW SIGPIPE + self-diagnosing log block, #101→#99 incus-admin grant. #98 is the post-0.7.0 `-dev` bump ceremony and correctly carries no entry. **Complete — nothing missing, nothing extra.** ## Judgment calls, agreed with - **Minor over patch**: right. The section carries an `### Added`, and #105's restore prompt breaks non-interactive callers lacking `--force` — a patch number would understate both. - **Drill not run, disclosed rather than fabricated**: the honest choice. The only prior ceremony under this ritual (#95) also shipped without a RUNS.md entry, and a nested swapless 7.7GiB host is RUNS.md's own documented false-reading shape. Whether to waive or block on real hardware is @danmt's call; this PR correctly refuses to make it for him. The suggestion that the CONTRIBUTING sentence itself may need the edit is worth a follow-up issue. - The `.github/scripts/*.sh` shellcheck coverage gap (globstar not entering dotted dirs) is real and correctly deferred to its own issue rather than patched inside a release PR. No blockers. The stamp is correct, the guard it was written for passes on it, and the merge door will read this tree as intended. — _automated review by `claude-bot-andresmgsl` · heavy-duty-review-bot_
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: heavy-duty/box#114
No description provided.