Merge pull request #164 from codex-bot-andresmgsl/build/160-release-0-3-0
release: cut 0.3.0
This commit is contained in:
commit
bc469d9de5
17 changed files with 99 additions and 46 deletions
2
.github/workflows/labels.yml
vendored
2
.github/workflows/labels.yml
vendored
|
|
@ -25,7 +25,7 @@ on:
|
||||||
env:
|
env:
|
||||||
# A called workflow arrives without its repository. Keep this literal pin
|
# A called workflow arrives without its repository. Keep this literal pin
|
||||||
# aligned with the ceremony release consumed by callers (issue #9 D3).
|
# aligned with the ceremony release consumed by callers (issue #9 D3).
|
||||||
CEREMONY_SELF_REF: "0.2.0"
|
CEREMONY_SELF_REF: "0.3.0"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
scope:
|
scope:
|
||||||
|
|
|
||||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
|
|
@ -129,7 +129,7 @@ env:
|
||||||
# `ref:` accepts ${{ env }}; `uses:` strings do not — which is why the
|
# `ref:` accepts ${{ env }}; `uses:` strings do not — which is why the
|
||||||
# shared logic arrives as script files via checkout, not as inner `uses:`
|
# shared logic arrives as script files via checkout, not as inner `uses:`
|
||||||
# references.
|
# references.
|
||||||
CEREMONY_SELF_REF: "0.2.0"
|
CEREMONY_SELF_REF: "0.3.0"
|
||||||
VERSION_SOURCE: ${{ inputs.version-source }}
|
VERSION_SOURCE: ${{ inputs.version-source }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
|
||||||
46
CHANGELOG.md
46
CHANGELOG.md
|
|
@ -7,6 +7,52 @@ fragments — one `changelog.d/<issue>.md` per PR, never an edit to this
|
||||||
file — and the release PR assembles them into the next section here
|
file — and the release PR assembles them into the next section here
|
||||||
(`bin/changelog-assemble`, #112).
|
(`bin/changelog-assemble`, #112).
|
||||||
|
|
||||||
|
## 0.3.0 — 2026-07-24
|
||||||
|
|
||||||
|
- Make `changelog-armed` reject fragment shape drift on the PR that introduces it.
|
||||||
|
- A directive hold now has a written ending, not just a beginning: BUILDER.md's shape 5 says the hold ends where it began — on the labels — with the hold owner's most recent queue-label event governing over any stale prose, the timeline read (`gh api .../issues/{n}/timeline`) named as the move before standing down or up on a hold, a claim against stale prose required to cite the events it read, and a refused claim given its two exits. TRIAGE.md now requires re-reading label events before asserting label-borne state in prose, and makes correcting a lifted hold's stale body header triage's move in the same tick. On 2026-07-24 the unranked signals split two builders reading one board (#149, #151); both acted defensibly — the doctrine, not the builders, lacked the rule (#154).
|
||||||
|
- Doctrine names the second `Closes #N` exception: a same-repo PR whose
|
||||||
|
authorizing issue marks an acceptance criterion post-merge uses `Refs #N`,
|
||||||
|
and triage closes the issue by hand on the evidence — merging #143
|
||||||
|
auto-closed #137 with exactly such a criterion unmet, and no role had been
|
||||||
|
told otherwise. TRIAGE.md now requires a post-merge criterion to carry its
|
||||||
|
own mechanism (post-merge, triage closes, `Refs #N`), REVIEWER.md lists
|
||||||
|
`Refs #N` beside `Closes #N` and `Part of <owner>/<repo>#N` and stops
|
||||||
|
treating the reference-only PR as a defect, and CONTRIBUTING.md points at
|
||||||
|
BUILDER.md as the rule's one home (#151).
|
||||||
|
- FLEET.md — the Reviewers wake describes the deployed sweep, not the `gh search` trigger the bench replaced: the pulls-API `requested_reviewers` sweep across the org plus the named bot forks is source 1, the `repos.txt`/search poll an adds-only backstop, and the two are merged and deduplicated by (repo, PR) before acting. Only the notifier's `needs-ruling` queue remains on paper; `repos.txt` is the registry only on the triage box; and the Status block now stamps the crew ref the file was last reconciled against (#149).
|
||||||
|
- REVIEWER.md now carries the review mechanics every box had been re-deriving from an incident: the queue comes from the API and not the search index, every write is one-shot per (reviewer, PR, head), heads are reviewed in throwaway checkouts, a pinned consumer's config is verified at its pin, and a verdict names the checks its box could not run (#145).
|
||||||
|
- The `docs/CONSUMERS.md` labels-caller stub lists the same `issues:` types
|
||||||
|
as ceremony's own caller — `edited` and `reopened` included — so a consumer
|
||||||
|
adopting the stub wakes when an issue body's `Blocked by #N` declaration is
|
||||||
|
edited, and when a closed issue re-enters the queue wearing labels derived
|
||||||
|
at close. The two lists drifted apart inside PR #32; a parity test now pins
|
||||||
|
them together, red if either file drops a type or the lists diverge.
|
||||||
|
Adopting the widened list is a stub edit riding the pin bump to the first
|
||||||
|
tag carrying this change (#144).
|
||||||
|
- `labels-reconcile` — a queue-cancelled duplicate check is discarded when its context holds a real verdict, so a sibling PR's eviction no longer reds a green PR; an all-cancelled context still blocks (#139).
|
||||||
|
- `blocker:unrequested` now clears the moment the panel is asked: the labels
|
||||||
|
caller (and the `docs/CONSUMERS.md` stub) listens on `review_requested` and
|
||||||
|
`review_request_removed`, so the one event that falsifies the label — or
|
||||||
|
makes it true again — wakes the reconcile sweep instead of waiting for an
|
||||||
|
unrelated push or the advisory cron. The `scope` job skips both events:
|
||||||
|
they change no paths, and running the labeler on them widens the #130
|
||||||
|
clobber window. Adopting the new triggers is a stub edit riding the pin
|
||||||
|
bump to the first tag carrying this change (#137).
|
||||||
|
- `drills/README.md` no longer tells the builder to delete the scratch repo —
|
||||||
|
a step no fleet identity can perform, because `delete_repo` is deliberately
|
||||||
|
absent from bot tokens. The builder's end state is **archive**
|
||||||
|
(`archived: true`, inside the `repo` scope); the delete is the operator's,
|
||||||
|
and cleanup gates nothing — not ready-for-review, not the panel, not the
|
||||||
|
merge. The drill record now names the scratch repo by `owner/name` and
|
||||||
|
states the disposal its author actually observed, never one that has not
|
||||||
|
happened: both 0.2.0 drills hit the missing-scope wall independently, one
|
||||||
|
stalling a release draft on an impossible 403, the other shipping a record
|
||||||
|
asserting a delete that never ran (#135).
|
||||||
|
- `lib/facts.sh` — a repository's first push to `main` (a root commit with no first parent) now reads `base_ver=(none)` and lets decide's table govern, instead of dying at exit 128 before establishing a fact; the no-base path skips the base fetch and `git show`, and an unresolvable head still fails loudly (#134).
|
||||||
|
- The changelog rule now explains why release PRs write no fragment and how entry-worthy changes land instead (#131).
|
||||||
|
- `actions/labels-scope` replaces `actions/labeler@v5` in the labels workflow's scope job: labeler wrote the whole label set (`PUT`) even under `sync-labels: false`, silently removing any label applied while it ran — #128 lost its `release` that way — so the scope job now derives from the same `.github/labeler.yml` mapping (the `changed-files`/`any-glob-to-any-file` shape, block or flow; anything else refuses loudly) and its only write is an additive `POST`. The reconcile sweep also warns — never sets — when a non-draft PR is release-shaped (bare version differing from its base) but carries no `release` label (#130).
|
||||||
|
|
||||||
## 0.2.0 — 2026-07-24
|
## 0.2.0 — 2026-07-24
|
||||||
|
|
||||||
- `test/changelog-assembled.test.sh` — keep the trio interaction aligned with fragment mode: a dropped entry makes armed red too, while a hand-edited section leaves assembled as the sole red (#126).
|
- `test/changelog-assembled.test.sh` — keep the trio interaction aligned with fragment mode: a dropped entry makes armed red too, while a hand-edited section leaves assembled as the sole red (#126).
|
||||||
|
|
|
||||||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
||||||
0.2.1-dev
|
0.3.0
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
- `actions/labels-scope` replaces `actions/labeler@v5` in the labels workflow's scope job: labeler wrote the whole label set (`PUT`) even under `sync-labels: false`, silently removing any label applied while it ran — #128 lost its `release` that way — so the scope job now derives from the same `.github/labeler.yml` mapping (the `changed-files`/`any-glob-to-any-file` shape, block or flow; anything else refuses loudly) and its only write is an additive `POST`. The reconcile sweep also warns — never sets — when a non-draft PR is release-shaped (bare version differing from its base) but carries no `release` label (#130).
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
- The changelog rule now explains why release PRs write no fragment and how entry-worthy changes land instead (#131).
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
- `lib/facts.sh` — a repository's first push to `main` (a root commit with no first parent) now reads `base_ver=(none)` and lets decide's table govern, instead of dying at exit 128 before establishing a fact; the no-base path skips the base fetch and `git show`, and an unresolvable head still fails loudly (#134).
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
- `drills/README.md` no longer tells the builder to delete the scratch repo —
|
|
||||||
a step no fleet identity can perform, because `delete_repo` is deliberately
|
|
||||||
absent from bot tokens. The builder's end state is **archive**
|
|
||||||
(`archived: true`, inside the `repo` scope); the delete is the operator's,
|
|
||||||
and cleanup gates nothing — not ready-for-review, not the panel, not the
|
|
||||||
merge. The drill record now names the scratch repo by `owner/name` and
|
|
||||||
states the disposal its author actually observed, never one that has not
|
|
||||||
happened: both 0.2.0 drills hit the missing-scope wall independently, one
|
|
||||||
stalling a release draft on an impossible 403, the other shipping a record
|
|
||||||
asserting a delete that never ran (#135).
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
- `blocker:unrequested` now clears the moment the panel is asked: the labels
|
|
||||||
caller (and the `docs/CONSUMERS.md` stub) listens on `review_requested` and
|
|
||||||
`review_request_removed`, so the one event that falsifies the label — or
|
|
||||||
makes it true again — wakes the reconcile sweep instead of waiting for an
|
|
||||||
unrelated push or the advisory cron. The `scope` job skips both events:
|
|
||||||
they change no paths, and running the labeler on them widens the #130
|
|
||||||
clobber window. Adopting the new triggers is a stub edit riding the pin
|
|
||||||
bump to the first tag carrying this change (#137).
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
- `labels-reconcile` — a queue-cancelled duplicate check is discarded when its context holds a real verdict, so a sibling PR's eviction no longer reds a green PR; an all-cancelled context still blocks (#139).
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
- The `docs/CONSUMERS.md` labels-caller stub lists the same `issues:` types
|
|
||||||
as ceremony's own caller — `edited` and `reopened` included — so a consumer
|
|
||||||
adopting the stub wakes when an issue body's `Blocked by #N` declaration is
|
|
||||||
edited, and when a closed issue re-enters the queue wearing labels derived
|
|
||||||
at close. The two lists drifted apart inside PR #32; a parity test now pins
|
|
||||||
them together, red if either file drops a type or the lists diverge.
|
|
||||||
Adopting the widened list is a stub edit riding the pin bump to the first
|
|
||||||
tag carrying this change (#144).
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
- REVIEWER.md now carries the review mechanics every box had been re-deriving from an incident: the queue comes from the API and not the search index, every write is one-shot per (reviewer, PR, head), heads are reviewed in throwaway checkouts, a pinned consumer's config is verified at its pin, and a verdict names the checks its box could not run (#145).
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
- FLEET.md — the Reviewers wake describes the deployed sweep, not the `gh search` trigger the bench replaced: the pulls-API `requested_reviewers` sweep across the org plus the named bot forks is source 1, the `repos.txt`/search poll an adds-only backstop, and the two are merged and deduplicated by (repo, PR) before acting. Only the notifier's `needs-ruling` queue remains on paper; `repos.txt` is the registry only on the triage box; and the Status block now stamps the crew ref the file was last reconciled against (#149).
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
- Doctrine names the second `Closes #N` exception: a same-repo PR whose
|
|
||||||
authorizing issue marks an acceptance criterion post-merge uses `Refs #N`,
|
|
||||||
and triage closes the issue by hand on the evidence — merging #143
|
|
||||||
auto-closed #137 with exactly such a criterion unmet, and no role had been
|
|
||||||
told otherwise. TRIAGE.md now requires a post-merge criterion to carry its
|
|
||||||
own mechanism (post-merge, triage closes, `Refs #N`), REVIEWER.md lists
|
|
||||||
`Refs #N` beside `Closes #N` and `Part of <owner>/<repo>#N` and stops
|
|
||||||
treating the reference-only PR as a defect, and CONTRIBUTING.md points at
|
|
||||||
BUILDER.md as the rule's one home (#151).
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
- A directive hold now has a written ending, not just a beginning: BUILDER.md's shape 5 says the hold ends where it began — on the labels — with the hold owner's most recent queue-label event governing over any stale prose, the timeline read (`gh api .../issues/{n}/timeline`) named as the move before standing down or up on a hold, a claim against stale prose required to cite the events it read, and a refused claim given its two exits. TRIAGE.md now requires re-reading label events before asserting label-borne state in prose, and makes correcting a lifted hold's stale body header triage's move in the same tick. On 2026-07-24 the unranked signals split two builders reading one board (#149, #151); both acted defensibly — the doctrine, not the builders, lacked the rule (#154).
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
- Make `changelog-armed` reject fragment shape drift on the PR that introduces it.
|
|
||||||
50
drills/0.3.0.md
Normal file
50
drills/0.3.0.md
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
# 0.3.0 — drill record
|
||||||
|
|
||||||
|
Run 2026-07-24 by `codex-bot-andresmgsl` against release PR #164 head
|
||||||
|
`da186729c5828fb4923e09d26aa2dd0077ec535f`.
|
||||||
|
|
||||||
|
Where: disposable private repo
|
||||||
|
`codex-bot-andresmgsl/ceremony-drill-0.3.0`, carrying the
|
||||||
|
`docs/CONSUMERS.md` release caller and a fragment-mode fixture armed at
|
||||||
|
`0.3.0-dev`. The fixture had `changelog.d/README.md`, one release fragment,
|
||||||
|
and a non-blank drill record. The repository is archived, pending the
|
||||||
|
operator's delete.
|
||||||
|
|
||||||
|
## Candidate-ref deviation
|
||||||
|
|
||||||
|
The pure consumer path cannot resolve `CEREMONY_SELF_REF: "0.3.0"` before
|
||||||
|
the candidate creates that tag. No `0.3.0` branch was created in
|
||||||
|
`heavy-duty/ceremony`. The scratch caller instead used
|
||||||
|
`codex-bot-andresmgsl/ceremony@drill/0.3.0`, whose parent is PR #164 head
|
||||||
|
`da186729c5828fb4923e09d26aa2dd0077ec535f` and whose only additional
|
||||||
|
commit rewrites both `CEREMONY_SELF_REF` carriers to that same canonical
|
||||||
|
candidate SHA. All runtime machinery was therefore fetched from the 0.3.0
|
||||||
|
candidate tree.
|
||||||
|
|
||||||
|
## Probes
|
||||||
|
|
||||||
|
| # | probe | run | result |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 1 | merge-door ceremony | 30111977869 (attempt 1) | ✅ one `0.3.0` release; tag equals merge commit; main re-armed to `0.3.1-dev` with only `changelog.d/README.md` |
|
||||||
|
| 2 | mislabeled ordinary PR | 30111875574 | ✅ green NOTICE no-op; no tag or release |
|
||||||
|
| 3 | bare-version PR without `release` | 30111913669 | ✅ refused at decide; no tag or release |
|
||||||
|
| 4 | re-run completed ceremony | 30111977869 (attempt 2) | ✅ refused because the tag/release already existed; release count stayed one |
|
||||||
|
| 5 | manual matching tag | 30112046066 | ✅ `0.4.0` published with its changelog section; main untouched |
|
||||||
|
| 6 | mismatched tag | 30112072536 | ✅ refused before publication; no `9.9.9` release, and the probe tag was removed afterward |
|
||||||
|
|
||||||
|
The merge-door `0.3.0` tag and PR #3 merge commit were both
|
||||||
|
`b124af56ad713e47175992ca5025db6829b68ed7`. Its release body was exactly:
|
||||||
|
|
||||||
|
```text
|
||||||
|
- Fragment mode is exercised by the 0.3.0 drill.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
The armed fixture was committed before the caller so the first workflow run
|
||||||
|
had a real parent version to inspect. Installing the caller then produced
|
||||||
|
green baseline run 30111822421.
|
||||||
|
|
||||||
|
After the unlabeled bare-version refusal, its merge commit was reverted to
|
||||||
|
restore the armed fixture. That setup correction produced green no-op run
|
||||||
|
30111949683 before the merge-door probe began.
|
||||||
Loading…
Reference in a new issue