Skip to content

fix(clusters): keep the chosen region when a second region is removed on a single-region tier - #1842

Open
dawsontoth wants to merge 2 commits into
david/1778-custom-regionsfrom
claude/1275-region-removal-keeps-siblings
Open

dawsontoth wants to merge 2 commits into
david/1778-custom-regionsfrom
claude/1275-region-removal-keeps-siblings

Conversation

@dawsontoth

@dawsontoth dawsontoth commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

A fox's first map flag staying put when the second is removed

⊙ Problem

On a tier that allows only one region (the free tier, which carries allowedRegionIds), removing the second region of a new cluster threw away the first region too: it snapped back to the default US region and its smallest latency (#1275). The free tier's own validation error on the second row ("You can only select one region with this performance tier!") is what asks the user to remove it, so the natural fix-up step is the one that loses their choice.

Reproduced on stage in a real browser before this rebase (Playwright against a local dev server with mocked API responses): pick Medium, choose Europe 45ms for region 1, add a region, switch to Free, remove region 2. Region 1 read US / 90ms, small distribution afterwards. #1780 keeps that US-first correction, so the bug is still there on its branch: with the fix reverted on top of #1780, the two #1275 tests below go red.

The cause is autoSelectRegionBasedOnAllowedRegionIds in ClusterForm.tsx. It corrects the only remaining region whenever that region is not one the tier allows, and it always corrected to US. Removing the second row is what drops the count to one and fires it. The triage suspect, autoPickLatencyDescription in RegionFormInputs.tsx (which #1780 removes), was not involved: rows are keyed by field.id, and removing a row leaves the other row's region and latency untouched on tiers without a region allow-list (pinned by a test below).

Stack: #1780 ← this PR ← #1849 ← #1851 ← #1870. This branch is based on #1780's branch (david/1778-custom-regions), so it lands on top of #1780 instead of #1780 rebasing around it; retarget to stage once #1780 merges. On 2026-10-13 this branch was rebased with #1780 onto stage, after #1917 merged. stage had gained its own ClusterForm.test.tsx (#1846's refused-edit cases), so this branch's region cases now sit beside it in ClusterForm.regions.test.tsx, following the repo's Component.topic.test.tsx convention. Both files keep every case.

❓ Your call: the requirement as filed asks that the first region "remains". It now keeps its region and moves only the latency when the tier does not offer the chosen latency (Europe 45ms becomes Europe 60ms on the free tier), because the alternative is leaving an invalid selection with an error under it. The latency changes without a notice. If you would rather the form never auto-correct after a removal and let the user fix the flagged latency by hand, or show a hint when it does, either is a small change in the same effect.

💡 Solution

The correction now prefers an allowed entry in the region the user already chose, and falls back to US, then the first allowed region, only when the tier offers nothing there.

How it fits #1780: #1780 stores each region plan as a region id, so the effect looks up the surviving id in #1780's regionLookup and matches the catalog region's name (ResolvedRegion.name, the catalog row's region). A custom region (oreg-…) is never corrected, because #1780's effect already skips those ids: the allow-list describes the catalog. Before the rebase the same preference read the entry's regionName directly.

When the tier allows several latencies in the chosen region, the correction takes the first allowed one in catalog order rather than the one closest to the old latency. Today's single-region allow-lists offer one latency per region, so the two can't differ yet.

🔧 Changes

  • src/features/clusters/upsert/ClusterForm.tsx — the change in autoSelectRegionBasedOnAllowedRegionIds: the surviving id's catalog name, then a find on it, run before the existing US and first-allowed fallbacks. Nothing else in the effect, including when it runs, changed.
  • src/features/clusters/DESIGN.md — records when the correction runs (including on removal), that a custom region is never corrected, and the same-region-first rule.

✅ Verification

Route: a component test driving the real ClusterForm (react-hook-form, zod resolver, Radix selects, #1780's region lookup, the real Remove button) in jsdom.

Cross-model review on the rebased branch (one round, vs david/1778-custom-regions): codex (graded), gemini and the Harper domain adjudicator all ran. The adjudicator kept two nits. Taken: the test helper's comment narrated its DOM walk, so it now says only why rows are read as shown. Rejected: explicit import extensions (this repo's imports are extensionless throughout). It dropped gemini's three majors on evidence: ResolvedRegion.name is the catalog row's region (lib/regionLookup.ts:53), the includes call only runs once allowedRegionIds?.length is truthy, and submit re-resolves each id from the same form state the effect writes. Its two open decisions (first allowed latency vs closest, silent latency change) are answered above.

Closes #1275

🤖 Generated by Anthropic Claude Code (Claude Opus 5.5); posted via @dawsontoth.

🤖 Generated with Claude Code

Related PRs: #1780 overlaps (this branch is stacked on it; it rewrote the same correction effect for region ids), #1849 overlaps (stacked on this branch), #1846 overlaps (it created stage's ClusterForm.test.tsx; this branch's cases sit beside it in ClusterForm.regions.test.tsx), 3 others independent
Complexity: easy

Review-Coverage: authored=claude; ran=gemini,codex; adjudicated=domain; declined=cursor-grok,cursor-composer,cursor-kimi,cursor-muse; rounds=1; full=1 @ d2c4490

Review-Attention: read ~3m (decisions: same-location-picks-first-allowed-latency, silent-latency-correction) @ d2c4490

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the region correction logic in ClusterForm to prioritize keeping the user's chosen region when correcting regions on a tier that limits allowed regions, falling back to 'US' or the first available region only if the chosen region is not offered. It also adds corresponding documentation in DESIGN.md and a comprehensive suite of unit tests in ClusterForm.test.tsx to verify this behavior. There are no review comments to address.

@github-actions

github-actions Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 79.17% 14687 / 18550
🔵 Statements 79.1% 15583 / 19698
🔵 Functions 74.56% 3916 / 5252
🔵 Branches 73.68% 11501 / 15608
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
src/features/clusters/upsert/ClusterForm.tsx 64.7% 43.94% 77.77% 64.1% 135-144, 149-153, 164-171, 177-181, 184-210, 224-228, 233-237, 285, 288-301, 305, 308, 365, 387, 398, 445-478, 488-495, 498-519, 532-562, 582-583, 589, 593
Generated in workflow #2361 for commit d9703d2 by the Vitest Coverage Report Action

dawsontoth and others added 2 commits October 13, 2026 21:17
…ects it

A tier with allowedRegionIds (the free tier) takes a single region, and the
form corrects that region whenever it is the only one left. The correction
always jumped to the default US region, so removing the second region, which
is what the tier's "only one region" error asks the user to do, also threw
away the first region and its latency.

Prefer a latency the tier allows in the region the user chose, and fall back
to the default region only when the tier offers nothing there.

Refs #1275

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… regions

Removing the first row shifts the survivor to index 0 before the correction
runs, so pin that it keeps its region there too.

Refs #1275

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dawsontoth
dawsontoth force-pushed the claude/1275-region-removal-keeps-siblings branch from d2c4490 to d9703d2 Compare October 14, 2026 01:18
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.

[Create Cluster] Deleting the second region will also revert the first chosen region and latency

1 participant