#!/usr/bin/env bash
# v1.4.3 AC11 G1-G6 完成判定门脚本(结构收尾终版全门)
# 判定铁律(用户裁定): 所有代码要不就在 xwkernel,要不就在一个插件,没有例外。
# 逐门 EXIT 留痕(L1 交付形态): 单命令全过=GATE_RC=0, 任一门 FAIL=GATE_RC=1。
# v143 守卫调用纳入(G1/G2 已由 v143 覆盖, 承继不重写)。
# v1.5.1 AC8 (用户裁定改派主线): G 门载体世代参数化——自动解析现役守卫代,
# G5 接线对现役代自动跟进(根治 F-3g-1 手工接线债: 世代交替须含 G 门载体层)。

set -u
GATE_RC=0
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
CROSS_REPO_DIR="${CROSS_REPO_DIR:-}"   # 跨仓联合电池根(AC10 申报形态, 空=跳过 G5 跨仓面)

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

# ── AC8: 现役守卫代自动解析 ──────────────────────────────────────
# 扫描 scripts/tests/v*_structural_guards.sh, 取世代号最大者为现役守卫。
# 世代号=文件名 v(\d+)_structural_guards.sh 的数字段(v150>v143>v142>v141>v140>v137)。
# 守卫翻页(新世代文件落位)→ G5 接线自动跟进, 零手工改线(F-3g-1 判例根治)。
active_guard_gen() {
    local max=0 f
    for f in "$REPO_ROOT"/scripts/tests/v*_structural_guards.sh; do
        [[ -e "$f" ]] || continue
        local gen
        gen="$(basename "$f" | sed -E 's/^v([0-9]+)_structural_guards\.sh$/\1/')"
        [[ "$gen" =~ ^[0-9]+$ ]] || continue
        [[ "$gen" -gt "$max" ]] && max="$gen"
    done
    echo "$max"
}

active_guard_script() {
    local gen
    gen="$(active_guard_gen)"
    [[ "$gen" != "0" ]] && echo "$REPO_ROOT/scripts/tests/v${gen}_structural_guards.sh"
}

# 2c C1 早退分支 (2026-09-23): 本脚本尾部裸 exit $GATE_RC 且 main 块无 BASH_SOURCE
# 守卫——外部 source 本脚本会顺带执行整门 G1-G6 后 exit 杀 sourcing shell(检查14b
# 原以 bash -c 'source...' 解析 active_guard_script 即中招: guard 恒空)。本分支提供
# 纯函数查询出口: bash $0 --print-active-guard → 仅回显现役守卫路径, 零门执行。
# 位置约束: 必须在 active_guard_script 定义之后(早退调用依赖函数先定义)。
if [[ "${1:-}" == "--print-active-guard" ]]; then
    active_guard_script
    exit 0
fi

# ── G1: 主线 Cargo.toml path 计数=0 ──────────────────────────────
gate_g1_path_zero() {
    local n
    n="$(grep -c '"crates/' "$REPO_ROOT/Cargo.toml" || true)"
    if [[ "$n" == "0" ]]; then
        note "G1 path 计数=0 ✓"
    else
        die "G1: 主线 Cargo.toml path 计数=$n ≠ 0"
    fi
}

# ── G2: crates/ 零 git 跟踪文件(r32-④ 版控语义化: 物理残留免疫) ──
gate_g2_crates_absent() {
    if [[ -z "$(git -C "$REPO_ROOT" ls-files crates/ 2>/dev/null)" ]]; then
        note "G2 crates/ 零跟踪文件 ✓"
    else
        die "G2: crates/ 下存在 git 跟踪文件"
    fi
}

