Skip to content

feat(kanban): ask the board which columns are deploy states, not a list - #249

Open
LukasWodka wants to merge 1 commit into
developfrom
feat/1846-deploy-state-by-order
Open

feat(kanban): ask the board which columns are deploy states, not a list#249
LukasWodka wants to merge 1 commit into
developfrom
feat/1846-deploy-state-by-order

Conversation

@LukasWodka

@LukasWodka LukasWodka commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Refs tracebloc/backend#1846 · epic tracebloc/backend#1646 · follow-up to #237, #245, #247

The instance was fixed. The class wasn't.

#237 fixed the guard that was matching the pre-rename Staging (human review) while the board's column is Staging (agent review) — a card hand-closed there lost its deploy state and kanban-archive.yml then hid it.

What survived was a hand-maintained list of six column names, duplicated in kanban-reconcile.yml, which the next rename or inserted column reopens silently. @saadqbal made exactly this point on #237:

The comment's 'drop the legacy name in both places' is a manual reminder, not a guard.

The board already answers the question

$PROJ carries the Status options in pipeline order, so a deploy state is any column at or after On dev and at or before Prod.

before after
six names, two files, updated by hand two anchors, read from the board
an inserted column is invisible until someone edits classified correctly with no edit
an intermediate rename breaks it silently position is what matters, not the name

An inserted column is exactly how Staging (agent review) arrived. Both anchors are written by this same workflow, so #247's checker already asserts they exist on the board.

Unknown no longer falls open

The other half of #1846. A column this workflow cannot place used to sail past the case and let Done erase a deploy state. It now refuses — a card sitting where it is costs nothing; erasing the fact that it shipped costs the board its meaning.

The test reads the function out of the workflow

This is the shape @saqlainsyed007 argued for on e2e#108: a copy of the logic in the test would let the workflow drift while the test stayed green — the same defect class as the list it replaces.

Verified by renaming col_index:

could not find col_index() in the workflow — did it get renamed?
This test refuses to fall back to a copy.

15 cases: every deploy state including the one the old list missed · everything before On dev · both terminal columns (the <= Prod bound is what keeps Cancelled reachable) · a newly inserted column between the anchors · unknown and empty columns · a board missing an anchor.

ruff and house-rules clean.

Not in scope

kanban-reconcile.yml's copy of the list. It runs in a different context with different variables, and one self-contained change reviews better — filed as the remaining half on backend#1846.

🤖 Generated with Claude Code


Note

Medium Risk
Changes when hand-closed issues get Done vs stay parked—wrong bounds could still erase deploy state or block legitimate closes—but behavior is fail-closed on unknown columns and covered by a selftest tied to the live workflow shell logic.

Overview
Hand-closed issues in deploy columns no longer rely on a fixed list of six Status names (and the stale Staging (human review) entry). When routing would set Done, the router now treats a column as a deploy state if its position on the board falls between On dev and Prod, using Status option order from the same $PROJ payload.

Fail-closed behavior is tightened: missing On dev / Prod anchors aborts the update with an error; a current column the board does not recognize skips Done instead of falling through and overwriting deploy state. The existing issue comment when Done is refused in a deploy column is unchanged.

Regression coverage adds kanban-deploy-state-selftest (GitHub Action + scripts/tests/kanban-deploy-state-selftest.py), which parses col_index() out of kanban-closure-router.yml and runs offline cases (deploy columns, pre-dev columns, terminals, inserted columns, unknown/missing anchors). kanban-reconcile.yml’s copy of the old list is explicitly out of scope.

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

.github#237 fixed the INSTANCE -- the guard matched the pre-rename
"Staging (human review)" while the board's column is "Staging (agent review)",
so a card hand-closed there lost its deploy state and kanban-archive.yml hid it.
The CLASS survived: a hand-maintained list of six names, duplicated in
kanban-reconcile.yml, that the next rename or inserted column reopens silently.

@saadqbal made the point on that PR and it is the right one -- the comment's
"drop the legacy name in both places" is a manual reminder, not a guard.

THE BOARD ALREADY ANSWERS THIS. `$PROJ` carries the Status options in PIPELINE
ORDER, so a deploy state is any column at or after "On dev" and at or before
"Prod". An inserted column -- exactly how "Staging (agent review)" arrived -- is
classified correctly with NO edit here, and a renamed intermediate column keeps
working because its POSITION is what matters, not its name. Two anchors instead
of six names, and both are written by this same workflow, so .github#247's
checker already asserts they exist.

UNKNOWN NO LONGER FALLS OPEN, which is the other half of #1846. A column this
workflow cannot place used to sail past the `case` and let Done erase a deploy
state. It now refuses: a card sitting where it is costs nothing, erasing the
fact that it shipped costs the board's meaning.

THE TEST READS THE FUNCTION OUT OF THE WORKFLOW rather than copying it -- the
shape @saqlainsyed007's e2e#108 review argued for. A copy would let the workflow
drift while the test stayed green, which is the same defect class as the list it
replaces. Verified: renaming `col_index` makes the test fail loudly ("refuses to
fall back to a copy") instead of testing a stale duplicate.

15 cases: every deploy state including the one the old list missed, everything
before On dev, both terminal columns (the `<= Prod` bound is what keeps
Cancelled reachable), a NEWLY inserted column between the anchors, unknown and
empty columns, and a board missing an anchor.

ruff and house-rules clean.

Refs tracebloc/backend#1846
@LukasWodka LukasWodka self-assigned this Aug 13, 2026
@LukasWodka
LukasWodka requested a review from saadqbal August 13, 2026 20:42
Sign up for free to 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