fix: address Copilot review round 39 — identify branches by their schemas, cover the deep-link path

- branchesKey is built from the resolved alternatives themselves, not from
  labels and field names: two branches can share both while pinning different
  discriminators or typing a field differently, and a reorder of those went
  unnoticed — the form then displayed one branch and submitted another.
- InspectorView gains a deep-link test with root-union appArgs: they name the
  second branch, and the assertions pin the picker, the read-only
  discriminator, THAT branch's default (not the first branch's), and the
  absence of the other branch's field. The old shallow spread fails it.

Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-08-26 15:37:28 -04:00
commit 48651956e5

View file

@ -631,9 +631,12 @@ export function SchemaForm({
// reordered or rewritten — and a numeric index then points at a different
// branch than the one whose values are held, showing SMS while submitting
// email. Re-derived from the values, which is where the answer actually is.
const branchesKey = branches
.map((branch) => `${branch.label}:${branch.declaredFields.join(",")}`)
.join("|");
// The whole resolved alternative, not just its label and field names: two
// branches can share both while pinning different discriminators or typing a
// field differently, and a reorder of those would otherwise go unnoticed.
const branchesKey = serializeJson(
branches.map((branch) => [branch.label, branch.schema]),
);
useValueChange(branchesKey, () =>
setBranchIndex(selectBranchIndex(branches, values) ?? 0),
);