@routerhub/agent-rules 1.5.217 → 1.5.219

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.base.md CHANGED
@@ -280,7 +280,7 @@ agent-rules 生成的规则文件分两层,行为与归属不同,评审/发
280
280
 
281
281
  - ⚠️ **核心认知:报告里的每一条主张——A/B 截图、前后对比、那个数字——都是你的结论,不是读者能自己检查的东西。** 他看完手里只有两个选项:信,或者不信。**一份只能「信或不信」的报告,等于把「可核实」偷偷降级成了「请相信我」。** 判据只有一句话:**把报告发给他、你不说任何一句话,他能不能自己把这条主张跑一遍、亲眼看到同样的结果?** 不能 = 这条主张没交付。
282
282
  - **类比:体检报告不能只印一句「各项指标正常」就让人签字——得把每项指标的数值、参考范围、以及「你自己去哪个科室能复查这一项」都写上,家属才可能拿着它去另一家医院复核。只给结论的报告是「请相信我」,不是「你可以自己看」。**
283
- - ⚠️ **硬性要求:每一条主张旁边,都要挂一份「你自己怎么复核这一条」的操作流程。** 适用范围 = 每条需求原话对应的实现、每个「已修复 / 已生效」的断言、每组前后对比。流程由**逐步编号的操作**组成,每步三件套缺一不可:
283
+ - ⚠️ **硬性要求:每一条主张旁边,都要挂一份「你自己怎么复核这一条」的操作流程。** 适用范围 = 每条需求原话对应的实现、每个「已修复 / 已生效」的断言、每组前后对比,**外加报告里每个「请你自己去某环境跑一下 / 确认一下」的开放项**(待确认项、前置准备、动手环节——它们不是「主张」,作者自己也没结论,最容易只丢一行片段,因此同样必须给到从零可跑的完整流程,见「⚠️ 截图规范 → HTML 文档截图与 curl 命令规范」的「片段即未执行」)。流程由**逐步编号的操作**组成,每步三件套缺一不可:
284
284
  1. **可复制粘贴的完整命令 / 操作**:参数写全,**禁止用 `...` 或占位符省略**(呼应「⚠️ 截图规范」的命令完整性要求);且**不得引用只有你本机才有的东西**(`localhost`、本机路径、容器名、未提交的文件、正在跑的本机服务)——否则读者一跑就断(呼应「⚠️ 验收环境铁律」)。
285
285
  2. **预期结果,对错两种都要给**:不只写「应该看到 X」(✅),还要写「**看到 Y 就是这条主张不成立**」(❌)。⚠️ **这是全篇最关键的一项**:只给成功输出,读者跑出任何别的东西时都无从判断是「我环境不对」还是「你说的不对」,最后又退回「信或不信」——**给了他反例,他才能自己宣判。**
286
286
  3. **这一步证明了什么**(一句话点明证据含义),让读者不必读完整篇才知道自己在验什么。
@@ -662,6 +662,16 @@ agent-rules 生成的规则文件分两层,行为与归属不同,评审/发
662
662
  - ⚠️ **文档中给出的每条命令/脚本,写入前必须亲自在终端实际执行验证过,确认确实可行后才能写入。** 执行失败的命令一律不得写入文档,禁止凭推断「应该能跑」就写进文档——推断得出的结论不能作为生成依据,必须实际测试过才能下结论。
663
663
  - ⚠️ **不止命令——文档里写的每一个操作步骤,都必须亲自真实走过一遍,并把这一次的执行现场截下来。** 「命令能跑通」和「跑出来长什么样」是两件事:读者要的是照着做出同一个结果,而你只有亲手做过,才知道中间会弹什么、输出长什么样、哪一步最容易看错。**执行过程本身就是配图的来源**——每写一步,手里就得有一步对应的现场截图(带箭头标注,圈出这一步的输出里哪一行是关键、它证明了什么);**禁止事后凭印象补画,更禁止拿推断出的「应该会输出什么」当截图**。**没执行过就别写这一步**:没跑过就写进文档的步骤,轻则读者照着一路卡住,重则把错的做法教给了人。**自查一句话:文档里每一个「你来操作一下」的步骤,我能不能指出它对应的是我哪一次真实执行时截的图?指不出 = 这一步还不该出现在文档里。**
664
664
  - **由来(真实案例)**:一份实现文档里写「第 1 次返回 `UPDATE 1`、第 2 次返回 `UPDATE 0`,证明幂等」——作者确实跑过、也确实知道哪行是哪行,但两行输出只差一个数字、psql 一屏几乎一模一样,读者照着敲完对不上号,只能回头问「我执行了咋没看出有啥不同」。**根因不是命令不对,而是少了那张把「哪一行」圈出来的现场截图**——执行过不等于交付清楚了(可辨识性要求见「⚠️ 可视化验证铁律」分步操作教学演示第 6 条)。
665
+ - ⚠️ **「片段即未执行」——凡是请读者去做的动作,必须给一段「从零跑到结论」的完整流程,禁止只丢一行片段。** 适用范围:文档里所有「请你去某环境跑一下 / 去确认一下 / 去做一下」的地方——**待确认项、开放问题、前置准备、复核步骤里的动手环节**(与相邻铁律的分工见本条末)。**这类残缺有一个共同的诊断指纹:只给一行片段 = 作者没真跑过。** 真跑过的人写不出这种片段——他必然先起了代理、先确认了库名、先把 `<某个账号>` 换成了真值,这些「先做的事」都在他手上,顺手就写下来了;**只有没跑过的人,才会把「凭印象记得的那条核心语句」当成读者需要的全部**。所以看到一行片段,先别急着补字,先去把它跑一遍——缺什么,跑一遍自然就浮出来了。
666
+ - **一行片段的四类典型残缺(对照自查,命中任一项即补齐):**
667
+ 1. **位置状语没有落点**——「在 ha-testing 上执行」。ha-testing 是哪个实例(全名 `horizonapi-485401:asia-southeast1:ha-testing`)?怎么连上去(起代理的完整命令)?连哪个库(`horizon_api`,不是默认的 `postgres`)?**只写「在 X 上」,读者到达不了 X。**
668
+ 2. **占位符没换真值**——`has_table_privilege('<网关运行账号>', ...)` 里的 `<网关运行账号>`。读者既不知道该填什么,也不知道去哪儿查(真值是 `970360445295-compute@developer`,即 Cloud Run 的运行账号)。**这不是「敏感值抽成占位符」式的谨慎,而是信息缺了一半**——占位符能成立的前提是「读者自己查得到真值」(见下方「敏感值内嵌真实值」)。
669
+ 3. **判读标准缺失**——跑出 `t` 是好事还是坏事?`f` 呢?**不给对错两种结果,读者拿到 `t` 也不知道该松口气还是该报警。**
670
+ 4. **前置条件没交代**——代理没起、gcloud 没登录、没有实例访问权……读者卡在第一步,却不知道卡在哪。
671
+ - ⚠️ **澄清一个常见误解:给本机地址(如 `127.0.0.1:5433`)本身不算违规,缺的是「怎么把它建起来」。** 「⚠️ 验收环境铁律」禁止的是**读者自己造不出来**的东西(你的 dev server、你未提交的文件、你正在跑的本机服务);而 Cloud SQL 代理这类**读者照着命令就能在自己机器上建出同一个**的本机地址是可以给的:把 `cloud-sql-proxy --port 5433 --auto-iam-authn horizonapi-485401:asia-southeast1:ha-testing` 给全,读者起自己的代理、连自己的 5433,拿到的是同一个库。**判断标准:读者照这几行,能不能在自己机器上把那个地址造出来?能 → 可以给(且必须给全建它的命令);不能 → 必须换成公共可达的地址。**
672
+ - **落笔自查一句话:把这几步原样发给一个没参与过这个项目的人,他能不能不问你任何一句话、从头跑到底,并自己判断结论对错?** 不能 → 缺的是上面四类里的哪一类,补齐再写。
673
+ - **由来(真实案例)**:一份实现文档的待确认项里写「授权是否生效 | 在 ha-testing 上执行 `SELECT has_table_privilege('<网关运行账号>','provider_accounts','UPDATE');`」——**四类缺口全中**:`<网关运行账号>` 没填真值、「在 ha-testing 上」没说怎么连、没说是 `horizon_api` 库、没说 `t` / `f` 各代表什么。读者照着做,第一步就停在「我怎么连上 ha-testing」,只能回来问作者。**作者亲手跑过的那一版**(还是同一条 SQL,只是补齐)是:① 起代理 `cloud-sql-proxy --port 5433 --auto-iam-authn horizonapi-485401:asia-southeast1:ha-testing`(已在跑则跳过)→ ② 连库执行 `psql "host=127.0.0.1 port=5433 dbname=horizon_api user=baikaifa666@gmail.com sslmode=disable" -X -c "SELECT has_table_privilege('970360445295-compute@developer','provider_accounts','UPDATE');"` → ③ 判读:返回 `t` = 授权已生效,网关可以 UPDATE 这张表;返回 `f` = 未生效,网关写这张表会报 `permission denied for table provider_accounts (SQLSTATE 42501)`。**同一件事,前者读者只能回来问,后者读者自己就能得出结论。**
674
+ - ⚠️ **与相邻铁律的分工**:**本条管「请你去做一下」这类动手指令**(待确认项 / 开放问题 / 前置准备 / 动手环节)——它们本身不是「主张」,不在「⚠️ 主张自带复核流程铁律」的适用范围内,是最容易漏的一类;**「⚠️ 主张自带复核流程铁律」管「主张旁边要挂复核流程」**(读者能不能自己验一条断言);**「⚠️ 验收环境铁律」管「给出去的东西别人打不打得开 / 跑不跑得起来」**。三者叠加,读者才既知道「去哪儿」、也知道「到了之后怎么做完、怎么判对错」。**复核流程里那一步如果本身是「在 X 上跑 Y」,同样要按本条给到从零可跑。**
665
675
 
