#!/usr/bin/env bash
# v1.5.4 check14 判据载体(机制化守卫, v153 世代交替——1d W1: 承继断言函数名禁改, 仅显示面归一)
# 断言函数即 check14 登记标识的真载体。v153 十九判据承继(函数名保留原名, check14 按名 grep 血统)+ v154 新增:
#   assert_v154_l5_date_guard      — L5: 日期防呆守卫(条目日期 ≤ 当日, 未来日期→FAIL; ==当日仅 3d-3i D 面纪律)
#   v154 承继面硬化(函数名不变, 内部实现机制化):
#     ac7_dual_value               — L1: 集合语义(双值无序精确匹配, 消顺序敏感假红)
# 世代交替经 G 门载体层自动接线(v143_gates active_guard_gen 自动解析世代号最大者, 零手工改线)。
# v153_structural_guards.sh 保留至 3d(退役须与版本 bump+check14 1.5.4 登记+md5 重锚同批, 1d W1 裁定)。
#
# ── ★★ v1.9.0 `P0-2` 器面专批(`ar` 裁「取乙」· 令源 `msg-1791738695206-1`)───────────
# 令逐字: 「`P0-2` 断言归属插件仓自仓 `gate`, 主线 `gate` 成仓状态纯函数 ⋯ 主线侧按序落笔,
#   缺失覆盖记 `GAP` 显名」。
# 病相(审计 `v191-…-r49` `F-08` / `02 §3.8` 逐字 · 九轮 `STILL OPEN`): 本档【五】处断言硬依赖
#   `${CARGO_HOME:-$HOME/.cargo}/git/checkouts/<repo>-*/<短rev>/` ⇒ 干净 `runner`(无 `checkout`)
#   首真跑 ⇒ `die` ⇒ 检查14b 红 ⇒ 与 archived 证据背离(6⇒26 份 gate log)。
# 处置(本批): **删**该五处断言 —— 其【内容断言】之归属 = **所钉之插件仓自仓 `gate`**
#   (承 `ar` 裁之「断言归属插件仓自仓 gate」∧ 审计 `F-08` 处方「改 `lock` 仓内声明式断言」):
#     · xwcore 面 4: `assert_v152_ac_cg_lazy_boot` ∧ `assert_v152_ac_cg_lazy_ensure` ∧
#       `assert_v152_ac_cg_dual_bounds` ∧ `assert_v151_ac4_codegraph_bound`
#     · xwrepl 面 1: `assert_v151_ac1_syntect_lazy`
#   ★ 连带: 辅助器 `xwcore_lock_commit()` / `xwcore_src_dir()` 唯此四处用 ⇒ 随之废;
#     `skip_note()`/`SKIP_COUNT` 唯 `ac1_syntect_lazy` 用(P0-4 之 silent-skip→WARN 面)
#     ⇒ 本档已【无 checkout 读取】⇒ 该面【无对象】⇒ 随之废(禁留死支)。
#   ★ 覆盖面之丧失 = 【记 `GAP` 显名】(见 `release/v1.9.0/evidence/P02_GATE_PURITY.md`)——
#     禁以「插件仓自仓 gate 将承载」充【主线已承】。
#   ★ 未动(并载): 旧世代档 `v143/v151/v152_structural_guards.sh` 仍含同名函数与 checkout 读取
#     —— 世代解析取【最大】⇒ 其【不在跑线】(检查14b 唯执行现役档)⇒ 本批不动(禁越改史档)。
# 后果之自证: 空 `CARGO_HOME` 跑本档 ⇒ `EXIT=0`(前态 `EXIT=1` ∧ 四 `FAIL` 皆 xwcore 面)。

# v1.5.6.1 F3(r34 P0-2 根因, AC-P4)强制步: 升钉必同步守卫常量+实跑守卫套件——
#   升钉批两步缺一: ①同步(本文件常量已派生化, 随钉面自洽, 历史条目见 git 血统)
#   ②实跑本套件 EXIT=0(漏实跑=批内失守; 判例: 批2 合法升钉 v1.2.7 未同步守卫
#   → v1.5.6 3i 前修红 4d0c80f18)。
set -u
FAIL=0
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"

# v1.5.6.1 F3(r34 P0-2 根因, AC-P4): 守卫常量改从主线 Cargo.toml 钉面动态解析——
# 字面固化在升钉批漏同步时守卫假绿(守卫放行失配钉面 = 门禁可信化缺口)。
# 解析面 = [workspace.dependencies] 该 git URL 首条 tag= 声明; 解析空值即 die
# (fail-fast, 禁静默空串放行)。
# ★ v1.9.0 P0-2: 原 `XWCORE_TAG`(唯 `ac_cg_lazy_boot` 用 · 含其「动态前驱推导」)
#   随该断言删除 ⇒ 本行同删(禁留死变量)。
pin_tag() {
    local tag
    tag="$(grep -m1 "$1.*tag = " "$REPO_ROOT/Cargo.toml" | sed -E 's/.*tag = "([^"]+)".*/\1/')"
    [[ -z "$tag" ]] && { echo "[v154-guards] FAIL: 守卫常量派生失败(Cargo.toml 无 $1 tag 钉面)" >&2; exit 1; }
    echo "$tag"
}
KERNEL_TAG="$(pin_tag 'xwkernel.git')"
XWWASM_TAG="$(pin_tag 'xwwasm.git')"

note() { echo "[v154-guards] $*"; }
die()  { echo "[v154-guards] FAIL: $*" >&2; FAIL=1; }

# ★★ v1.9.0 P0-2 器面专批: 本档已【无 checkout 读取】——
#   原 `xwcore_lock_commit()` / `xwcore_src_dir()`(自 `Cargo.lock` 取短 sha 再于
#   `${CARGO_HOME}/git/checkouts` 定位源码目录)随其唯四调用方(xwcore 面 4 断言)同批删除;
#   原 `skip_note()`/`SKIP_COUNT`(P0-4 之 silent-skip→WARN 面, 唯 `ac1_syntect_lazy` 用)
#   亦随该断言删除而【无对象】⇒ 同删(禁留死支)。详见档头 P0-2 注。

# ── v152 新增: CodeGraph 惰性判据 ─────────────────────────────
# ★★ v1.9.0 P0-2: 原 `assert_v152_ac_cg_lazy_boot` / `assert_v152_ac_cg_lazy_ensure` /
#   `assert_v152_ac_cg_dual_bounds` 三判据(xwcore 面 · 读 checkout 之源码内容)已删 ——
#   其内容断言之归属 = `xwcore` 自仓 `gate`(详见档头)。主线侧之【缺失覆盖】记 `GAP`。

# ── v151 承继: 有界化结构判据 ─────────────────────────────────

# G-AC4 (v150 承继): wasmtime 惰性行为面——xwwasm 钉 v0.1.2 + v0.1.1 零残留
assert_v151_ac4_wasmtime_lazy() {
    local n
    n="$(grep -c "xwwasm.git.*tag = \"$XWWASM_TAG\"" "$REPO_ROOT/Cargo.toml" || true)"
    if [[ "$n" -ge "2" ]]; then
        note "v152_ac4_wasmtime_lazy: xwwasm 钉 $XWWASM_TAG 双声明在位 ✓"
    else
        die "xwwasm 钉 $XWWASM_TAG 声明计数=$n, 期望 ≥2(xw-plugin + xw-plugin-wasmtime)"
    fi
    if grep -q 'xwwasm.git.*tag = "v0.1.1"' "$REPO_ROOT/Cargo.toml"; then
        die "xwwasm v0.1.1 残留声明(惰性化载体未升钉)"
    else
        note "v152_ac4_wasmtime_lazy: xwwasm v0.1.1 零残留 ✓"
    fi
}

# G-AC5 (v150 承继): worker 缺省 min(4,ncpu)——parse_worker_threads + kernel 钉
assert_v151_ac5_worker_default() {
    if grep -q "parse_worker_threads" "$REPO_ROOT/src/main.rs"; then
        note "v152_ac5_worker_default: 根 bin parse_worker_threads 在位 ✓"
    else
        die "根 bin parse_worker_threads 缺失(worker 收口未落)"
    fi
    if grep -q "available_parallelism" "$REPO_ROOT/src/main.rs"; then
        note "v152_ac5_worker_default: 缺省 min(4,ncpu) 计算在位 ✓"
    else
        die "缺省 min(4,ncpu) 计算缺失(available_parallelism 未引用)"
    fi
    local n
    n="$(grep -c "xwkernel.git.*tag = \"$KERNEL_TAG\"" "$REPO_ROOT/Cargo.toml" || true)"
    if [[ "$n" -ge "4" ]]; then
        note "v152_ac5_worker_default: kernel 钉 $KERNEL_TAG 声明在位 ✓"
    else
        die "kernel 钉 $KERNEL_TAG 声明计数=$n, 期望 ≥4"
    fi
}

