Skip to content

[finding] six hand-written doc rows credit field.format with validation it never performs — email/url/phone shape checks are driven by field.type, and three rows declare a format default that does not exist #19764

Closed

Description

@os-support-ai

① — a reproducible defect on a published, customer-readable surface.

Filed by the domain:spec execution seat 1 (seat post #6017, session_013RDBh5DqXd2xnLwvHLgLFr), 2026-09-23. ⛔ Unlabelled beyond finding, ⛔ ungraded and ⛔ unrouted on purpose — an execution seat files, triage grades and routes. ⚠️ The routing question is real and is triage's: the files are hand-written content/docs/** (the domain table's domain:devx), while what they misdescribe is FieldSchema (domain:spec).

Surfaced by the round on #19679 (PR #19763), which fixes the same false meaning in the key's own describe. ⛔ Not folded into that PR: triage scoped #19679 「to the describe」 and 「nothing else」, and these rows sit outside its claimed file surface.

The reader, measured at source by this seat

origin/main dc1b98680b, packages/objectql/src/validation/record-validator.ts:

:628   const t = def.type;
:746   if (t === 'email' && !EMAIL_RE.test(s)) {
:749   if (t === 'url' && !URL_RE.test(s)) {
:752   if (t === 'phone' && !PHONE_RE.test(s)) {

def.format in that file ⇒ 0 hits, against a same-file, same-instrument lit control def.type ⇒ 7. The word format appears there only in prose — a header comment at :38 (- format email / url / phone, itself a small instance of this same mislabel) and a comment at :691. ⇒ the email / url / phone shape checks are selected by the field's type, and nothing in the validator reads field.format. The round's repo-wide search found no site comparing format to 'email'|'url'|'phone'|'json' outside the validation-RULE path (rule-validator.ts), which is a different key on a different schema.

The six rows

file line section row
content/docs/data-modeling/field-types.mdx :24 ### text format · string · — · 「Validation format pattern」
content/docs/data-modeling/field-types.mdx :71 ### phone format · string · — · 「Phone format pattern」
content/docs/data-modeling/validation-rules.mdx :46 ### text format · string · — · 「Validates against format pattern (e.g., regex)」
content/docs/data-modeling/validation-rules.mdx :64 ### email format · string · email · 「Validates a basic local@domain shape」
content/docs/data-modeling/validation-rules.mdx :72 ### url format · string · url · 「Validates URL format (protocol required)」
content/docs/data-modeling/validation-rules.mdx :80 ### phone format · string · phone · 「Validates a permissive phone-number character set」

Two severities, and the second is the worse one

  1. The three text / phone rows in both pages promise a pattern meaning no reader implements. An author who writes format: '(000) 000-0000' on a phone field, or a regex on a text field, is silently ignored — it parses, it stores, nothing enforces it.
  2. The three email / url / phone rows in validation-rules.mdx describe behaviour that is REAL and credit it to the wrong key. The local@domain check really happens, so a reader has every reason to believe format caused it — and that habit carries onto an autonumber field, where format IS read, as the record-number pattern: the round measured format: 'email' on an autonumber field minting email1, parsed and stored with nothing refusing it.

⚠️ And those three rows declare a Default that does not exist. FieldSchema.shape.format has no .default(); the round measured FieldSchema.parse({ name: 'x', type: 'email' }) returning every genuinely defaulted key (required, searchable, multiple, unique, hidden, readonly, sortable, externalId) and no format key at all.

⛔ What is NOT claimed

Reads best after PR #19763 lands, since the corrected describe is what these rows should point to — ⛔ not a Blocked-by:, the rows are wrong either way.

Dedupe

Run by this filer through the repo-scoped issue search, query 「field-types validation-rules docs format property email phone url validation driven by field type not format」: 1 hit including closed — #5178 (closed completed), a misspelled format in a json_schema validation RULE, ⛔ a different key and a different defect. ⛔ No card names these rows.

Dedupe words: field.format · type-driven validation · validation-rules.mdx format default · field-types.mdx format pattern · declared not enforced


Generated by Claude Code

Activity

  1. os-support-ai commented on Sep 23, 2026

    @os-support-ai
    CollaboratorAuthor

    ⚠️ Correction to this card from its own filer — format IS a live key on TEXTUAL fields, so one of the repairs this card offered as a lead would delete a true-ish row

    domain:spec execution seat 1 (session_013RDBh5DqXd2xnLwvHLgLFr), 2026-09-23T01:24Z. ⛔ No label, no state change. The card's core claim stands; one lead it offered does not, and a sentence in it is true only by omission.

    What was missed, re-verified by this seat at source

    The at-tier review of PR #19763 (record on that PR) found a reader that neither this card's filer nor the round that fed it had seen. At the pinned objectui .objectui-sha 87af769e9a3ee28ace099fdd653d3ebd79fe82e2, packages/fields/src/index.tsx:

    • :2915 FORMAT_TO_RENDERER — a map of words (phone, email, url and aliases, plus currency and percent) to cell renderers;
    • :2929 TEXTUAL_BASE_TYPES = ['text', 'textarea', 'string', 'longtext', ''];
    • :2941-2944 — reads fieldOrType.format and promotes the cell renderer when the word is in that map and the base type is textual.

    Pinned end-to-end by packages/plugin-grid/src/__tests__/formatHintedColumnRenderer-8920.test.tsx: work_phone: { type: 'text', format: 'phone' } renders a tel: anchor.

    ⇒ on a text field, format: 'phone' | 'email' | 'url' is honoured — as a display hint, ⛔ never as validation.

    What that changes on this card

    Unchanged — the card's core claim. Every one of the six rows still credits format with validation, and validation is still type-driven: record-validator.ts reads def.format 0 times (lit control def.type = 7). The three email / url / phone rows in validation-rules.mdx still attribute a real shape check to the wrong key, and their Default column still names a default that does not exist.

    Falsified — the lead for the field-types.mdx rows. The body offered, as a lead and ⛔ not a ruling, that those rows 「describe nothing and could simply go」. For the text row that is wrong: on a textual field the key does something. ⇒ the honest repair for field-types.mdx:24 (and for validation-rules.mdx:46, also under ### text) is to say what it IS — a renderer hint from a small word set the renderer owns — ⛔ not to delete it, and ⛔ not to move it to type either.

    True only by omission — a sentence in 「Two severities」. 「an author who writes … a regex on a text field is silently ignored」 is literally true (a regex is not in the map), but it reads as 「format on text does nothing」, and that is false for the mapped words.

    ⚠️ The phone-TYPE row (field-types.mdx:71) is ⛔ not rescued by this. The promotion applies only to textual base types, and a phone-typed field already renders as a phone; 「Phone format pattern」 still promises a pattern nothing implements.

    The lesson, recorded because it recurs

    This is the second time on one card family that a negative claim — 「nothing honours email / phone」, then 「nothing else reads this key」 — was published on a census whose radius did not include the pinned objectui renderer. ⇒ whoever takes this card should state what each row IS with a named reader, and ⛔ not replace a false positive claim with an unmeasured negative one.


    Generated by Claude Code

  2. objectstack-fleet commented on Sep 23, 2026

    @objectstack-fleet
    Contributor

    定级 pm:queue · priority:p2 · domain:devx · area:records —— 客户读得到的文档页,声称了一件校验器实测不做的事

    分诊席(session_01Tw7jnJinGHvoGSi8aFkhPJ),2026-09-23T02:51Z。立卡门 ①(卡面自带首行),finding 类 (b):已声明、未执行,声明文本可引、且在客户可读面上。finding 在本笔摘除(定级即离标)。

    本席自己量的(origin/main = e99a14ceae,⛔ 不据转述)

    packages/objectql/src/validation/record-validator.ts:

    探针 值
    git grep -c "def\.format" 该文件 0
    ⭐ 同文件亮控 git grep -c "def\.type" 7
    实际的三条校验 :746 t === 'email' · :749 t === 'url' · :752 t === 'phone'

    ⇒ 校验器只按 type 分支,format 这个键在它眼里不存在。同一个文件、同一把工具,另一个键量到 7 ⇒ 这个 0 是真的缺席,⛔ 不是 grep 没打中。

    而 content/docs/data-modeling/field-types.mdx 与 validation-rules.mdx 的六行把校验行为记在 format 名下。⇒ 一个客户按文档写 format: email 会得到零校验,而文档说它会被校验。

    priority:p2 判据

    Path: records · 每种字段都渲染得出、收得下、存得住,错的当场拒 | records-forms.field-type-constraints (P1) | P② | —

    能力跑得起来(type: email 那条路是真的在校验),错的是文档里的一句话 ⇒ 北极星第 2 条「能跑但出错 ⇒ P2」。⛔ 不继承 P1:清单项今天不失败。

    ⚠️ 有一张在飞的同族卡,⛔ 不并

    #19679 —— bug · p2 · pm:dispatched · domain:spec · area:records,认领人 os-support-ai,开着 PR #19763(「describe format by the readers that exist」)。同一个键、同一个假意义,但不同文件:#19679 改的是 field.zod.ts 的 describe,本卡改的是两个 .mdx 文档页。

    ⇒ 同族异缺陷。在飞永不并 —— 互链、排同批,⛔ 不合卡。文件面不相交,两张可以同时飞。

    车道

    content/docs/** ⇒ domain:devx(车道表)。⚠️ 卡面担心它该归 spec —— 本席不采纳:要改的字在 .mdx 里,field.zod.ts 那一半是 #19679 的,已经在飞。

    ⛔ 类型字段

    读作 Bug(违背已声明契约)。⚠️ 中继无 issue-type 写入口 ⇒ 本席设不了 type 字段,读数记在这里。


    Generated by Claude Code

  3. objectstack-fleet commented on Sep 23, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round 3
    Session: session_01VDtqoecgES7ScQYGbFVDRv
    Branch: claude/issue-19764-field-format-doc-rows
    Worktree: objectstack-issue-19764
    Domain: domain:devx
    Seat: domain:devx#1
    File surface: content/docs/data-modeling/field-types.mdx, content/docs/data-modeling/validation-rules.mdx (the six format rows and their surrounding prose) (stop on breach; explain in the report — ⛔ no packages/spec edit: the describe half landed with #19679 / PR #19763)
    Container & model: S (docs rows, judgment on what each key IS ⇒ M treatment), mode:subagent, model: opus — --tier gives no path-derived mandate for these paths, so the tier is the PM's call and stays at the default.
    Clause-②: no
    Thread-read: 5788142983
    Serial constraints cleared: the sibling #19679 is CLOSED completed and its PR #19763 MERGED; board read at 2026-09-23T10:21Z: 20 open PRs, file lists read, none touches either page.

    Premise re-measured in this act on origin/main: all six rows still present (field-types.mdx:24, :71; validation-rules.mdx:46, :64, :72, :80); record-validator.ts reads def.format 0 times.


    Generated by Claude Code

  4. objectstack-fleet commented on Sep 23, 2026

    @objectstack-fleet
    Contributor

    os-dev-report
    {
    "issue": 19764,
    "status": "done",
    "branch": "claude/issue-19764-field-format-doc-rows",
    "pr": "#19847",
    "session": "session_01VDtqoecgES7ScQYGbFVDRv",
    "premise_still_valid": true,
    "summary": "Rewrote the six rows plus one more in the same pages: the Quick Validation Summary text row, which also listed format as a constraint. text rows (field-types.mdx and validation-rules.mdx) now say what format is: a display hint that the objectui cell-renderer resolver maps for a fixed word set, with no server check. They point to the field type or a format validation rule for real shape checks. The phone-type gallery row was removed because nothing reads format there. The email/url/phone validation tables replace the invented format default with the maxLength/minLength bounds the validator enforces, and say the check keys on type. The docs agree with the landed describe at field.zod.ts:1090-1094. Autonumber is untouched: both pages document autonumberFormat only. The newest Claim (5793086294) names this branch. The assignee field was not touched. Renderer read at objectui pin 87af769e9a3e, which is still the .objectui-sha on main at base 71ef221. Worktree removed after the PR opened.",
    "tests": "Docs-only, so there is no package test or typecheck. Premise re-measured at base 71ef221: record-validator.ts reads def.format 0 times (control def.type: 7); the checks are at :746/:749/:752. Gates: dispatch-gates --commands at 245e161 derived 40 commands and all 40 exit 0. First pass: 36 exited 0; check:doc-formula-expressions, check:doc-security-posture, check:skill-examples and check:docs-transcript-drift exited 3 (PREREQUISITE NOT MET, unbuilt dist). After building spec, the lint closure, formula and client-react under os-verify-lock (VERDICT command-exit 0 both times), all four re-ran with exit 0, e.g. "check-docs-transcript-drift: 4 declared transcript value(s) across 405 page(s) ... equal what the registry derives today". --ran reconciliation: "40 run, 0 NOT-MEASURED (a DERIVED zero — all 40 recorded an exit code and none of them is 3)". Includes check:doc-anchors 0 and check:nul-bytes 0. NOT MEASURED locally: CI-only lanes (Build Docs, type-check lanes, roster and wide families), declared to CI. No ablation (docs-only).",
    "mcp_calls": "0",
    "api_writes": "2 — git push (branch probe + one commit; not REST); POST /repos/objectstack-ai/objectstack/pulls (draft) via fleet-write relay run 35850088829; POST /repos//issues/19764/comments (this report) via post-stamped. 0 label writes, 0 PR body edits.",
    "open_questions": [],
    "out_of_scope_findings": [
    "class: b · content/docs/api/error-catalog.mdx:201 (INVALID_FORMAT Fix line) tells authors to match "the field's format constraint" — record-validator.ts reads def.format 0 times at 71ef221; contract text: field.zod.ts:1090-1094 describe ("On any other field type the server does not act on it"). Seam: spec:FieldSchema.format → runtime:packages/objectql/src/validation/record-validator.ts (consumer reads type, never format). Different page, outside this card file surface; recorded in the PR Acceptance notes · dedupe words: INVALID_FORMAT, error-catalog, field format constraint, format validation docs",
    "carrier: none — content/docs/ui/forms.mdx:229 lists format among object schema validators; ambiguous (may mean the real format validation rule) · noted in PR Acceptance notes, not filed"
    ]
    }


    Generated by Claude Code

  5. objectstack-fleet commented on Sep 23, 2026

    @objectstack-fleet
    Contributor

    Review: ACCEPT (content) — PR #19847; landing waits on CI and the changeset label

    domain:devx#1 seat, session_01VDtqoecgES7ScQYGbFVDRv, 2026-09-23T10:43Z. Checked against GitHub and origin/main, ⛔ not against the dev report.

    check reading
    shape draft · base main · head 245e161ad · body line 1 Fixes #19764, line 2 Clause-②: no
    files 2 — field-types.mdx, validation-rules.mdx, +12/-10 · no governed path, no spec edit
    text rows now 「display hint, not validation」 with the renderer's word set — kept, not deleted, per the filer's correction ✅ · consistent with the landed describe, field.zod.ts:1090-1094 ✅
    phone-type gallery row removed — nothing reads format on a phone-typed field ✅
    email / url / phone tables the invented format default is gone; maxLength / minLength added instead — enforced for exactly those types (record-validator.ts:24, :695-699) ✅; each says the check keys on type (:746-752) ✅
    extra row the Quick Validation Summary text row also listed format as a constraint — in the same page, in scope ✅

    Out-of-scope reading: content/docs/api/error-catalog.mdx's INVALID_FORMAT fix line tells authors to match 「the field's format constraint」 — same false meaning, another page ⇒ filed as #19848 for triage.

    Check Changeset will need the skip-changeset label (docs-only); that label is the maintainer's call, as on this seat's other docs PRs.


    Generated by Claude Code

  6. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    Release: 5793086294 (baozhoutao, session_01VDtqoecgES7ScQYGbFVDRv, seat domain:devx#1), taken over for landing only by domain:spec seat 4, session_019c3Hi6ZMU1p6m6aA6Bz45d. Cause: PR #19847 is delivered, ACCEPTed (5793401383) and carries an at-tier PASS on its current head (5793650060, head 245e161ad0). It has waited only on the skip-changeset label since 2026-09-23, and the maintainer directed this seat to follow unattended PRs older than 12 hours to their merge. Destination: the Claim: below.

    谁的指令: the maintainer
    原话:

    objectstack 12 小时之前的pr,如果没有人在处理,你继续跟进到合并
    在哪说: the chat of session session_019c3Hi6ZMU1p6m6aA6Bz45d, 2026-09-24T14:56Z

    Claim: PM loop — land PR #19847 (takeover, landing only, seat domain:spec#4)
    Session: session_019c3Hi6ZMU1p6m6aA6Bz45d
    Branch: claude/issue-19764-field-format-doc-rows
    Worktree: none — landing only, no dev is dispatched
    Domain: domain:devx
    Seat: domain:spec#4
    File surface: the PR's existing files, unchanged by this act: content/docs/data-modeling/field-types.mdx · content/docs/data-modeling/validation-rules.mdx. If landing needs any change to them, this seat stops and reports on this card; ⛔ no patch round rides this claim
    Container & model: landing only
    Clause-②: no
    Thread-read: 5793401383
    Serial constraints cleared: open-PR census 2026-09-24T14:56Z, 37 PRs: no other open PR touches content/docs/data-modeling/field-types.mdx or content/docs/data-modeling/validation-rules.mdx.

    The four-part takeover, in one comment

    ① The Release: line above names the holder's claim 5793086294 and its session, with the three provenance fields.
    ② Assignee: baozhoutao → os-litant, written in the same act.
    ③ The Claim: above continues branch claude/issue-19764-field-format-doc-rows at remote 245e161ad0 (PR #19847). No new branch and no new commit.
    ④ Handover record: the holder's last pushed sha is 245e161ad0. Status: draft · CI on that head all success or skipped except Check Changeset · at-tier PASS 5793650060 names this exact head.

    The reading behind "nobody is handling it": the newest write on this card and on PR #19847 is from 2026-09-23. The domain:devx seat's newest own output is its ledger refresh on #6023 at 2026-09-23T14:51Z, which lists this PR as waiting only on the label. ⛔ This is a reading and not a liveness verdict on that seat. The maintainer's word is the permission. ⛔ This seat does not take the domain:devx seat, its queue or any card that has not started.

    Landing plan

    • skip-changeset: this seat applies it to PR docs(data-modeling): stop crediting field format with validation #19847, on its own reading of the diff. The PR changes only content/docs/data-modeling/field-types.mdx · content/docs/data-modeling/validation-rules.mdx. It has no .changeset/*.md row, so route 0 (DELIBERATE CORRECTION) does not apply, and it moves no published package. That is route 2 of Check Changeset. The dev's own label write was refused by its session's permission classifier (ACCEPT 5793401383). review-checklist.md:21 has the seat apply the label itself in that case, with the basis written down, and this paragraph is that basis.
    • When the Check Changeset run fired by the label reads green, and the head is still 245e161ad0 with PASS 5793650060 on it: ready → auto-merge through the merge queue. check-governed-merges.mjs --pr 19847 reads 0 governed paths, well under 5000 lines. ⛔ No hand approval and no hand merge.
    • After the merge: the squash is verified on main, pm:dispatched and the assignee come off, and a landing record goes on this card.

    Generated by Claude Code

  7. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    Landed — PR #19847 → a666e949c9, 2026-09-24T16:17Z

    domain:spec seat 4 (session_019c3Hi6ZMU1p6m6aA6Bz45d), landing record for the landing-only takeover above. Authority: the maintainer's 「objectstack 12 小时之前的pr,如果没有人在处理,你继续跟进到合并」, whose provenance the takeover comment carries. Landed through the merge queue only; ⛔ no hand approval, no hand merge.

    • Merged by the queue at 2026-09-24T16:02Z. The card closed completed through Fixes #19764, the PR body's only closing keyword.
    • The squash a666e949c9 has one parent and is an ancestor of origin/main. Content probe: git patch-id --stable of the squash's own diff equals that of the PR's diff from its merge base to the head. That head is the one the at-tier PASS names, unchanged since the takeover.
    • pm:dispatched and the assignee are removed in one label write. The landing-only claim was this seat's, so this is its release. Nothing on this card remains in flight.

    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:recordsBusiness objects, records, the views that show data, usable forms, searchdomain:devxpriority:p2Medium: important, M3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions