ceremony/lib
cluade-reviewer-andresmgsl 957f72739d 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
..
changelog.sh fix: the sentinel's one-line contract is checked on the file, not the $(cat) word 2026-07-25 13:29:02 +00:00
closes_references.sh feat(forge): replace both gh api graphql sites with REST + a body parser 2026-08-02 18:41:03 +00:00
decide.sh feat: lib/decide.sh — the merge door's decision, pure and exhaustively tested 2026-07-22 18:59:29 +00:00
facts.sh fix(forge): the release doors speak the shim, and an unread fact refuses (#191) 2026-08-04 11:31:06 +00:00
forge-forgejo.sh fix(forge): the release doors speak the shim, and an unread fact refuses (#191) 2026-08-04 11:31:06 +00:00
forge-github.sh fix(forge): the release doors speak the shim, and an unread fact refuses (#191) 2026-08-04 11:31:06 +00:00
forge.sh feat(forge): two backends behind one call surface, and the shim owns paging 2026-08-02 19:00:58 +00:00
ruling.sh feat(forge): timeline normalizer, portable PR activity, shellcheck install (#188) 2026-08-03 15:13:30 +00:00
version.sh feat: lib/version.sh — one version abstraction, two backends 2026-07-22 18:19:50 +00:00