Path: none | instrument-adjacent contract (spec parse surface) | 北极星「优先级」4
Filed by the domain:spec execution seat (seat 3, session_019srGWGCBBCBHqcDoRZpQRh) at the shift boundary. Reported in PR #19147's body by its implementing dev, which then DIED before filing it (container restarted about 23:20Z); confirmed independently by the PR's at-tier contract reviewer (record 5737516015). ⛔ Unassigned and ungraded — grading is triage's.
The third site of the #17852 family, and the one the ruling did not reach. AssignmentConfigSchema's own OBJECT carries .catchall(z.unknown()) and its top-level keys may be author-named flow variables — and zod's catchall branch skips a __proto__ own key exactly the way its record branch does. ⇒ a variable named __proto__ declared at the TOP level of an assignment node config is silently dropped from the parsed config while the parse reports success.
The two halves, and whose reading each is
In-tree half — this seat's own reading, packages/spec/src/automation/builtin-node-config.zod.ts (read on origin/main, 2026-09-18 22:01 UTC, and unchanged by PR #19147 apart from the assignments slot):
export const AssignmentConfigSchema = lazySchema(() => z.object({
assignments: …,
})
.catchall(z.unknown()));
and its docblock, verbatim: 「Not strict: an assignment node is exempt from registerFlow()'s undeclared-key walk by design (its top-level keys may be variables), and a closed shape here would contradict the descriptor's additionalProperties: true the form↔Zod ledger pins.」 ⇒ the top level of this config is an authoring surface for variable names, by design and on purpose.
Vendor half — NOT this seat's reading, attributed: the PR's at-tier reviewer reports handleCatchall skipping __proto__ at zod core/schemas.js:767-769 (it pulled the 4.4.3 tarball; this container has no node_modules). The same mechanism one function over from $ZodRecord's if (key === "__proto__") continue;, which #17852 measured and fixed. ⚠️ Whoever takes this card re-reads that line themselves against the pinned version before acting — it is the whole premise, and it arrives here second-hand.
Why it is a separate card rather than part of #17852
Maintainer ruling A-narrow (comment 5725370319 on #17852) named exactly two slots — ObjectSchema.fields and AssignmentConfigSchema.assignments — and said in terms: 「⛔ No sweep over the 398 records; a further record keyed by author-named identifiers is its own card when measured」. PR #19147 refuses __proto__ at the assignments RECORD; this is the enclosing OBJECT's catchall, a different mechanism at a different depth, and it was named as a measurement lead in that round's dispatch (5736756482) precisely so it would be filed rather than folded in.
What is NOT claimed
One more hazard the same reviewer raised, recorded here because it shares the subject
zod's treeifyError and error.format() throw a TypeError on any issue path containing __proto__ (reviewer's reading, record 5737516015). It named zero consumers in reach that call either on these schemas, and a one-line remedy (path: [] on the guard's issue). ⚠️ Relevant here because a refusal that crashes the formatter is a worse answer than the silent drop for whoever does call it, and PR #19147 is the first code in this tree that can produce such a path. ⛔ Not this card's subject and not its acceptance condition — recorded so the connection is not rediscovered.
Dedupe words
catchall __proto__ skip · AssignmentConfig top-level variable dropped · handleCatchall proto · assignment node catchall authoring surface · treeifyError proto TypeError
Related: #17852 (the record-level defect and its ruling) · #18847 (the assignments slot) · PR #19147 (implements both; carries this as an unfiled finding in its body) · #18670 (the JSON Schema projection gap).
Generated by Claude Code in session session_019srGWGCBBCBHqcDoRZpQRh; attribution is prose because a footer block is stripped on issue creation.
Generated by Claude Code
Path: none | instrument-adjacent contract (spec parse surface) | 北极星「优先级」4
Filed by the
domain:specexecution seat (seat 3,session_019srGWGCBBCBHqcDoRZpQRh) at the shift boundary. Reported in PR #19147's body by its implementing dev, which then DIED before filing it (container restarted about 23:20Z); confirmed independently by the PR's at-tier contract reviewer (record 5737516015). ⛔ Unassigned and ungraded — grading is triage's.The third site of the #17852 family, and the one the ruling did not reach.
AssignmentConfigSchema's own OBJECT carries.catchall(z.unknown())and its top-level keys may be author-named flow variables — and zod's catchall branch skips a__proto__own key exactly the way its record branch does. ⇒ a variable named__proto__declared at the TOP level of anassignmentnode config is silently dropped from the parsed config while the parse reports success.The two halves, and whose reading each is
In-tree half — this seat's own reading,
packages/spec/src/automation/builtin-node-config.zod.ts(read onorigin/main, 2026-09-18 22:01 UTC, and unchanged by PR #19147 apart from theassignmentsslot):and its docblock, verbatim: 「Not strict: an
assignmentnode is exempt fromregisterFlow()'s undeclared-key walk by design (its top-level keys may be variables), and a closed shape here would contradict the descriptor'sadditionalProperties: truethe form↔Zod ledger pins.」 ⇒ the top level of this config is an authoring surface for variable names, by design and on purpose.Vendor half — NOT this seat's reading, attributed: the PR's at-tier reviewer reports⚠️ Whoever takes this card re-reads that line themselves against the pinned version before acting — it is the whole premise, and it arrives here second-hand.
handleCatchallskipping__proto__at zodcore/schemas.js:767-769(it pulled the 4.4.3 tarball; this container has nonode_modules). The same mechanism one function over from$ZodRecord'sif (key === "__proto__") continue;, which #17852 measured and fixed.Why it is a separate card rather than part of #17852
Maintainer ruling A-narrow (comment 5725370319 on #17852) named exactly two slots —
ObjectSchema.fieldsandAssignmentConfigSchema.assignments— and said in terms: 「⛔ No sweep over the 398 records; a further record keyed by author-named identifiers is its own card when measured」. PR #19147 refuses__proto__at theassignmentsRECORD; this is the enclosing OBJECT's catchall, a different mechanism at a different depth, and it was named as a measurement lead in that round's dispatch (5736756482) precisely so it would be filed rather than folded in.What is NOT claimed
__proto__on an assignment node. The finding(spec): zod z.record() SILENTLY DROPS a__proto__key from its parse OUTPUT while reporting success — ObjectSchema accepts the document and hands back a different one #17852 census coveredfieldskeys andassignmentsvariable names, not this depth;cloudandhotcrmwere outside that container's reach entirely.__proto__key from its parse OUTPUT while reporting success — ObjectSchema accepts the document and hands back a different one #17852 was first filed as — and that card's own history is the warning: it was filed 「LATENT today」 and a later round measured live consumers.refuseRecordProtoKey) is a record-level wrapper; whether it composes onto an object's catchall, or wants a sibling, is the card's first question, not its premise.One more hazard the same reviewer raised, recorded here because it shares the subject
zod's⚠️ Relevant here because a refusal that crashes the formatter is a worse answer than the silent drop for whoever does call it, and PR #19147 is the first code in this tree that can produce such a path. ⛔ Not this card's subject and not its acceptance condition — recorded so the connection is not rediscovered.
treeifyErroranderror.format()throw aTypeErroron any issue path containing__proto__(reviewer's reading, record 5737516015). It named zero consumers in reach that call either on these schemas, and a one-line remedy (path: []on the guard's issue).Dedupe words
catchall __proto__ skip·AssignmentConfig top-level variable dropped·handleCatchall proto·assignment node catchall authoring surface·treeifyError proto TypeErrorRelated: #17852 (the record-level defect and its ruling) · #18847 (the
assignmentsslot) · PR #19147 (implements both; carries this as an unfiled finding in its body) · #18670 (the JSON Schema projection gap).Generated by Claude Code in session
session_019srGWGCBBCBHqcDoRZpQRh; attribution is prose because a footer block is stripped on issue creation.Generated by Claude Code