From 17fdc53c31f8c00c815e1ca487ae4fe31b8cdb37 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 7 Sep 2026 11:31:10 +0000 Subject: [PATCH 1/4] agents(os-dev): name the one foreground wait shape, and never end the turn for a background notification MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three lines rewritten in place under the 403 ceiling (net 0), all in the clean-exit section: - The two shape lines fold into one: the only shape that is both anti-poll and non-stop is a single foreground blocking wait — run it to completion in the foreground, or block on the job's pid. The old second line named the harness's Monitor as the compliant shape; Monitor's own contract is a background event stream that notifies a RUNNING turn, so a dev who followed that line armed a Monitor and had nothing left to do in the foreground but end the turn. - The freed line carries the report-time rule: a gate that outlives the turn is read from its log (the redirect target) at the moment the report is written, and an unfinished one is recorded NOT MEASURED with the reason. - The "completion notice is itself the stop" tail becomes the explicit fact and prohibition: never end the turn to wait for a Monitor or background notification — a finished turn is a stopped agent, notifications reach only a running turn. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_018dxq7YqsLDMeZDZ5AzsgJX --- .claude/agents/os-dev.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.claude/agents/os-dev.md b/.claude/agents/os-dev.md index 9368edacb3..a5812b8733 100644 --- a/.claude/agents/os-dev.md +++ b/.claude/agents/os-dev.md @@ -337,11 +337,11 @@ model: opus - 两条合法出路:在轮内同步等它(资源纪律的排队条款:限时获取 ⇒ 无锁工作 ⇒ 再取)。 - 或者收窄这次检查的范围并在报告里申报:已申报的收窄是被接受的偏差,CI 跑满农场。 - PM 复核的是 CI 收敛,不是你本地的覆盖面;未申报的收窄不在此列,那是漏跑。 - - 反轮询与不停轮由同一个形状同时满足,而且只有这一个:一次前台阻塞等待。 - - 形状是 Monitor 带 until 条件,或干脆在前台把那套件跑完。 + - 唯一同时反轮询又不停轮的形状是一次前台阻塞等待:前台跑完,或 `tail --pid` 等它退出。 + - 比回合长的门禁在写报告那一刻读日志(重定向目标);未完成的记 NOT MEASURED 并写原因。 - ⛔ 不以结束一轮当反轮询解法:停轮不是合规替代,它恰是本条禁止的终点。 - 自检是机械的,不看你怎么形容这次等待:终消息只能是报告 JSON 或 `blocked` 报告。 - - 其它任何收尾文本按定义即停摆;⛔ 不指望后台 monitor 唤醒你,完成通知本身就是停轮。 + - ⛔ 永不结束回合去等 Monitor / 后台通知:结束回合即停摆,通知只送达在跑的回合。 - 结束一轮之前自检:最后一条消息是否在描述你不拥有的进程给你的唤醒? - 排队的锁、别的 agent 的 build、脱管的 watcher 都不会来;保持这一轮活着,自己收退出码。 - 报告不违反此条:它以结果结束一轮,不是等别的东西来恢复的承诺。 From d54346527bf46c2d14be640384b13bde5f36a661 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 7 Sep 2026 11:32:03 +0000 Subject: [PATCH 2/4] =?UTF-8?q?agents(os-dev):=20step=20=E2=91=A0=20exists?= =?UTF-8?q?=20only=20when=20the=20diff=20touches=20a=20package,=20and=20is?= =?UTF-8?q?=20a=20no-op=20on=20an=20empty=20closure?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two lines rewritten in place, one rider line added, one restatement folded (net 0 at 403): - ① is conditioned on the file surface: the dependency-closure build runs only when the diff touches a package; a diff touching none reports that there is no ①. On a graph-root package (`packages/spec` has no workspace dependency) the closure is empty, so ① runs nothing — gates that read `dist/` need the package itself built first. The old "skipping it produces failures that look like your change broke an import" tail is the false-red lesson the build-before-judging pair already states. - Rider beside the consumer-sweep lines: a retired key's sweep defaults to the retirement playbook's tree-scoped absence pin instead of rebuilding the consumer closure for one absence check. - Folded: "the report does not violate this clause" — the clause's own header already says a turn ends only at report delivery. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_018dxq7YqsLDMeZDZ5AzsgJX --- .claude/agents/os-dev.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.claude/agents/os-dev.md b/.claude/agents/os-dev.md index a5812b8733..c96100f022 100644 --- a/.claude/agents/os-dev.md +++ b/.claude/agents/os-dev.md @@ -126,8 +126,8 @@ model: opus ## 本地验证范围 —— 本地只跑定向门禁,全农场归 CI - ⛔ 不把 lint workflow 的 `check:*` 全枚举本地跑:CI 会把农场跑满。本地清单如下。 -- ① 先 build 依赖闭包:`pnpm --filter '^...' build` 是新 worktree 的第一条命令。 -- 跳过它产出的失败,读起来与你的改动弄坏了 import 一模一样。 +- ① diff 触到某包才有 ①:`pnpm --filter '^...' build` 建依赖闭包;不触任何包则报告无 ①。 +- 闭包为空(`packages/spec` 无 workspace 依赖)时 ① 空跑;读 `dist/` 的门禁前先 build 本包。 - ② 受影响包自己的 `pnpm test` / `pnpm typecheck`,用 `--filter` 圈定。 - 受影响包 = 本包;import 方只在公开面变化时欠测试:spec 契约、发布的 `exports`、线上形状。 - 公开面字节不变 ⇒ 只欠本包测试与派生门禁,⛔ 不给每个 import 方补测试。 @@ -188,6 +188,7 @@ model: opus - 消费者清扫的 filter 方向是前缀:`pnpm --filter '...@objectstack/'` = 下游消费者。 - 后缀形式是上游依赖,方向相反;契约收紧永远落在下游。 - 报告里写 N 个包全绿必须说方向,否则这句话无法复核。 +- 退役键的清扫默认走退役 playbook 的 tree-scoped 缺席 pin,不为一次缺席检查重建消费者闭包。 - 跨包类型改动需要一次反向验证:贴进一个新类型会拒绝的键,确认转红,再恢复。 - 这证明你读的是重建后的 `.d.ts`,不是缓存。 - `packages/spec`:`gen:schema` 会重写 `authorable-surface.base.json`,这是预期产物。 @@ -344,7 +345,6 @@ model: opus - ⛔ 永不结束回合去等 Monitor / 后台通知:结束回合即停摆,通知只送达在跑的回合。 - 结束一轮之前自检:最后一条消息是否在描述你不拥有的进程给你的唤醒? - 排队的锁、别的 agent 的 build、脱管的 watcher 都不会来;保持这一轮活着,自己收退出码。 - - 报告不违反此条:它以结果结束一轮,不是等别的东西来恢复的承诺。 ## 何时停手不写码 From 1a1e984a4657689f20623e37df3ded5b11a3c3fb Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 7 Sep 2026 11:32:03 +0000 Subject: [PATCH 3/4] =?UTF-8?q?agents(os-dev):=20one=20skip-changeset=20cr?= =?UTF-8?q?iterion=20=E2=80=94=20nothing=20published=20moves=20=E2=80=94?= =?UTF-8?q?=20with=20the=20path=20list=20as=20its=20fast=20path?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two lines rewritten, one measurement line added, one restatement folded (net 0 at 403): - The label has one criterion: nothing published moves, where published is what each package's `files[]` actually ships. The closed path list is demoted to the fast path — those paths publish nothing by definition — and everything else is measured: build, then grep the paths `files[]` lists for the symbol with a positive control; the symbol at zero hits while the control hits means unpublished. - Folded: "waiting for the lock, a gate batch or any slow step blocks in the foreground within the turn; the lock script waits by itself" — stated by the foreground-pipeline rule, the lock's single-call budget line and the one foreground wait shape. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_018dxq7YqsLDMeZDZ5AzsgJX --- .claude/agents/os-dev.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.claude/agents/os-dev.md b/.claude/agents/os-dev.md index c96100f022..b1136fb6eb 100644 --- a/.claude/agents/os-dev.md +++ b/.claude/agents/os-dev.md @@ -102,7 +102,6 @@ model: opus - 排队约 20 分钟无进展 ⇒ 先看这次检查能否收窄到不必持锁(收窄要申报,见干净收尾)。 - 收窄不了就停下报 `blocked` 并点名持锁者:`os-verify-lock.sh --status` 打印持锁者与队列。 - 一动不动的持锁者本身就是真发现;沉默是唯一错误答案。 - - 等锁、门禁批或任何慢步骤一律在本轮内前台阻塞,锁脚本自己会等。 ## Toolchain traps @@ -293,8 +292,9 @@ model: opus - 密度优化只随净减内容的 PR;分界只问折行有没有为新增内容买行。 - ⛔ 不把不买内容的密度修复当筹行拒掉;删不出等量内容 ⇒ 报 `blocked`,⛔ 不抬 ceiling。 - 例外:派发令点名测量优先的零余量受管账本 ⇒ 落行、不动上限行、红着报实测行数。 -- `skip-changeset` 标签按仓库分流,先认清目标仓有没有这个机制;判据:不从任何包发布东西。 -- 例:`docs/adr/**` · `.claude/**` · `scripts/pm/**` · 仓根工具配置 · 私有 workspace · 注释。 +- `skip-changeset` 唯一判据:没有已发布的东西移动;已发布 = 各包 `files[]` 实际发运的内容。 +- 快速通道:`docs/adr/**` · `.claude/**` · `scripts/pm/**` · 仓根配置 · 私有包 · 注释,不发布。 +- 其余实测:构建后 grep `files[]` 所列路径找符号,带正控;符号零命中、正控命中 ⇒ 不发布。 - 本仓库:标签是真实机制,打标签是你的步骤、不是 CI 的,PR 一开出就打。 - 写入首选加法端点(REST `POST .../issues//labels`,不碰已有标签);可达性按会话探,先探后用。 - 被拒 ⇒ 走回退:MCP 读现值→并集→整组写→必做对比式读回,并申报换道。 From ae47456aa6858bd31d07ac0b724edebcff591b0a Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 7 Sep 2026 11:32:03 +0000 Subject: [PATCH 4/4] agents(os-dev): the authorable-surface anchor is written only by gen:authorable-surface-base, never by a plain build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two lines rewritten in place (net 0 at 403); the prohibition line between them is untouched: - The causal claim narrows to what build-schemas.ts does: the deletion gate's in-tree anchor is written only in `--update-base` mode (`gen:authorable-surface-base`), never on a plain build — measured here by a plain `gen:schema` run that left `git status` empty. - Consequence stated where the old clause pointed the other way: on a plain build a move of that file is a finding, not an artifact. The "never revert it, never hand-edit it, `check:authorable-surface` green is the assertion" line survives verbatim. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_018dxq7YqsLDMeZDZ5AzsgJX --- .claude/agents/os-dev.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.claude/agents/os-dev.md b/.claude/agents/os-dev.md index b1136fb6eb..50bf720c14 100644 --- a/.claude/agents/os-dev.md +++ b/.claude/agents/os-dev.md @@ -190,9 +190,9 @@ model: opus - 退役键的清扫默认走退役 playbook 的 tree-scoped 缺席 pin,不为一次缺席检查重建消费者闭包。 - 跨包类型改动需要一次反向验证:贴进一个新类型会拒绝的键,确认转红,再恢复。 - 这证明你读的是重建后的 `.d.ts`,不是缓存。 -- `packages/spec`:`gen:schema` 会重写 `authorable-surface.base.json`,这是预期产物。 +- `packages/spec`:`authorable-surface.base.json` 只由 `gen:authorable-surface-base` 写,普通构建从不写。 - ⛔ 永不回退它、永不为凑某个相等手改它;作数的断言是 `check:authorable-surface` 绿。 -- `baseRev` 允许滞后,一行信息不是错误。 +- `baseRev` 允许滞后,一行信息不是错误;普通构建下该文件动了是 finding,不是产物。 - ⛔ 永不在 MERGE 态跑 `gen:schema`:HEAD 还是 merge 前的 tip,锚点会静默回滚到旧分叉点。 - 那样门禁全绿而已落地的推进被吞掉;先 commit merge 再重生成:`bash scripts/pm/os-regen-merge.sh`。 - `git worktree` 只隔离工作树与 HEAD;`.git/` 下其余一切全 worktree 共享。