## 问题 `BatchOptionsSchema`(`packages/spec/src/api/batch.zod.ts:64`)声明了: ```ts validateOnly: z.boolean().optional().default(false) .describe('If true, validate records without persisting changes (dry-run mode)'), ``` 该字段挂在 `updateManyData` / `deleteManyData` 的 `options` 上(`protocol.zod.ts:526,541`)以及 `/batch` 请求体里。但**运行时没有任何一处读它** —— 全仓 grep `validateOnly` 的消费者为零(只有 schema 声明和一个断言默认值能解析的测试)。`protocol.ts` 的 `updateManyData` / `deleteManyData` / `batchData` 都无条件落库。 ## 为什么这比无害的 no-op 更糟 `validateOnly` 的语义是**数据安全承诺** —— 调用者以为在跑一次不落库的预检(导入前校验一批记录、CI 里验证 payload),实际行为是**照常写库**。这个字段把"预演"骗成了"真删/真改"。这是 PD #10「声明 ≠ 强制」里危害最高的一类:不是能力缺失,而是**契约主动误导**。 对比同组三个兄弟,全都真实生效,唯独它悬空: | 选项 | 运行时消费点 | |------|------| | `atomic` | `protocol.ts:3482` + `rest-server.ts:6607`(`atomic===false → 400`) | | `returnRecords` | `protocol.ts:3501` | | `continueOnError` | `protocol.ts:3486,3610` | | **`validateOnly`** | **无** | ## 决定:墓碑退役(而非仓促实现) 一个真正的 dry-run 有独立的设计空间(no-commit 下的 cascade / 唯一约束语义、响应契约该如何表达每行"若执行是否会通过"),值得在有真实需求时单独立项做对,而不是为了填坑仓促实现。因此: - `batch.zod.ts`:`validateOnly` → `retiredKey(...)` 墓碑(写它 → 解析报错并给出处方,而非静默剥除,ADR-0104)。 - `step18.semantic[]` 注册一条 semantic 迁移记录(与 `analytics-query-request-format-retired` 同型:声明但从未实现、无存储可改写,故为 semantic TODO 而非 stack conversion),使 `spec-changes.json` / upgrade-guide / `spec_changes` MCP 工具如实记录本次退役。 - major changeset。 `validateOnly` 是 optional + 有 default,退役不影响任何现有正确调用者。日后要做 dry-run 随时可重新引入一个设计完整的版本。 ## 顺带(同一 PR) `packages/spec/src/api/plugin-rest-api.zod.ts:918` 的 `requestSchema: 'CreateManyRequestSchema'` 是一处**悬空引用** —— 从未有 schema 导出此名(真实契约是 `protocol.zod.ts` 的 `CreateManyDataRequestSchema`)。该字符串运行时和 OpenAPI 生成都不消费,是文档字符串失真,危害低于 `validateOnly`。改指向真实存在的 `CreateManyDataRequestSchema`。
Activity
docs(api): drop retired validateOnly from hand-written batch examples (…
feat(spec)!: retire BatchOptions.validateOnly — a dry-run flag never …
Merge main into the wait-timeout retirement branch (2nd)
fix(spec)!: the retirement prescriptions name protocol 17, the major …
fix(spec)!: the retirement prescriptions name protocol 17, the major …
docs(client): drop the retired validateOnly batch option from the REA…
test(spec): the first api/ file group's test titles state each cited …
test(spec): the second api/ file group's test titles state each cited…