Uh oh!
There was an error while loading. Please reload this page.
docs(plugin-dashboard): README 的 TypeScript 一节按真实导出面重写虚构的 DashboardSchema / MetricCardSchema - #5069
Conversation
`packages/plugin-dashboard/README.md:321` 导入的 `DashboardSchema` 与 `MetricCardSchema`,在本包与 `@object-ui/types` 的导出面上都不存在,照抄该节 是两条 TS2305。导出名集合取自构建产物 `dist/index.d.ts`(走 TS compiler API 的 checker.getExportsOfModule,不是对 src 做正则),示例逐块对同一构建产物 strict 编译验证。 - `DashboardSchema`:标识符 grep 的典型假信号 —— 它只出现在三处注释 (DashboardRenderer.tsx:884、DashboardGridLayout.tsx:76/:88),以及 `@objectstack/spec/ui` 里那个元数据级 zod schema 的名字上;按导出面查,本包 与 `@object-ui/types` 都零命中。真身存在,故按真身重写而非删节: `@object-ui/types` 的 `DashboardComponentSchema`。 - `MetricCardSchema`:纯虚构,加词边界后除本 README 外全仓零命中。且**改不成 同族真名** —— widget 侧不存在「按族」的 schema 类型,一个 `DashboardWidgetSchema` 覆盖全部 type,族内设置在 `options` 下。示例改按 `DashboardWidgetSchema` 写,并给出该类型真正承载的三种作者形:数据集绑定的 KPI、无查询的静态单值(值在 `options` 下)、以及 widget 的 `component` 槽里 的注册组件节点。 新增一段陈述该类型集**不**覆盖什么,因为旧片段暗示了相反的事:`value` / `trend` / `trendValue` 是 MetricCard 的**组件** props,`DashboardWidgetSchema` 三个都不声明(逐键单独探,因为第一个多余属性会把后续诊断短路),而组件 props 接口也不在本包导出面上。 ⛔ 未新增、未 re-export、未改名任何导出来把旧名变真;`dashboardComponents` (真实存在,src/index.tsx:338)一节未动。 Fixes#5015 Co-authored-by: Claude <noreply@anthropic.com>
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
yinlianghui
commented
Aug 17, 2026
CI 终态读数(按 jobs 端点判,不单凭 check-runs),head 11 个 run 全部
这正是正文「docs-only 的 CI 形状」那一段预告的结果: 但并非全部被短路 —— 两道门对本 PR 给了真信号,值得单独记一笔:
另附一条过程上的自我纠正,以免同族后续 PR 踩同一坑:第一版 CI 守望脚本用 Generated by Claude Code |
yinlianghui
commented
Aug 17, 2026
PM 验收:ACCEPT(session 实物核验:merge-base 验收要点:
派生物分诊(本评论即记录):#5064( 转 ready 并挂 auto-merge(squash)。 Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#5015
基线
origin/main@bb3fab62c7729092174a1e8ae6032cbb29ce28a3(worktree 显式建在该 sha 上)。方法学照抄同族已落地的三单:#5010 → PR #5046、#5016 → PR #5053、#5012 → PR #5059。前提验证:卡面读数自己复测,两条都成立
卡面的复核命令写的是裸 grep,所以按 #5012 的教训先补词边界重测:
DashboardSchema—— 19 处命中,没有一处是本包或@object-ui/types的导出:3 处是本包的注释(src/DashboardRenderer.tsx:884、src/DashboardGridLayout.tsx:76、:88),其余是@objectstack/spec/ui那个元数据级 zod schema 的名字被引用(packages/types/src/zod/complex.zod.ts:21以DashboardSchema as SpecDashboardSchema导入、packages/app-shell/src/views/metadata-admin/dashboard-schema.ts:25、clientValidation.ts:587),加上SKILL.md与本 README 自己。卡面说的「标识符 grep 的假信号」成立,而且假信号有两个来源:注释,以及一个同名但属于另一个包、另一个层次(zod 而非 TS 类型)的真实物件。MetricCardSchema—— 除本 README 的:321/:323外全仓零命中。纯虚构。MetricCardProps是真的但未从 index re-export」也成立,见下。真身查证(#5012 的路数:先查真身再定修法)
声明式 grep(
^\s*(export )?(declare )?(type|interface|const|class) …)在@object-ui/types找 dashboard 侧的授权类型:@object-ui/types导出DashboardComponentSchemapackages/types/src/complex.ts:738(type: 'dashboard'+widgets+columns/gap/header/globalFilters/dateRange)src/index.ts:278DashboardWidgetSchemacomplex.ts:676(extends Omit< Partial< SpecDashboardWidget >, 'type' | 'options' | 'chartConfig' | 'filter' >)src/index.ts:277DashboardWidgetLayoutcomplex.ts:652src/index.ts:276容器侧真身存在 ⇒ 示例按真身从
@object-ui/types重写。metric card 侧不是「同名换路径」,分两层量:
DashboardWidgetSchema覆盖全部type,族内设置在options下 —— 不存在MetricCardSchema的兄弟名。而且metric-card也不是 spec widget 家族成员:@objectstack/spec@17.0.0的DashboardWidgetSchema.type枚举里是metric/kpi,没有metric-card(objectui 把type放宽成string,所以 tsc 收但 spec 不收)。MetricCardProps(src/MetricCard.tsx:35)是真的,没从src/index.tsxre-export:按认领裁定 ⛔ 不代裁命名、⛔ 不加新导出、⛔ 不 re-export
MetricCardProps。这半个裁定已经是在途卡 #4600 的余留范围(该卡 2026-08-14 状态注记:「which schema an SDUI dashboard COMPONENT node validates against; classes A/B + metric-card」,等 objectstack#8593),所以按「附着不散落」的纪律写成 #4600 的追评而不另立孪生卡 —— 见下文「顺手立的卡」。判定表
:321import type { DashboardSchema … }from 本包@objectstack/spec/ui的同名 zod schemaDashboardComponentSchemafrom@object-ui/types:321… MetricCardSchema }、:323const metricCard: MetricCardSchemaMetricCardProps不在导出面(TS2724)DashboardWidgetSchema写,并如实陈述这三个键是组件 props:42-52dashboardComponents手动注册src/index.tsx:338):416-422onSchemaChange示例名集合核对读数
导出名集合取自构建产物
dist/index.d.ts,走 TS compiler API 的checker.getExportsOfModule;README 侧不用正则抓 import —— 先抽 fenced 块,每块ts.createSourceFile,再走ImportDeclaration的 AST,A as B判propertyName(导出名)而非本地别名。#5043 记的两个坑因此在结构上不可能发生。绑定数不变是对的:换掉的两个名从本包挪到了
@object-ui/types,另三个(dashboardComponents、ComponentRegistry、createObjectStackAdapter)本来就成立。编译探针读数
README 的 ts/tsx 块抄进 scratch,对同一批构建产物编译(
strict: true,没有为让块通过而放松任何选项);块按内容签名分类而非块序号,所以改前改后共用一套机器。跳过的两块(输出里列明,不静默丢):
:61-67与:75-84的 Schema API 形状速写 ——widgets: Widget[]/title: string是类型语法落在值位置,故意不合法的 TS。harness 两处,都只补作用域、不放松检查:
:293的colorVariant裸 widget 字面量被钉在真DashboardWidgetSchema上(改前改后皆绿,该节确认为真话);:417的裸 JSX 补dashboard/client声明。逐键 pin(散文新增的断言不靠外推)。 新增那段说
value/trend/trendValue三个键DashboardWidgetSchema都不声明,而合并写在一个字面量里只报一条 —— 第一个多余属性会把其余诊断短路(PR #5059 记过同一现象)。所以一文件一键单独探:DashboardWidgetSchema的诊断valueTS2561 … 'value' does not exist … Did you mean to write 'values'?trendTS2353 … 'trend' does not exist in type 'DashboardWidgetSchema'trendValueTS2353 … 'trendValue' does not exist in type 'DashboardWidgetSchema'反向验证(两条,预判先写)
(a) 名集合核对自证。 预判:往多行类型 import 块里 planted,
MISSING COUNT0 → 2,恰为{DashboardSchema, DashboardThings};别名判导出名;行尾注释里的非导出词不得报。四条全符 ——DashboardSchemaDashboardSchema@:332DashboardThings as ThingsDashboardThings而非别名ThingsDashboardThings@:332DashboardWidgetSchema→DashboardWidgetSchema as WidgetSchema// MetricCardSchema was never realMISSING COUNT: 2,还原读数0。变异全做在 README 的 scratch 副本上(检查器的--readme指向副本),git status --porcelain全程只有本卡那一个M—— 不存在「临时改动误入 commit」的窗口。(b) 改前 README 回填探针。 预判:回填后必须转红,且错误与所改两处一一对应,
:417那条既有红原样携带。同一套机器直接跑git show $BASE:packages/plugin-dashboard/README.md的副本,转红rc=2:DashboardSchemablock10(1,15): TS2305 … has no exported member 'DashboardSchema'MetricCardSchemablock10(1,32): TS2305 … has no exported member 'MetricCardSchema'onSchemaChange红block12(8,63): TS2345(改前改后同一坐标)预判与实测无出入,方向即通常的「改前红 / 改后绿」—— 本卡的
??链、计数门那类反转情形不适用(这是导入名不存在,不是取值判决)。验证
pnpm exec turbo run type-check --concurrency=2→81 successful, 81 total(4m34s;重活经flock -w 3600 /tmp/os-heavy-verify.lock串行 +--max-old-space-size=4096)。node scripts/check-doc-links.mjs→Links are valid across 13 scan roots.node scripts/check-control-bytes.mjs→OK (scanned 4512 tracked text file(s); skipped 85 binary);改动两文件另做grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f]'自扫,零命中。pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-dashboard...' build→ rc=0(探针与名集合核对所依赖的构建产物)。docs-only 的 CI 形状:
**/*.md与.changeset/**在paths-ignore里,Test / Type Check 各 job 的实质步骤会被 path-filter 短路成 skipped 而 job 报 success。按纪律计绿,但类型证据是上面的本地仓根读数,不是 CI 的(#5046 / #5053 / #5059 先例)。顺手立的卡(均未认领,不夹带进本 PR)
dashboardComponents用组件类名作键(全仓唯一一个),README 教的手动注册循环因此注册 11 个没人写的 type、8 个真 type 一个没注册 #5064 —dashboardComponents用组件类名作键('DashboardRenderer'…),是全仓 5 个*Componentsmap 里唯一一个;其余 4 个(charts / editor / kanban / markdown)全按 schema type 键。于是 README 教的那个Object.entries(...).forEach(register)循环注册 11 个没人写的 type,本包真正认领的 8 个一个没注册,并触发 11 条 namespace 弃用告警。名字是真的、键的词汇表是错的 —— 与本卡不同性质,且认领裁定明写该节勿动。onSchemaChange示例把string | undefined传给saveItem的必填name—— 照抄在 TS 消费者那里是 TS2345 #5066 —:416-422的onSchemaChange示例把DashboardComponentSchema['name'](string | undefined,packages/types/src/base.ts:86)传给saveItem(type: string, name: string, item: any)(@objectstack/client@17.0.0dist:714)的必填name。名字与键全真,错的是可选性。就是改后探针剩下的那一条。widget.dataset的as any及其理由注释已过期 ——DashboardWidgetSchema在 spec 17.0.0 上已声明dataset/values#5067(finding,不打pm:queue) —DashboardRenderer.tsx:528读widget.dataset的as any及其理由注释已过期:spec 17.0.0 的DashboardWidgetSchema已声明dataset/values,dataset不在 objectui 的Omit名单里,直接读即可通过 strict。观察级 —— 行为与收窄后一致,今天没有用户会撞上。plugin-dashboardexamples are refused by the spec'sDashboardSchema— the AI few-shot corpus teaches the pre-ADR-0021 widget shape #4600 追评(不另立卡,命中在途卡即写在卡上)—— 本包导出面上没有任何 schema 类型、容器真身是DashboardComponentSchema、widget 侧无按族类型、MetricCardProps的 TS2724 与三个键的逐键读数。都落在该卡等 objectstack#8593 的余留范围内。changeset
.changeset/plugin-dashboard-readme-truth-5015.md,@object-ui/plugin-dashboard: patch,口径同 #5046 / #5053 / #5059:无代码/类型/运行时改动,声明 patch 是因为README.md在包的files里,随下次发布到 npm。Generated by Claude Code