Skip to content

Commit 8a063f6

Browse files
committed
fix(spec): 把 #3746 陷阱的警告本身移出 doc block,并补 批 15 changeset(#4001)
getFileDescription() 用裸正则在原始源码上找第一个 doc block,所以在 // 行里 引用那个双星开头的字面量也会被匹配成文件的首个 doc block —— 于是这条警告 自己把 theme/chart 两个参考页的描述清空了。check:docs 抓到;改写措辞后 两页与 main 逐字节相同。 同时把 clickAction 的 finding-7 说明从 JSDoc 移到 // 注释:它是给下一个 维护者的话,不是协议文档,不该发布到公开参考页。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ehu85kbvMcrNTUJjwxvLJ9
1 parent d22ccbc commit 8a063f6

3 files changed

Lines changed: 79 additions & 12 deletions

File tree

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
'@objectstack/spec': major
3+
---
4+
5+
**未知键收紧:`ui/theme.zod.ts` 全部 14 个站点 + `ui/chart.zod.ts` 5 / 7 个站点(#4001 批 15)**
6+
7+
作者写进主题和图表配置里的未声明键,过去被 zod 默认的 `.strip` 静默丢弃、解析照常成功。现在是一条点名该键、并在能识别时给出正确拼法的报错。
8+
9+
**先测门,再收紧。** 两个文件在账本上都标着 `authorable (p)`,`(p)` 是待验证:
10+
11+
- `theme.zod.ts` —— 门是真的,而且有两道:`stack.zod.ts` 声明 `themes: z.array(ThemeSchema)`(所以 `defineStack()` 在每次启动和 `objectstack build` 时解析每个主题),`defineTheme()` 直接解析一个。从 24 个 metadata-type root 加 `ObjectStackSchema` 做 BFS,文件内每个 schema 都可达。**14/14 收紧。**
12+
- `chart.zod.ts` —— 5 个可达(`DashboardWidget.chartConfig` / `ReportChartSchema`),已收紧;**`ChartAggregateSchema``ChartGroupBySchema` 的 object 分支不可达,故意保持原样**,见下。
13+
14+
## 破坏性变更 · 迁移
15+
16+
以下写法过去被静默接受(键被丢弃),现在报错。括号内是新报错直接给出的处方。
17+
18+
**主题(`defineStack({ themes })` / `defineTheme()`)**
19+
20+
| 旧写法 | 改成 |
21+
|---|---|
22+
| `colors: { card, foreground, mutedForeground, muted, destructive }` | `surface` / `text` / `textSecondary` / `disabled` / `error` |
23+
| `typography.fontSize: { md }` | `base`(`borderRadius`/`shadows``md`,字号阶梯没有) |
24+
| `typography.fontWeight: { base }` | `normal` |
25+
| `animation.timing: { easeIn, easeOut, easeInOut }` | `ease_in` / `ease_out` / `ease_in_out` |
26+
| `shadows: { inset }` | `inner` |
27+
| `zIndex: { backdrop, overlay }` | `modalBackdrop` |
28+
| 顶层 `palette` / `radius` / `shadow` / `animations` / `cssVars` / `extend` | `colors` / `borderRadius` / `shadows` / `animation` / `customVars` / `extends` |
29+
| #3494 删除的 8 个 prop(`spacing` / `breakpoints` / `logo` / `density` / `wcagContrast` / `rtl` / `touchTarget` / `keyboardNavigation`) | 各自带独立墓碑处方;多数指向 `customVars`,`logo` 指向 app 的 `branding.logo` |
30+
31+
**图表(dashboard widget 的 `chartConfig` / report 的 `chart`)**
32+
33+
| 旧写法 | 改成 |
34+
|---|---|
35+
| `chartType` | `type`(`chartType` 是内部拼写,从来不是作者契约) |
36+
| `legend` / `dataLabels` | `showLegend` / `showDataLabels` |
37+
| `interactions` / `annotation` | `interaction` / `annotations`(同一个块里一个单数一个复数) |
38+
| axis 上的 `name` / `label` / `dataKey` | `field` / `title` |
39+
| series 上的 `field` / `title` / `stackId` / `strokeDasharray` | `name` / `label` / `stack` / `dashArray` |
40+
| annotation 上的 `from` / `to` | `value` / `endValue` |
41+
| `interaction.zoom` / `interaction.clickAction`(#3752 已删) | `brush: true` / `onSegmentClick``ReportSchema.drilldown`、widget 的 `options`|
42+
| `width` / `stacked` / `dataset` / `objectName` / `aggregate` / `options` | 都是层级放错,报错点名正确的那一层(`layout.w``series[].stack`、widget 自己的键、react prop) |
43+
44+
⚠️ **严格性会顺着 `.extend()` 传到 `ReportChartSchema`**(`ChartConfigSchema.extend(...)`)。这是有意的,并有测试钉住:report chart 只是把 `xAxis`/`yAxis` 收窄成 dataset 维度/度量名,不新增键,所以继承的键集正好。
45+
46+
## 两个站点故意没收紧
47+
48+
`ChartAggregateSchema``ChartGroupBySchema` 的 object 分支**有活的承载键**(react 层 `< ObjectChart objectName aggregate={…} >`,objectui 的 `ObjectChart` 真的读它跑查询),**但没有任何 parse**:两者从所有 metadata-type root 都不可达,三个仓库里除单测外无人 `.parse()`,而唯一审查它的 react 页发布 lint 是手写重推规则、从不检查未知键。
49+
50+
`.strict()` 是 parse 的属性,这里没有 parse —— 收紧只会让文件看起来完成,并留下*一个被精确校验的死槽位*(#4583)。账本因此新增第四类 **`no gate`**(承载键活、parse 缺),与批 13 的 `no door`(承载键本身不存在)并列:两者处方相反,前者该接闸门,后者该走 ADR-0049 退役。已归档为独立 issue。
51+
52+
主题里那些**发出后无人读取**的 CSS 变量(`--font-size-*` / `--z-*` / `--duration-*` …)是 ADR-0049 的 liveness 题目,不是未知键题目,同样单独归档 —— 收紧能让被丢弃的键变响,不能让一个槽位变活。

packages/spec/src/ui/chart.zod.ts

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@ import { strictObject } from '../shared/strict-object';
1010
// closed; two are deliberately left open with the reason recorded, because
1111
// closing them would gate nothing.
1212
//
13-
// ⚠️ Nothing above this block may be a `/** */` comment: `build-docs.ts`'s
13+
// ⚠️ Nothing above this block may be a JSDoc block: `build-docs.ts`'s
1414
// `getFileDescription()` publishes the module's FIRST doc block as the
15-
// reference page's description (#3746 trap 1). Hence `//`.
15+
// reference page's description (#3746 trap 1). Hence `//`. Note you cannot
16+
// safely spell that token out here either — see the longer note in
17+
// `theme.zod.ts`, where quoting it inside a `//` line silently emptied the
18+
// published page description.
1619
//
1720
// CLOSED (real door, three measurements, 2026-08-03):
1821
// `ChartConfigSchema`, `ChartAxisSchema`, `ChartSeriesSchema`,
@@ -300,16 +303,20 @@ export const ChartAnnotationSchema = lazySchema(() => strictObject(
300303
* on a dashboard widget, the renderer's segment drill under the widget's
301304
* `options` bag, which is `passthrough` precisely so renderer-only
302305
* capabilities have a declared home.
303-
*
304-
* ⚠️ This paragraph said "Migration: `drillDown`" from #3752 until #4001
305-
* 批 15, and **`drillDown` is not a key this protocol declares anywhere** —
306-
* it is an untyped `(schema as any).drillDown` read inside objectui's
307-
* `ObjectChart`. Promoting that sentence into a strict rejection message
308-
* would have handed an author the platform's authority for a key the very
309-
* same gate then rejects: the ledger's finding 7 for the third time. The
310-
* underlying gap — a live renderer capability with no spec declaration —
311-
* is filed, not fixed here.
312306
*/
307+
// ⚠️ Kept OUT of the doc comment above on purpose — `build-docs.ts` publishes
308+
// that block to the public reference page, and the following is a note to the
309+
// next maintainer, not protocol documentation (the #3746 trap, in its subtler
310+
// form: not the file's FIRST block, but internal prose inside a published one).
311+
//
312+
// That `clickAction` paragraph read "Migration: `drillDown`" from #3752 until
313+
// #4001 批 15, and **`drillDown` is not a key this protocol declares
314+
// anywhere** — it is an untyped `(schema as any).drillDown` read inside
315+
// objectui's `ObjectChart`. Promoting that sentence into the strict rejection
316+
// message below would have handed an author the platform's authority for a key
317+
// the very same gate then rejects: the ledger's finding 7, third occurrence.
318+
// The underlying gap — a live renderer capability with no spec declaration —
319+
// is filed, not fixed here.
313320
export const ChartInteractionSchema = lazySchema(() => strictObject(
314321
{
315322
surface: 'this chart interaction block',

packages/spec/src/ui/theme.zod.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,19 @@ import { SnakeCaseIdentifierSchema } from '../shared/identifiers.zod';
88
// MEASURED before anything was tightened, not assumed. Read this before adding
99
// a key, and before "finishing" any sibling file by analogy.
1010
//
11-
// ⚠️ Nothing above this block may be a `/** */` comment: `build-docs.ts`'s
11+
// ⚠️ Nothing above this block may be a JSDoc block: `build-docs.ts`'s
1212
// `getFileDescription()` publishes the module's FIRST doc block as the
1313
// reference page's description, so a doc-comment header here would replace the
1414
// public page's text with an internal note (#3746 trap 1). Hence `//`.
1515
//
16+
// And do not spell that hazard out with the literal two-star opener, either —
17+
// `getFileDescription()` matches it with a bare regex over the raw source, so
18+
// even INSIDE a `//` line it reads as the file's first doc block. The first
19+
// draft of this very warning quoted the token, matched as an empty description,
20+
// and deleted "Color Palette Schema / Defines brand colors and their variants"
21+
// from the published page. The caution about the trap sprang the trap; caught
22+
// by `check:docs`, which is exactly what it is for.
23+
//
1624
// THE DOOR (three measurements, 2026-08-03, each with controls in the run):
1725
//
1826
// 1. CARRIER KEY — `stack.zod.ts` declares `themes: z.array(ThemeSchema)`,

0 commit comments

Comments
 (0)