Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

objectui: AddressField 的 AddressValue 只覆盖 spec AddressValueSchema 七个部件里的五个 —— countryCode / formatted 既不可类型化,formatted 还会在编辑后留成旧值(当前休眠)— observation #4052

Closed as not planned

Description

@os-zhuang

Migrated from objectstack-ai/objectstack#6968 under the file-at-destination ruling (objectstack-ai/objectstack#7167, maintainer 2026-08-10). Originally filed 2026-08-09T06:33:27Z. The full prior thread — including triage rulings and hold/restart conditions — remains on the source issue and MUST be read before acting on this card.


观察

修 objectstack-ai/objectstack#5143(邮编键错配)时顺手核对了 @objectstack/spec 的地址契约,发现 objectui 侧的类型只覆盖了它的一部分。

@objectstack/spec@17.0.0-rc.5 的 AddressValueSchema(packages/spec 侧,address 字段类型的强制值契约,$strip 语义)声明七个部件:

street, city, state, postalCode, country, countryCode, formatted

objectui packages/fields/src/widgets/AddressField.tsx 导出的 AddressValue 在 objectstack-ai/objectstack#5143 修好键名之后声明五个,缺 countryCode 与 formatted。

两个后果,严重度不同

  1. countryCode 不可类型化(纯类型缺口)。 widget 不渲染它是合理的(UI 上只给 country 一个框),但引用 AddressValue 的应用代码没法给这个 spec 合法的部件写类型。运行时无损:widget 写回时 {...address} 整体透传,未知键不会被它丢掉。

  2. formatted 编辑后会留成旧值(数据一致性,当前休眠)。 widget 的只读渲染自己用 street / city / state postalCode / country 拼显示串,完全不读存储里的 formatted;编辑任一部件时也既不更新也不清除它。所以一旦有生产者(geocoder / 导入)写过 formatted,改完街道保存,记录里的 formatted 仍是改前那句话,而任何优先读 formatted 的消费方会显示旧地址,与同一条记录的 street 自相矛盾。

为什么标 observation 而不是缺陷

objectui 仓内目前没有任何 formatted / countryCode 的生产者或消费者(git grep formatted origin/main -- packages/ 无地址相关命中,packages/plugin-map 源码零 address 命中),所以今天没有用户能碰到第 2 条 —— 它要等平台侧的 geocoding 真的落地 formatted 才会活过来。是否要 widget 承担 formatted 的维护(编辑时清掉、让服务端重算),还是契约上就规定 formatted 为服务端派生、客户端只读,是个契约问题,不该由渲染器自行决定 —— 这也是我没有在 objectstack-ai/objectstack#5143 的 PR 里顺手改它的原因(那个 PR 只动邮编键)。

建议的处理方向(留给 triage)

  • 短期:AddressValue 补齐 countryCode / formatted 两个可选部件,与 spec 一比一(纯类型,零行为变化);
  • 需决策:formatted 的所有权。若定为服务端派生,则 widget 在写回时应显式清除它(让服务端重算),并在 spec 上写明"客户端不得写入";若定为客户端可写,则 widget 需要在编辑时重算。两条路都要先在 spec 上说清,再改渲染器。

相关

发现于 objectui worktree claude/issue-os5143-address-postalcode,base 5e524950d1d2bd062010cde9207adf14b247e85e。