# ── G3: 产品代码物理住址 ∈ {xwkernel 仓, 插件仓} 逐行对账 ─────────
# 对账面: 主线仓 src/ 仅极薄根 bin(调 kernel_host::boot::run); 无 crates/ 无 src 下产品模块。
gate_g3_physical_address() {
    local leaks=0
    # 主线 src/ 产品面检查: 极薄根 bin 合法面 = main.rs 单文件调 kernel_host
    [[ -f "$REPO_ROOT/src/main.rs" ]] || die "G3: 主线 src/main.rs 缺席(装配面不完整)"
    # 主线产品代码黑名单面(应零存在): crates/ 已删; 历史退役面
    local banned=("xw-runtime" "m3_seam_adapter" "diagnostic_seam")
    for b in "${banned[@]}"; do
        if [[ -e "$REPO_ROOT/$b" ]] || ls "$REPO_ROOT"/src/*"$b"* >/dev/null 2>&1; then
            die "G3: 主线物理残留 '$b'"
            leaks=1
        fi
    done
    # r32-④: crates 以 git 跟踪面判(物理残留免疫)——残留目录不解锁铁律
    if [[ -n "$(git -C "$REPO_ROOT" ls-files crates/ 2>/dev/null)" ]]; then
        die "G3: 主线 crates/ 存在 git 跟踪文件(版控语义判据)"
        leaks=1
    fi
    # 主线 src/ 产品 mod 面(除 main.rs 应零 .rs)
    #
    # ★★ v1.9.12 `M3-b`(承 `ar` 裁25 裁5 **取甲(最小)** · 治 test `M3-g3`):
    #   **具名豁免** `pure.rs` —— 本谓词(`v1.4.3` 时点)**早于** `v1.7.2 AC1`,而后者自
    #   `src/main.rs` **合法抽出** `pure.rs`(`std-only` 纯函数 · 承 `ar` 裁决 `05` 裁1 三条件:
    #   ① 零依赖 ② 行为零变 ③ `#[path]` 同源机制经 `ac1_miri_leg.sh` 实证锁定)——
    #   该档系**产品真逻辑**(深测靶**同源面**,非拷贝)∧ 已入**检查14 名册**
    #   (`verify_release.sh` 之 `parse_worker_threads` 面)⇒ 本谓词与其现实**失配** ⇒ 假红。
    #   ★ 豁免之形 = **逐名可审**(显名清单 · **非**通配/前缀)—— 余者**仍零容忍**
    #     (任何新增非 `main.rs`/`pure.rs` 之 `src/*.rs` 照旧判红 ⇒ 判据力不缩)。
    #   ★ 潜伏性(照实 · 双方一手一致): 本档**整门不在跑线** —— `verify_release.sh` 唯调
    #     `--print-active-guard`(**纯函数早退**)⇒ 本 G3 之红**非阻塞**;本笔为**谓词正名**
    #     (消潜伏假红),零现行影响。
    local src_rs
    local g3_src_exempt=(pure.rs)
    local g3_find_excl=() e
    for e in "${g3_src_exempt[@]}"; do g3_find_excl+=(! -name "$e"); done
    src_rs="$(find "$REPO_ROOT/src" -name '*.rs' ! -name 'main.rs' "${g3_find_excl[@]}" 2>/dev/null | wc -l)"
    if [[ "$src_rs" != "0" ]]; then
        die "G3: 主线 src/ 存在 $src_rs 个非 main.rs 产品文件(应在各插件仓; 具名豁免 = ${g3_src_exempt[*]})"
        leaks=1
    fi
    [[ "$leaks" == "0" ]] && note "G3 产品代码物理住址对账 ✓"
}

# ── G4: 消费方向全 git dep + 锥锁反查 DUAL=0 ─────────────────────
gate_g4_cone_lock() {
    # r32-③: 吞诊断修——>/dev/null 2>&1 改落文件, FAIL 时回放诊断(审计 P0: 锥锁
    # 反查失败仅见"钉漂移/多实例"零细节, 排障盲)
    local out; out="$(mktemp)"
    if bash "$REPO_ROOT/scripts/tests/cone_lock_reverse_lookup.sh" >"$out" 2>&1; then
        note "G4 锥锁 DUAL=0 ✓"
    else
        die "G4: 锥锁反查存在钉漂移/多实例——诊断:"
        sed 's/^/      /' "$out" >&2
    fi
    rm -f "$out"
}

# ── G5: 红绿电池 C1-C6 + 全套锚(跨仓联合电池) ──────────────────
gate_g5_batteries() {
    # 主线电池: 锚 0/0/0 四件套 + 现役守卫(AC8 参数化: 世代交替零手工接线——
    # v1.5.0 F-3g-1 裁定 a 承继: 钉面覆盖只强不弱, 守卫翻页 G5 自动跟进)
    local guard
    guard="$(active_guard_script)"
    if [[ -n "$guard" ]]; then
        # r32-③: 吞诊断修——守卫输出落文件, PASS 时注记尾部诊断供人读, FAIL 时回放
        local gout; gout="$(mktemp)"
        if bash "$guard" >"$gout" 2>&1; then
            note "G5 主线电池: $(basename "$guard") ✓"
        else
            die "G5: 现役守卫 FAIL($(basename "$guard"))——诊断:"
            sed 's/^/      /' "$gout" >&2
        fi
        rm -f "$gout"
    else
        die "G5: 无现役守卫(active_guard_script 解析失败)"
    fi
    # 跨仓联合电池(AC10 定谳底账: 1672; kernel 285 须生态完整 checkout)
    if [[ -n "$CROSS_REPO_DIR" ]] && [[ -d "$CROSS_REPO_DIR" ]]; then
        local total=0
        for r in kernel xwcore xwrepl xwtui xwcomm xwmgmt xwdiag; do
            local dir="$CROSS_REPO_DIR/$r"
            if [[ ! -d "$dir" ]]; then
                note "G5 $r 目录缺席(跳过, 需生态完整 checkout)"
                continue
            fi
            local n
            n="$(cd "$dir" && CARGO_TARGET_DIR="$CROSS_REPO_DIR/.target-$r" cargo test --workspace 2>/dev/null | grep -oE 'test result: ok\. [0-9]+ passed' | awk '{s+=$4} END{print s+0}')"
            note "G5 $r 电池: $n"
            total=$((total + n))
        done
        note "G5 跨仓联合电池合计: $total(AC10 底账 1672; kernel 285 须完整 checkout)"
    else
        note "G5 跨仓联合电池: CROSS_REPO_DIR 未设, 跳过(AC12/3j 联动完整跑)"
    fi
}

# ── G6: PLUGIN_VIEW 终版(全 ✓ 零例外) ─────────────────────────
gate_g6_plugin_view() {
    if grep -q "全 ✓ 零例外\|36/36" "$REPO_ROOT/docs/PLUGIN_VIEW.md" 2>/dev/null; then
        note "G6 PLUGIN_VIEW 终版(全 ✓ 零例外)✓"
    else
        die "G6: PLUGIN_VIEW 未达终版(无 36/36 全 ✓ 落档)"
    fi
}

gate_g1_path_zero
gate_g2_crates_absent
gate_g3_physical_address
gate_g4_cone_lock
gate_g5_batteries
gate_g6_plugin_view

if [[ "$GATE_RC" == "0" ]]; then
    note "G1-G6 全过 ✓"
else
    die "G 门存在 FAIL(见上)"
fi
exit "$GATE_RC"