Repository navigation
Commit af515db
docs(checklist-test): a QA security finding gets no card and goes privately to the PM session, runners only test, and runner dispatches state effort by card shape (#27642)
<!-- claude-projects-attribution: {"github_login":"os-elon-musk"} -->
_Requested by **Elon** · [project
thread](https://claude.ai/code/project/chan_01WedDzV26nniwxv7jC88B9D?thread=cmsg_01WedDzV26nniwxv7jC88B9DCvt1Z3RM8RYroegHc3zfLi)_
Fixes #27382
Fixes #27390
Clause-②: no
Metadata-protocol: none
## 维护者速读
- 改了什么:测试中遇到的安全问题不再立任何 GitHub 卡,复现经会话间消息私下报给派发会话,由它派修复并持有 PR;runner
只测试;runner 派发按卡定 effort(跑测 `high`,修安全与对抗复核 `xhigh`),并记花费。
- 为什么改:你 10-29 的几句话(汇总在 #27377 评论 6500750765);只写 detail withheld
的卡仍在公开仓里预告某项有洞;第三波 runner 没人定 effort,一张卡半小时花了 $33。
- 风险与回滚:只改规则文本(RUNNER 规则 2、checklist-test 技能、os-dev
两行、行数棘轮上限),不动产品代码;回滚即 revert。
- 先看:`docs/qa/platform-checklist/RUNNER.md` 规则 2
的两条子项;`.claude/skills/checklist-test/SKILL.md` 的 Guardrails 与 §2。
- 两分钟验证:`pnpm check:pm-skill-ratchet && node
scripts/check-platform-checklist.mjs`,两者 exit 0。
- 需要你做的:无,席位落地(Tier S,欠一次契约档复审)。
## What changes
One rule, written in both places —
`docs/qa/platform-checklist/RUNNER.md` rule 2 and
`.claude/skills/checklist-test/SKILL.md` — and neither text claims
precedence over the other.
**Security findings (#27382).** A security finding is an authentication
or authorization hole, or any finding whose reproduction is an exploit
recipe.
- It gets **no GitHub card at all**. That includes the withheld-detail
card, and it is not mentioned on the wave anchor or a tracking card
either. Its reproduction appears nowhere on GitHub.
- The run record keeps one row, `area.item · clause · security finding —
detail withheld, reported to PM`. That row is a completed verdict, and
the title counts it as a `FAIL`.
- The runner reports the reproduction privately to the session that
dispatched it, by session-to-session message.
- That PM session dispatches the fix through pm-dispatch: an in-seat
`os-dev` subagent at `xhigh`, with the reproduction only in the dispatch
prompt and hardening-only wording in the PR, commit and changeset. A
finding that needs a contract decision first goes to the maintainer.
**Runners only test (#27382, widened to issues and PRs).**
- Every GitHub write and every issue or PR handling step of a run
(extraction, dedupe, close-out) goes through the pm-dispatch write
doors.
- A runner never spawns `os-dev` and never drives a PR. The dispatching
PM session owns every PR the run produces: review, contract review where
it is owed, readiness and landing.
- When a runner's own permission check refuses a write door, it stages
the writes in a file, reports the path and hands off. The dispatching
session reads them and posts them through the same doors in the staged
order. A staged file never carries a security reproduction.
**Runner effort (#27390), skill §2 only.**
- Effort by card shape, stated in every runner dispatch, never empty. A
run card (Tier 1 pin batch, manual API/CLI or browser set, P0 smoke, UX
walkthrough) is `high`. `xhigh` is only for the `os-dev` that fixes a
security finding and for adversarial re-verification of a contested
verdict.
- Per backend:
- An `Agent` subagent gets `effort` passed explicitly, and the skill
line is what makes passing it lawful.
- A cloud card (`create_session`) takes no effort. Its record carries no
effort field either (measured, below), so the dispatch note says "not
set" plus the dispatching session's own level. When that level is above
the card's shape, the dispatcher follows the dispatch-runbook's 〈云卡五课〉
item 五 ② line, which the skill cites rather than restates, or opens a
project thread instead and sets its effort at spawn.
- The spend line: the wave anchor's dispatch note and each runner's
final report carry each card's spend at report time, read from
`get_session` `external_metadata.usage.cost_usd`.
**Files.**
- `docs/qa/platform-checklist/RUNNER.md`: rule 2's carve-out is
rewritten, and a new sub-bullet, "The runner only tests", is added. Two
later mentions of the retired card shape now match it: the *Run records*
paragraph and the *Extraction obligation* bullet.
- `.claude/skills/checklist-test/SKILL.md`:
- Guardrails: the security bullet is rewritten, and a "runner 只测试"
bullet is added.
- §4: the extraction line is rewritten, and the write-door paragraph now
covers issue and PR handling and the refused door.
- §2: three bullets cover effort, backends and spend, and the QA-run
line names PR ownership.
- `.claude/agents/os-dev.md`: two existing lines now carry the no-card
dispatch. The dispatch prompt stands in for the card, there is no `Fixes
#`, and the report is the final message only. No line is added (402
lines, ceiling 402).
- `scripts/pm/check-skill-line-ratchet.mjs`: the
`checklist-test/SKILL.md` ceiling goes from 246 to 259.
## Why
The maintainer's words on 2026-10-29 in the dispatching session,
verbatim and untranslated, all collected on #27377 in **comment
6500750765** (the ruling of record):
- 「你应该使用 pm-dispatch 技能处理 issue」
- 「对于测试中遇到的安全问题,不适合提交issue 的,只是使用pm-dispatch技能派发」
- 「这些都应该写到 checklist skills 中」
- widening (#27382, 6493929972): 「每个会话我都交代了:你应该使用 pm-dispatch 技能处理 issue
和 pr」
- scope change (#27382, 6493958591), which replaces "the runner
dispatches the fix": 「但是我建议开发任务是不是应该由你同意派,云agent
只负责测试,能做到吗?安全问题他可以私下报告给你吗」
- #27390: 「你派的任务都需要 extra 吗」, then 「立卡更新 skills」
**pm-skill line ratchet raise.** Ruling of record: #27377 comment
**6500750765**. Measured line delta: **+13**,
`.claude/skills/checklist-test/SKILL.md` 246 → 259. The `CEILINGS` row
moves by exactly that amount. No other ceiling moves, and `os-dev.md`
stays at 402.
## Measured before writing (#27390 item 2)
All readings were taken with `get_session` on 2026-10-29, between 15:20Z
and 15:30Z.
| session | kind | `session_context.effort_level` |
|---|---|---|
| project coordinator `session_016WV4cyMsvviaf7j5XzQrfC` | parent of the
two threads below | `low` |
| this card thread `session_016WV4cxs6a1nUyBHTEo84qV` | project thread,
spawned by the coordinator | `xhigh` |
| sibling card thread `session_016WV4d1oYpq8eEjYF141fC3` | project
thread, spawned in the same minute | `xhigh` |
| devx seat thread `session_01LKHDniRQSWjRJyDtacwpEd` | project thread |
`high` |
| spec seat 1 `session_01HjR8RUwTPQ3TgbfKihmxp9` | dispatching seat
(web) | `xhigh` |
| its card `session_01GDoMKJFY45jdSGzFmyumij` (origin
`claude_code_mcp_seed`) | `create_session` cloud card | **field absent**
|
| services seat 2 `session_018VqJPGA1NDNSCZsnecsChP` | dispatching seat
(web) | `xhigh` |
| its card `session_013JuCowY7RrGXYbGEv3cWsQ` (origin
`claude_code_mcp_seed`) | `create_session` cloud card | **field absent**
|
What this shows:
- A project thread runs at the level it was given at spawn, not at its
parent's.
- A `create_session` card's record carries no effort level at all, so
nobody can read back the level it ran at. That is why the skill tells
the dispatcher to record "not set" and the dispatching session's level,
and does not claim an inherited level.
- `usage.cost_usd` sits at `external_metadata.usage.cost_usd`, and a
session with no finished turn has no `usage` block yet (this thread's
own record at 15:18Z).
## Verification
All at head `6b95c870`, on a fresh worktree off `main` at `9c513147`.
- `pnpm check:pm-skill-ratchet` (self-test and gate): exit 0.
`checklist-test/SKILL.md` is 259 lines against a ceiling of 259, every
line is within 120 bytes, and the table-row pin is unchanged.
`os-dev.md` is 402 against 402.
- `node scripts/check-platform-checklist.mjs`: exit 0. That is 16 areas
and 352 items.
- `pnpm check:pm-skill-id-lint`: exit 0, with no issue number in
`os-dev.md`.
- `node scripts/check-commit-card-trailers.mjs --range
origin/main..HEAD`: exit 0.
- `pnpm exec eslint scripts/pm/check-skill-line-ratchet.mjs`: exit 0.
- `node scripts/pm/dispatch-gates.mjs --ran` accounts for all 43 derived
families: 43 run, 0 unrun, every one exit 0.
- `check:doc-formula-expressions` first exited 3 (its prerequisite was
not met). It passed after `pnpm --filter '@objectstack/lint...' build`.
- Changed lines: 112 (+71 / −41), under the 3000 human-merge threshold.
<details><summary>The 43 derived families and their exit codes</summary>
```text
node scripts/check-adr-links.mjs :: exit 0
node scripts/check-adr-links.mjs --self-test :: exit 0
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/check-declaration-mirrors.mjs :: exit 0
node scripts/check-declaration-mirrors.mjs --self-test :: exit 0
node scripts/check-self-test-wired.mjs :: exit 0
node scripts/check-self-test-wired.mjs --self-test :: exit 0
node scripts/check-self-test-workflow-commands.mjs :: exit 0
node scripts/check-self-test-workflow-commands.mjs --self-test :: exit 0
node scripts/check-whole-set-label-write.mjs :: exit 0
node scripts/check-whole-set-label-write.mjs --self-test :: exit 0
node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0
node scripts/pm/bare-root-worklist.mjs --self-test :: exit 0
node scripts/pm/check-governed-queue-guard.mjs --self-test :: exit 0
node scripts/pm/check-harness-current.mjs --self-test :: exit 0
pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0 (after the lint closure build; first run exit 3)
pnpm check:agent-model-declared :: exit 0
pnpm check:agent-test-spelling :: exit 0
pnpm check:bash32-floor :: exit 0
pnpm check:ci-filter-parity :: exit 0
pnpm check:cli-command-ids :: exit 0
pnpm check:commit-card-trailers :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:doc-authoring :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:entry-guard :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:parse-guard :: exit 0
pnpm check:platform-checklist :: exit 0
pnpm check:pm-dispatch-gates :: exit 0
pnpm check:pm-governed-merges :: exit 0
pnpm check:pm-skill-id-lint :: exit 0
pnpm check:pm-skill-ratchet :: exit 0
pnpm check:pnpm-filter-targets :: exit 0
pnpm check:pnpm-flag-spellings :: exit 0
pnpm check:ratchet-remedy-authority :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:scripts-symbol-anchors :: exit 0
pnpm check:skill-frame-sync :: exit 0
pnpm check:watch-hint-literal :: exit 0
```
</details>
## Acceptance notes
- **The file surface is widened by two RUNNER.md mentions outside rule
2.** The *Run records* paragraph and the *Extraction obligation* bullet
repeated the retired withheld-card shape, so left alone they would have
contradicted rule 2. They are in the same file, and `docs/qa/**` is not
governed. Declared to the seat.
- **Three checklist item strings still quote the retired `detail
withheld pending maintainer` wording**, as pointers to rule 2's
carve-out: one in `areas/access-security.json` and two in
`areas/identity-auth.json`. They defer to rule 2, which governs.
Rewording them is an item revision (a `revision` bump and a `history`
row), which is outside this card's surface. Left for the seat: either a
follow-up or noted only.
- **pm-dispatch `dispatch-runbook.md` 〈云卡五课〉 item 五 ② says a session
that cannot take effort inherits the seat's level.** The readings above
cannot confirm that for `create_session` cards, because their record has
no effort field. The runbook is not edited here (pm-dispatch is outside
this surface). The skill cites the line and records what can be read.
- **Tier.** Touching `.claude/agents/os-dev.md` makes `dispatch-gates
--tier` derive a MANDATORY contract-review tier for the surface. The
two-line amendment there is one-line-class and mechanical. The build ran
at the default tier, and the contract-tier review the seat arranges is
the compensating control.
- **No PR assignee.** `os-dev.md` says a PR carries none, and the
maintainer reaches the PR through the seat's hand-off.
## Human Minimum
- [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic.
(`packages/spec` is not touched.)
- [x] 2. Every name I added uses the casing for its kind.
- [x] 3. No formatter ran; `pnpm lint` passes. (eslint on the one `.mjs`
file changed: exit 0.)
- [ ] 4. One issue, one branch off an up-to-date `main`, one pull
request. (Two cards folded into one PR by the seat's dispatch order; one
branch off `main` at `9c513147`.)
- [x] 5. A change that publishes carries a changeset, and both
declaration lines are filled in here and in the changeset. (Nothing
publishes: `skip-changeset`. Both declaration lines are above.)
- [x] 6. `packages/spec` touched: its generated artifacts are
regenerated and committed. (Not touched.)
- [x] 7. No hand edits to `content/docs/references/`,
`packages/*/CHANGELOG.md` or `content/docs/releases/`.
- [x] 8. Title, body and comments are in English. (The 维护者速读 block and
the quoted rulings are Chinese, as the repo's rules require.)
- [x] The *Before Submitting* list in CONTRIBUTING.md is done.
---
_Generated by [Claude
Code](https://claude.ai/code/session_016WV4cxs6a1nUyBHTEo84qV)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 9e73c08 commit af515db
6 files changed
Lines changed: 107 additions & 55 deletions
File tree
- .claude
- agents
- skills/checklist-test
- docs/qa/platform-checklist
- areas
- scripts/pm
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
| 4 | + | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
| 7 | + | |
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
15 | | - | |
16 | | - | |
| 15 | + | |
| 16 | + | |
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| |||
359 | 359 | | |
360 | 360 | | |
361 | 361 | | |
362 | | - | |
| 362 | + | |
363 | 363 | | |
364 | | - | |
| 364 | + | |
365 | 365 | | |
366 | 366 | | |
367 | 367 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
102 | 102 | | |
103 | 103 | | |
104 | 104 | | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
105 | 113 | | |
106 | | - | |
| 114 | + | |
107 | 115 | | |
108 | 116 | | |
109 | 117 | | |
| |||
126 | 134 | | |
127 | 135 | | |
128 | 136 | | |
129 | | - | |
130 | | - | |
131 | | - | |
132 | | - | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
133 | 142 | | |
134 | 143 | | |
135 | 144 | | |
| |||
149 | 158 | | |
150 | 159 | | |
151 | 160 | | |
152 | | - | |
| 161 | + | |
153 | 162 | | |
154 | 163 | | |
155 | 164 | | |
| |||
175 | 184 | | |
176 | 185 | | |
177 | 186 | | |
178 | | - | |
179 | | - | |
180 | | - | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
181 | 190 | | |
182 | 191 | | |
183 | 192 | | |
| |||
235 | 244 | | |
236 | 245 | | |
237 | 246 | | |
238 | | - | |
239 | | - | |
240 | | - | |
241 | | - | |
242 | | - | |
243 | | - | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
244 | 257 | | |
245 | 258 | | |
246 | 259 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
78 | 78 | | |
79 | 79 | | |
80 | 80 | | |
81 | | - | |
82 | | - | |
83 | | - | |
84 | | - | |
85 | | - | |
86 | | - | |
87 | | - | |
88 | | - | |
89 | | - | |
90 | | - | |
91 | | - | |
92 | | - | |
93 | | - | |
94 | | - | |
95 | | - | |
96 | | - | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
97 | 113 | | |
98 | 114 | | |
99 | 115 | | |
| |||
763 | 779 | | |
764 | 780 | | |
765 | 781 | | |
766 | | - | |
767 | | - | |
768 | | - | |
769 | | - | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
770 | 787 | | |
771 | 788 | | |
772 | 789 | | |
| |||
860 | 877 | | |
861 | 878 | | |
862 | 879 | | |
863 | | - | |
864 | | - | |
865 | | - | |
866 | | - | |
867 | | - | |
868 | | - | |
| 880 | + | |
| 881 | + | |
| 882 | + | |
| 883 | + | |
| 884 | + | |
869 | 885 | | |
870 | 886 | | |
871 | 887 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3051 | 3051 | | |
3052 | 3052 | | |
3053 | 3053 | | |
3054 | | - | |
| 3054 | + | |
3055 | 3055 | | |
3056 | 3056 | | |
3057 | 3057 | | |
| |||
3115 | 3115 | | |
3116 | 3116 | | |
3117 | 3117 | | |
3118 | | - | |
| 3118 | + | |
3119 | 3119 | | |
3120 | 3120 | | |
3121 | 3121 | | |
| |||
3215 | 3215 | | |
3216 | 3216 | | |
3217 | 3217 | | |
| 3218 | + | |
| 3219 | + | |
| 3220 | + | |
| 3221 | + | |
| 3222 | + | |
| 3223 | + | |
3218 | 3224 | | |
3219 | 3225 | | |
3220 | 3226 | | |
| |||
0 commit comments