Skip to content

docs(pm-dispatch): 协调模型改版 —— 分诊/执行纵向拆分 + 一人一车道双射 + 登记表正文即真相 + 座位 Routine 化 (#5472) - #5522

Merged
os-zhuang merged 3 commits into
mainfrom
claude/pm-dispatch-unassigned-tasks-j0ghxx
Aug 5, 2026
Merged

docs(pm-dispatch): 协调模型改版 —— 分诊/执行纵向拆分 + 一人一车道双射 + 登记表正文即真相 + 座位 Routine 化 (#5472)#5522
os-zhuang merged 3 commits into
mainfrom
claude/pm-dispatch-unassigned-tasks-j0ghxx

Conversation

@os-zhuang

@os-zhuang os-zhuang commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Fixes #5472

维护者 2026-08-05 拍板的 PM 协调模型改版,落到唯一文件面 .claude/skills/pm-dispatch/SKILL.md(加一份 changeset)。

前提核查(先做,再写)

git fetch origin main 之后逐条比对 issue 的「SKILL.md 待改条款」与 origin/main 现状(首轮取 HEAD 736519d):

issue 条款 origin/main 现状 处置
#5130 决策轴扩三条 已合(3681d2a) 不在本 PR 范围,未动
#5095 域分类表补 22 包 已合(1ce2030) 保留其全部成果,只在其上拆 engine
engine 拆为 engine-core / drivers 未落地 —— 1ce2030 只补包、未拆域,domain:engine 仍是一行且含 driver-* 本 PR 落地
rule 4 纵向拆分 / 双射 / 删 borrowing 未落地(旧「分片阶梯 + 同队列禁令 + Borrowing」原文在) 本 PR 落地
全局在飞检查降级 未落地(仍是「run it at batch selection」的每轮常备税) 本 PR 落地
登记表协议(正文即真相) 未落地(SKILL 仍写「registers its domain set in the registry issue」= 评论式登记) 本 PR 落地
rule 5 org Project 视图层 只有一句「gives the maintainer a single view」,无分层定位 本 PR 补齐
Dispatch backends / Collect 的 Routine 形态 未落地 本 PR 落地

premise 成立(只有 #5130 / #5095 两条已被覆盖,其余全缺),按增量施工。

改了什么

  1. rule 4 重写为「纵向拆分 + 一人一车道双射」:1 个分诊 PM(全仓唯一,只扫/分类/打标签/拆跨域/查重,永不认领派发,domain:* 的唯一生产者)+ N 个执行 PM(信任标签、跳过分诊、只在本车道认领)。旧的「分片阶梯 / 同队列禁令 / Borrowing」三段删除,以一句「越界许可已删除」的墓碑替代(见下「留给复核的三处」)。
  2. 跨域例外路径成为唯一越界通道,并写明触发条件(当且仅当认领分诊座位指定的跨域例外单)与检查范围(申报文件面所触及的那几个域,不是全仓);全局在飞检查随之降级为该路径专用,附降级理由(每轮 O(PM × 在飞) 的开销 vs 自由文本判据)。
  3. 座位表协议([PM] 分片分工登记表 — 谁在管哪个仓库的队列 #4604):正文表格即唯一权威现状,行 = 座位 / 列 = 座位|范围|当前 PM|说明,接管即就地编辑该行 + 审计评论;评论不承载状态;无心跳,活性惰性判定(Routine 座位查 last_fired / next_run,会话座位查最近产出评论),超过 24h 无产出可回收。epic 登记退回 pm:epic 父单正文(label:pm:epic 即索引),座位表不重复记 —— state model 表、gh label create pm:epic 的描述、Epic 一节的委托信号/收尾/僵尸回收/残余风险四段同步改写。
  4. rule 5 补 org Project 的分层定位:视图层、没有任何机器读它、因只有 GraphQL 入口(配额实测,Operational note 3)绝不进循环热路径;权威层坚持 issue 正文 + REST。
  5. 域表重切:domain:engine 拆为 domain:engine-core(objectql / metadata* / platform-objects / core / formula / plugin-pinyin-search)与 domain:drivers(plugins/driver-* 四个),附拆分理由、存量标签迁移纪律、座位表加行要求;锚定规则里 hook 的 condition 求不出值时:全局 fail loud —— 抛错并中断该次操作(方案 B 已拍板;Blocked-by #4770) #4775 的示例同步改为 domain:engine-coreplugin-pinyin-search 归 engine-core 是读代码定的:__search 伴生列由 SchemaRegistry 声明、engine 把它 OR 进 $search(见 packages/plugins/plugin-pinyin-search/src/companion-projection.ts 首段注释),落点在编译/查询核心而非任何 driver。
  6. 座位 Routine 化的运行形态:新增「座位 Routine 化」小节(挂在 Dispatch backends 之下,并明确它不是第三个 dispatch backend)+ Collect 的跨轮收集边界 + step 9 的通知通道。轮次互斥取 issue 允许「实施中定型」的那个倾向方案(fire 开始查上一轮产出时间,间隔不足即自退),并把 试点:分诊 PM 座位 Routine 化 —— 全仓唯一分诊者,cron 定时 fresh session,只标签不认领(#5472 模型第 5 点先行验证) #5474 试点的自限(每轮限量、优先最新;三处扫描排除)写进 step 0 与本节。
  7. ⛔ 如实写入 试点:分诊 PM 座位 Routine 化 —— 全仓唯一分诊者,cron 定时 fresh session,只标签不认领(#5472 模型第 5 点先行验证) #5474 已实测的运维约束:经 CCR 会话内 create_trigger 创建的 Routine 不携带 GitHub 连接器 → fired session 拿不到 github MCP 工具 → 静默零产出(2026-08-05 烟测近 50 分钟零写入,已回滚);座位 Routine 须由维护者从 claude.ai Routines UI 带连接器创建,且创建后先手动 fire 一轮烟测、判据取 GitHub 上的产出;附带记录模型无法经 API 钉住(update_trigger 返回 model_update_disabled,Routine 继承环境默认模型)。
  8. round loop 职责划分表 + step 0 / step 2 的座位标注 + Guardrails 两条新的 binding(分诊座位永不认领派发;domain:* 单一生产者)+ step 4 认领模板里 borrowing 措辞的清理。

终轮语义合并已完成(停放解除)

原「与 #5441 串行停放」一节作废:#5441 的 PR #5501 已于 2026-08-05T15:02:23Z 合并进 main(早于本 PR 的首次 push 15:12:53Z —— 首轮 fetch 的 736519d 取在其合并之前,所以首轮基线不含它)。终轮已做:

PR 保持 draft;转 ready 由 PM 复核后执行,本会话不转、不挂 auto-merge、不合并任何东西。

验证

文档改动,跑与 .claude/** 相关的门禁(全部在共享锁 flock /tmp/os-heavy-verify.lock 下串行,NODE_OPTIONS=--max-old-space-size=4096)。终轮(合并 + 语义补充之后)重跑的实际输出:

  • node scripts/check-nul-bytes.mjs --self-test✓ check-nul-bytes --self-test: 48 assertions over a temp git repo (real scan() path)
  • node scripts/check-nul-bytes.mjscheck-nul-bytes: OK (scanned 5481 tracked text file(s); skipped 5 binary, 1 non-regular; no raw ASCII control bytes).(首轮 5468 → 终轮 5481,差值即合入的新文件)
  • node scripts/check-doc-authoring.mjs --self-test✓ check-doc-authoring self-test: scope wiring ... and the dead-root hard error ... all hold.
  • node scripts/check-doc-authoring.mjs✓ doc authoring guard: 362 files clean — no bare metadata literals.
  • node scripts/docs-audit/check-audit-scope.mjs✓ docs-accuracy-audit scope is in sync with content/docs/: 178 hand-written doc(s).✓ release-owned pages are in scope and read-only: 9 page(s) ... review-only
  • 字节纪律自扫:用 grep -naP 扫 C0 控制字符集合(0x00 至 0x08、0x0b、0x0c、0x0e 至 0x1f)两文件 → exit 1(零命中);并用一个「确定存在的邻近词」做正向对照反查(grep -c 座位 Routine 化 → 1),证伪「扫描器坏了 / 路径错了」

未跑 pnpm test / pnpm typecheck:本 PR 的 diff 是纯 markdown 协议文本,零 TS/包边,两者对它没有覆盖面。

留给复核的三处(如实声明,不是偷偷做的决定)

  1. 「borrowing」字样保留一处墓碑句。 验收条款字面要求「borrowing 字样从 SKILL 移除」;本 PR 保留了 rule 4 里的一处「越界许可(旧条款的 borrowing)已删除」,理由是学过旧协议的会话会 grep 这个词,读到「已删除」比读到沉默更安全。若维护者要字面零命中,删掉那半句即可(一行改动),协议语义不变。
  2. epic 领地与域车道的相交防护:全局在飞检查删除后,这条防护原本挂在它上面。替代写法是「父单正文的领地声明 + 域座位每轮读一次 label:pm:epic 索引」(索引查询是 O(epic 数)),并在残余风险段如实标注它仍是声明式、不是机械保证。这是删除旧机制的必要补位,不是新契约。
  3. 分诊座位空缺期的代扫条款:依据 [PM] 分片分工登记表 — 谁在管哪个仓库的队列 #4604 正文现行的「重建前分诊欠账由会话型 PM 代扫」,写成「代扫只做分诊动作、不解除双射」。同理由,「epic PM 不同时持有 domain:* 座位」一句是座位表「每个 PM 恰好一个座位」的推论,不是新增规则。

后续动作(不在本 PR,提示 PM)

domain:engine-core / domain:drivers 两个标签需创建,存量 domain:engine issue 需按落点改标并在清零后删除旧标签;#4604 的 engine 行需一分为二(冻结指令锚在 drivers 行)。两者都是运行态动作,不是代码。相关的词表对账已归挂 #5469(见其评论),建议等本 PR 落地后一次做完。

未动(刻意)

.claude/agents/os-dev.md(#5501 已改过的领地,本 PR 一字未碰)、content/docs/releases/**、已发布目录 skills/objectstack-pm-dispatch/(发布内容,另单 #5451)、#4604 正文本身(运行态登记由 PM 侧落地;本 PR 只让 SKILL 引用与其实态一致)。

…ine 化 (#5472)

维护者 2026-08-05 拍板的 PM 协调模型改版,落到 `.claude/skills/pm-dispatch/SKILL.md`
(唯一文件面)加一份 changeset。前提已对 origin/main 核过:同文件今天已合的 #5130
(决策轴)与 #5095(域表 22 包)成果全部保留,engine 域拆分与本单其余条款在 main
上均未落地,按增量施工。

- Multi-repo rule 4 重写为「纵向拆分 + 双射」:1 个分诊 PM(全仓唯一,只扫/分类/
  打标签/拆跨域/查重,永不认领派发,`domain:*` 的唯一生产者)+ N 个执行 PM(信任
  标签、跳过分诊、只在本车道认领)。旧的分片阶梯 / 同队列禁令 / Borrowing 三段
  删除,只留一处「越界许可已删除」的墓碑句。
- 跨域例外路径成为唯一越界通道:分诊座位指定单一车道 PM 认领 + 申报文件面 +
  定向在飞检查(写明触发条件与检查范围);全局在飞检查从每轮常备税降级为该路径专用。
- 座位表协议(#4604):正文表格即唯一权威现状,行=座位 / 列=座位|范围|当前 PM|说明,
  接管即就地编辑该行 + 审计评论;评论不承载状态;无心跳,活性惰性判定,>24h 无产出
  可回收。epic 登记退回 `pm:epic` 父单正文(`label:pm:epic` 即索引),座位表不重复记。
- rule 5 补 org Project 的分层定位:视图层、无任何机器读它、GraphQL 配额不进循环
  热路径;权威层坚持 issue 正文 + REST。
- 域表重切:`domain:engine` 拆为 `domain:engine-core`(objectql / metadata* /
  platform-objects / core / formula / plugin-pinyin-search)与 `domain:drivers`
  (`plugins/driver-*`),附存量标签迁移与座位表加行要求;拆分后每包恰好一域。
- 座位 Routine 化的运行形态(Dispatch backends / Collect / step 9):每座位一个
  cron Routine、fresh session per fire、频率随队列深度独立调、读 #4604 拿范围 →
  从 labels 重建状态 → 跑一轮 → 结束;轮次互斥取「fire 开始查上一轮产出时间,
  间隔不足即自退」。⛔ 如实记录 #5474 试点实测:CCR 会话内 create_trigger 创建的
  Routine 不携带 GitHub 连接器,fired session 无 mcp github 工具即静默零产出,
  座位 Routine 须由维护者从 claude.ai Routines UI 带连接器创建并先烟测。
- round loop 新增职责划分表(step 0 / step 2 分类半边属分诊座位,step 1、3-9 属
  执行座位)+ step 0 三处扫描排除 + Guardrails 两条新 binding。

刻意未动:`.claude/agents/os-dev.md`(在飞 #5441 的领地)、`content/docs/releases/`、
已发布目录 `skills/objectstack-pm-dispatch/`、#4604 正文本身(运行态登记由 PM 落地)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N3uGFF8teXbpgtbEJ1aYXu
@vercel

vercel Bot commented Aug 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 5, 2026 3:30pm

Request Review

claude added 2 commits August 5, 2026 15:28
#5501(#5441 的实施)已于 2026-08-05T15:02:23Z 合入 main,本分支终轮 git merge
origin/main 无冲突(两 PR 的落点区段互不相交)。机械合并之后补两处**语义**叠加,
使两侧意图相加而不是并排放置:

- step 6 Collect:#5501 的停摆纠偏靠 SendMessage 唤醒一个还活着的对面,而座位
  Routine 的 fire 结束后没有可唤醒的 subagent —— 停摆与「会话已销毁」在 GitHub
  上是同一个读数。补一段:验证管线可能超过一个 fire 的活,一开始就走 mode:cloud,
  把恢复权交给下一轮的 GitHub 读数。
- 座位 Routine 化一节:补跨 fire 长流程的可行性依据 —— 串行接力(一棒一整圈 +
  棒间 PM 复核)必然跨多个 fire,能跨过去是因为交接物全是 GitHub 读数(draft/
  ready、auto-merge 是否挂上、预期红停放那份签名级清单写在 PR body 里);因此
  对长流程只加一条要求:接力/停放的每一项都要落成 GitHub 上可读的文本,不许把
  「下一棒该干什么」留在会话记忆里。

未改 #5501 的任何原文(含其「飞行中范围重叠拦截」段 —— 它说的是 PM 为**自己**
在飞的 agent 复查 main,双射之下天然就是本车道范围,与本单删掉的跨 PM 全局在飞
检查不是同一个机制,无需改写)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N3uGFF8teXbpgtbEJ1aYXu
@os-zhuang
os-zhuang marked this pull request as ready for review August 5, 2026 16:27
@os-zhuang
os-zhuang added this pull request to the merge queue Aug 5, 2026
Merged via the queue into main with commit 5acb93a Aug 5, 2026
21 checks passed
@os-zhuang
os-zhuang deleted the claude/pm-dispatch-unassigned-tasks-j0ghxx branch August 5, 2026 16:39
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Aug 6, 2026
…in 滞后、死代码删除复核 (objectstack-ai#5513) (objectstack-ai#5645)

2026-08-05 跑完一整条 filter 缺陷链(objectstack-ai#5363 / objectstack-ai#5366 / objectstack-ai#5368 / objectstack-ai#5375 / objectstack-ai#5431 / objectstack-ai#5445,
cloud#1117)后回看,六处在那一轮真实咬过人或真实救过场的规程,SKILL 里没有对应条目。
六条各落在 issue 指定的节内,**纯增补**:111 行插入、0 行删除,既有条目(objectstack-ai#5501 的接力
模式、objectstack-ai#5522 的座位模型、objectstack-ai#5630 的 assertEngineDeleteDispatch 条款)一字未动。

落点与要点:

1. **Multi-repo,rule 2 之后**「pin 滞后」——`Blocked-by:` 只保证上游已合并,姊妹仓还有
   第二个读数:本仓 pin 是否覆盖那个 commit。cloud#1116 的裁决落于 framework objectstack-ai#5368
   (`9c5abf4e9`),而 cloud 的 `.objectstack-sha` 未覆盖它,于是 `TursoDriver` 有一个
   方向反了的分叉窗口(fail-closed 一侧先到)。规程:派发前核祖先关系;未覆盖则 dev 在
   PR 正文留档窗口与方向,⛔ pin bump 不做 rider。
2. **step 3** 末「阻塞解除后重新定价」—— 前一单合入会改变后一单的成本模型,方向不止一个
   (本轮变便宜、没变、成本估计过期各有实例)。两个动作配对:派发前一单时带必答项
   「你的改动是否让 #X 变简单 / 变难 / 不必要 / 无影响」,派发被延后那单前用该回答重读
   其选项与成本估计。
3. **step 5** 派发令「多面组件的测试落点」—— 同一契约 ≥2 实现面时,新用例进共享一致性
   覆盖而非独立文件(原话照录)。附 objectstack-ai#5375 / objectstack-ai#5431 / objectstack-ai#5445 三条正交轴共用一条不变量。
4. **step 7 清单**「收益穿过它必经的那道边界之后还在吗」—— 判据是价值主张是否依赖下游
   如实转发;实例即 objectstack-ai#5423(4xx 直通曾整条替换 ≥500 字符正文,`code` 到了正文没到)。
5. **step 7 清单**「死代码删除的复核」——「这是死代码」是断言而非能从 diff 读出的事实,
   PM 在 origin/main 独立核一次引用面再 ACCEPT(查法用 Operational notes 6:notes 6 说
   怎么查不假阴性,本条说什么时候必须查)。
6. **step 8** 升级门槛之后「带前提的裁决」—— 分歧关键是可被代码证伪的事实时,第三档 =
   裁决 + 前提验证要求 + 「前提不成立报 fork,不许硬做也不许悄悄改选」禁令,三件缺一
   不可;缺第 3 条即退化为无人裁决且无读数显示。

实施时两处核实结果与 issue 正文不同,成文按核实后的事实写:

- issue 的附带论断「没有任何闸门在量这个 pin 滞后」**不成立** —— cloud 的
  `scripts/check-pin-staleness.sh`(test.yml 以 `continue-on-error` 跑)每次 CI 都报两个
  pin 各落后 main 多少 commit,advisory 是**有意设计**(`--max-behind` 需显式传)。它答
  的是「落后多少」,不是「是否覆盖我这条裁决 commit」;成文因此指向该脚本,并只把后一个
  问题留给派发前的祖先判断。据此**未**另立「无闸门」的发现单。
- 第 4 条的 rest-server 缺陷本身已由 objectstack-ai#5423 按「截断而非替换」修掉,成文改用过去时并注明,
  以免后来的读者去找一个已不存在的活 bug;该条要补的是**复核清单的缺口**,与代码是否已修
  无关。

第 1 / 3 条按 issue「未验证的部分」的克制写入适用判据(前后单共用同一契约或数据表示;
组件对同一契约有 ≥2 实现面),形态迥异的批次(纯 UI、纯文档)明确不强加。

验证:`node scripts/check-nul-bytes.mjs --self-test` + 全仓扫描绿(48 断言 / 5537 文件);
改动文件自扫 `grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]'` 零命中,并用邻近词反查证伪
「扫描器坏了」;`check:docs-audit-scope` 绿;markdown 结构核对(强调标记成对、代码围栏
16 个偶数、嵌套围栏缩进对齐)。

Claude-Session: https://claude.ai/code/session_01GX3sL71LFq8m2usg6VqTSE

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: os-zhuang <hr@objectstack.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tooling

Projects

None yet

2 participants