Skip to content

fix(spec): make the bulk-action option item's openness deliberate, not accidental (#4001) - #4909

Merged
xuyushun441-sys merged 3 commits into
mainfrom
claude/issue-4001-bulk-action-options
Aug 3, 2026
Merged

fix(spec): make the bulk-action option item's openness deliberate, not accidental (#4001)#4909
xuyushun441-sys merged 3 commits into
mainfrom
claude/issue-4001-bulk-action-options

Conversation

@xuyushun441-sys

Copy link
Copy Markdown
Contributor

Part of #4001

执行 2026-08-03 11:42Z 维护者裁决第 ② 项(方案 A):给 BulkActionParamSchemaoptions 条目补 .passthrough(),让代码与旁边那句散文一致。裁决不再重议,本 PR 只负责执行 + 交出裁决要求的先验证据。

先验证据(裁决的执行前提)

裁决明确要求先核 objectui 侧兜底确实存在——因为台账散文本身刚被证明会漂。核完的结论是:兜底存在,但不在裁决预期的那一层,所以这里把实测贴全,而不是只回一句「已确认」。

位置 实际是什么
类型 objectui packages/types/src/objectql.ts:271 options?: Array< { label: string; value: string | number | boolean } > —— 封闭,没有索引签名
运行时 objectui packages/plugin-grid/src/components/bulkParamToField.ts:131 options?.map(o => ({ ...o, value: String(o.value) })) —— 展开,每个多余键原样存活
落点 objectui packages/types/src/field-types.ts:288 SelectOptionMetadatalabel/value 之外声明 color / icon / disabled / visibleWhen

而且落点的键确实被读:option?.color 见 objectui packages/fields/src/index.tsx:1089(dot 外观)与 :1101(badge 配色)。

所以裁决的业务论据成立,且比预期更强:被 strip 掉的不是「可能有人想写的自由字段」,而是渲染器会真的读、真的画出来的 widget 配置。作者写下 color: '#8B5CF6' 只会得到一个默认色的徽章,没有任何提示。

一处必须如实说明的偏差:裁决措辞是「核 objectui 侧那个 [key: string]: unknown 兜底确实存在」。在 param 这一层它确实存在(objectql.ts:293,注释写明 min/max/step/format 转发给字段渲染器);但在 option 条目这一层没有——那一层的类型是封闭的,开放性来自展开 + 落点类型。结论不变(passthrough 仍是对的姿态,且与运行时一致),但依据换成了实测事实。这条类型/运行时不一致已按 Prime Directive #10 单独归档为 objectstack-ai/objectui#3309,未在本 PR 修改 objectui(该仓本次只读)。

改动

  • packages/spec/src/ui/bulk-action.zod.ts:option 条目 .passthrough();模块头 rationale 块补一条,按本文件惯例写清为什么这一层是开的,并带上上表的 file:line。
  • 测试:钉住新行为(color/icon/disabled/visibleWhen 存活),并在注释里明说这是刻意开放,连同证据,好让下一轮 strict 化扫荡走到这里停住而不是「顺手修好」。另加一条反向断言——开放 ≠ 无形状,label 缺失仍然报错。
  • 台账:ui/bulk-action.zod.ts strip 归零 → 按 fix(spec): #4001 重测 —— 实测剩余站点清单,并修好测量它的那把尺 #4852 的反向闸删除其 remaining-strip 行,表头 124 → 123 of 198,并把 triage 行那句「both deliberately open」改成如实描述(原文正是漂移本身)。
  • changeset:minor,放宽(原先被剥掉的键现在保留),明说行为变化;无迁移动作。

.describe() 那笔是被动修补:gen:docs 把数组里的 passthrough 对象渲染成 Record< string, any >[],一开放就把 { label, value } 的形状从参考页上抹掉了——一个仍有两个必填键的东西在作者面前显示成「无形状」,正是 strip 时代那股味道反过来。形状与开放理由因此写进该键自己的 .describe(),生成器会原样渲染。

验证

先证红,再信绿(战役自定规矩),台账闸门两个方向都诱发过:

控制组 1(把删掉的行加回去)
  ✗ ledger:650 — `ui/bulk-action.zod.ts` has NO strip sites left, but still has a row
    in the remaining-strip map. → the file is CLOSED: delete the row and decrement the header.

控制组 2(把 .passthrough() 撤掉)
  ✗ `ui/` has 1 file(s) with strip sites missing from the remaining-strip map:
    bulk-action.zod.ts (1)

两个控制组都恢复后:

✓ strictness ledger: 67 file(s) across 5 triaged director(ies) — site counts match,
  no undeclared schema files, section totals balance.
✓ remaining-strip map: 50 open file(s) / 324 strip site(s) across 4 director(ies)

