docs(pm-dispatch): 增补 2026-08-03 全天运行沉淀的八条 PM 操作经验 (#4882) - #4885
Merged
Conversation
按落点融入既有结构,纯插入不重写: - step 2 分诊:「无生产者」形状(声明了、消费端有读取、gate 全绿,却无人写值) - step 3 选批:同文件跨轮串行,推迟时把已知的坑当场钉到 issue 上 - step 5 派发:同日 main 变更写进派发词;新增 worktree 接手协议(宿主中断的 dev 不可恢复但 worktree 完好) - step 7 复核:dev 证伪前提是好报告的标志;`+0/-0` 先怀疑 NUL 字节 - 新增 Operational notes(实测坑位):gh-readonly-queue 判入队、队列踢出先认签名、 GraphQL 配额与 rate_limit 轮询、核验 main 一律用 origin/main Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015Br2xsJsczFsTR9bvbh2Ny
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
os-zhuang
marked this pull request as ready for review
August 3, 2026 13:17
This was referenced Aug 3, 2026
This was referenced Aug 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #4882
把 2026-08-03 主 backlog PM 会话跑完 12 单合并 + 8 单新立后沉淀的八条操作经验写进
.claude/skills/pm-dispatch/SKILL.md,让下一个 PM 会话不用重新踩。纯插入,不重写既有章节:git diff --stat为134 insertions(+),既有行删除数为 0。落点与内容
step 2 分诊 — 新增「无生产者」形状的识别规则:声明了、消费端有读取、gate 全绿,却没有任何生产者写值;类型系统与 lint 只验消费方,所以这类洞在全绿下长期存活。当日五次命中(#4704 / #4837 / #4839 / #4862 / #4867)。遇到 declared ≠ enforced 类 issue,分诊时先问「生产者在哪」,答案通常就是根因,并会在派发前改掉 issue 的作用域与
domain:*标签。step 3 选批 — 同文件 issue 严格跨轮串行,并明确推迟 ≠ 搁置:#4820 的 dev 查出 #4821 正文建议的
JSON.stringify键法会改掉类型强制语义、引入静默新缺陷,这条警告与Blocked-by:在 #4820 复核完成的同一轮就钉到了 #4821 上 —— 被推迟的 issue 在每次 sweep(包括别的 PM 的)里看起来都是可派发的,你知道的坑不写上去就等于不存在。step 5 派发 — 两条:
phoneOtp.cooldownSeconds配成大于 1 小时会被静默截断 —— OtpSendGuard 的历史 TTL 硬编码 1 小时 #4808 派发前 fix(plugin-auth): 每号码 OTP 发送预算改用惰性解析的共享计数存储 —— 多节点下不再按节点数倍增 (#4790) #4806 刚改过同一 guard,compareTo drops every measure-scoped filter, so<measure>__comparesilently reports a different measure than the column beside it #4820 派发前 fix(service-analytics): 按聚合种类填充「查询从未报告过的分组」,并补上 compareTo 这一道接缝 (#4708) #4822 刚改过同一文件,两单都因派发词点名而避开返工。#### Handing off an interrupted dev(worktree 接手协议):/compact与宿主中断会把运行中的子 agent 连同挂起的工具调用一并杀死(@objectstack/verify的 bootStack 与 qa dogfood 同样用裸 import 解析 cloud 私有包 —— 与 cloud#1013 同一缺陷类 #4700 / hook 的condition求不出值时:全局 fail loud —— 抛错并中断该次操作(方案 B 已拍板;Blocked-by #4770) #4775 停在同一秒),agent 不可恢复但 worktree/分支/提交完好。接手 = 派新 agent + 明确「worktree 已存在,⛔ 不要新建」+ 先通读既有改动再逐块决定取舍 + 补跑从未跑过的验证 + 认领与分支不变。两单按此接手后均一次通过复核。step 7 复核 — 两条:
phoneOtp.cooldownSeconds配成大于 1 小时会被静默截断 —— OtpSendGuard 的历史 TTL 硬编码 1 小时 #4808 / 内核的插件 init/start 超时守卫定时器从不清除也不 unref —— 每个进程在工作结束后还要空转 startupTimeout(CLI 挂 ~120s 才退出) #4813 / [metadata] nextEventSeq() 把驱动读失败也当成「表还没建」,静默从 1 重新发号 —— #4632 同形,机械检查覆盖不到 #4825 / 每号码 OTP 发送预算(#2780)也只在进程内计数 —— 与 #4772 的限流洞同类,多节点下可按节点数倍增 #4790);PM 被纠正时公开认账,错误归因另立 issue(os migrate成功时退出码是随机非零值(208/171/176/163/62…),--version/--help却干净退出 0 #4873)而不是静默丢弃。+0/-0未必是空文件 —— 文件含 NUL 字节时 git 判为二进制。fix(service-analytics): compareTo 带上 measure 自己的 filter,__compare 列不再是另一个 measure (#4820) #4870 的 347 行测试文件即如此,PM 一度误判为占位空文件。判据落在 blob 不落在 diff;修法写转义\\u0000(反斜杠 + u0000),不写裸字节。新增
## Operational notes(实测坑位)(接在 State model 之后,中文,与 Domain lanes 节先例一致) — 四条队列/平台层结论,共同点是「判据取命令输出,不取 API 字段字面值,也不取本地工作树现状」:gh-readonly-queue/*分支,不看auto_merge(入队后该字段回落为 off,零信息量);spec/src/cloud/tenant.test.ts的 #4739 导出面用例贴着 5s 超时 —— 今晚已两次把不相干的 PR 踢出合并队列 #4796 连踢五个无关 PR,原样重投全过);但止血 PR fix(spec): 给 packages/spec 的 vitest 设 testTimeout 60s —— 止血,不再把无关 PR 踢出合并队列 (#4850) #4856 合入后同签名再现即新问题,禁止条件反射式重投;rate_limit的resources.graphql.remaining,复核意见先用 REST 发出不等配额;git grep ... origin/main/git show origin/main:—— 共享检出可能落后数十提交(当日 PM 与一名 dev 都在落后 63 提交的树上 grep 出假阴性),这条同时写进派发词。验收自检
生产者×2、worktree 接手×1、gh-readonly-queue×2、rate_limit×2、origin/main×9、nul×5(不区分大小写)134 insertions(+), 0 deletions,既有行删除数 grep 得 0---/---),不发布任何包 —— 与.changeset/pm-dispatch-domain-lanes.md首 12 字节逐字节一致门禁
node scripts/check-nul-bytes.mjs→check-nul-bytes: OK (2986 tracked source file(s), no raw NUL bytes).值得记一笔:写 C2 那条时编辑工具真的把转义写成了裸 NUL 字节(SKILL.md 第 626 行),先被控制字符扫描(
grep -naP '[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f]')抓住、按字节改写为转义文本后才提交 —— 该条经验在自己身上原样复现了一次;本 PR 正文首版的同一处也被 GitHub 吃掉过一次,现已修正。eslint 不覆盖 md(配置仅**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}等 JS/TS glob),check:doc-authoring的 ROOTS 是skills/content,不含.claude/,故无其他适用门禁。改动面严格限于
.claude/skills/pm-dispatch/SKILL.md+ 一个 changeset,未碰.claude/agents/os-dev.md、packages/**、顶层skills/**、content/docs/**。🤖 Generated with Claude Code
https://claude.ai/code/session_015Br2xsJsczFsTR9bvbh2Ny