#!/bin/bash
# ds-sweep-cron —— launchd 包装器（report-only）
#
# owner 2026-09-04 拍定「A+B 档自动 / C 档排队 / 定时任务触发」后落地。
#
# ⛔ 本脚本只**取数与报告**，不修任何东西、不 commit。
#    「A 档自动修」需要 launchd → headless agent 那一步，⚠️ 那条链路我尚未实测，
#    ⛔ 故不在此处盲上（见 docs/decision-queue.md Q7）。
#
# ⚠️ 环境名（AGENTS.md §2.14「性能/读数自称必须带环境名」）：
#    launchd 的 `bash -l` 在本机解析到的是 ServBay 的 node（v22.21.1），
#    **不是**交互 shell 的 nvm node（v24.15.0）。两者读数已实测一致（2026-09-04），
#    但本脚本每次仍把真实版本写进产物 —— ⛔ 别再假设它们一样。
#
# ⛔ fail-closed：找不到 node / 找不到仓 / 采集器自称装置故障（exit 2）时，
#    一律在日志里显式喊出来并以非 0 退出。⛔ 绝不静默 exit 0。

set -u

LAB="${LAB:-$HOME/Documents/AICoding/VS_Code/ai-ds-lab}"
DS="${DS_ROOT:-$HOME/Documents/AICoding/VS_Code/tvu-design-system}"
STATE_DIR="${STATE_DIR:-$HOME/.claude/ds-sweep}"
LOG="$STATE_DIR/ds-sweep.log"

mkdir -p "$STATE_DIR" || { echo "FATAL 建不了 state dir $STATE_DIR" >&2; exit 3; }

TS="$(date +%Y-%m-%dT%H:%M:%S%z)"
DAY="$(date +%Y-%m-%d)"
OUT="$STATE_DIR/sweep-$DAY.json"

log() { echo "$*" | tee -a "$LOG"; }

# ── 前置：装置在不在（⛔ 缺了要喊，不能静默跳过）─────────────────────────
if ! command -v node >/dev/null 2>&1; then
  log "[$TS] FATAL node 不在 PATH —— launchd 不继承交互 shell 的 PATH。PATH=$PATH"
  exit 3
fi
if ! command -v pnpm >/dev/null 2>&1; then
  log "[$TS] FATAL pnpm 不在 PATH —— 6 条闸一条都跑不了。PATH=$PATH"
  exit 3
fi
if [ ! -f "$LAB/metrics/ds-sweep.mjs" ]; then
  log "[$TS] FATAL 找不到采集器 $LAB/metrics/ds-sweep.mjs"
  exit 3
fi
if [ ! -d "$DS/.git" ]; then
  log "[$TS] FATAL 找不到 DS 仓 $DS"
  exit 3
fi

NODE_V="$(node -v 2>/dev/null)"
NODE_PATH_REAL="$(command -v node)"
PNPM_V="$(pnpm -v 2>/dev/null)"
HEAD_SHA="$(git -C "$DS" rev-parse --short HEAD 2>/dev/null || echo '?')"

# ── 取数（⛔ 不带管道 —— 管道会吞退出码，lab:N47）──────────────────────
node "$LAB/metrics/ds-sweep.mjs" --ds "$DS" --out "$OUT" >"$STATE_DIR/last-run.txt" 2>&1
RC=$?

# 环境名写进产物旁边，⛔ 不只写进日志（日志会轮转/被清）
cat > "$STATE_DIR/sweep-$DAY.env.json" <<EOF
{
  "sweptAt": "$TS",
  "dsHead": "$HEAD_SHA",
  "exitCode": $RC,
  "env": {
    "invokedBy": "launchd (bash -l)",
    "node": "$NODE_V",
    "nodePath": "$NODE_PATH_REAL",
    "pnpm": "$PNPM_V"
  },
  "note": "⚠️ launchd 的 node 与交互 shell 的 nvm node 可能不同版本；引用本产物的读数时带上本 env"
}
EOF

# ── 判读（三档退出码必须分开报，⛔ 不许合并成「失败」）──────────────────
case $RC in
  0)
    log "[$TS] OK   @$HEAD_SHA 全清（扫描面内）· node $NODE_V"
    ;;
  1)
    RED=$(node -e 'const r=require(process.argv[1]);console.log(r.verdict.redGateCount)' "$OUT" 2>/dev/null || echo '?')
    STALE=$(node -e 'const r=require(process.argv[1]);console.log(r.verdict.staleLedgerCount)' "$OUT" 2>/dev/null || echo '?')
    log "[$TS] ATTN @$HEAD_SHA 要人看：闸红 $RED · 度量线断 $STALE —— 明细 $OUT"
    log "         A 档（机械判据+修法唯一）可直接修；C 档（价值取舍/文档与 Figma 冲突/放宽闸）⛔ 写进 docs/decision-queue.md"
    ;;
  2)
    log "[$TS] BROKEN @$HEAD_SHA 采集器自称**装置前置不成立**（exit 2）"
    log "         ⛔ 这不得读作「DS 没问题」—— 见 $STATE_DIR/last-run.txt"
    ;;
  *)
    log "[$TS] UNEXPECTED @$HEAD_SHA 采集器退出码 $RC（不在 0/1/2 之内）⇒ 当装置故障处置"
    ;;
esac

exit $RC
