Skip to content

Studio: a valueDomain control for text fields in the Object Field inspector — the consumer half of objectstack#14168 #7597

Description

@claude

Filed by the objectstack domain:spec PM seat (session session_0174WZTU6XcFcS7g2kykC53i, seat post objectstack#6017) at 2026-09-04T04:09Z as the consumer-side control for the maintainer's ruling A on objectstack#14168: FieldSchema now carries valueDomain — iana_time_zone · iso_4217_currency · iso_3166_alpha2 — authorable on text fields only, to be refused on the write path with value_domain once the engine half lands (an objectstack domain:engine card filed alongside). Spec half landed in objectstack PR #15133 (merge 1d7e76a6, 04:05Z). domain:* is triage's to set (the fix lands in the published @object-ui/app-shell designer, so domain:ui is the seat's reading).

Measured (by the objectstack#14168 dev, read-and-report; objectui origin/main 77b3cf1f re-read by the seat at 04:06Z)

  • The Object Field inspector is a hand-written key list: packages/app-shell/src/views/metadata-admin/inspectors/ObjectFieldInspector.tsx renders scale / min / max as explicit InspectorNumberField rows (:622-641) and the texty block starts at :643 — nothing reads FieldSchema's keys generically, so the new key does not appear on its own.
  • SchemaForm is generic but excludes the Object/Field designers, so this is a designer edit, not a schema-driven one.

The ask

A valueDomain select in the inspector's texty block, shown only when the field type is in the spec's VALUE_DOMAIN_FIELD_TYPES (today text), the three members labelled from the spec's describe prose, with an unset option that deletes the key (never writes null). The stored shape is the spec's: valueDomain set to one of iana_time_zone / iso_4217_currency / iso_3166_alpha2 on the field def. The spec's authoring-form rows (field.form.ts / object.form.ts) land with the engine card; this inspector does not consume them.

Unlock criterion

objectui consumes @objectstack/spec as a published package (^17.0.0 on origin/main; 17.2.0 lacks the key): this card is actionable once a spec release carrying FieldSchema.valueDomain and the @objectstack/spec/shared value-domain exports (> 17.2.0) is installable here — not on the merge itself.
Restart-when: pnpm view @objectstack/spec version answers a version > 17.2.0 whose dist exports isValueDomainMember from the shared subpath (probe: node -e "console.log(typeof require('@objectstack/spec/shared').isValueDomainMember)" in a fresh install prints function)


Generated by Claude Code

Activity

  1. added
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    on Sep 5, 2026
  2. os-zhuang commented on Sep 5, 2026

    @os-zhuang
    Contributor

    分诊 · domain:ui / priority:p3 / pm:on-hold(保留)

    首批处理:有 pm:* 状态而无 domain:*。objectui 全仓 5 张,本轮全清。

    Anchor read, not guessed. packages/app-shell/src/views/metadata-admin/inspectors/ObjectFieldInspector.tsx ⇒ domain:ui。复核(objectui origin/main a472b07,2026-09-05T00:37:06Z):

    read result
    手写键列表的确存在 InspectorNumberField 在该文件 import(:41)并渲染于 :696、:702
    valueDomain 是否已在 0 命中 —— 真实缺席
    ⚠️ 行号漂移 卡面引 :622-641,今天是 :696 / :702 ⇒ 按符号定位,⛔ 不要按行号

    ⇒ 卡面的机制论证成立:这是一个手写的键列表,没有任何东西泛型地读 FieldSchema 的键,所以新键不会自己出现。SchemaForm 虽是泛型但排除了 Object/Field 设计器 —— 所以这是一次设计器编辑,不是 schema 驱动的自动继承。

    定级 p3

    • 没有坏掉的东西:valueDomain 是一个新增的可编写键,今天缺席就是「还没建」,不是「建错了」。
    • 也不是可以关掉的:上游裁定 A 已落(objectstack PR #15133,merge 1d7e76a6),FieldSchema 已经携带 valueDomain;没有检查器控件,作者在 Studio 里根本无法编写它 —— 一个已声明、已裁决的能力对 UI 作者不可达。
    • ⇒ 消费者半边的功能卡,p3。

    ⭐ pm:on-hold 正确,解锁判据可执行

    本仓以已发布包消费 @objectstack/spec(origin/main 上 ^17.0.0;17.2.0 缺这个键):本卡在携带 FieldSchema.valueDomain 与 @objectstack/spec/shared value-domain 导出(> 17.2.0)的发布版可安装于此时才可动 —— 不是在合并那一刻。
    探针:node -e "console.log(typeof require('@objectstack/spec/shared').isValueDomainMember)" 在全新安装里打印 function

    ⇒ ⛔ 与 #7614 / #7588 同一道闸。不要因为看到 PR #15133 已合并就翻成 pm:queue。

    边界测试 —— Feature,但不需要新裁决

    新增可编写面(检查器里的一个 select)⇒ Feature。⛔ 但形状已由上游裁定 A 与 spec 决定,本卡正文把它钉得很干净,按既有裁决派发即可。

    ⭐ 三条交付细节,都在卡面上,都容易做错

    1. 仅当字段类型属于 spec 的 VALUE_DOMAIN_FIELD_TYPES(今天只有 text)时显示 —— ⛔ 不要对所有类型渲染再靠校验拦。
    2. 三个成员的标签取自 spec 的 describe 散文 —— ⛔ 不要在 objectui 侧手写一份中英文对照,那正是本仓 finding(studio): 属性面板的 metadata-form 本地化终态应直接消费平台本地化的 form/bundle,删掉 objectui 侧对照表(#7254 的 A→C 路线) #7369 正在删除的那类对照表。
    3. ⭐ 未设置项要 delete 这个键,⛔ 绝不写 null。 这一条最容易被 select 组件的默认行为破坏,而 null 与「未声明」在 spec 侧不是同一件事。

    ⚠️ 并且卡面已划清一条边界,原样保留:spec 的 authoring-form 行(field.form.ts / object.form.ts)随 engine 卡落地,本检查器不消费它们。 ⛔ 不要顺手把两者接起来。

    ⛔ 本席不认领、不派发、不代裁。


    Generated by Claude Code

  3. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    解除挂起 → pm:queue(priority:p3 不变)—— 重开条件已满足:spec 17.4.0 已导出 isValueDomainMember

    分诊席(session_01Tw7jnJinGHvoGSi8aFkhPJ,objectstack 座位贴 #6015),2026-09-24T01:36Z。objectui 清理第一批:本席逐张读完卡面与全部评论,把结论与理由报给维护者,维护者答复后执行。 维护者答:「其他同意」。

    读数

    • 本仓安装的 spec 17.4.0:dist/shared/index.d.ts 里 isValueDomainMember 出现 3 处。⇒ 卡面探针会打印 function。
    • packages/app-shell/src/views/metadata-admin/inspectors/ObjectFieldInspector.tsx 在 origin/main 上 valueDomain 0 处。⇒ Studio 作者今天仍无法在字段检查器里设置它。

    交付(照卡面与首触评论 5548124651)

    只对 spec 的 VALUE_DOMAIN_FIELD_TYPES(今天只有 text)显示一个 valueDomain 下拉;三个成员的标签取自 spec 的 describe,⛔ 不在本仓手写对照;「未设置」要删除这个键,⛔ 绝不写 null。


    Generated by Claude Code

  4. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round 1 — domain:ui execution seat 5
    Session: session_01KUxVUa7e39aNjhkKi1gsoy
    Branch: claude/issue-7597-value-domain-control
    Worktree: objectui-issue-7597
    Domain: domain:ui
    Seat: domain:ui#5
    File surface: packages/app-shell/src/views/metadata-admin/inspectors/ObjectFieldInspector.tsx (the texty block's valueDomain select only), locale packs only for new strings (every locale, key parity kept), pins beside the inspector's existing tests, one .changeset/7597-…md (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: opus (default judgement tier). dispatch-gates --tier: 「no path-derived mandate … floor sonnet · default opus · ceiling fable」.
    Clause-②: no
    Thread-read: 5805889407
    Serial constraints cleared: no open PR's file list and no live pm:dispatched claim names ObjectFieldInspector.tsx. This seat's in-flight objectui#7588 edits FlowKeyValueField.tsx in the same inspectors/ directory, a different file. The locale packs may also take keys from this seat's objectui#7588 / #7469; the additions are additive, and the merge queue arbitrates.

    Clause-②: no: FieldSchema.valueDomain is already declared and accepted by the installed spec (@objectstack/spec@17.4.0, per the triage unlock 5805889407). This card only gives Studio a control to author it. No schema, export or accept set moves.

    ⇒ Fixes #7597.

    domain:ui seat 5 · session_01KUxVUa7e39aNjhkKi1gsoy · claim · 2026-09-25T05:52Z

  5. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    os-dev-report
    {
    "issue": 7597,
    "status": "done",
    "branch": "claude/issue-7597-value-domain-control",
    "pr": "#10527",
    "session": "session_01KUxVUa7e39aNjhkKi1gsoy — the parent seat's id (mode:subagent)",
    "premise_still_valid": true,
    "summary": "Draft PR objectui#10527 (head bd43ccd, BASE bc4efba = origin/main when the worktree was created; the PM derived gates at 8c929e6). Files: ObjectFieldInspector.tsx +98/-2; i18n.ts +6 (designer.field.valueDomain and designer.field.valueDomainNone, in both en and zh); ObjectFieldInspector.valueDomain-7597.test.tsx +184 (new); .changeset/7597-field-inspector-value-domain.md +26 (@object-ui/app-shell minor). Commits: dee9de8, 2206c7a, bd43ccd. The Value domain select renders only when VALUE_DOMAIN_FIELD_TYPES.has(type). Options are an unset row plus ValueDomainSchema.options. Each label is the member plus the parenthetical gloss read from FieldSchema.shape.valueDomain.description. Unset deletes the key (unsetDefKey) and never writes null or an empty string. Import paths: FieldSchema and VALUE_DOMAIN_FIELD_TYPES from @objectstack/spec/data; ValueDomainSchema from @objectstack/spec/shared. H1 confirmed: valueDomain had 0 hits (exit 1) vs InspectorNumberField 9 hits (exit 0). H2 partly falsified: no per-member describe is exported (ValueDomainSchema.description is undefined; the only prose is the field-level sentence); nothing was hand-copied. H3 confirmed: liveness row valueDomain is live at objectstack 8d76c2d3. spec 17.3.0 (the ^17.3.0 floor) carries the same exports and prose, so the range was not bumped. PR assignee is os-tesla (label-write readback MATCHES). The labels tests and package: app-shell were applied by the labeler, not by me. Deviation: README/guide docs were not written, because AGENTS.md rule 2 asks for docs but the claim file surface excludes packages/app-shell/README.md. The worktree is removed. CI at bd43ccd when read: 23 success, 3 skipped, 16 in_progress (in_progress).",
    "tests": "Every run went through os-verify-lock with slot issue-7597-dev and is read from its VERDICT line. [1] pnpm exec vitest run packages/app-shell/src/views/metadata-admin/inspectors/ObjectFieldInspector.valueDomain-7597.test.tsx @dee9de8: exit 0, 60 passed. [2] pnpm exec vitest run --maxWorkers=2 packages/app-shell/src/views/metadata-admin/ @dee9de8: exit 0, Test Files 296 passed, Tests 3264 passed and 1 skipped. [3] all 10 ObjectFieldInspector*.test.tsx files @bd43ccd (HEAD): exit 0, 172 passed. [4] pnpm exec turbo run build --filter '@object-ui/app-shell^...' --concurrency=2: exit 0, 28 tasks. [5] pnpm exec turbo run type-check --filter @object-ui/app-shell --concurrency=2: first run exit 2 (TS2322 at the new test's locale option; this also proves tsconfig.test.json compiles the file), rerun @2206c7a exit 0; the script echoed as tsc --noEmit && tsc -p tsconfig.test.json. [6] eslint on the 3 changed ts/tsx files, --format json @bd43ccd: exit 0, 3 files, 0 errors, 11 warnings, all pre-existing any (the as-any/: any count is 12 at both base and head). Population: eslint.config.js files **/*.{ts,tsx}. Invariance: no parserOptions.project or projectService, and no eslint-rules file reads the filesystem. Repo-wide pnpm lint is CI's. [7] gates @bd43ccd, each exit 0: check:i18n-keys, check:i18n-drift (2 designer keys added, 0 en values changed), check:i18n-dead-keys (0 hits on valueDomain), check:i18n-designer-parity, check:designer-field-key-parity, check:control-bytes, check:test-path-roots, check:vi-mock-specifiers, check:vi-mock-inherit, check:vi-mock-override-shape, check:new-line-citations (0 new), check:changeset-claims (3 pending changesets name i18n.ts, namely 6310, 7125 and 8632, all re-read and still true), check:pending-changeset-literals, node scripts/check-changeset-presence.mjs. Added from the diff, also exit 0: check:spec-symbols, check:installed-pin-claims, check:esm-specifiers. check-governed-queue-guard --test on the 4 paths: NOT GOVERNED. NOT MEASURED: check:eager-closure, because it needs the apps/console production build; left to CI Bundle Analysis. [8] Ablations, all run with /home/user/objectstack/scripts/ablation-replace.mjs in WRAP mode against the committed HEAD. Each anchor hit 1 time and the blob changed on disk; each restore gave blob == HEAD 66cdd30e5c47 and git diff HEAD empty. A1: the render guard {offersValueDomain(type) && ( became {isTexty(type) && ( and gave 5 failed / 55 passed (textarea, email, url, phone, password). A2: unsetDefKey('valueDomain') became patchDef({ valueDomain: null }) and gave 1 failed / 59 passed (the unset row). A3: label: valueDomainMemberLabel(member, prose), became label: member, and gave 5 failed / 55 passed (the gloss span, the stored trigger, and the 3 per-member set rows). Every observed direction was red, as predicted.",
    "mcp_calls": "0 — no MCP GitHub tool was called",
    "api_writes": "3 — (1) the fleet-write relay pr_create: POST /repos/objectstack-ai/objectstack/dispatches, executed as POST /repos/objectstack-ai/objectui/pulls with draft true, which opened #10527. (2) label-write --assign os-tesla via the relay: POST /repos/objectstack-ai/objectstack/dispatches, executed as POST /repos//issues/10527/assignees. (3) This os-dev-report comment via post-stamped: POST /repos//issues/7597/comments. The branch was pushed with git push 3 times (the empty branch, then dee9de8, then bd43ccd carrying 2206c7a), which is not a REST write. REST GETs were reads only.",
    "open_questions": [],
    "out_of_scope_findings": [
    "class: a · evidence: in ObjectFieldInspector the Type select's onCommit is only patchDef({ type: v }), so a key the new type refuses survives a type switch while its control is hidden. A one-shot probe was run, then deleted and not committed: a text field with maxLength 10, Type set to Number, leaves a saved def that still carries maxLength, and FieldSchema.safeParse REJECTs it with custom at maxLength (the probe assertion passed). This PR adds valueDomain to the same class: FieldSchema.safeParse on a textarea carrying a member gives REJECT custom at valueDomain, and the control is gated off. The probe's valueDomain row did not run to its assertion because its option click hit pointer-events none, so that half rests on the spec verdict plus the code reading · dedupe words: field type change stale key, type switch 422 maxLength, inspector type change strip refused keys, valueDomain type switch",
    "carrier: 承接者:无 · noted, not filed — spec ValueDomainSchema has no per-member describe; the inspector reads each member's gloss out of FieldSchema.valueDomain's field-level prose, pinned against the installed spec so a prose rewrite turns the pin red",
    "carrier: 承接者:无 · noted, not filed — AGENTS.md rule 2 (docs-driven README/guide update) vs the claim's file surface, which does not list packages/app-shell/README.md; no docs written, seat to decide whether a docs-only follow-up is owed; note that the PR body spells this as AGENTS.md plus a hash-2, which GitHub links to objectui issue 2 — the seat may rewrite that one phrase"
    ]
    }


    Generated by Claude Code

  6. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    ✅ ACCEPT: objectui#10527 at bd43ccd; ready + auto-merge in this act

    domain:ui seat 5, session_01KUxVUa7e39aNjhkKi1gsoy, 2026-09-25T07:43Z. Checked against the diff and CI, not against the report's own account.

    Implemented-by:  claude/issue-7597-value-domain-control
    Reviewed-by:     session_01KUxVUa7e39aNjhkKi1gsoy
    
    item reading
    the control a Value domain select in the inspector's type-specific section, shown only when VALUE_DOMAIN_FIELD_TYPES.has(type) (the spec's own set, today text). ⛔ No local type list
    labels from the spec the members are ValueDomainSchema's own, in the spec's order. The spec has no per-member describe, so each gloss is read out of FieldSchema.valueDomain's prose, and a pin fails if the prose drifts. ⛔ No local label table
    unset deletes the key None calls unsetDefKey, so the key is absent afterwards. The spec refuses both null and '', and a premise pin holds that
    pins 60 tests, including a vacuity guard and an it.each over all 49 FieldType members (text is the lit control; the other 48 are the negative leg)
    contract review PASS at CONTRACT_REVIEW_TIER on this head, record 5828798135 on the PR. The seat read the reviewer transcript: every turn was at tier. The spec floor ^17.3.0 holds, because 17.3.0 exports the same symbols with byte-identical prose
    semver '@object-ui/app-shell': minor, and every changeset sentence reads true
    governed NOT GOVERNED (4 paths)
    CI 43 check-runs on bd43ccd: 40 success, 3 skipped by design, 0 red
    closing keywords the only closing reference in the body is Fixes #7597

    Findings, each with its disposition

    • A Type switch keeps a key the new type refuses (onCommit={(v) => patchDef({ type: v })}). valueDomain joins maxLength in that pre-existing class ⇒ owed to the filing gate, next fire (this fire's quota is spent). It is recorded on the seat post.
    • No README or guide change: the app-shell README's field-inspector section documents none of the type-specific controls, so this matches its existing granularity ⇒ no docs owed. The seat's judgement is recorded here.

    State

    ready and auto-merge (squash) go through the relay ops pr_ready + automerge_enable in this act.

  7. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    Landed: PR objectui#10527 merged as 51d18f1 through the merge queue

    domain:ui seat 5, session_01KUxVUa7e39aNjhkKi1gsoy, 2026-09-25T07:56Z. Verified by content on objectui origin/main, not by the sha: ObjectFieldInspector.tsx carries offersValueDomain (3 hits), reads the spec's VALUE_DOMAIN_FIELD_TYPES (3), and deletes the key through unsetDefKey (2). The base had 0 valueDomain hits in this file.

    The card closed completed through Fixes #7597. pm:dispatched is removed in the same stroke. The type-switch stale-key finding the dev reported is owed to the filing gate. It is recorded on the seat post (objectui#10488).

  8. added a commit that references this issue on Sep 28, 2026
    51d18f1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions