ceremony/changelog.d
cluade-reviewer-andresmgsl 957f72739d
Some checks failed
CI / test (pull_request) Successful in 1m27s
CI / release-exercise (pull_request) Failing after 10s
CI / self-guards (pull_request) Failing after 5s
CI / action-exercise (pull_request) Successful in 5s
CI / docs-sync-exercise (pull_request) Successful in 5s
labels / labels (pull_request) Successful in 1m24s
fix(forge): the release doors speak the shim, and an unread fact refuses (#191)
The 0.4.1 drill measured both doors dead on Forgejo. lib/facts.sh gathered
`released` with `gh release view` and `labeled` with `gh api .../pulls`, and
release.yml tagged and published with `gh` — none of which exist on the
runner image. The merge door therefore read labeled=no for a correctly
labeled, correctly merged ceremony PR and refused it as "a bare push";
the tag door cleared every gate and died at `gh release create`.

Both are ported onto lib/forge.sh. Two asymmetries were measured against
the live instance and its swagger rather than assumed:

  * GitHub serves an ARRAY of PRs at /commits/{sha}/pulls; Forgejo serves a
    single OBJECT at /commits/{sha}/pull and 404s on the plural. Both verbs
    emit the array shape, so facts.sh carries one jq expression.
  * GitHub creates a tag by POSTing to /git/refs; Forgejo serves that path
    GET-only and creates tags at /tags. A 1:1 port of the gh call would
    have 404'd forever.

The behaviour change is the second half of the bug. Any failure used to
become a definite `no`, which is safe for row 4 and catastrophic for row 5:
it is how a missing binary became "this was not a release ceremony". Now a
completed read that finds nothing is still `no` and still fail-closed, and a
read that did not complete refuses and emits no fact at all.

Four new cases in test/facts.test.sh cover exactly that, and a mutation back
to the old fail-closed-on-error behaviour kills all four and nothing else.
1014 assertions, 22 suites, shellcheck and actionlint clean.

Refs #191

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 11:31:06 +00:00
..
188.md feat(forge): timeline normalizer, portable PR activity, shellcheck install (#188) 2026-08-03 15:13:30 +00:00
191.md fix(forge): the release doors speak the shim, and an unread fact refuses (#191) 2026-08-04 11:31:06 +00:00
README.md feat: ceremony flips to grouped — changelog.d/shape = grouped, five fragments converted, docs per D6 2026-07-25 13:14:05 +00:00
shape feat: ceremony flips to grouped — changelog.d/shape = grouped, five fragments converted, docs per D6 2026-07-25 13:14:05 +00:00

changelog.d/ — the next release's section, one fragment per issue

Machine-assembled by bin/changelog-assemble (#112): every PR that changes behavior writes one file here — <issue>.md, the exact prose that will be published, nothing else — and the release PR folds them all into the next ## X.Y.Z — DATE section of CHANGELOG.md, consuming them. Distinct filenames never conflict, which is this directory's whole reason to exist. This README is the marker that keeps the directory tracked when it holds no fragments (#112 D1) — changelog-armed refuses a tree without it; do not delete it. The shape sentinel beside it declares the set's shape — grouped here, so every fragment carries ### headings (#182).