Skip to content

refactor(spec): 折叠 #6619 漏掉的两个手写 unrecognized_keys 映射,并把闭合钉从实例拓宽为类(#6805) - #6935

Merged
os-project-manager merged 2 commits into
mainfrom
claude/issue-6805-fold-residual-errmaps
Aug 9, 2026
Merged

refactor(spec): 折叠 #6619 漏掉的两个手写 unrecognized_keys 映射,并把闭合钉从实例拓宽为类(#6805)#6935
os-project-manager merged 2 commits into
mainfrom
claude/issue-6805-fold-residual-errmaps

Conversation

@os-project-manager

@os-project-manager os-project-manager commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

Fixes #6805

前提复核(不继承卡片计数)

在新鲜 origin/main @ 2672f855f 上重跑 census,卡片前提成立

符号 实测位置 卡片记录 类别(按首行 issue.code 判)
strictToolError ai/tool.zod.ts:83(消费 :180 :83/:180 unrecognized_keys — 在类
strictCapabilitiesError data/object.zod.ts:169(消费 :274 正文写 :160,PM 分诊评论已更正为 :169/:274 unrecognized_keys — 在类
uniqueScopeError data/field.zod.ts:271 invalid_union不在类,未触碰

区分「存在 vs 缺席」的对照:同一条查询在同一次运行里找不到 strictVisibilityError / strictWidgetAnalyticsError / strictTenancyError#6804 折掉的三个),因此不是恒真查询。

做了什么

Route 1 + Route 2 都做了,理由与 lane 评估在 #6805 的实施前披露评论里(实施前发布)。

Route 1 — 折叠两张表

手写映射 折叠后 surface
strictToolError strictObject + history: TOOL_STRICT_HISTORY + guidance: TOOL_RETIRED_KEY_GUIDANCE the tool definition
strictCapabilitiesError strictObject + history: CAPABILITIES_HISTORY + guidance: CAPABILITIES_RETIRED_KEY_GUIDANCE 带反引号的 enable

两者的 surface 字符串与消费点的 .strict() / .describe() 链均原样保留,因此前言一句(Unrecognized key(s) on …)逐字节不变。

#6619 记录的「折不了的理由」被证伪,而不是被绕过。 strictCapabilitiesError 的 docblock 明确写着:模板无条件追加 history${message} ${history}),而这两张表不发解释句,「Fold it only when the template can express a history-less surface」。复核后这是文案的缺口,不是模板的极限——history 槽位编码的是位置(两条修复通道之后,#5955/#6416 的排序契约),#6804strictTenancyError 时已经据此把常驻解释句放进该槽;这两个面同样有真实可陈述的历史(关门前未声明键被静默 strip,#1535 类),写下来即可折。两句都写进了源码 docblock,连同「为什么之前是空的」。

Route 2 — 闭合类,不是实例

alias-integrity.test.ts 新增按 AST 判定的类闭合钉:包内任何模块把自己写的、分支在 unrecognized_keys 上的映射交给一个 zod 工厂调用的 { error } 参数,即红。

判据是两个合取项,无豁免名单

  1. 已挂载——出现在某个 z.xxx(…) 工厂调用的 params 对象里。schema.safeParse(data, { error: map }) 是调用方一次解析的选择,不是 shape 的属性。
  2. 决断 unrecognized_keys——按映射分支的 code 判,不按名字。

两个活体反例把这两个合取项各自钉成实测对照,而不是写进豁免表:

  • data/field.zod.tsuniqueScopeError:挂载方式与本类完全一致(z.union([…], { error: uniqueScopeError })),扫描够得着它,然后按 code 判它出局invalid_union)。「不要把它扫进来」由仪器执行,不由名字。
  • shared/error-map.zod.tsobjectStackErrorMap确实决断 unrecognized_keys,但从不挂到 shape 上(按次解析的全局兜底,只有一句通用「check for typos」,没有按键内容)。第一版粗判据(裸字面量)把它和邻居 carriesUnknownKey(一个只读 issue.code 排序 union 分支的谓词)一起误报了——这是本 PR 实现过程中的真实发现,判据据此收紧。

扫描覆盖全部模块,含 HELPER_MODULES,刻意不设豁免:收紧后的判据下 helper 本身也不命中(strict-object.ts 唯一的 z.object(shape, { error: … }) 传的是对共享工厂的调用,而「调用」正是「非手写」的样子)。实测确认,而非假设——一条什么都不豁免的豁免,读起来像覆盖率,正是本钉要取代的那份清单的失败形态。

为什么 Route 2 不占用 #6635 的设计空间

本 PR 的闭合钉 #6635
判据 结构:某模块把自写的、决断 unrecognized_keys 的映射挂到 shape 上 散文:同一文件内退役符号的多处提及,一部分带退役注解、一部分不带且现在时
单位 一处错误映射声明 一次符号提及
抓的缺陷 guidance 通道绕开注册表 一次退役只更新了部分提及

关键点:本钉抓不到 #6635 要抓的东西。折叠之后 TOOL_RETIRED_KEY_GUIDANCE 仍可能含有指向已不存在键的处方(#6756/#6758 那一类),结构钉对此完全沉默——那正是 #6635 存在的理由。这句话写进了钉子自身的注释。

盲区闭合的实测证据(注册表可见性 before/after)

strictObjectDeclarations() 全量强制遍历后计数,与 alias-integrity.test.ts 同一套 force + dedup:

折叠前(2672f855f 折叠后
唯一声明面 291 293
其中携带 guidance/guidanceSets 129 131
the tool definition 不可见 可见
带反引号的 enable 不可见 可见
移除的面 0
对照:#6804 折的三个面 可见 可见(不动)

新增恰为两个,与折叠的两张表一一对应。

接受面:逐字节不变(探针矩阵)

46 个用例(22 tool + 20 capabilities + 4 经 ObjectSchema.enable 的真实作者门),逐例记录 parse 输出issue code+path(刻意不记 message——message 允许移动)。折叠前后 diff 为空,合并 origin/main @ 183b4c47b 后再跑一次仍为空。

覆盖:最小/完整合法体、五个退役键各自单独与全上、编辑距离内/外的未知键、多未知键、未知键+退役键、值级拒绝(regex 不匹配、缺必填、类型错、非对象、null、空对象)、protection envelope 键、apiMethods 的 primitives/legacy/legacy-only/空数组/非法值。

消息装配的刻意变化(按 #6804 既有的三类)

  1. 处方文本逐字节保留(有专门的 byte-for-byte 钉)。
  2. 无处方的键改由模板的编辑距离通道作答——这是本折叠对读者唯一的净收益,共 8 处:labllabelparamatersparametersobjectnameobjectNameoutputSchemoutputSchemasearchiblesearchabletrackHistroytrackHistoryclonclonefeedfeeds。此前它们只被告知「x is not a ToolSchema field.」/「is not an enable capability flag.」——说了问题、没给修复。与 refactor(spec): 三个手写 unrecognized_keys 错误映射折叠进 strictObject 的按集合取键 guidance(#6619) #6804 折 tenancy 时(tenantfieldtenantField)同一处置。
  3. 两个面首次带上解释句(此前为空槽),位置在最后,每条消息一次。

发射顺序契约(前言 → 修复通道 → 解释句最后)在两个面各有一条专钉。

#6804 遗产的处置

反向验证(方向在运行前预测)

实验 预测 实测
RV1 还原 strictToolError 手写映射 红:类钉 + tool 实例钉 ✅ 2 红,恰为这两条;类钉报 ai/tool.zod.ts:195 — strictToolError
RV2没有任何实例钉点名的面上新增一个全新手写映射 类钉红,全部实例钉绿 ✅ 1 红(data/object.zod.ts:625 — rv2BrandNewError),含 #6804 三面钉在内的实例钉全绿
RV3 两个源文件回到 origin/main(钉子保持 #6805 形态) 13 红 ✅ 13 红:tool 改名 4 + 顺序 1、capabilities 改名 4 + 顺序 1、实例钉 1、类钉 1、ledger 夹具对照 1

RV2 是把 route 2 与 route 1 分开的那次测量:一个全新的手写映射对每一条实例钉都是隐形的,只有类钉抓得住。

RV3 里刻意保持绿色的对照:「超出编辑距离的键仍被点名、且不给误导性建议」(×2)与「处方文本逐字节保留」(×2)——它们两侧都绿,这正是它们作为对照而非变更钉的资格。

反真空守卫

类钉断言的是「搜索结果为空」,正是仪器坏掉时同样会通过的形态。四条对照:

  • (a) 认得出类:拿本 PR 折叠之前 mainstrictToolError 及其接线的真实源码作标本,扫描命中第 9 行。
  • (b) 不是 grep:只在散文里提及 unrecognized_keys 的模块——本包遍地都是,包括这条钉自己的注释——命中为 0。文本扫描会把它们全部误报,判据就只能退化成豁免名单。
  • (c) 挂载合取项有用objectStackErrorMap 决断该 code 却不在类(实测负例,非豁免)。
  • (d) code 合取项有用uniqueScopeError 挂载方式在类却不在类。

没有把「helper 模块会亮」当对照——粗判据下它会,收紧后不会,因此诚实的活性证据是 (a) 那个仪器从未见过的新文件。)

顺带修掉的一处 in-radius 陈述腐烂

data/field.zod.ts 的 docblock 写着「pattern of strictCapabilitiesError」——本 PR 折掉该符号后这个指针会失效(正是 #6635 那一类)。替换为「本文件为什么跟着折」的说明,并点明类钉正把这个站点当活体对照读。

test-typecheck-debt.json 台账

before == after,文件未改动:58 文件 / 266 错误。check:test-typecheck 两次运行均报同一数字。

验证(均在合并 origin/main @ 183b4c47b 之后复跑)

  • pnpm --filter @objectstack/spec test349 文件 / 9055 用例全绿
  • pnpm --filter @objectstack/spec typecheck:绿(tsc + check:scripts-typecheck + check:test-typecheck 58/266 未增)
  • pnpm --filter @objectstack/spec check:generated10 个生成工件全部最新(含 check:api-surface——两张映射均为 module-private,公开导出面零变化;含 check:authorable-surface,它以 OS_EAGER_SCHEMAS=1 运行,即 ObjectCapabilities 模块作用域 strictObject 调用的 TDZ 实测清账;含 check:strictness-ledger,counts 工件零再生)
    • ⚠️ 首跑 check:api-surface 报 stale——新 worktree 未 build 的幻影,pnpm --filter @objectstack/spec build 后复跑全绿
  • check:exported-any / check:dual-source-exports / check:liveness:绿
  • node scripts/check-nul-bytes.mjs:绿;触碰文件另做超出门面的自扫([\x00-\x08\x0b\x0c\x0e-\x1f\x7f]):无命中
  • npx eslint(7 个触碰文件)--no-inline-config:exit 0
  • check:empty-changeset / check:doc-authoring / check:role-word / check:adr-anchors:绿
  • 下游抽查(先 build 依赖闭包,避开 Failed to resolve entry 假红):@objectstack/lint 67 文件 / 1759 用例绿,@objectstack/metadata-protocol 64 文件 / 763 用例绿

消费半径清扫

packages/spec 之外对两个旧符号名、两条旧兜底消息字节的引用为;下游测试中没有任何一条钉住这两个面的消息(按字面短语与 toMatch(/…/) 转义正则两种拼法各扫一遍)。

声明顺序(#5593 的 TDZ 约束)

ObjectCapabilities 不是 lazySchemastrictObject 在模块作用域求值其 options,因此 CAPABILITIES_RETIRED_KEY_GUIDANCECAPABILITIES_HISTORY 必须在其之上声明——两者本就在。约束写进了 ObjectCapabilities 的 docblock(与 ObjectSchemaBase#5593 的同类警示对齐),并由 OS_EAGER_SCHEMAS=1 的全量 build 实测清账。

Changeset

.changeset/fold-residual-unrecognized-key-maps.md@objectstack/spec: patch


Generated by Claude Code

os-project-manager and others added 2 commits August 9, 2026 04:39
…e the class (#6805)

#6416's blind spot was declared closed by #6619/PR #6804, but its inventory
was two short. `strictToolError` (ai/tool.zod.ts) and `strictCapabilitiesError`
(data/object.zod.ts) were the same shape — `unrecognized_keys` prescription
tables attached to a `.strict()` object via `{ error: … }`, seen by no
registry — and `TOOL_RETIRED_KEY_GUIDANCE` is a hand-maintained per-key
retirement table, the most rot-prone content the audit exists for.

- Both maps fold into `strictObject`'s `guidance` channel. #6619's stated
  blocker (the template appends `history` unconditionally; these surfaces
  emitted no trailing sentence) was a gap in the TEXT, not a limit of the
  template — the slot encodes position, and both surfaces had a real history
  nobody had written down.
- Registry visibility 291 -> 293 surfaces (129 -> 131 carrying guidance);
  added exactly `the tool definition` and `` `enable` ``, removed none.
- alias-integrity gains a CLASS pin: no module may hand a zod shape a
  hand-written map that decides `unrecognized_keys`. Two conjuncts (attached
  AND deciding that code), no allowlist — `uniqueScopeError` (invalid_union)
  and `objectStackErrorMap` (per-parse, never attached) are out of class by
  measurement, each pinned as a live control.
- Acceptance byte-for-byte unchanged: 46-case probe matrix identical before
  and after (parse output + issue code/path). Message assembly moves per the
  #6804 precedent; 8 keys gain the rename channel.
- strictness-ledger fixture moves to PerOperationRequiredPermissionsSchema,
  per that test's own instruction, with a control on the two vacated sites.

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

vercel Bot commented Aug 9, 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 9, 2026 4:52am

Request Review

@github-actions github-actions Bot added the size/l label Aug 9, 2026
@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

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

113 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/tenancy-modes.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 @objectstack/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/data-service.mdx (via @objectstack/spec)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/examples.mdx (via @objectstack/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 @objectstack/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via @objectstack/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/permissions/system-context.mdx (via packages/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/spec)
  • content/docs/releases/v9.mdx (via @objectstack/spec)
  • content/docs/ui/actions.mdx (via @objectstack/spec)
  • content/docs/ui/apps.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/field-grouping-and-order.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.

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

⛔ merge queue 构建失败 — 先分诊,再决定要不要重排

队列构建 31297316580 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集),
所以失败的测试可能在本 PR 没碰过的包里 —— 那不是重排能修的。每次盲目重排都会让排在后面的所有 PR 重建一轮。

失败的 job(日志抽取,best effort):

  • Test Core (3/3) — 失败步骤: Run this shard's tests

    �[41m�[1m FAIL �[22m�[49m src/commands/database-driver-allowlist.pin.test.ts�[2m > �[22m#6860 — --database-driver allowlist agrees with resolveStorageDefinition�[2m > �[22mos start�[2m > �[22moffers e
    �[41m�[1m FAIL �[22m�[49m src/commands/database-driver-allowlist.pin.test.ts�[2m > �[22m#6860 — --database-driver allowlist agrees with resolveStorageDefinition�[2m > �[22mos dev�[2m > �[22moffers eve
    �[41m�[1m FAIL �[22m�[49m src/commands/database-driver-allowlist.pin.test.ts�[2m > �[22m#6860 — --database-driver allowlist agrees with resolveStorageDefinition�[2m > �[22mos start�[2m > �[22mparses e
    �[41m�[1m FAIL �[22m�[49m src/commands/database-driver-allowlist.pin.test.ts�[2m > �[22m#6860 — --database-driver allowlist agrees with resolveStorageDefinition�[2m > �[22mos dev�[2m > �[22mparses eve
    

历史信号:

  • 本 PR 过去 24h 无队列失败记录(首次)。
  • 过去 24h 队列共有 8 个失败构建(不含本次)。

分诊清单:

  1. 失败测试在本 PR 改动的包里 → 真回归,修 PR。
  2. 失败测试与本 PR 无关 → 在其他 PR 的同类评论里搜同名测试;出现过 ⇒ flaky 实锤,开 issue 修/隔离那条测试。修好前重排只会再烧一轮全队列。
  3. 两者都不是 → 可能与同组 PR 语义冲突;等前面的 PR 落地或失败出队后再重排一次即可,不要连续重排。

Generated by Claude Code · merge-queue-triage workflow (#4859)

Copy link
Copy Markdown
Collaborator Author

队列失败分诊 —— 与本 PR 无关,且⛔ 本席暂不重排。 spec-surface 席 #6298

按 E15 三路分诊走,而不是直接重投。

清单第 1 条 —— 失败测试在本 PR 触及的包里吗?否。 本 PR 只改 packages/spec(ai/tool.zod.tsdata/object.zod.tsshared/alias-integrity.test.tsshared/strict-object.ts 等)。失败的是 packages/cli/src/commands/database-driver-allowlist.pin.test.ts。折叠两张 unrecognized_keys 错误映射,够不到 CLI 的 --database-driver flag 与 resolveStorageDefinition 的一致性。

清单第 2 条 —— 他处见过吗?见过,而且就在几分钟前。

本席的另一张 PR #6918 在一次独立的队列构建里红在完全相同的四条断言上(build 31297338477,本 PR 是 31297316580)。两张 PR 面向完全不同的文件面(#6918kernel/execution-context.zod.ts + security/rls.zod.ts.describe()),唯一共同点是都不碰 packages/cli

两次独立构建、同一组失败、两个无关的 diff —— 这排除了「某一张 PR 造成的回归」。

所以为什么不重排: 重排只在「失败与本 PR 无关下一次构建条件会不同」时才有意义。这里两张都中,说明触发条件与我的 diff 无关 —— 重排任何一张都只是再烧一轮全队列,然后大概率红在同一处。今晚已有先例:#6847 的 flaky 重排一次即过,但那次的判据是同批的 #6846 跑同一套全量套件并合并成功,即存在绿的对照。这次没有那个对照,两张都红。

背景读数(git 协议,不吃 REST 配额):

待确认的一项:该钉在干净 main 上是否已红。本席正在独立探针里跑这一条 —— 结论决定这是「main 已坏、影响所有 PR」还是「同批语义冲突」。⛔ 在拿到读数之前不重排。

若探针显示 main 已红,本席会立卡并通知维护者:那是全队列级阻塞,归 domain:cli,不是任何一张排队 PR 能修的。


Generated by Claude Code

Merged via the queue into main with commit 44d677c Aug 9, 2026
28 checks passed
@os-project-manager
os-project-manager deleted the claude/issue-6805-fold-residual-errmaps branch August 9, 2026 06:05

Copy link
Copy Markdown
Collaborator Author

结案 —— 探针读数出来了,两张也都已合入。⛔ 全程没有重排,而不重排是对的。

探针结论:该钉在干净 main 上是绿的。 两个不同 ref 上各跑一次,均 Test Files 1 passed / Tests 10 passed:

所以不是 main 已坏。排除了那个分支之后,剩下的是同批语义冲突 —— 而它自己解决了:GitHub 的自动队列管理在批次组成变化后重投,两张都直接通过并合入(d03fe2528 / 44d677c93)。

这正是不重排的价值所在。 若当时手动重排,得到的是同样的结果加上一轮全队列重建的代价;而如果重排后仍红,还会诱使人再排第三次。判据不是「看起来像不像 flaky」,而是有没有一个绿的对照:

#6847(今晚早些时候) 本次
现象 单张被弹 两张无关 PR 在两次独立构建里红在同一签名
对照 同批 #6846 跑同一套全量套件合并成功 ⇒ 套件本身没坏 无对照,两张都红
处置 重排一次 ⇒ 即过 不重排 ⇒ 自动队列自行消解

补充一条对下一个撞上这条钉的人有用的读数:两张 PR 的队列分支相对 mainpackages/cli零改动(git diff --stat origin/main...<queue-ref> -- packages/cli 为空),所以同批里也没有人改 CLI。结合「干净 main 双 ref 皆绿」,这条钉的红既不来自 main、也不来自任何一处 CLI 侧改动 —— 它对批次的组成敏感,而不是对某个 diff 敏感。

该钉是 9d425a94d(PR #6913,收 #6860)几小时前引入的双侧源码推导型一致性钉:一侧读 oclif flag 定义,另一侧读 packages/cli/src/utils/storage-driver.ts 的源文本。它的注释写明这是刻意设计。这种形态在全量队列构建里对上下游构建产物的状态更敏感,值得 domain:cli 席位知道 —— 但本席不代其立卡:干净 main 是绿的,没有可复现的缺陷可写,把「我这两张排队时它红过」写成 CLI 的 bug 会是一张无法复现的卡。读数留在这里,给下一个撞上的人。


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

2 participants