# G-AC6 (v150 承继): mallopt cfg(gnu)+env 不覆盖——clamp_malloc_arenas + libc 直依赖
assert_v151_ac6_arena_cap() {
    if grep -q "clamp_malloc_arenas" "$REPO_ROOT/src/main.rs"; then
        note "v152_ac6_arena_cap: 根 bin clamp_malloc_arenas 在位 ✓"
    else
        die "根 bin clamp_malloc_arenas 缺失(arena 收口未落)"
    fi
    if grep -q "cfg(target_env = \"gnu\")" "$REPO_ROOT/src/main.rs"; then
        note "v152_ac6_arena_cap: cfg(gnu) 门控在位 ✓"
    else
        die "cfg(gnu) 门控缺失(非 gnu 平台无保护)"
    fi
    if grep -q "MALLOC_ARENA_MAX" "$REPO_ROOT/src/main.rs"; then
        note "v152_ac6_arena_cap: env 不覆盖守卫在位 ✓"
    else
        die "MALLOC_ARENA_MAX env 守卫缺失(用户显式值会被覆盖)"
    fi
    if grep -q "^libc = " "$REPO_ROOT/Cargo.toml"; then
        note "v152_ac6_arena_cap: libc 直依赖在位 ✓"
    else
        die "libc 直接依赖缺失(mallopt 无法调用)"
    fi
}

# G-AC7 (v150 承继, v154 L1 集合语义硬化): fancy-regex 双值集合精确匹配原值域 {0.16.2, 0.19.2}——无序, 消顺序敏感假红
assert_v151_ac7_dual_value() {
    local vals
    vals="$(grep -A2 'name = "fancy-regex"' "$REPO_ROOT/Cargo.lock" | grep -oP 'version = "\K[0-9.]+' || true)"
    local v150 v152
    v150="$(echo "$vals" | head -1)"
    v152="$(echo "$vals" | sed -n 2p)"
    # L1 集合语义: 双值(可无序)与目标集合做无序精确匹配——双值任一缺失/漂移即 FAIL, 出现顺序无关
    local norm_vals norm_target
    norm_vals="$(echo "$vals" | sort)"
    norm_target="$(printf '0.16.2\n0.19.2' | sort)"
    if [[ "$norm_vals" == "$norm_target" ]]; then
        note "v154_ac7_dual_value: fancy-regex 双值集合 {$v150, $v152} 无序精确匹配原值域 {0.16.2, 0.19.2} ✓"
    else
        die "fancy-regex 双值集合期望 {0.16.2, 0.19.2} 实得 {$v150, $v152}——双值漂移须人工核验终态语义(v1.5.4 L1 集合语义, 消顺序敏感假红)"
    fi
}

# G-AC3 (v151 新增): rayon 线程池封顶——clamp_rayon_threads + RAYON_NUM_THREADS
assert_v151_ac3_rayon_cap() {
    if grep -q "clamp_rayon_threads" "$REPO_ROOT/src/main.rs"; then
        note "v152_ac3_rayon_cap: 根 bin clamp_rayon_threads 在位 ✓"
    else
        die "根 bin clamp_rayon_threads 缺失(rayon 收口未落)"
    fi
    if grep -q "RAYON_NUM_THREADS" "$REPO_ROOT/src/main.rs"; then
        note "v152_ac3_rayon_cap: RAYON_NUM_THREADS 缺省策略在位 ✓"
    else
        die "RAYON_NUM_THREADS 缺省策略缺失"
    fi
    if grep -q "min(4, ncpu)" "$REPO_ROOT/src/main.rs"; then
        note "v152_ac3_rayon_cap: 缺省 min(4,ncpu) 计算在位 ✓"
    else
        die "缺省 min(4,ncpu) 计算缺失"
    fi
}

