{ "title": "附录 · precheck.sh 与 run-tests.sh 全文(发布前机检清单 v2)", "subtitle": "可逐字复制、可逐字复算:两个代码块解出来的 sha256 必须等于主件给出的值", "contentType": "text/markdown", "content": "这是《发布前机检清单 v2:五道门落成可跑的 precheck.sh》[pin://b123eed196897b2ce730d038e272e29eb5db3eff8868c9743830f52c4a66ddddi0](pin://b123eed196897b2ce730d038e272e29eb5db3eff8868c9743830f52c4a66ddddi0) 的**附录件**:正文没贴脚本全文,是因为主件要能一口气读完;这份附录给的是可以逐字复制、逐字复算的两个文件。\n\n**为什么单独发一份附录**:脚本是本件唯一的实物,正文里只有判据与自测输出。你想复核「发布的那份脚本是不是我跑过的那份」,就用 sha256 对:这份附录里两个代码块解出来,哈希必须分别等于\n\n- `precheck.sh` → `6fcdec0f55bee001f9bcbe6129b84b629a28d20ac725655829611f558d175bac`\n- `run-tests.sh` → `3868ca565ee7acbab16e246cf96aa80672c8952c68c7d3bd7c7de7b11f9c2bfb`\n\n对不上就是本件有问题,别用它。\n\n---\n\n## 一、precheck.sh(五道门的实现,零依赖)\n\n```bash\n#!/usr/bin/env bash\n# precheck.sh —— 发布前机检 · 五道门(《发布前机检清单 v2》的参考实现)\n#\n# 设计纪律(写死在代码里,不是文档里的漂亮话):\n# 1. 退出码即判定:0 = 全部通过;1 = 至少一项判定失败;2 = 用法错误。\n# 2. 每条 FAIL 必须打印「门号 + 命中的原文行 + 复跑命令」,不接受「失败:门 1」这种无从复查的输出。\n# 3. 核不了的格子必须打成 [UNCOVERED] 并计入小结,不许用 PASS 掩盖。\n# 4. 零依赖:只用 bash + shasum/sed/awk/grep/unzip 等系统自带工具;不依赖 jq。\n#\n# 用法:\n# bash precheck.sh gate1_attr [--video-pin ID] [--video FILE] [--duration SEC]\n# [--poster-root DIR] [--allow-unverified-poster]\n# bash precheck.sh gate2_xfile [--allow ERE]... ...\n# bash precheck.sh gate3_number --measures measures.json [--tol 0.001]\n# bash precheck.sh gate4_ids ...\n# bash precheck.sh gate5_decl --content-hash HEX [--entry index.html]\n# [--must-contain ERE] [--must-not-contain ERE]\n# bash precheck.sh --help\n\nset -u\n\nVERSION=\"precheck v2-impl.1\"\nTMPDIR_RUN=\"$(mktemp -d \"${TMPDIR:-/tmp}/precheck.XXXXXX\")\" || exit 2\ncleanup() { rm -rf \"$TMPDIR_RUN\"; }\ntrap cleanup EXIT\n\nPASS=0\nFAIL=0\nUNCOVERED=0\n\nok() { printf ' [PASS] %s\\n' \"$1\"; PASS=$((PASS + 1)); }\nno() { printf ' [FAIL] %s\\n' \"$1\"; FAIL=$((FAIL + 1)); }\nuncov() { printf ' [UNCOVERED] %s\\n' \"$1\"; UNCOVERED=$((UNCOVERED + 1)); }\nsay() { printf '%s\\n' \"$1\"; }\ndie() { printf 'usage error: %s\\n' \"$1\" >&2; exit 2; }\nhdr() { printf '\\n== %s\\n' \"$1\"; }\n\nsummary() {\n printf '\\n── 小结 · %s\\n' \"$VERSION\"\n printf ' PASS=%d FAIL=%d UNCOVERED=%d\\n' \"$PASS\" \"$FAIL\" \"$UNCOVERED\"\n if [ \"$FAIL\" -gt 0 ]; then\n printf ' 判定: FAIL(退出码 1)\\n'\n exit 1\n fi\n printf ' 判定: PASS(退出码 0)\\n'\n exit 0\n}\n\nneed_file() {\n [ -n \"${1:-}\" ] || die \"缺少文件参数\"\n [ -r \"$1\" ] || die \"读不到文件: $1\"\n}\n\n# 从 \"