docs(os-dev): 自扫字符类补上 DEL,与 #5460 扩面后的门禁扫描面对齐 (#5484) - #5577
Merged
Conversation
`.claude/agents/os-dev.md` 的 Byte discipline 段要求 dev agent 在改动涉及 控制字符时「self-scan beyond the gate」,给出的字符类却停在 #5157 时代的 扫描面(C0 减 tab/LF/CR)。#5460(PR #5479)已把 `check:nul-bytes` 的扫描 面扩到含 DEL(0x7f),该指令未跟 —— 于是它成了门禁的真子集:agent 写下一枚 0x7f,按指令自扫绿,推上去 CI 红,把本可本地一秒发现的问题推迟整个 CI 轮次, 恰好在这条指令唯一被设计来防的场景里给出假绿。 改动一行,字符类与门禁脚本头的 `[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]` 一致。 「同一事实手抄三处」的单源化根治方向留在 #5484 正文,不在本单实施。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GX3sL71LFq8m2usg6VqTSE
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
Author
|
范围外发现(Prime Directive #10,未在本 PR 修):
本 PR 严格只改裁定的那一行字符类,未顺手改散文 —— 该段散文的准确性归 #5579。 Generated by Claude Code Generated by Claude Code |
This was referenced Aug 5, 2026
os-zhuang
marked this pull request as ready for review
August 5, 2026 19:47
os-zhuang
enabled auto-merge
August 5, 2026 19:47
This was referenced Aug 5, 2026
This was referenced Aug 5, 2026
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Aug 6, 2026
…ack-ai#5580) (objectstack-ai#5625) `github.event.pull_request.labels` 是事件触发那一刻的快照。开 PR 后数秒内补 `skip-changeset` 标签,`opened` 事件的 run 看不见它 → 走计数路径 → 无 changeset → 红;而 `rerun_failed_jobs` 复用同一份载荷(pm-dispatch Operational notes 5), 于是这个红 run 按构造无法被重跑成绿。一日三例:objectstack-ai#5467(本门禁自己的修复 PR)、 objectstack-ai#5501、objectstack-ai#5577,每例都要一个人或 agent 停下来「认签名解释掉」。 job 内新增第一个步骤,用 `gh api repos/$REPO/pulls/$PR` 实时读回标签集,产出 `steps.labels.outputs.skip`;其后每个步骤按它决定是否执行。载荷读法按 issue 建议 保留为 fast-path —— 载荷已有标签就整个 job 跳过,常规路径依旧零 runner 成本。 - **容忍方向朝着执行**:标签读不到(API 报错、无 PR 号)判为 `skip=false`,即 照常执行守卫。读不到输入的门什么也没验证,据此发豁免正是 objectstack-ai#4690 反模式(静默 跳过、exit 0、看起来像「无违规」);失败以 `::warning::` 明说,由计数步骤定论。 - **实时读放在 checkout 之前**:标签在位时其后全部步骤跳过,整个 job 只花一次 API 调用 —— 收敛到实时状态比它替掉的那个 stale 红更便宜。 - **精确整行匹配**(`grep -qxF`,here-string 而非管道):被替换的 `contains(数组, 'skip-changeset')` 是数组元素精确匹配,子串匹配会让 `skip-changeset-audit` 这类标签新获豁免;here-string 让 `grep -q` 不进管道,避免 `-q` 首个命中即关闭 管道、写入端吃 SIGPIPE 在 `pipefail` 下把判定翻成 false。 - 保留 fast-path 留下唯一一个反向 stale 格:标签在开 PR 后被**移除**时本 run 仍 短路。该格自愈 —— 移除标签必然触发 `unlabeled` 事件,它起的 run 两处都看不到 标签而照常执行;objectstack-ai#5580 那个方向没有这种救援(`labeled` run 的绿不会清掉 `opened` run 的红)。文件内注释写明了这笔交换。 ⛔ 未动 `BASE_SHA` diff 计数逻辑与 objectstack-ai#5292/PR objectstack-ai#5467 的三段有序失败文案(heredoc 终结符仍在块基缩进);未动其他 job。`allow-major` 步骤的同款载荷读法按边界留在 原样 —— RC pre-mode 期间休眠(`check-changeset-no-major.mjs` 整体让位),已记为 objectstack-ai#5620。 验证:`check:workflow-status-functions` 与 `check:nul-bytes`(含各自 self-test) 全绿;从 YAML 抽出该步骤真实脚本,以 stub `gh` 在 `bash -e` 与 `bash -eo pipefail` 两种方言下跑 7 场景 × 2 = 14 例全通过(载荷 stale/标签实时在位、无标签、空标签、 API 失败、无 PR 号、近似标签名、401 个标签的 pipefail 压力);另建前后决策真值表, 7 格中仅「载荷无标签 + 实时有标签」的首 run 与其重跑两格改变(enforce → exempt), 与事前预测一致。 Fixes objectstack-ai#5580 Claude-Session: https://claude.ai/code/session_01GX3sL71LFq8m2usg6VqTSE Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Aug 6, 2026
…objectstack-ai#5579) (objectstack-ai#5642) 该段给出的唯一理由是「One raw control byte makes grep treat the whole file as binary: zero matches, no signal」——而这条只对 NUL 成立。在容器内独立复现(样本用 printf 生成,未粘贴裸字节;GNU grep 3.11 + ripgrep 14.1.0): U+0000 grep: binary file matches rg: binary file matches (found "\0" ...) U+0001 grep: 2:searchable line rg: 2:searchable line U+007F grep: 2:searchable line rg: 2:searchable line 即门禁扫描面里除 NUL 之外的每个字节(含 objectstack-ai#5460 纳入门禁、objectstack-ai#5577 补进自扫字符类的 DEL)都不会让文件被当成二进制。危害只写这一条的后果不是文字不精确:agent 写出一枚 非 NUL 控制字节、自扫命中后去核对指令,会发现唯一被陈述的判据不成立,从而把门禁的红 判成误报。 `scripts/check-nul-bytes.mjs` 脚本头早就把两侧分开论证好了(objectstack-ai#5157 段),本次把散文 口径搬过去对齐: - binary-file / zero-matches 那条点名 NUL,并标明是实测结论; - 其余扫描面字节引脚本头写清的三条:渲染为空(代码对每个读者说谎)、两种拼写互不 命中(文件里是字节,不是你会去搜的转义文本)、事故源不挑字节值; - 补一句直接堵住上述推理:「不是 NUL、grep 还能搜到」永远不构成把门禁红或自扫命中 读成误报的理由; - 危害论证指向脚本头「引用它,不要重新推导」,不在此处再抄一遍论证细节。 顺带修同段两处陈旧: - 「this repo has paid four times」的硬编码计数改为免计数措辞——该族已多于四例, objectstack-ai#5624 刚因同样的漂移把台账里的 sibling 计数改成不含数字的表达; - 「a `0x01` that `check:nul-bytes` does not scan for (objectstack-ai#5157)」的现在时已错:objectstack-ai#5157 正是把该字节纳入扫描面的那一单,改为过去时的事实句。 未做(留档而非顺手扩面):单源化——让字符类与危害论证不再手抄多处——是 objectstack-ai#5484 正文 留下的方向,本 PR 只修散文口径,不动 `scripts/check-nul-bytes.mjs`、不动 objectstack-ai#5577 刚 补的自扫字符类、不动 objectstack-ai#5630 刚加的 Toolchain traps 条目。 纪律:全程未向任何文件写入裸控制字节,散文沿用该文件与脚本头既有的 `0x01`/`0x7f` 十六进制写法(不含反斜杠转义,不会被编辑工具 materialise)。 `node scripts/check-nul-bytes.mjs` 绿;改动文件自扫 `grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]'` 无命中;`cat -A` / `od -c` 复核新增 行无意外字节。 `.claude/` 文档-only,无用户可见变更,走 skip-changeset 标签路线。 Fixes objectstack-ai#5579 Claude-Session: https://claude.ai/code/session_01GX3sL71LFq8m2usg6VqTSE Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Aug 6, 2026
…ai#5680) 字符类此前在两处手抄:IS_SCANNED 表(门禁真正扫的东西)与 os-dev.md 自扫命令行。该族漂移当日已付两次(objectstack-ai#5577 自扫类缺 \x7f、objectstack-ai#5579 危害论证 只搬了对 NUL 成立的那条)。 scannedCharClass() 从表派生出 PCRE 字符类,--self-test 断言登记在 CHAR_CLASS_REFERENCES 里的每处引用与之逐字节相等;提取不到也红。 不做散文 codegen:引用文件是手写 prompt,断言只拒绝它们「错」,并在 失败信息里给出该粘贴的确切字符串。 Co-authored-by: Claude <noreply@anthropic.com>
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 #5484
问题
.claude/agents/os-dev.md的 Byte discipline 段要求 dev agent 在改动「提及控制字符」时,除了跑门禁还要逐字节自扫,理由原话是 self-scan beyond the gate —— the gate's blind spots are exactly where these bytes hide。但它给出的字符类停在 #5157 时代的扫描面(ASCII 控制字符减 tab/LF/CR,且只覆盖 C0 连续区间)。#5460(PR #5479)已把门禁
scripts/check-nul-bytes.mjs的扫描面扩到含 DEL(U+007F,该字节不属于 C0,独自坐在 ASCII 表末端,正因如此被区间写法漏掉),这条指令没跟 —— 于是它成了门禁的真子集:check:nul-bytes→ 红。即这条指令在它唯一被设计来防的场景里给出假绿,把本可本地一秒发现的问题推迟整个 CI 轮次。
改动
一行:该字符类补上
\x7f,与门禁脚本头现行表述一致([\x00-\x08\x0b\x0c\x0e-\x1f\x7f])。周边散文未陈述扫描面范围,无需同步;文件面仅.claude/agents/os-dev.md,未触scripts/与packages/lint。「同一事实手抄三处(门禁脚本 / 历史 changeset / 本指令)、靠人肉同步」的单源化根治方向,按裁定留在 #5484 正文,不在本单实施。另两处均正确:门禁脚本 #5460 已更新;两份历史 changeset 凝固在各自当时的语义。
验证
本改动无可执行面、无单测面(纯 agent 指令文本),验证由覆盖
.claude/的两道门禁 + 逐字节自扫构成。写这条修改本身就是 #4890 一族的事故源现场(该族多次事故全发生在「写关于该字节的内容」时),因此自扫用的是扩面后的字符类。字节级确认改动写入的是转义文本而非真字节(
od -c该行):\ x 7 f四个字符,行内无177八进制字节。反向验证(方向先判后跑)
预判三条腿:同一枚真 DEL 字节的样本上,旧字符类绿(即 issue 描述的假绿)、新字符类红、门禁红。实跑与预判一致:
od -c显示case ' 177 ':(以printf '\177'生成,未粘贴裸字节);[\x00-\x08\x0b\x0c\x0e-\x1f]→ exit=1,无匹配 = 假绿;--self-test(本 PR 已跑,48 断言全绿)自带 DEL(0x7f)在 C0 扫描面之外:login.ts / register.ts 各有一枚裸 0x7f 当 Backspace 键值,与刚转义的 0x03 同处一个 switch #5460 的 DEL 样本断言,包括'#5460: a raw 0x7f Backspace literal must be flagged'。三条腿合起来即「指令与门禁在该字节类上等价」——issue 描述的假绿窗口关闭。
changeset
.claude/内部 agent 指令文本,不释放任何包 → 按 pr-automation.yml 的 route 2 走skip-changeset标签(先例 PR #5501),不加空 frontmatter changeset(#4898)。🤖 Generated with Claude Code
https://claude.ai/code/session_01GX3sL71LFq8m2usg6VqTSE
Generated by Claude Code