Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 12 additions & 21 deletions .claude/skills/checklist-author/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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-<task>
-b <branch> 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-<task> -b <branch> origin/main`。全部编辑落在那里;派发任何 agent
之前先读清单现状。
2. **只有编排者碰 `coverage.json` 与 `scripts/`。** hunter 一个文件都不写,writer 一
个区文件一人 —— 这是并行 agent 之间唯一的串行化依据。
3. **本技能的简报是假设,源码才是真相** —— 每个测试项按 README.md「Item anatomy」
的契约写;缺 fixture 记 `blocked`/`knownGaps`,永不伪造覆盖。

## 规模指引

Expand Down
32 changes: 14 additions & 18 deletions .claude/skills/checklist-test/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -75,8 +75,9 @@ node scripts/checklist-select.mjs <selector> --json
区没跑。**默认复用**已配好的树;每轮开一个冷容器,只在这一轮必须**活得比派发会话
久**时才值(长时间浏览器运行、dogfood)。

**按 tier 排序,钉住的先跑、按区批量。** 解析器给出的 `automated.ref` 是最便宜的切
分:
**按 tier 排序,钉住的先跑、按区批量。** 最便宜的切分是 `automated.ref` —— 但
`--json` **不投影它**(它只给 id · priority · surface · since · revision),按 id 到
区文件 `areas/<area>.json` 里读:

- **Tier 1 —— 带 `automated.ref` 的项**:**按区批量**,一次 vitest 覆盖该区全部钉住
的文件,一条命令为多项取证(RUNNER 规则 6:不重证自动化已钉住的东西)。
Expand All@@ -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 <paths>` 的输出、⛔ 不凭记忆(floor
sonnet · default opus · ceiling fable);每个给:该项 JSON、RUNNER.md、dogfood 技
能、自己的端口/DB、结果不进仓规则(§4)。
- **没有子代理工具时,顺序跑 —— 并在运行记录里声明这一轮是顺序执行的。** 规则与它
的论证住在 `checklist-author` 技能(维护者所定,一处成文);⛔ 不留第二份拷贝。
- 忠实执行每项的 `steps`,按各自声明的 `oracle` 判定每条 `acceptance` 与 `negative`
并采证 —— oracle 层级、证据要求与防误报自查是 RUNNER 规则 1–2,⛔ 这里不复述。

## 3. 当这一轮教你的是关于测试项本身的东西

Expand DownExpand Up@@ -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,不要糊在一起。
30 changes: 10 additions & 20 deletions .claude/skills/dogfood-verification/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,10 +28,15 @@ metadata:
dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行的 Claude/dogfood 会
话会抢走浏览器标签页、留下挡住导航的未保存草稿、弄脏工作树。开工前先隔离:

⚠️ 环境事实的锚点是 `docs/qa/platform-checklist/RUNNER.md` —— 本节只写它没有的那
几条,⛔ 不留第二份拷贝。

- [ ] **自有端口**:挑一个空闲的非默认端口(不要 3000/3001/3210)。先查:
`lsof -nP -iTCP:<port> -sTCP:LISTEN`。在 `.claude/launch.json` 加一条指向**本**
工作目录的具名配置,例如
`pnpm -C <abs>/examples/app-showcase exec objectstack dev --ui --seed-admin -p <port> -d file:/tmp/<run>/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/<run>/data.db` 重启后仍在(适合多步配置的运行);`--fresh`
给全新首跑(退出即清)。
Expand All@@ -49,8 +54,9 @@ dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行
- [ ] Console UI 在 `/_console/`;应用在 `/_console/apps/<appId>`(如
`com.objectstack.setup`、`com.objectstack.studio`)。API 根 `/api/v1`,设置
`/api/settings`,合并后的应用/导航 `/api/v1/meta/app?id=<appName>`。
- [ ] ⚠️ **`?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,
Expand All@@ -63,24 +69,8 @@ dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行
watcher 只重编译示例应用自己的 `objectstack.config.ts` / `src`,不管工作区的包。
- [ ] 所以:先做完**全部**源码编辑 → `pnpm --filter <pkg...> 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 <pkg> build` → **证明它到达了 `dist/`** → 才
读运行结果:`node scripts/ablation-dist-preflight.mjs <pkg> '<marker>'` 只在被消费
的 `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 修复 —— *甚至
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 12 additions & 21 deletions .claude/skills/checklist-author/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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-<task>
-b <branch> 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-<task> -b <branch> origin/main`。全部编辑落在那里;派发任何 agent
之前先读清单现状。
2. **只有编排者碰 `coverage.json` 与 `scripts/`。** hunter 一个文件都不写,writer 一
个区文件一人 —— 这是并行 agent 之间唯一的串行化依据。
3. **本技能的简报是假设,源码才是真相** —— 每个测试项按 README.md「Item anatomy」
的契约写;缺 fixture 记 `blocked`/`knownGaps`,永不伪造覆盖。

## 规模指引

Expand Down
32 changes: 14 additions & 18 deletions .claude/skills/checklist-test/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -75,8 +75,9 @@ node scripts/checklist-select.mjs <selector> --json
区没跑。**默认复用**已配好的树;每轮开一个冷容器,只在这一轮必须**活得比派发会话
久**时才值(长时间浏览器运行、dogfood)。

**按 tier 排序,钉住的先跑、按区批量。** 解析器给出的 `automated.ref` 是最便宜的切
分:
**按 tier 排序,钉住的先跑、按区批量。** 最便宜的切分是 `automated.ref` —— 但
`--json` **不投影它**(它只给 id · priority · surface · since · revision),按 id 到
区文件 `areas/<area>.json` 里读:

- **Tier 1 —— 带 `automated.ref` 的项**:**按区批量**,一次 vitest 覆盖该区全部钉住
的文件,一条命令为多项取证(RUNNER 规则 6:不重证自动化已钉住的东西)。
Expand All@@ -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 <paths>` 的输出、⛔ 不凭记忆(floor
sonnet · default opus · ceiling fable);每个给:该项 JSON、RUNNER.md、dogfood 技
能、自己的端口/DB、结果不进仓规则(§4)。
- **没有子代理工具时,顺序跑 —— 并在运行记录里声明这一轮是顺序执行的。** 规则与它
的论证住在 `checklist-author` 技能(维护者所定,一处成文);⛔ 不留第二份拷贝。
- 忠实执行每项的 `steps`,按各自声明的 `oracle` 判定每条 `acceptance` 与 `negative`
并采证 —— oracle 层级、证据要求与防误报自查是 RUNNER 规则 1–2,⛔ 这里不复述。

## 3. 当这一轮教你的是关于测试项本身的东西

Expand DownExpand Up@@ -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,不要糊在一起。
30 changes: 10 additions & 20 deletions .claude/skills/dogfood-verification/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,10 +28,15 @@ metadata:
dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行的 Claude/dogfood 会
话会抢走浏览器标签页、留下挡住导航的未保存草稿、弄脏工作树。开工前先隔离:

⚠️ 环境事实的锚点是 `docs/qa/platform-checklist/RUNNER.md` —— 本节只写它没有的那
几条,⛔ 不留第二份拷贝。

- [ ] **自有端口**:挑一个空闲的非默认端口(不要 3000/3001/3210)。先查:
`lsof -nP -iTCP:<port> -sTCP:LISTEN`。在 `.claude/launch.json` 加一条指向**本**
工作目录的具名配置,例如
`pnpm -C <abs>/examples/app-showcase exec objectstack dev --ui --seed-admin -p <port> -d file:/tmp/<run>/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/<run>/data.db` 重启后仍在(适合多步配置的运行);`--fresh`
给全新首跑(退出即清)。
Expand All@@ -49,8 +54,9 @@ dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行
- [ ] Console UI 在 `/_console/`;应用在 `/_console/apps/<appId>`(如
`com.objectstack.setup`、`com.objectstack.studio`)。API 根 `/api/v1`,设置
`/api/settings`,合并后的应用/导航 `/api/v1/meta/app?id=<appName>`。
- [ ] ⚠️ **`?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,
Expand All@@ -63,24 +69,8 @@ dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行
watcher 只重编译示例应用自己的 `objectstack.config.ts` / `src`,不管工作区的包。
- [ ] 所以:先做完**全部**源码编辑 → `pnpm --filter <pkg...> 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 <pkg> build` → **证明它到达了 `dist/`** → 才
读运行结果:`node scripts/ablation-dist-preflight.mjs <pkg> '<marker>'` 只在被消费
的 `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 修复 —— *甚至
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 12 additions & 21 deletions .claude/skills/checklist-author/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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-<task>
-b <branch> 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-<task> -b <branch> origin/main`。全部编辑落在那里;派发任何 agent
之前先读清单现状。
2. **只有编排者碰 `coverage.json` 与 `scripts/`。** hunter 一个文件都不写,writer 一
个区文件一人 —— 这是并行 agent 之间唯一的串行化依据。
3. **本技能的简报是假设,源码才是真相** —— 每个测试项按 README.md「Item anatomy」
的契约写;缺 fixture 记 `blocked`/`knownGaps`,永不伪造覆盖。

## 规模指引

Expand Down
32 changes: 14 additions & 18 deletions .claude/skills/checklist-test/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -75,8 +75,9 @@ node scripts/checklist-select.mjs <selector> --json
区没跑。**默认复用**已配好的树;每轮开一个冷容器,只在这一轮必须**活得比派发会话
久**时才值(长时间浏览器运行、dogfood)。

**按 tier 排序,钉住的先跑、按区批量。** 解析器给出的 `automated.ref` 是最便宜的切
分:
**按 tier 排序,钉住的先跑、按区批量。** 最便宜的切分是 `automated.ref` —— 但
`--json` **不投影它**(它只给 id · priority · surface · since · revision),按 id 到
区文件 `areas/<area>.json` 里读:

- **Tier 1 —— 带 `automated.ref` 的项**:**按区批量**,一次 vitest 覆盖该区全部钉住
的文件,一条命令为多项取证(RUNNER 规则 6:不重证自动化已钉住的东西)。
Expand All@@ -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 <paths>` 的输出、⛔ 不凭记忆(floor
sonnet · default opus · ceiling fable);每个给:该项 JSON、RUNNER.md、dogfood 技
能、自己的端口/DB、结果不进仓规则(§4)。
- **没有子代理工具时,顺序跑 —— 并在运行记录里声明这一轮是顺序执行的。** 规则与它
的论证住在 `checklist-author` 技能(维护者所定,一处成文);⛔ 不留第二份拷贝。
- 忠实执行每项的 `steps`,按各自声明的 `oracle` 判定每条 `acceptance` 与 `negative`
并采证 —— oracle 层级、证据要求与防误报自查是 RUNNER 规则 1–2,⛔ 这里不复述。

## 3. 当这一轮教你的是关于测试项本身的东西

Expand DownExpand Up@@ -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,不要糊在一起。
30 changes: 10 additions & 20 deletions .claude/skills/dogfood-verification/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,10 +28,15 @@ metadata:
dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行的 Claude/dogfood 会
话会抢走浏览器标签页、留下挡住导航的未保存草稿、弄脏工作树。开工前先隔离:

⚠️ 环境事实的锚点是 `docs/qa/platform-checklist/RUNNER.md` —— 本节只写它没有的那
几条,⛔ 不留第二份拷贝。

- [ ] **自有端口**:挑一个空闲的非默认端口(不要 3000/3001/3210)。先查:
`lsof -nP -iTCP:<port> -sTCP:LISTEN`。在 `.claude/launch.json` 加一条指向**本**
工作目录的具名配置,例如
`pnpm -C <abs>/examples/app-showcase exec objectstack dev --ui --seed-admin -p <port> -d file:/tmp/<run>/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/<run>/data.db` 重启后仍在(适合多步配置的运行);`--fresh`
给全新首跑(退出即清)。
Expand All@@ -49,8 +54,9 @@ dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行
- [ ] Console UI 在 `/_console/`;应用在 `/_console/apps/<appId>`(如
`com.objectstack.setup`、`com.objectstack.studio`)。API 根 `/api/v1`,设置
`/api/settings`,合并后的应用/导航 `/api/v1/meta/app?id=<appName>`。
- [ ] ⚠️ **`?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,
Expand All@@ -63,24 +69,8 @@ dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行
watcher 只重编译示例应用自己的 `objectstack.config.ts` / `src`,不管工作区的包。
- [ ] 所以:先做完**全部**源码编辑 → `pnpm --filter <pkg...> 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 <pkg> build` → **证明它到达了 `dist/`** → 才
读运行结果:`node scripts/ablation-dist-preflight.mjs <pkg> '<marker>'` 只在被消费
的 `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 修复 —— *甚至
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 12 additions & 21 deletions .claude/skills/checklist-author/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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-<task>
-b <branch> 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-<task> -b <branch> origin/main`。全部编辑落在那里;派发任何 agent
之前先读清单现状。
2. **只有编排者碰 `coverage.json` 与 `scripts/`。** hunter 一个文件都不写,writer 一
个区文件一人 —— 这是并行 agent 之间唯一的串行化依据。
3. **本技能的简报是假设,源码才是真相** —— 每个测试项按 README.md「Item anatomy」
的契约写;缺 fixture 记 `blocked`/`knownGaps`,永不伪造覆盖。

## 规模指引

Expand Down
32 changes: 14 additions & 18 deletions .claude/skills/checklist-test/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -75,8 +75,9 @@ node scripts/checklist-select.mjs <selector> --json
区没跑。**默认复用**已配好的树;每轮开一个冷容器,只在这一轮必须**活得比派发会话
久**时才值(长时间浏览器运行、dogfood)。

**按 tier 排序,钉住的先跑、按区批量。** 解析器给出的 `automated.ref` 是最便宜的切
分:
**按 tier 排序,钉住的先跑、按区批量。** 最便宜的切分是 `automated.ref` —— 但
`--json` **不投影它**(它只给 id · priority · surface · since · revision),按 id 到
区文件 `areas/<area>.json` 里读:

- **Tier 1 —— 带 `automated.ref` 的项**:**按区批量**,一次 vitest 覆盖该区全部钉住
的文件,一条命令为多项取证(RUNNER 规则 6:不重证自动化已钉住的东西)。
Expand All@@ -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 <paths>` 的输出、⛔ 不凭记忆(floor
sonnet · default opus · ceiling fable);每个给:该项 JSON、RUNNER.md、dogfood 技
能、自己的端口/DB、结果不进仓规则(§4)。
- **没有子代理工具时,顺序跑 —— 并在运行记录里声明这一轮是顺序执行的。** 规则与它
的论证住在 `checklist-author` 技能(维护者所定,一处成文);⛔ 不留第二份拷贝。
- 忠实执行每项的 `steps`,按各自声明的 `oracle` 判定每条 `acceptance` 与 `negative`
并采证 —— oracle 层级、证据要求与防误报自查是 RUNNER 规则 1–2,⛔ 这里不复述。

## 3. 当这一轮教你的是关于测试项本身的东西

Expand DownExpand Up@@ -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,不要糊在一起。
30 changes: 10 additions & 20 deletions .claude/skills/dogfood-verification/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,10 +28,15 @@ metadata:
dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行的 Claude/dogfood 会
话会抢走浏览器标签页、留下挡住导航的未保存草稿、弄脏工作树。开工前先隔离:

⚠️ 环境事实的锚点是 `docs/qa/platform-checklist/RUNNER.md` —— 本节只写它没有的那
几条,⛔ 不留第二份拷贝。

- [ ] **自有端口**:挑一个空闲的非默认端口(不要 3000/3001/3210)。先查:
`lsof -nP -iTCP:<port> -sTCP:LISTEN`。在 `.claude/launch.json` 加一条指向**本**
工作目录的具名配置,例如
`pnpm -C <abs>/examples/app-showcase exec objectstack dev --ui --seed-admin -p <port> -d file:/tmp/<run>/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/<run>/data.db` 重启后仍在(适合多步配置的运行);`--fresh`
给全新首跑(退出即清)。
Expand All@@ -49,8 +54,9 @@ dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行
- [ ] Console UI 在 `/_console/`;应用在 `/_console/apps/<appId>`(如
`com.objectstack.setup`、`com.objectstack.studio`)。API 根 `/api/v1`,设置
`/api/settings`,合并后的应用/导航 `/api/v1/meta/app?id=<appName>`。
- [ ] ⚠️ **`?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,
Expand All@@ -63,24 +69,8 @@ dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行
watcher 只重编译示例应用自己的 `objectstack.config.ts` / `src`,不管工作区的包。
- [ ] 所以:先做完**全部**源码编辑 → `pnpm --filter <pkg...> 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 <pkg> build` → **证明它到达了 `dist/`** → 才
读运行结果:`node scripts/ablation-dist-preflight.mjs <pkg> '<marker>'` 只在被消费
的 `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 修复 —— *甚至
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 12 additions & 21 deletions .claude/skills/checklist-author/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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-<task>
-b <branch> 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-<task> -b <branch> origin/main`。全部编辑落在那里;派发任何 agent
之前先读清单现状。
2. **只有编排者碰 `coverage.json` 与 `scripts/`。** hunter 一个文件都不写,writer 一
个区文件一人 —— 这是并行 agent 之间唯一的串行化依据。
3. **本技能的简报是假设,源码才是真相** —— 每个测试项按 README.md「Item anatomy」
的契约写;缺 fixture 记 `blocked`/`knownGaps`,永不伪造覆盖。

## 规模指引

Expand Down
32 changes: 14 additions & 18 deletions .claude/skills/checklist-test/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -75,8 +75,9 @@ node scripts/checklist-select.mjs <selector> --json
区没跑。**默认复用**已配好的树;每轮开一个冷容器,只在这一轮必须**活得比派发会话
久**时才值(长时间浏览器运行、dogfood)。

**按 tier 排序,钉住的先跑、按区批量。** 解析器给出的 `automated.ref` 是最便宜的切
分:
**按 tier 排序,钉住的先跑、按区批量。** 最便宜的切分是 `automated.ref` —— 但
`--json` **不投影它**(它只给 id · priority · surface · since · revision),按 id 到
区文件 `areas/<area>.json` 里读:

- **Tier 1 —— 带 `automated.ref` 的项**:**按区批量**,一次 vitest 覆盖该区全部钉住
的文件,一条命令为多项取证(RUNNER 规则 6:不重证自动化已钉住的东西)。
Expand All@@ -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 <paths>` 的输出、⛔ 不凭记忆(floor
sonnet · default opus · ceiling fable);每个给:该项 JSON、RUNNER.md、dogfood 技
能、自己的端口/DB、结果不进仓规则(§4)。
- **没有子代理工具时,顺序跑 —— 并在运行记录里声明这一轮是顺序执行的。** 规则与它
的论证住在 `checklist-author` 技能(维护者所定,一处成文);⛔ 不留第二份拷贝。
- 忠实执行每项的 `steps`,按各自声明的 `oracle` 判定每条 `acceptance` 与 `negative`
并采证 —— oracle 层级、证据要求与防误报自查是 RUNNER 规则 1–2,⛔ 这里不复述。

## 3. 当这一轮教你的是关于测试项本身的东西

Expand DownExpand Up@@ -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,不要糊在一起。
30 changes: 10 additions & 20 deletions .claude/skills/dogfood-verification/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,10 +28,15 @@ metadata:
dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行的 Claude/dogfood 会
话会抢走浏览器标签页、留下挡住导航的未保存草稿、弄脏工作树。开工前先隔离:

⚠️ 环境事实的锚点是 `docs/qa/platform-checklist/RUNNER.md` —— 本节只写它没有的那
几条,⛔ 不留第二份拷贝。

- [ ] **自有端口**:挑一个空闲的非默认端口(不要 3000/3001/3210)。先查:
`lsof -nP -iTCP:<port> -sTCP:LISTEN`。在 `.claude/launch.json` 加一条指向**本**
工作目录的具名配置,例如
`pnpm -C <abs>/examples/app-showcase exec objectstack dev --ui --seed-admin -p <port> -d file:/tmp/<run>/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/<run>/data.db` 重启后仍在(适合多步配置的运行);`--fresh`
给全新首跑(退出即清)。
Expand All@@ -49,8 +54,9 @@ dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行
- [ ] Console UI 在 `/_console/`;应用在 `/_console/apps/<appId>`(如
`com.objectstack.setup`、`com.objectstack.studio`)。API 根 `/api/v1`,设置
`/api/settings`,合并后的应用/导航 `/api/v1/meta/app?id=<appName>`。
- [ ] ⚠️ **`?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,
Expand All@@ -63,24 +69,8 @@ dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行
watcher 只重编译示例应用自己的 `objectstack.config.ts` / `src`,不管工作区的包。
- [ ] 所以:先做完**全部**源码编辑 → `pnpm --filter <pkg...> 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 <pkg> build` → **证明它到达了 `dist/`** → 才
读运行结果:`node scripts/ablation-dist-preflight.mjs <pkg> '<marker>'` 只在被消费
的 `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 修复 —— *甚至
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 12 additions & 21 deletions .claude/skills/checklist-author/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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-<task>
-b <branch> 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-<task> -b <branch> origin/main`。全部编辑落在那里;派发任何 agent
之前先读清单现状。
2. **只有编排者碰 `coverage.json` 与 `scripts/`。** hunter 一个文件都不写,writer 一
个区文件一人 —— 这是并行 agent 之间唯一的串行化依据。
3. **本技能的简报是假设,源码才是真相** —— 每个测试项按 README.md「Item anatomy」
的契约写;缺 fixture 记 `blocked`/`knownGaps`,永不伪造覆盖。

## 规模指引

Expand Down
32 changes: 14 additions & 18 deletions .claude/skills/checklist-test/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -75,8 +75,9 @@ node scripts/checklist-select.mjs <selector> --json
区没跑。**默认复用**已配好的树;每轮开一个冷容器,只在这一轮必须**活得比派发会话
久**时才值(长时间浏览器运行、dogfood)。

**按 tier 排序,钉住的先跑、按区批量。** 解析器给出的 `automated.ref` 是最便宜的切
分:
**按 tier 排序,钉住的先跑、按区批量。** 最便宜的切分是 `automated.ref` —— 但
`--json` **不投影它**(它只给 id · priority · surface · since · revision),按 id 到
区文件 `areas/<area>.json` 里读:

- **Tier 1 —— 带 `automated.ref` 的项**:**按区批量**,一次 vitest 覆盖该区全部钉住
的文件,一条命令为多项取证(RUNNER 规则 6:不重证自动化已钉住的东西)。
Expand All@@ -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 <paths>` 的输出、⛔ 不凭记忆(floor
sonnet · default opus · ceiling fable);每个给:该项 JSON、RUNNER.md、dogfood 技
能、自己的端口/DB、结果不进仓规则(§4)。
- **没有子代理工具时,顺序跑 —— 并在运行记录里声明这一轮是顺序执行的。** 规则与它
的论证住在 `checklist-author` 技能(维护者所定,一处成文);⛔ 不留第二份拷贝。
- 忠实执行每项的 `steps`,按各自声明的 `oracle` 判定每条 `acceptance` 与 `negative`
并采证 —— oracle 层级、证据要求与防误报自查是 RUNNER 规则 1–2,⛔ 这里不复述。

## 3. 当这一轮教你的是关于测试项本身的东西

Expand DownExpand Up@@ -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,不要糊在一起。
30 changes: 10 additions & 20 deletions .claude/skills/dogfood-verification/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,10 +28,15 @@ metadata:
dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行的 Claude/dogfood 会
话会抢走浏览器标签页、留下挡住导航的未保存草稿、弄脏工作树。开工前先隔离:

⚠️ 环境事实的锚点是 `docs/qa/platform-checklist/RUNNER.md` —— 本节只写它没有的那
几条,⛔ 不留第二份拷贝。

