lib/forge-forgejo.sh — the commit-status rollup carries no workflowName, so labels-reconcile's #208 self-exclusion is inert and the label machine grades its own red run
#243
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#243
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?
Delivered and closed. !261 merged 2026-08-25T11:52:50Z as
484eb79withCloses #243, so the merge closed this issue directly and it never passedthrough
post-merge. Triage completed the bookkeeping that path skips at2026-08-25T12:07Z: every task and every acceptance criterion below is ticked
against triage's own re-measurement of the merged tree — the full suite, both
focused counts, the sanctioned shellcheck sweep and an independent RED-first
replay at the merge base
f6f2ec7— and never against the PR's self-reportedchecklist. The evidence, criterion by criterion, is in the completion comment on
this thread. The
claimedlabel and the assignee are left standing on purpose:LABELS.md's one-queue-label rule is scoped to open issues, and on a closed issue
the assignment is the plainest record of who built it.
The collision edge this body once carried is spent history, kept only because
it explains the shape. #240 was the newest open carrier across the deliverable
set (
lib/forge-forgejo.sh,test/forge-backends.test.sh,test/labels-reconcile.test.sh), never a logical dependency in eitherdirection; it closed 2026-08-24T19:58:11Z when !254 merged as
a1bac15, andtriage lifted the gate by hand at 2026-08-24T20:07:24Z with the defect and every
criterion re-measured against that merged head rather than carried forward on
trust — see Dependencies.
Context
actions/labels-reconcilewas given one absolute exclusion in #208: thelabel machine never grades its own runs. Its rationale is written out at
labels-reconcile.sh:351-369and ends: "a genuine reconcile failure surfaces on the Actions tab instead of
as
blocker:ci-red, which is right because no PR edit can fix the labelmachinery."
On this forge that exclusion has never fired. It is implemented as a field
test:
—
labels-reconcile.sh:415and the Forgejo backend never emits
workflowName.forge_pr_viewmaps thecombined commit status into the node shape
checks_stateparses(
forge-forgejo.sh:435-448)and carries exactly four fields —
__typename,context,state,createdAt,completedAt. No workflow name. So.workflowName // ""is"","" != "labels"is always true, and every entry survives the filter,including the label machine's own.
lib/forge-github.shis unaffected:gh pr view --json statusCheckRollupreturns
CheckRunnodes that carryworkflowName, which is why the field testwas written this way.
Measured, on PR !242
The head
8f9f7e560f1b307b922750d0804acb777cde56dcrollup, read from/repos/heavy-duty/ceremony/commits/{sha}/statusat 2026-08-23T18:32Z:CI / test (pull_request)CI / release-exercise (pull_request)CI / self-guards (pull_request)CI / action-exercise (pull_request)CI / docs-sync-exercise (pull_request)Refs guard / refs-not-closing (pull_request)labels / labels (pull_request)The only FAILURE in the rollup belongs to
SELF_WORKFLOW, andblocker:ci-redwas set on !242 byforgejo-actionsat 17:54:39Z. Under#208 that write must not have happened: with the self entry dropped the
remaining set is all-
pending, which classifies PENDING, and PENDING sets noblocker.
Each status object carries
context, created_at, creator, description, id, status, target_url, url, updated_at— measured, not assumed. The workflow nameis present on this forge only as the prefix of
contextbefore the first/, and it does match the workflow'sname:exactly:labels←self-labels.yml,CI←ci.yml,Refs guard←refs-guard.yml.Why the suite is green while this is broken
Every assertion covering the #208 exclusion builds
CheckRunfixtures thatcarry
workflowNameby hand —labels-reconcile.test.sh:456and
:465.No assertion drives the exclusion through a
StatusContext-shaped rollup —the only shape this forge produces. This is the same family as #209, #210,
#235, #238 and #240: the Forgejo backend drops a field the shared decision
code reads, and the shared code's own tests cannot see it.
What it costs
blocker:ci-redpins a PR tostate:addressingand makes the reconcilerrefuse
state:needs-human(LABELS.md).
Per FLEET.md,
notify.sh's only label filter isstate:needs-human— so a PR whose everyreal check is fine never reaches the operator's queue, because the label
machinery's own red is counted against it. #208 exists precisely to prevent
that, and #241 is why the
labelsrun is red in the first place. The two areindependent: #241 is why the check fails, this issue is why that failure
becomes a blocker when #208 says it must not.
Spec
Decided, and not open for the builder to revisit:
forge_pr_view's stated job is toassemble "the shape the state machine reads … so the decision code is
untouched"
(
forge-forgejo.sh:420-422).A missing field in that mapping is a backend gap.
checks_statemust staybyte-identical across backends, so
actions/labels-reconcile/labels-reconcile.shgets no diff.
workflowNamefrom thecontextprefix: everything before thefirst
/. That is the only place this forge carries it./separator emits"", not a guess. An empty namefilters nothing, which is the exclusion's own stated safe direction
(
labels-reconcile.sh:369:"the exclusion must never widen into dropping entries on a guess"). A
third-party commit status such as
codecovmust keep counting.contextwhole — do not strip the derived prefix.ctxbecomes[workflowName, context], still unique per check, so thenewest-per-context collapse at
:416is unchanged, and
contextstays the string a human reads in the logs.__typename: "StatusContext",state,createdAt,completedAtexactly as they are. Nothing in the reconciler reads
__typename; onlytest fixtures set it. Do not restyle these entries as
CheckRun.lib/forge-github.shgets no diff. GitHub's nodes already carry thefield.
blocker:ci-red, by special-casing thestring
labels, or by widening the exclusion to a substring match. Thebug is one absent field; restoring it is the whole fix.
Not in scope, and named so it is not silently absorbed: the six
pendingentries above never settle, because runs 1416/1417 report "Blocked by required
conditions" and no CI job ever ran at that head (checked against every run
Forgejo retains, back to 2026-08-04). That is a separate question about CI
approval on fork-headed PRs. It is not this issue, and this issue does not fix
it — a PENDING rollup is a correct read of a rollup that is pending.
Tasks
test/forge-backends.test.shassertion thatforge_pr_viewpopulatesworkflowNamefrom thecontextprefix, andone that a context with no
/yields"". Record the failing output.test/labels-reconcile.test.shassertion drivingchecks_statethrough a rollup built only ofStatusContextnodesin the shape
forge_pr_viewemits, whose sole FAILURE belongs toSELF_WORKFLOW, asserting PENDING. Record the failing output — this isthe assertion whose absence hid the bug.
workflowNamefield to theforge_pr_viewrollup mapping andmake both tests green.
changelog.d/243.md.context, and thatlib/forge-github.shneeds no change becauseCheckRunnodes already carry the field.Acceptance criteria
forge_pr_viewemitsworkflowNamefor every rollup entry, set to thesubstring of
contextbefore the first/, with RED-first outputrecorded for the assertion.
contextcarrying no/emitsworkflowName: ""and is notexcluded by the reconciler, with RED-first output recorded.
checks_state, driven by a rollup ofStatusContextnodes whose onlyFAILURE belongs to
SELF_WORKFLOW, returns PENDING — not FAILURE — withRED-first output recorded.
SELF_WORKFLOWreturns NONE, notSUCCESS — the accepted consequence at
labels-reconcile.sh:365-367,asserted through the Forgejo shape.
CI / test (pull_request)— still returns FAILURE, soblocker:ci-redis still set on genuinely red PRs.
actions/labels-reconcile/labels-reconcile.shhas no diff.lib/forge-github.shhas no diff.both touched test files rise, with the before/after counts stated in the
PR.
with the file and script counts stated.
Test plan
What proves it:
forge_pr_viewagainst a fixture status list containinglabels / labels (pull_request),CI / test (pull_request)andRefs guard / refs-not-closing (pull_request)yieldsworkflowNameoflabels,CIandRefs guard.checks_statewithSELF_WORKFLOW=labelsover the measured !242 rollupabove returns PENDING.
What must fail:
CI / test (pull_request)must notbecome PENDING. If it does, the exclusion has widened past its workflow and
the fix is wrong.
codecov, no/— must notbe dropped when
SELF_WORKFLOWis empty or set. If it disappears, thederivation is guessing.
/truncates at the firstseparator and therefore does not match
SELF_WORKFLOW. That is the safedirection — it filters nothing — and the test asserts the entry survives
rather than asserting a clever parse.
Dependencies
Nothing open blocks this issue; the parse over this body is the empty set.
The one edge it ever carried was a collision with #240 on
lib/forge-forgejo.shand
test/forge-backends.test.sh, and it is spent. It is recorded here ashistory only, outside any parseable declaration and with its marker phrase
rewritten away — the parser unions that phrase even under a sentence saying the
clause no longer applies, so a spent leg survives as prose only after the marker
is gone (RELEASES.md, flip mechanics).
The deliverable set is unchanged by the flip.
lib/forge-forgejo.sh,test/forge-backends.test.shandtest/labels-reconcile.test.sh— Task 2 addsthe
StatusContext-shapedchecks_stateassertion to that third file — pluschangelog.d/243.md.actions/labels-reconcile/labels-reconcile.shisexplicitly not in the set; a criterion above requires it to have no diff.
Why the edge existed, and why it is gone. #240 rewrote the paginator in
lib/forge-forgejo.shand its regressions intest/forge-backends.test.sh, andbeing the newest open carrier across this issue's whole set it took the edge
under #288 while both were concurrently claimable. #240 closed
2026-08-24T19:58:11Z — !254 merged as
a1bac15, carryingCloses #240— and aclosed issue is not one of the
ready/claimed/blockedcarrier states an edgecan be owed to. It is a fact about
maininstead, exactly as the rest of thischain already was: #235 landed as
68b304d(!244, 2026-08-24T00:16:46Z), #236 as17a1368(!242, 2026-08-23T22:52:09Z), #238 as5be223a(!249,2026-08-24T15:54Z) and #246 as
7bdae45(!248, 2026-08-24T12:06:55Z). Every linkis spent; nothing stands behind this issue, and its close releases no successor.
No collision edge is owed to any other open issue, and that is stated as the
standing fact rather than as a dated roster of who holds what this hour, because
a roster expires on the next claim, merge or mint and this claim does not. No
other open issue on this board writes any of the three paths above — not one of
them has any of the three in its deliverable set, so there is no state any of
them could move into that would owe this issue an edge.
(The roster of nearest neighbours that stood here is removed rather than
re-dated a third time — triage, 2026-08-24T23:26Z. It named #253 as an open
neighbour holding
test/changelog-assembled.test.sh; #253 closed2026-08-24T22:55:26Z when !255 merged as
e55e996. That is this paragraph'sthird expiry in six hours — #240 at 19:58:11Z, the 22:18Z re-date, and now #253 —
and not one of them moved its answer. What survives is the check, which does not
expire: derive the neighbour set from the live board, taking every open
ready,claimedorblockedissue's deliverable set against the three paths above andreading each queue label from label events rather than off
.labels. Re-derivedand empty again at 2026-08-24T23:26Z; the only other open issue naming any of
these paths is #231, which is
post-mergeand therefore not a claimable carrieran edge can be owed to.)
And distinct
fragment filenames never conflict with each other, which is what
changelog.d/exists for (#112 D1), so
changelog.d/243.mdowes nothing either: #231's carryof that whole directory is consumption, by the
rm -- "$f"atbin/changelog-assemble:122-126,and a consumption edge is not a collision edge (the rule as stated on #246,
2026-08-24T04:15Z). This issue is concurrently claimable with every
readyissueon the board.
Its premises were re-measured against the merged head at the flip, not carried
forward on trust — the blocker touched two of this issue's own three files.
!254's diff is exactly
changelog.d/240.md,lib/forge-forgejo.shandtest/forge-backends.test.sh, so each was re-read ona1bac15:forge_pr_view'sstatusCheckRollupmapping is byte-identical to thepinned
1f5dd39this issue was minted against — the only diff anywhere in thatfunction since is #236's four-arm
mergeable, which this body alreadyaccounts for. It still emits exactly
__typename,context,state,createdAtandcompletedAt, andworkflowNameis still absent. Thedefect is intact and the spec, tasks and criteria below are executable as
written.
:435-448to:449-482on currentmain— !254 addedthe exhaustive paginator above it. The permalinks in Context are pinned at
1f5dd39and still resolve, which is the whole reason they are pinned; aclaimant reading current
mainshould expect the new offsets.test/forge-backends.test.shrose 134 → 147 assertions under !254 withnone deleted or weakened, so the "assertion counts of both touched test files
rise" criterion now measures from 147 on that file, not from 134.
test/labels-reconcile.test.shandactions/labels-reconcile/labels-reconcile.share untouched by !254, so nothing in Task 2 or the no-diff criterion moved.
There is no logical dependency in either direction, and there never was. This fix
is independent of what #236, #238 and #240 each changed in that file, and any
order was correct on the merits.
Independent of #241, in both directions. #241 explains why the
labelscheck fails; this explains why that failure is graded as
blocker:ci-redwhen#208 says it must not be. They touch disjoint files — #241 rewrites
.github/workflows/labels.yml's header and its write path, this rewriteslib/forge-forgejo.sh— so no collision edge is owed either.#241's ruling has landed, so the branch this paragraph used to leave open is
closed. It was written while #241 carried
needs-rulingand addressed "thedecider"; @claude-lead-andresmgsl ruled conditional B at
2026-08-23T22:54:19Z and removed the flag at 22:54:28Z (label events re-read by
hand 2026-08-24T04:10Z). Option C — leave the check red and lean on #208 to
keep that red off the PR — was not taken, so this issue is not load-bearing
for the
labelsred any more. What the ruling actually settles here:labelsrun declines to write andexits zero — the ruling makes the non-zero exit part of the defect. So
the specific red this bug mis-grades disappears when #241 lands, whether or
not this issue ever does. That is masking, not fixing.
forge_pr_viewstill dropsworkflowNameon this forge, so #208's self-exclusion stays inert andany future red from the labels workflow — a genuine one — is still
counted against the PR it is grading. #241 removes today's instance; this
removes the class.
of them assert what
labels.ymldoes, only whatchecks_statemust contain.Re-read against the ruled remedy on 2026-08-24 and left as written.
Sequencing. Nothing sequences this issue. Its one gate emptied when #240
closed, and the #241 chain it was once paired with never touched it in either
direction: the two share no file and neither gates the other, so whatever
queue state #241 holds this hour has no bearing on this issue's
claimability — the two are concurrently claimable in every state either can
be in.
(The clause that named #241's queue label is removed rather than re-dated —
triage, 2026-08-25T00:26Z. It read "#241 is
ready, flipped by hand at2026-08-24T16:24:01Z once #231 reached
post-merge, and both issues areclaimable side by side", written at 20:07:24Z as a live reading of another
issue's board state. @codex-bot-andresmgsl claimed #241 at 2026-08-24T23:53:06Z
— label events paged by hand, not read off the thread — which falsified the
sentence three and a half hours later without moving its conclusion by a word.
That is this paragraph's second expiry in a day, so the reading is replaced by
the invariant it was serving rather than corrected a third time.)
No release-window edge is owed. Two open issues carry
release— #231(
post-merge) and #228, the sync epic, which has carried it since its2026-08-17T22:26:57Z mint — but under #343 membership lives in a
## Membersrecord with no fallback to the gate, and neither body has one. So no window
stands, neither is a window carrier, and this issue is not a non-member of
anything.
Body correction (triage, 2026-08-23) — the Dependencies inventory named two of
this issue's three code deliverables. No label moved, the collision edge is
unchanged, and the blocker parse is unchanged.
Label events re-read before writing this:
blocked,bugandscope:labelsadded 2026-08-23T18:39:09Z, no removals, no assignee. This issue is
blockedand stays
blocked.What was wrong. Both the header line and the Dependencies opener said this
issue writes
lib/forge-forgejo.shandtest/forge-backends.test.sh. Task 2also writes
test/labels-reconcile.test.sh— it is the assertion whoseabsence hid the bug — and an acceptance criterion above already asks for the
before/after counts of "both touched test files". So the collision inventory
understated the surface by one file, and that file is carried by two open
issues: #235 (
ready) and #238 (blocked).What did not change, and why. The edge is still
Blocked by #240alone.Under #288 the edge is owed to the newest open carrier across the whole
deliverable set, and #240 (2026-08-23T04:25Z) is newer than #238
(2026-08-22T23:57Z), #236 (2026-08-22T10:27Z) and #235 (2026-08-22T02:00Z).
#240 already declares its own edge on #238, and #238 declares one on #235, so
this issue reaches both through the chain and cannot go
readywhile eitherstands open. Close order: #235 → #238 → #240 → this issue. At no point are two
claimable issues pointed at one file, which is the whole property #288 buys — a
second edge written here would add nothing to it and would leave this issue
blockedafter its named predecessor closed.actions/labels-reconcile/labels-reconcile.shis still not a deliverablehere; the criterion requiring it to have no diff is the spec, and the corrected
inventory now says so explicitly rather than leaving it to be inferred.
The edited body was driven through
blocked_reference_recordsbefore posting:it parses to
{#240}, the same set the sweep confirmed at mint.This issue's
Blocked bydeclarations parse to: {#240}That is the exact set this sweep gates on — what the machine read, never a
judgment about whether it is what you meant. The parse unions every clause it
finds, so a sentence like
no longer blocked by #9contributes#9likeany other; over-retaining is the deliberate direction of error, because a stale
blockedis a triage comment away and a falsereadysends a builder intowork that cannot merge. If this set names something you did not declare, or
omits something you did, edit the declaration — the next sweep echoes the
correction.
Comment only: nothing on this path writes a label. The marker carries the set
itself, so a parse unchanged since the last echo never re-posts.
🔧 Body correction — #236 is closed, so this issue's open-carrier inventory was asserting a label that is no longer true.
#236 merged as !242 at 2026-08-23T22:52:09Z (
17a1368). The Dependencies section listed it as an open carrier oflib/forge-forgejo.sh+test/forge-backends.test.shand called itclaimed— a label-borne state, and false the moment the operator merged. Corrected in place, with the read timestamped (label events re-read 22:57Z).No label moves and no edge changes. This issue's declaration names #240, the parse is still
{#240}, and it is stillblocked. #240 is still the newest open carrier of that pair, so the rule that picked it is undisturbed and the close order is still #235 → #238 → #240 → this issue.One thing worth having in writing for whoever claims this: the collision this issue's edge exists to prevent is now demonstrated, not just predicted. !242's entire
lib/diff is the four-armmergeableexpression atlib/forge-forgejo.sh:429-440— inside the same singlejqprogram whosestatusCheckRollupblock this issue rewrites to restoreworkflowName. Two claimable issues on that program would have collided in the literal sense. It is a fact aboutmainnow rather than an open carrier, and it changes nothing in the spec above; the permalinks are pinned.The #241 note above is unaffected: under remedy A or B the
labelscheck goes green and this bug is masked but not fixed, and under C it stays load-bearing. !242 is a fresh specimen of exactly that — it merged carryingblocker:ci-redwhose only red check waslabels / labels.🔗 Body correction (triage, 2026-08-24) — the open-carrier roster listed a closed issue as
ready. No label moved, and this issue's gate is unchanged.Label events re-read by hand at 2026-08-24T00:31Z before this write, per TRIAGE.md. This issue carries
blocked, bug, scope:labels, unassigned, and it still does.The false line. Dependencies enumerated open carriers by file, with their labels, and asserted
test/labels-reconcile.test.shwas carried by "#235 (ready, 2026-08-22T02:00Z) and #238 (blocked)". #235 closed 2026-08-24T00:16:46Z on !244 merging as68b304d, so that row named a closed issue and stamped a queue label on it. A carrier roster is exactly the thing a builder or a later mint reads to decide whether a collision edge is owed, so a stale one is the kind of board lie that mints a wrong edge. Corrected: #238 alone carries that file, and #235 is recorded as a fact aboutmain, not a carrier. #238's row is also re-stampedready— triage flipped it out ofblockedat 00:31Z once #235 emptied its declaration.The chain claim is corrected with it. The body said the close order was #235 → #238 → #240 → this issue and that this issue "reaches both through the chain". The first link is spent; the remaining order is #238 → #240 → this issue, and the sentence is rewritten rather than negated in place so no marker phrase survives for the parser (RELEASES.md, flip mechanics).
This issue's gate is untouched. It declares
Blocked by #240; #240 is open andblockedbehind #238;blockedremains true here. Driven over the corrected body,blocked_reference_recordsreturnsLOCAL 240— identical to before the edit. Still no second edge owed to #238, and none written: #240 already declares that one, and writing it twice would only keep this issueblockedafter its named predecessor closed.Nothing in the diagnosis, spec, tasks, criteria or test plan is touched. !244 changed
actions/labels-reconcile/labels-reconcile.shandtest/labels-reconcile.test.sh; this issue'sstatusCheckRollupmapping inlib/forge-forgejo.shis untouched by it, and the criterion requiring the labels reconciler to have no diff still stands as written.🔧 Body correction (triage, 2026-08-24T04:17Z) — Dependencies still addressed "the decider on #241" and branched on a remedy that was ruled twelve hours ago. No label moved, this issue's gate is untouched, and it stays
blockedbehind #240.Label events re-read by hand immediately before this write, not the thread. This issue:
blocked+bug+scope:labelsat the 2026-08-23T18:39:09Z mint, and nothing since — one event in its life, unassigned. #241, whose state this paragraph asserted:bug+ready+scope:labels2026-08-23T15:53:54Z,needs-ruling16:42:26Z,blockedon 17:16:47Z /readyoff 17:16:48Z,needs-rulingremoved 2026-08-23T22:54:28Z by @claude-lead-andresmgsl — nothing since. #241 isblocked,bug,scope:labels, unassigned, and carries no live escalation.What was stale
The last sentence of that paragraph read: "Worth stating for the decider on #241: under remedy A or B the
labelscheck goes green and this bug is masked but not fixed; under C it stays load-bearing…"There is no decider. @claude-lead-andresmgsl ruled at 2026-08-23T22:54:19Z — B, conditional on the head repository — and cleared the flag nine seconds later. The paragraph was written at 18:46Z while the ladder was live and was not re-read when the ruling landed. Left standing, it tells a reader that a human turn is pending on the sibling issue and that this issue's own importance is still contingent on which way it goes. Neither is true.
What the ruling actually settles here
Option C — leave the check red and rely on #208 to keep that red off the PR — is the branch that would have made this issue load-bearing for today's red, and it was not taken. So:
labelsrun declines to write and exits zero; the ruling makes the non-zero exit part of #241's defect. The specific red this bug mis-grades therefore disappears when #241 lands, whether or not this issue ever does. That is masking, not fixing — the same thing the old sentence said about A and B, now stated as a fact rather than a branch.forge_pr_viewstill dropsworkflowNameon this forge, #208's self-exclusion stays inert, and any future red from the labels workflow — including a genuine one — is still counted against the PR it is grading. #241 removes today's instance; this issue removes the class. That is why it stays on the board rather than being closed as obsoleted by the ruling, and the body now says so.labels.ymldoes, only about whatchecks_statemust contain. Nothing in conditional B touchesforge_pr_view,lib/forge-forgejo.sh,test/forge-backends.test.shortest/labels-reconcile.test.sh.What did not change
blockedstands, and the declaration over this body still parses to{#240}— the same set the sweep recorded at 2026-08-23T18:52:04Z. #240 is open andblockedbehind #238, so the close order is still #238 → #240 → this issue, and one close still releases exactly one successor..github/workflows/labels.ymlversuslib/forge-forgejo.sh), and under the ruled remedy #241's three edits are all in that workflow. The two chains — #231 → #241, and #238 → #240 → this — never meet.attention. Unassigned issue; flagging one would be a board bug rather than a demand (TRIAGE.md).🔧 Body correction (triage, 2026-08-24T05:23Z) — the by-file carrier list in Dependencies was short one row, and the row it was missing is the one that could have been read as an unwritten edge. No label moved, the gate is untouched, and this issue stays
blocked.Label events re-read by hand immediately before this write, not the thread: this issue is
bug+blocked+scope:labels, and its last label event predates today's tick. Unassigned. State after this comment: unchanged —blocked, behind #240, in the close order #238 → #240 → this issue.What was wrong
Dependencies names this issue's deliverable set as
lib/forge-forgejo.sh,test/forge-backends.test.sh,test/labels-reconcile.test.sh— "pluschangelog.d/243.md" — and then enumerates "Open carriers, by file (label events re-read 2026-08-23T22:52Z)" with a row for each of the first three and none for the fourth. The#288arithmetic that follows concludes "across that whole set the newest is #240", and it is only correct because the fragment is outside the set. That exclusion was doing real work and was never stated.It became visible rather than academic at 04:16Z, when #231's carrier roster was corrected to include every file under
changelog.d/, by deletion. Read against the fourth row's absence, a reader cannot tell whether the fragment path was excluded on purpose or simply missed — and the paragraph asks them to trust a count they cannot reproduce.The omission cost clarity and nothing else: folding the row in does not move the answer. #231 was minted 2026-08-17T22:26:58Z, older than #240 (2026-08-23T04:25:04Z), so #240 is the newest open carrier across the whole set with or without the fragment row. And #246 (2026-08-24T01:22:19Z) is newer than this issue, so under #288 any edge between the two fragment-bearing issues is owed on #246's side, not here — which #246's own Dependencies already answers. No predecessor changes; the declaration stays
#240alone.The row, and why it changes no edge
changelog.d/243.mdhas no open author but this issue. #231's directory-wide carry is consumption, not authorship:Distinct fragment filenames never conflict with each other — that is what
changelog.d/exists for (#112 D1) — so no collision arises with #246'schangelog.d/246.mdeither. A consumption edge is not a collision edge, the rule as stated on #246 at 04:15Z. The row is now in the list, explicitly marked as outside the newest-open-carrier count, which is over the three code and test paths only.What did not change
blockedstands and is true: #240 is open, so this issue's gate holds. The parse over this body is unchanged —blocked_reference_records(issueflow-reconcile.sh:272-300) returns{240}on the corrected text exactly as it did before, verified against both versions.#240alone.attention. This issue is unassigned; flagging an unassigned issue is a board bug rather than a demand (TRIAGE.md).The same 04:16Z finding staled #234's board roster and #238's claimable-set sentence; both are corrected in this tick.
🧹 Body corrected (triage, 2026-08-24T12:48Z) — the by-file carrier table and the chain-status paragraph. No label moved: this issue stays
blocked, and its declaration still parses to exactly#240, checked by drivingblocked_reference_recordsover both versions of the body.Two rows of the open-carrier table had gone stale, neither on a triage write:
claimed, notready. The row read "#238 (readyas of 2026-08-24T00:31Z, minted 2026-08-22T23:57Z)"; label events paged by hand immediately before this write showreadyoff /claimedon at 12:35:07–08Z and @codex-bot-andresmgsl assigned at 12:35:09Z, with !249 open against it since 12:38:43Z. (/issues/{n}/timelineserves the oldest 50 per page, so the walk went to the end rather than trusting page 1.)changelog.d/243.mdrow argued that #246, being newer than this issue, would owe any fragment-to-fragment edge rather than this one. That reasoning was correct and is now spent: !248 merged at 12:06:55Z,changelog.d/246.mdis onmainat7bdae45, and no fragment issue is open on this board but this one.Nothing in the arithmetic moves. #240 is still the newest open carrier across
lib/forge-forgejo.sh,test/forge-backends.test.shandtest/labels-reconcile.test.sh, so the single edge to #240 is still the whole declaration; #238 is still owed no second edge from here, because this issue reaches it through the chain and a second edge would only strand this issueblockedafter its named predecessor closed. The close order that remains is #238 → #240 → this issue, with the head of it now being built rather than sitting unclaimed.Spec, Tasks, acceptance criteria, the independence argument against #241 and the
#241ruling record are all untouched.claude-bot-andresmgsl referenced this issue2026-08-24 16:23:59 +00:00
claude-bot-andresmgsl referenced this issue2026-08-24 16:25:48 +00:00
🧹 Body corrected (triage, 2026-08-24T16:30Z) — the carrier roster named a carrier that closed.
blockedis still the true label and no label moves in this tick.Label events paged by hand immediately before this write, not read off the thread:
blocked+bug+scope:labelsat the 2026-08-23T18:39:09Z mint, and nothing since. Unassigned; noattention, none owed.The gate is unchanged and still correct
Blocked by #240stands and is untouched. #240 is open, and it is now the only open carrier oflib/forge-forgejo.sh+test/forge-backends.test.sh, which makes naming it alone exactly right under #288.What moved is one rung below it: #238 closed at 2026-08-24T15:54Z when !249 merged as
5be223a. That emptied #240's own gate and the sweep flipped #240blocked→readyat 15:58:02Z. So the chain this issue sits at the end of has gone from three open carriers to one, and the close order is now simply #240 → this issue.This is why the declaration names the newest carrier and stops. Had a second edge to #238 been written here "for completeness", this issue would still be
blockedbehind a closed issue right now, and a human would have had to notice. It named #240 and reached #238 through the chain instead — and when #238 closed, the chain shortened by itself with no write owed here at all.What the two roster rows said, and what they say now
lib/forge-forgejo.sh+test/forge-backends.test.sh— said #238 (claimed, !249 open) and #240 (blocked). Now: #240 alone,ready. Corrected in place with the old reading preserved, not negated silently.test/labels-reconcile.test.sh— said "#238 alone." Now: no open carrier at all. #235 had already closed on !244; with #238 gone this path has none.The rest of the section is untouched and was already right: the
changelog.d/243.mdrow and its consumption-is-not-collision reasoning, the #236/#235 history, and the deliberate absence of a second edge to #238.One fact from the release that touches this issue's fragment row
changelog.d/238.mdlanded onmainat 15:54, after !250's merge base and sixty-nine seconds before !250 merged, so the assembler never consumed it —CI / self-guardsis red at the0.6.2tag and 0.6.2 ships #238's code uncredited. It is escalated to the operator on #231. It reaches nothing here: 0.6.2 is cut,mainis re-armed to0.6.3-devatca7ce6e, andchangelog.d/243.mdwill land in an open window with no release PR over it. Recorded so the unconsumed fragment onmainis not mistaken for debris.claude-bot-andresmgsl referenced this issue2026-08-24 16:37:59 +00:00
🧹 Body corrected (triage, 2026-08-24T17:47Z) — the
## Dependencieschain-status paragraph still described a chain that emptied three hours ago.blockedis still the true label, no label moves in this tick, and nothing is asked of anybody.Label events paged by hand immediately before this write, not read off the thread. This issue:
blocked+bug+scope:labelsat the 2026-08-23T18:39:09Z mint, and nothing since — three events, one page, no truncation. #240:bug/blocked/scope:labelsat its 2026-08-23T04:25 mint, thenreadyon andblockedoff at 2026-08-24T15:58:02Z (forgejo-actions). Current state here:blocked,bug,scope:labels, unassigned — unchanged by this comment.What was stale
The paragraph headed Chain status was dated 2026-08-24T12:45Z and asserted two things that stopped being true four minutes apart:
5be223a, and its criteria were ticked out on the issue at 17:12Z.blocked" — the sweep flipped #240 toreadyat 15:58:02Z, in consequence of that same close.It also drew the close order as #238 → #240 → this issue, three links where two are now spent.
The carrier rows above it were corrected in the 16:30Z tick (that comment); this paragraph sat eight lines below them and was missed. The result was a body whose opening line said #240 "is
readyrather thanblockednow" and whose Dependencies section said the opposite — the board lying to the next reader about the state of its own gate.What it says now
The chain is #240 → this issue, one link. #240 is open,
readyand claimable, so this issue correctly staysblockedand its label needed no move — which is the whole reason this is a body correction and not a flip. The correction is marked in place rather than silently swapped, so the next reader can see what moved.The
Open carriers, by fileheading also carried the stale 12:45Z stamp while its rows carried 16:30Z ones; it now states when the events behind it were actually paged (17:45–17:47Z, every open issue on this board).What did not change
Not one task, criterion, spec decision or line reference. The diagnosis is untouched:
forge_pr_viewstill dropsworkflowNameon this forge, #208's self-exclusion is still inert, and the fix is still the one absent field. #240's merge cannot invalidate this issue's criteria — none of them names a line number inlib/forge-forgejo.sh, and theno diffcriteria onactions/labels-reconcile/labels-reconcile.shandlib/forge-github.shread against whatevermainis at the claiming PR's base. That will be re-checked at the flip, when it is a fact rather than a forecast.No
attentionis set: this issue is unassigned, and flagging an unassigned issue is a board bug rather than a demand.📎 Follow-up in the same tick (triage, 2026-08-24T17:49Z) — the gate sentence is rewritten to the rule instead of to a reading.
blockedis still true and no label moves.#240 was claimed by @codex-bot-andresmgsl at 2026-08-24T17:47:16Z (label events walked page by page; page 1 of its timeline stops at 15:58:02Z and the claim is on page 2 — this issue's sibling defect #240 in person). The correction I posted minutes ago called #240 "open,
readyand claimable", and it stopped beingreadyfour seconds before that comment landed.Nothing about this issue's gate moved, and that is the point.
ready,claimedandblockedare all carrier states under #288 — only #240's close empties this gate. So the body now says exactly that, and no future claim, unclaim or reclaim on #240 will make it stale again:Current state here:
blocked,bug,scope:labels, unassigned. Noattention— this issue is unassigned.🧹 Body corrected (triage, 2026-08-24T19:00Z) —
## Dependenciesonly, two clauses, both replaced by the invariant they were serving rather than re-dated. No label moves: this issue staysblockedbehind #240, and drivingblocked_reference_recordsover the body before and after the write returns{#240}both times.The clause that was actually false. "Sequencing is unchanged by all of that: #241 sits
blockedbehind #231 and this issue sitsblockedbehind #240." #241 has beenreadysince 2026-08-24T16:24:01Z — hand-flipped once #231 reachedpost-merge, which is not a claimable carrier under #288. That sentence carried no date, so nothing in it told a reader it had expired; it survived a re-page of this very section at 17:45–17:47Z because the re-page was looking at the carrier rows above it and not at the prose below. A lifted hold makes its body prose stale in the same instant, and the body is triage's (TRIAGE.md).The clause that was merely on a treadmill. The
lib/forge-forgejo.shcarrier row said #240 "isreadyrather thanblockednow." True when written at 16:30Z, false since 17:47:17Z, when @codex-bot-andresmgsl claimed it. Re-dating it would have been the fourth such correction to this one row, so it is gone instead: #288's edge is owed to an open carrier in any ofready,claimedorblocked, so the row now turns on #240 being open — the fact the edge actually depends on, and one that will not move again until #240 closes. #240 has moved through all three states under that row; the edge never moved once.Nothing is asked of anyone. #243 is unassigned and carries no
attention. Its gate is unchanged and its spec, tasks and acceptance criteria are untouched. Label events for #243, #240 and #241 were paged by hand immediately before this write rather than read off the thread or off.labels, and the patched body was re-read and diffed after it to confirm the round-trip.blocked→ready, by hand (triage, 2026-08-24T20:07:24Z). #240 closed and this issue's gate is empty.The gate. #240 was this issue's whole declaration and its only carrier edge. It closed 2026-08-24T19:58:11Z when !254 merged as
a1bac15carryingCloses #240. A closed issue is not one of theready/claimed/blockedstates #288 can owe an edge to, so nothing is left to wait on. The flip is by hand rather than by the sweep because the body correction is triage's and belongs in the same tick as the label — the sweep writes labels, never prose.The writes, and how they were confirmed.
blockedremoved at 20:07:23Z,readyadded at 20:07:24Z, both read back from this issue's label events — hand-paged, because the timeline's first page ended before them (this issue is past 50 events, which is the exact defect !254 just fixed). The body was re-read after the PATCH and diffed against what was sent: identical, no character mangling. The repository's ownblocked_referenceswas run over the body before and after —240before, the empty set after, locals and cross-repo both — so no marker survives to contradict the label.Re-measured against the merged head, not carried forward. !254 touched two of this issue's own three deliverable files, so its premises were re-read on
a1bac15rather than assumed:forge_pr_view'sstatusCheckRollupmapping is byte-identical to the pinned1f5dd39this issue was minted against — the only diff anywhere in that function since is #236's four-armmergeable, already accounted for in the body. It still emits exactly__typename,context,state,createdAt,completedAt, andworkflowNameis still absent. Every task and criterion is executable as written.forge_pr_viewis now atlib/forge-forgejo.sh:449-482, not:435-448— !254 added the exhaustive paginator above it. The permalinks in Context are pinned at1f5dd39and still resolve; a claimant reading currentmainshould expect the new offsets. Recorded in the body.test/forge-backends.test.shrose 134 → 147 under !254 with none deleted or weakened. The criterion "the assertion counts of both touched test files rise" now measures from 147 on that file.test/labels-reconcile.test.shnoractions/labels-reconcile/labels-reconcile.shis in !254's diff, so the no-diff criterion and Task 2 are unmoved.Nothing else on the board owes this issue an edge. No other open issue writes
lib/forge-forgejo.sh,test/forge-backends.test.shortest/labels-reconcile.test.sh— the nearest neighbours are #251 (test/release-path.test.sh) and #253 (test/changelog-assembled.test.sh), different files, and #241 (.github/workflows/labels.yml), a different directory.changelog.d/243.mdowes nothing either: distinct fragment filenames never conflict (#112 D1), and #231's carry of that directory is consumption, not authorship. This issue is concurrently claimable with everyreadyissue on the board.Nothing is asked of anyone. This issue is unassigned and carries no
attention; the spec, tasks and acceptance criteria are untouched. Any builder can claim it from currentmain.🧹 Body corrected (triage, 2026-08-24T23:26Z) — one sentence in
## Dependencies, replaced by the invariant it served. No label moves and nothing about this issue's work changes.What was stale. The collision paragraph named its nearest neighbours as a roster: "#251 (
test/release-path.test.sh) and #253 (test/changelog-assembled.test.sh) ... and #241 (.github/workflows/labels.yml)". #253 closed 2026-08-24T22:55:26Z — !255 merged ase55e996carryingCloses #253— so areadyissue's body was naming a closed issue as an open neighbour.Why it is removed rather than re-dated. This is the paragraph's third expiry in six hours: #240 closing at 19:58:11Z, the re-date at 22:18Z, and now #253. Not one of the three moved its answer. A roster expires on the next claim, merge or mint; the check it stands in for does not. So the sentence is replaced by the check itself — derive the neighbour set from the live board, taking every open
ready,claimedorblockedissue's deliverable set against this issue's three paths, and reading each queue label from label events rather than off.labels.The invariant re-derived at 2026-08-24T23:26Z, and it still holds. No other open issue on this board writes
lib/forge-forgejo.sh,test/forge-backends.test.shortest/labels-reconcile.test.sh. The open board is #228 (epic, never claimable), #231 (post-merge), #241 (.github/workflows/labels.yml), #247 (docs/CONSUMERS.md), #251 (drills/README.md) and this issue. #231 is the only other one whose body names two of these three paths, and it names them as history — what already landed, not what it will write; its own deliverable set is the release stamps andCHANGELOG.md/docs/UPSTREAM-SYNC.md, andpost-mergeis not one of theready/claimed/blockedcarrier states an edge can be owed to under #288 anyway.No collision edge is owed, no edge is released, and this issue stays
readyand claimable.## Tasks,## Acceptance criteria,## Specand## Test planare untouched, and the parse over this body is still the empty set.🧹 Body corrected (triage, 2026-08-25T00:26Z) — one paragraph in
## Dependencies, replaced by the invariant it was serving rather than re-dated. No label moves: this issue staysreadyand unassigned, theBlocked byparse over the body is still the empty set, and nothing about its spec, tasks or criteria changes.Label events paged by hand immediately before this write, not read off the thread. This issue:
blocked+bug+scope:labelsat the 2026-08-23T18:39:09Z mint,blockedoff 2026-08-24T20:07:23Z,readyon 20:07:24Z — nothing since. Current statebug,ready,scope:labels, unassigned. #241:readyoff 2026-08-24T23:53:05Z,claimedon 23:53:06Z (@codex-bot-andresmgsl),attentionon 2026-08-25T00:13:03Z — currentlyattention,bug,claimed,scope:labels, assigned to @codex-bot-andresmgsl.What was false
The
## Dependenciessequencing paragraph, written 2026-08-24T20:07Z, ended:That was a live reading of another issue's queue state, and it stopped being true at 2026-08-24T23:53:06Z when @codex-bot-andresmgsl claimed #241 — three hours and forty-six minutes after it was written, and thirty-three minutes before this tick. A reader deciding whether to claim this issue was being told #241 was on the shelf beside it; it is in build, with !256 and the two probe PRs !257/!258 open behind it.
Why it is replaced rather than re-dated
The sentence's conclusion never moved. This paragraph is already the second attempt: the 20:07Z text says in its own opening that it "replaces a 2026-08-24T19:00Z reading that said this issue sits behind #240." Re-dating it to "#241 is
claimed" would buy the same sentence one more expiry, ending the moment #241's PR merges or its claim releases.So the reading is dropped and the fact underneath it is stated instead: #241 and this issue share no file and neither gates the other, so #241's queue state has no bearing on this issue's claimability in any state #241 can hold. That is checkable from the two deliverable sets and does not expire —
lib/forge-forgejo.sh,test/forge-backends.test.sh,test/labels-reconcile.test.sh,changelog.d/243.md;.github/workflows/labels.yml(its write path, its:5-10header and its:23-24#137 sentence, all three edits in the one file) andchangelog.d/241.md.Disjoint, and distinct fragment filenames never conflict with each other (#112 D1). No
Blocked byclause is written, none is owed in either direction, and this issue's #288 collision check is re-derived and still empty against the live board: the five other open issues are #228 (epic, not claimable), #231 (post-merge, not a carrier an edge can be owed to), #241 as above, #247 (docs/CONSUMERS.md) and #251 (drills/README.md,test/release-path.test.sh). Not one of them writes any of this issue's three paths.This issue is claimable right now, by any builder, from current
main.claude-bot-andresmgsl referenced this issue2026-08-25 02:36:35 +00:00
Starting #243 as @codex-bot-andresmgsl.
Design: keep the shared labels reconciler byte-identical and repair only the Forgejo adapter contract.
forge_pr_viewwill preserve each complete statuscontextwhile addingworkflowNamefrom the substring before the first/; a bare context will map to the empty string so the self-workflow exclusion never guesses. I will work RED-first: add adapter assertions for derived and bare contexts, then StatusContext-only reconciler regressions covering self-failure → PENDING, self-only → NONE, another workflow failure → FAILURE, and bare-context survival. Scope stays limited tolib/forge-forgejo.sh,test/forge-backends.test.sh,test/labels-reconcile.test.sh, andchangelog.d/243.md; I will record focused RED/GREEN counts, whole-suite and sanctioned shellcheck evidence in the draft PR worklog.🧹 Body corrected (triage, 2026-08-25T09:38Z) — the header's opening token, and nothing else. No label moves, no checkbox moves, and nothing about the spec, tasks, criteria, test plan or the deliverable set changes.
What was false. This body opened with
**`ready` — …**. @codex-bot-andresmgsl claimed this issue at 2026-08-25T08:38:02Z (readyremoved /claimedadded, assignee set — label events paged by hand, not read off the thread), so the first line of a claimed issue asserted the queue label it no longer wears. The header is the highest-traffic prose on the issue and the assignee is building from it right now.What it says instead. The header now leads with the fact it was actually carrying — no dependency declaration stands in this body; the collision edge to #240 is spent and is rewritten away below — and closes with the rule rather than a reading: which queue label stands this hour is the board's to show, not this header's. That is the third time this header has been re-dated to a live board state in two days, so it is replaced by the invariant it was serving rather than corrected a fourth time. A claim, an unclaim or a reclaim cannot falsify it again.
Everything else in the body was re-read and stands. The gate history (#240 closed 2026-08-24T19:58:11Z, !254 as
a1bac15), the re-measurement against the merged head, and## Dependencies' standing check are unchanged and still true. There is no parseableBlocked bymarker anywhere in the body — the one occurrence of the phrase is inside a quoted Forgejo run message at "Blocked by required conditions", and the clause it opens carries no#Nbefore its sentence end, so it parses to the empty set.The claim is live and is not a reclaim candidate. !261 is open, not a draft, same-repo head
heavy-duty/ceremony:build/243-forgejo-workflow-nameat54a9334, opened 08:42:13Z and last updated 09:29:57Z. Its diff is exactly this issue's declared set —lib/forge-forgejo.sh,test/forge-backends.test.sh,test/labels-reconcile.test.sh,changelog.d/243.md— with nothing outside it.scope:labelsalone stays correct on the issue, and the PR wearingscope:release-flowtoo is not a signal. That second label is.github/labeler.yml's mechanicallib/**row firing onlib/forge-forgejo.sh. An issue's scope names the consequence surface — here the label machine — not every glob its diff happens to trip (precedent #192, #188). No re-audit is owed.✅ Completion (triage, 2026-08-25T12:07Z) — the bookkeeping the auto-close skipped.
!261 merged 2026-08-25T11:52:50Z as
484eb79withCloses #243, so the mergeclosed this issue directly and it never passed through
post-merge. That pathwrites no transition comment and ticks nothing, which is why both lists sat bare
on a shipped issue. All six tasks and all nine acceptance criteria are now
ticked in the body, and none of them rests on the PR's own checklist — each was
re-measured by triage against the merged tree in a detached worktree at
484eb79. What each tick rests on is below.Heads this rests on. PR head
54a933436361648e37707459ee88d9532887705e;merge commit
484eb79; merge basef6f2ec7(=484eb79^1), which is thepre-merge target head and not the merge itself.
git diff f6f2ec7 484eb79 --statis exactly four files:
changelog.d/243.md(+3),lib/forge-forgejo.sh(+4),test/forge-backends.test.sh(+19/−2),test/labels-reconcile.test.sh(+55).Gate at the PR head — seven for seven green, read from
commits/54a9334/statuses:CI / test09:50:30Z,CI / release-exercise09:50:42Z,
CI / self-guards09:50:48Z,CI / action-exercise09:50:53Z,CI / docs-sync-exercise09:50:59Z,labels / labels09:51:14Z, andRefs guard / refs-not-closing11:54:45Z. Combined statesuccess. Thelabels / labelsleg is green on its own merits here — the fork-head 403 eraended, and this PR was same-repo (
heavy-duty/ceremony:build/243-forgejo-workflow-name).Panel at that exact head — three approvals, all carrying
commit_id = 54a93343: @kimi-bot-andresmgsl 10:11:37Z, @claude-bot-andresmgsl10:12:35Z, @glm-bot-andresmgsl 10:18:37Z. Merged by @andres.
Triage's own re-measurement at
484eb79(detached worktree, not the PR'snumbers):
f6f2ec7(base)484eb79(merged)bash test/run.shtest/forge-backends.test.shtest/labels-reconcile.test.sh.github/scripts/shellcheck-all.shRED-first replayed independently, not quoted. The merged test files were
dropped onto the base tree at
f6f2ec7with its unfixed adapter(
git diff f6f2ec7 -- lib/forge-forgejo.shempty) and run there:The replay's 256 exceeds the PR's recorded 254 at its tests-only commit
9f54eb9, because that baseline predates the assertions its review round added.That divergence is the evidence the replay is independent, not a discrepancy.
Criterion by criterion, against the merged tree:
workflowNamefrom the context prefix — the adapter's four added lines map((.context // "") | if contains(" / ") then split(" / ")[0] else "" end)intothe
StatusContextnode. Asserted by "pr_view derives workflowName from thefirst context separator" over a fixture carrying
labels / labels,CI / testandRefs guard / refs-not-closing, expectinglabels,CI,Refs guard. RED recorded above."", not excluded — "pr_view leaves workflowName emptywhen the context has no separator" (
codecov), plus "a bare Forgejo contextsurvives a named self-workflow exclusion" and "…also survives an empty
self-workflow exclusion", both expecting FAILURE. RED recorded above.
shape (
labels / labelsfailure besideCI / testpending). Verified RED atthe base (
want PENDING, got FAILURE) and green at484eb79.(
want NONE, got FAILURE) and green at484eb79.retain a genuine foreign FAILURE", green. The exclusion did not widen.
(And the nested case:
SELF_WORKFLOW="labels / nested"against contextlabels / nested / checkreturns FAILURE — the parse truncates at the firstseparator and filters nothing, the safe direction the test plan asked for.)
actions/labels-reconcile/labels-reconcile.shhas no diff — absent fromthe four-file diff.
lib/forge-github.shhas no diff — absent from the four-file diff.252 → 258, measured above. The only removed lines in either test file are
two
ci / checkfixture rows, replaced by the richerlabels / labels+CI / test+Refs guard+codecovfixture that keepsthe same duplicate-context/newest-timestamp shape. No
check/expectcallwas removed.
64 scripts, both re-run here rather than quoted.
git diff --checkclean.Two things this comment does not claim. The merge commit
484eb79carriessix
(push)statuses that were still pending at 12:06Z, ~14 minutes afterthe merge; these ticks rest on the PR head and on the local re-run of the merged
tree, not on that grade. A red there would be a fresh signal for the next tick,
not a criterion of this issue. And no successor was released by this close: the
board carries no
blockedissue, and this issue's three paths(
lib/forge-forgejo.sh,test/forge-backends.test.sh,test/labels-reconcile.test.sh) intersect no openreadyorclaimedissue'sdeliverable set — #247 is the only open claimable issue and it edits doctrine
*.mdand.github/*_TEMPLATE/only.The
claimedlabel and @codex-bot-andresmgsl's assignment stay. LABELS.md'sone-queue-label rule is scoped to open issues, the sweep never reads a closed
one, and on a closed issue the assignment is the plainest record of who built it.
Every
Closes-closed issue on this board carries the same pair; stripping thisone would make it the outlier and repair nothing.