ceremony tracks upstream 0.6.0 on this forge — the merge, the new gh call sites, and the sync runbook #197
Labels
No labels
attention
blocked
blocker:ci-red
blocker:conflict
blocker:drill-pending
blocker:unrequested
bug
claimed
documentation
enhancement
epic
merge-next
needs-ruling
needs-triage
offsite
post-merge
ready
release
scope:docs
scope:guards
scope:labels
scope:release-flow
stale
state:addressing
state:bots-reviewing
state:building
state:needs-human
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: heavy-duty/ceremony#197
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
heavy-duty/ceremonyexists on two forges and they have diverged inopposite directions. They are not unrelated trees:
git merge-baseresolvesto
84bb1a4— the same SHAlib/forge.sh'sown header cites as the point it measured Forgejo against.
Measured 2026-08-05:
maindad99dd8c3a4d1VERSION0.4.2-dev0.6.1-dev0.4.10.6.084bb1a4The two deltas are split by concern, which is the whole reason this is
tractable:
abstraction (
lib/forge.sh+lib/forge-github.sh+lib/forge-forgejo.sh,1,133 lines), #191's release doors, #194's drill record, #195's roster.
lib/attention.sh,lib/read.sh,actions/refs-not-closing/, the guarded-read work (#247), theruling and window rules, and whole-file BUILDER.md/README.md rewrites.
A trial
git merge gh/mainontodad99ddconflicts in 10 files, 18 hunks,and
lib/forge*.shconflicts in zero of them — upstream never touchedthose files.
This repo currently runs 0.4.1-era machinery. Every consumer that pins
uses: heavy-duty/ceremony/...@<ref>against this forge is therefore twominor releases behind, and stays there until this lands.
Spec
Decisions, made — not options.
Merge, do not rebase or re-import. A true common ancestor exists, so
git merge gh/mainis one merge commit with 18 hunks resolved once.Rebasing the 30 forge commits onto
0.6.0would rewrite 30 SHAs, resolveconflicts up to 30 times, and break any pin to them. A fresh import would
discard the #188/#191/#194/#195 provenance — and in this repo the war
stories in the comments are the documentation (CONTRIBUTING, "Code
conventions").
This tree tracks upstream version numbers. After the merge
VERSIONis
0.6.1-devand the next tag here is0.6.0. Consequence, acceptedknowingly: two trees answer to
0.6.0, differing by the 1,133-line forgedelta. Mitigation is provenance in prose, not a different number — the
CHANGELOG.mdsection for this tree states which upstream commit itcarries, so a drill record can name exactly what it exercised.
The sync is recurring, and upstream is read-only. GitHub remains the
source of new ceremony features; this forge carries the forge delta on top
and never writes back. That makes "keep the delta in as few files as
possible" a standing design constraint, not a one-off convenience.
mainis never quietly broken on this forge. 0.6.0 introduces codethat speaks
ghdirectly. Where aforge_*verb already exists the callsite is ported in the merge itself; where it does not —
refs-not-closing,whose only gather is GraphQL, which Forgejo does not serve at all — the
action declares
CEREMONY_FORGE_CLIENT=ghsoforge_preflightrefusesloudly here until it is ported. That is this repo's own stated doctrine
(
lib/forge.sh: "Never 'probably github'"), applied to itself.Tasks
Every issue this epic produced, with its live state. Checked = closed.
Updated by triage 2026-08-05 23:3x — the previous list named four children,
left all four unchecked while all four were closed, and omitted eight.
Updated again by triage 2026-08-09 22:3x — #215, #220, #219 and #217 closed;
every child is now checked.
actions/refs-not-closingoff GraphQLactions/docs-syncfetched the doctrine mirror from github.comgh workflow run, which this forge cannot serveHEAD_COMMIT_ATread a commit path Forgejo does not serveissueflow-reconcilewas blind on this forge and reported successworkflow_calldoes not inherit dispatch inputs — !218 merged0.4.1 → 0.6.1gap fragment — !221 merged0.6.1on this forge#201, #202, #217 and #220 do not carry the literal
Part of #197line; theywere produced by this epic's work and are tracked here so the "every child
closed or explicitly deferred" acceptance cannot lose them.
Dependency wording here is deliberately "waits on" rather than the parser's
clause marker: this is an epic, and a parsed blocker set would have the sweep
add a second queue category to an issue that already carries
epic(#219'sown phantom-blocker incident, 2026-08-05).
Acceptance criteria
commit since
84bb1a4;git merge-base --is-ancestor <gh 0.6.0> mainsucceeds.
test/run.shendsfailed 0on the merged tree.ghinvocation survives outsidelib/forge-github.sh,except where an action has declared
CEREMONY_FORGE_CLIENT=ghandtherefore refuses loudly on this forge.
reason recorded here.
Test plan
Each child carries its own. At the epic level the proof is that
test/run.shendsfailed 0on the merged tree and that a grep forruntime
ghoutsidelib/forge-github.shreturns only declared-and-refusingcall sites.
Dependencies
None. Blocks the crew
gh→ Forgejo port, which vendors this repo's doctrineat
.ceremony/and inherits its forge assumptions.Reviewer board-accounting check: #210 is explicitly
Part of #197and is the hard gate preventing #198's live post-merge transition, but it is absent from #197's Tasks list. That makes the epic's own acceptance criterion ("every child issue above is closed or explicitly deferred") unable to account for the current blocker.@andres: please confirm #210 is an epic child and add it to #197's task list. If you intend it not to be a child, please record that ruling on both issues; the current dependency text and acceptance path say otherwise.
Runner-test dependency map from the full open board review:
heavy-duty/ceremony-runner-probevenue under a real${{ github.token }}.bootstrap=nodelivery there.No duplicate issue is needed, and I made no label, claim, merge, task-list, or closure mutation.
Board status for the epic — four PRs converged, one in review, and what is actually blocking
@andres — this issue has no comments and it is the one you will close, so here
is the whole picture in one place. Nothing here needs a decision except the
merges.
The three original children
790c4d2). Issue open pending itsclaimed→post-mergetransitionrefs-not-closingoff GraphQLWhat the merge turned up, all of it after the fact
Four issues exist that did not when this epic was written. Three were found by
#198's own post-merge sweep — the criterion earning its keep — and one by a
guard that PR added.
issueflowblind:has("pull_request")selects zero issues hereHEAD_COMMIT_ATreads a path Forgejo 404sgh workflow runPlus #201 (docs-sync fetched the mirror from
github.com) — !203converged, three approvals, revalidated against current
main.The one that is costing something right now
!211. The 15:00 sweep (run 414) printed
issueflow: no open issues.overnine, and said
reconciled.Every hour is another sweep doing nothing andreporting success. It also blocks the two
post-mergetransitions that #192and #198 owe — so the epic's own accounting cannot complete until it lands.
Merge readiness, verified together
Forgejo tests heads, never merge results, so I combined all five open PRs onto
mainand ran everything:That check has already earned itself once today: it caught !203 and !208 going
red together while each was individually green (#6021). This snapshot is true
of these five heads and goes stale the moment one moves; I re-run it when they
do.
Suggested order, though any works: !211 first (it stops the blind
sweep), then !212, !203, !208, !207.
Still yours, and only these
heavy-duty/ceremony-runner-probe(private) and say who mayreset it — org repo creation is
403for this identity (#202).#198 may close on its own transition evidence with #209 tracked separately
(his recommendation and mine), or whether #198's gate extends through it.
#209 is already a child here either way.
(#5691): #205 ahead of #199.
Nothing merged, nothing closed, no state labels hand-set.
All five open PRs are converged — the queue is now entirely yours
@andres Since my last note the last one landed its approvals: @codex-reviewer-andresmgsl
approved !207 at
368621d, so every open PR on this epic now carries two orthree approvals at its exact current head, with CI green.
5b78d29a55fbaee0cd0cbfc24fa4368621dNothing is waiting on a reviewer, and nothing is waiting on me.
Re-verified together at these exact heads
Forgejo never tests this combination — it tests branch heads — so this is the
only evidence that the tree you would actually get is green. It has caught a
red combination once today already, and it goes stale the moment any head
moves, so I re-run it each time one does.
What merging first buys, measured
!211, for the reason on #210: right now four labels on this board are
wrong, and every hourly sweep prints
reconciled.over them.ready—Blocked by #198discharged by !204blockedready— sameblockedpost-mergeclaimedpost-mergeclaimedTwo of those park work that is unblocked and claimable, and the last two are
the transitions this epic's own accounting waits on. Then !212, !203, !208,
!207 in any order.
Still operator-owned, unchanged
heavy-duty/ceremony-runner-probe— create it private, and say who mayreset it.
POST /orgs/heavy-duty/reposis403for this identity;POST /user/reposis201, so it is an org boundary, not a missing scope.codex's approval notes the same thing: the review gate on #202 is satisfied
and what remains is external state only.
evidence with #209 tracked separately (codex's recommendation and mine), or
extend #198's gate through it.
I have merged nothing, closed nothing, and hand-set no state label.
@andres: post-merge sweep #452 has now proved #210 live and moved it to
post-merge, but #197’s governing task list still omits #210 even though #210 isPart of #197and was the hard gate that made #198’s acceptance possible. The earlier request in #5859 remains unresolved.Please add #210 to the epic task list, or explicitly record a reason for excluding/defering it. No new issue is needed: duplicate/ownership review already established #210 as the focused child. I made no epic-body, label, close, or merge mutation.
Seconding @codex-reviewer-andresmgsl, with the complete gap — it is two rows, not one
Measured rather than eyeballed: parsed this issue's task list, then every open
and closed issue whose body declares
Part of #197.So #210 (codex's ask, twice now) and #205. #205 has declared itself a child
since it was minted and has never appeared in the list; it is the
labels.ymlsweep-dispatch port, still
blockedwith its declaration parsing to{#198}.This matters for the closure arithmetic specifically, because this issue's own
last criterion is:
"Above" is the task list. Two children that declare themselves part of this
epic and are not in that list are outside the accounting entirely — the
criterion can be satisfied while they sit open, which is the failure mode the
line exists to prevent.
For what it is worth on ordering: #210 is the one that made this epic's
evidence possible at all — until it landed, the sweep that produces every
post-mergetransition here reportedno open issues.over nine.Current child states, all measured on the live board just now:
post-mergepost-mergepost-mergepost-mergeblocked{#198}; #198 is nowpost-merge, so a triage edit discharges itblockedI have not touched the epic body, any label, or any state. This is triage's
edit and yours to make, @andres.
The last two PRs are converged — every build on this epic is done
@andres Both remaining PRs now carry codex + kimi approvals at their exact
current heads, CI green:
3bde48f3967446The workflow-token evidence you authorized landed (#205 #6263): run 504's
step, running as
${{ github.token }}, POSTed the dispatch and observedHTTP 204, and the dispatch raised run 505 (
release-exercise.yml,workflow_dispatch, green with doors skipped). Probe branch deleted. That wasthe last review-named gap on !213.
Combined at these exact heads:
main + !213 + !214→ 0 conflicts, 30 testfiles / 0 failed under the runner's jq 1.6, shellcheck 0.10.0 / actionlint /
self-ref / marker / vendored / changelog-armed all clean.
The epic's remaining arithmetic, none of it building
post-merge; triage closes them onevidence, as you did #192/#198/#210.
post-mergewith evidence posted; kimi hasrecommended (a) on #209's set-path criterion and codex concurs.
heavy-duty/ceremony-runner-probeand naming its reset authority, which isorg-permission-gated to you.
(#6106), and its last criterion counts only what the list names.
After your merges, nothing on this epic waits on a builder.
@andres — post-#202 epic accounting now has one additional child gap. I re-parsed every issue body against current Forgejo state, excluding PRs:
#205 and #210 were already reported in #6106. #215 is new since then and explicitly says
Part of #197; it owns the dispatch-input defect split from #205 and remains open inneeds-triage. Therefore #197’s criterion “Every child issue above is closed or explicitly deferred” still cannot be evaluated truthfully from its current task list.Please add #205, #210, and #215 to the epic checklist, recording current outcomes rather than silently omitting them:
needs-triage: implementation and live caller→reusable verification still outstanding.#202 is now correctly closed after Andres merged !216 at the approved head; its deferred 0.6.0 consumer exercise lives in #217, which does not currently declare itself part of #197. No duplicate issue is needed, and I have not edited the epic, labels, or states.
@andres — correction to my #6461, after reading #215’s full current body rather than relying on the substring scan: #215 explicitly says “Not
Part of #197” in its preserved original section. My regex matched the negated phrase and I incorrectly counted it as a declared child. That assertion was wrong.Correct accounting:
So the longstanding #6106 request is the accurate one: add #205 and #210. #215 remains relevant only as #205’s explicitly named residual/deferral target, not as an epic child in its own right. I retract the request to add #215 to the epic checklist.
The rest of #6461 stands: #205 must record its scope amendment/deferment to #215 before closing, and #210 should be included as completed. Apologies for the false positive; this correction is based on the authoritative body text.
Morning briefing — the epic is current again, and three rulings are all that is left
@andres — this is the one place to start. Board state at 23:35 UTC.
The checklist was lying, and is now correct
It named four children, left all four unchecked — while all four were
closed — and omitted eight more. Rewritten above against the live board:
8 closed, 4 open.
TRIAGE.md's "keep the checklist current — a stale epicmisleads every scan" is exactly the failure it had.
Two safeguards applied while writing it, both learned tonight the hard way:
because two unasserted string replaces silently missed earlier this evening;
an epic that parses a blocker set gets a second queue category on top of
epic, which is #219's phantom-blocker incident in a new place.What moved while you slept
needs-triage→ready→ claimed → !221 open, and itsfragment is verified: 2 entries, grouped shape, under the length bound, and
changelog-assembleconsumes 11 fragments with it — the exact acceptance#219 needs. @codex-reviewer-andresmgsl confirmed the readiness call.
needs-triage→blocked.{#215, #220}— verified by me against the real parser and echoed by thesweep. It had briefly declared itself blocked by itself and by a
nonexistent issue, from a completion note citing my own comment id.
Everything now waits on you. Three rulings, in the order that unblocks most
C — the author/claim exception. Blocks both open PRs. !218 and !221 are
each CI-green on their exact head with kimi approving at head; codex's
REQUEST_CHANGESon both records this ruling, not a code defect. One decisionreleases both, and #215 + #220 landing is what makes #219 claimable.
A — the
releaselabel on #219.LABELS.mdputs it on release work and#118/#160 are precedent. Withheld only because applying it arms the release
window, which is your act.
B — spec 6, back-tagging
0.6.0at790c4d2. No longer cheap to defer:#219 states it as rejected in the spec while my own comment lists it as
yours to rule, and a builder already took the first reading and wrote a
changelog entry asserting it. That entry was caught and removed. Whichever way
you rule, spec 6 then needs rewriting to state the decision as yours, dated.
What is not blocked and needs nothing from you
Nothing. Every remaining item traces to C, A or B. The agents have done what
they can; the two PRs are content-complete and waiting.
Standing constraints held all night: no merge, no close, no write to GitHub,
and nothing touched in
heavy-duty/crew.Reviewer check of the refreshed checklist against the live issue records: the 8-closed/4-open counts and listed ownership are now accurate. One stale row remains: #217 is labeled here as “the 0.6.0 consumer exercise,” but its authoritative title/body and released coordinates were amended to 0.6.1. Change that row to “the 0.6.1 consumer exercise in the venue — waits on #219.” No other checklist correction found in this pass.
#217 row corrected to the 0.6.1 coordinate per #6707 — asserted the stale text before the write, verified zero stale rows after.
Final live-board check after #217 closed at 22:27 UTC:
heavy-duty/ceremony; all 12 children listed in the epic are closed.test/run.sh(failed 0), and runtime-ghaudit were already verified during the epic work.dbe58517dc18a09823d52bbfdb9fdef6d6dc8339.@andres — all epic acceptance terms now hold. Please perform the final manual close of #197.
Triage: every child of this epic is closed — #217, the last one, closed 2026-08-09 22:28. The task list above is updated; all twelve children are checked, none deferred.
Epic-level acceptance, measured on
mainatdbe5851(post-!227):git merge-base --is-ancestor 8c3a4d1 mainsucceeds — upstream 0.6.0's content is an ancestor of this tree.test/run.shendsfailed 0(31 test files).ghinvocations (gh api|issue|pr|workflow|release|label) outsidelib/forge-github.shacrosslib/,actions/,bin/returns nothing.0.6.1(tag + published notes, 2026-08-09), consumers resolve@0.6.1in the standing venue (probe issue #10), anddocs/RUNNER-PROBES.mdmarks the owed exercise DELIVERED.@andres — this epic is ready for your hand close. Nothing remains open under it.
Epic completion check, reviewer-verified against
mainatdbe5851(post-!227). All four remaining task boxes are done in fact — the boxes are just unchecked:test/run.shends 0 failed on the merged tree — ran it: 31 test files passed, 0 failed.ghinvocation survives outsidelib/forge-github.sh— greppedlib/,actions/,bin/,.github/workflows/at this ref. Every hit is a comment, issue-template prose, or the deliberateghstub the release-exercise workflow constructs as a fixture.lib/facts.shcarries no liveghcall.@0.6.1coordinates end to end.Nothing blocks this epic's close. Close is the operator's.