- [ ] **自有端口**:挑一个空闲的非默认端口(不要 3000/3001/3210)。先查:
`lsof -nP -iTCP:<port> -sTCP:LISTEN`。在 `.claude/launch.json` 加一条指向**本**
工作目录的具名配置,例如
`pnpm -C <abs>/examples/app-showcase exec objectstack dev --ui --seed-admin -p <port> -d file:/tmp/<run>/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/<run>/data.db` 重启后仍在(适合多步配置的运行);`--fresh`
给全新首跑(退出即清)。
Expand All@@ -49,8 +54,9 @@ dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行
- [ ] Console UI 在 `/_console/`;应用在 `/_console/apps/<appId>`(如
`com.objectstack.setup`、`com.objectstack.studio`)。API 根 `/api/v1`,设置
`/api/settings`,合并后的应用/导航 `/api/v1/meta/app?id=<appName>`。
- [ ] ⚠️ **`?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,
Expand All@@ -63,24 +69,8 @@ dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行
watcher 只重编译示例应用自己的 `objectstack.config.ts` / `src`,不管工作区的包。
- [ ] 所以:先做完**全部**源码编辑 → `pnpm --filter <pkg...> 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 <pkg> build` → **证明它到达了 `dist/`** → 才
读运行结果:`node scripts/ablation-dist-preflight.mjs <pkg> '<marker>'` 只在被消费
的 `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 修复 —— *甚至
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 12 additions & 21 deletions .claude/skills/checklist-author/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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-<task>
-b <branch> 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-<task> -b <branch> origin/main`。全部编辑落在那里;派发任何 agent
之前先读清单现状。
2. **只有编排者碰 `coverage.json` 与 `scripts/`。** hunter 一个文件都不写,writer 一
个区文件一人 —— 这是并行 agent 之间唯一的串行化依据。
3. **本技能的简报是假设,源码才是真相** —— 每个测试项按 README.md「Item anatomy」
的契约写;缺 fixture 记 `blocked`/`knownGaps`,永不伪造覆盖。

## 规模指引

Expand Down
32 changes: 14 additions & 18 deletions .claude/skills/checklist-test/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -75,8 +75,9 @@ node scripts/checklist-select.mjs <selector> --json
区没跑。**默认复用**已配好的树;每轮开一个冷容器,只在这一轮必须**活得比派发会话
久**时才值(长时间浏览器运行、dogfood)。

**按 tier 排序,钉住的先跑、按区批量。** 解析器给出的 `automated.ref` 是最便宜的切
分:
**按 tier 排序,钉住的先跑、按区批量。** 最便宜的切分是 `automated.ref` —— 但
`--json` **不投影它**(它只给 id · priority · surface · since · revision),按 id 到
区文件 `areas/<area>.json` 里读:

- **Tier 1 —— 带 `automated.ref` 的项**:**按区批量**,一次 vitest 覆盖该区全部钉住
的文件,一条命令为多项取证(RUNNER 规则 6:不重证自动化已钉住的东西)。
Expand All@@ -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 <paths>` 的输出、⛔ 不凭记忆(floor
sonnet · default opus · ceiling fable);每个给:该项 JSON、RUNNER.md、dogfood 技
能、自己的端口/DB、结果不进仓规则(§4)。
- **没有子代理工具时,顺序跑 —— 并在运行记录里声明这一轮是顺序执行的。** 规则与它
的论证住在 `checklist-author` 技能(维护者所定,一处成文);⛔ 不留第二份拷贝。
- 忠实执行每项的 `steps`,按各自声明的 `oracle` 判定每条 `acceptance` 与 `negative`
并采证 —— oracle 层级、证据要求与防误报自查是 RUNNER 规则 1–2,⛔ 这里不复述。

## 3. 当这一轮教你的是关于测试项本身的东西

Expand DownExpand Up@@ -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,不要糊在一起。
30 changes: 10 additions & 20 deletions .claude/skills/dogfood-verification/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,10 +28,15 @@ metadata:
dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行的 Claude/dogfood 会
话会抢走浏览器标签页、留下挡住导航的未保存草稿、弄脏工作树。开工前先隔离:

⚠️ 环境事实的锚点是 `docs/qa/platform-checklist/RUNNER.md` —— 本节只写它没有的那
几条,⛔ 不留第二份拷贝。

- [ ] **自有端口**:挑一个空闲的非默认端口(不要 3000/3001/3210)。先查:
`lsof -nP -iTCP:<port> -sTCP:LISTEN`。在 `.claude/launch.json` 加一条指向**本**
工作目录的具名配置,例如
`pnpm -C <abs>/examples/app-showcase exec objectstack dev --ui --seed-admin -p <port> -d file:/tmp/<run>/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/<run>/data.db` 重启后仍在(适合多步配置的运行);`--fresh`
给全新首跑(退出即清)。
Expand All@@ -49,8 +54,9 @@ dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行
- [ ] Console UI 在 `/_console/`;应用在 `/_console/apps/<appId>`(如
`com.objectstack.setup`、`com.objectstack.studio`)。API 根 `/api/v1`,设置
`/api/settings`,合并后的应用/导航 `/api/v1/meta/app?id=<appName>`。
- [ ] ⚠️ **`?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,
Expand All@@ -63,24 +69,8 @@ dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行
watcher 只重编译示例应用自己的 `objectstack.config.ts` / `src`,不管工作区的包。
- [ ] 所以:先做完**全部**源码编辑 → `pnpm --filter <pkg...> 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 <pkg> build` → **证明它到达了 `dist/`** → 才
读运行结果:`node scripts/ablation-dist-preflight.mjs <pkg> '<marker>'` 只在被消费
的 `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 修复 —— *甚至
Expand Down
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 12 additions & 21 deletions .claude/skills/checklist-author/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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-<task>
-b <branch> 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-<task> -b <branch> origin/main`。全部编辑落在那里;派发任何 agent
之前先读清单现状。
2. **只有编排者碰 `coverage.json` 与 `scripts/`。** hunter 一个文件都不写,writer 一
个区文件一人 —— 这是并行 agent 之间唯一的串行化依据。
3. **本技能的简报是假设,源码才是真相** —— 每个测试项按 README.md「Item anatomy」
的契约写;缺 fixture 记 `blocked`/`knownGaps`,永不伪造覆盖。

## 规模指引

Expand Down
32 changes: 14 additions & 18 deletions .claude/skills/checklist-test/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -75,8 +75,9 @@ node scripts/checklist-select.mjs <selector> --json
区没跑。**默认复用**已配好的树;每轮开一个冷容器,只在这一轮必须**活得比派发会话
久**时才值(长时间浏览器运行、dogfood)。

**按 tier 排序,钉住的先跑、按区批量。** 解析器给出的 `automated.ref` 是最便宜的切
分:
**按 tier 排序,钉住的先跑、按区批量。** 最便宜的切分是 `automated.ref` —— 但
`--json` **不投影它**(它只给 id · priority · surface · since · revision),按 id 到
区文件 `areas/<area>.json` 里读:

- **Tier 1 —— 带 `automated.ref` 的项**:**按区批量**,一次 vitest 覆盖该区全部钉住
的文件,一条命令为多项取证(RUNNER 规则 6:不重证自动化已钉住的东西)。
Expand All@@ -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 <paths>` 的输出、⛔ 不凭记忆(floor
sonnet · default opus · ceiling fable);每个给:该项 JSON、RUNNER.md、dogfood 技
能、自己的端口/DB、结果不进仓规则(§4)。
- **没有子代理工具时,顺序跑 —— 并在运行记录里声明这一轮是顺序执行的。** 规则与它
的论证住在 `checklist-author` 技能(维护者所定,一处成文);⛔ 不留第二份拷贝。
- 忠实执行每项的 `steps`,按各自声明的 `oracle` 判定每条 `acceptance` 与 `negative`
并采证 —— oracle 层级、证据要求与防误报自查是 RUNNER 规则 1–2,⛔ 这里不复述。

## 3. 当这一轮教你的是关于测试项本身的东西

Expand DownExpand Up@@ -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,不要糊在一起。
30 changes: 10 additions & 20 deletions .claude/skills/dogfood-verification/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,10 +28,15 @@ metadata:
dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行的 Claude/dogfood 会
话会抢走浏览器标签页、留下挡住导航的未保存草稿、弄脏工作树。开工前先隔离:

⚠️ 环境事实的锚点是 `docs/qa/platform-checklist/RUNNER.md` —— 本节只写它没有的那
几条,⛔ 不留第二份拷贝。

- [ ] **自有端口**:挑一个空闲的非默认端口(不要 3000/3001/3210)。先查:
`lsof -nP -iTCP:<port> -sTCP:LISTEN`。在 `.claude/launch.json` 加一条指向**本**
工作目录的具名配置,例如
`pnpm -C <abs>/examples/app-showcase exec objectstack dev --ui --seed-admin -p <port> -d file:/tmp/<run>/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/<run>/data.db` 重启后仍在(适合多步配置的运行);`--fresh`
给全新首跑(退出即清)。
Expand All@@ -49,8 +54,9 @@ dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行
- [ ] Console UI 在 `/_console/`;应用在 `/_console/apps/<appId>`(如
`com.objectstack.setup`、`com.objectstack.studio`)。API 根 `/api/v1`,设置
`/api/settings`,合并后的应用/导航 `/api/v1/meta/app?id=<appName>`。
- [ ] ⚠️ **`?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,
Expand All@@ -63,24 +69,8 @@ dev 工作树、dev-server 端口、preview 浏览器全是**共享的**:并行
watcher 只重编译示例应用自己的 `objectstack.config.ts` / `src`,不管工作区的包。
- [ ] 所以:先做完**全部**源码编辑 → `pnpm --filter <pkg...> 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 <pkg> build` → **证明它到达了 `dist/`** → 才
读运行结果:`node scripts/ablation-dist-preflight.mjs <pkg> '<marker>'` 只在被消费
的 `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 修复 —— *甚至
Expand Down
Loading
Loading