Finding from the axis-① .describe() sweep (describe claims vs measured acceptance face — the #6762 class). Recorded unassigned; suggest domain:spec-surface for routing. Sibling of the severity finding on the same schema (filed separately — different field, different claim type).
Anchor
packages/spec/src/automation/io-node-config.zod.ts, NotifyConfigSchema:
sourceObject: z.string().optional()
.describe('Object name of the record the notification links to (writes sys_notification.source_object). Requires sourceId.'),
sourceId: z.string().optional()
.describe('Record id the notification links to (writes sys_notification.source_id). Requires sourceObject.'),
Described claim
"Requires sourceId." / "Requires sourceObject." — to a schema reader, "requires" says the half-specified pair is refused at the gate.
Measured acceptance face
Probed on origin/main @ 2f3e79351 (tsx safeParse, sources via git archive; controls both sides):
control-accept full pair : ACCEPTED
control-reject unknown key : rejected [unrecognized_keys]
sourceObject WITHOUT sourceId : ACCEPTED
sourceId WITHOUT sourceObject : ACCEPTED
And the acceptance is deliberate — the same file's module JSDoc, a few lines above, records the opposite of what the describes say:
sourceObject/sourceId only take effect as a PAIR — a half-specified click-through target is dropped so the inbox never renders a dead link. The schema keeps both optional rather than refining, because the executor tolerates (drops) the half-specified shape rather than rejecting it.
So the contract is "tolerated and silently dropped", and the describe says "required". The two sentences sit in one file and cannot both be true.
Why it matters for an authoring reader (ADR-0033)
Only the .describe() reaches the published reference — content/docs/references/automation/io-node-config.mdx renders "Requires sourceId." verbatim in the property table, while the JSDoc paragraph carrying the real semantics does not travel (#6762 measured exactly this asymmetry: gen:docs renders .describe() and the module docblock, never the property JSDoc). A reader of the docs concludes a half pair will error and can be leaned on as validation; in fact it parses green, publishes green, and the click-through link silently never renders — the invisible-failure shape this repo's own guidance entries repeatedly warn about (#2675, #4923).
Suggested shape, if triage wants it fixed
Make the describes state the documented tolerance instead of a phantom requirement, e.g. "Only takes effect together with sourceId — a half-specified pair is dropped at execute time (no link is rendered)." No acceptance change; regenerate io-node-config.mdx. (Adding the refine instead would contradict the recorded executor contract and is a bigger decision.)
Refs
#6762 (class specimen), #2675 (pair-only click-through), #4923 (alias-conversion tolerance on this schema), ADR-0033.
Finding from the axis-①
.describe()sweep (describe claims vs measured acceptance face — the #6762 class). Recorded unassigned; suggestdomain:spec-surfacefor routing. Sibling of theseverityfinding on the same schema (filed separately — different field, different claim type).Anchor
packages/spec/src/automation/io-node-config.zod.ts,NotifyConfigSchema:Described claim
"Requires sourceId." / "Requires sourceObject." — to a schema reader, "requires" says the half-specified pair is refused at the gate.
Measured acceptance face
Probed on
origin/main@2f3e79351(tsxsafeParse, sources viagit archive; controls both sides):And the acceptance is deliberate — the same file's module JSDoc, a few lines above, records the opposite of what the describes say:
So the contract is "tolerated and silently dropped", and the describe says "required". The two sentences sit in one file and cannot both be true.
Why it matters for an authoring reader (ADR-0033)
Only the
.describe()reaches the published reference —content/docs/references/automation/io-node-config.mdxrenders "Requires sourceId." verbatim in the property table, while the JSDoc paragraph carrying the real semantics does not travel (#6762 measured exactly this asymmetry:gen:docsrenders.describe()and the module docblock, never the property JSDoc). A reader of the docs concludes a half pair will error and can be leaned on as validation; in fact it parses green, publishes green, and the click-through link silently never renders — the invisible-failure shape this repo's own guidance entries repeatedly warn about (#2675, #4923).Suggested shape, if triage wants it fixed
Make the describes state the documented tolerance instead of a phantom requirement, e.g. "Only takes effect together with
sourceId— a half-specified pair is dropped at execute time (no link is rendered)." No acceptance change; regenerateio-node-config.mdx. (Adding the refine instead would contradict the recorded executor contract and is a bigger decision.)Refs
#6762 (class specimen), #2675 (pair-only click-through), #4923 (alias-conversion tolerance on this schema), ADR-0033.