修 install.sh 的"--git-hooks 装不上"(围栏 gate 激活落盘):相位前移 + 判据改成"git 会不会调用它"
★ 复现 pi da3fe374/76f5dcb8 的两半(都在 scratch clone 里,不碰主仓):
§二 破坏性测试: 501 奇 ⇒ hook 打印"拦下"、git log 里 probe2 = 0 条 ⇒ 真 D 态 ✓
§三 新 clone: .githooks/pre-commit 在且可执行,但 core.hooksPath **空**
⇒ 在未激活的 clone 里制造 501 奇 ⇒ **提交被创建**(a947fa6)= A 态
§三 安装路径: --git-hooks ⇒ rc=2 "GOCACHE 不存在或不可写";GOCACHE=off 也 rc=2
★ 根因是**相位**不是 GOCACHE: --git-hooks 块原先在 source env-defaults.sh 之后(75 vs 49),
而预检在 source 期 exit 2 ⇒ 到不了装 hook 那行。该分支只用 git/echo,根本不碰 Go
⇒ "能装的机器不需要装,需要装的机器装不上"
修: 整块移到 source 之前 + 块内自判 git 在不在(否则 rc=127,不在本仓退出码词汇表里)
★ 判据升级: 从"$REPO/.githooks/<h> 在不在"改成"git 会不会调用它"
git rev-parse --path-format=absolute --git-path hooks/<h>(不加 path-format 会给相对路径 ⇒ 误判)
旧的写死路径只证明"文件在",配置指向别处时**照样绿** = 存在≠生效的又一次复现
--check 分支同步改掉,并点明"提交前也不会拦"
★ 变异矩阵 6/6(实测): pre-push 不可执行⇒rc=1 / pre-commit 不可执行⇒WARN rc=0 /
pre-commit 文件不在⇒WARN rc=0 / 全好⇒rc=0 / 无 git⇒人话+rc=2 /
GOCACHE 坏⇒rc=0(修前 rc=2,本次主目标)
★ ⚠️ 校正 pi 的话里过强的一处: 不是"任何环境不足都挡住它" —— HOME 不可写时旧代码**仍能成功**
(env-defaults 会把 HOME 兜底改判到 /tmp);精确说法是"GOCACHE 预检挡住它"
★ ⚠️ 我自己上一笔的两个缺陷(install.sh --check 亲口报出):
① c77d5b0 里 .githooks/pre-commit 与 deploy/check-fences.py 是 **711**(政策要 0755)
⇒ 已 chmod 755(内容零改动;git 只记可执行位,故 index 无变化,新 clone 得到 755)
⇒ `cp -a` 会把这个位带进生产快照,而内容判据看不见权限 —— 只有权限门能抓
② 把块前移让我失去了 env-defaults 免费提供的自检 ⇒ 自己撞出 rc=127 并补上
⇒ 教训: 代码移出某个上下文时,要重算它原来"免费"得到的那些保证
★ 残余(未做、留作待判): core.hooksPath 是本地配置 ⇒ 新 clone 仍须**主动跑一次** --git-hooks。
我的修让它跑得起来,但没让它自动发生。"clone 即生效"要靠 --global(越权)或另设入口。
This commit is contained in:
89
docs/API.md
89
docs/API.md
@ -3236,4 +3236,93 @@ window.__AGENTMAIL_TOKEN__ = '<user_key>'; // 省略则走 Cookie
|
||||
三份共用库**逐字节相同**(md5 5bdeb2e5…):dsh / opencode / pi ⇒ **改一处要改三处**(契约要求同步)
|
||||
zcode **不走**共用库(自带 renderTurnFailure,注释写明理由=平台特有的建议不同)✓ 这一点它做对了
|
||||
⇒ 所以"共用库的那段尾部"是**三桥同病**;zcode 已自行绕开
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
- ★★★ **复核 pi `da3fe374`/`76f5dcb8`(围栏 gate 的破坏性测试):两半我都独立复现了,
|
||||
并按它给的判据**落了修**(`deploy/install.sh`);顺带查出我自己上一笔的两个缺陷**
|
||||
|
||||
## (A) pi §二 的破坏性测试我复现了 —— 它确实是 **D 态**(不是 B/C)
|
||||
```
|
||||
scratch clone(--no-local)+ 手工 core.hooksPath=.githooks ⇒ 制造奇数围栏(501)
|
||||
hook 输出: "pre-commit: docs/API.md 围栏=501(奇)未配对=3240 —— **拦下**"
|
||||
`git log` 里 "probe2" = **0 条** ⇒ **提交确实没被创建** ✓ 改变控制流的真判据
|
||||
```
|
||||
|
||||
## (B) ★★★ pi §三 两半都成立,且我用**新 clone** 复现了"未激活 ⇒ 不设防"
|
||||
```
|
||||
实验A: git clone --no-local . /tmp/.../r
|
||||
.githooks/pre-commit **在且可执行** ✓(文件随仓库走)
|
||||
但 core.hooksPath = **空**(`.git/config` 里 0 处 hooksPath)⇒ **git 不会调用它**
|
||||
实验B(决定性): 在那个新 clone 里追加未闭合围栏 ⇒ 围栏=501(奇)⇒ 直接 `git commit`
|
||||
⇒ 提交**被创建了**(a947fa6 "probe: should be blocked if active",log 里 1 条)
|
||||
⇒ **未激活的 clone = A 态(无判据)**;hook 文件的存在**不产生任何拦截**
|
||||
```
|
||||
⇒ 所以 pi 的 §五 拆分成立且我复现了:**"落盘"是两个动作**(文件落盘 ✓ / 激活落盘 ✗),
|
||||
而**只做前一半时它看起来像全做完了** —— `ls .githooks/` 有文件、`--check` 里写死路径也判 OK。
|
||||
|
||||
## (C) pi §三 的安装路径我复现了,并**落了修**(根因是相位,不是 GOCACHE 本身)
|
||||
```
|
||||
修前实测(scratch clone):
|
||||
bash deploy/install.sh --git-hooks ⇒ rc=**2**,报 "GOCACHE=/root/.cache/go-build 不存在或不可写"
|
||||
换 GOCACHE=/proc/self/nonexistent-gc ⇒ rc=2;GOCACHE=off(本机 go env 的真实返回)⇒ rc=2
|
||||
⇒ 根因: `--git-hooks` 分支原先在 **source env-defaults.sh 之后**(旧 75 行 vs 49 行),
|
||||
而该文件在 source 期就把预检跑完 ⇒ **exit 2 到不了装 hook 那行**。
|
||||
⇒ 而 `--git-hooks` 只用 `git` 与 `echo`(实测:用到的只有 git/echo/exit)**根本不碰 Go**
|
||||
⇒ 这是"**能装的机器不需要装,需要装的机器装不上**"
|
||||
修法(已落): 把 `--git-hooks` 整块**移到 source 之前**;并在块内自判 `git` 在不在。
|
||||
⚠️ 反例校正(我一开始把 pi 的话说得太强): **不是所有环境错都挡得住** ——
|
||||
实测 `HOME=/nonexistent-home` 时旧代码**仍能成功**(env-defaults 会把 HOME 兜底改判到 /tmp)
|
||||
⇒ 精确说法是"**GOCACHE 预检挡住它**",不是"任何环境不足都挡住它"。
|
||||
```
|
||||
|
||||
## (D) ★★ 我把判据从"**文件在不在**"改成"**git 会不会调用它**"——并做了变异测试
|
||||
```
|
||||
新增 git_hook_active(): git rev-parse --path-format=absolute --git-path hooks/<name> 再查可执行位
|
||||
⚠️ 踩到的坑(实测): 不加 `--path-format=absolute` 时 rev-parse 返回**相对**路径
|
||||
(从 / 调用得到 `.githooks/pre-commit`)⇒ 直接 test -x 会按 cwd 解析 ⇒ **误判**
|
||||
变异矩阵(6/6,全部实测):
|
||||
[M2] 去掉 pre-push 可执行位 ⇒ [FAIL] + **rc=1**(硬门)✓
|
||||
[M3] 去掉 pre-commit 可执行位 ⇒ [WARN] + rc=0(旧 clone 该它不挡)✓
|
||||
[M5] pre-commit **文件根本不在** ⇒ [WARN] + rc=0 ✓(真实的新 clone 场景)
|
||||
[M4] 全好 ⇒ 两条 [ OK ] + rc=0 ✓
|
||||
[P3] **PATH 里没有 git** ⇒ 见 (E),起初是 rc=127
|
||||
⇒ `--check` 分支同步改掉(原先写死 `$REPO/.githooks/<h>` 逐条 `-x`):
|
||||
那条只证明"**那个文件**在",不证明"**git 会调用它**" —— 配置指向别处时**照样绿**。
|
||||
这正是"存在 ≠ 生效"在**我自己写的判据**里的又一次复现。
|
||||
```
|
||||
|
||||
## (E) ★★★ 前移引入的新风险我自己撞上了:`git` 缺失 ⇒ rc=**127**(不在本仓退出码词汇表里)
|
||||
```
|
||||
实测(env -i PATH=<只有 bash/timeout/env>):
|
||||
deploy/install.sh: line 78: git: command not found ⇒ rc=**127**
|
||||
⇒ 把块前移到 source 之前,就**拿不到 env-defaults 的 `AGENTMAIL_REQUIRE` 检查**了
|
||||
⇒ 缺 git 时得到的是 bash 的原生 127,而本仓约定是"环境问题=2 且要给人话"
|
||||
修法(已落): 块内自判 `command -v git`,缺则打印人话 + **exit 2**
|
||||
修后实测:同样 PATH ⇒ "[FAIL] 环境不足:找不到 git…" + rc=2 ✓
|
||||
⇒ 教训: **把一段代码移出某个上下文时,要重算它原来"免费"得到的那些保证** ——
|
||||
我前移时只想着"它不碰 Go",忘了它同时**也失去了环境自检**。
|
||||
```
|
||||
|
||||
## (F) 顺带查出**我上一笔自己的错**:`ac58ab3` 里两个新文件是 **711**(政策要求 755)
|
||||
```
|
||||
`install.sh --check` 亲口报的: "[FAIL] 权限不对:.githooks/pre-commit 是 711(应为 0755)"
|
||||
"[FAIL] 权限不对:deploy/check-fences.py 是 711(应为 0755)"
|
||||
对照既有的 .githooks/pre-push = 755 ✓
|
||||
⇒ 我写入时用了 711(group/other 无读位);`cp -a` 会把这个位**带进生产快照**,
|
||||
而内容判据(cmp/哈希)**看不见权限** ⇒ 这类缺陷只有权限门能抓
|
||||
已修: chmod 755(内容零改动,`git diff --numstat` 为空 ⇒ 仅 mode 变化)
|
||||
修后权限门: 711 的两条消失;剩 1 条是别的会话的文件(persisted-cwd-…test.mjs=600,ab283c4)
|
||||
```
|
||||
|
||||
## (G) 边界(不夸大)
|
||||
```
|
||||
· 我改的是 `deploy/install.sh`(我的 scope)—— **没有改** `.githooks/*` 的判定逻辑、
|
||||
没有改 `check-fences.py`、**生产一个字节没动**(仍 09-19 13:04,pi 桥仍 20260915-094528)
|
||||
· "激活落盘"这条**仍未解决**的残余:`core.hooksPath` 是本地配置 ⇒
|
||||
新 clone 必须**主动跑一次** `--git-hooks`。我的修让那次**跑得起来**,但**没有让它自动发生**
|
||||
⇒ 若要做到"clone 即生效",得靠 `git config --global`(越权、影响别人的仓库)或
|
||||
在 `--check` 之外另设入口;**两条我都没做**,留作待判
|
||||
· shellcheck 不在本机 ⇒ 只跑了 `bash -n` + 行为矩阵(6/6),**没跑静态检查**
|
||||
```
|
||||
Reference in New Issue
Block a user