Preview: PR 19787 on mf Reviewed: e243cca96 Pull request Issue 14111 Round 1 page

PR 19787, round 2: convert() fixed where the bug was

By codyrancher, milestone v2.17.0. Round 2 reviewed 2026-11-10, two passes (Cody's process and ours) merged.

Preview: https://rancherpr19787r.13.48.147.135.sslip.io/dashboard/ rebuilt from e243cca96, backend https://rancher.13.48.147.135.sslip.io (Rancher v2.16 head). The round-1 build is gone; the fork build pr19787conv is still up.

Verdict: approve. Both passes agree. Cody took your suggestion: convert() now builds its own list and keeps each label as its own rule, and the clones are gone. Your round-1 comment is addressed, checked live. No blockers. One request about the PR description and one optional nit. Nothing is posted on GitHub.
Your approval was dismissed You submitted it on 11-06 with your own text. Cody's push on 11-09 (a rebase plus the new commit) dismissed it, and Cody re-requested review this morning, so the PR needs a fresh approval.

What changed since round 1

Your round-1 comment: addressed

I ran the round-1 walk again against the new build, with the Harvester extension blocked and every write aborted, so each result is the request the form would send. Every case gives the same result as our fork build did on 11-06.

Round 1 PR build: one row aaa in list bbb, aaa, banner Matches 3 of 5 existing pods, three pods listed
Round 1 build: the label merged into the rule, 3 of 5 pods.
e243cca96: two rows aaa in list bbb and aaa in list aaa, banner Matches 0 of 5 pods, no pods listed
e243cca96: two rows, 0 of 5 pods, as kubectl says.
CaseRound 1 builde243cca96
New PodDisruptionBudget, two ruleseach rule sent twicesent once, as labels
Monitoring install, aaa plus bbb NotIn xaaa sent twicesent once
Mixed policy aaa=aaa plus aaa In [bbb]one row, 3 of 5 podstwo rows, 0 of 5
Retype that rule and savesaves the wider aaa in (bbb,aaa)saves both rules, still 0 pods
Ingress rule targets, same selector3 of 5 pods, 1 of 174 namespaces0 of 5, 0 of 176
Policy already saved with duplicatesone rowone row, sent unchanged
Save with no changes: ClusterGroup, PodDisruptionBudget, autoscalerrewrittenunchanged
Plain selectors, other operators, Clone, workload and ReplicaSet podsfinesame

The new convert() next to ours

It is the change from your fork branch (zz-19787-convert-rewrite) with two differences. Neither matters in practice.

The round-1 harness, rerun with three versions over 2,457 generated selectors: Cody's output equals ours in every case. Neither writes to its input. Both agree with Kubernetes on 22,113 pod checks, where master is wrong 972 times. The copy is shallow, but MatchExpressions clones every rule before editing it and no caller writes to the result.

The two passes

Cody's process (ai-skills, second-round skill)Our process (fresh agent)
VerdictApprove: 1 comment addressed, 0 newApprove: 1 suggestion, 1 optional nit
Round-1 commentAddressed, round-1 walk rerun liveAddressed, each claim in Cody's reply checked live
Stale PR descriptionNoticed, not filed (that skill files code problems only)Filed as a suggestion
Docblock says what, not whyNot filed (no nits)Optional nit
Checked by bothMixed fixture, PodDisruptionBudget create, Monitoring install, already-doubled policies, ClusterGroup Save, autoscaler, no regression in any other convert() caller
Only this passSide-by-side harness against our fork, GitHub search for extension callers, workload and ReplicaSet pod listsPR's tests run against master's convert() (9 fail, so they guard the fix), per-caller code read, two pre-existing bugs below
CostIn this session, about 25 minutesAbout 18 minutes, 92 tool calls

Neither pass changed anything on mf. The shared admin's language is set to Traditional Chinese by someone else. Both passes switched it to English in their own browser only, and its saved value is unchanged.

Findings that survived

REQUESTThe PR description still describes round 1

The technical notes still say convert() writes into the array it is given, "hence the deep copy", and that fixing convert() is "left for a follow-up". This PR is now that follow-up. The regression areas list only network policies, but convert() also backs the PodDisruptionBudget, Monitoring storage and autoscaler metric selectors, Fleet cluster groups and GitRepo cluster targets, and the matching pods lists. QA plans from that section. It should also say that a label and an In rule on the same key now show as two rows. No code change needed.

OPTIONALThe convert() docblock says what, not why

selector.js:125: the reason a label must not join an In rule on the same key is that they are ANDed, and merging widens the selector. That is what someone could "simplify" back later. The new test at selector.test.ts:267 already guards it, so I'd leave this out unless you want it.

Already on master, not filed

Dropped, and why

What I'd post (Approve)

Body

Thanks for changing convert() itself. I tested it again on a real Rancher. Your mixed fixture shows two rows and matches no pods. The PodDisruptionBudget form and the Monitoring storage selector send each rule once. Selectors already saved with the duplicates show one row. Save with no changes sends the selector unchanged on network policies, PodDisruptionBudgets, autoscalers and Fleet cluster groups. LGTM.

One thing before merging: could you update the description? It still says fixing convert() is left for a follow-up, and the regression areas only cover network policies. Since convert() is shared, it would help QA to list the other places it reaches: the PodDisruptionBudget, Monitoring storage and autoscaler metric selectors, Fleet cluster groups and cluster targets, and the matching pods lists. It's also worth saying that a label and an In rule on the same key now show as two rows.

Optional inline comment on shell/utils/selector.js line 125

Optional: a few words on why a label stays its own rule would help here. A label and an In rule are ANDed, so merging them widens the selector, and that is the part someone might "simplify" back later.

Your round-1 thread can be resolved once you submit.

Left on mf

Previews dashboard-pr19787 (now e243cca96) and dashboard-pr19787conv. Pages pr19787-review on mf and this one on created-dashboard-2. Namespaces zz-pr19787, zz-pr19787-peer and zz-pr19787-conv, and ClusterGroup fleet-default/zz-pr19787-cg-mixed. Round 2 created nothing.