# G-AC3 伴生 (v151 新增): tokio 缺省 Builder 无帽收口——clamp_tokio_threads
assert_v151_ac3_tokio_cap() {
    if grep -q "clamp_tokio_threads" "$REPO_ROOT/src/main.rs"; then
        note "v152_ac3_tokio_cap: 根 bin clamp_tokio_threads 在位 ✓"
    else
        die "根 bin clamp_tokio_threads 缺失(tokio 收口未落)"
    fi
    if grep -q "TOKIO_WORKER_THREADS" "$REPO_ROOT/src/main.rs"; then
        note "v152_ac3_tokio_cap: TOKIO_WORKER_THREADS 缺省策略在位 ✓"
    else
        die "TOKIO_WORKER_THREADS 缺省策略缺失"
    fi
}

# G-AC8 (v151 新增): G 门载体世代参数化——v143_gates.sh 自动解析现役守卫代
assert_v151_ac8_guard_param() {
    if grep -q "active_guard_gen" "$REPO_ROOT/scripts/tests/v143_gates.sh"; then
        note "v152_ac8_guard_param: 世代自动解析在位 ✓"
    else
        die "v143_gates.sh active_guard_gen 缺失(世代参数化未落)"
    fi
    if grep -q "active_guard_script" "$REPO_ROOT/scripts/tests/v143_gates.sh"; then
        note "v152_ac8_guard_param: 现役守卫自动接线在位 ✓"
    else
        die "v143_gates.sh active_guard_script 缺失(自动接线未落)"
    fi
}

# ★★ v1.9.0 P0-2: 原 `assert_v151_ac4_codegraph_bound`(CodeGraph 建图有界 MAX_FILES/MAX_DEPTH,
#   读 xwcore checkout)与 `assert_v151_ac1_syntect_lazy`(xwrepl `repl.rs` 惰性构造, 读 xwrepl
#   checkout)二判据已删 —— 其内容断言之归属 = `xwcore` / `xwrepl` 各自仓之 `gate`(详见档头)。

# v143 承继 → ★ v1.10.0 改形(承 `R07` ∧ `R09`): `crates/` 白名单内**唯一成员仓** `crates/xwteam`;
#   其余 `crates/**` 仍须零跟踪(物理残留免疫之本义不变)。
#   ★ 由(显名): `v143` 原形之判据「`crates/` 零跟踪」之前件 = `members = []`(`v1.8.0` 裁 09);
#     该前件已由 `R07`(新增成员)与 `R09`(`.gitignore` 白名单形)改变 ⇒ 判据随前件改形。
#   ★ 二向(防谓词空转): 白名单内 4 档在位 ⇒ 绿; 白名单外任一档 ⇒ 红(下方 `_bad` 分支)。
#   ★★ `v1.10.0` 批(承 `docs/V1_10_0_RULINGS_21.md` **准甲**: 档数随批同步): `#13`/`#14` 于
#     `crates/xwteam/` 正当增档(`Cargo.toml`+`src/lib.rs` ⇒ +`src/role.rs`+`src/cli.rs`)
#     ⇒ 白名单档数 `2 ⇒ 4`(器自书之令「增删须同批改本判据与名单」)。
#     ★ 并载其限(照实): 本数系**脆量** —— 成员仓每正当增档须同批改之;
#     `R21` 已明「去写死(成员集自 `Cargo.toml` 派生)另立候选, 非本版」⇒ 本批只同步数, 不改谓词形。
#   ★★ `v1.10.1` `M2` 批(承 `ar` `V1_10_1 R02@4a7efa94a` 判「过」· `R21` 甲): 邮箱落 `src/mailbox.rs`
#     ⇒ 白名单档数 `4 ⇒ 5`(同批改判据与名单之令不因件异而变)。
#     ★ 并载其限(照实): 本数仍是**脆量**; `M3a`/`M3b` 各再加一档 ⇒ 各自批内再 +1。
#   ★★ `v1.10.1` `M3a` 批: 生命周期落 `src/crew.rs` ⇒ 白名单档数 `5 ⇒ 6`(同上律, 同批改)。
#   ★★ `v1.10.1` `M3b` 批: 护栏落 `src/guard.rs` ⇒ 白名单档数 `6 ⇒ 7`(同上律, 同批改)。
assert_v151_crates_absent() {
    local n _bad
    n="$(git -C "$REPO_ROOT" ls-files crates/ 2>/dev/null | wc -l || true)"
    _bad="$(git -C "$REPO_ROOT" ls-files crates/ 2>/dev/null | grep -vE '^crates/xwteam/' | wc -l || true)"
    if [[ "${_bad:-0}" -ne "0" ]]; then
        die "crates/ 白名单外存在 ${_bad} 个跟踪文件(插件化出树未彻底)"
    fi
    if [[ "$n" -eq "7" ]]; then
        note "v152_crates_absent: crates/ 跟踪文件 7 档皆在 白名单 crates/xwteam/(物理残留免疫)✓"
    else
        die "crates/ 跟踪文件数 ${n} ≠ 7(白名单成员仓之档数 —— 增删须同批改本判据与名单)"
    fi
}

