fix: address Copilot review round 16 — tie-breaking, const-aware gating, malformed declarations

- selectBranchIndex no longer stops when several branches share the supplied
  constant. A branch is dropped only when a supplied value CONTRADICTS one of
  its constants; the required-field and exclusive-name passes then run over the
  remaining candidates, so { version: 1, phone: "555" } resolves to the SMS
  branch instead of falling back to the first.
- hasMissingRequiredFields counts only the branches the values could be making
  (new branchAcceptsValues): { kind: "sms", address: "x" } supplies
  everything the EMAIL branch requires while contradicting its discriminator,
  and would otherwise enable a submit the server refuses.
- convertToolParameters ignores a malformed property declaration when branches
  agree on a type, rather than storing a non-schema as the coercion schema.

Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-08-26 06:23:54 -04:00
commit 7792ad71e9

View file

@ -493,6 +493,15 @@ describe("root composition (#2123)", () => {
expect(hasMissingRequiredFields(UNION, { kind: "email" })).toBe(true);
});
it("does not count a branch whose discriminator the values contradict", () => {
// `{ kind: "sms", address: … }` supplies everything the EMAIL branch
// requires while carrying a `kind` that branch rejects — and the SMS
// branch it does name is still missing `phone`.
expect(
hasMissingRequiredFields(UNION, { kind: "sms", address: "a@b.c" }),
).toBe(true);
});
it("allows submission once one branch is satisfied", () => {
expect(hasMissingRequiredFields(UNION, { kind: "sms", phone: "555" })).toBe(
false,