Skip to content

feat(spec,lint): 声明 chart segment drill —— ChartDrillDownSchema,挂在真正读它的那一层 (#5022) - #5221

Merged
xuyushun441-sys merged 5 commits into
mainfrom
claude/issue-5022-drilldown-declare
Aug 4, 2026
Merged

feat(spec,lint): 声明 chart segment drill —— ChartDrillDownSchema,挂在真正读它的那一层 (#5022)#5221
xuyushun441-sys merged 5 commits into
mainfrom
claude/issue-5022-drilldown-declare

Conversation

@xuyushun441-sys

@xuyushun441-sys xuyushun441-sys commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Fixes #5022

背景:delivered but never declared

drillDown 一直在驱动一个真实能力 —— 点 <ObjectChart> 的柱子/扇区,objectui 打开按点击类目过滤的记录抽屉。可是协议里从来没有声明过它:objectui 读的是 (schema as any).drillDown,grep drillDown packages/spec 只能搜到一条注释 —— 正是 #3752 写下的、把这个键当作迁移目标推荐给作者的那句话。批 15 已经就地修正了那句处方,底下的缺口留到这单。

这是 Prime Directive #10 反过来的形态:不是「声明了没交付」,而是「交付了从没声明」。

本 PR 声明它,additive,原先能 parse 的一律照旧。

形状:ObjectChart 实测读的六个键

{ enabled?, filter?, title?, target?: 'drawer' | 'dialog', columns?, maxRows? }

每一个都反推自一个读取点:isDrillEnabled(缺省关,{} 开)、computeDrillFilterresolveDrillTitle'dialog' 分支、列映射、页大小。

objectui 自己的 DrillDownConfig 更宽,因为它是 table / pivot / metric 几个 widget 共用的。没有照抄那个并集:chart 一个额外键都不读,其中 view / sort 更是任何 widget 都不读(objectui#3354)。照抄会把四个死键提升成带协议权威的能力。每个缺席的键都有一条 guidance 说明它属于哪儿,而不是给一个 rename 建议。

落点:react 块契约,不是 chart config、也不是 widget 的 options 袋

issue 里提的两个候选,实测在 dashboard 元数据面都是死的:

  • widget.chartConfig.drillDown —— DashboardRenderer 全文不读 chartConfig;DatasetWidget 只从里面转发一个键(showLegend),注释自陈 "the rest of chartConfig stays unforwarded"。
  • widget.options.drillDown —— DashboardRenderer 确实读,但只在 legacy 的 isObjectProvider 分支里;而 DashboardWidgetSchema.dataset 是必填,datasetBound 恒真,那份 component schema 恒被丢弃、从不渲染。

ADR-0021 dataset-bound widget 的 drill 是从语义层派生的,不认任何 drill 配置 —— 这一点 content/docs/ui/dashboards.mdx 早就写着(there is no per-widget drill configuration in the dataset form)。

所以声明挂在 react-blocks.ts 的 interaction 覆盖层,刻意不进 ChartConfigSchema:后者的成员同时是 dashboard widget chartConfig 解析的东西,放进去就会造出一个「可写、parse 通过、没人读」的键。

三个作者可能写错的地方,现在都会回答而不是耸肩:

写在哪儿 现在得到什么
widget.chartConfig.drillDown 拒绝 + 指向 react-tier prop
widget.drillDown / widget.drilldown 拒绝 + 说明 dashboard drill 是 AUTOMATIC 的,并点名两个可配置的 drill 各在哪
report.drillDown 拒绝 + 指回 chart prop

ReportSchema.drilldown 的双向消歧

同一个词,差一个字母,两种能力:

drillDown drilldown
拼写 camelCase 全小写
类型 配置对象 布尔
react <ObjectChart> prop ReportSchema 键(ADR-0021 D2,默认开)

编辑距离在这儿是帮倒忙的:两个拼写距离为 1,裸的 "did you mean" 会把在 report 上写 drillDown 的作者送去 drilldown,然后他的配置对象在布尔槽位上被第二次拒绝。两边的 guidance 都点名类型差异,不只是拼写。

declared = enforced,同一个 PR 里

.strict()parse 的属性,而 react 面上此前没有任何东西调用过 parse。packages/lint/src/validate-react-page-props.ts 现在直接 PARSE 这个 schema(react-chart-drilldown-invalid),而不是像旁边 aggregateCHART_FUNCTIONS 那样把规则再抄一遍 —— 这正是 strictness 台账 chart.zod.ts 那一行一直在等的修法,先在一个键上做出来。

来自 React state、静态不可解的值照旧跳过:unresolvable ≠ wrong(ADR-0072 D1)。

仪器

  • 批 15 的钉子是「改写」不是「放宽」:ChartInteractionSchema 的处方仍然不许出现裸的 drillDown —— 理由换了:这个 schema 从两个 tier 都能到达且分辨不出自己在哪个上,裸处方对一半读者是死路。断言不动,justification 换了,并写进注释。
  • 新增约 20 条断言:逐键接受、{} 即开、缺席保持 optional、未知键带 surface 名被拒、每个非 chart 键带理由被拒(不是 rename)、target:'navigate' 有专属处方(而一个普通的错值不会被喷这段文字)、载体判定双向钉死、发布出去的 react 类型串由 schema shape 反查校验。
  • lint gate 10 条测试;台账行与站点计数更新(ui/ 198 → 199)。

顺带发现(已立单,未在此修)

配套 PR

objectui 半边:objectstack-ai/objectui#3358 —— registry inputs 加上 drillDown(让 SDUI save gate 从 unknown-prop 变成正式契约),并把 (schema as any) 换成类型化读取。

验证

pnpm --filter @objectstack/spec test      → 305 files / 7839 passed
pnpm --filter @objectstack/lint test      → 57 files / 1190 passed (4 skipped)
pnpm --filter @objectstack/spec typecheck → clean
pnpm --filter @objectstack/lint typecheck → clean
check:generated        → ✓ All 8 generated artifacts are up to date
check:strictness-ledger → ✓ 67 files / 5 dirs — counts match, totals balance
check:liveness          → ✓ every governed-type property classified

已在 git merge origin/main(未 rebase)之后重跑上述全部。

🤖 Generated with Claude Code

https://claude.ai/code/session_01Ehu85kbvMcrNTUJjwxvLJ9

claude added 4 commits August 4, 2026 07:41
…(no code yet)

断点位置:测量完成,**尚未写任何 spec 代码**。测量结果与裁决前提冲突,
倾向 needs_decision(见下)。分支上目前是空提交,仅承载证据。

## 已完成的测量(objectui @91757a7 + objectstack @41e605ec70)

### A. ObjectChart 实际读取词汇(反推自 packages/plugin-charts/src/ObjectChart.tsx)
读到的键(:602 起,经 @object-ui/core drill-down.ts):
  enabled?  boolean            isDrillEnabled: 无 config=关;{}=开;enabled:false=关
  filter?   Record<string,unknown>  computeDrillFilter,支持 ${event.*} 插值
  title?    string             resolveDrillTitle,支持 ${event.*} 插值
  target?   'drawer'|'dialog'  :755 — **只分支 'dialog',其余一律 Sheet**
  columns?  string[]           :762 → accessorKey/header
  maxRows?  number             :761 → pageSize
ObjectChart **不读**:mode / view / report / sort,且 **不实现 target:'navigate'**
(navigate 只在 DrillDownDrawer.tsx:84 实现,ObjectChart 自绘 Sheet/Dialog,不走它)。
objectui 侧已有 TS 接口 DrillDownConfig(packages/types/src/data-display.ts:897),
是 5 个 widget 共享的更宽形状:{enabled,mode,target(含 navigate),filter,title,
view,report,columns,sort,maxRows}。其中 view/sort 无任何渲染器读取。

### B. 载体测量 —— 与裁决前提("渲染器已在读的 drillDown,objectui 零改动,挂 chart config")冲突
1. widget.chartConfig.drillDown → **无人读**。
   DashboardRenderer.tsx 全文 0 处 chartConfig;DatasetWidget.tsx:595-605 只取
   showLegend 一个键,注释自陈 "the rest of chartConfig stays unforwarded";
   :632 构造的 chart schema 里没有 drillDown。
2. widget.options.drillDown → DashboardRenderer.tsx:494/:570/:531 确实读,但**全部在
   isObjectProvider(widgetData) 的 legacy inline 分支内**;而 DashboardWidgetSchema
   要求 dataset(dashboard.zod.ts:427,非 optional),datasetBound 恒真,
   DashboardRenderer.tsx:691/:720 恒走 <DatasetWidget>,componentSchema 被丢弃。
   ⇒ 对 v17 合法 widget,options.drillDown 永不被读。
3. ADR-0021 正路 DatasetWidget 的 drill 是**从 dataset 结果派生、不可配置**的:
   canDrill 由 dimensionFields/drillRanges 决定,DrillDownDrawer 只收
   {objectName, filter, title, dataSource} —— 上述词汇一个都不认。
4. 唯一真活的面是 **react tier**:ChartConfigSchema 的键在 react 块上是**扁平 prop**
   (react-blocks.ts:226-247 dataProps),所以 <ObjectChart drillDown={…}> 确实生效;
   但 drillDown 既不在 spec dataProps/interactions,也不在 objectui registry inputs
   (ObjectChart.tsx:822-830),SDUI save gate 会报 unknown-prop(warning,不拦)。

⇒ 结论:挂 chart config 在 **react tier 交付、dashboard 元数据面不交付**;
挂 options 在两面都不交付。任一选择都会造出 #5011 "same key, two fates" 的形状。

## 剩余步骤(若维护者裁定后继续)
1. [待裁决] 定载体:(A) 只挂 react 块契约 /(B) 挂 ChartConfigSchema 并明写
   dashboard 面不转发 /(C) 挂 options 并在 objectui DatasetWidget 落地实现(非小改动)。
2. [待裁决] 定形状:chart 诚实子集 {enabled,filter,title,target:'drawer'|'dialog',
   columns,maxRows} vs objectui 共享 DrillDownConfig 全集。
3. 写 ChartDrillDownSchema(strictObject,surface/history/guidance),JSDoc 与
   ReportSchema.drilldown 双向点名消歧。
4. 逐键验收测试 + 调和 chart.test.ts:464 的批 15 钉子。
5. liveness/dashboard.json 分类 + check:strictness-ledger 台账行。
6. changeset(minor,v17 pre 模式);objectui 侧把 (schema as any).drillDown 换成声明类型。
7. 合 origin/main(#5154/#5162 已入队)后重跑 check:strictness-ledger + check:generated。

## 顺带发现(超范围,待立 issue)
- widget.chartConfig 在 dashboard 面只有 showLegend 落地,其余 11 个已声明键全惰性;
  liveness/dashboard.json 的 chartConfig 行写 "chart-config bag forwarded",高估。
- objectui DrillDownConfig.view / .sort 无渲染器读取;ObjectChart 忽略 target:'navigate'。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ehu85kbvMcrNTUJjwxvLJ9
…ema, on the tier that reads it (#5022)

`drillDown` drove a real capability with no protocol declaration behind it:
objectui's ObjectChart read `(schema as any).drillDown` and really did open a
filtered record drawer from it, while `grep drillDown packages/spec` found only
a comment — the one #3752 wrote prescribing the key as a migration target. That
inverted Prime Directive #10: delivered, never declared.

Declared now, additively, at the one surface measured to read it.

## The shape is the six keys ObjectChart reads

`{ enabled?, filter?, title?, target?: 'drawer' | 'dialog', columns?, maxRows? }`,
each reverse-engineered from a read point: `isDrillEnabled` (absent = off, `{}` =
on), `computeDrillFilter`, `resolveDrillTitle`, the `'dialog'` branch, the column
map, the page size. objectui's own `DrillDownConfig` is wider because it is
shared with the table / pivot / metric widgets, and copying that union would have
promoted four keys a chart ignores — two of which NO widget reads (objectui#3354)
— into protocol-declared capabilities. Each absent key is a `guidance` entry
naming where it does apply, not a rename.

## The carrier is the react block, NOT chart config or the widget options bag

Both candidates in the issue measured dead on the dashboard metadata path:
`DashboardRenderer` never reads `chartConfig`, and `DatasetWidget` forwards
exactly one key out of it (`showLegend`); `options.drillDown` is read only in
`DashboardRenderer`'s legacy `isObjectProvider` branch, which a spec-legal v17
widget cannot reach, because `dataset` is required and `datasetBound` therefore
discards that component schema unrendered. An ADR-0021 dataset-bound widget
drills through the semantic layer and honours no drill config at all — which
`content/docs/ui/dashboards.mdx` already said. So the declaration rides
`react-blocks.ts`'s interaction overlay, deliberately not `ChartConfigSchema`,
whose members a dashboard widget's `chartConfig` also parses. A member there
would have been authorable, parse-clean and unread.

The three places an author reaches for it now answer instead of shrugging:
`chartConfig.drillDown` → the react prop; `widget.drillDown`/`widget.drilldown` →
dashboard drill is AUTOMATIC, plus both configurable drills named;
`report.drillDown` → back to the chart prop.

## Two-way disambiguation with ReportSchema.drilldown

Same word, one letter apart, two capabilities. Edit distance actively gets this
wrong — the spellings are distance 1, so a bare "did you mean" sends an author to
the boolean slot where their config object fails a second time. Both gates name
the TYPE difference, not just the spelling.

## Declared = enforced, in the same commit

`.strict()` is a property of a parse, and nothing on the react surface called
one. `validate-react-page-props.ts` now PARSES the schema against a static
`drillDown={{…}}` literal (`react-chart-drilldown-invalid`) instead of
re-deriving the rules the way `CHART_FUNCTIONS` does for `aggregate` beside it —
the fix the strictness ledger's `chart.zod.ts` row has been waiting on, shown on
one key. A value from React state is skipped: unresolvable is not wrong
(ADR-0072 D1).

## Instruments

- 批 15's pin (`chart.test.ts`) is RECONCILED, not relaxed: the ChartInteraction
  prescription still must not say a bare `drillDown`, now because that schema is
  reached from both tiers and cannot tell which, so the advice would be a dead
  end for half its readers.
- 20 new assertions: per-key acceptance, `{}` enables, absent stays optional,
  unknown key rejected with the surface named, each non-chart key rejected with
  its reason, `target:'navigate'` prescribed (and a plain wrong value NOT given
  that text), the carrier verdict pinned in both directions, and the published
  react type string derived-checked against the schema shape.
- 10 lint-gate tests; ledger row and site counts updated (`ui/` 198 → 199).

Filed, not fixed here: #5175 (`chartConfig` delivers 1 of 12 keys on the
dashboard path; the liveness row's evidence overstates it) and objectui#3354
(`DrillDownConfig.view`/`.sort` read by nothing; `navigate` silently degrades).

Fixes #5022

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ehu85kbvMcrNTUJjwxvLJ9
@vercel

vercel Bot commented Aug 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 4, 2026 11:21am

Request Review

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/lint, @objectstack/spec.

107 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx (via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx (via @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via @objectstack/spec)
  • content/docs/api/environment-routing.mdx (via @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx (via @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/spec)
  • content/docs/automation/approvals.mdx (via @objectstack/spec)
  • content/docs/automation/connectors.mdx (via @objectstack/spec)
  • content/docs/automation/flows.mdx (via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx (via @objectstack/lint, packages/spec)
  • content/docs/automation/hooks.mdx (via @objectstack/spec)
  • content/docs/automation/index.mdx (via @objectstack/spec)
  • content/docs/automation/webhooks.mdx (via @objectstack/spec)
  • content/docs/automation/workflows.mdx (via @objectstack/spec)
  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via packages/spec)
  • content/docs/concepts/north-star.mdx (via @objectstack/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx (via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx (via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx (via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx (via @objectstack/spec)
  • content/docs/data-modeling/index.mdx (via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx (via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx (via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx (via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx (via @objectstack/spec)
  • content/docs/deployment/cli.mdx (via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/deployment/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx (via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx (via packages/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via packages/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/spec)
  • content/docs/kernel/services.mdx (via @objectstack/spec)
  • content/docs/permissions/authorization.mdx (via @objectstack/lint, @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx (via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/permissions/positions.mdx (via @objectstack/spec)
  • content/docs/permissions/rls.mdx (via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/plugins/development.mdx (via @objectstack/spec)
  • content/docs/plugins/index.mdx (via @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/protocol/diagram.mdx (via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/http-protocol.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx (via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx (via @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v12.mdx (via @objectstack/spec)
  • content/docs/releases/v13.mdx (via @objectstack/spec)
  • content/docs/releases/v16.mdx (via @objectstack/spec)
  • content/docs/releases/v17.mdx (via @objectstack/lint, @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/spec)
  • content/docs/ui/actions.mdx (via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx (via @objectstack/spec)
  • content/docs/ui/dashboards.mdx (via @objectstack/spec)
  • content/docs/ui/forms.mdx (via @objectstack/spec)
  • content/docs/ui/index.mdx (via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx (via @objectstack/spec)
  • content/docs/ui/setup-app.mdx (via @objectstack/spec)
  • content/docs/ui/translations.mdx (via @objectstack/spec)
  • content/docs/ui/views.mdx (via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

…ger surgery)

#5220 (#5107) split the strictness ledger into numbers and prose: every count
moved to the generated `…ledger.counts.md` (`gen:strictness-ledger`, os-regen
managed), and the hand-written file lost its numeric columns and header figures.
This branch had hand-edited exactly those numbers, so both conflicts were mine.

Resolution, per the rule the split exists to enforce — never hand-carry a count:

* Both conflict hunks taken WHOLE from origin/main (the de-numbered `ui/` triage
  table header and the `#### ui/ — remaining strip sites` table).
* Every number I had touched is DISCARDED and recomputed by the generator:
  `ui/` 198 → 199, strict 117 → 118, total 482 → 483, `chart.zod.ts` 7 → 8, and
  the strip-of table's `2 | 8`. All of that is now generator output in
  counts.md; my diff against main under `docs/audits/` contains no hand-written
  digit.
* The two PROSE edits are re-applied onto main's rows, in the new format:
  the triage `Class` cell reads `**mixed — 6 authorable, 2 no gate**`, and the
  remaining-strip row keeps main's `**no gate**` verdict (no split declaration
  needed — that Class is not `mixed`/`split`), extended with the note that the
  eighth site arrived with its publish gate already wired.

`strictness-ledger.test.ts` merged cleanly: main only APPENDED the #5072 chain-
posture cases, and my `chart.zod.ts` 7 → 8 assertion is a unit test of the AST
counter, not of the ledger document, so #5107 does not subsume it and it stays
where it is. Nothing to re-hang.

Verified after the merge: spec 306 files / 7856 tests, lint 57 / 1190, both
typecheck clean, `check:generated` 9/9 (including the new counts gate), and
`check:strictness-ledger` green on all three of its sections.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ehu85kbvMcrNTUJjwxvLJ9
@xuyushun441-sys
xuyushun441-sys marked this pull request as ready for review August 4, 2026 11:22
@xuyushun441-sys
xuyushun441-sys added this pull request to the merge queue Aug 4, 2026
Merged via the queue into main with commit 0161c7f Aug 4, 2026
25 checks passed
@xuyushun441-sys
xuyushun441-sys deleted the claude/issue-5022-drilldown-declare branch August 4, 2026 11:43
xuyushun441-sys pushed a commit that referenced this pull request Aug 4, 2026
#5221)

The merge with origin/main brought in #5221 (`chart.zod.ts` gains
`ChartDrillDownSchema`). Git text-merged the GENERATED counts file cleanly and
WRONGLY — the ledger's own documented failure mode: each side's row deltas do
not overlap, so the subtotals merge clean while naming a tree neither branch
ever had (483/199, missing #5221's site).

Regenerated via `gen:strictness-ledger` from the merged tree, which is the only
state in which the numbers are right: 484 sites / ui 200, strict 244 / ui 120.
Both hand-written prose rows survive untouched — `view.zod.ts` (this PR) and
`chart.zod.ts` (#5221) are different rows.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ehu85kbvMcrNTUJjwxvLJ9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation protocol:ui size/l tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

drillDown 是 objectui 读的活能力,却不是 spec 声明的任何键 —— #3752 的迁移处方曾指向它

2 participants