# v143 承继: workspace members path 计数=0
assert_v151_path_zero() {
    local n
    n="$(grep -A5 '^\[workspace\]' "$REPO_ROOT/Cargo.toml" | grep -c '^\s*"' || true)"
    if [[ "$n" -eq "0" ]]; then
        note "v152_path_zero: workspace members path 计数=0 ✓"
    else
        die "workspace members path 计数=$n(应=0, 全 git dep 形态)"
    fi
}

# v143 承继: [patch.xwcode.git] 段退役
assert_v151_xwcode_git_absent() {
    if grep -q '\[patch\."https://gitcode.com/kemeng1/xwcode.git"\]' "$REPO_ROOT/Cargo.toml"; then
        die "[patch.xwcode.git] 段回流(ca2f7e34 时代终结失守)"
    else
        note "v152_xwcode_git_absent: [patch.xwcode.git] 段退役 ✓"
    fi
}

# ── v153 新增: AC-G1/AC-G2 门禁化判据 ─────────────────────────

# AC-G1: 内存红线真实口径门禁载体在位——realtotal_gate.sh 收编+红侧构造实证脚本
assert_v153_ac_g1_mem_gate() {
    if [[ -f "$REPO_ROOT/scripts/tests/realtotal_gate.sh" && -x "$REPO_ROOT/scripts/tests/realtotal_gate.sh" ]]; then
        # v1.6.0 SB.4: 阈值面精确钉(防旧口径回潮; 用户铁律 gate 化同步面)。
        # ★★ v1.9.14 P1 抬线批(用户 2026-10-23 定夺 · 承 ar R19): 钉值 20,000 ⇒ 32,768
        #   (32 MiB)—— 用户铁律本体之值随用户令变更; 本守之【职】不变(阈值面精确钉,
        #   防静默漂移 ∧ 防旧口径回潮), 唯【所钉之值】随现行处方走。
        if grep -q "THRESHOLD_KB=32768" "$REPO_ROOT/scripts/tests/realtotal_gate.sh" && \
           grep -q "NTOT" "$REPO_ROOT/scripts/tests/realtotal_gate.sh"; then
            note "v153_ac_g1_mem_gate: realtotal_gate.sh 收编在位(红线 32,768 kB[v1.9.14 P1] + NTOT 原值判定)✓"
        else
            die "realtotal_gate.sh 缺 THRESHOLD_KB=32768/NTOT 判定标识(内存红线门禁载体不完整或阈值面静默漂移)"
        fi
    else
        die "realtotal_gate.sh 缺失/不可执行(AC-G1 探针机械化未落)"
    fi
    if [[ -f "$REPO_ROOT/scripts/tests/realtotal_gate_redside.sh" ]]; then
        note "v153_ac_g1_mem_gate: realtotal_gate_redside.sh 红侧构造载体在位 ✓"
    else
        die "realtotal_gate_redside.sh 缺失(红侧构造实证载体未落)"
    fi
    if grep -q "检查19" "$REPO_ROOT/scripts/verify_release.sh"; then
        note "v153_ac_g1_mem_gate: verify_release 检查19 接线在位 ✓"
    else
        die "verify_release.sh 检查19 缺失(3j 部署位门禁未接线)"
    fi
}

# AC-G1: CI memory-gate job 分级挂载(manual/scheduled 先行, push-gate 收敛后挂)
assert_v153_ac_g1_ci_job() {
    if grep -q "memory-gate" "$REPO_ROOT/.github/workflows/ci.yml" && \
       grep -q "workflow_dispatch" "$REPO_ROOT/.github/workflows/ci.yml" && \
       grep -q "realtotal_gate" "$REPO_ROOT/.github/workflows/ci.yml"; then
        note "v153_ac_g1_ci_job: CI memory-gate job 在位(分级挂载 manual/scheduled 先行)✓"
    else
        die "CI memory-gate job 缺失/未分级(AC-G1 CI 载体未落)"
    fi
}

# AC-G2: selftest 锚绑定机制化——红侧⑦增条目变异+动态字面整形
assert_v153_ac_g2_registry_bind() {
    if grep -q "red7_registry_append_detected" "$REPO_ROOT/scripts/tests/verify_release_gate_selftest.sh"; then
        note "v153_ac_g2_registry_bind: selftest 红侧⑦增条目变异在位 ✓"
    else
        die "selftest 红侧⑦缺失(AC-G2 ① 锚绑定双向补齐未落)"
    fi
    if grep -q "RED_SIDE_COUNT" "$REPO_ROOT/scripts/tests/verify_release_gate_selftest.sh"; then
        note "v153_ac_g2_registry_bind: selftest 动态红侧计数字面整形在位 ✓"
    else
        die "selftest 动态字面整形缺失(AC-G2 ③ 三红侧陈旧字面未整)"
    fi
}

# AC-G2: 锚绑定纪律落位——3d 登记 check14 条目须同批重锚(硬条款, tasks 版本级 Step13.4)
assert_v153_ac_g2_anchor_bind_discipline() {
    if grep -q "同批重锚\|同步重锚\|重锚" "$REPO_ROOT/openspec/changes/v1.5.3-gate-and-convergence/tasks.md"; then
        note "v153_ac_g2_anchor_bind_discipline: 3d 重锚纪律硬条款在位 ✓"
    else
        die "tasks.md 缺同批重锚硬条款(AC-G2 ① 纪律未文档化)"
    fi
}

# ── v154 新增: L5 日期防呆守卫 ─────────────────────────────

# L5 (v1.5.4 新增, 1d W2 裁定): CHANGELOG/ROADMAP/发布文档条目日期 ≤ 当日
# v1.5.3 W① 未来日期判例机制化——未来日期(> 当日)→ FAIL(真不变量)。
# ==当日 仅作 3d-3i 发布窗 D 面纪律(非本守卫断言)。日期定谳源=本机 date(CST)唯一权威;
# comm 显示钟为 UTC 不可信(判例入注)。红侧构造: 注入未来日期条目 → 断言 FAIL。
# ★★ `v1.9.18` `P4` 订正(承 `docs/V1918_RULINGS_05.md` §二 `P4` · `test` `M1E_PIPELINE_PROBLEMS.md` §P4):
#   旧形 `date +%Y-%m-%d` 取 **ambient `TZ`** ⇒ 而上注自陈「定谳源 = **CST**」⇒ ★ **名实不符**。
#   ★ 实证(`#6` 容器): `.xuanwu/release/Dockerfile.verify-release` ∧ `.xuanwu/snippets/setup-rust-ci.sh`
#     **皆无 `TZ` 之设** ⇒ 随基镜像 = **UTC** ⇒ `today` 得 `2026-10-24`,而文档日期 `2026-10-25`
#     于 CST **即当日** ⇒ 判「未来日期」= ★ **假红**(判据钉 TZ 承其自陈之语义, 非放宽判据)。
#   ★ 治: **显式钉 `TZ=Asia/Shanghai`** —— 使「定谳源」与「注释所陈」一致, 且**不随宿主/容器漂**。
#     ★ 禁取「宿主 `date`」或「取二 TZ 之较宽者」: 前者即今之 ambient 之弊, 后者等于**弃判据**。
assert_v154_l5_date_guard() {
    local today
    # ★ 时区显式钉(CST = 判据之语义基)—— 非 ambient、非宿主、非 UTC
    today="$(TZ=Asia/Shanghai date +%Y-%m-%d)"
    local f fut
    fut=0
    for f in "$REPO_ROOT/CHANGELOG.md" "$REPO_ROOT/ROADMAP.md" "$REPO_ROOT/openspec/specs/roadmap.md"; do
        [[ -f "$f" ]] || continue
        while read -r d; do
            [[ -z "$d" ]] && continue
            if [[ "$d" > "$today" ]]; then
                die "L5 日期防呆: $f 含未来日期 $d > 当日 $today(CST=Asia/Shanghai 显式钉 · comm 显示钟 UTC 不可信)——v1.5.3 W① 判例机制化 FAIL"
                fut=1
            fi
        done < <(grep -oP '\d{4}-\d{2}-\d{2}' "$f" || true)
    done
    if [[ "$fut" -eq 0 ]]; then
        note "v154_l5_date_guard: 日期防呆通过(全文档条目日期 ≤ 当日 $today, CST=Asia/Shanghai 显式钉)✓"
    fi
}

# ── v151 承继判据(★ v1.9.0 P0-2 后: 十一 ⇒ 九 —— `ac4_codegraph_bound` ∧ `ac1_syntect_lazy`
#    二条随 checkout 依赖同批删, 见档头)────────────────────────
assert_v151_ac4_wasmtime_lazy
assert_v151_ac5_worker_default
assert_v151_ac6_arena_cap
assert_v151_ac7_dual_value
assert_v151_crates_absent
assert_v151_path_zero
assert_v151_xwcode_git_absent
# v151 新增有界化判据(承继)
assert_v151_ac3_rayon_cap
assert_v151_ac3_tokio_cap
assert_v151_ac8_guard_param
# ★ v1.9.0 P0-2: 原 `assert_v151_ac4_codegraph_bound` ∧ `assert_v151_ac1_syntect_lazy` 调用点已删。
# ★ v1.9.0 P0-2: 原 `assert_v152_ac_cg_lazy_boot` / `assert_v152_ac_cg_lazy_ensure` /
#   `assert_v152_ac_cg_dual_bounds` 三调用点已删(xwcore 面 checkout 断言 ⇒ 归 xwcore 自仓 gate)。
# v153 新增 AC-G1/AC-G2 门禁化判据
assert_v153_ac_g1_mem_gate
assert_v153_ac_g1_ci_job
assert_v153_ac_g2_registry_bind
assert_v153_ac_g2_anchor_bind_discipline
# v154 新增 L5 日期防呆守卫
assert_v154_l5_date_guard

if [[ "$FAIL" == "1" ]]; then
    die "守卫未全过"
    exit 1
fi
# ★ v1.9.0 P0-2: 原 SKIP_COUNT 警示支(P0-4 之 WARN 化面)随 `ac1_syntect_lazy` 删除而废 ——
#   本档已无 checkout 读取 ⇒ 【无跳过路径】⇒ 该支【无对象】(禁留死支)。读数之纯净由
#   空 `CARGO_HOME` 跑(`EXIT=0`)自证, 见档头「后果之自证」。
note "v154 十五守卫全过 ✓(★ v1.9.0 P0-2 后: 二十 ⇒ 十五 —— 五条 checkout 依赖断言删除, 见档头)"
exit 0