Skip to content

fix(kanban): finish #1592 step 3 — writers first, then the fallback - #245

Merged
LukasWodka merged 30 commits into
developfrom
fix/1592-step3-retire-dead-column
Aug 13, 2026
Merged

fix(kanban): finish #1592 step 3 — writers first, then the fallback#245
LukasWodka merged 30 commits into
developfrom
fix/1592-step3-retire-dead-column

Conversation

@LukasWodka

@LukasWodkaLukasWodka commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #237, found by @shujaatTracebloc's review there. Refs tracebloc/backend#1592.

Step 3, as currently written, is an outage

Three sites still writeStaging (human review) — a column that no longer exists on the board — and two fallbacks quietly translate it to FR on staging. Today's behaviour is correct because of those fallbacks, and both are labelled "removed in step 3 of #1592".

Delete them while the writers remain, and every staging promotion fails its option lookup and exits 1.

sitepath
kanban-closure-router.yml:71pull_request writer
kanban-closure-router.yml:156issue-closure writer
advance-deploy-env.yml:71push writer

The order is the fix. Writers emit the live name; only then is the fallback dead code — and it goes in the same change so nothing is left half-done.

What this deliberately does not do

It does not start writing Staging (agent review).

I checked, and nothing writes that column anywhere — by design. fr-gate.yml ranks it 7 and says so: "READ-ONLY for now — nothing writes this value yet (#1578 does that, in a LATER hop)." So a card landing in FR on staging on a staging merge is the documented transition, not a skipped stage.

That's one correction to the review on #237: the mechanism described there is exactly right, but the impact — "every staging promotion appears to bypass agent review" — reads worse than it is. There is nothing to bypass yet. Writing the agent column here would instead move cards into a column nothing advances, which is backend#1846's dead end, created on purpose.

Two sites left alone, on purpose

Readers.case arms accepting both names match values read from the board, which can never return the dead one. That is tolerance, not a dependency, and it costs nothing:

kanban-closure-router.yml:279 advance-deploy-env.yml:88, :209

fr-pass-comment.yml needs no change and is worth pointing at as the shape the other two should have had: it resolves the column by probing the board for whichever name exists, and fails loudly when neither does — so it never depended on a hardcoded name at all.

Evidence

Both files parse as YAML · every embedded run: block parses under bash -n · house-rules clean · no writer of the dead name remains (grep confirms only the three reader arms above).

🤖 Generated with Claude Code


Note

Medium Risk
Touches deploy and closure automation that aborts if Status options do not resolve; wrong timing would break staging promotions, but the change matches the documented live column name.

Overview
Completes backend#1592 step 3 by aligning GitHub Actions writers with the live kanban Status column name and removing rename-window fallbacks that are no longer safe once the old option is gone.

advance-deploy-env.yml sets staging push status to FR on staging instead of Staging (human review), and the GraphQL Status lookup no longer falls back to the old name when the new one is missing.

kanban-closure-router.yml uses FR on staging when a PR merges to staging or when a completed issue was closed by such a PR; the same fallback block before Status resolution is removed, so a missing option fails the run instead of silently retargeting.

Read-side tolerance (e.g. rank/override case arms that still accept both names) is unchanged on purpose.

Reviewed by Cursor Bugbot for commit 631603f. Bugbot is set up for automated code reviews on this repo. Configure here.

