Skip to content

feat(kanban): resolve "Staging (human review)", fall back to "FR on staging" (backend#1592 step 1) - #187

Merged
LukasWodka merged 1 commit into
developfrom
feat/1592-staging-human-review-fallback
Aug 10, 2026
Merged

feat(kanban): resolve "Staging (human review)", fall back to "FR on staging" (backend#1592 step 1)#187
LukasWodka merged 1 commit into
developfrom
feat/1592-staging-human-review-fallback

Conversation

@LukasWodka

@LukasWodkaLukasWodka commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Step 1 of the three-step rename in backend#1592. Nothing changes behaviourally — this teaches all five reusables to prefer the new column name and accept the old one, so they work on both sides of the rename instant.

Why a fallback rather than a swap

A rename cannot be done reads-before-writes. Adding a column can — teach everything to read the new name, then start writing it. A rename makes the old name stop existing at a single instant with no period where both are present. Every select(.name=="FR on staging") would resolve to null on the far side of that instant, and null resolution in these workflows means abort or, worse, skip silently.

So each resolver asks for the new name and falls back to the old; each comparator accepts both.

Verified against live board data, in both states

today (only the old name exists): opt_either -> d3caf1d4
after rename (name swapped): opt_either -> d3caf1d4
live id of "FR on staging": d3caf1d4

Same option id either way — which is exactly what the in-place UI rename preserves, and why step 2 must be the UI.

What changed, by kind rather than by file

kindwhere
Resolvers (name → option id), new→old fallbackadvance-deploy-env, kanban-closure-router, kanban-reconcile (new opt_either helper)
Comparators (status read back from the board), accept bothadvance-deploy-env override map + rank(), fr-gaterank(), kanban-reconcile ×3, kanban-closure-router, fr-pass-comment
Write sites, now naming the new columnkanban-closure-router staging branch, advance-deploy-env staging
Existence probefr-pass-comment resolves whichever staging-review column exists, keeping its loud failure for the case where neither does

Both rank() functions score the two names identically, so the monotonic never-demote guard cannot read a rename as a backwards move.

fr-pass-comment's probe already carried a comment anticipating exactly this: "this board has been renamed before … so the next rename fails loudly here instead of reporting 'wrong column' for every card." That intent is preserved.

Deliberately not in this PR

18 literal references remain in comments and user-facing message strings. They are correct today and become wrong only after step 2, so changing them now would make the files describe a board that does not exist yet. They are step 3's work.

After this merges — and this order matters

  1. Promote to main (callers pin @main, so nothing takes effect until it does).
  2. @LukasWodka renames the option in the GitHub UI. Not the API: updateProjectV2Field replaces the whole option set and re-mints every ID — measured 2026-08-05, adding one option preserved 0 of 11 option IDs and blanked 625 of 625 items, recovered only because a name-keyed backup existed (#1576).
  3. Dispatch kanban-reconcile with dry-run=true and confirm green.
  4. Then step 3 removes the fallback and updates the 18 strings.

Parent backend#1592 → #1552.


Note

Medium Risk
Changes sit on promotion gates, deploy advancement, and board writes, but they are additive aliases and fallbacks meant to keep behavior identical across the rename instant; a mistake could still break status resolution or monotonic guards until step 3 cleans up.

Overview
Step 1 of backend#1592 prepares five reusable kanban workflows for renaming the staging functional-review column from FR on staging to Staging (human review) without changing behavior until the board is renamed in the UI.

Resolvers resolve Status option IDs by trying the new name first, then falling back to the old (advance-deploy-env, kanban-closure-router, kanban-reconcile via new opt_either).

Comparators treat both names as the same pipeline stage: rank() in advance-deploy-env and fr-gate, column lists and deploy-state guards in kanban-reconcile and kanban-closure-router, and /fr-pass column checks in fr-pass-comment (including a probe for which staging-review option exists).

Write paths for staging merges now emit Staging (human review); .kanban.yml overrides map both names to the staging deploy environment. Fallback logic is documented as temporary until step 3 removes it.

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

…taging" (backend#1592 step 1)
Step 1 of the three-step rename. Nothing changes behaviourally: this teaches all
five reusables to prefer the NEW column name and accept the OLD one, so they
work on both sides of the rename instant. Step 2 is the UI rename (Lukas), step 3
removes the fallback.
WHY A FALLBACK RATHER THAN A SWAP. A rename cannot be done reads-before-writes.
Adding a column can - teach everything to read the new name, then start writing
it - but a rename makes the old name stop existing at a single instant, with no
period where both are present. Every `select(.name=="FR on staging")` would
resolve to null on the far side of that instant, and null resolution in these
workflows means "abort" or, worse, "skip silently". So each resolver asks for the
new name and falls back to the old, and each comparator accepts both.
WHY THE UI, NOT THE API - and this is measured, not cautious. The ticket records
that `updateProjectV2Field` replaces the whole option set and re-mints every ID:
on 2026-08-05, adding ONE option preserved 0 of 11 option IDs and blanked 625 of
625 items, recoverable only because a name-keyed backup existed (#1576). The UI
renames in place, preserving the option ID and every item's value. Step 2 is
therefore deliberately a human action.
Changed, by kind rather than by file:
RESOLVERS (name -> option id), given a new->old fallback:
advance-deploy-env.yml, kanban-closure-router.yml, kanban-reconcile.yml
(via a new opt_either helper)
COMPARATORS (status name read back from the board), now accepting both:
advance-deploy-env.yml override map + rank(), fr-gate.yml rank(),
kanban-reconcile.yml x3, kanban-closure-router.yml, fr-pass-comment.yml
WRITE SITES, now naming the new column:
kanban-closure-router.yml staging branch, advance-deploy-env.yml staging
EXISTENCE PROBE:
fr-pass-comment.yml resolves whichever staging-review column exists and
keeps its loud failure for the case where NEITHER does - which is what that
block was written for, and its comment already anticipated this rename.
Both rank() functions score the two names identically, so the monotonic
never-demote guard cannot see a rename as a backwards move.
VERIFIED against live board data in both states, not just reasoned about:
today (only the old name exists): opt_either -> d3caf1d4
after rename (name swapped): opt_either -> d3caf1d4
live id of "FR on staging": d3caf1d4
Same id either way, which is exactly what the in-place UI rename preserves.
18 literal references remain in comments and user-facing message strings. Those
are correct as they stand today and become wrong only after step 2, so they are
step 3's work rather than a partial edit now.
@LukasWodka
LukasWodka merged commit 0c4e8ab into developAug 10, 2026
11 checks passed
@LukasWodka
LukasWodka deleted the feat/1592-staging-human-review-fallback branch August 10, 2026 08:17
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.

2 participants

@LukasWodka@saadqbal