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
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Rationale: objectui validate is a live authoring-time surface and it is wrong in both directions at once — it rejects validation written to the public TS contract ({ value, message } object shape) and passes a flat scalar dialect the renderer never reads (the "looks validated, executes nothing" symptom of #5099, hidden on the zod face). For JSON-only authors this zod face is the only authoring-time defence, so the false negative actively teaches the correct shape as wrong.
Dispatch notes: align FieldConstraintsSchema to FieldValidationRules (post-#5099 shape); on the JSON face pattern.value should be rejected by name with guidance toward the metadata route (FieldSchema.pattern), per the #5099 ruling's JSON-face half as argued on-card. The existing form-field-zod-coverage.test.ts pins top-level keys only — the fix should pin the validation inner shape so this class of drift cannot re-open silently.
Claim: PM loop round 5
Session: session_01RV6yuVCxymHYE16PL9vQkE
Branch: claude/issue-5186-field-constraints-zod-mirror
Worktree: objectui-issue-5186
Domain: repo:objectui (execution seat)
File surface: packages/types/src/zod/form.zod.ts (FieldConstraintsSchema and its use at FormFieldSchema.validation), the pin in packages/types/src/__tests__/form-field-zod-coverage.test.ts, plus tests. ⛔ OUT: packages/types/src/form.ts (the TS contract is the reference, not the thing to change — see below), packages/components/src/renderers/form/**, packages/fields/**, packages/app-shell/**, packages/plugin-view/plugin-list (#5177), packages/plugin-report (#5137), packages/i18n (#5215).
Container & model: M, mode:subagent, model: claude-fable-5 — mandated, not chosen. Tier read this round from CONTRACT_REVIEW_TIER (scripts/pm/dispatch-gates.mjs:1569), ⛔ not recalled.
Clause-②: yes — content limb, and squarely: this changes what objectui validateaccepts and rejects. The object shape currently refused becomes valid; the flat dialect currently passed becomes invalid. That is a contract accept/reject change on a live authoring-time surface. Dispatched at the contract-review tier, so no needs:contract-review is owed at enqueue.
Serial constraints cleared: packages/types freed this round — #4314's PR #5209 merged at 15:01Z and #4538's PR #5218 (which touched types import specifiers) merged at 15:23Z. Nothing open touches the package. Re-verify at your claim.
Zone 1 — Triage's ruling (binding)
Graded pm:queue / bug: objectui validate is a live authoring-time surface and it is wrong in both directions at once —
False negative: it rejectsvalidation written to the public TS contract ({ value, message } object shape), teaching the correct shape as wrong.
Direction: align FieldConstraintsSchema to FieldValidationRules (post-#5099 shape). The TS contract and the renderer's read point are the reference; the zod mirror is the thing that is wrong.
The JSON-face half of the #5099 ruling — and the one subtle part
#5099 narrowed FieldValidationRules.pattern.value to RegExp, so a TS author writing a string now fails to compile. JSON authors have no TS, and JSON cannot express a RegExp at all. Their only authoring-time defence is this zod face, and today it enforces a dialect nobody reads.
So per triage: on the JSON face, pattern.value should be rejected by name, with guidance toward the metadata route (FieldSchema.pattern) — because a hand-written pattern genuinely cannot travel through JSON, and the honest answer is to point the author at the route that can. ⛔ Do not silently strip it, and ⛔ do not invent a string→RegExp coercion to make it "work" — that would re-open exactly what #5099 closed.
Zone 2 — PM mechanism assumptions (verify; falsifying these is a good run)
I expect the fix is one direction: the zod mirror moves to the TS shape. If you find a place where the TS contract is the wrong one and the flat dialect is genuinely load-bearing somewhere, stop and report — that would make this a contract question rather than a mirror repair, and it goes back to the decision box.
I expect required: string | boolean on the TS side to be the one field that does not follow the { value, message } pattern. Check it rather than pattern-matching the others onto it.
Tests — the drift survived because the existing pin looks like it covers this
form-field-zod-coverage.test.ts pins FormFieldSchema's top-level keys (#3090). It does not pin validation's inner shape, which is exactly why this drift lived silently under a green guard. Triage asked for that hole closed, and it is the part of this card that stops it re-opening.
Pin all four facts: the TS-contract object shape is accepted; the flat scalar dialect is rejected; pattern.value is rejected by name with the guidance; and a FormField carrying contract-shaped validation parses. The first two are the two directions the card measured — both must be red before your change.
Gates
Derive from your diff — expect Lint, Type Check, the shards, changeset gates, Control Byte Scan, and the consumer radius for @object-ui/types (a zod schema tightening can break a consumer's parse without touching its source — this is the gate most likely to be under-run here). Changeset required. Score minor and describe the behaviour change in the body per AGENTS.md §版本号策略 — ⛔ never major, it trips the fixed-group gate.
⛔ Do not background a long check and end your turn — two devs stalled that way today. If the suite queues behind the shared verify lock, narrow it and declare the narrowing.
Deliver
Draft PR against main, first line Fixes #5186. Push the branch early. Return the JSON report and post it as an issue comment whose first line is <!-- os-dev-report -->. Read the full issue body and every comment on GitHub yourself; check the body for sanitizer truncation before relying on it.
{
"issue": 5186,
"status": "done",
"branch": "claude/issue-5186-field-constraints-zod-mirror",
"pr": "https://github.com/objectstack-ai/objectui/pull/5230",
"premise_still_valid": true,
"summary": "Aligned FieldConstraintsSchema (zod face of FormFieldSchema.validation) to the FieldValidationRules TS contract per the triage ruling: required is boolean|string, minLength/maxLength/min/max are {value,message} objects, pattern is {value: RegExp, message} with a non-RegExp pattern.value rejected BY NAME with guidance toward FieldSchema.pattern (no strip, no coercion), validate stays a function. Re-measured the card's probe against the current source tree (post-#5209/#5218) before changing anything — both directions still wrong, premise intact. Verified the flat dialect is load-bearing nowhere: FieldConstraintsSchema has exactly 3 references (definition, FormFieldSchema.validation, barrel export) and no z.infer anywhere; fixture triage across the rule's consumer radius found every validation: literal either already contract-shaped or an unrelated key (i18n catalogs, preview sample). PM's required-field assumption confirmed: required: string|boolean is the one non-{value,message} rule.",
"tests": "Red-before at unfixed schema: 5/6 new pins failed incl. both card directions ('ACCEPTS TS contract' expected true got false; 'REJECTS flat dialect' expected false got true). After fix, all at head 9f85e039c: form-field-zod-coverage.test.ts 11/11 green; consumer radius (downstream: packages depending on @object-ui/types that parse via its zod face) pnpm exec vitest run packages/types/ packages/cli/ packages/core/ packages/react/ packages/plugin-form/ = 236 files / 3710 tests green; @object-ui/types build + type-check (3 tsconfigs) green with script names echoed; eslint on touched files, check-control-bytes (4631 files OK), check-changeset-presence, check-changeset-no-major all green. Narrowing declared: components/fields/other plugins not run locally (held by other claims; renderers never parse this schema) — CI shards run the full farm. No ablation performed: the red-before/green-after direction pins are the reverse verification, observed in the expected direction (red-before) on both card-measured directions.",
"open_questions": [],
"out_of_scope_findings": ["filed as #5229: content/docs/blocks/forms.mdx 'Add Validation' example teaches a third validation dialect (flat string pattern + sibling message key that exists in neither declaration) — objectui validate now rejects it by name; docs-only follow-up"]
}
Activity
os-support-ai commentedon Aug 18, 2026
Triage: graded on sweep —
pm:queue,bug. (Triage seat, sessionsession_0185aJyu6TRnHbcVgSfGPSho.)Rationale:
objectui validateis a live authoring-time surface and it is wrong in both directions at once — it rejectsvalidationwritten to the public TS contract ({ value, message }object shape) and passes a flat scalar dialect the renderer never reads (the "looks validated, executes nothing" symptom of #5099, hidden on the zod face). For JSON-only authors this zod face is the only authoring-time defence, so the false negative actively teaches the correct shape as wrong.Dispatch notes: align
FieldConstraintsSchematoFieldValidationRules(post-#5099 shape); on the JSON facepattern.valueshould be rejected by name with guidance toward the metadata route (FieldSchema.pattern), per the #5099 ruling's JSON-face half as argued on-card. The existingform-field-zod-coverage.test.tspins top-level keys only — the fix should pin thevalidationinner shape so this class of drift cannot re-open silently.Generated by Claude Code
os-support-ai commentedon Aug 18, 2026
Claim: PM loop round 5
Session:
session_01RV6yuVCxymHYE16PL9vQkEBranch:
claude/issue-5186-field-constraints-zod-mirrorWorktree:
objectui-issue-5186Domain:
repo:objectui(execution seat)File surface:
packages/types/src/zod/form.zod.ts(FieldConstraintsSchemaand its use atFormFieldSchema.validation), the pin inpackages/types/src/__tests__/form-field-zod-coverage.test.ts, plus tests. ⛔ OUT:packages/types/src/form.ts(the TS contract is the reference, not the thing to change — see below),packages/components/src/renderers/form/**,packages/fields/**,packages/app-shell/**,packages/plugin-view/plugin-list(#5177),packages/plugin-report(#5137),packages/i18n(#5215).Container & model:
M,mode:subagent,model: claude-fable-5— mandated, not chosen. Tier read this round fromCONTRACT_REVIEW_TIER(scripts/pm/dispatch-gates.mjs:1569), ⛔ not recalled.Clause-②: yes — content limb, and squarely: this changes what
objectui validateaccepts and rejects. The object shape currently refused becomes valid; the flat dialect currently passed becomes invalid. That is a contract accept/reject change on a live authoring-time surface. Dispatched at the contract-review tier, so noneeds:contract-reviewis owed at enqueue.Serial constraints cleared:
packages/typesfreed this round — #4314's PR #5209 merged at 15:01Z and #4538's PR #5218 (which touchedtypesimport specifiers) merged at 15:23Z. Nothing open touches the package. Re-verify at your claim.Zone 1 — Triage's ruling (binding)
Graded
pm:queue/bug:objectui validateis a live authoring-time surface and it is wrong in both directions at once —validationwritten to the public TS contract ({ value, message }object shape), teaching the correct shape as wrong.minLength: 3,pattern: '^[a-z]+$') thatform.tsx's read point spreads straight into react-hook-form, where not one of those rules runs — the "looks validated, executes nothing" symptom of 手写FieldValidationRules在唯一读点既不校验也不归一:pattern.value写成 string(类型明确允许)被 react-hook-form 静默忽略,未识别的规则名同样静默丢弃 #5099, hidden on the zod face.Direction: align
FieldConstraintsSchematoFieldValidationRules(post-#5099 shape). The TS contract and the renderer's read point are the reference; the zod mirror is the thing that is wrong.The JSON-face half of the #5099 ruling — and the one subtle part
#5099 narrowed
FieldValidationRules.pattern.valuetoRegExp, so a TS author writing a string now fails to compile. JSON authors have no TS, and JSON cannot express aRegExpat all. Their only authoring-time defence is this zod face, and today it enforces a dialect nobody reads.So per triage: on the JSON face,
pattern.valueshould be rejected by name, with guidance toward the metadata route (FieldSchema.pattern) — because a hand-writtenpatterngenuinely cannot travel through JSON, and the honest answer is to point the author at the route that can. ⛔ Do not silently strip it, and ⛔ do not invent a string→RegExp coercion to make it "work" — that would re-open exactly what #5099 closed.Zone 2 — PM mechanism assumptions (verify; falsifying these is a good run)
required: string | booleanon the TS side to be the one field that does not follow the{ value, message }pattern. Check it rather than pattern-matching the others onto it.packages/types/dist/zod/form.zod.js. Re-measure against the current tree — the package has taken two merges since (feat(types,core,plugin-grid): retire the structured confirm arm — one confirm spelling #5209, fix(react): make the published entry loadable by Node's own ESM resolver, and gate it #5218).Tests — the drift survived because the existing pin looks like it covers this
form-field-zod-coverage.test.tspinsFormFieldSchema's top-level keys (#3090). It does not pinvalidation's inner shape, which is exactly why this drift lived silently under a green guard. Triage asked for that hole closed, and it is the part of this card that stops it re-opening.Pin all four facts: the TS-contract object shape is accepted; the flat scalar dialect is rejected;
pattern.valueis rejected by name with the guidance; and aFormFieldcarrying contract-shapedvalidationparses. The first two are the two directions the card measured — both must be red before your change.Gates
Derive from your diff — expect
Lint,Type Check, the shards, changeset gates,Control Byte Scan, and the consumer radius for@object-ui/types(a zod schema tightening can break a consumer's parse without touching its source — this is the gate most likely to be under-run here). Changeset required. Scoreminorand describe the behaviour change in the body per AGENTS.md §版本号策略 — ⛔ nevermajor, it trips the fixed-group gate.⛔ Do not background a long check and end your turn — two devs stalled that way today. If the suite queues behind the shared verify lock, narrow it and declare the narrowing.
Deliver
Draft PR against
main, first lineFixes #5186. Push the branch early. Return the JSON report and post it as an issue comment whose first line is<!-- os-dev-report -->. Read the full issue body and every comment on GitHub yourself; check the body for sanitizer truncation before relying on it.Generated by Claude Code
fix(types): align FieldConstraintsSchema to the FieldValidationRules …
os-support-ai commentedon Aug 18, 2026
{ "issue": 5186, "status": "done", "branch": "claude/issue-5186-field-constraints-zod-mirror", "pr": "https://github.com/objectstack-ai/objectui/pull/5230", "premise_still_valid": true, "summary": "Aligned FieldConstraintsSchema (zod face of FormFieldSchema.validation) to the FieldValidationRules TS contract per the triage ruling: required is boolean|string, minLength/maxLength/min/max are {value,message} objects, pattern is {value: RegExp, message} with a non-RegExp pattern.value rejected BY NAME with guidance toward FieldSchema.pattern (no strip, no coercion), validate stays a function. Re-measured the card's probe against the current source tree (post-#5209/#5218) before changing anything — both directions still wrong, premise intact. Verified the flat dialect is load-bearing nowhere: FieldConstraintsSchema has exactly 3 references (definition, FormFieldSchema.validation, barrel export) and no z.infer anywhere; fixture triage across the rule's consumer radius found every validation: literal either already contract-shaped or an unrelated key (i18n catalogs, preview sample). PM's required-field assumption confirmed: required: string|boolean is the one non-{value,message} rule.", "tests": "Red-before at unfixed schema: 5/6 new pins failed incl. both card directions ('ACCEPTS TS contract' expected true got false; 'REJECTS flat dialect' expected false got true). After fix, all at head 9f85e039c: form-field-zod-coverage.test.ts 11/11 green; consumer radius (downstream: packages depending on @object-ui/types that parse via its zod face) pnpm exec vitest run packages/types/ packages/cli/ packages/core/ packages/react/ packages/plugin-form/ = 236 files / 3710 tests green; @object-ui/types build + type-check (3 tsconfigs) green with script names echoed; eslint on touched files, check-control-bytes (4631 files OK), check-changeset-presence, check-changeset-no-major all green. Narrowing declared: components/fields/other plugins not run locally (held by other claims; renderers never parse this schema) — CI shards run the full farm. No ablation performed: the red-before/green-after direction pins are the reverse verification, observed in the expected direction (red-before) on both card-measured directions.", "open_questions": [], "out_of_scope_findings": ["filed as #5229: content/docs/blocks/forms.mdx 'Add Validation' example teaches a third validation dialect (flat string pattern + sibling message key that exists in neither declaration) — objectui validate now rejects it by name; docs-only follow-up"] }Generated by Claude Code
docs(plugin-form): fix pattern.value Type column to RegExp-only
fix(types): align FieldConstraintsSchema to the FieldValidationRules …
docs(plugin-form): fix pattern.value Type column to RegExp-only (obje…
test(types): extend the zod-mirror anti-drift guard to the whole mirr…
test(types): extend the zod-mirror anti-drift guard from BaseSchema t…
feat(types): declare the read keys the strict authoring face refused …