666
676
  ## Go 规则
667
677
 
package/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  所有对 @routerhub/agent-rules 的重大更改都会记录在这个文件中。
4
4
 
5
+ ## [1.5.219] - 2026-09-16
6
+
7
+ ### Changed
8
+
9
+ - **`loop-review` 取消「最大轮数(默认 5 轮 / 深度循环 8 轮)」上限——循环结束只由「性质」决定,不再由「跑了几轮」决定**:起因是用户提出「循环没必要设这个上限的数,按『必须修复的修复就行,其他不必须修复的走 Won't fix』就行」。原规则把「达到最大轮数仍有值得修的问题 → 停止循环,把剩余问题交给用户决定」当兜底,但这条兜底与循环真正的收敛机制是**打架**的:循环的收敛出口是「本轮没有任何必须修的新问题」,而 bot 每轮全量重读 diff、总能再挖出新层次(上一轮漏报的角落 / 修复引入的回归 / 新代码自带的新毛病)——所以「第 N 轮还有必须修的问题」完全可能只是**真的还有必须修的问题**,此时按轮数停下,等于把仍然必须修的问题挂着交出去;反过来,数字上限还会诱导一条更危险的歪路:为了「跑够轮数就收工」,把真问题降级成口味问题 Won't fix 掉。
10
+ - **现在的判据**:`skills/loop-review/SKILL.md` 步骤 6 删除「达到最大轮数」条目并显式写明「**循环不设轮数上限——结束只看『这一轮有没有必须修的问题』,不看『已经跑了几轮』**」;步骤 7 开头「循环结束或达到轮数上限后」改为「循环结束后」;「循环终止条件」表格删掉「达到最大轮数」一行;铁律把原「必须设最大轮数**和等待超时**」拆开——轮数上限取消,**等待 bot 出新 review 的 15 分钟超时保留**(它管的是「不要干等」,不是循环上限)。
11
+ - **同时加了一条反向约束**:禁止为了尽快收工把真问题降级成口味问题 Won't fix 掉——数字上限一去,「必须修的都修完」就成了唯一的收敛出口,这条歪路必须堵住。
12
+ - **为什么去掉上限后不会无限循环**:真正会无限冒的只是「口味 / 过度设计」那类,而它们每轮都被 Won't fix 回复 + 落盘到 `decisions/` 挡住、进不了「必须修」,所以「必须修的清零」这一条件迟早成立、且不会被轮数提前打断。
13
+
5
14
  ## [1.5.216] - 2026-09-14
6
15
 
7
16
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@routerhub/agent-rules",
3
- "version": "1.5.217",
3
+ "version": "1.5.219",
4
4
  "description": "Shared Copilot agent rules and guidelines for RouterHub projects",
5
5
  "main": "AGENTS.base.md",
6
6
  "bin": {
package/rules/global.md CHANGED
@@ -280,7 +280,7 @@ agent-rules 生成的规则文件分两层,行为与归属不同,评审/发
280
280
 
281
281
  - ⚠️ **核心认知:报告里的每一条主张——A/B 截图、前后对比、那个数字——都是你的结论,不是读者能自己检查的东西。** 他看完手里只有两个选项:信,或者不信。**一份只能「信或不信」的报告,等于把「可核实」偷偷降级成了「请相信我」。** 判据只有一句话:**把报告发给他、你不说任何一句话,他能不能自己把这条主张跑一遍、亲眼看到同样的结果?** 不能 = 这条主张没交付。
282
282
  - **类比:体检报告不能只印一句「各项指标正常」就让人签字——得把每项指标的数值、参考范围、以及「你自己去哪个科室能复查这一项」都写上,家属才可能拿着它去另一家医院复核。只给结论的报告是「请相信我」,不是「你可以自己看」。**
283
- - ⚠️ **硬性要求:每一条主张旁边,都要挂一份「你自己怎么复核这一条」的操作流程。** 适用范围 = 每条需求原话对应的实现、每个「已修复 / 已生效」的断言、每组前后对比。流程由**逐步编号的操作**组成,每步三件套缺一不可:
283
+ - ⚠️ **硬性要求:每一条主张旁边,都要挂一份「你自己怎么复核这一条」的操作流程。** 适用范围 = 每条需求原话对应的实现、每个「已修复 / 已生效」的断言、每组前后对比,**外加报告里每个「请你自己去某环境跑一下 / 确认一下」的开放项**(待确认项、前置准备、动手环节——它们不是「主张」,作者自己也没结论,最容易只丢一行片段,因此同样必须给到从零可跑的完整流程,见「⚠️ 截图规范 → HTML 文档截图与 curl 命令规范」的「片段即未执行」)。流程由**逐步编号的操作**组成,每步三件套缺一不可:
284
284
  1. **可复制粘贴的完整命令 / 操作**:参数写全,**禁止用 `...` 或占位符省略**(呼应「⚠️ 截图规范」的命令完整性要求);且**不得引用只有你本机才有的东西**(`localhost`、本机路径、容器名、未提交的文件、正在跑的本机服务)——否则读者一跑就断(呼应「⚠️ 验收环境铁律」)。
285
285
  2. **预期结果,对错两种都要给**:不只写「应该看到 X」(✅),还要写「**看到 Y 就是这条主张不成立**」(❌)。⚠️ **这是全篇最关键的一项**:只给成功输出,读者跑出任何别的东西时都无从判断是「我环境不对」还是「你说的不对」,最后又退回「信或不信」——**给了他反例,他才能自己宣判。**
286
286
  3. **这一步证明了什么**(一句话点明证据含义),让读者不必读完整篇才知道自己在验什么。
@@ -662,6 +662,16 @@ agent-rules 生成的规则文件分两层,行为与归属不同,评审/发
662
662
  - ⚠️ **文档中给出的每条命令/脚本,写入前必须亲自在终端实际执行验证过,确认确实可行后才能写入。** 执行失败的命令一律不得写入文档,禁止凭推断「应该能跑」就写进文档——推断得出的结论不能作为生成依据,必须实际测试过才能下结论。
663
663
  - ⚠️ **不止命令——文档里写的每一个操作步骤,都必须亲自真实走过一遍,并把这一次的执行现场截下来。** 「命令能跑通」和「跑出来长什么样」是两件事:读者要的是照着做出同一个结果,而你只有亲手做过,才知道中间会弹什么、输出长什么样、哪一步最容易看错。**执行过程本身就是配图的来源**——每写一步,手里就得有一步对应的现场截图(带箭头标注,圈出这一步的输出里哪一行是关键、它证明了什么);**禁止事后凭印象补画,更禁止拿推断出的「应该会输出什么」当截图**。**没执行过就别写这一步**:没跑过就写进文档的步骤,轻则读者照着一路卡住,重则把错的做法教给了人。**自查一句话:文档里每一个「你来操作一下」的步骤,我能不能指出它对应的是我哪一次真实执行时截的图?指不出 = 这一步还不该出现在文档里。**
664
664
  - **由来(真实案例)**:一份实现文档里写「第 1 次返回 `UPDATE 1`、第 2 次返回 `UPDATE 0`,证明幂等」——作者确实跑过、也确实知道哪行是哪行,但两行输出只差一个数字、psql 一屏几乎一模一样,读者照着敲完对不上号,只能回头问「我执行了咋没看出有啥不同」。**根因不是命令不对,而是少了那张把「哪一行」圈出来的现场截图**——执行过不等于交付清楚了(可辨识性要求见「⚠️ 可视化验证铁律」分步操作教学演示第 6 条)。
665
+ - ⚠️ **「片段即未执行」——凡是请读者去做的动作,必须给一段「从零跑到结论」的完整流程,禁止只丢一行片段。** 适用范围:文档里所有「请你去某环境跑一下 / 去确认一下 / 去做一下」的地方——**待确认项、开放问题、前置准备、复核步骤里的动手环节**(与相邻铁律的分工见本条末)。**这类残缺有一个共同的诊断指纹:只给一行片段 = 作者没真跑过。** 真跑过的人写不出这种片段——他必然先起了代理、先确认了库名、先把 `<某个账号>` 换成了真值,这些「先做的事」都在他手上,顺手就写下来了;**只有没跑过的人,才会把「凭印象记得的那条核心语句」当成读者需要的全部**。所以看到一行片段,先别急着补字,先去把它跑一遍——缺什么,跑一遍自然就浮出来了。
666
+ - **一行片段的四类典型残缺(对照自查,命中任一项即补齐):**
667
+ 1. **位置状语没有落点**——「在 ha-testing 上执行」。ha-testing 是哪个实例(全名 `horizonapi-485401:asia-southeast1:ha-testing`)?怎么连上去(起代理的完整命令)?连哪个库(`horizon_api`,不是默认的 `postgres`)?**只写「在 X 上」,读者到达不了 X。**
668
+ 2. **占位符没换真值**——`has_table_privilege('<网关运行账号>', ...)` 里的 `<网关运行账号>`。读者既不知道该填什么,也不知道去哪儿查(真值是 `970360445295-compute@developer`,即 Cloud Run 的运行账号)。**这不是「敏感值抽成占位符」式的谨慎,而是信息缺了一半**——占位符能成立的前提是「读者自己查得到真值」(见下方「敏感值内嵌真实值」)。
669
+ 3. **判读标准缺失**——跑出 `t` 是好事还是坏事?`f` 呢?**不给对错两种结果,读者拿到 `t` 也不知道该松口气还是该报警。**
670
+ 4. **前置条件没交代**——代理没起、gcloud 没登录、没有实例访问权……读者卡在第一步,却不知道卡在哪。
671
+ - ⚠️ **澄清一个常见误解:给本机地址(如 `127.0.0.1:5433`)本身不算违规,缺的是「怎么把它建起来」。** 「⚠️ 验收环境铁律」禁止的是**读者自己造不出来**的东西(你的 dev server、你未提交的文件、你正在跑的本机服务);而 Cloud SQL 代理这类**读者照着命令就能在自己机器上建出同一个**的本机地址是可以给的:把 `cloud-sql-proxy --port 5433 --auto-iam-authn horizonapi-485401:asia-southeast1:ha-testing` 给全,读者起自己的代理、连自己的 5433,拿到的是同一个库。**判断标准:读者照这几行,能不能在自己机器上把那个地址造出来?能 → 可以给(且必须给全建它的命令);不能 → 必须换成公共可达的地址。**
672
+ - **落笔自查一句话:把这几步原样发给一个没参与过这个项目的人,他能不能不问你任何一句话、从头跑到底,并自己判断结论对错?** 不能 → 缺的是上面四类里的哪一类,补齐再写。
673
+ - **由来(真实案例)**:一份实现文档的待确认项里写「授权是否生效 | 在 ha-testing 上执行 `SELECT has_table_privilege('<网关运行账号>','provider_accounts','UPDATE');`」——**四类缺口全中**:`<网关运行账号>` 没填真值、「在 ha-testing 上」没说怎么连、没说是 `horizon_api` 库、没说 `t` / `f` 各代表什么。读者照着做,第一步就停在「我怎么连上 ha-testing」,只能回来问作者。**作者亲手跑过的那一版**(还是同一条 SQL,只是补齐)是:① 起代理 `cloud-sql-proxy --port 5433 --auto-iam-authn horizonapi-485401:asia-southeast1:ha-testing`(已在跑则跳过)→ ② 连库执行 `psql "host=127.0.0.1 port=5433 dbname=horizon_api user=baikaifa666@gmail.com sslmode=disable" -X -c "SELECT has_table_privilege('970360445295-compute@developer','provider_accounts','UPDATE');"` → ③ 判读:返回 `t` = 授权已生效,网关可以 UPDATE 这张表;返回 `f` = 未生效,网关写这张表会报 `permission denied for table provider_accounts (SQLSTATE 42501)`。**同一件事,前者读者只能回来问,后者读者自己就能得出结论。**
674
+ - ⚠️ **与相邻铁律的分工**:**本条管「请你去做一下」这类动手指令**(待确认项 / 开放问题 / 前置准备 / 动手环节)——它们本身不是「主张」,不在「⚠️ 主张自带复核流程铁律」的适用范围内,是最容易漏的一类;**「⚠️ 主张自带复核流程铁律」管「主张旁边要挂复核流程」**(读者能不能自己验一条断言);**「⚠️ 验收环境铁律」管「给出去的东西别人打不打得开 / 跑不跑得起来」**。三者叠加,读者才既知道「去哪儿」、也知道「到了之后怎么做完、怎么判对错」。**复核流程里那一步如果本身是「在 X 上跑 Y」,同样要按本条给到从零可跑。**
665
675
 
666
676
  ## Go 规则
667
677
 
@@ -174,11 +174,14 @@ description: >-
174
174
  - ⚠️ 步骤之间用编号衔接(步骤 1 → 步骤 2 → …),说明文字必须一图一句、逐张不同,禁止用一句套话覆盖所有步骤的截图
175
175
  - ⚠️ **每个步骤都必须是「我真跑过的那一次」**:写入文档前,这一步必须亲自真实执行一遍,且**这次执行的现场截图就是该步骤配图的唯一来源**——禁止事后凭印象补画,禁止拿推断出的「应该会输出什么」当截图。**没执行过就别写这一步**:没跑过就写进文档的步骤,轻则读者照着一路卡住,重则把错的做法教给了人。**自查:文档里每个「你来操作一下」的步骤,我能不能指出它对应哪一次真实执行时截的图?指不出 = 不该出现在文档里。**(规则见 `AGENTS.base.md`「HTML 文档截图与 curl 命令规范」)
176
176
  - ⚠️ **「差别可辨识」自检——读者照着做完,能看出你说的那个现象吗?** 凡步骤涉及**对比 / 变化 / 前后差异**(两次执行、修复前后、A/B 两组输出),必须自问:读者照做之后,能不能一眼看出这个差异?**看不出 → 文字讲不清,必须在现场截图上用箭头把「哪一行 / 哪个数字 / 哪一列」变了、变成了什么直接圈出来。** 最容易翻车的是**肉眼看几乎一样的对比**:如 `UPDATE 1` 与 `UPDATE 0` 只差一个数字、同一段命令两次执行输出几乎雷同、两次探测返回同一状态——作者自己清楚哪行对应哪句,读者对着一屏几乎相同的输出根本对不上号,只能回头问「我执行了咋没看出有啥不同」。**判据是读者,不是作者——作者知道 ≠ 读者看得出。**(规则见 `AGENTS.base.md`「⚠️ 可视化验证铁律」分步操作教学演示第 6 条)
177
+ - ⚠️ **「片段即未执行」——凡是请读者去做的动作,必须给一段「从零跑到结论」的完整流程,禁止只丢一行片段。** 适用范围:文档里所有「请你去某环境跑一下 / 去确认一下」的地方——**待确认项、开放问题、前置准备**(这些不是「主张」、作者自己也没结论,最容易顺手写一行就过去,恰恰是读者最需要「具体咋弄」的地方)。**诊断指纹:只给一行片段 = 作者没真跑过**——真跑过的人必然先起了代理、先确认了库名、先把占位符换成了真值,这些「先做的事」顺手就写下来了。四类典型残缺(命中任一即补齐):① **位置状语没有落点**(「在 ha-testing 上执行」→ 实例全名是什么、怎么连上去、连哪个库);② **占位符没换真值**(`<网关运行账号>` 该填 `970360445295-compute@developer`);③ **判读标准缺失**(返回 `t` 说明什么、`f` 说明什么);④ **前置条件没交代**(代理没起、gcloud 没登录、没有访问权)。**自查:把这几步原样发给一个没参与过这个项目的人,他能不能不问你任何一句话、从头跑到底并自己判断对错?**(规则见 `AGENTS.base.md`「HTML 文档截图与 curl 命令规范」的「片段即未执行」)
178
+ - ⚠️ **给本机地址(如 `127.0.0.1:5433`)本身不算违规,缺的是「怎么把它建起来」。** 「验收环境铁律」禁止的是**读者自己造不出来**的东西(你的 dev server、未提交的文件、正在跑的本机服务);Cloud SQL 代理这类**读者照着命令就能在自己机器上建出同一个**的本机地址可以给,但建它的命令必须给全(`cloud-sql-proxy --port 5433 --auto-iam-authn horizonapi-485401:asia-southeast1:ha-testing`)。**判断标准:读者照这几行能不能在自己机器上造出那个地址?能 → 可以给;不能 → 换成公共可达的地址。**
177
179
  - 截图统一用 base64 data URI 内嵌,禁止引用外部图片文件
178
180
 
179
181
  ### 命令与复制按钮
180
182
 
181
183
  - ⚠️ 文档中出现的每条可执行命令/脚本,必须能**直接复制到终端执行**:命令完整可复制(禁止省略参数、禁止用 `...` 占位、禁止只给片段)、在项目根目录下可直接运行
184
+ - ⚠️ **「禁止只给片段」不只看命令本身,还要看读者能不能到达执行它的现场**:命令再完整,如果它前面缺了「怎么连上那个环境」(起代理 / 登录 / 装依赖)和「在哪个库 / 目录下跑」,读者照样跑不起来。**凡命令是「在 X 上执行 Y」的形式,X 必须落到实处**——X 的完整标识、连接它的完整命令、以及前置条件。判读标准同样不能少(跑出 A 是对、跑出 B 是不对)。四类残缺与自查见上一节「分步操作记录」的「片段即未执行」。
182
185
  - ⚠️ 每条命令/脚本写入文档前,必须**亲自在终端实际执行一遍验证确实可行**,验证通过后才能写入文档;执行失败的命令一律不得写入,禁止凭推断「应该能跑」就下结论
183
186
  - ⚠️ 每个命令块必须配「一键复制」按钮:点击按钮将完整命令复制到剪贴板,并给出「已复制」反馈
184
187
  - 复制按钮实现:命令块右上角放复制按钮 → 点击用 `navigator.clipboard.writeText(命令全文)` 复制(不可用时用 `document.execCommand('copy')` 兜底)→ 按钮文案短暂变为「已复制」→ 约 2 秒后恢复为「复制」
@@ -199,6 +199,10 @@ SELECT provider_id, count(*) FROM provider_model_pricing
199
199
 
200
200
  ⚠️ **位置铁律:就近嵌入,禁止堆到附录。** 面板要紧贴它要证明的那条主张——**在「需求原文 / 我们的实现 / 截图证据」三列表里,就是那一行的正下方,跨整行(`colspan`)铺开**。用户读到那句主张时当场就能验;堆到文末 = 他读完满篇结论、再自己回头找对应关系。
201
201
 
202
+ ⚠️ **本节适用范围不止「主张」——报告里每个「请你自己去某环境跑一下 / 确认一下」的开放项(待确认项、上线前准备、动手环节)一律同样处理,而且这里最容易翻车。** 它最容易只丢一行片段(`在 ha-testing 上执行 SELECT has_table_privilege('<网关运行账号>','provider_accounts','UPDATE');`),因为它不是「断言」、作者自己也没结论,顺手写一行就过去了——**而它恰恰是用户最需要「具体咋弄」的地方**。**诊断指纹:只给一行片段 = 作者没真跑过**(真跑过的人必然先起了代理、先确认了库名、先把占位符换成了真值,顺手就写下来了)。补齐标准 = 上文三件套,外加两类只在这里出现的缺口:**① 位置状语要有落点**(「在 X 上」必须给出 X 的完整标识 + 怎么连上去 + 连哪个库);**② 前置条件要交代**(代理没起、gcloud 没登录、没有访问权,用户会卡在第一步而不知卡在哪)。
203
+
204
+ ⚠️ **本机地址本身不违规——违规的是只给地址、不给「怎么把它建起来」。** 「只有你本机才有的东西」指**用户自己造不出来**的(你的 dev server、未提交的文件、正在跑的本机服务);Cloud SQL 代理这类**用户照着命令就能在自己机器上建出同一个**的本机地址可以给,但**建它的命令必须给全**(`cloud-sql-proxy --port 5433 --auto-iam-authn horizonapi-485401:asia-southeast1:ha-testing`)。判断标准:用户照这几行能不能在自己机器上造出那个地址?能 → 可以给(且必须给全建它的命令);不能 → 换成公共可达的地址。
205
+
202
206
  ⚠️ **让因果链在代码 / 数据里自证,而不是靠你断言「是这个改动修好的」。** 「问题 → 修复」那一环,优先落到用户能自己打开的可自查锚点上——**最强的形式是修复脚本 / 部署脚本的注释里逐字引用了问题日志的 trace_id**,用户顺着文件路径和行号点进去,能看到「问题」与「修复」被同一份代码同时提到。退而求其次:迁移文件里写了对应表名、配置项当年的错值就摆在 diff 里。只有确实找不到锚点时,才用你的叙述把因果讲清楚。
203
207
 
204
208
  > 实例:某次修复的 `deploy.sh` 注释里逐字写着 `trace_id f0aaf7f89cf29f6d69bc8180118de23e`,而那正是此前报 `permission denied (42501)` 那条日志的 trace_id。用户点开脚本第 317-319 行自己一看,「问题日志 → 修复动作」这条链就闭上了,完全不需要信作者的转述。
@@ -207,13 +207,14 @@ done
207
207
 
208
208
  - **本轮没有任何「值得修」的新问题**(要么 bot 没提新的,要么新问题全是已处理/口味/误报,全部有回复落点)→ 循环结束 ✅,进入步骤 7 收尾
209
209
  - **本轮有「值得修」的新问题** → 已修复并回复,回到步骤 5 进入下一轮
210
- - **达到最大轮数(默认 5 轮;用户明确要求深度循环时最多 8 轮)仍有值得修的新问题** → 停止循环,把剩余问题逐条列给用户,由用户决定(继续 / 放过 / 人工处理),禁止无限循环
210
+
211
+ ⚠️ **循环不设轮数上限——结束只看「这一轮有没有必须修的问题」,不看「已经跑了几轮」。** bot 每轮全量重读 diff,总能再挖出新层次(上一轮漏报的角落 / 修复引入的回归 / 新代码自带的新毛病),**只要它提的还落在「必须修」范围内,就继续修**,禁止因为「都跑到第 N 轮了」就把仍然必须修的问题挂着交出去。循环天然会收敛:真正会无限冒的只是「口味 / 过度设计」那类,而它们每轮都被 Won't fix 回复挡住、进不了「必须修」,所以「必须修的清零」这一条件迟早成立、且不会被轮数提前打断。
211
212
 
212
213
  ⚠️ 每轮结束向用户汇报:本轮发现什么、改了什么、拒绝了什么、剩什么。
213
214
 
214
215
  ### 7. 收尾汇报
215
216
 
216
- 循环结束或达到轮数上限后,输出汇总报告:
217
+ 循环结束后,输出汇总报告:
217
218
 
218
219
  ```
219
220
  循环 review 完成,共 X 轮:
@@ -228,8 +229,7 @@ done
228
229
 
229
230
  | 条件 | 行为 |
230
231
  |------|------|
231
- | 本轮没有任何「值得修」的新问题 | ✅ 结束(注意:**不是**「严重度清零」——bot 总会挂着几条我们判断过不值得修的) |
232
- | 达到最大轮数(默认 5 轮;用户明确要求深度循环时最多 8 轮) | ⛔ 停止,剩余问题交用户决定 |
232
+ | 本轮没有任何「值得修」的新问题 | ✅ 结束(注意:**不是**「严重度清零」、**也不是**「跑够多少轮」——bot 总会挂着几条我们判断过不值得修的) |
233
233
  | 等待新 review 超时(默认 15 分钟) | ⏸ 停止等待,询问用户 |
234
234
  | 连续两轮 review 内容完全相同(bot 疑似卡死) | ⛔ 停止,向用户报告 |
235
235
 
@@ -242,7 +242,7 @@ done
242
242
  - ⚠️ **每条 review 建议必须有落点**(修复 commit / Won't fix / 误报回复),禁止静默跳过——不回复 bot 下轮必重提,循环无限。
243
243
  - ⚠️ **每轮先确认哪些是上一轮已处理过的**,一律不重复改,直接回复「已修复于 <hash>」。
244
244
  - ⚠️ **禁止使用 `[skip ci]` / `[skip review]`**——循环依赖「每次 push 触发 review」,跳过就断了。
245
- - ⚠️ **必须设最大轮数(默认 5;用户明确要求深度循环时最多 8)和等待超时(默认 15 分钟)**,禁止无限循环 / 无限等待。
245
+ - ⚠️ **循环不设轮数上限**:结束只由「本轮有没有必须修的新问题」决定,与轮数无关。**禁止因为「已经跑了好几轮」就把仍然必须修的问题挂着交给用户**;反向同样禁止——为了尽快收工,把真问题降级成口味问题 Won't fix 掉。**等待 bot 返回新一轮 review 的超时保留(默认 15 分钟)**,它管的是「不要干等」,不是循环上限。
246
246
  - ⚠️ **已修复的功能性问题单独 commit**,禁止与大量建议级改动混在一起,保证每轮 push 的 diff 可读。
247
247
  - ⚠️ **每条 review 修复都必须同 commit 回 PR 对应的 feature 分支并推送远程**,不得只推到 test 分支或只放在工作区不 commit。feature 分支与 test 分支两条线必须同步,缺一不可(详见步骤 3)。
248
248
  - ⚠️ **等待 bot 审查期间遵守心跳约定**:超过 1 分钟无输出主动说明在等什么。