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
发现于 #5186 的实施(对齐 FieldConstraintsSchema 到 FieldValidationRules 时按规则消费半径扫描文档示例)。Filed unassigned, not claiming. #5186 remains open until its own PR lands; this card is the docs-only follow-up.
Triage: lands in content/docs/blocks/forms.mdx (docs-only) — promoted to pm:queue, type Bug: the published example teaches a validation dialect neither declared surface ever had, and objectui validate now rejects it by name after #5186's alignment, so the tutorial breaks first-runs. Fix direction is in the body (teach the metadata route FieldSchema.pattern, or the { value: RegExp, message } object form in TS examples; sweep the file for sibling examples of the same dialect).
Serial note: #5186 is in flight (pm:dispatched) but touches the zod mirror, not this docs file — no file-surface overlap; do respect its outcome as the source of truth for what the accepted shape is (claim after it lands or re-read its PR before writing). Size/model suggestion: S, sonnet.
Claim: PM loop round 6
Session: session_01RV6yuVCxymHYE16PL9vQkE
Branch: claude/issue-5229-forms-mdx-validation-dialect
Worktree: objectui-issue-5229
Domain: repo:objectui (execution seat)
File surface: content/docs/blocks/forms.mdx. ⛔ OUT: packages/types/** (#5186 landed today — the contract is now correct and is the reference, not a thing to adjust), packages/fields/**, examples/hello-world/** (#5236, dispatched this round), packages/cli (#5237), packages/auth + app-shell/providers (#5198).
Container & model: S, mode:subagent, model: opus — docs-only, but the teaching decision (which of two correct routes to show for which face) is judgement, and getting it wrong publishes a fourth dialect.
Clause-②: no — docs only; no code, no contract.
Serial constraints cleared: nothing open touches content/docs/blocks/**. #5186's PR5230 merged this round, so the contract this card must teach is settled and on main.
Why this is urgent now rather than ordinary docs tidying
PR5230 landed today and changed this example from quietly wrong to loudly wrong. Before it, objectui validate accepted the documented pattern and react-hook-form then silently dropped it — the reader got "looks validated, executes nothing" (#5099's symptom). After it, objectui validaterejects this example by name and points at the metadata route.
That is a net improvement — a loud rejection of something that never worked beats silence — but it means the published documentation now teaches a shape our own tool refuses. A reader who copies the documented example gets an error. That is the state this card closes.
The defect — three dialects, and the docs teach the one that never existed
A sibling message key — this has existed in neither declaration, ever. Messages have always lived inside each rule object. Any zod face of any vintage strips it silently.
The teaching decision — this is the part that needs care
JSON cannot carry a RegExp. So on the JSON face the documented shape is not merely mis-spelled, it is inexpressible: there is no correct way to write a pattern rule in a JSON form block. Rewriting it as "pattern": { "value": "…", "message": "…" } would publish a fourth dialect that objectui validate also rejects — by the same named rejection, for the same reason.
The honest routes, and they are face-dependent:
JSON / YAML metadata → the field metadata route: FieldSchema.pattern (a string), which @object-ui/fields' buildValidationRules compiles into a RegExp before it ever reaches the form's validation shape.
TS / programmatic → pattern: { value: /…/, message: '…' } directly, since a real RegExp is in hand.
Pick per the surrounding example's face — if the section's examples are JSON, teach the metadata route there. ⛔ Do not show a JSON snippet with a pattern object and imply it validates.
The other rules (minLength / maxLength / min / max) are { value, message } and are expressible in JSON; required is boolean | string where a string is the message. If the section teaches any of those, they can be shown correctly in place.
Scope
Sweep the whole file, not just lines 41–53 — the card asks for this explicitly. Report every occurrence of the flat dialect or a stray sibling message you find, and whether you fixed each.
⛔ Do not touch packages/types. The contract is correct as of PR5230 and is your reference. If the docs and the contract disagree, the docs are wrong.
Docs-only, so the pin is the tool's verdict, not a unit test. Show the before and after of objectui validate (or the doc-snippet gate, if it reaches this file) over the example you change: rejected-by-name before, accepted after. If no gate covers content/docs/blocks/**, say so plainly — that is itself worth knowing, and #5174 already records that check-doc-snippet-types.mjs collects only .mdx under content/docs, so check whether this file is actually gated before claiming it is.
If the corrected example cannot be validated by any tool we ship, report that: a docs fix nothing can check is a weaker deliverable and the maintainer should know.
Gates
Derive from your diff. scripts/pm/dispatch-gates.mjs is objectstack-only. Expect Internal Docs Link Check, Doc Snippet Type Check, Build Docs, Control Byte Scan. Changeset almost certainly not required for content/docs/** — run check-changeset-presence.mjs and report its actual verdict rather than assuming.
⛔ Do not background a long check and end your turn.
Deliver
Draft PR against main, first body line Fixes #5229. Return the JSON report and post it as a comment whose first line is the literal <!-- os-dev-report --> marker.
{
"issue": 5229,
"status": "done",
"branch": "claude/issue-5229-forms-mdx-validation-dialect",
"pr": "https://github.com/objectstack-ai/objectui/pull/5251",
"premise_still_valid": false,
"summary": "The DEFECT is real and is fixed; the card's MECHANISM and urgency claim are falsified. Measured on origin/main at 56735762f, `objectui validate` ACCEPTS the published example (`✓ Schema is valid! Type: input`) — it does not reject it by name, before or after PR5230. Reason: the documented node is `\"type\": \"input\"` → InputSchema, which declares NO `validation` key at all, and BaseSchemaCore ends `.passthrough()`, so the whole object rides through unvalidated. FieldConstraintsSchema (the shape PR5230 hardened) is wired only into FormFieldSchema.validation (form.zod.ts:465) — a FORM node's fields[], never an input node. So the example is not 'a third dialect of a real key'; it is an INERT key on the wrong node type, invisible to every shipped tool: validate accepts it, InputRenderer never reads schema.validation (it reads schema.pattern, input.tsx:56), and form.tsx's #5099 diagnostic walks a form node's fields[] so a standalone input node is never in it. That is #5099's symptom still fully alive here and untouched by PR5230 — quieter than the card claims, not louder. Fix: taught the keys the input node actually declares and the renderer actually reads (`required` + `pattern` as a string, forwarded to the native HTML input attributes), then handed off to the `form` component's fields[].validation for rule objects in the `{ value, message }` shape FieldConstraintsSchema pins, stating why `pattern` alone cannot come from JSON there and pointing at the field-metadata route and the TS form. No JSON snippet shows a `pattern` object implying it validates. Whole-file sweep of all 82 lines / 4 json fences: exactly ONE occurrence of the dialect, fixed; 'Add Submit Action' and 'Customize Layout' are clean. packages/types untouched.",
"tests": "Docs-only; the pin is the tool's verdict. BEFORE (origin/main 56735762f), published example extracted verbatim via `sed -n '43,52p'`: `objectui validate` → `✓ Schema is valid! Type: input` — ACCEPTED, contradicting the card. Counterfactual proving the hardening is real but out of reach: the same validation block inside `{\"type\":\"form\",\"fields\":[…]}` → `✗ Schema validation failed! 1. Invalid input Code: invalid_union`. Passthrough measured directly: `{\"type\":\"input\",...,\"validation\":{\"pattern\":12345,\"message\":false,\"nonsense\":[1,2]}}` → `✓ Schema is valid!` (complete garbage accepted), while the DECLARED key `{\"type\":\"input\",...,\"pattern\":12345}` → `✗ Schema validation failed!`. AFTER: both published snippets → `✓ Schema is valid!` (Type: input / Type: form). GATE UNION re-run on final commit 6297e3b3e, all green: check-doc-component-types (482 registered, 88 exempted), check-doc-links (valid across 13 scan roots), check-control-bytes (4645 files) + manual `grep -naP '[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]'` clean, check-changeset-presence (\"1 file(s) changed, 0 under the src/ of a package the release covers … no changeset is owed\" — run, not assumed), check-doc-snippet-types (67/67 blocks judged, 0 failed, after a full `pnpm -r --filter './packages/**' build`), Build Docs (`pnpm turbo run build --filter='@object-ui/site'` → 29 successful, 29 total — confirms the MDX parses). No ablation performed: docs-only change, no guard to mutate. NO GATE COVERS THIS FILE'S SNIPPETS — check-doc-snippet-types' TS_FENCE_LANGUAGES is {ts,tsx,typescript} and this file is entirely json fences, so they never enter the compile set; check-doc-component-types judges the `type` literal only, by design; objectui validate cannot discriminate because the keys are passthrough. The corrected example is still a checkability improvement: it moves the declaration into `pattern`, which the validator does enforce.",
"open_questions": [],
"out_of_scope_findings": [
"filed as #5249: content/docs/plugins/plugin-form.mdx:108 still types `pattern.value` as `string | RegExp`, contradicting the narrowed contract (form.ts declares `{ value: RegExp; message: string }`) and its own Notes cell in the same row — #5118's file, left as-is",
"filed as #5250: finding — JSON doc snippets are checked by nothing (ts/tsx-only fence filter + BaseSchema.passthrough() accepting arbitrary undeclared keys); #5138 filed this class and was closed by PR #5161, which built the TypeScript half only"
]
}
⛔ CORRECTION — the urgency claim on this card was mine, and it was false
PM round 6, session session_01RV6yuVCxymHYE16PL9vQkE. Recording this on the card because I put the claim here, in the dispatch, and in my ACCEPT comment on PR5230, so it is in the record in three places.
What I said (dispatch, and the "one consequence to carry forward" section of PR5230's ACCEPT):
> PR5230 landed today and changed this example from quietly wrong to loudly wrong… objectui validaterejects this example by name… A reader who copies the documented example gets an error.
What is true, measured by the dev and re-verified by me on origin/main before writing this:
$ sed -n '43,52p' content/docs/blocks/forms.mdx > before.json
$ objectui validate before.json
✓ Schema is valid!
Type: input
It is accepted. It was accepted before PR5230 and it is accepted after.
Why, and this is the layer I never checked:
The documented node is "type": "input" → InputSchema, defined as BaseSchema.extend({…}) at packages/types/src/zod/form.zod.ts:192.
BaseSchema ends .passthrough() (base.zod.ts:143, comment: "Allow additional properties for type-specific extensions"), so an undeclared validation object rides through wholly unvalidated.
FieldConstraintsSchema — the shape PR5230 hardened — has exactly one wiring site in the whole zod surface: form.zod.ts:465, validation: FieldConstraintsSchema.optional(), inside FormFieldSchema. That is a form node's fields[]. It never applies to an input node.
The counterfactual the dev ran confirms the hardening is real and simply out of reach here: the same validation block inside {"type":"form","fields":[…]}is rejected (invalid_union).
What I did wrong, precisely
I read PR5230's changeset — which correctly says objectui validate now rejects the flat dialect — and carried that conclusion to a documentation example without checking whether the documented node was one the hardened schema reaches. I reasoned about a schema and a document as if "the validator now rejects this shape" implied "the validator now rejects this file". Between those two statements sits a node-type question I never asked.
That is my fifth premise error today and the only one I authored rather than inherited. It also propagated: I raised this card's priority on the strength of it, and told the maintainer in a round report that a documented example now fails our own tool. It does not. Correcting that publicly here.
The defect is real — and worse than the card said, in the other direction
Not "a third dialect of a real key". It is an inert key on the wrong node type, invisible to every tool we ship:
Surface
Verdict on the published example
objectui validate
accepts — validation undeclared, BaseSchema is .passthrough()
InputRenderer
never reads schema.validation; it reads schema.pattern (input.tsx:56)
walks a form node's fields[]; a standalone input node is never in it
check-doc-component-types
passes — judges the type literal only, by design
check-doc-snippet-types
never sees it — TS_FENCE_LANGUAGES is ts/tsx only; this file is all json
Measured starkly: {"type":"input","name":"email","validation":{"pattern":12345,"message":false,"nonsense":[1,2]}} → ✓ Schema is valid!, while the declared key {"type":"input","name":"email","pattern":12345} → ✗ Schema validation failed!.
So a reader copying the example got zero validation and zero diagnostics. That is #5099's symptom fully alive on this surface, untouched by PR5230 — quieter than I claimed, not louder, and quiet is worse.
The fix is better than the one I specified
I told the dev to teach the field-metadata route for the JSON face. They instead taught the keys the input node actually declares and the renderer actually reads — required, and pattern as a string, since InputSchema.pattern is z.string() and InputRenderer forwards it to the native HTML attribute — then handed off to the form component for rule objects with custom messages.
That is not a fourth dialect: pattern is a first-class declared key on the exact node type the example uses. It also improves checkability, which my version would not have: it moves the declaration out of a key the validator cannot see and into one the validator does enforce.
Whole-file sweep done as asked: 82 lines, 4 json fences, exactly one occurrence, fixed; the other two sections are clean.
#5250 records the structural gap the dev was asked to state plainly — JSON doc snippets are checked by nothing, because the fence filter is ts/tsx-only andBaseSchema.passthrough() accepts arbitrary undeclared keys. Note that is a second angle on #5174: the fence-language filter, not the .md/.mdx collection filter. #5249 is a real sibling in plugin-form.mdx that still types pattern.value as string | RegExp, contradicting the narrowed contract and its own Notes cell in the same row.
Reviewing PR5251 on its own merits once CI converges.
Activity
os-support-ai commentedon Aug 18, 2026
Triage: lands in
content/docs/blocks/forms.mdx(docs-only) — promoted topm:queue, type Bug: the published example teaches a validation dialect neither declared surface ever had, andobjectui validatenow rejects it by name after #5186's alignment, so the tutorial breaks first-runs. Fix direction is in the body (teach the metadata routeFieldSchema.pattern, or the{ value: RegExp, message }object form in TS examples; sweep the file for sibling examples of the same dialect).Serial note: #5186 is in flight (
pm:dispatched) but touches the zod mirror, not this docs file — no file-surface overlap; do respect its outcome as the source of truth for what the accepted shape is (claim after it lands or re-read its PR before writing). Size/model suggestion: S, sonnet.Generated by Claude Code
os-support-ai commentedon Aug 18, 2026
Claim: PM loop round 6
Session:
session_01RV6yuVCxymHYE16PL9vQkEBranch:
claude/issue-5229-forms-mdx-validation-dialectWorktree:
objectui-issue-5229Domain:
repo:objectui(execution seat)File surface:
content/docs/blocks/forms.mdx. ⛔ OUT:packages/types/**(#5186 landed today — the contract is now correct and is the reference, not a thing to adjust),packages/fields/**,examples/hello-world/**(#5236, dispatched this round),packages/cli(#5237),packages/auth+app-shell/providers(#5198).Container & model:
S,mode:subagent,model: opus— docs-only, but the teaching decision (which of two correct routes to show for which face) is judgement, and getting it wrong publishes a fourth dialect.Clause-②: no — docs only; no code, no contract.
Serial constraints cleared: nothing open touches
content/docs/blocks/**. #5186's PR5230 merged this round, so the contract this card must teach is settled and onmain.Why this is urgent now rather than ordinary docs tidying
PR5230 landed today and changed this example from quietly wrong to loudly wrong. Before it,
objectui validateaccepted the documentedpatternand react-hook-form then silently dropped it — the reader got "looks validated, executes nothing" (#5099's symptom). After it,objectui validaterejects this example by name and points at the metadata route.That is a net improvement — a loud rejection of something that never worked beats silence — but it means the published documentation now teaches a shape our own tool refuses. A reader who copies the documented example gets an error. That is the state this card closes.
The defect — three dialects, and the docs teach the one that never existed
content/docs/blocks/forms.mdx"Add Validation" (≈ lines 41–53) teaches:Both keys are wrong, in different ways:
patternas a flat string — the public TS contractFieldValidationRules.patternis a{ value, message }object, and since 手写FieldValidationRules在唯一读点既不校验也不归一:pattern.value写成 string(类型明确允许)被 react-hook-form 静默忽略,未识别的规则名同样静默丢弃 #5099valueis narrowed to a compiledRegExp. As of PR5230 the zod face matches, and rejects a stringpattern.valueby name with guidance towardFieldSchema.pattern.messagekey — this has existed in neither declaration, ever. Messages have always lived inside each rule object. Any zod face of any vintage strips it silently.The teaching decision — this is the part that needs care
JSON cannot carry a
RegExp. So on the JSON face the documented shape is not merely mis-spelled, it is inexpressible: there is no correct way to write apatternrule in a JSON form block. Rewriting it as"pattern": { "value": "…", "message": "…" }would publish a fourth dialect thatobjectui validatealso rejects — by the same named rejection, for the same reason.The honest routes, and they are face-dependent:
FieldSchema.pattern(a string), which@object-ui/fields'buildValidationRulescompiles into aRegExpbefore it ever reaches the form'svalidationshape.pattern: { value: /…/, message: '…' }directly, since a realRegExpis in hand.Pick per the surrounding example's face — if the section's examples are JSON, teach the metadata route there. ⛔ Do not show a JSON snippet with a
patternobject and imply it validates.The other rules (
minLength/maxLength/min/max) are{ value, message }and are expressible in JSON;requiredisboolean | stringwhere a string is the message. If the section teaches any of those, they can be shown correctly in place.Scope
messageyou find, and whether you fixed each.packages/types. The contract is correct as of PR5230 and is your reference. If the docs and the contract disagree, the docs are wrong.validation数组拼法让校验静默失效,ValidationRule全仓不存在 #5118 fixed a different dialect inplugin-form.mdx. Read it for how that one phrased the correction, but note it did not cover this file.Verification
Docs-only, so the pin is the tool's verdict, not a unit test. Show the before and after of
objectui validate(or the doc-snippet gate, if it reaches this file) over the example you change: rejected-by-name before, accepted after. If no gate coverscontent/docs/blocks/**, say so plainly — that is itself worth knowing, and #5174 already records thatcheck-doc-snippet-types.mjscollects only.mdxundercontent/docs, so check whether this file is actually gated before claiming it is.If the corrected example cannot be validated by any tool we ship, report that: a docs fix nothing can check is a weaker deliverable and the maintainer should know.
Gates
Derive from your diff.
scripts/pm/dispatch-gates.mjsis objectstack-only. ExpectInternal Docs Link Check,Doc Snippet Type Check,Build Docs,Control Byte Scan. Changeset almost certainly not required forcontent/docs/**— runcheck-changeset-presence.mjsand report its actual verdict rather than assuming.⛔ Do not background a long check and end your turn.
Deliver
Draft PR against
main, first body lineFixes #5229. Return the JSON report and post it as a comment whose first line is the literal<!-- os-dev-report -->marker.Generated by Claude Code
docs(blocks): teach a validation shape the input node actually declar…
os-support-ai commentedon Aug 18, 2026
{ "issue": 5229, "status": "done", "branch": "claude/issue-5229-forms-mdx-validation-dialect", "pr": "https://github.com/objectstack-ai/objectui/pull/5251", "premise_still_valid": false, "summary": "The DEFECT is real and is fixed; the card's MECHANISM and urgency claim are falsified. Measured on origin/main at 56735762f, `objectui validate` ACCEPTS the published example (`✓ Schema is valid! Type: input`) — it does not reject it by name, before or after PR5230. Reason: the documented node is `\"type\": \"input\"` → InputSchema, which declares NO `validation` key at all, and BaseSchemaCore ends `.passthrough()`, so the whole object rides through unvalidated. FieldConstraintsSchema (the shape PR5230 hardened) is wired only into FormFieldSchema.validation (form.zod.ts:465) — a FORM node's fields[], never an input node. So the example is not 'a third dialect of a real key'; it is an INERT key on the wrong node type, invisible to every shipped tool: validate accepts it, InputRenderer never reads schema.validation (it reads schema.pattern, input.tsx:56), and form.tsx's #5099 diagnostic walks a form node's fields[] so a standalone input node is never in it. That is #5099's symptom still fully alive here and untouched by PR5230 — quieter than the card claims, not louder. Fix: taught the keys the input node actually declares and the renderer actually reads (`required` + `pattern` as a string, forwarded to the native HTML input attributes), then handed off to the `form` component's fields[].validation for rule objects in the `{ value, message }` shape FieldConstraintsSchema pins, stating why `pattern` alone cannot come from JSON there and pointing at the field-metadata route and the TS form. No JSON snippet shows a `pattern` object implying it validates. Whole-file sweep of all 82 lines / 4 json fences: exactly ONE occurrence of the dialect, fixed; 'Add Submit Action' and 'Customize Layout' are clean. packages/types untouched.", "tests": "Docs-only; the pin is the tool's verdict. BEFORE (origin/main 56735762f), published example extracted verbatim via `sed -n '43,52p'`: `objectui validate` → `✓ Schema is valid! Type: input` — ACCEPTED, contradicting the card. Counterfactual proving the hardening is real but out of reach: the same validation block inside `{\"type\":\"form\",\"fields\":[…]}` → `✗ Schema validation failed! 1. Invalid input Code: invalid_union`. Passthrough measured directly: `{\"type\":\"input\",...,\"validation\":{\"pattern\":12345,\"message\":false,\"nonsense\":[1,2]}}` → `✓ Schema is valid!` (complete garbage accepted), while the DECLARED key `{\"type\":\"input\",...,\"pattern\":12345}` → `✗ Schema validation failed!`. AFTER: both published snippets → `✓ Schema is valid!` (Type: input / Type: form). GATE UNION re-run on final commit 6297e3b3e, all green: check-doc-component-types (482 registered, 88 exempted), check-doc-links (valid across 13 scan roots), check-control-bytes (4645 files) + manual `grep -naP '[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]'` clean, check-changeset-presence (\"1 file(s) changed, 0 under the src/ of a package the release covers … no changeset is owed\" — run, not assumed), check-doc-snippet-types (67/67 blocks judged, 0 failed, after a full `pnpm -r --filter './packages/**' build`), Build Docs (`pnpm turbo run build --filter='@object-ui/site'` → 29 successful, 29 total — confirms the MDX parses). No ablation performed: docs-only change, no guard to mutate. NO GATE COVERS THIS FILE'S SNIPPETS — check-doc-snippet-types' TS_FENCE_LANGUAGES is {ts,tsx,typescript} and this file is entirely json fences, so they never enter the compile set; check-doc-component-types judges the `type` literal only, by design; objectui validate cannot discriminate because the keys are passthrough. The corrected example is still a checkability improvement: it moves the declaration into `pattern`, which the validator does enforce.", "open_questions": [], "out_of_scope_findings": [ "filed as #5249: content/docs/plugins/plugin-form.mdx:108 still types `pattern.value` as `string | RegExp`, contradicting the narrowed contract (form.ts declares `{ value: RegExp; message: string }`) and its own Notes cell in the same row — #5118's file, left as-is", "filed as #5250: finding — JSON doc snippets are checked by nothing (ts/tsx-only fence filter + BaseSchema.passthrough() accepting arbitrary undeclared keys); #5138 filed this class and was closed by PR #5161, which built the TypeScript half only" ] }Generated by Claude Code
os-support-ai commentedon Aug 18, 2026
⛔ CORRECTION — the urgency claim on this card was mine, and it was false
PM round 6, session
session_01RV6yuVCxymHYE16PL9vQkE. Recording this on the card because I put the claim here, in the dispatch, and in my ACCEPT comment on PR5230, so it is in the record in three places.What I said (dispatch, and the "one consequence to carry forward" section of PR5230's ACCEPT):
> PR5230 landed today and changed this example from quietly wrong to loudly wrong…
objectui validaterejects this example by name… A reader who copies the documented example gets an error.What is true, measured by the dev and re-verified by me on
origin/mainbefore writing this:It is accepted. It was accepted before PR5230 and it is accepted after.
Why, and this is the layer I never checked:
"type": "input"→InputSchema, defined asBaseSchema.extend({…})atpackages/types/src/zod/form.zod.ts:192.BaseSchemaends.passthrough()(base.zod.ts:143, comment: "Allow additional properties for type-specific extensions"), so an undeclaredvalidationobject rides through wholly unvalidated.FieldConstraintsSchema— the shape PR5230 hardened — has exactly one wiring site in the whole zod surface:form.zod.ts:465,validation: FieldConstraintsSchema.optional(), insideFormFieldSchema. That is a form node'sfields[]. It never applies to aninputnode.The counterfactual the dev ran confirms the hardening is real and simply out of reach here: the same
validationblock inside{"type":"form","fields":[…]}is rejected (invalid_union).What I did wrong, precisely
I read PR5230's changeset — which correctly says
objectui validatenow rejects the flat dialect — and carried that conclusion to a documentation example without checking whether the documented node was one the hardened schema reaches. I reasoned about a schema and a document as if "the validator now rejects this shape" implied "the validator now rejects this file". Between those two statements sits a node-type question I never asked.That is my fifth premise error today and the only one I authored rather than inherited. It also propagated: I raised this card's priority on the strength of it, and told the maintainer in a round report that a documented example now fails our own tool. It does not. Correcting that publicly here.
The defect is real — and worse than the card said, in the other direction
Not "a third dialect of a real key". It is an inert key on the wrong node type, invisible to every tool we ship:
objectui validatevalidationundeclared,BaseSchemais.passthrough()InputRendererschema.validation; it readsschema.pattern(input.tsx:56)form.tsx's #5099 diagnosticfields[]; a standaloneinputnode is never in itcheck-doc-component-typestypeliteral only, by designcheck-doc-snippet-typesTS_FENCE_LANGUAGESis ts/tsx only; this file is alljsonMeasured starkly:
{"type":"input","name":"email","validation":{"pattern":12345,"message":false,"nonsense":[1,2]}}→✓ Schema is valid!, while the declared key{"type":"input","name":"email","pattern":12345}→✗ Schema validation failed!.So a reader copying the example got zero validation and zero diagnostics. That is #5099's symptom fully alive on this surface, untouched by PR5230 — quieter than I claimed, not louder, and quiet is worse.
The fix is better than the one I specified
I told the dev to teach the field-metadata route for the JSON face. They instead taught the keys the
inputnode actually declares and the renderer actually reads —required, andpatternas a string, sinceInputSchema.patternisz.string()andInputRendererforwards it to the native HTML attribute — then handed off to theformcomponent for rule objects with custom messages.That is not a fourth dialect:
patternis a first-class declared key on the exact node type the example uses. It also improves checkability, which my version would not have: it moves the declaration out of a key the validator cannot see and into one the validator does enforce.Whole-file sweep done as asked: 82 lines, 4 json fences, exactly one occurrence, fixed; the other two sections are clean.
#5250 records the structural gap the dev was asked to state plainly — JSON doc snippets are checked by nothing, because the fence filter is ts/tsx-only and
BaseSchema.passthrough()accepts arbitrary undeclared keys. Note that is a second angle on #5174: the fence-language filter, not the.md/.mdxcollection filter. #5249 is a real sibling inplugin-form.mdxthat still typespattern.valueasstring | RegExp, contradicting the narrowed contract and its own Notes cell in the same row.Reviewing PR5251 on its own merits once CI converges.
Generated by Claude Code
docs(blocks): teach a validation shape the input node actually declar…