Activity

  1. os-zhuang commented on Aug 10, 2026

    @os-zhuang
    ContributorAuthor

    Findings-triage: held (finding stays) — grade carried over onto this card from the source thread so it is readable where the label lives.

    The disposition recorded on objectstack#6968 (objectui shard PM, 2026-08-09 09:51Z) stands unchanged: formatted ownership (server-derived read-only vs client-writable-recompute) is a contract question that must be settled on the spec side first, and this repo currently has zero producers or consumers of formatted / countryCode — dormant. Restart conditions: (a) a spec ruling on formatted ownership, or (b) the first real producer/consumer landing (geocoding/import). The short-term type-gap half (adding the two optional members to AddressValue, zero behavior change) can ride any future card touching AddressField.

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  2. claude commented on Aug 10, 2026

    @claude
    Contributor

    Findings round — held (finding kept), premise re-verified.

    • Re-checked @ objectui origin/main e638531: AddressValue still declares five of the seven AddressValueSchema parts (packages/fields/src/widgets/AddressField.tsx:22-28 — no countryCode, no formatted), and dormancy still holds: the widget's readonly path self-assembles its display line (formatAddress at :127 — a local, not the stored formatted part), and a repo grep shows no producer or consumer of the stored formatted/countryCode components (all other formatted hits are i18n/locale prose).
    • Held: the formatted ownership question (server-derived read-only vs client-recompute) is a spec-side contract question, and nothing reaches the stale-value consequence until a producer exists.

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  3. os-zhuang commented on Aug 11, 2026

    @os-zhuang
    ContributorAuthor

    Findings round — held (finding kept), premise re-verified.

    Re-checked @ objectui origin/main b42558a: AddressValue still declares five of the seven AddressValueSchema parts (packages/fields/src/widgets/AddressField.tsx:22-28 — no countryCode, no formatted), and the dormancy holds: the readonly path still self-assembles its display line locally rather than reading a stored formatted part. Nothing a user hits today; the stored-formatted-goes-stale hazard stays latent until something starts producing/consuming those two parts.

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  4. os-zhuang commented on Aug 11, 2026

    @os-zhuang
    ContributorAuthor

    Findings triage (cadence re-check): HOLD — stays finding.

    Premise re-verified on origin/main @ 6d8231c: AddressField.tsx:94 still renders readonly via formatAddress(address) (own concatenation, never the stored formatted), and the exported AddressValue still omits countryCode/formatted versus the spec's seven-part AddressValueSchema. Both halves stand.

    Why still held: consequence 1 is a pure type gap (runtime lossless — the widget spreads the whole object back), and consequence 2 (stale formatted after edit) stays dormant while nothing in-repo reads the stored formatted. Per the migrated thread's own hold conditions, this waits for the next AddressField pickup rather than a dispatch of its own.

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  5. added theissue type on Aug 17, 2026
  6. os-zhuang commented on Aug 17, 2026

    @os-zhuang
    ContributorAuthor

    Findings centralized round, batch 2 (triage seat, 2026-08-17): state transition finding → pm:on-hold per the 2026-08-13 status-semantics ruling. Standing grade unchanged and absorbed: formatted ownership (server-derived read-only vs client-recompute) is a spec-side contract question, and both consequences stay dormant while the repo has zero producers/consumers of formatted/countryCode. The pure type-gap half (two optional members on AddressValue, zero behaviour) rides the next AddressField pickup.

    Restart-when: a dispatched card's file surface includes packages/fields/src/widgets/AddressField.tsx, or a spec ruling lands on AddressValueSchema.formatted ownership. Trigger file: packages/fields/src/widgets/AddressField.tsx.


    Generated by Claude Code

  7. added
    domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lane
    on Aug 23, 2026
  8. os-zhuang commented on Aug 23, 2026

    @os-zhuang
    ContributorAuthor

    Triage: domain:spec (lane only — pm:on-hold untouched). The card is a coverage gap between objectui's AddressValue and the spec's — a contract-shape question, with packages/fields / packages/plugin-map as the consumers that expose it.

    Routed via the maintainer direct-dispatch channel, this session, verbatim: 「然后 批 4–5」. PM session session_0124Qg8rLvpXnQDwCmpKUmaJ. objectui three-stream split (maintainer 2026-08-21); not a Routine triage fire — the triage seat may re-grade.


    Generated by Claude Code

  9. yinlianghui commented on Sep 2, 2026

    @yinlianghui
    Contributor

    Hold re-verification (spec@objectui seat, session session_01V3hPr7riucnMfhcHY86Msd, 2026-09-02) — premise drifted in the good direction; the type-gap half is closed, the formatted half is unchanged. Evidence only, hold kept.

    • Type gap (consequence 1): closed. packages/fields/src/widgets/address-format.ts:29 import type { AddressValue } from '@objectstack/spec/data' and :64 export type { AddressValue } — a direct re-export replacing the five-part local copy (its docstring :46-51 records that this closed objectui#4167 for exactly that reason); AddressField.tsx:24,30 uses it as the widget's value type. countryCode / formatted are typeable now.
    • Stale formatted after edit (consequence 2): unchanged and still dormant. AddressField.tsx:93-104 handleFieldChange spreads the canonical value and overwrites one part, so a stored formatted / countryCode passes through untouched; the readonly render (:122) calls the local formatAddress(address, displayLocale) and never reads a stored formatted. git grep formatted|countryCode over packages/fields/src (non-test): zero producers or consumers of the stored parts; packages/plugin-map/src has no address hits. Reachable only if some producer starts writing formatted.
    • Restart-when: the trigger file appears once in git log origin/main -- packages/fields/src/widgets/AddressField.tsx (03380aa, 2026-09-01, fix(plugin-detail): present the server's VALIDATION_FAILED as per-field inline-edit hints, and record the ruling that the server is the authority #7109 plugin-detail hints) but on a 50-commit shallow clone the diff cannot be read; nothing in the address-value logic changed. No spec ruling on AddressValueSchema.formatted ownership found in code. Ambiguous, not a clean hit.
    • A narrowed card would strike consequence 1 and keep only "who owns formatted (spec-side producer vs widget recompute) — decide before any producer writes it".

    Generated by Claude Code

  10. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    关闭 not_planned —— 维护者同意:类型缺口已修好;formatted 由谁维护这个问题,在两个仓库里都还没有任何写入方,等真正写它的功能出现时再定

    分诊席(session_01Tw7jnJinGHvoGSi8aFkhPJ,objectstack 座位贴 #6015),2026-09-24T14:09Z。objectui 清理第九批(#8587 的挂起卡一次性清点):本席读完了卡面和评论(7 条,全部读到),并在本地 main(62597c5)和 objectstack main(3b5607019f)上重新核对,把建议报给维护者。维护者答:「第⑨批 同意」。

    本卡说的是什么

    地址组件的 AddressValue 只覆盖 spec AddressValueSchema 七个部件中的五个。卡里有两件事:一是 countryCode / formatted 无法写类型;二是一旦有人写入 formatted,编辑地址后它会留成旧值。第二件事需要先在 spec 上说清 formatted 归谁维护。

    本席实测

    为什么关

    用户今天碰不到第二件事。formatted 归谁维护,应该由将来真正写它的那张卡来决定,那时才有真实的需求可以判断。同一个组件的 #4738 已在上一批关闭。

    什么时候重开

    地理编码、导入等功能开始写入 formatted 时,先在 spec 上定归属:要么服务端派生、客户端只读(组件编辑时清掉它),要么客户端可写(组件编辑时重算)。定完再改组件。

    标签:摘 pm:on-hold;以 not_planned 关闭。


    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

    domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lane

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions