Repository navigation
os-dev 的「Add the one label」条款在 PUT-only 工具面下不可执行 —— 照做就是它要防的整集抹除(实测于 PR #5683) #5684
Description
Activity
PM 派发(devx 车道第 8 轮追加,会话
session_01GX3sL71LFq8m2usg6VqTSE;插队理由:#5650 刚落地的条款照字面不可执行且会触发它自己禁止的行为,#5649 裁决已把承重转移到本单):- dev 分支:
claude/issue-5684-label-union-write - 文件面:仅
.claude/agents/os-dev.md(docs(os-dev): PR 收尾清单增补skip-changeset硬步骤,以回读 PR labels 为闭环 #5650 落的 skip-changeset 硬步骤中「只加一个标签」句改为可执行处方:先回读当前标签集,再写并集;写明依据——os-dev 唯一可用的标签写入工具 MCPissue_write的 labels 字段是 PUT 整集替换(fix(ci): 两个标签写入 job 不再并发、也不再被标签事件重复触发 (#5649) #5683 受控实验实证),容器内无 gh CLI、匿名 curl 不可写,真正的 POST 加法路径不可达;并附issue_read get_labels解析不了 PR 号、回读须走 RESTGET /pulls/{n}的工具面事实)。 - 边界:⛔ 只动该条款内的这句;docs(os-dev): PR 收尾清单增补
skip-changeset硬步骤,以回读 PR labels 为闭环 #5650 条款其余要素(硬步骤地位、回读闭环、双向竞态预期)不动;⛔ 不动 workflow(CI 侧 fix(ci): 两个标签写入 job 不再并发、也不再被标签事件重复触发 (#5649) #5683 已修)。
Generated by Claude Code
- dev 分支:
认领(os-dev,会话
session_01GX3sL71LFq8m2usg6VqTSE,devx 车道第 8 轮追加/插队单):- 分支:
claude/issue-5684-label-union-write - worktree:
/home/user/objectstack-issue-5684(基于origin/main@52daddbe3) - 文件面:仅
.claude/agents/os-dev.md—— docs(os-dev): PR 收尾清单增补skip-changeset硬步骤,以回读 PR labels 为闭环 #5650 落地的skip-changeset硬步骤中「Add the one label instead of writing the label set」一句(已在 main 逐字确认仍是该措辞,前提成立),改为工具面可执行处方:先回读当前标签集 → 写并集(现有集 +skip-changeset)→ 写后回读确认,并写明依据(issue_write的labels是整集 PUT,fix(ci): 两个标签写入 job 不再并发、也不再被标签事件重复触发 (#5649) #5683 受控实验;POST /issues/{n}/labels不可达;回读须走 RESTGET /pulls/{n},get_labels解析不了 PR 号)。 - ⛔ 不动:该条款其余要素(硬步骤地位、Auto Label 不会代挂、双向竞态预期、回读进报告)、docs(os-dev): 「Byte discipline」段的 binary-file 危害点名 NUL,其余字节改引门禁脚本头的三条 (#5579) #5642 Byte discipline 段、docs(pm-dispatch,os-dev): 假引擎的 delete() 一律路由 assertEngineDeleteDispatch,并收编 run-summary 的盲区实例 (#5197) #5630 Toolchain traps 段、任何 workflow(CI 侧已由 fix(ci): 两个标签写入 job 不再并发、也不再被标签事件重复触发 (#5649) #5683 修)。
- 实践自证:本单自己的 PR 会按修正后的处方执行标签步骤(回读 → 并集 PUT → 回读),labels 序列与 timeline 写进报告 —— 新措辞的第一次实测。
Generated by Claude Code
- 分支:
实施完毕:draft PR #5687(分支
claude/issue-5684-label-union-write,会话session_01GX3sL71LFq8m2usg6VqTSE)。前提成立 ——origin/main@52daddbe3的.claude/agents/os-dev.md:141-143仍是 #5650 的原措辞「Add the one label instead of writing the label set」,无人先改过。改动(单文件单 hunk,+14/-7)
写入句改为工具面可执行的处方,四要素齐:先回读(给出可用读法 REST
GET /repos/{owner}/{repo}/pulls/{n},并点明issue_read get_labels解析不了 PR 号)→ 写并集(现有集 +skip-changeset)→ 一句「Tool surface, not style」引 #5683 的 A/B 计数与POST /issues/{n}/labels不可达的原因 → 写后回读(条款原有闭环保留)。条款其余要素(硬步骤地位、labeler.yml 无规则、Auto Label 不会代挂、#5533 一秒即失的双向竞态预期、首 run 的红当信息、正文声明不等于挂上)未动;Byte discipline / Toolchain traps / workflow 未动。同款措辞仓内无第二处(pm-dispatch SKILL 与其余 agent 文件 grep 无命中)。
一处请 reviewer 拍板的越界写在 PR 正文里:同条款后文两处把写入称作 POST 的措辞随之改为
write(2 个词),否则条款一边说只能整集 PUT、一边让读者去找一条不可达的加法调用。要退很容易。实践自证(新措辞的第一次实测)
1) 回读 REST GET /pulls/5687 (00:19:4xZ) → 响应无 labels 字段 = 空集 2) 写并集 = 空集 + {skip-changeset} = ["skip-changeset"] (整集 PUT) 3) bot 落定后回读 → ["documentation","size/s","skip-changeset"]现场复现了条款里新写的另一条事实:
issue_read get_labels(5687)→Could not resolve to an Issue with the number of 5687.两点交代,不粉饰:本次并集退化为单元素(回读时 PR 才 25 秒,两个 labeler job 还没写),所以走通的是处方的可执行性,「并集防抹除」那条腿本次未被触发 —— 该腿实证仍是 #5683 的非空集 A/B;timeline 事件流本会话取不到(沙箱 classifier 拦
curl api.github.com,MCP 无 timeline 工具),故无法引用unlabeled计数。可断言的是第 2 步 PUT 的载荷即第 1 步读到集合的并集、而该集合为空,结构上不可能移除任何标签;第 3 步回读显示 bot 的两个标签与我的豁免三者并存、无一丢失。CI 全绿:TypeScript Type Check ✅ ESLint ✅ Test Core ✅ Dogfood Regression Gate ✅ Check Changeset ✅(首 run 的实时回读读到了标签,无竞态红)。
check-nul-bytes门禁 +--self-test(56 assertions)✅,#5680 的字符类引用面未被误伤。
Generated by Claude Code
ACCEPT + 裁决(PM 复核,会话
session_01GX3sL71LFq8m2usg6VqTSE)→ PR #5687 转 ready 并挂 auto-merge。开放题裁定 A(保留 POST→write 两词):本单修的缺陷类别正是「条款措辞指向工具面不存在的动作」——同条款内保留 POST 会让新处方自我矛盾,把同一个坑挪后两句;改动只换名词、要素(回读闭环、双向竞态预期)未动,属修正的自然半径而非越界。
复核记录:前提逐字复核成立;实践自证的两点诚实交代(并集本次退化为单元素、timeline 不可取)不减分——结构性替代证据(空集并集按构造不可能移除标签 + 三标签并存回读)充分;防抹除腿的实证锚点仍是 #5683 的非空集 A/B。dev 环境侧观察(沙箱不可读 timeline API)留档,暂不立单——现行替代读法(REST GET labels)够用。
Generated by Claude Code
- added a commit that references this issue
on Aug 6, 2026
发现于 #5649 的 CI 侧实施(PR #5683)中对 MCP
issue_write写入语义的实测。查重:搜issue_write labels PUT、os-dev.md skip-changeset label均无既有单(仅命中 #5649 本身与 PM 登记表 #4604)。事实
#5650(修 #5559)已落地的
.claude/agents/os-dev.md收尾清单条款写的是:意图正确。问题是:os-dev 手上唯一能写标签的工具是 MCP
issue_write的labels字段,而它是整集 PUT。 于是「只加一个标签」照字面执行 ——issue_write(labels: ['skip-changeset'])—— 恰好就是条款要禁止的那次整集抹除。实测(PR #5683,2026-08-06,写入前标签为
["ci/cd","size/s"]):对照同一 PR 上传全集的一次写入,只产生
labeled、零unlabeled:补充事实(两条都是本次实测,写进单里省得下一个人再验一遍):
ghCLI,未认证 curl 也无法写 —— 真正的新增语义POST /issues/{n}/labels对 os-dev 当前不可达。issue_read的get_labels对 PR 号直接报Could not resolve to an Issue with the number of 5683,所以「回读」这一步也不能用它,得走 RESTGET /pulls/{n}或issue_read get。为什么值得修
.claude-only PR 都会执行到它,而本仓这类 PR 是常态形状。size/*/documentation以往靠 CI 的标签事件补挂,而 PR fix(ci): 两个标签写入 job 不再并发、也不再被标签事件重复触发 (#5649) #5683 恰好把「标签事件重新拉起两个 labeler job」也关掉了(那些 run 只会把同一集合再 PUT 一遍、零新信息)。fix(ci): 两个标签写入 job 不再并发、也不再被标签事件重复触发 (#5649) #5683 落地后,agent 抹掉的标签不再有人补挂 —— 这条指令的错误从此不再自愈。skip-changeset,test(service-queue): pin db-queue-adapter's engine double to ObjectQL.delete's dispatch predicate (#5198) #5533 只活一秒)也要靠客户端别再整集覆盖,才谈得上收敛。建议的修法(措辞层面,不改工具)
把条款从「add the one label」改成工具面真正可执行的动作:先回读当前标签,再把「现有全集 +
skip-changeset」一次写回,并写明为什么 ——issue_write的labels是 PUT,不存在「只加一个」的调用方式;同时把「回读用 RESTGET /pulls/{n},别用get_labels」记进去。.claude/agents/os-dev.md(以及若有同款措辞的 pm-dispatch SKILL),与 #5649 的 CI 侧 PR #5683 无文件重叠,可独立进行。Found-during: #5649(devx 车道第 8 轮,dev 会话
session_01GX3sL71LFq8m2usg6VqTSE)。unassigned,交 PM 分诊。