fix: address Copilot review round 37 — stale constants, inherited answers, prefixed labels

- The seeding effect re-applies constants as well as filling absences: an
  in-place schema change can move a `const` the user cannot edit, and the
  read-only field then displayed the new value while `values` still held the
  old one — which is what would be submitted. Ordinary defaults are still only
  ever added, so an edited field keeps what the user put there.
- hasMissingIn checks own-property presence: a required argument legally named
  `constructor` resolved to the inherited one and read as supplied, enabling
  a submit the schema rejects.
- The TUI keeps the declared name as a branch field's fallback title. The
  prefix is an internal field NAME, and buildFields labels from its map key —
  so the showcase displayed `__b0__address` where the schema says
  `address`.

Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-08-26 14:50:52 -04:00
commit 85b030cbde

View file

@ -601,6 +601,20 @@ describe("root composition (#2123)", () => {
).toBe(true);
});
it("does not read an inherited property as a supplied answer", () => {
// `constructor` is a legal argument name; reading it off the prototype
// would enable a submit the schema rejects.
const schema: InspectorFormSchema = {
type: "object",
// Built through `fromEntries`: in an object literal, `constructor` is
// TypeScript's own inherited member rather than a plain key.
properties: Object.fromEntries([["constructor", { type: "string" }]]),
required: ["constructor"],
};
expect(hasMissingRequiredFields(schema, {})).toBe(true);
expect(hasMissingRequiredFields(schema, { constructor: "x" })).toBe(false);
});
it("blocks submission while no branch is satisfied", () => {
expect(hasMissingRequiredFields(UNION, {})).toBe(true);
expect(hasMissingRequiredFields(UNION, { kind: "email" })).toBe(true);