基数从 51 文件 / 325 站点降到 50 / 324,与本单预期恰好一致。

其余闸门(packages/spec 全部 check,build 先行):

✓ All 8 generated artifacts are up to date.
PASS check:generated / liveness / empty-state / react-declaration-parity
PASS check:skill-examples / variant-docs / strictness-ledger / exported-any / dual-source-exports

Test Files  295 passed (295)
     Tests  7362 passed (7362)
tsc --noEmit  (clean)

近邻消费者 @objectstack/lint + @objectstack/metadata-protocol typecheck 通过(首次报 Cannot find module '@objectstack/formula' 是未构建依赖,即 AGENTS.md §9 那个陷阱,补构建后即 Done,与本改动无关)。本改动是放宽,只会多接受、不会少接受,消费者均以 loose record 读 bulkActionDefs

os-regen 同步

git merge origin/main(未 rebase、未 force),git checkout origin/main -- 全部 merge=os-regen 路径后整体重生成。结果:工作区与本分支提交逐字节一致,且七类生成物对 origin/main 的差集 content/docs/references/ui/bulk-action.mdx 一行——即兄弟 PR 的条目全部存活。


🤖 Generated with Claude Code

https://claude.ai/code/session_01Ehu85kbvMcrNTUJjwxvLJ9


Generated by Claude Code

claude added 3 commits August 3, 2026 15:19
…t accidental (#4001)

`BulkActionParamSchema`'s `options[]` entry was bare default-strip while the
strictness ledger's prose called it and its parent "both deliberately open" —
one intent, two postures, found by the #4001 2026-08-03 re-measure (#4852).

Per the maintainer's verdict A the code moves to the prose: `.passthrough()` on
the option item. Verified before writing, since the prose itself had just been
proven able to drift — objectui's option TYPE is closed
(`Array<{ label; value }>`, `packages/types/src/objectql.ts:271`), but the type
is not what an authored option meets: `bulkParamToField` SPREADS every entry
(`packages/plugin-grid/src/components/bulkParamToField.ts:131`) into the field
metadata, whose vocabulary is `SelectOptionMetadata`
(`packages/types/src/field-types.ts:288`) — `color` / `icon` / `disabled` /
`visibleWhen` beyond the pair, and read (`packages/fields/src/index.tsx:1089`).
So the strip was deleting widget config the renderer would have honoured.

The new test states the openness is deliberate and names the evidence, so a
future strict-ification sweep stops there instead of "fixing" it.

Ledger: `ui/bulk-action.zod.ts` reaches zero strip sites, so its remaining-strip
row is deleted and the header arithmetic reconciled (124 → 123 of 198). Both
directions of that gate were driven red before the green was believed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ehu85kbvMcrNTUJjwxvLJ9
`gen:docs` renders a passthrough object inside an array as `Record<string,
any>[]`, so the reference page lost the `{ label, value }` shape the moment the
entry opened — an author-facing surface reading "shapeless" for something that
still has two required keys, which is the strip-era smell pointed the other way.

The declared pair now lives in the key's own `.describe()`, which the generator
renders verbatim, along with WHY the entry is open and which extra keys the
widget actually reads. Regenerated `content/docs/references/ui/bulk-action.mdx`
accordingly (the one artifact `check:generated` proved stale — not the set).

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

vercel Bot commented Aug 3, 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 3, 2026 3:41pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests protocol:ui tooling size/m labels Aug 3, 2026
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec.

106 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 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/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/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/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.

@xuyushun441-sys
xuyushun441-sys marked this pull request as ready for review August 3, 2026 16:18
@xuyushun441-sys
xuyushun441-sys added this pull request to the merge queue Aug 3, 2026
Merged via the queue into main with commit 2e284b2 Aug 3, 2026
24 checks passed
@xuyushun441-sys
xuyushun441-sys deleted the claude/issue-4001-bulk-action-options branch August 3, 2026 16:29
xuyushun441-sys pushed a commit that referenced this pull request Aug 3, 2026
批 9 (#4925) landed the same automation/ ledger section. Both waves deleted
their own rows and decremented the section header by their own count, so git
merged the ROWS cleanly and conflicted only on the header — while the
authorable subtotal one line below, which conflicted with nothing, merged
clean while being wrong on both branches. Header recomputed from the surviving
rows (42 strip of 75, authorable 16 of 42) rather than resolved in favour of
either side; check:strictness-ledger's header arithmetic is the arbiter and
reads 45 open files / 299 strip sites.

os-regen four-step run: merge -> checkout origin/main for every path in
.gitattributes -> wholesale regenerate -> assert siblings survived. 批 9's
three reference pages and #4909's bulk-action page are byte-identical to
origin/main.

Co-Authored-By: Claude Opus 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/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants