From 56d1ef524237365edf2c6c716791119b318f84ac Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 2 Sep 2026 13:54:25 +0000 Subject: [PATCH 1/4] =?UTF-8?q?docs(skills):=20spec-property-retirement=20?= =?UTF-8?q?=E2=80=94=20SPR-C-01/C-02/C-03/C-04/C-05/C-06/D-01/F-01=20+=20t?= =?UTF-8?q?hree=20dead=20references?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SPR-C-05 adds the fifth section-0 checkbox for the ledger's `live-elsewhere` verdict: dead here by measurement, genuinely enforced in a sibling repo, and therefore NEVER a removal candidate — what to check instead is its attestation discipline (foreign pointer, cross-repo scope, dated `verifiedAt`, 180-day expiry), verified at source against the ledger README and the gate that executes those four criteria. It is paid for by SPR-C-01 and SPR-C-04, so no ceiling is raised. SPR-C-01 deletes the dormant-gate trap (the job and its `paths` filter no longer exist). SPR-D-01 replaces four traps that duplicate AGENTS.md and the dev-agent definition with a pointer at those anchors. SPR-C-04 replaces the hand-rolled ten-name gate loop with the one wrapper command, and SPR-C-03 completes the pure-source-audit list from three names to all five. SPR-C-02 rewrites the strict-delete route onto the shared `strictObject()` guidance slot and its audit test. SPR-C-06 drops a rotting hand count in favour of the pin test that actually judges the corpus. SPR-F-01 adds the ADR-0087 disposition marker the changeset row omitted. Dead references corrected: the orphans script, the advisory-lint file's new package, and the consumed changeset sample. File: 337 -> 333 lines (ceiling 337); widest table row 328 -> 326 bytes (pin 328). Anchors untouched. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1 --- .../skills/spec-property-retirement/SKILL.md | 56 +++++++++---------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/.claude/skills/spec-property-retirement/SKILL.md b/.claude/skills/spec-property-retirement/SKILL.md index f4ffa125ce..c797e6146b 100644 --- a/.claude/skills/spec-property-retirement/SKILL.md +++ b/.claude/skills/spec-property-retirement/SKILL.md @@ -51,6 +51,12 @@ preview renderer 不算消费者)与 AGENTS.md §"Touched `packages/spec`?"(八 的键,就**吸收**它:把改名折进删除,删掉改名条目。二者复合后效果不可观测,而 conversion 表的 fixture 不相交契约(§3)会因叠放而失败。先例: `agent.knowledge` 在发布前吞掉了 `topics`→`sources` 改名。 +- [ ] **台账判它 `live-elsewhere` 吗?** 本仓实测无消费者、姊妹仓真在强制执行的 + 键 —— **永不是删除候选**。单读 `dead` 会批准一次删除,而它删掉的是姊妹仓某 + 道门的输入。该核的不是删除面,是它的佐证纪律:外仓指针、 + `evidenceScope: "cross-repo"`、带日期的 `verifiedAt`、180 天过期 —— 四条由 + `packages/spec/scripts/liveness/elsewhere.mts` 执行,出处见 README 的 + `live-elsewhere` 一节。 ## 1. 裁判是构建,不是台账 @@ -78,7 +84,7 @@ dead(「两个仓都没有 form 路径的读者」),而删除打断了 `gen:sche | Schema | 路线 | 机制 | |---|---|---| | **非 `.strict()`** | `retiredKey()` 墓碑 | `packages/spec/src/shared/retired-key.ts` 的 `retiredKey(guidance)` —— `z.never({ error: () => guidance }).optional()`。两个通道:`tsc`(输入类型 `never`)与 parse(处方本身,不是 "unrecognized key")。 | -| **`.strict()`** | 删键 + guidance map | 从 shape 里删除;向某个 `*_RETIRED_KEY_GUIDANCE` record 加条目,由传给 `z.object(shape, { error: … }).strict()` 的 `z.core.$ZodErrorMap` 消费。参考:`packages/spec/src/ai/tool.zod.ts:29-93,180`。object 顶层键另见 `object.zod.ts` 的 `UNKNOWN_KEY_GUIDANCE`。 | +| **`.strict()`** | 删键 + guidance map | 从 shape 里删除;向该 schema 的 `*_RETIRED_KEY_GUIDANCE` 加条目,由 `strictObject()` 的 `guidance:` 槽消费(`shared/strict-object.ts`;整族一条走 `guidanceSets`)。样板 `ai/tool.zod.ts`,审计 `shared/alias-integrity.test.ts`。⛔ 别再手写 `$ZodErrorMap`。 | | **没人 parse 它** | 都不用 | 没人能收到的处方是噪音。有意删掉 baseline 行并在 changeset 里写明 —— 先例 #3896 与 #4834(PR #4878),都在 kernel plugin-runtime 家族。家族删除后幸存的解释块在 `packages/spec/src/kernel/index.ts`(搜 `plugin-runtime.zod`)。 | 永不从非 strict schema 上裸删一个键:zod 会静默剥掉它,你只是用一个静默 no-op 换了 @@ -100,7 +106,7 @@ liveness 门禁走的是 **schema 的 shape**,逐个属性去 - 删掉**墓碑**键的行,报 **UNCLASSIFIED**(#3896 清扫一次 14 个 —— 本节就是防它); - 留着 **strict 删除**键的行,报 **ORPHAN** 行。 -orphan 这条腿是新的(`scripts/liveness/orphans.mts`)。它落地之前这个方向从不失败 +orphan 这条腿是新的(`packages/spec/scripts/liveness/orphans.mts`)。它落地之前这个方向从不失败 —— 门禁走 schema 再查行,键已离开 shape 的行根本不会被问到,原地腐烂。report 的 `aria`/`performance` 行就这样比它们的键多活了一整个 release,靠有人恰好读到那个文件 才手工删掉。你撞上 orphan 报错而属性确实还可编写时,要修的是 **walk**,不是行: @@ -142,7 +148,7 @@ ratchet(#2978)会先开火,要求你**有意删除**对应的 manifest key;删 ### guidance 字符串怎么写 -五条惯例,树上 ~28 个墓碑全部遵守: +五条惯例,树上每个墓碑都遵守 —— 逐点判定归下面那个 pin 测试,不归这段散文: 1. 反引号包着的**全限定**键打头 —— `` `flow.errorHandling.fallbackNodeId` ``,不是裸尾段。 2. `was removed in @objectstack/spec (#issue[, ADR-XXXX Dn])`。 @@ -258,7 +264,7 @@ conversion 是消费者跟的。两个都要写。 - [ ] **i18n bundle** —— 剪掉表单输入会改变抽取出的标签:`pnpm i18n:extract` 重新生 成 `packages/platform-objects/src/apps/translations/*.metadata-forms.generated.ts` (merge 模式;退役是纯删除)。由 `pnpm check:i18n` 把门。 -- [ ] **CLI advisory lint** —— `packages/cli/src/utils/lint-liveness-properties.ts` +- [ ] **CLI advisory lint** —— `packages/lint/src/lint-liveness-properties.ts` 是台账驱动的,退役键会自动停止告警;更新它的**测试**去断言 non-warn(「strict parse 现在接管它们」)。 - [ ] **Pin 测试** —— 一条阴性,断言处方本身 @@ -279,8 +285,9 @@ conversion 是消费者跟的。两个都要写。 - [ ] **Changeset** —— `@objectstack/spec` 用 `major`。AGENTS.md:breaking changeset 必须带 FROM → TO 映射与一行修复;它作为 npm 包里的 `CHANGELOG.md` 发出,是升级中的 agent 撞上墓碑报错后 grep 的东西。 - `.changeset/tool-inert-keys-removed.md` 是样板 —— 抄它的 "The retirement - kit:" 段。 + 样板是任一条活着的 `.changeset/*-retired.md` —— 抄它的 "The retirement + kit:" 段。⚠ 并带上 ADR-0087 处置标记(AGENTS.md 的 changeset 一节; + `pnpm check:adr-0087-registration` 把门)—— 退役正是它点名的那一类。 - [ ] **`check:generated` 明确不跑的源码审计 —— 整组跑,永不单点。** 它的输出会点名 它们;陷阱是跑了五个漏了第六个。咬退役的是 `check:variant-docs`:删掉一个 discriminated union 会孤儿化它的 variant/doc-ledger 条目,本地跳过则只在 CI @@ -300,38 +307,27 @@ conversion 与测试都改了 —— 但 release-notes 行与台账 README 行 ## 5. 把门禁跑到真能失败 ```bash -cd packages/spec && pnpm build # REQUIRED first — see the dist trap below -for c in check:liveness check:empty-state check:authorable-surface check:docs \ - check:api-surface check:spec-changes check:upgrade-guide \ - check:skill-refs check:skill-docs check:skill-examples; do - pnpm -s "$c" >/dev/null 2>&1; e=$? # capture BEFORE anything else runs - printf '%-28s %s\n' "$c" "$( [ $e -eq 0 ] && echo PASS || echo FAIL )" -done -cd ../.. && pnpm check:i18n && pnpm --filter @objectstack/spec test +pnpm --filter @objectstack/spec build # REQUIRED first — 见 §6 的 dist 陷阱 +pnpm --filter @objectstack/spec check:generated # 一条命令跑齐,首个失败不挡住其余 +pnpm check:i18n && pnpm --filter @objectstack/spec test ``` -`check:liveness`、`check:empty-state`、`check:skill-examples` 没有生成器 —— 那里的 -失败是真发现,不是过期产物。 +⛔ 永不手搓一份 `check:*` 名单逐个跑:手工配对是 AGENTS.md 明禁的,而一条命令一次 +报全部过期产物,正是 CI 做不到的事。`check:generated` 的输出会点名它**不**跑的五个 +纯源码审计 —— `check:liveness`、`check:empty-state`、`check:skill-examples`、 +`check:exported-any`、`check:dual-source-exports` —— 它们没有生成器,那里的失败是 +真发现、不是过期产物,按 §4 那一行整组另跑。 ## 6. 各费过一轮红构建的陷阱 -- **过期 `dist`(一条工作线上 5+ 次假警报)。** 包从 `dist` 加载。改了 `src` 之后本 - 地套件红,通常是 dist 旧了,不是你改坏了 —— `check:api-surface` 读 - `dist/*.d.ts`,会报幻影 "breaking removals"。相信任何本地红之前、去立「main 坏 - 了」的单之前,先 `pnpm turbo run build --filter=...`。 -- **`| tail -1` 吃掉退出码。** 门禁的管道接上 `tail`,报的是管道的状态,失败的门读 - 成绿。显式抓 `exit=$?`(上面的循环就是)。一次 liveness 失败曾藏在这后面。 +⚠️ 四个陷阱不写在这里,因为它们对每个 dev 都成立、锚点在别处:过期 `dist` 的假 +红、管道吃掉退出码、串行门禁互相遮蔽、`--check` 是门而裸模式重写。锚点是 AGENTS.md +的「Touched `packages/spec`?」一节与 `.claude/agents/os-dev.md` 的「本地验证范围」; +⛔ 这里不留第二份拷贝。 + - **截断的 grep 漏掉编写者。** `| head -8` 藏掉了 `SKILL.md` 的 `defineSkill` 示 例;`examples/` 有三处 `template: true`,不是一处。先按上下文找文件,再进文件里 grep 键 —— 且把 `tsc` 和门禁当权威清扫器。 -- **串行门禁互相遮蔽。** `Check Generated Artifacts` 与 `TypeScript Type Check` 各 - 自按序跑门、停在第一个失败。提前把全部重新生成;不要一次红构建迭代一个。 -- **绿 CI 可能是休眠的门。** `check-generated` 在 `ci.yml` 里跑在 `paths` 过滤器后 - 面;路径不在过滤器里,门恰好对打破它的那些 PR 沉默(过滤器整体携带 - `packages/spec/src/**` 就是这个原因)。你新增生成产物或某产物的新输入,同一个 PR - 里把路径加上。 - **只改 conversion 的 `summary` 也会过期。** 那个字符串被逐字抄进 `spec-changes.json` 的 `to` 字段与 upgrade guide 的表行,所以纯散文改动也要 `gen:spec-changes` + `gen:upgrade-guide`,和任何别的改动一样。 -- **`--check` 模式是门;裸模式重写。** `gen:*` 修文件,`check:*` 是同一脚本断言它已 - 提交。永不靠手改生成文件去「修」一个 `check:*` 失败。 From 242acd74ff9a68fe5a20ceb5f94922501c898b60 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 2 Sep 2026 13:56:14 +0000 Subject: [PATCH 2/4] =?UTF-8?q?docs(skills):=20dogfood-verification=20?= =?UTF-8?q?=E2=80=94=20DOG-C-01=20pointer,=20DOG-F-01,=20X-01=20anchor=20+?= =?UTF-8?q?=20stock-app-name=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DOG-C-01: the ablation predict-then-mutate rule was an 18-line second copy of the dev-agent definition's own rule — same criterion, same unaliased-import ledger, same two measured incidents — and both texts already said the rule is not dogfood's. It becomes a two-line pointer at that anchor. X-01 is decided by pointer: the platform-checklist runner doc is the environment anchor, and section 0 now says so and carries only what that anchor lacks. DOG-F-01 is exactly that case — the runner doc names dogfood section 0 by name as the origin of the `-p`-alone trap, while this file had no mention of the variable the self-pinging connectors actually read. Same section, same defect class, evidence pinned by the anchor: the stock-boot app-name list dropped an app that a stock boot does not load, so an empty `?id=` result there is correct rather than the missing-metadata false P0 the bullet exists to prevent. File: 157 -> 147 lines (ceiling 157). Anchors untouched. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1 --- .claude/skills/dogfood-verification/SKILL.md | 30 +++++++------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/.claude/skills/dogfood-verification/SKILL.md b/.claude/skills/dogfood-verification/SKILL.md index 7da79d57d6..d03c99ce28 100644 --- a/.claude/skills/dogfood-verification/SKILL.md +++ b/.claude/skills/dogfood-verification/SKILL.md @@ -28,10 +28,15 @@ metadata: dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行的 Claude/dogfood 会 话会抢走浏览器标签页、留下挡住导航的未保存草稿、弄脏工作树。开工前先隔离: +⚠️ 环境事实的锚点是 `docs/qa/platform-checklist/RUNNER.md` —— 本节只写它没有的那 +几条,⛔ 不留第二份拷贝。 + - [ ] **自有端口**:挑一个空闲的非默认端口(不要 3000/3001/3210)。先查: `lsof -nP -iTCP: -sTCP:LISTEN`。在 `.claude/launch.json` 加一条指向**本** 工作目录的具名配置,例如 `pnpm -C /examples/app-showcase exec objectstack dev --ui --seed-admin -p -d file:/tmp//data.db`。 +- [ ] **同时导出 `OS_PORT` —— 只给 `-p` 不够。** showcase 的自 ping 连接器读的是*环 + 境*(`SHOWCASE_SELF_URL`→`OS_PORT`→`PORT`→3000),于是 `fetch failed` 冒充出口被封。 - [ ] **自有数据**:`--seed-admin` 在空 DB 上给出 `admin@objectos.ai / admin123`。持 久化 `-d file:/tmp//data.db` 重启后仍在(适合多步配置的运行);`--fresh` 给全新首跑(退出即清)。 @@ -49,8 +54,9 @@ dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行 - [ ] Console UI 在 `/_console/`;应用在 `/_console/apps/`(如 `com.objectstack.setup`、`com.objectstack.studio`)。API 根 `/api/v1`,设置 `/api/settings`,合并后的应用/导航 `/api/v1/meta/app?id=`。 -- [ ] ⚠️ **`?id=` 键的是应用 `name`,不是包 id。** 真实 name 是 `showcase_app` / - `setup` / `studio` / `account` —— 不是上一行那种 `com.objectstack.setup` / +- [ ] ⚠️ **`?id=` 键的是应用 `name`,不是包 id。** stock boot 的 name 是 + `showcase_app` / `setup` / `account`(`studio` 不随 stock boot 装载,`?id=studio` + 理应为空 —— 详见 RUNNER)—— 不是上一行那种 `com.objectstack.setup` / `com.example.showcase`(那是包 id,只在 `/_console/apps/` 的路径段上成立)。传 包 id 得到的是 `{"items":[]}`,读起来和「应用元数据没了」一模一样 —— 最高价值 的假 P0 形状。**先不带 query 取一次 `/api/v1/meta/app`,读它真正返回的 name, @@ -63,24 +69,8 @@ dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行 watcher 只重编译示例应用自己的 `objectstack.config.ts` / `src`,不管工作区的包。 - [ ] 所以:先做完**全部**源码编辑 → `pnpm --filter build` → `preview_stop` + `preview_start`。不要每修一处就编辑→构建→重启一遍。 -- [ ] ⚠️ **消融验证(predict-then-mutate)以最危险的方式继承这一条,而且它不是 dogfood - 专属 —— mutate 腿与 restore 腿各自都要重建,并在报告里写明重建过。** 判据是解析 - 路径:任何主体经依赖的 `exports` 解析(→ 该包的 `dist/`,且没有 vitest alias - 把 specifier 拉回源码)的测试都中招,普通单元套件一样(这批 pair 的台账是 - `scripts/check-test-source-alias.mjs` 的 `KNOWN_UNALIASED_TEST_IMPORTS`)。忘记重 - 建*修复*是假红:费一圈,但会被发现。忘记重建**消融**跑的是突变前的构建,套件保持 - **绿**,而这份绿会被记成「测试已被证明有区分度」—— 给一条可能根本红不了的断言 - 发了 - 证书,之后任何 CI 都暴露不了它(CI 构建正确,在那边永远绿);消融本就为证明**新门 - 禁能失败**时更毒 —— 那份绿读作「门禁没触发」,指向门禁坏了而不是夹具坏了,会诱 - 人 - 去弱化一条本来正常的门禁(实测:plugin-auth → core;plugin-email → - platform-objects 则是消融后 375 试假绿、重建后 4 红)。每一腿(mutate **与** - restore)都是:改动 → `pnpm --filter build` → **证明它到达了 `dist/`** → 才 - 读运行结果:`node scripts/ablation-dist-preflight.mjs ''` 只在被消费 - 的 `dist/` 真带着该状态时才退 0(消融删除守卫、以及每个 restore 腿,用 - `--absent`)。⛔ restore 腿最常被跳过 —— 留在 `dist/` 里的 marker 会让突变代码对该 - 树之后的每次运行保持生效,后面的测量量的是错的树。 +- [ ] ⚠️ **消融的 mutate 腿与 restore 腿都要重建 —— 但那条规则不是 dogfood 专属**: + 判据、preflight 与两次实测住在 `.claude/agents/os-dev.md`;⛔ 这里不留第二份拷贝。 - [ ] `dist/` 已 gitignore —— 安全;永不提交构建产物。 - [ ] **`/_console` UI 是 *vendored objectui 构建*,与框架 `dist` 是两回事。** 它由 `.objectui-sha` 钉住、按预构建 bundle 提供。已合并的 objectui 修复 —— *甚至 From 25714042a116057b01083fc7d9890b06e847a630 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 2 Sep 2026 14:01:10 +0000 Subject: [PATCH 3/4] =?UTF-8?q?docs(skills):=20checklist-author=20?= =?UTF-8?q?=E2=80=94=20CLA-C-01=20rewrite=20to=20the=20clauses=20SWEEP=20l?= =?UTF-8?q?acks,=20CLA-C-02,=20README=20anchor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CLA-C-01: the orchestration section opened by declaring itself "not a second copy of the process" and then restated the sweep doc's six steps one for one, plus its angle table. It is rewritten to a pointer at that doc plus the three clauses measurably absent from it (measured, not assumed: zero hits there for worktree/PD#11, and zero for subagent/sequential): worktree-first, the orchestrator-exclusive write surfaces, and brief-is-a-hypothesis. CLA-C-02 travels with it: the stale waiver count ("four of six expired") was the oldest of three disagreeing numbers and its containing clause was one of the restated steps, so the number is gone rather than corrected in a second place. The surviving anchor states the measured truth, and the checklist gate itself reports `0 waived` today. The README citation moves off a term that no longer exists in that file and onto the section that does. X-02: this file keeps the sole copy of the no-subagent degradation clause — the "no other gaps" conclusion it protects is a sweep conclusion. File: 62 -> 53 lines (ceiling 62). Anchors untouched. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1 --- .claude/skills/checklist-author/SKILL.md | 33 +++++++++--------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/.claude/skills/checklist-author/SKILL.md b/.claude/skills/checklist-author/SKILL.md index 6648ca0925..e488841d6c 100644 --- a/.claude/skills/checklist-author/SKILL.md +++ b/.claude/skills/checklist-author/SKILL.md @@ -28,27 +28,18 @@ metadata: `node scripts/check-platform-checklist.mjs` 下校验为绿,并按 AGENTS.md (worktree-first,PD#11)落在任务分支上。 -## 编排契约 - -1. **Worktree 先行**(PD#11):`git fetch origin main && git worktree add --no-track ../objectstack- - -b origin/main`。全部编辑都在那里做。派发任何 agent 之前先读清单现状。 -2. **五个只读 gap hunter 并行** —— 每个 SWEEP.md 角度一个(console UI / spec 枚举 / - 路由与运行时 / 内置应用 / 文档声称)。每个拿到:当前 item-id 清单、已知的 waiver - 与 blocked 项(不重复上报),以及输出契约 `surface | evidence path | coverage - verdict | proposed id | sketch | fixture?`。hunter 不写任何文件。 -3. **去重并入一个草稿登记表**(落地前删掉)。跨角度的重复命中是高优先级信号,不是噪 - 音。 -4. **按区 writer agent** —— 每个 `areas/*.json` 文件一个 agent,writer 之间永不相 - 撞;除编排者外谁都不碰 `coverage.json` 与 `scripts/`。每个测试项都遵守 README.md - 的 deep-test 契约;缺 fixture 就记 `blocked`/`knownGaps`,永不伪造覆盖。writer - 断言之前把每个 endpoint、枚举、错误码都对到源码上 —— 把本技能的简报当假设,源码 - 才是真相。 -5. **集中对账**:hunter 证明有现成 fixture 的种类一律解除 waiver(2026-08 那轮 - sweep 里六条 waiver 有四条已过期 —— 每次都重审全部 waiver),新项映射进 - `coverage.json`,新的 variants 矩阵钉上 `enumSource`(见 README「Variants stay - fresh automatically」)。 -6. **校验 + 落地**:校验器绿,再提交到任务分支。产品缺陷与文档漂移进 - `FOLLOW-UPS.md`;安全敏感的发现,没有维护者的决定**永不**公开立单。 +## 编排契约 —— 只写 SWEEP 没有的 + +六步流程照 `SWEEP.md`「How to run it」执行,⛔ 这里不复述。它没有、而这一轮必须成 +立的三条: + +1. **Worktree 先行**(PD#11):`git fetch origin main && git worktree add --no-track + ../objectstack- -b origin/main`。全部编辑落在那里;派发任何 agent + 之前先读清单现状。 +2. **只有编排者碰 `coverage.json` 与 `scripts/`。** hunter 一个文件都不写,writer 一 + 个区文件一人 —— 这是并行 agent 之间唯一的串行化依据。 +3. **本技能的简报是假设,源码才是真相** —— 每个测试项按 README.md「Item anatomy」 + 的契约写;缺 fixture 记 `blocked`/`knownGaps`,永不伪造覆盖。 ## 规模指引 From 7df16bc7ada8900138a4e281eae8c086c2170103 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 2 Sep 2026 14:01:10 +0000 Subject: [PATCH 4/4] =?UTF-8?q?docs(skills):=20checklist-test=20=E2=80=94?= =?UTF-8?q?=20CLT-B-01,=20CLT-C-01,=20CLT-C-02/C-03=20pointers,=20X-02?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CLT-B-01 was unexecutable as written: the Tier-1 batching step told the runner to read `automated.ref` from the selector's `--json`, which projects only id, priority, surface, since and revision. The field is real but lives in the area file, so the step now says where to read it. CLT-C-01 replaces a memory-sourced blanket model tier with the rule the dispatch protocol actually binds — derive the tier from the current dispatch-gates output, never from recall. CLT-C-02/C-03 stop re-copying the runner doc's rules 1-2. C-03 becomes a pointer. C-02 keeps the disclosure guardrail in place (the runner doc states in its own text that this is one rule deliberately written in both places, so deleting this copy would falsify an anchor I must not edit) but drops the elaboration and, with it, the precedence claim that same anchor explicitly denies. X-02: the no-subagent degradation clause now points at its single home in the sibling skill instead of restating it near-verbatim. File: 238 -> 234 lines (ceiling 238). Anchors untouched. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1 --- .claude/skills/checklist-test/SKILL.md | 32 +++++++++++--------------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/.claude/skills/checklist-test/SKILL.md b/.claude/skills/checklist-test/SKILL.md index 4f3d33d32e..af42edace8 100644 --- a/.claude/skills/checklist-test/SKILL.md +++ b/.claude/skills/checklist-test/SKILL.md @@ -75,8 +75,9 @@ node scripts/checklist-select.mjs --json 区没跑。**默认复用**已配好的树;每轮开一个冷容器,只在这一轮必须**活得比派发会话 久**时才值(长时间浏览器运行、dogfood)。 -**按 tier 排序,钉住的先跑、按区批量。** 解析器给出的 `automated.ref` 是最便宜的切 -分: +**按 tier 排序,钉住的先跑、按区批量。** 最便宜的切分是 `automated.ref` —— 但 +`--json` **不投影它**(它只给 id · priority · surface · since · revision),按 id 到 +区文件 `areas/.json` 里读: - **Tier 1 —— 带 `automated.ref` 的项**:**按区批量**,一次 vitest 覆盖该区全部钉住 的文件,一条命令为多项取证(RUNNER 规则 6:不重证自动化已钉住的东西)。 @@ -93,16 +94,14 @@ Tier 1 批量清掉,剩下的预算才对得起 Tier 2。 `shared-browser-tab` 陷阱。 - **并行度**:API 面测试项放开并行扇出(各自端口,便宜)。浏览器项**少量并行** (2–3 个),各自端口 + 浏览器上下文 —— 超过这个数,单机 CPU 与共享显示开始互相争 - 抢。派发 runner 子代理时,**必须用 `opus`**,每个给:该项 JSON、RUNNER.md、 - dogfood 技能、自己的端口/DB、结果不进仓规则(§4)。 -- **没有子代理工具时,顺序跑 —— 并在运行记录里声明这一轮是顺序执行的。** 会话里不 - 存在 Task/子代理工具是允许的退化路径,不是阻塞。但并行的全部价值在于**读者彼此独 - 立**:悄无声息地塌缩成一个读者,findings 依然成立,**「没有别的遗漏」这个结论不再 - 成立**,而输出上看不出任何区别 —— 所以声明是强制的,不靠自觉。 -- 忠实执行每项的 `steps`;对照各自声明的 `oracle` 判定每条 `acceptance` 与每条 - `negative`,采集条款点名的 `evidence`。**服务端真相压过像素;截图确认渲染之后才查 - DOM;一个 `fail` 需要 ×2 复现 + 自动化自查 + 运行 issue 里的复现规则** - (RUNNER §rules)。 + 抢。派发 runner 子代理时,档位引当次 + `node scripts/pm/dispatch-gates.mjs --tier ` 的输出、⛔ 不凭记忆(floor + sonnet · default opus · ceiling fable);每个给:该项 JSON、RUNNER.md、dogfood 技 + 能、自己的端口/DB、结果不进仓规则(§4)。 +- **没有子代理工具时,顺序跑 —— 并在运行记录里声明这一轮是顺序执行的。** 规则与它 + 的论证住在 `checklist-author` 技能(维护者所定,一处成文);⛔ 不留第二份拷贝。 +- 忠实执行每项的 `steps`,按各自声明的 `oracle` 判定每条 `acceptance` 与 `negative` + 并采证 —— oracle 层级、证据要求与防误报自查是 RUNNER 规则 1–2,⛔ 这里不复述。 ## 3. 当这一轮教你的是关于测试项本身的东西 @@ -227,12 +226,9 @@ QA-source: #运行记录号 · area.item · 条款 或记 `blocked(environment)`;证到一半的项是 `partial`,不是 `pass`。带证据的 blocked 判定是一次成功运行;伪造的 pass 不是。 - **认证 / 授权漏洞的复现,永不发布到 GitHub 的任何地方** —— 不进运行 issue,不进跟 - 踪卡,不进评论。**本条压过 §4 的「每个 `fail` 一条复现规则」与 RUNNER 规则 2 的同 - 款要求**:记下项 id、条款,以及 `detail withheld pending maintainer`;复现留在会话 - 里,停下等维护者。「换个公开的地方贴」不是缓解 —— 跟踪卡同样是公开仓库里的公开 - issue,一次照办就把一个未认证读写洞的可用配方发布了出去。存在性公开、配方不公开的 - 发现,依然是一份完整、可行动的报告;让缺陷得到修复,从不需要把可用的 exploit 交到 - 任何人手上。 + 踪卡,不进评论。记下项 id、条款与 `detail withheld pending maintainer`,复现留在会 + 话里,停下等维护者。⚠ 这与 RUNNER 规则 2 是**同一条规则写在两处**,⛔ 两边都不是 + 对另一边的优先级主张;完整论证与它的维护者裁定在 RUNNER。 - **不把 blocked 项当可运行的跑** —— 解析器隐藏它们正为此。 - **一个选择器、一次运行、一张 issue。** release sweep 把 `since:vN` 与 `priority:P0` 作为分开的两轮跑 → 两张 issue,不要糊在一起。