agentleFS
Sirius-JiSirius-Ji/dsh-disciplinary-skills-for-greenhands/agent-execution-hygiene/SKILL.md

agent-execution-hygiene

Skill1 starsChanged 8 days agoMITView on GitHub

Use when your own tool runs start failing for self-inflicted reasons — a script path that does not exist, an empty command output that silently passes, a compile-clean change that raises at runtime, a file written through shell that came out as UTF-16, or a commit that skipped the gate. Fourteen hard rules for a write-verify-run loop. 执行卫生、探针路径、空输出、NameError、提交前门禁、自证闭环、重定向编码、UTF-16、CRLF、cmd 转义、字节层、脱敏验证、擅自改方案.

The file

Files
SKILL.md

SKILL:执行卫生(自证闭环)

适用症状

  • 脚本/命令报"文件不存在",而你以为自己刚写过它(同一轮里反复出现)
  • 把输出重定向到文件后,结果是空的,但流程继续往下走(后续步骤基于空数据做判断)
  • 改动 compile/语法检查绿了,一跑就 NameError / UnboundLocalError
  • 从相邻函数复制代码后,带进了不属于当前作用域的变量
  • 提交之后才发现门禁没跑(或跑的是上一次的结果)
  • 测试脚本本身写错了(路径、参数、断言),却被当成"被测系统有问题"

不适用:环境/权限/网络层面的失败(那属于平台问题,不是执行卫生问题)。

快速判断(30 秒)

按这六问自查,任一答"否"就先修执行链,不要继续往下测:

  1. 我被调用的那个文件,在调用前一刻确认存在了吗?
  2. 重定向/写入的目标目录存在吗?输出非空吗(空 = 失败)?
  3. 我改完之后真的跑过一次吗(不是只看编译/语法)?
  4. 失败信息指向的是调用姿势(路径/参数/环境)还是被测系统?
  5. 这次提交前后各跑过一次门禁吗?
  6. 这次要落盘的字节,和我要的是同一串吗?(看前 4 字节:fffe/feff = 被 UTF-16 坑了)

十九条硬规则

规则 1 · 写 → 验 → 跑

写出被调用文件后,立刻确认它存在(Test-Path / ls / stat),再执行。 write 成功 ≠ 你记住的路径就是它落的路径(子目录、扩展名、拼写都可能错)。

成本:一条 Test-Path(10 ms);收益:省掉一次"找不到文件 → 重写 → 再跑"的循环(分钟级)。

规则 2 · 重定向前建目录;空输出视为失败

  • 写文件/重定向前先确保父目录存在(mkdir -p 语义)。
  • 命令输出为空时必须显式失败:if not result: raise。不要把空字符串当成"没问题"继续跑。
  • 汇总类脚本要打印样本量(处理了 N 条);N=0 也是失败信号。

规则 3 · 编译通过 ≠ 可运行

静态检查不解析名字、不解析运行时分支。改完必须真跑一次目标路径,并检查:

  • 未导入的模块/未定义的名字(NameError 类)
  • 分支里才出现的变量(UnboundLocalError 类)

判据:一个改动如果没有被真正执行过,它的状态就是"未知",不是"完成"。

解析失败 = 一行都不执行。 PowerShell 对整段脚本做词法解析:只要出现一个 不配对的引号、一个不可见字符(例如类名中间混进一个 U+200B)、一行误写的重定向符, 整段脚本就会被拒绝,连第一行都不会跑。而且报错位置常常指向"看起来没问题"的地方。

本会话因此翻车 3 次,三次都差点把"已完成"报上去:

#触发现象
1脚本首行误写成 > -*- coding: utf-8 -*-SyntaxError,整段不执行
2Microsoft.VisualBasic.FileIO.UIOption 中混入不可见字符ParserError,整段不执行
3Write-Output 那行单引号与双引号不配对ParserError,整段不执行

规则:

  1. 脚本越长越要落成文件(.py / .ps1)再执行,别用 -Command 或 here-string 内联;
  2. 落盘后先跑一次语法预检(py_compile / [Parser]::ParseFile),通过了再真跑;
  3. 看到解析错误,第一件事不是改代码,而是核状态:Test-Path 目标文件存在吗? git rev-parse HEAD 提交发生了吗?—— 先确认"上一步真的没执行",再重做。 否则你会把"什么都没做"误报成"做完了",这是比报错更贵的错误。

规则 4 · 复制邻近代码,先扫未定义名

从相邻函数/文件复制一段逻辑时,逐行核对当前作用域里这些名字是否存在。 复制是最高效的写法,也是最容易带进"孤儿变量"的写法(尤其是累加器、计数器、临时索引)。

规则 5 · 一次提交 = 一次门禁

  • 提交前跑门禁(确认要提交的确实是绿的状态)
  • 提交后再跑一次(确认入库的版本本身是绿的)
  • 门禁失败 ⇒ 先回退改动,不要"顺手再改一处"

规则 6 · 测试脚本本身也是代码

它同样需要:能编译、路径正确、断言能在"坏情况下变红"。 空结果、0 样本、全跳过,都必须让测试失败,而不是打印一行空表就通过。

规则 7 · 先怀疑调用姿势,再怀疑被测系统

失败出现时,排查顺序固定为:

  1. 路径 / 文件名 / 扩展名(最常见)
  2. 参数个数、顺序、类型(含"传了对象 A 却按对象 B 用")
  3. 环境前置(开关、配置、依赖是否加载)
  4. 才轮到"被测系统有 bug"

规则 8 · 字节别过文本层(shell 与文本 API 会静默改写它)

症状:写的和读的"看起来一样",字节不一样,而且不报错。本机(中文 Windows + PowerShell + Python)已实测 5 种:

#坑表现替代做法
1PowerShell > / *> / Out-File写 UTF-16LE + BOM ff fe;按 UTF-8 读报 0xff 或得到空。↳ 版本依赖:Windows PowerShell 5.1 默认 UTF-16LE;PowerShell 7 默认 UTF-8 无 BOM(换版本后复现不出来 ≠ 规则过期)cmd /c "… > f",或 Python write_bytes
2Python read_text() / write_text()行尾翻译:读方向所有平台都归一(universal newlines:\r\n→\n),写方向按平台(Win: \n→\r\n;Linux: \n→\n)⇒ 读仓库 LF 文件再写回 ⇒ 与仓库逐字节比必假差异,且不报错read_bytes().decode("utf-8") / write_bytes(b)
3Get-Content / Set-Content(不带 -Encoding)按 GBK 解 UTF-8 ⇒ 中文静默损坏、行数少算[IO.File]::ReadAllText($f,[Text.Encoding]::UTF8)
4cmd /c 里的 ^转义下一个字符:abc^:src/x.py → abc:src/x.py ⇒ git 引用被吃成别的提交传显式哈希;或不经 cmd 直接调
5PowerShell 传含 " / \ 的参数,或 @"…"@ here-string 里塞代码引号/反斜杠被吞、$ 被插值。最阴的一种:吃完引号语法仍成立 —— "5.1" in A 变成 5.1 in A ⇒ 静默改语义(只在 TypeError 或错误结论时才暴露);也可能当场 SyntaxError文本走文件(git commit -F msg.txt);代码写进 .py 文件再跑;非要内联就用单引号 here-string @'…'@(不插值、不吞引号)

判据(一句):只要结果要逐字节或逐字符和原文比,就走 Python 的 bytes 层——不走 shell、不用文本 API。

10 秒自检:open(f,'rb').read(8).hex()(或 Format-Hex -Path f -Count 8)。fffe/feff = 被 UTF-16 坑了;正常 UTF-8 以 2222(""")或 e… 开头。

为什么最容易犯:坑 1/4/5 都不报错,坑 2 的差异"看起来像真差异"。唯一自救:看字节 + 用已知期望值证伪(见下方实战案例)。

工具:tools/byte_gate.py 是我另一个项目里的脚本,本仓库不含它,别照抄路径——要复现就把下面几条命令包成自己的小工具。原意是—— extract(从 git 取基线,不经 shell ⇒ 坑 1/4 物理消失) / head / cmp / eol / --selftest(7 条自检,含 extract 端到端)。

规则 9 · 自定义函数/参数别撞内置名

症状:命令静默失效或结论假绿,但不报错。PowerShell 的命令解析优先级是 Alias > Function > Cmdlet,而 $Args $Input $Error $Host 是自动变量 —— 自定义函数/参数取到这些名字,会被静默抢走。

同一类错误在 2026-11-02 一天内犯了 3 次,三次都是"输出看着正常、结论完全错误":

#写法实际发生了什么
1function Del撞 Remove-Item 别名 ⇒ 4 个删除调用全部落空("已删除"是假的)
2function H撞 Get-History 别名 ⇒ 四个哈希全是 $null,null -eq null 打出"三端一致 = True"
3param([string[]]$Args)撞自动变量 $args ⇒ & git @Args 展开成空参数,git 报用法错误

规则:

  1. 自定义函数/参数禁用单字母、常见英文缩写,以及 Args Input Error Host Matches This 等内置名;命名取完整语义(如 Get-FileSha、$GitArgs)。
  2. 比较型证据必须先做"已知输入 → 非空输出"前置自检,否则 null 会伪装成"相等":

    $h = Get-FileSha $p
    if ($h.Length -ne 64) { throw "hash broken: '$h'" }   # 先证函数是活的
  3. 想知道名字是否已被占用:Get-Alias -Name <名字>(非空 = 撞了), 以及 Get-Variable -Name <名字> -ErrorAction SilentlyContinue(非空 = 撞自动变量)。

规则 10 · 跨进程取文本,必须写明编码

症状:脚本跑到一半突然抛 UnicodeDecodeError,前面已经写盘的步骤不会自动回滚,留下半成品。

真实事故(2026-11-05,tools/release.py 第一次真跑):脚本用 subprocess.run(..., text=True) 去调自己的 bump_handoff.py。Windows 下 text=True 拿系统代码页(GBK)解码子进程输出,而我们的工具一律输出 UTF-8 ⇒ 读到第一个中文就炸。 炸点在父进程解码,子进程其实已经把版本号成功写进文件了。

规则

  1. 任何跨进程取文本的地方,显式写 encoding="utf-8", errors="replace",不依赖平台默认;
  2. Python 脚本开头就 sys.stdout.reconfigure(encoding="utf-8") —— 临时脚本也一样, 一个 ✓ 打进 GBK 控制台就能让整个流程中断;
  3. 父进程既要捕获子进程输出,就要同时想好"子进程炸了怎么还原"(本脚本加了 try/except 还原备份)。

规则 11 · 锚点用行内短串,跨行就按行改

症状:替换/插入脚本报"锚点命中 0 次";更糟的是命中 0 次但脚本仍然报"成功"。

真实事故(2026-11-05,README 批量改写):README 是 CRLF,我拿一段含换行的整句 去做字符串匹配,实际文件里是 \r\n ⇒ 命中 0。同类的还有:按 \n 切行再拼回去, 行尾被整体换掉,哈希和字节数都变。

规则

  1. 锚点只用单行内的短子串(不超过 30 字符、不含换行);
  2. 需要跨行定位时,改成"按行内容找到行号 → 插入",不要拼整句;
  3. 写完独立再读一次盘核对目标串在不在,别信脚本自己打的 ✓。

规则 12 · 改完就写,别中途重读覆盖

症状:脚本每一步都打 ✓,最后打开文件却发现你的改动不在里面。

真实事故(2026-11-05,同一次 README 改写):我在内存里做完了两处替换, 随后为了取行尾风格又 open() 读了一遍磁盘,最后把从磁盘重读的那份写了回去 ⇒ 两处替换被静默丢弃,只有后面插入的内容生效。验证阶段才发现"10份"还在文件里。

规则

  1. 一份内容全程只读一次盘,之后所有变换在内存里做,最后一次写;
  2. 真要重读,就先断言手里的变量与刚读到的字节一致 —— 不一致说明存在两条写路径;
  3. 收尾必须有一步"从磁盘再读一次,断言目标内容真的在"。

规则 13 · 「与源一致」不等于「已脱敏」

症状:发布/脱敏的合格证是"逐个文件与源仓库比对",看起来全绿,实际上有文件从未被任何脱敏规则覆盖。

真实事故(2026-11-06,开源仓发 v1.0.2):27 个发布文件我按两类核对——"与端② 逐字节相同(16 个)" 与"施加替换后相同(7 个)"。_template/AGENTS.md.template 因为与源原样相同,直接被归进第一类, 于是再没人看它的内容。可它里面写着本机真实路径 <你的Conda环境路径>\envs\<env>\python.exe, 而用户早在 v1.0.0 就把它改成了占位符 ⇒ 我按"与源一致"复制回去,等于把已经修好的脱敏回退了。

规则

  1. "已脱敏"只有一个判据:每个要发布的文件都被违禁词扫描器扫过,且 0 命中。 "和源一样"只证明你没改坏它,不证明它干净。
  2. 规则表按文件清单枚举,不按"哪些文件有替换"枚举。不在表里的文件是嫌疑对象,不是安全对象。
  3. 扫两遍:源仓库全部受控文件 + 将要提交的那棵树(git ls-files -s 取 blob 扫,别扫工作区)。
  4. 违禁词里要放安装目录片段(miniconda、dsh-runtimes、盘符 + 常见目录名), 不能只有用户名和项目名——本次就是补上安装目录名之后才现形的。

规则 14 · 别替用户做「更干净」的决定

症状:用户给的是操作步骤,我交回的是"我认为更彻底"的方案;交付时还挺得意,事后要拆掉重做。

真实事故(2026-11-06):用户要求开源仓发 v1.0.2。我判断"旧提交里带本机路径",于是 checkout --orphan 把整个历史换成单一根提交。但用户亲手推上去的 v1.0.0 工作树本来就 0 敏感词;孤儿化收益为 0, 副作用却是把一次普通快进 push 变成必须 --force——等于把安全动作改造成踩红线的动作。 用户原话:「你搞出孤儿分支纯属画蛇添足。」

规则

  1. 用户给了步骤(尤其是编号步骤)就按步骤做。要偏离,先说明偏离点与理由、等人点头, 不要等交付时才补一句"我顺手优化了"。
  2. 判断"要不要动手"时,收益和副作用写在同一段:本次收益=0、副作用=必须强推。 只写收益的方案不叫方案。
  3. 凡是改变历史形状的动作(--orphan、rebase、filter-branch、移动已发出的 tag)默认不做; 它们不可逆,且几乎总能换成加法(新分支 / 新仓库)来做。
  4. 交付前问一句:我交的是他要的那个东西,还是我顺手换的另一个东西?

规则 15 · 绝对路径分「本地」和「发布」两套口径

症状:为了显得"通用",把本地主库里写死的绝对路径全改成「当前工作区」;结果本地脚本、门禁、 AI 的路径认知一起变模糊——而发布端本来就有脱敏这道闸,根本不需要主库先自我阉割。

真实事故(2026-11-06):用户要求清掉全局宪法里的项目硬编码。我把 6 处一律改成「当前工作区根目录」, 连 skill-evolution 的「技能只准写进主库 skills」和 tools/sync-to-runtime.py 的路径说明一起改了。 用户驳回:本地主库要真绝对路径(认知精准、脚本零歧义),脱敏只在发布环节做。

规则

  1. 本地主库(私人工作区):允许并鼓励绝对路径。 脚本、门禁、属性文件里写死真路径是最不容易出错的做法, 不要为了"看起来通用"把它改掉。
  2. 全局纪律与通用技能:禁止写死本机绝对路径。 它们面向所有项目,写死 D:\某项目 会让 别的项目(如 某项目)把交接文件往这个目录里塞;通用文本一律写「当前工作区根目录」。
  3. 开源 / 发布仓:交给脱敏流程,把真路径换成 <你的主库路径>、<你的用户名> 之类占位符。 脱敏是发布侧的职责,不是主库的职责。
  4. 改完必须自查分类:全仓搜盘符绝对路径(grep -rnE '[A-Z]:[\\/]' <目录>),逐条问「这是本项目专有信息, 还是我图省事」——专有信息留在主库 / 工作区自己的 AGENTS.md,通用文档改成相对说法。

规则 16 · 全景式断言必须交代主语

症状:写出「本机只保留一个 Git 仓库」「全机只允许 X」这类句子。写的人心里指的是这个体系, 读的人(另一个 AI、半年后的我)会按字面子目当成整台电脑的铁律去执行。

真实事故(2026-11-06):全局纪律 §七 写「本机只保留一个 Git 仓库,就是当前工作区的 skills\」。 本意是「技能与纪律只有一个主库」,字面却是「这台电脑上不许有任何别的 Git 仓库」—— 去开发 某项目 的人会被这句话直接劝退。用户当场揪出,改成「只保留一个用于管理底层技能与纪律的 Git 主库;其他业务项目(如 某项目)各自拥有独立的 Git 仓库,互不干涉」。

规则

  1. 写「本机 / 全机 / 唯一 / 只允许 / 全部 / 禁止新建」这类全景式断言前,先问一句: 这句话的主语是这个体系,还是整台电脑?
  2. 主语是体系 ⇒ 把范围写进句子里(「用于管理底层技能与纪律的」「本仓库内」「本工作区内」), 不要用一个光秃秃的「本机」。
  3. 主语确实是整机 ⇒ 写明例外面(「其他业务项目各自独立,互不干涉」),并给出反例场景。
  4. 审查他人的全局文档时,这类句子优先级最高——它能静默改变后续所有任务的动作范围。

规则 17 · 安全删除:探针 → 送回收站 → $I 自证

症状:Remove-Item -Recurse -Force 一敲,东西就没了;或者调了 SendToRecycleBin 就报告「已送回收站」—— 而回收站里根本没有它。

真实事故:2026-11-02 workspace-write、2026-11-06 danger-full-access 两次复现静默硬删—— API 返回成功、文件确实消失,$I 条目零新增。别拿沙箱模式当判据,两种模式都翻过车。 本会话我还用 Remove-Item -Force 清过临时脚本,按本条属违规(无探针、无 $I 验证)。

模板(PowerShell,三处都过才算删成功)

$Volume = '<盘符>:\'                                   # 目标所在卷
$Sid    = (whoami /user | Select-String 'S-1-5-21-\S+').Matches.Value
$Bin    = Join-Path (Join-Path $Volume '$Recycle.Bin') $Sid
function Count-I { @(Get-ChildItem -LiteralPath $Bin -Force -Filter '$I*' -ErrorAction SilentlyContinue).Count }

# ① 前置探针:同卷建一次性文件 → 用同一 API 删掉 → 看 $I 是否 +1
$probe  = Join-Path $Volume ('__probe_{0}.tmp' -f [guid]::NewGuid().ToString('N'))
Set-Content -LiteralPath $probe -Value 'probe' -Encoding utf8
$b0 = Count-I
[Microsoft.VisualBasic.FileIO.FileSystem]::DeleteFile($probe, 'OnlyErrorDialogs', 'SendToRecycleBin')
if ((Count-I) - $b0 -ne 1) { throw '回收站不可用:探针未产生 $I,禁止继续删除' }

# ② 真删:逐个路径送回收站,每个都自证
foreach ($t in $Targets) {
    $b = Count-I
    if (Test-Path -LiteralPath $t -PathType Container) {
        [Microsoft.VisualBasic.FileIO.FileSystem]::DeleteDirectory($t, 'OnlyErrorDialogs', 'SendToRecycleBin')
    } else {
        [Microsoft.VisualBasic.FileIO.FileSystem]::DeleteFile($t, 'OnlyErrorDialogs', 'SendToRecycleBin')
    }
    if ((Count-I) - $b -ne 1) { throw "静默硬删:$t 未产生 $I —— 已永久删除,不可恢复" }
}

规则

  1. 没有前置探针就不许调用删除;探针失败一律停手,不许"先删了再看"。
  2. $I 必须数同一卷的(C:\$Recycle.Bin 与 D:\$Recycle.Bin 各管各的);SYSTEM/Administrator 目录无权限, 只认当前用户 SID 那个。路径里含 $,PowerShell 单引号才安全。
  3. 删完的报告必须写清:路径清单、$I 前后计数、是「进了回收站」还是「已永久删除」。
  4. 反射调用时参数数组要用 [object[]]::new(4) 组装,否则 PSObject 包装会让类型转换失败。

规则 18 · 写含 Windows 路径的代码:原始字符串 + 落盘后字节自检

症状:代码里的盘符路径(如 <盘符>:\xxx)被转义吃掉、路径少一个括号、文本里的 % 被当成格式占位符—— 脚本编译能过,运行时才发现目标文件根本不存在,或者写进去的是一串乱码。

本会话踩过的 4 次(全部留下现场)

#写法后果
1"… 100% 对齐 …" % (a, b)% 被当占位符 ⇒ TypeError: not enough arguments,INDEX 整行没写进去
2手写 100% 落盘成 100��文件里出现乱码字符,靠比对才发现
3r"D:\某项目(含子目录"目录名本身以 ) 结尾,少写一个右括号 ⇒ FileNotFoundError(连犯 3 次)
4python - <<'PY' heredocPowerShell 不认,整条命令解析失败,一个动作都没执行

规则

  1. 含 Windows 路径的字符串一律原始字符串 r"<盘符>:\...";不能用 r 时写双反斜杠。 目录名以 )、空格、中文结尾时,写完先 Test-Path 再执行。
  2. 文本里含 % 时禁止用 % 格式化(用拼接或 f-string);% 只用于纯数字占位。
  3. 多行代码落成文件再跑,不要用 shell 的 heredoc / here-string(PS 5.1 会吃引号、改语义)。
  4. 落盘后立刻做字节级自检:
    • 无控制字符(0x00-0x08、0x0b-0x1f,\t/\n/\r 除外);
    • 关键片段在(assert b.count(key) == 1);
    • 行尾风格未变(CRLF 文件仍是纯 CRLF);
    • 前 8 字节不是 BOM 污染。
  5. 写坏过的文件先 diff 再继续:改完后独立再读一次盘,别信脚本自己打的 ✓。

规则 19 · PowerShell 只许写短脚本;复杂逻辑一律 Python

症状:用 PowerShell 写一个几十行的删除/探针脚本,跑起来先吐一堆乱码 + ParserError, 结果是整段脚本一行都没执行,而你以为它跑了。

真实事故(2026-11-06,一次会话内 ≥3 次):

#写法后果
1含中文的 .ps1 用 UTF-8 无 BOM 落盘PS 5.1 按 GBK 解码 ⇒ 中文乱码、引号被撑坏 ⇒ ParserError,探针根本没跑
2.ps1 里写中文路径字面量同上,路径变乱码 ⇒ Test-Path 全 False,误判「文件不存在」
3没 Add-Type 就调 [Microsoft.VisualBasic.FileIO.FileSystem]TypeNotFound,删除函数一行未执行
4python - <<'PY' heredocPowerShell 不认,整条命令解析失败

规则

  1. PowerShell 只写 ≤5 行的短命令(查状态、跑单个程序、读几个属性)。超过 5 行就换 Python。
  2. 复杂自动化、临时探针、任何循环或多步判断,一律用 Python 写文件再跑;Python 3 源码默认按 UTF-8 解析, 没有 PS 5.1 的 GBK 历史包袱。
  3. 必须写 .ps1 且内容含任何中文/非 ASCII 字符时,强制落盘为 UTF-8 with BOM(EF BB BF); 改已有 .ps1 先看前 3 字节,原文件有 BOM 就必须保 BOM、行尾也要保持原样。
  4. .ps1 里不要写中文路径字面量:用 ASCII 通配符(Get-ChildItem -Path '<盘符>:\SomeDir*')、 $PSScriptRoot 或参数传入——中文只出现在运行时值里,不出现在源码里。
  5. 调用 .NET 类型前先 Add-Type -AssemblyName <程序集>(如 Microsoft.VisualBasic)。
  6. 脚本落盘后先语法预检再执行: [System.Management.Automation.Language.Parser]::ParseFile($p,[ref]$null,[ref]$errs); $errs.Count -ne 0 就是没跑起来,别急着看业务结果。

上手核对清单(每次执行前逐条过)

  • 被调用的文件存在?(绝对路径 + 文件名逐字符核对)
  • 目标目录存在?输出非空?
  • 这次改动跑过了吗?
  • 复制来的代码里,有不属于当前作用域的名字吗?
  • 提交前后各跑一次门禁了吗?
  • 测试脚本自己能失败吗(把被测对象弄坏,它会红吗)?
  • 这次落盘的是字节层吗?(要逐字节比 ⇒ Python write_bytes/read_bytes,不用 shell > 与文本 API)
  • 要发布的每个文件都被违禁词扫过吗?("和源一样"不算证据)
  • 我在按用户给的步骤做,还是顺手换了方案?

反模式

  • ❌ "文件应该在那儿" —— 不验证就执行,然后对着 not found 猜原因
  • ❌ 空输出当通过 —— OK= FAIL= 打印为空就继续,后面所有结论都建在沙上
  • ❌ 编译绿就报完成 —— 从未执行过的代码被当成已验证
  • ❌ 一次提交改多处 —— 门禁红了不知道是哪处引起的
  • ❌ 反复重试同一姿势 —— 同一个"找不到文件"连错多次,却不去 ls 一次
  • ❌ 把测试脚本的错算到被测系统头上 —— 探针自己写错,却去改业务代码
  • ❌ 要字节却走 shell —— cmd > f 写出 UTF-16、read_text 归一 CRLF、cmd /c 吃掉 ^:三个都不报错
  • ❌ 基线取错却报"全绿" —— git show 被 ^ 吃成别的提交 ⇒ "改动 0 行"其实是自己比自己
  • ❌ 拿"和源一样"当"已脱敏" —— 没被扫描覆盖的文件不会自己暴露;比对源只能证明"没改坏"
  • ❌ 替用户"优化"步骤 —— 交回来的不是他要的那个东西,返工成本比照做高得多

与相邻 skill 的分工

  • 本 skill:"我的执行动作本身有没有错"(路径、目录、空输出、未定义名、门禁时机)
  • 测量工具会骗人:"我量到的东西是不是真的"(指标、口径、灵敏度)
  • 改动的验证要有证据:"我凭什么说它好了"(证据类型、A/B、回归)
  • 何时该回滚不改:"该不该继续改"(沉没成本、层错判)

实战案例与复盘

以下为当时的一手记录,保留原始术语(项目名 / 模块名 / 改动编号),仅作方法论的实证注解。

  • 规则 1 的代价(同一轮内 ≥8 次):探针脚本多次"写完就报 can't open file"—— p395/content_21_v7.txt(真实位置是 p391/)、probe3.py、probe4.py、realtest.py、 realtest2.py、final.py、verify_final.py、all4.py、check.py。 每次都是"我以为写过 → 直接 python xxx.py → 报错 → 重写"。一次 Test-Path 就能省掉全部 8 次。
  • 规则 2 的代价:python -m src.main --selftest > data\tmp\p448\st.txt ——目录不存在 ⇒ Out-File : 未能找到路径 ⇒ 后续打印出 OK= FAIL= 两个空值,但流程继续。
  • 规则 3 的代价(compile 绿的两次翻车): ① NameError: name 'logging' is not defined(src/main.py 里没有 import logging)⇒ 自检 44/1; ② UnboundLocalError: cannot access local variable 'hit'(从相邻函数复制时留下的累加器)⇒ 四份 PDF 全部 build 失败。
  • 规则 4 的代价:上面 ② 就是复制粘贴带进孤儿变量 hit 的实例。
  • 规则 5 的代价:提交 d16082f 时没跑 selftest(因为重定向目录不存在), 提交后才补跑;虽然结果绿,但"提交一个未验证的版本"本身就是风险。
  • 规则 6 的代价:探针脚本两次把"图数=0"当成"通过"(因为没传渲染开关 config 且没断言样本量)。
  • 规则 7 的代价:tex_of(con, hash) 报 'sqlite3.Connection' object has no attribute 'query' —— 不是被测函数坏,是我传错了对象(该函数要 Database,我给了裸 Connection)。
  • 规则 8 的代价(同一天 3 次 + 一次造出"假通过"): ① git show HEAD:src/main.py > f ⇒ UnicodeDecodeError: byte 0xff in position 0, 在 stripcheck / gate / 上下文 dump 三处各踩一次(都是 PowerShell > 写了 UTF-16); ② cmd /c "git show 88f22a6^:src/main.py > f" —— ^ 被 cmd 吃掉 ⇒ 取到的是修复后的文件 ⇒ 门禁报「改动 0 行、六项全绿」。判据:如果我没改会怎样?答案是 799 个 □ ⇒ 报 0 就说明基线取错了,不是修好了。

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.