Skip to content

finding(pm-dispatch): 认领评论的「门禁反向要求的派生物」开放臂能把 skills/** 长进实际文件面 —— 档位裁定与净增行数预算都按一个不含它的面定,事后无任何闸比对 #18665

Description

@os-bill

⏱️ 本卡所有读数取自同一动作:2026-09-17T13:21Z;逐条本席第一手实测,来源逐条标注。

症状

派发时的档位是从认领时的文件面导出的。认领评论允许写一条预先申报的开放臂 ——「任何门禁反向要求的派生物」(本班 #18124 的原话)。这条臂是必要的:开发不可能在动工前枚举 check:generated 会要求重生成哪些产物。

但它有一个没有闸的后果:生成器可以把内容写进 skills/**,于是实际 diff 的文件面带上了一条 clause ① 强制 claude-fable-5-1 的路径,而施工已经按认领时导出的档位跑完了。事后没有任何机械闸比对「认领时的面」与「实际 diff 的面」的档位裁定。

实测(第一手,两次 --tier 调用,同一棵 origin/main84ad2e1394)

① 认领时的面(#18124 认领评论逐字点名的 7 个 .zod.ts):

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --tier \
  packages/spec/src/api/contract.zod.ts packages/spec/src/data/field-value.zod.ts \
  packages/spec/src/kernel/plugin-lifecycle-advanced.zod.ts \
  packages/spec/src/kernel/plugin-security-advanced.zod.ts \
  packages/spec/src/kernel/plugin-versioning.zod.ts \
  packages/spec/src/system/auth-config.zod.ts packages/spec/src/system/metrics.zod.ts

Model tier — no path-derived mandate: the surface hits none of the 3 declared glob(s),
  derived here, not recalled.
  The tier stays the PM's per-card judgment call (floor sonnet · default opus · ceiling fable).

⇒ 认领评论写的 Container & model: model: default judgement tier 在认领那一刻是对的

② 实际 diff 的面(PR #18657 的 29 条路径,GET /pulls/18657/files 导出):

node scripts/pm/dispatch-gates.mjs --tier <那 29 条>

Model tier — MANDATORY: claude-fable-5-1 (derived from the file surface, not recalled).
  - skills/objectstack-api/references/_index.md ⇢ 'skills/**' — clause ①
    (2026-09-10 ruling …「必须 fable的还包括对外发布的skills」)
  Exits …: the one-line-class mechanical-edit downgrade is ⛔ NOT available for this
  surface — 'skills/**' carries no one-line exemption (the published catalog,
  2026-09-10 ruling), and one such path closes the exit for the whole card

⇒ 同一张卡,两个面,两个不同的档位裁定,而中间没有任何东西会报警。

③ 那一行是怎么进来的(⭐ 亮控:它确实是生成的,不是有人手写的):

git diff 922c755888 43b24d4c70 -- skills/objectstack-api/references/_index.md
+ - `node_modules/@objectstack/spec/src/shared/duration.zod.ts` — Exports: DurationMs, DurationSeconds

一条排进有序清单的指针,因为 API skill 可达集里新出现了一个 importer。

第二个漏掉的义务:净增行数预算

SKILL.md:546 写:「触 skills/** 的卡,派发词必带 PM 定的净增行数预算」。#18124 的派发词没有带 —— 因为派发时那张面上没有 skills/**。⇒ 同一个缺口一次漏两件,档位与预算。

(本例里预算事后由 dev 自己量了且很小:改动文件 50 → 51 行;整包每个 SKILL.md 之和 6145 → 6145,+0。⇒ 本例无害,但那是运气,⛔ 不是闸。)

为什么定 p3 而不是 p2

危害是有界的:这条臂只覆盖生成器的输出,而生成器输出在落地前会被 check-governed-merges.mjs#11705 例外按字节验一次 —— 不是纯重生成的内容会掉回受管路线、等人批。⇒ 能从这个缺口溜走的,只有「机器生成且已被字节认证」的内容;fable 档的判断力加不到一个字节相等证明上。

⛔ 但这不等于没有缺口:上面的有界性来自另一个仪器的性质,而不是来自档位闸自己想到了这件事。换一个把生成物写进 skills/** 的生成器、或换一条不经 #11705 登记的路径,同一个洞就是无界的。

建议的修法(⛔ 非裁定,列出取舍供排期)

  • A(最小):落地前检加第四条 —— 拿 PR 实际 diff 重跑 --tier,与认领评论的 Container & model 行比对;不等 ⇒ 在卡上记一行、由派发席判要不要重派。只报不拦,因为多数情形(如本例)重派是纯浪费。
  • B:dispatch-gates.mjs 增一个 --tier-drift <claim-tier> <paths> 子命令,把上面这条比对机械化,让它能进巡检。
  • C:认领评论的预申报臂显式排除 skills/** —— 即「派生物落到 skills/** ⇒ 停下回报」。代价是每次 gen:skill-refs 的连带一行都要往返一次,可能过重。

⚠️ 本席不替维护者选;A 与 B 可叠加,C 与前两者互斥。

与既有卡的关系(MCP search_issues,含 closed)

触发本卡的现场

domain:spec seat 2(座位贴 #18549)在 PR #18657 落地前检时读到的。该 PR 本身已按普通队列入队,⛔ 不因本卡停下 —— 本卡治的是规则的缺口,不是那一行内容。


Generated by Claude Code

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions