Found during PM review of PR #6804 (#6619's fold), by re-running the census the card rested on rather than taking its count. Filed unassigned for triage.
This is not a defect in PR #6804. That PR folded exactly the three maps its card named, and did so correctly. What is wrong is the inventory — inherited from #6416 and repeated by #6619 — which asserted those three were all of them.
The claim that does not hold
#6619's body states, of the three maps it folds:
#5593 has now landed … measured on the merged ref, all three hand-written $ZodErrorMaps survive it untouched … So they are now the only alias/guidance tables in the package that no registry sees.
PR #6804 repeats it: the fold closes "#6416 命名的盲区,就此闭合".
The blind spot #6416 named is indeed closed. The blind spot class is not.
The measurement
Census of z.core.$ZodErrorMap under packages/spec/src, excluding *.test.ts, run on both refs.
origin/main — six hand-written maps (plus the shared machinery in strict-object.ts and suggestions.zod.ts, which is the template itself, not an instance):
| Symbol |
Site |
Disposition |
strictVisibilityError |
shared/visibility.ts:113 |
folded by #6804 |
strictWidgetAnalyticsError |
ui/dashboard.zod.ts:163 |
folded by #6804 |
strictTenancyError |
data/object.zod.ts:442 |
folded by #6804 |
strictToolError |
ai/tool.zod.ts:83 |
survives |
strictCapabilitiesError |
data/object.zod.ts:160 |
survives |
uniqueScopeError |
data/field.zod.ts:271 |
survives — different class, see below |
On PR #6804's head (47be8449) the first three are gone and the last three remain.
The two that are the same class
Both are unrecognized_keys prescription tables attached to a .strict() object via { error: … } — byte-for-byte the shape the fold was built for.
ai/tool.zod.ts:83, consumed at :180 (}, { error: strictToolError }).strict()):
const strictToolError: z.core.$ZodErrorMap = (issue) => {
if (issue.code !== 'unrecognized_keys') return undefined;
const keys = (issue as { keys?: readonly string[] }).keys ?? [];
const lines = keys.map((key) =>
TOOL_RETIRED_KEY_GUIDANCE[key] ?? `\`${key}\` is not a ToolSchema field.`,
);
It carries TOOL_RETIRED_KEY_GUIDANCE — a per-key retirement prescription table, which is precisely the kind of content #6416 wanted under the integrity gate, and it is hand-maintained.
data/object.zod.ts:160, consumed at :274 (}, { error: strictCapabilitiesError }).strict()) — same shape, same invisibility.
The one that is NOT the same class — do not sweep it in
uniqueScopeError (data/field.zod.ts:271) branches on invalid_union, not unrecognized_keys:
const uniqueScopeError: z.core.$ZodErrorMap = (issue) => {
if (issue.code !== 'invalid_union') return undefined;
It is a value-level error map (a mis-spelled unique scope), not an unknown-key alias/guidance table. strictObject's guidance channel does not address it and folding it would be a category error. Recorded explicitly so the next agent does not spend a round discovering this.
Why it matters
The argument for the fold was never aesthetic — it was that a hand-rolled map registers in neither registry, so its aliases and prescriptions are unmeasured rather than clean. That argument applies unchanged to strictToolError and strictCapabilitiesError. strictToolError is the more valuable of the two, because a retirement prescription table is exactly the surface that rots silently: the tombstone sweep filed as #6756/#6758 found two live prescriptions pointing at keys that no longer exist, and neither of those tables was under a gate either.
The secondary harm is the claim itself. #6619 and PR #6804 both state the package now has no unregistered guidance tables. Anyone auditing "is the #6416 blind spot closed?" reads that and stops — the same failure shape as #6630's "the maxAttempts tombstone is the whole migration channel" sentence, which was false in the same way.
Suggested direction
Non-binding: fold strictToolError and strictCapabilitiesError the way PR #6804 folded the other three, reusing the KeySetGuidance / guidanceSets machinery it introduced (which did not exist when #6416 was written and removes the reason the earlier fold was hard). PR #6804 also added a closure pin to alias-integrity.test.ts that goes red if a folded map is reverted to a hand-written $ZodErrorMap — extending that pin to fail on any new hand-written unrecognized_keys map, rather than only the folded three, would close the class instead of the instances, and is the cheaper half of this card.
Not in scope
uniqueScopeError — different error code, different class (above).
- The shared machinery in
strict-object.ts / suggestions.zod.ts — that is the template, not an instance.
- No acceptance change. Folding these two must leave
ToolSchema and the capabilities block accepting and rejecting exactly what they accept today; only the message assembly moves. If a fold cannot preserve that, it is a different defect class.
Provenance
Found during PM review of PR #6804 (#6619's fold), by re-running the census the card rested on rather than taking its count. Filed unassigned for triage.
This is not a defect in PR #6804. That PR folded exactly the three maps its card named, and did so correctly. What is wrong is the inventory — inherited from #6416 and repeated by #6619 — which asserted those three were all of them.
The claim that does not hold
#6619's body states, of the three maps it folds:
PR #6804 repeats it: the fold closes "#6416 命名的盲区,就此闭合".
The blind spot #6416 named is indeed closed. The blind spot class is not.
The measurement
Census of
z.core.$ZodErrorMapunderpackages/spec/src, excluding*.test.ts, run on both refs.origin/main— six hand-written maps (plus the shared machinery instrict-object.tsandsuggestions.zod.ts, which is the template itself, not an instance):strictVisibilityErrorshared/visibility.ts:113strictWidgetAnalyticsErrorui/dashboard.zod.ts:163strictTenancyErrordata/object.zod.ts:442strictToolErrorai/tool.zod.ts:83strictCapabilitiesErrordata/object.zod.ts:160uniqueScopeErrordata/field.zod.ts:271On PR #6804's head (
47be8449) the first three are gone and the last three remain.The two that are the same class
Both are
unrecognized_keysprescription tables attached to a.strict()object via{ error: … }— byte-for-byte the shape the fold was built for.ai/tool.zod.ts:83, consumed at:180(}, { error: strictToolError }).strict()):It carries
TOOL_RETIRED_KEY_GUIDANCE— a per-key retirement prescription table, which is precisely the kind of content #6416 wanted under the integrity gate, and it is hand-maintained.data/object.zod.ts:160, consumed at:274(}, { error: strictCapabilitiesError }).strict()) — same shape, same invisibility.The one that is NOT the same class — do not sweep it in
uniqueScopeError(data/field.zod.ts:271) branches oninvalid_union, notunrecognized_keys:It is a value-level error map (a mis-spelled
uniquescope), not an unknown-key alias/guidance table.strictObject'sguidancechannel does not address it and folding it would be a category error. Recorded explicitly so the next agent does not spend a round discovering this.Why it matters
The argument for the fold was never aesthetic — it was that a hand-rolled map registers in neither registry, so its aliases and prescriptions are unmeasured rather than clean. That argument applies unchanged to
strictToolErrorandstrictCapabilitiesError.strictToolErroris the more valuable of the two, because a retirement prescription table is exactly the surface that rots silently: the tombstone sweep filed as #6756/#6758 found two live prescriptions pointing at keys that no longer exist, and neither of those tables was under a gate either.The secondary harm is the claim itself. #6619 and PR #6804 both state the package now has no unregistered guidance tables. Anyone auditing "is the #6416 blind spot closed?" reads that and stops — the same failure shape as #6630's "the
maxAttemptstombstone is the whole migration channel" sentence, which was false in the same way.Suggested direction
Non-binding: fold
strictToolErrorandstrictCapabilitiesErrorthe way PR #6804 folded the other three, reusing theKeySetGuidance/guidanceSetsmachinery it introduced (which did not exist when #6416 was written and removes the reason the earlier fold was hard). PR #6804 also added a closure pin toalias-integrity.test.tsthat goes red if a folded map is reverted to a hand-written$ZodErrorMap— extending that pin to fail on any new hand-writtenunrecognized_keysmap, rather than only the folded three, would close the class instead of the instances, and is the cheaper half of this card.Not in scope
uniqueScopeError— different error code, different class (above).strict-object.ts/suggestions.zod.ts— that is the template, not an instance.ToolSchemaand the capabilities block accepting and rejecting exactly what they accept today; only the message assembly moves. If a fold cannot preserve that, it is a different defect class.Provenance
origin/mainand on PR refactor(spec): 三个手写 unrecognized_keys 错误映射折叠进 strictObject 的按集合取键 guidance(#6619) #6804's head47be84494f9efda272ba1807baec1d427d39cb6d, viagit grep -n 'z.core.\$ZodErrorMap'overpackages/spec/src/**/*.tsexcluding*.test.ts, then the consumption sites viagit grep -n 'error: <symbol>'.mainand not on the branch, so the instrument distinguishes present from absent.issue.codeguard read out of each map's first line, not by name.strictObjectguidance — requires a set-keyed guidance form, and closes the alias-integrity gate's blind spot (#6416 direction 2) #6619, both of which assert the opposite of this finding; no open card records the residue.