You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
console: registry-inputs-spec-parity's refusesKind reads a union branch's [invalid_type, too_small] pair as a CONTENT refusal, so an array probe the contract refuses enters the accepted-kind set #8204
Suspected mechanism 1 below ("refusesKind does not recurse into z.union") is FALSE. It does recurse; the invalid_union arm runs and carries branch verdicts up. Suspected mechanism 2 ("acceptedMemberKinds folds refuses-content into accepted") is INTENDED and load-bearing, not a defect.
The real defect is one level in: zod keeps running a schema's checks after its type check fails, so z.string().min(1) answers the probe [] with bothinvalid_type and too_small, and refusesKind's every read that pair as a CONTENT refusal — recording an array the contract refused for being an array as an accepted kind.
Measured and fixed in PR #8210; full account in comment 5563643927. The title was amended; the original body is preserved unchanged below, because what the filing seat got wrong is part of the record — I inferred a mechanism from a symptom and wrote it in as this card's headline.
Filed by the domain:spec @ objectui execution seat (session session_0114Ytxr5sM1vdW19Y9WAx6E), R1. Split out of #8137.
Why this is a separate card
#8137 is a decision card carrying two failures of the same test. They are independent, and only one of them is a decision:
failure
needs
1
a calibration control asserts 'Account' is refuses-content; 17.3.0 genuinely accepts it
⛔ human ruling — editing a control is on the manual floor. Stays on #8137.
2
the kind classifier reports contract accepts {string, array} for a member whose array form is measurably refused
ordinary gate bug — this card
Sequencing them behind one ruling was my error; (2) does not depend on (1). This card is (2) alone.
The defect
apps/console/src/__tests__/registry-inputs-spec-parity.test.ts (and whatever helper module refusesKind / acceptedMemberKinds live in).
The gate nonetheless reports record:activity.types as contract accepts {string, array} and fails the single-kind direction. Arrays are refused; the gate says they are accepted.
Two mechanisms are suspected, both to be confirmed on disk before any fix:
refusesKind does not recurse into z.union. A member whose type is z.array(z.union([...])) is probed at the top level only, so the union's rejection of a wrong-typed element never reaches the classifier.
acceptedMemberKinds counts a kind when the verdict is acceptsorrefuses-content. A refuses-content verdict means the shape was accepted, the content was not — that is not the same claim as "this kind is accepted", and folding them together is what lets an unmeasured kind appear in the accepted set. Decide deliberately whether this is intended; if it is, say why in a comment on the helper.
If the mechanism is real, every union-typed member this gate judges is currently mis-classified — not just this one.
Scope — read this before touching anything
✅ In scope: the classifier helper (refusesKind, acceptedMemberKinds, and their probe construction).
⛔ If your fix makes a different, previously-passing control assertion fail, stop and report on this card. Do not adjust the control.
Verification the card requires
Measure, don't infer. CI on PR chore(deps): resolve @objectstack/spec at 17.3.0 in the lockfile #7685 head f1e02a88f also named element:record_picker.sort, object-grid.searchableFields and page:accordion.items in the same failing block. ⚠️ Only record:activity.types has been measured directly. safeParse each affected member against the installed @objectstack/spec artifact and report the actual verdicts; do not treat that list as derived.
Positive control on the fix itself. A member that genuinely is multi-kind must still be reported multi-kind afterwards. A fix that collapses everything to a single kind would also make the failing assertion pass — prove that is not what happened, or the run measured nothing.
Before/after on the reported kind set for at least record:activity.types: {string, array} → {string} expected.
Coordination
⚠️#8176 is dispatched against the same file (registry-inputs-spec-parity's reverse direction, eager-registration judging). Per the file/region granularity ruling (maintainer, 2026-09-05), state the region you touch in your PR body and keep out of the reverse-direction block. If the two edits genuinely collide, say so rather than merging around it.
Related
#8137 (the decision card this splits from — failure 1 stays there) · #7122 / PR #7685 (blocked by both) · #8097 / cf1d29e2f (the gate) · objectstack#11658 / objectstack#11507 (the open-vocabulary ruling that surfaced this) · #8176 (same file, different region) · #8127 (a different 17.3.0 union-drift finding)
Filed by the
domain:spec@ objectui execution seat (sessionsession_0114Ytxr5sM1vdW19Y9WAx6E), R1. Split out of #8137.Why this is a separate card
#8137 is a decision card carrying two failures of the same test. They are independent, and only one of them is a decision:
'Account'isrefuses-content; 17.3.0 genuinely accepts itcontract accepts {string, array}for a member whose array form is measurably refusedSequencing them behind one ruling was my error; (2) does not depend on (1). This card is (2) alone.
The defect
apps/console/src/__tests__/registry-inputs-spec-parity.test.ts(and whatever helper modulerefusesKind/acceptedMemberKindslive in).@objectstack/spec17.3.0 declares:Measured against the installed artifact via
safeParse(not inferred):The gate nonetheless reports
record:activity.typesascontract accepts {string, array}and fails the single-kind direction. Arrays are refused; the gate says they are accepted.Two mechanisms are suspected, both to be confirmed on disk before any fix:
refusesKinddoes not recurse intoz.union. A member whose type isz.array(z.union([...]))is probed at the top level only, so the union's rejection of a wrong-typed element never reaches the classifier.acceptedMemberKindscounts a kind when the verdict isacceptsorrefuses-content. Arefuses-contentverdict means the shape was accepted, the content was not — that is not the same claim as "this kind is accepted", and folding them together is what lets an unmeasured kind appear in the accepted set. Decide deliberately whether this is intended; if it is, say why in a comment on the helper.If the mechanism is real, every union-typed member this gate judges is currently mis-classified — not just this one.
Scope — read this before touching anything
refusesKind,acceptedMemberKinds, and their probe construction).it(...)assertion to make the suite green. Failure (1) above will still be red after your fix, and that is correct — it belongs to Decision:registry-inputs-spec-parityfails on the 17.3.0 merge — a calibration control now asserts something the contract accepts, and the kind classifier may not recurse throughz.union#8137 and is undecided. A green suite is not this card's success criterion.MULTI_KIND_MEMBER_CONTRACTSentries. Declaring these members multi-kind records something the contract contradicts, and would hide the same defect everywhere else it occurs. That is option B on Decision:registry-inputs-spec-parityfails on the 17.3.0 merge — a calibration control now asserts something the contract accepts, and the kind classifier may not recurse throughz.union#8137 and it was rejected there.Verification the card requires
f1e02a88falso namedelement:record_picker.sort,object-grid.searchableFieldsandpage:accordion.itemsin the same failing block.record:activity.typeshas been measured directly.safeParseeach affected member against the installed@objectstack/specartifact and report the actual verdicts; do not treat that list as derived.record:activity.types:{string, array}→{string}expected.Coordination
registry-inputs-spec-parity's reverse direction, eager-registration judging). Per the file/region granularity ruling (maintainer, 2026-09-05), state the region you touch in your PR body and keep out of the reverse-direction block. If the two edits genuinely collide, say so rather than merging around it.Related
#8137 (the decision card this splits from — failure 1 stays there) · #7122 / PR #7685 (blocked by both) · #8097 /
cf1d29e2f(the gate) · objectstack#11658 / objectstack#11507 (the open-vocabulary ruling that surfaced this) · #8176 (same file, different region) · #8127 (a different 17.3.0 union-drift finding)