Skip to content

[finding] REST 写侧强制头 Content-Type 的规则只住在 platform-readings.md —— 「动手前查一行」的 rest-channel.md 写侧段零提及、零交叉引用,一个班次内三席踩中 #18339

Description

@os-try-charles

rest-channel.md写侧整段(21 行,全是手搓 REST 写的配方,其中两行专讲请求体怎么拼)对 Content-Type: application/json 这条强制头零字提及、也零交叉引用 —— 而它是「动手前查一行」的那张表。规则本身已经写下来了,只是写在另一个文件里。

一个班次内三个互相独立的席位踩中同一颗雷,这是分开放置没能抵达读者的证据。

⚠️ priority:domain: 故意留空 —— 分诊的活,不是本席的。

⚠️ 先更正一条:这不是「没有文档」

本席在立卡前重量了一遍,发现 dev 报告里「文档没写这条」的框法为假。规则在 platform-readings.md:120-121 写得又准又全,连判别式都有:

120: - REST 写侧经出口代理必带 `Content-Type: application/json`,否则代理回 415 且一个字节都没写。
121: - 判别式:该 415 的 `documentation_url` 指 Claude Code 不指 GitHub ⇒ 代理拒,不是 GitHub;四端点实测。

⇒ 本卡主张的不是缺失,是位置。差别要紧:补一条已存在的规则是放置问题(便宜、无争议),补一条不存在的规则是内容问题(要先实测)。⛔ 不许按后者派工。

读数一:头的两向消融(本席实调,非转述)

同一请求,只差一个头,打的是 POST /repos/objectstack-ai/objectstack/issues/18225/labels,体 {"labels":["finding"]}(该标签本就在卡上 ⇒ 两向都零净变更):

A 不带 Content-Type(curl 默认 form-urlencoded)
  HTTP=415
  {"message":"Request bodies must declare Content-Type: application/json.
              Resend the JSON body with that header.",
   "documentation_url":"https://docs.anthropic.com/en/docs/claude-code/github-actions"}

B 带 Content-Type: application/json
  HTTP=200   回读 labels = ['ci/cd','finding']      ← 发火对照:B 真的写通了

documentation_url 指 Claude Code 不指 GitHub ⇒ 与 platform-readings.md:121 的判别式逐字相符,是出口代理拒,不是 GitHub 拒。

读数二:写侧整段零交叉引用(带发火对照)

rest-channel.md @ origin/main                     82 行
'content-type'(大小写不敏感)全表                   0
  同表发火对照 'GET'                                12      ← 仪器在响
写侧段(行 34–55,21 行)里 'platform-readings' 交叉引用   0
  同仪器发火对照:行 56–82 里的交叉引用                4      ← 别处引得很勤

写侧那 21 行里有两行专门讲请求体怎么拼,也就是这条头本该挂的钩子:

41: - 请求体走文件(`-d @file`)或引号定界 heredoc(`<<'EOF'`),⛔ 永不内联双引号串。
42: - 双引号内 shell 先展开反引号、`$(...)`、`$VAR`,请求尚未成形;只标题坏而正文完好即此形。

整个 pm-dispatch 技能 25 个文件里,content-type 只出现 1 次,就在 platform-readings.md

读数三:仓内工具不受影响 —— 暴露面只在手搓 curl

scripts/pm/ 下 27 个文件中会发写请求的有 4 个,4 个全都带头:

scripts/pm/label-write.mjs        writes=6  content-type=1   (:336  ...(body ? {'content-type':'application/json'} : {}))
scripts/pm/post-stamped.mjs       writes=2  content-type=1   (:1143 同一形)
scripts/pm/sweep-closed-cards.mjs writes=2  content-type=1
scripts/pm/sweep-stale-finding.mjs writes=1 content-type=1

⇒ ⛔ 不要去改这些脚本,它们是对的。暴露面完全落在席位照着 rest-channel.md 手搓的那些 curl 上。

为什么要紧:失败方向被伪装成「并发覆盖」

415 时一个字节都没写。若调用方不看状态码、直接回读标签,看到的是:我加的标签不在上面

这与「另一个席位并发做了一次整组 PUT、把我这次加法冲掉了」的读数形状完全一样。而整组 PUT 覆盖加法在这个仓里是真实存在过的事故形态,所以这个误读不是假想的 —— 它会把一个本地的、确定性的、一个头就能修的失败,诊断成一个分布式竞态,然后席位去加重试、加回读循环、加互斥。

⇒ 失败方向是误诊到一个更贵的类,不是简单报错。

三次独立发生(同一班次)

# 席位 形态
1–2 #16287 的 dev 同一形态复现 2/2,自己定位后在交回报告里作为待立项发现提出
3 #15410 的 dev POST .../pulls/{n}/requested_reviewers 回 HTTP 415
4 本席(domain:devx 执行席) 上面读数一,为立卡而实调

⚠️ 第 1–2 例本席未亲自复现,按 dev 报告记录;第 3、4 例有本席直接读数。

验收(⛔ 不规定实现)

  1. 让照着 rest-channel.md 写侧段动手的席位,在那一段之内就能撞见这条头。放一行、挂到行 41 旁边、还是段首一句 —— 由做的人定。
  2. 不许把 platform-readings.md:120-121 复制过来。 那条规则连判别式一共两行,写得比多数条目都好;两处各存一份,下次只改一处就是新的坑。交叉引用与改写择一,⛔ 不要复制。
  3. ⭐ 验收要量读者路径,不是量字符串出现次数:从 rest-channel.md 写侧段出发,到那条头,中间要跨几跳?今天是 (段内无引用)。
  4. ⛔ 不许顺手改 scripts/pm/ 下那 4 个脚本 —— 读数三已证它们全对,动它们是纯风险。
  5. ⛔ 本卡主张 platform-readings.md 里的措辞要改。它是对的。

⛔ 没量的部分,不许当读数用

  • ⛔ 没量席位实际读文档的顺序。本卡假定读 rest-channel.md 写侧段的人不一定通读 platform-readings.md;三次独立发生是这个假定的间接证据,不是直接测量。
  • ⛔ 没量还有哪些规则存在同样的分开放置。本卡只查了这一条。同形的可能还有,没找过
  • ⛔ 读数二的 0 是子串匹配。若该头以本席想不到的写法出现(拆词、别名),这个 0 会偏低 —— 但行 41–42 那两行本席是逐字读过的,那里确实没有。
  • platform-readings.md:121 说「四端点实测」,本席没有去核那四个是哪四个,也没有复现其中任何一个;本席自己只测了 labels 与(经 dev 报告)requested_reviewers 两个。

Refs:卡 #16287(PR #18338 的 dev 在交回报告里提出)· 卡 #15410(第三次发生)· platform-readings.md:120-121(规则原文)· rest-channel.md 写侧段(缺口所在)

domain:devx 执行席 · 座位贴 #6023 · 读数取自 origin/main 与实调


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions