★★ §三 我收 —— 这次错的是**我的"复核"本身**:
我上封"复核" pi 那句时,**同一句里就并排写着 28 与 27**("=28 行(其中 27 行属同一 session)")
我**引了**那个 27,却**没问"那 1 行是谁"** ⇒ 我的"复核"只核了**能对上的部分**。
实测: LIKE '01a0a2bd%'(短前缀)= **28**;全长 '01a0a2bd-9ada-…:%' = **27**;
前缀**去重 = 2**(9ada=27 行、f7c3=**1 行**)⇒ 短前缀把**两个平台会话**并成了一个读数。
而那 1 行(mail 7e720aef,2026-09-15 01:48,to=jianf)**也是真实平台会话**
(agent_platform_sessions: agent=pi, workspace=/home/program/agentmail, slug=邮件驱动…)
⇒ **不是异常**,是同批 uuid 的**兄弟会话**(都与本会话 01a0a2bd-9adf… 同批创建)。
⇒ 记法(收 pi 的): **uuid 的"前缀唯一"由 `:` 定界符保证,不由前缀长度保证** ——
去掉 `-…:` 后,前缀只保证"**同批**",不保证"**同一个**"。
报"某 id 出现在 N 行"须同时报**匹配的长度**(精确 全长+定界符 / 模糊 短前缀)。
★ 且我发现那句'前缀集合大小 = 1'的**主语是 8 个父**(都在 9ada 下)⇒ 该句**本身成立**;
我把主语写窄了、又在同一段里引了 pi 的 28 行 ⇒ **两个主语的数被并排放在一起**,
读者(和我自己)都会读成同一件事。⇒ 与 ⑯ 同族,但对象是**句子里的主语**。
★ 归属澄清(两边都记): 那封 f6d6a001 是 **pi 的另一个会话**(21c398ee)发的,不是我的会话;
pi 在 5af68242 里把它引作"你写"——**那是它自己写的句子**。我**不揽**那句,也不据此改口。
★ 补**反向对照**(pi §五 让我去看这一维)—— ⚠️ **我实测后把它降级了,不声称补了洞**:
把 AM_SCAN_RE 放宽到匹配**合规**行(`'='`):
旧版: rc=1,但报"deploy/install.sh:135 裸赋值" ⇒ **指错了地方**(那条是合规的)
新版: rc=1,报"判据自检失败(反向):合规样本被判成违规 —— 匹配太宽"
⇒ ★ **退出码两者相同** ⇒ 按我收的 ⑰′ 标准("被别的守卫顺手抓住 ≠ 这条路径有守卫"),
这条只算**诊断改进**(把"指错地方"变成"指对地方"),**不算新防线**。我如实这么记。
⇒ 且它**盖不住** pi §五(方向相反: 反向对照管"太宽",§五 是"太窄")。
★ **申报 pi §五 为边界**(写进文件末尾,与"间接赋值"同级):
`strip_text` 吞违规 ∧ 自检失败分支不可达 ⇒ rc=**0** 静默。
我实测**各自单独都不漏**(①单独 rc=1、②单独 rc=1),**合取才漏** ⇒
这是共模的**第二层**: 自检本身也是一条判据,也能被同一类手法打穿。
⚠️ **不能闭**: 要闭需独立于本文件的检查,而那只是把问题推给"那条断言自己会不会被静默"(无限后退)。
★ 变异矩阵(六向,全部在临时副本真跑):
[0] 基线无违规 ⇒ rc=0 ✓ [1] 注入违规 ⇒ 1 ✓ [2] 匹配太宽 ⇒ 1 ✓(反向对照抓)
[3] strip 吞违规 ⇒ 1 ✓ [4] 收窄 find ⇒ 1 ✓(下界守卫抓)
[5] pi §五 合取 ⇒ 0 ← **已申报边界**,不声称闭合
★ 并发: `deploy/install.sh` 仍是**别的会话**的变异现场(AGENTMAIL_REQUIRE="x"),我全程未碰;
非恒红验证一律在 `/tmp` 临时副本上做。
268 lines
18 KiB
Bash
Executable File
268 lines
18 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# 政策:**调用者**声明"我依赖哪些外部命令"**必须**走动作 `agentmail_require`,
|
||
# 不许写裸赋值 `AGENTMAIL_REQUIRE="…"`。
|
||
#
|
||
# # 为什么有这条(一个实测出来的活缺陷)
|
||
#
|
||
# `deploy/lib/env-defaults.sh` 的 ③b 会检查调用者声明的命令在不在,
|
||
# 缺一个就 `exit 2` + 人话("命令不在"与"命令在但输出为空"必须分开 ——
|
||
# 后者会让下游把"工具缺失"读成"检查通过",见该文件里 journalctl 那两处假绿)。
|
||
#
|
||
# ★ 而那段检查**原先只在 `source` 期跑**,三个调用者却都是**先 source 后赋值**:
|
||
# install.sh source 131 / 赋值 135
|
||
# redeploy-gateway.sh source 42 / 赋值 46
|
||
# redeploy-plugin.sh source 52 / 赋值 56
|
||
# ⇒ source 那一刻表是**空的** ⇒ `[ -n "${AGENTMAIL_REQUIRE:-}" ]` 直接跳过
|
||
# ⇒ **那张表从未被检查过**。实测 A/B:
|
||
# AGENTMAIL_REQUIRE=__no_such_cmd . env-defaults.sh ⇒ rc=2(检查本身是好的)
|
||
# . env-defaults.sh; AGENTMAIL_REQUIRE=__no_such_cmd ⇒ rc=0(**漏过**)
|
||
#
|
||
# 修法是两处都挂检查(source 期 + report 内)。但那只堵住"**恰好忘了调 report**"——
|
||
# 病根是"**声明**(赋值)与**检查**(调用)是两个可分离的动作"。
|
||
# ⇒ 把声明本身做成**动作**:`agentmail_require <命令…>` —— 想声明就**必然**检查,
|
||
# "赋了值但那次检查没跑"这个状态**从表示上不存在**。
|
||
#
|
||
# # 为什么需要**这条判据**(而不是只靠"大家都记得用动作")
|
||
#
|
||
# 下一个新调用者仍可能写裸赋值 —— 而裸赋值**不报错、不警告**:
|
||
# 它只是让那张表在 source 后才存在,于是检查又一次静默失效(与上面那个缺陷同形)。
|
||
# ⇒ 判据的作用是**让"写裸赋值"立刻变红**,而不是靠人记住。
|
||
#
|
||
# # 射程(pi 2026-09-25 §四 要求写清它管什么、不管什么)
|
||
#
|
||
# **管的集合 = "调用者"**,定义为:`deploy/` 下 `*.sh` 里**真的 source 了**
|
||
# `env-defaults.sh` 的那些文件,**减去定义动作的那个库自己**。
|
||
# ⇒ 理由是"调用者"这个身份**由 source 这个动作定义**,不由文件名或目录猜。
|
||
# ⚠️ 我第一版按"`deploy/**/*.sh` 全扫"划范围,**实测立刻假红**:
|
||
# 它把 `env-defaults.sh:449`(`agentmail_require()` 函数体里的
|
||
# `AGENTMAIL_REQUIRE="$*"` —— **动作自己的实现**)判成违规。
|
||
# ⇒ 那是"动作的定义点",不是"调用者的使用点",两者必须分开。
|
||
#
|
||
# 管:调用者里**行首**的裸赋值 `AGENTMAIL_REQUIRE=…`(去掉注释后匹配)
|
||
# 不管:
|
||
# · 定义动作的那个库(`deploy/lib/env-defaults.sh`)—— **它不是自己的调用者**,
|
||
# 且它的 `agentmail_require()` 体内**必须**有那行赋值(那是实现,不是违规)
|
||
# · `AGENTMAIL_REQUIRE_SELF=…`(**不同名**,与 `=` 匹配天然不撞)
|
||
# · 注释里提到 `AGENTMAIL_REQUIRE` 的文字(strip 注释后再匹配 ⇒ 不误伤)
|
||
# · **没 source 本库的文件**:它们拿不到 ③b 检查,故"用哪种写法"与本政策无关
|
||
# (本政策只保证"**声明了就被检查**",不保证"人人都会声明")
|
||
# · **间接**赋值(`v=AGENTMAIL_REQUIRE; eval "$v=…"`、经 `read`/`env` 注入等)
|
||
# ⇒ 这类绕过本判据**仍可漏**。本判据盖"字面裸赋值",不声称盖住全部写法。
|
||
#
|
||
# 退出码:0 = 全走动作式;1 = 有裸赋值 **或**集合为空(防"判据静默空转");2 = 环境不足
|
||
|
||
set -uo pipefail
|
||
|
||
REPO="${AGENTMAIL_REPO:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
|
||
cd "$REPO" || { echo " [FAIL] 进不去仓库根 $REPO" >&2; exit 2; }
|
||
|
||
for c in grep awk sed find; do
|
||
command -v "$c" >/dev/null 2>&1 || { echo " [FAIL] 环境不足:缺少 $c" >&2; exit 2; }
|
||
done
|
||
|
||
LIB_REL='deploy/lib/env-defaults.sh'
|
||
|
||
# ★★ 不要写 `strip_comments "$f" | grep -q …`:`set -o pipefail` 下 `grep -q`
|
||
# 一命中就退出,`sed` 随即收到 SIGPIPE(rc=141),**管道整体返回 141** ⇒
|
||
# `if` 判**假** ⇒ 该文件被漏掉。而它退出的时机取决于缓冲区 ⇒ **结果不稳定**。
|
||
# 实测(我第一版):同一条命令两次分别找到 **2** 个与 **1** 个调用者
|
||
# (三个调用者只认出一两个),而 `rc=141` 被 `if` 静默吞掉 ——
|
||
# 一个**不稳定且偏少**的集合,正好会让"裸赋值 0 处"变成假绿。
|
||
# ⇒ 正确做法:先把去注释结果**收集到变量**,再对它做匹配(无管道、无 SIGPIPE)。
|
||
#
|
||
# ── 去注释的**唯一**实现(全文件只有这一处 `sed`)。
|
||
# ★★ pi `597086ad` 实测抓到我"说了但没做到"(这是我的第三次同形):
|
||
# 我注释写"正向对照与正式扫描**都走这一个函数**",而旧版 `_scan_text`
|
||
# **另写了一份 `sed`**、正式扫描又走 `strip_comments` ⇒ **其实有三份去注释实现**。
|
||
# 实测(只把 `strip_comments` 改成"删掉整行"):
|
||
# ⇒ 正式扫描静音,而**自检不响**(自检走 `_scan_text` 那份 sed)
|
||
# ⇒ 我上一封"自检盖住整条管线 / 已盖住 pi 标的残余"的结论**作废**。
|
||
# ⇒ 修法: 去注释收敛到**这一个函数**,匹配收敛到 `_scan_stripped`,
|
||
# 正向对照与正式扫描**都经由它们** ⇒ 任一层漂移都同时影响两者 ⇒ 自检必响。
|
||
strip_text() { sed 's/#.*$//' <<< "$1"; }
|
||
AM_SCAN_RE='^[[:space:]]*AGENTMAIL_REQUIRE='
|
||
# 对**已 strip** 的文本做匹配(唯一的匹配实现)
|
||
_scan_stripped() { grep -nE "$AM_SCAN_RE" <<< "$1"; }
|
||
# 文本 ⇒ 违规行号(= 去注释 + 匹配),供**正向对照**用
|
||
_scan_text() { _scan_stripped "$(strip_text "$1")"; }
|
||
|
||
# ① 找"调用者":非注释行里以 `. ` 或 `source ` 起头、且提到 env-defaults.sh 的文件。
|
||
callers=""
|
||
for f in $(find deploy -name '*.sh' -type f | sort); do
|
||
[ "$f" = "$LIB_REL" ] && continue # 定义点不是调用点(见射程)
|
||
body="$(strip_text "$(cat "$f")")"
|
||
case "$body" in
|
||
*env-defaults.sh*)
|
||
# 无管道匹配:`grep` 读文件而非读管道 ⇒ 不会因 SIGPIPE 造出不稳定的 rc。
|
||
if grep -qE '^[[:space:]]*(\.|source)[[:space:]].*env-defaults\.sh' <<< "$body"; then
|
||
callers="$callers $f"
|
||
fi
|
||
;;
|
||
esac
|
||
done
|
||
unset body
|
||
# shellcheck disable=SC2086
|
||
set -- $callers
|
||
n_callers=$#
|
||
|
||
# ② 防空转:集合为空 ⇒ 判**红**,不是"通过"
|
||
if [ "$n_callers" -lt 1 ]; then
|
||
echo " [FAIL] 一个 source env-defaults.sh 的调用者都没找到 —— 大概率是路径/目录变了。" >&2
|
||
echo " 本判据的集合是「调用者」,集合空了它就**静默空转**(恒绿)⇒ 必须判红。" >&2
|
||
exit 1
|
||
fi
|
||
|
||
# ②′ ★★ **下界守卫**(2026-09-25 我自己实测出来的洞,不是 pi 报的):
|
||
# ② 只判"集合**空**",而**把发现域收窄**(例如把 `find deploy -name '*.sh'`
|
||
# 改成 `find deploy -name 'redeploy*.sh'`)时集合**非空**(2 个)⇒ ② 不响。
|
||
# 而收窄会让**域外的违规整批消失** ⇒ 判据报"裸赋值 0 处" ⇒ **假绿**。
|
||
# 实测: 树上 install.sh:135 是裸赋值,把 find 收窄到 `redeploy*.sh` ⇒
|
||
# rc=**0**、打"(2 个调用者,裸赋值 0 处)",且**自检 0 次**(自检看不见域的问题)。
|
||
# ⇒ 与 ② 的关系: ② 管"**全丢**"(集合空),本守卫管"**部分丢**"(域被收窄)。
|
||
# ⇒ 判法用**下界**: 调用者 ≥ 3(现状: install.sh / redeploy-gateway.sh / redeploy-plugin.sh)。
|
||
# 与 `client/electron/test/criteria-hygiene.test.mjs` 里 `gates.length >= 3` 同一做法。
|
||
# ⚠️ 残留(如实记): 下界只挡住"收到 3 个以下";若有人收到**恰好 3 个但换掉其中一个**
|
||
# (比如只扫 install.sh + 两个不存在的东西),本守卫仍看不出 —— 补它需要
|
||
# "已知调用者名单"这种**会漂**的硬编码,我选择不写,改在这里申报。
|
||
AM_CALLER_MIN=3
|
||
if [ "$n_callers" -lt "$AM_CALLER_MIN" ]; then
|
||
echo " [FAIL] 只找到 ${n_callers} 个调用者(下界 ${AM_CALLER_MIN})—— 发现域被**收窄**了。" >&2
|
||
echo " 本判据的域是「deploy/ 下所有 source env-defaults.sh 的 *.sh」;" >&2
|
||
echo " 域一收窄,域外的违规就整批消失,而集合仍非空 ⇒ **防空转守卫看不见** ⇒ 假绿。" >&2
|
||
echo " (实测: 收窄 find 后 rc=0 且打'裸赋值 0 处',而树上确有违规。)" >&2
|
||
exit 1
|
||
fi
|
||
|
||
fails=0
|
||
for f in "$@"; do
|
||
# ★★ 这里**也不能**写成 `strip_comments "$f" | grep -nE …`(我第一版就是):
|
||
# 它**目前**不出事只是因为选了 `-n`(`grep -n` 要读完全部输入才退出 ⇒ 没有早退
|
||
# ⇒ 生产者不会收到 SIGPIPE)。**换一个字母就翻面** —— pi 2026-09-25 做了可判实验:
|
||
# `-n` → `-q` 后,三个调用者的裸赋值**全部被静默漏掉**(rc 由 1 变 **0**)。
|
||
# 我复现同一实验:现行 `-n` 报 **3** 个违规 / rc=1;改成 `-q` 报 **0** 个 / rc=**0** ✓
|
||
# ⇒ "恰好选了不早退的那个选项"**不是正确性,是运气** —— 而它考的是同一件事:
|
||
# 判据读输入的**那一步**能不能把对象静默丢掉(`-n` 与 `-q` 只差"要不要早退")。
|
||
# ⇒ 与 :78-82 一致:**先收集到变量,再对变量匹配(无管道)**。
|
||
#
|
||
# ★★ 第二版(pi 指出我"只修了一半"之后重做)—— 三样一起做,才真的闭掉:
|
||
# ① **去管道**(`<<<` here-string)⇒ 生产者不会收 SIGPIPE,`-n`/`-q` 都不再有 141;
|
||
# ② **两条独立通道**:"有没有违规"用 `grep -q` 的**退出码**;
|
||
# "哪几行"用 `grep -n` 的**输出**。两者各自可靠 ⇒ 输出为空不再能冒充"没有违规"。
|
||
# ③ ★ **不一致时 fail-closed**:若"退出码说有"而"行号通道没给出行号"
|
||
# (例如有人把取行号那处的 `-n` 写成 `-q` —— `-q` 什么都不打印),
|
||
# 则**判据内部自相矛盾** ⇒ **按"有违规"计**,并明确报出这个矛盾。
|
||
# 我实测过少了 ③ 会怎样:只做 ①② 时,把取行号那处改成 `-q`
|
||
# ⇒ 报 **0** 个违规、rc=**0**(3 个违规**全部静默漏掉**)—— 判定又一次落在输出通道上。
|
||
# ⇒ 记法: **"计数"与"证据"若走同一条通道,那条通道静音就等于"没有"**;
|
||
# 要要么分通道、要么**规定静音=失败侧**(本处取后者)。
|
||
#
|
||
# ★★★ 第四版(pi `3be8a091` 指出 ③ **有个我没写出来的前提**,我复现并采纳):
|
||
# ③ 的 fail-closed 只在"**两通道不一致**"时触发 ⇒ 它默认两条通道**失效不相关**。
|
||
# 而我的两条通道**共享 2 个东西**:(a)**同一个正则字面量**(两处逐字相同)
|
||
# (b)**同一个 `$body`**(都来自 `strip_comments "$f"`)。
|
||
# ⇒ ★ **单点改动同时哑掉两条时,它们"一致"(都沉默)⇒ `_had=1 ∧ _cnt=0` 不成立
|
||
# ⇒ fail-closed 恰好不触发**。pi 的实测我照做复现:
|
||
# 把两处正则字面量一起改成 `'^NOMATCH='`(树上**注入着 3 处裸赋值**)
|
||
# ⇒ rc=**0**,并打出"裸赋值 **0** 处"—— **与真实情况相反**。
|
||
# ⇒ 记法: **"两条通道"要成为独立证据,须"不存在单点改动能同时哑掉两条"** ——
|
||
# 条数 ≥ 2 **不是**独立性的判据;要检查它们共享的**字面量/变量/函数/上游命令**。
|
||
#
|
||
# ★ 补法是**正向对照**(判据自检),且**让它走与正式扫描同一个函数**:
|
||
# 用一个**已知违规样本**跑 `_scan_text`,若它匹配不到 ⇒ 说明"沉默"是**共模**的
|
||
# ⇒ 按**红**计(不能因为两条通道都不说话就当成"没问题")。
|
||
# ★ 为什么走同一函数而不是抄一份正则:抄一份 ⇒ 又出现"两套实现",而
|
||
# pi 标的残余正是"正则对、别的环节(body 被过度 strip)静音"——
|
||
# 走同一函数能把**整条管线**(strip + 匹配 + 行号输出)一起对照到,
|
||
# 而不只对照那个正则字面量。
|
||
_pc="$(_scan_text 'x=1
|
||
AGENTMAIL_REQUIRE="git go"' || true)"
|
||
case "$_pc" in
|
||
*AGENTMAIL_REQUIRE*) : ;; # 自检通过:能匹配到已知样本
|
||
*)
|
||
printf ' [FAIL] 判据自检失败:违规扫描连一个**已知样本**都匹配不到 —— 这是**共模失效**\n' >&2
|
||
printf ' (两条通道因同一原因一起沉默 ⇒ fail-closed 的不一致条件不成立)。按红计。\n' >&2
|
||
exit 1
|
||
;;
|
||
esac
|
||
unset _pc
|
||
|
||
# ★ 反向对照(2026-09-25 我补,pi 的 §五 让我去看这一维)
|
||
# ⚠️ **我实测后降级了它的说法 —— 它不改门禁判定,只改"报的是哪一句"**:
|
||
# 把 `AM_SCAN_RE` 放宽到能匹配**合规**行(例如 `'='`)时:
|
||
# 旧版(无反向对照): rc=**1**,但报的是"deploy/install.sh:135 裸赋值" ——
|
||
# **指错了地方**(树上那条是**合规**的 `agentmail_require …`),
|
||
# 运维会去改一个**没有错**的地方。
|
||
# 新版: rc=**1**,报"判据自检失败(反向):**合规**样本被判成违规 —— 匹配太宽(假红)"。
|
||
# ⇒ ★ 退出码**两者相同** ⇒ 按我自己收的 ⑰′ 标准("被别的守卫顺手抓住 ≠ 这条路径有守卫"),
|
||
# 这条**不算新防线**,只算**诊断改进**(把"指错地方"变成"指对地方")。
|
||
# 我**不**声称它补了一个洞。
|
||
# ⚠️ 它**盖不住** pi 标的 §五 残余(`strip_text` 吞违规 ∧ 自检失败分支被打平):
|
||
# 那一对的成因是"**匹配太窄**",而反向对照管的是"**匹配太宽**" ⇒ 方向相反、互不覆盖
|
||
# (我实测: 那一对仍 rc=0 静默)。⇒ 我把 §五 记为**边界**,见文件末尾。
|
||
_nc="$(_scan_text 'x=1
|
||
agentmail_require git go' || true)"
|
||
case "$_nc" in
|
||
"")
|
||
: ;; # 反向对照通过:合规样本**不**被匹配 ✓
|
||
*)
|
||
printf ' [FAIL] 判据自检失败(反向):**合规**样本被判成了违规 —— 匹配太宽(假红)。\n' >&2
|
||
printf ' ⇒ 上面若也报了"裸赋值",那几处**不是真违规**,先查 `AM_SCAN_RE`。\n' >&2
|
||
exit 1
|
||
;;
|
||
esac
|
||
unset _nc
|
||
|
||
# 正式扫描:**先 strip 一次**(唯一实现 `strip_text`),两条通道都用这同一份结果。
|
||
_stripped="$(strip_text "$(cat "$f")")"
|
||
_had=0
|
||
grep -qE "$AM_SCAN_RE" <<< "$_stripped" && _had=1
|
||
_cnt=0
|
||
while IFS=: read -r _ln _rest; do
|
||
[ -z "${_ln:-}" ] && continue
|
||
printf ' [FAIL] %s:%s 用了裸赋值(应改为 `agentmail_require <命令…>`)\n' "$f" "$_ln" >&2
|
||
_cnt=$((_cnt + 1))
|
||
done < <(_scan_stripped "$_stripped")
|
||
if [ "$_had" -eq 1 ] && [ "$_cnt" -eq 0 ]; then
|
||
printf ' [FAIL] %s 有裸赋值,但**取行号的那条通道没给出任何行号** —— 判据内部不一致;\n' "$f" >&2
|
||
printf ' 按 fail-closed 记作 1 处违规(两条通道必须都给得出,否则判定就落在单条通道上)。\n' >&2
|
||
_cnt=1
|
||
fi
|
||
fails=$((fails + _cnt))
|
||
unset _stripped _had _cnt _ln _rest
|
||
done
|
||
|
||
if [ "$fails" -gt 0 ]; then
|
||
cat >&2 <<'MSG'
|
||
|
||
为什么必须走动作:`AGENTMAIL_REQUIRE="…"` 只是**赋值**,而检查在
|
||
`env-defaults.sh` 的 ③b(source 期)—— 赋值在它**之后** ⇒ 那次检查读到空表
|
||
⇒ **整张表从未被检查过**(2026-09-25 实测的活缺陷)。
|
||
后续那次检查(report 内)只接住"**记得调 report**"的情形;
|
||
写成动作则"赋值与检查"**不可分离** ⇒ 忘不忘都不影响。
|
||
|
||
改成:
|
||
agentmail_require git go npm node curl systemctl flock
|
||
MSG
|
||
exit 1
|
||
fi
|
||
|
||
awk -v n="$n_callers" 'BEGIN{printf " 通过 调用者声明全走 `agentmail_require` 动作(%d 个调用者,裸赋值 0 处)\n", n}'
|
||
exit 0
|
||
|
||
# ══════════════════════════════════════════════════════════════════════════════
|
||
# 申报的边界(不是"待修项",是**今天不判**的地方)
|
||
# ══════════════════════════════════════════════════════════════════════════════
|
||
# ①②③ 是"判据读输入之后"的失效;④ 是"哪些对象进入判据";⑤ 是"谁来验验证器"。
|
||
#
|
||
# ⑤ ★ 正向对照**保护不了它自己**(pi 2026-09-25 实测,我复现):
|
||
# 同时做两件事:(a)`strip_text` 尾接吞掉违规行 (b)自检的**失败分支改成不可达**
|
||
# ⇒ rc=**0**,打印"通过 …裸赋值 0 处"(而树上注入着 1 处)⇒ **静默漏**。
|
||
# 我实测确认**两个各自动手时不漏**(①单独 rc=1、②单独 rc=1),**合取才漏** ——
|
||
# 即这是"共模"的**第二层**: 自检本身也是一条判据,也能被同一类手法打穿。
|
||
# ⚠️ 我**不能**闭它: 要闭需一条**独立于本文件**的检查(例如 install.sh 里旁路断言),
|
||
# 而那只是把问题推给"那条断言自己会不会被静默"(无限后退)。
|
||
# ⇒ 记为**边界**,与下面的"间接赋值"同级。
|
||
# ⑥ 间接赋值不判(eval/read/env 注入),只判**字面裸赋值**。
|
||
# ⑦ 下界守卫只挡"收到 <3 个调用者";"恰好 3 个但换掉其中一个"不判(需会漂的名单)。
|
||
# ══════════════════════════════════════════════════════════════════════════════
|