Skip to content

core 的 DatasetResultField 仍是 spec AnalyticsResult.fields[] 的手写重述(今日未漂移,但 type 已被放宽为可选) #3815

Description

@yinlianghui

#3752 的派单要求"顺手核对 packages/core/src/utils/dataset-format.ts:34 的本地 DatasetResultField 是否也应派生自 spec —— 只核对不实施"。这是核对结论,按流程立卡供 PM 分诊,未实施任何改动。

事实(objectui origin/main @ 2a54e860c,spec 实装版本 @objectstack/spec@17.0.0-rc.5)

packages/core/src/utils/dataset-format.ts:29 起:

export interface DatasetResultField {
  name: string;
  type?: string;
  label?: string;
  format?: string;
  currency?: string;
  percentScale?: PercentScale;
}

与 spec contracts 的 AnalyticsResult.fields[] 元素逐项对比:

  • 键集合完全一致(六项),今日没有漂移 —— percentScale 在(Dashboard '0.0%' format: a ratio of exactly 1 renders as 1.0% instead of 100.0% #3136 之后补的),而且 PercentScale 本身就是从 @objectstack/spec/data import 的真身,不是手抄的字面量联合(dataset-format.ts:20),第 52 行还把它原样 re-export 给既有 import 路径。
  • 唯一形状差异:type 在这里是可选(type?: string),spec 是必填(type: string)。方向是"放宽",所以 core 的消费者读 field.type 拿到 string | undefined,必须自己兜 undefined;反过来,凡是构造这个类型的地方都可以合法地不给 type,而服务端契约保证它一定在。

为什么按 observation-class 立(finding,不带 pm:queue)

若要实施,需要先决的两点(所以本卡不含 patch)

  1. type 的可选性是不是有意的。改成 spec 元素(type 必填)会波及所有构造 DatasetResultField 的地方,包括测试 fixture;还要看它与 ChartResultField(注释称 DatasetResultField 是其超集,后者只需 name/label/format)的父子关系是否仍成立。这需要读一遍构造点再决定,不是机械替换。
  2. 导出路径的兼容。dataset-format.ts 现在把 PercentScale re-export "让既有 @object-ui/core 消费者保持 import 路径";DatasetResultField 本身也是被 plugin-dashboard/plugin-report 直接 import 的公开名字。派生自 spec 时要决定是 type DatasetResultField = AnalyticsResult['fields'][number](名字保留、形状收紧)还是保留 interface 只补 type 必填。

跨包面(packages/core)超出 #3752 的单文件面,故只记录不动手。相关:#3752(adapter 返回侧,已修)、#3613/#3753(参数侧,已修)、#3136(percentScale 的由来)。

Activity

  1. os-zhuang commented on Aug 8, 2026

    @os-zhuang
    Contributor

    Findings round: promoted — finding removed, pm:queue added (labels and this comment land as a pair).

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


    Generated by Claude Code

  2. self-assigned this
    on Aug 10, 2026
  3. yinlianghui commented on Aug 10, 2026

    @yinlianghui
    CollaboratorAuthor

    Claim: PM loop round 5 (rolling slot refill)
    Session: session_017Qqyix2QcnpUC9XeYVDzx3 · Branch: claude/issue-3815-dataset-field-derive · Worktree: objectui-issue-3815
    File surface: packages/core/src/utils/dataset-format.ts + construction/consumption sites the investigation names (plugin-dashboard / plugin-report / DatasetPreview fixtures as needed) + tests. Serial constraints: disjoint from #3810/#4111/#4114/#3781 in flight (core's evaluator work #4104 already merged).
    Container & model: S, mode:subagent, model: opus

    Direction: the card's two pre-decisions are both answerable by reading, so the dispatch is investigate-then-implement — (1) read every DatasetResultField construction site to determine whether type can be required as spec says; (2) prefer the full derivation (AnalyticsResult['fields'][number], public name preserved) if the construction read supports it; if a constructor legitimately cannot supply type, fall back to the honest middle: keep the shape but add a key-set parity tripwire against the spec element (the drift the card warns about becomes a red instead of a silent divergence) and document why full derivation was declined. Check the ChartResultField superset claim holds under whichever shape ships.


    Generated by Claude Code

  4. yinlianghui commented on Aug 10, 2026

    @yinlianghui
    CollaboratorAuthor

    ACCEPT (objectui seat PM, session session_017Qqyix2QcnpUC9XeYVDzx3, review of record) — PR #4128.

    Both of the card's pre-decisions resolved by measurement, not preference: nothing in the repo constructs a result column (every value flows from queryDataset, whose fields was already spec-typed by #3752) and nothing reads .type off one — so the requiredness restoration is free and the PREFERRED full derivation ships: DatasetResultField = AnalyticsResult['fields'][number], public name preserved, PercentScale untouched, no tripwire needed because the type IS the spec now. The ChartResultField superset claim was verified where it is load-bearing (DatasetWidget passes columns to buildChartSeries), and the newly-true asymmetry — the reverse direction stops holding with type required — is pinned as the actual content of the word "superset".

    The structural catch is worth more than the card: core's build tsconfig excludes tests AND core sits in check-type-check-coverage's TEST_DEBT, so a compile-time pin dropped in core's test tree would have been read by NO tsc program — the #3009 landmine, defused with a tsconfig.typetests.json per the sanctioned #3181 pattern (coverage script now reports 10 narrow projects, and the TEST_DEBT note names core honestly). The dispatch-template deviation (no dead undefined-guards to clean, because no reader exists) is reported instead of manufactured — correct. Changeset minor with the .d.ts-narrowing semantics spelled out per the bump policy.

    Flipping ready + auto-merge. Wind-down posture: no slot refill.


    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

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions