diff --git a/deploy/check-require-declaration.sh b/deploy/check-require-declaration.sh index 934c879..8555bc5 100755 --- a/deploy/check-require-declaration.sh +++ b/deploy/check-require-declaration.sh @@ -150,12 +150,30 @@ _strip_comments_lex() { _is_caller_text() { local t t="$(printf '%s\n' "$1" | _strip_comments_lex /dev/stdin)" - case "$t" in - *env-defaults.sh*) - grep -qE '^[[:space:]]*(\.|source)[[:space:]].*env-defaults\.sh' <<< "$t" - ;; - *) return 1 ;; - esac + # ★★★ 谓词从"**行内出现子串**"收紧为"**指向本库**"(pi `ae164e2e` 实测打出的**假红**,我复现): + # 旧谓词 `.*env-defaults\.sh` 只要求**子串出现** ⇒ + # `. /tmp/not-our-lib/env-defaults.sh.other` ⇒ rc=**1** 并报该文件裸赋值 + # 而该文件**没有 source 本库** ⇒ **假红**(域偏宽)。 + # ★ pi 的诊断对: **域的宽度该用谓词精度管,不该用阈值管** —— + # 空集守卫 / 下界守卫**都只兜"域偏小/空"**这个方向,加"上界阈值"只会把 + # 一个**精确性**问题换成一个**调参**问题(阈值调多少都是猜)。 + # ⇒ 收紧后的谓词: source 的**参数末尾**必须是 `…/lib/env-defaults.sh`(可带引号/空白), + # 即"**这一行指向的就是本库那个文件**",而不是"这一行里出现过这个字符串"。 + # ① `[^[:alnum:]_.-]lib/env-defaults\.sh` ⇒ 前面必须是**路径分隔符或词边界**, + # 排除 `not-our-lib/env-defaults.sh`(`-lib` 前面是 `-`)这类同后缀异文件 + # ② `["']?[[:space:]]*$` ⇒ **尾锚** ⇒ 排除 `env-defaults.sh.other` 这类**更长**的名字 + # ★ 实测(本仓 3 个真实调用者 + 6 个反例): + # `. "$REPO/deploy/lib/env-defaults.sh"` ⇒ 调用者 ✓ + # `. "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib/…"` ⇒ 调用者 ✓(两处真实形态) + # `. "${REPO#/home}/deploy/lib/env-defaults.sh"` ⇒ 调用者 ✓ + # `. "$A #B/deploy/lib/env-defaults.sh"` ⇒ 调用者 ✓ + # `. /tmp/not-our-lib/env-defaults.sh.other` ⇒ 不算 ✓(pi 的假红例) + # `. /tmp/not-our-lib/env-defaults.sh` ⇒ 不算 ✓ + # `. /tmp/x/lib/env-defaults.sh.other` ⇒ 不算 ✓ + # ⚠️ 射程: 这是**行内文本**的判法,不解析变量实际取值 —— + # 若有人写 `. "$SOMEDIR/lib/env-defaults.sh"` 而 `$SOMEDIR` 指向别处, + # 本判据仍算它"调用者"(**偏宽**、方向安全,会多查一个文件而不是漏查)。 + grep -qE '^[[:space:]]*(\.|source)[[:space:]].*[^[:alnum:]_.-]lib/env-defaults\.sh["'"'"']?[[:space:]]*$' <<< "$t" } # ① 找"调用者":非注释行里以 `. ` 或 `source ` 起头、且提到 env-defaults.sh 的文件。 @@ -301,6 +319,8 @@ AGENTMAIL_REQUIRE="git go"' || true)" _pc_bad="" _is_caller_text '. /dev/null;# 提到 env-defaults.sh' && _pc_bad="分号后的注释(该截没截)" _is_caller_text '# . env-defaults.sh' && _pc_bad="${_pc_bad}整行注释" + # ★ pi `ae164e2e` 打出的**假红**(谓词过宽: 子串出现 ≠ 指向本库)—— 这条必须在反向对照里: + _is_caller_text '. /tmp/not-our-lib/env-defaults.sh.other' && _pc_bad="${_pc_bad}同名后缀的**别的**文件" if [ -n "$_pc_bad" ]; then printf ' [FAIL] 判据自检失败(调用者判定,反向):**非调用者样本**被判成了调用者(%s)——\n' "$_pc_bad" >&2 printf ' ⇒ 域会**偏大**,与该库无关的文件被拖进来报红(假红)。按红计。\n' >&2 @@ -369,14 +389,23 @@ agentmail_require git go' || true)" # `sed 135d` ⇒ `t=801` ≠ 802 ⇒ 抓到;`head/tail -N` ⇒ 缺探针 ⇒ 抓到; # `tac` ⇒ `h=802 t=1`(顺序反)⇒ 抓到;`grep -v '^$'` / `sort -u` ⇒ `t` 偏离 ⇒ 抓到。 # ★ 三个条件合起来 = "**这个过滤器是逐行原位的**"(保行数、保顺序、保两端)。 - _probe_in="AGENTMAIL_REQUIRE=\"__AM_P_HEAD__\" + # ★★★ 但**固定标记**本身有个洞(pi `551d7d85` 实测打出的**假红**,我复现): + # 标记 `__AM_P_TAIL__` 是**字面量**,而它**出现在本判据自己的源码里**(:374/:379 两处)。 + # 于是当**本判据文件自己被当成数据读**(域偏宽 / 自指)时,`grep -F … | head -1` + # 匹配到的是**源码里那行**,不是文件末尾之后的真尾探针 ⇒ 行号算术失败 ⇒ **假红**。 + # ★ 这不是"域偏宽"的问题被误报 —— 是**探针的记号与数据不可分辨**。 + # ⇒ 修法: 用**运行时 nonce**(`$RANDOM` + pid)代替固定字面量 ⇒ + # 该记号**不可能**预先出现在任何静态文件里 ⇒ 碰撞**不可表示**(比"再多加几个下划线"根本)。 + # ⚠️ 射程: 这消掉"记号与数据碰撞"这一类;**不**改变"域偏宽"本身是否该红(那是谓词的事,见 `_is_caller_text`)。 + _am_nonce="AM${RANDOM}${RANDOM}${$}Z" + _probe_in="AGENTMAIL_REQUIRE=\"${_am_nonce}HEAD\" $(cat "$f") -AGENTMAIL_REQUIRE=\"__AM_P_TAIL__\"" +AGENTMAIL_REQUIRE=\"${_am_nonce}TAIL\"" # 内容行数与探针**同一条读取路径**(都经 `printf '%s\n'` 补回被命令替换吃掉的尾换行) _probe_n="$(printf '%s\n' "$(cat "$f")" | awk 'END{print NR}')" _probe_out="$(_scan_stripped "$(strip_text "$_probe_in")" || true)" - _ph="$(grep -F '__AM_P_HEAD__' <<< "$_probe_out" | head -1 | cut -d: -f1)" - _pt="$(grep -F '__AM_P_TAIL__' <<< "$_probe_out" | head -1 | cut -d: -f1)" + _ph="$(grep -F "${_am_nonce}HEAD" <<< "$_probe_out" | head -1 | cut -d: -f1)" + _pt="$(grep -F "${_am_nonce}TAIL" <<< "$_probe_out" | head -1 | cut -d: -f1)" _pexp=$(( ${_ph:-0} + _probe_n + 1 )) if [ -z "$_ph" ] || [ -z "$_pt" ] || [ "$_ph" -ge "$_pt" ] || [ "$_pt" -ne "$_pexp" ]; then printf ' [FAIL] %s 逐文件探针失败:读入这一环**不是逐行原位**的 —— 它在丢弃或重排内容。\n' "$f" >&2 @@ -389,7 +418,7 @@ AGENTMAIL_REQUIRE=\"__AM_P_TAIL__\"" printf ' ⇒ 按红计(绝不能因为两条通道都不说话就当成"没问题")。\n' >&2 exit 1 fi - unset _probe_in _probe_out _probe_n _ph _pt _pexp + unset _probe_in _probe_out _probe_n _ph _pt _pexp _am_nonce # ★★★ 逐行局部不变量(2026-09-25 **pi 提的非循环补法**,我实测后采纳): # 上一节的首尾探针只锁"**行数 / 顺序 / 两端**"(**形状**),锁不住"**某一行内容被抹**"。 # pi 的补法: 对**每一行**要求