Skip to content

PR 标签写入是「整集替换」而非「新增一个」:agent 与 CI labeler 互相抹标签,已抹掉过一次 skip-changeset 豁免(#5533 只活一秒) #5649

Description

@os-zhuang

发现于 #5559(os-dev 收尾清单补 skip-changeset 硬步骤)的前提核对:逐 PR 拉 timeline 的 labeled/unlabeled 事件时,发现标签写入双向互抹。查重:仓内无既有单(搜 label clobber / labeler / sync-labelsskip-changeset label 均无命中;#5620 是 allow-major 从事件载荷读标签的孪生竞态,与本条不同 —— 那是,这是)。

事实(六例 timeline,2026-08-05)

方向一:agent 的写入抹掉 bot 的标签。 每次 agent 挂 skip-changeset,同一秒都伴随一条 agent 自己发出的 unlabeled,抹掉 bot 刚挂的标签,bot 随后再补挂:

这只有一种解释:挂标签走的是整集替换(PUT /issues/{n}/labels,或 MCP 的 labels 字段),而不是新增(POST /issues/{n}/labels)。整集写入把当时读到的标签集覆盖回去,于是并发 bot 刚挂的标签被抹除。

方向二(有实际代价):bot 的写入抹掉 agent 的 skip-changeset #5533:

15:46:42 labeled   size/m         by github-actions[bot]
15:46:44 unlabeled size/m         by os-zhuang        # agent 整集写入,抹掉 size/m
15:46:44 labeled   skip-changeset by os-zhuang        # 豁免标签落地
15:46:45 unlabeled skip-changeset by github-actions[bot]   # 一秒后被 CI 抹掉
15:46:45 labeled   size/m         by github-actions[bot]
15:46:45 labeled   tests          by github-actions[bot]
15:47:08 labeled   skip-changeset by os-zhuang        # 只好再挂一次

skip-changeset 是 Check Changeset 的门禁豁免依据。它被 CI 抹掉一秒,直接制造了 #5559 立单时记录的现象「dev 声明的标签没落到 PR 上」—— 实际是落了又被抹,dev 侧看起来与「没挂」无法区分。

为什么值得修

两个半独立的落点

  1. 写入侧(客户端):挂单个标签必须走新增语义(POST .../issues/{n}/labels,body {"labels":["skip-changeset"]}),不得整集替换。若 MCP 的 issue label 写入本身是 PUT 语义,则约束落在 agent 指令面(finding(os-dev): 测试-only PR 的 skip-changeset 标签两次由 dev 声明却未落到 PR 上 —— 疑似 os-dev 定义/工具面缺口,每次都靠 PM 兜底 + 烧一轮门禁红 #5559 的新条款已写明「只加一个标签,不要整集写入」)。
  2. CI 侧:确认 actions/labeler@v7.0.0(.github/workflows/pr-automation.yml 的 Auto Label)与 codelytv/pr-size-labeler@v1.10.4(Check PR Size)各自是否在做整集同步 —— 方向二说明至少有一个会移除自己没管的标签。若是 labeler 的 sync-labels 语义,应显式关掉;若是 size-labeler 的实现,需要评估其对无关标签的处理。
    ⚠️ pr-automation.yml 今日已被 Check Changeset 从事件载荷读 skip-changeset 标签:开 PR 后 5 秒内加标签,首个 run 永久红(重跑复用载荷)—— 一日三例 #5580/fix(ci): Check Changeset 实时读 skip-changeset 标签,首个 run 不再永久红 (#5580) #5625 改过,pr-automation.yml 的 allow-major 步骤仍从事件载荷读标签:#5580 同款竞态的孪生体(pre-mode 期间休眠) #5620 也在排队动同一文件,改动请先协调避免撞车。

复现

curl -sS -H "Authorization: Bearer $GITHUB_TOKEN" \
  "https://api.github.com/repos/objectstack-ai/objectstack/issues/5533/timeline?per_page=100" \
  | node -e '...filter(e => ["labeled","unlabeled"].includes(e.event))'

created_at 排序打印 event | label | actor,上文序列即原样可见。

Found-during: #5559(devx 车道第 7 轮,dev 会话 session_01GX3sL71LFq8m2usg6VqTSE)的前提核对。unassigned,交 PM 分诊。

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions