Skip to content

Commit 04492ec

Browse files
docs(pm): the security seat triages a non-finding, reads a release by ancestry, and recovers the CI flakes the relay cannot re-run (#30155)
Fixes #30111 Clause-②: no Metadata-protocol: none ## 维护者速读 - 改了什么:安全席的五个工作步骤写进各自归属的那一份 pm-dispatch 参考文件:无门铃公告的认领与关闭、发布状态归谁、版本内容按祖先判、把写挪到应答之后的 PR 的入队前检查、中继重跑不了的 CI 抖动怎么恢复。 - 为什么改:这些步骤 11-03/04 的工作轮里实际用过,技能文本里没有或写法不同;维护者让安全席走过「认领处理关闭」流程后立了本卡。 - 风险与回滚:只改三份技能参考,不动代码、不动门禁;三份文件行数都停在上限,新增行靠删掉别处已有的重复表述付账。回滚即还原本 PR。 - 先看:`lanes/security.md`(接收 ② 与判定两行、祖先两行);`platform-readings.md` 重跑段新增三行;`review-checklist.md` 末尾新增两行。 - 两分钟验证:`node scripts/pm/check-skill-line-ratchet.mjs`,预期全部 ✓,三份文件各自 headroom 0。 - 需要你做的:无,席位落地(Tier S,由安全席出契约复核记录后入队)。 ## What changes Each of the card's five additions lands in the one reference that owns its topic. All three files are under `.claude/skills/pm-dispatch/references/`. 1. **A report that is not a finding** goes in `lanes/security.md`, section 接收与台账. A second intake route is added: an advisory sitting in `triage` with no doorbell (an outside report, or a relay live test). The seat reads it through `advisory_read` and claims it as a `received` row on the seat post. Then it judges the advisory. A finding moves to `draft` through the relay's `advisory_state` and follows the fix path. A non-finding moves to `closed`, and its ledger row says it was not a finding, with no detail (the ledger line already bars detail). The line naming where advisory ids come from gains "a relay live test". 2. **Ledger states** stay in `lanes/security.md`. PR #30135 had already put `closed` (fix merged) into the vocabulary and the relay publish onto the maintainer's list. What remained was which state move belongs to whom. The publish line now says that the maintainer's approval of the list is `awaiting publish`, and the seat's relay publish is `published`. The vocabulary line is unchanged. 3. **A release's contents are read by ancestry** goes in `lanes/security.md`, section 呈维护者, next to the publish-list line. That section owns the per-release list. `release-aftercare.md` owns production roll-out duties and has no publish list. A fix is in version X only if its merge commit is an ancestor of the commit tagged for X (`git merge-base --is-ancestor`). A merge time earlier than the tag time is not proof. 4. **A change that moves work after the response** goes in `review-checklist.md`, section 测试与门禁证据, beside the `dogfood_battery` check. It is a review step before landing. `true-green.md` is a per-repository index of how to run checks, so it does not own it. The dogfood jobs skip `pull_request` and `merge_group` (ci.yml THE TWO SPEEDS). So a PR that moves a send or write to after the response can be green everywhere and still red `main` on push. Before queueing, the seat greps `packages/qa/dogfood/test` for readers of that side effect straight after the answer, and has them wait within a bound in the same PR. 5. **CI recoveries the relay leaves** go in `platform-readings.md`, directly under the existing `rerun-failed.mjs` rule. `rest-channel.md` is the per-operation channel table and does not hold the rerun or re-queue rules. Three lines are added: - `run_rerun_failed` covers `ci.yml` only (`RERUN_FAILED_WORKFLOWS`). ⛔ Never an empty commit, never close and reopen. - `pr-automation.yml`: the seat's body edit that records the flake reason is an `edited` event, and `edited` re-runs `Check Changeset` (the workflow's `on.pull_request.types` lists it). - `lint.yml`: once `main` has moved, a relay `pr_update_branch` produces a real new head with a full run. While the head is level with `main`, the update is a no-op. The merge-group case (the failed step is `Checkout repository` timing out) is folded into the existing known-flaky re-queue line, which now also says to record the reason on the PR. The neighbouring line ("a second ejection of the same PR stops re-queueing") already limits it to once. **How each file stays at its line ceiling.** The ratchet allows no raise without a ruling, so every added line is paid for by deleting text that already lives somewhere else: | file | lines | deleted (said elsewhere) | |:--|:--|:--| | `lanes/security.md` | 53 → 53 | the fix-dispatch line restated `security-findings.md` §3 (no-card dispatch, `xhigh`, mechanism only in the order); the contract-review lines restated §6; the card-closing line restated `landing-operations.md` (MERGED closes `Fixes`/`Part of` cards); the mis-disclosed-card line restated §7. Each line now points to its section. | | `review-checklist.md` | 76 → 76 | two head-pin lines said the same thing, so they are merged; "the gate families run inside" (stated in AGENTS.md) and "do not skip on a reported local green" (stated by the next-but-one line, "the local union proves only the local subset") are deleted | | `platform-readings.md` | 458 → 458 | a second copy of the quota section's "a user ID in the rate-limit message is no evidence of a shared pool" line; the GraphQL-pool line's restated definition of "the few things with no REST equivalent"; and from the `rerun_failed_jobs` pair, the recipe `landing-operations.md` spells; after the review, the merge-time judgment is restored and paid for by folding the `minimal_output` pair into one line (dropping the 107-point figure, stated in the quota section, and the unmeasured narrow-interface alternative) | `lanes/security.md` still carries no finding, advisory id, path, object name or mechanism. Its diff names only relay op names, the existing `GHSA-ID` placeholder and the `git merge-base` command. **Governed surface:** the diff touches `.claude/**` (Tier S). It lands on the owning seat's contract-tier review of record, not on green alone. ## Tests Prose-only change to skill references: no test file, no ablation (no tested behaviour changed). Line widths were measured before writing: every added or rewritten line is at most 120 bytes. ## Acceptance notes - Item 2: #30135 already did most of it, so the residue here is one rewritten line (the state owners on the publish line). - Not edited, noted only: `SKILL.md` still names MCP `rerun_failed_jobs` as the one exception to "no MCP writes". `platform-readings.md` routes a seat's re-run through `rerun-failed.mjs` (the relay). Those two lines may disagree. `SKILL.md` is at headroom 0 and outside this card's file surface, so the question is left for the seat. ## Verification Head `2e3dbd35ed`. `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 20 families, and all 20 ran locally, each with its exit captured before any pipe. `--ran` reconciliation: "20 derived famil(ies) accounted for — 20 run, 0 NOT-MEASURED (a DERIVED zero — all 20 recorded an exit code and none of them is 3)". <details><summary>Local gate exits</summary> Every family exited 0: `check-closing-keyword-parity` (and `--self-test`), `check-comment-mask-corpus`, `check-governed-queue-guard --self-test`, `check-harness-current --self-test`, `check:agent-test-spelling`, `check:cross-package-test-inputs`, `check:doc-authoring`, `check:driver-memory-census`, `check:gitlink-declared`, `check:nul-bytes`, `check:pm-governed-merges`, `check:pm-half-states`, `check:pm-skill-id-lint` ("110 file(s) clean"), `check:pm-skill-ratchet`, `check:refd-timer-probe`, `check:required-contexts`, `check:skill-frame-sync`, `check:watch-hint-literal`, and `check:doc-formula-expressions`. The last one ran after `@objectstack/formula` and `@objectstack/lint` were built under the shared verify lock ("VERDICT command-exit 0"). Roster families with a roster under `.claude` were also run: `check:pm-settings-deny-roster` exit 0, `check-skills-token-ratchet` exit 0, `check-published-list-mirrors` exit 0. </details> CI runs more families than the local subset. Read those from this PR's check-runs. <!-- signed: security#1 · os-justin · session_01QSeKYn5CmmdShCJifm6WYj --> --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 7193160 commit 04492ec

3 files changed

Lines changed: 23 additions & 23 deletions

File tree

‎.claude/skills/pm-dispatch/references/lanes/security.md‎

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,40 +13,40 @@
1313

1414
## 接收与台账
1515

16-
- 接收 = 发现者的一次 `Notify: security · GHSA-ID` 门铃,草稿公告已由其经中继建好。
16+
- 接收 ①:发现者的一次 `Notify: security · GHSA-ID` 门铃,草稿公告已由其经中继建好。
17+
- 接收 ②:无门铃的 `triage` 公告(外报或中继实测):经 `advisory_read` 读,座位贴记 `received`。
18+
- 判定:发现 ⇒ 中继 `advisory_state` 置 `draft` 走派修;非发现 ⇒ 置 `closed`,台账记非发现。
1719
- 中继拒或本席空缺照第 3、9 节。
18-
- 云席列不了本仓公告,中继也拒裸集合:编号只来自维护者或门铃。
20+
- 云席列不了本仓公告,中继也拒裸集合:编号只来自维护者、门铃或中继实测。
1921
- 读出的公告明文只印本席进程 stdout(`--reveal`),⛔ 不进文件、日志或后台任务输出。
2022
- 台账住座位贴,一份一行:不透明编号 · 会话 · 状态;⛔ 无细节;修复的认领只记台账。
2123
- 状态词表:`received` → `fixing` → `merged` → `closed`;挑中发布再 `awaiting publish` → `published`。
2224

2325
## 派修与复核
2426

25-
- 修复 = 本席向 `os-dev` 下无卡派发令,`xhigh`;机制只进派发令与公告,⛔ 不进 PR 与评论。
26-
- L/XL、build 重、长跑或浏览器验证的派修走 `mode:cloud`,余 `mode:subagent`(`../execution-duties.md`)。
27-
- 修复 PR 的契约复核归本席:记录停在规则层,机制只在本席本地的 `security-note.md`(第 6 节)。
28-
- 要定契约的修复交维护者(呈前照下节)。
27+
- 修复照第 3 节派发;L/XL、build 重、长跑或浏览器验证走 `mode:cloud`,余 `mode:subagent`。
28+
- 修复 PR 的契约复核归本席,照第 6 节;要定契约的修复交维护者前照下节。
2929

3030
## 呈维护者
3131

3232
- 任何问题呈维护者前,先由隔离 agent 以 `CONTRACT_REVIEW_TIER` 复核其分析;⛔ 不写模型名。
3333
- 复核者只拿分析与证据,⛔ 不拿本席结论;核四轴、选项无漏、推荐成立、证据为真。
3434
- 问题随附复核判词与全部异议。
3535
- 每次发版前呈发布与否清单:上次发版后 `closed` 的公告,高危、中危在前;先经上条复核。
36-
- 维护者批准清单后,本席经中继发布,照 `../security-findings.md` 第 3 节;⛔ 不发清单外的。
36+
- 修复在版本 X 内,只当其合并提交是 X 打标提交的祖先(`git merge-base --is-ancestor`)。
37+
- ⛔ 合并时刻早于打标时刻不是证据。
38+
- 维护者批准即 `awaiting publish`;本席经中继发布即 `published`,照第 3 节;⛔ 不发清单外的。
3739

3840
## 收口(逐对象)
3941

4042
- PR 由合并队列合入;本席确认 MERGED 后照 `../landing-operations.md` 收口其卡。
41-
- 卡:`Fixes #N` 合入即关,本席补落地记录并摘 `pm:*`;`Part of #N` 卡末段落地时本席自关。
4243
- 公告:修复合入即经中继 `advisory_state` 置 `closed` 并记座位贴,⛔ 不逐份请示。
4344
- 云卡:工作落地即由本席归档;子代理自行结束并删自己的 worktree。
4445

4546
## 误公开的卡(第 7 节)
4647

47-
- 本席接管:挂 `security` 标签,⛔ 不追加细节;是否移入公告并关卡交维护者定,⛔ 不代关。
48-
- 本席巡查自读 open 的 `security` 标签卡,标签即转交;分诊敲 `Notify: security · #N` 只为提速。
49-
- 分诊只即推维护者并转交本席(`triage.md`);本席空缺时分诊照第 7 节处置。
48+
- 本席照第 7 节接管;巡查自读 open 的 `security` 标签卡,标签即转交。
49+
- 分诊即推维护者并转交本席(`triage.md`);`Notify: security · #N` 只为提速;本席空缺照第 7 节。
5050

5151
## 收班
5252

‎.claude/skills/pm-dispatch/references/platform-readings.md‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373
- 从根在当前 `origin/main` 的那条起走父-tip 链即真实排队序;`ls-remote` 的字典序无意义。
7474
- 名形里的 `<PARENT>` 是推测基:实测晚十余分钟才落 `main` ⇒ ⛔ 不读作该基已落地。
7575
- 该读法零配额,答 timeline 答不了的排第几;⛔ 只读现在、不重建历史。
76-
- 队列踢出先认签名再决定重投:核对失败签名与已知 flaky 一致 ⇒ 原样重投。
76+
- 队列踢出先认签名:与已知 flaky(如 `Checkout repository` 超时)一致 ⇒ 原样重投,理由记 PR。
7777
- 止血修复合入后同一签名再现就不再是那条 flaky,是新问题须重新诊断,⛔ 禁反射式重投。
7878
- 第三种签名:本 PR 名下没有任何 `merge_group` run,且批次同伴的 run 全部 `success`。
7979
- 队列重建的连带取消不是红 ⇒ 带签名收据重投一次,收据留在 PR 上,⛔ 无收据不重投。
@@ -129,8 +129,7 @@
129129
- `performed_via_github_app`、`GET /user` 与 core 限流头对两类同答 ⇒ 三者都不是判别式。
130130
- 封号隐藏其全部评论、无 timeline 事件;assignee、PR、正文存活;分诊没了挂 `pm:retriage`。
131131
- ⇒ 耐久算按令牌类重算,⛔ 不假定署名恒 `claude[bot]`;用户类下请 PR 作者复审回 422。
132-
- GraphQL 池 5000/时,只留给没有 REST 对应物的几件。
133-
- 那几件 = `rest-channel.md`〈不可迁移〉那三件;draft 翻转与 auto-merge 挂载有中继 op、不在内。
132+
- GraphQL 池 5000/时只留给 `rest-channel.md`〈不可迁移〉三件;draft 翻转与挂载走中继 op。
134133
- 逐操作通道归属、写侧配方与队列路由三读法见 `rest-channel.md`,⛔ 不在本表复述。
135134
- MCP list/search 家族整个走 GraphQL 稀缺池,`issue_write` 连查找半边都吃。
136135
- 配额红时认领类动作排队,评论走 REST 桶先行把结论发出去。
@@ -140,13 +139,11 @@
140139
- 红窗调度:守候只给上面那几件 GraphQL-only 的,⛔ 其余一切不为配额空等。
141140
- 走队列的仓落地仍必经 auto-merge,红窗里照样走中继 op 挂载;直合仓合并本身有 REST 端点。
142141
- 被挡住的翻转是在等窗口,不是关于该 PR 的信号 ⇒ ⛔ 不据它重挂、不据它改判状态。
143-
- 报文里的 user ID 只是报文:据它推 MCP 池跨席共享与本节首条冲突,⛔ 未裁不写成事实。
144142
- `issue transfer` 因配额或权限拿不到 ⇒ 当轮改走多仓协调条款的在目的仓重建配方。
145143
- 该配方 = 出处头加裸 `#N` 改全名加关源单为 moved:纯 REST、配额免疫,⛔ 不为它空等重置。
146144
- 两个瘦身参数都不省池。`fields` 省载荷:MCP list/search 服务器端无条件抓 Project field_values。
147145
- ⇒ 池枯竭时最小字段请求同样全体失败,报错串是 failed to fetch issue field values。
148-
- ⛔ `minimal_output: true` 不裁 `list_issues` 的 `body`,⛔ 永不当省额度手段写进任何 skill。
149-
- 没有参数能关掉 `body`:要么整表 107 点,要么换窄接口(点数未测)。
146+
- `minimal_output` 不裁 `list_issues` 的 `body`,也无参数关得掉;⛔ 永不当省额度手段写进 skill。
150147
- 站得住的证据是直接观察 `body` 在,不是前后体积对比 —— 两次调用之间 population 已变。
151148
- git 先行:本地检出、`git log`、`ls-remote` 不花配额,断粮期分支存在性检查照常可用。
152149
- PR 文件读取同走 git:REST PR files 端点可瞬态 404。
@@ -287,8 +284,11 @@
287284
- 读数:带链接与管道的 `git push` 被拒,裸 `git push origin <分支>` 放行,拒绝文案不点名元素。
288285
- 判定跨天翻面 ⇒ ⛔ 一次拒绝不是能力边界;`permissions.allow` 条目才是仓库侧确定性通道。
289286
- `rerun_failed_jobs` 复用原 run 的提交与合并 ref,不拿新 main 重算。
290-
- ⇒ 基上缺已合修复时重跑无效,只能 `git merge origin/main` 推提交;判别看修复合并时间。
287+
- ⇒ 基上缺已合修复(修复合入晚于该 run 建立)时重跑无效,改 merge main。
291288
- 经 `rerun-failed.mjs` 重跑 PR `ci.yml` 失败 job 仅一次,先在 PR 或卡写明 flake 理由;二败即真红。
289+
- `run_rerun_failed` 只收 `ci.yml`;他 workflow 的 flake 走下两条,⛔ 永不空提交、永不关了重开。
290+
- `pr-automation.yml`(`Check Changeset` 取消无后继):席位改正文记下 flake 理由,其 `edited` 即重跑。
291+
- `lint.yml`(检出超时):`main` 前进后中继 `pr_update_branch` 出真新 head 整套重跑;齐平即空操作。
292292
- 同一 head 上轻量兄弟 workflow `success` 加重量级载体 `cancelled` 是普通取代的预期签名。
293293
- 同名 `failure` 也会被带另一诊断的后一次 `failure` 取代 ⇒ 任何判定前先按名取最新一次。
294294
- cancel-in-progress 窗口只罩得住慢载体 ⇒ 先比对 run `head_sha` 与 PR 当前 head,不开调查。

‎.claude/skills/pm-dispatch/references/review-checklist.md‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,15 @@
3939
- 判据是同块点名声明该符号的模块那份移动了的产物,或具名探针;缺则记 INCONCLUSIVE。
4040
- 报告证据里有 git 本可回答的 API 读吗:`list_issues`/`search_issues` 一类,或重跑去重读数。
4141
- ⛔ 不因此判 REWORK,ACCEPT 照给,但把这条记进 ACCEPT 评论。
42-
- 翻 ready、挂 auto-merge 或入队前,亲核 Lint & Repo Gates 与 TypeScript Type Check 两个 job。
43-
- 两个 job 的 `conclusion` 都须为 `success`,门禁族跑在其内;⛔ 不因报告写了本地绿跳过。
42+
- 翻 ready、挂 auto-merge 或入队前,亲核 Lint & Repo Gates 与 TypeScript Type Check 皆 `success`。
4443
- 两 job 只是 required 地板,入队另要求全 check 绿(第三种情形见 SKILL.md);跑法见 `true-green.md`。
4544
- 收敛期转红走补丁轮续派原 dev,⛔ 不作 REWORK 的理由;重量级卡可在派发令写本单等 CI。
46-
- 每个门禁读数先钉到 PR 当前 head:比对 run `head_sha` 与 `head.sha`,不一致的双向都不入账。
45+
- 门禁读数钉当前 head:run `head_sha` 或 dev 所抄短 sha 不符 `head.sha`、或没抄 ⇒ 双向不入账。
4746
- ⛔ 非当前 head 上的 `cancelled` 零动作、永不重跑:新推送自带全套 run。
48-
- 席位核对门禁证据 = 钉 head 的 check-runs(名+结论);本地并集只证本地子集,⛔ 不替缺席者。
49-
- dev 本地并集钉 head:所抄 `git rev-parse --short HEAD` 不符 PR `head.sha` 或没抄 ⇒ 双向都不入账。
47+
- 席位核对门禁证据 = check-runs(名+结论);本地并集只证本地子集,⛔ 不替缺席者。
5048
- `!` 或 `(narrowing)`:入队前核 `dogfood_battery` 钉 head、全量、红已修/已报;缺或收窄 ⇒ REWORK。
49+
- 把发送或写挪到应答之后的 PR:dogfood 门禁不跑于 PR 与队列,全绿照样红 `main` 的 push 全量。
50+
- ⇒ 入队前 grep `packages/qa/dogfood/test` 里应答后紧读该副作用的用例,同一 PR 改为有界等待。
5151

5252
## 断言与收益
5353

0 commit comments

Comments
 (0)