LukasWodkaand others added 30 commits August 1, 2026 16:30
promote: develop -> main (D30 self-signoff relaxation)
chore(promote): develop → main — fr-pass exit codes, fail-closed mutators, caller comment (backend#1412, #1413)
chore(promote): develop → main — wire the Done column, and give the closer lookup a token (backend#1411)
Three sites still WROTE `Staging (human review)`, a column that no longer
exists on the board, and two fallbacks quietly translated it to `FR on staging`.
Behaviour today is correct because of those fallbacks -- and both are labelled
"removed in step 3 of #1592".
So step 3 as written is an outage: delete the fallbacks while three writers still
emit the dead name and every staging promotion fails its option lookup and exits
1. The order is the whole fix. Writers emit the live name; only then is the
fallback dead code, and it goes in the same change so nothing is left half-done.
kanban-closure-router.yml:71 pull_request writer
kanban-closure-router.yml:156 issue-closure writer
advance-deploy-env.yml:71 push writer
Found by @shujaatTracebloc reviewing .github#237, which fixed the same
stale-string class on the GUARD path. This is the WRITE path.
WHAT THIS DELIBERATELY DOES NOT DO: it does not start writing
`Staging (agent review)`. Nothing writes that column anywhere, by design --
fr-gate ranks it 7 and says so ("READ-ONLY for now; nothing writes this value
yet, #1578 does that in a LATER hop"). A card landing in `FR on staging` on a
staging merge is the documented transition, not a skipped stage. Writing the
agent column here would move cards into a column nothing advances, which is
backend#1846's dead end, created on purpose.
READERS are left alone. `case` arms that accept both names match values read
FROM the board, which can never be the dead one -- that is tolerance, not a
dependency, and it costs nothing. `fr-pass-comment.yml` needs no change either:
it resolves the column by PROBING the board and fails loudly when neither name
exists, which is the shape the other two should have had.
Verified: both files parse as YAML, every embedded `run:` block parses under
`bash -n`, house-rules clean, and no writer of the dead name remains.
Refs tracebloc/backend#1592
@LukasWodkaLukasWodka self-assigned this Aug 13, 2026
@LukasWodka
LukasWodka merged commit eb0d8bd into developAug 13, 2026
11 checks passed
LukasWodka added a commit that referenced this pull request Aug 13, 2026
…it (#247)
* feat(kanban): assert the board has every Status column the writers emit
The board's column names and the workflows that write them are two systems that
must agree, and nothing checked that they did. #1592 carried the `FR on staging`
rename by hand across three PRs; in between, the writers emitted a column the
board did not have and only a fallback made it work.
That gap is exactly what .github#243 reported and what #245 closed by hand. This
makes it un-driftable instead of remembered.
The failure it prevents is a silent one. A written name that does not resolve
means the card is not moved -- and until #246 that was a `::warning::` on a green
run, so a frozen board and a working board looked identical.
SCOPE IS DELIBERATELY NARROW:
* WRITERS are asserted. A name that is written must exist or the write cannot
land. `advance-deploy-env.yml` and `kanban-closure-router.yml`, listed rather
than globbed -- `STATUS=` is a common shell variable and other workflows use
it for "ok"/"absent"/"unreadable", which are not column names.
* RESOLVERS are NOT asserted. They ask for names on both sides of a rename on
purpose: `opt_either("Staging (human review)", "FR on staging")` is the #1592
shim and its first argument is SUPPOSED to be absent today. Enforcing there
would make the tolerance impossible to express.
* `STATUS_NAME="$OVERRIDE"` is skipped: a per-repo .kanban.yml value cannot be
known here.
Runs on PRs touching the writers, and DAILY -- the board can be renamed in the UI
at any time with no PR to hang a check on, which is the failure this is really
for.
Fails closed throughout: an unreadable board, an unparseable response, zero
options returned, or a literal pattern that matches nothing are all errors. The
last one matters most -- a stale regex would make the check pass vacuously, which
is the failure mode of every guard it is modelled on.
Verified: passes on today's board (5 names); reproducing the pre-#245 state
(writer emitting "Staging (human review)") fails and names the exact file and
value; selftest 6/6 with the board stubbed, covering absent names, a stale name
among good ones, and a case near-miss.
* fix(kanban): gate the conformance check on the selftest job
Bugbot (Medium): the check job ran in parallel with selftest and had no
needs: selftest. If the checker failure paths regress while the board still
matches, "Selftest the checker" goes red but "Written Status names exist on the
board" can still report success -- a conformance-named green from a broken guard.
caller-drift + standards-sync gate their audit on selftest for the same reason.
Add needs: selftest so the conformance verdict is only trusted once the checker
is proven able to fail.
.github#247.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@LukasWodka
LukasWodka deleted the fix/1592-step3-retire-dead-column branch August 14, 2026 13:53
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@LukasWodka