#!/bin/bash # 第七轮(死断言处理后的复验): # A. axe harness 扩到「tag 通道 + 规则级通道」——先 2 路由 sanity,再全站 34 路由 × 4 组合 # B. Lighthouse 去掉 3 条死断言后重跑,证明 EXIT=0 且 0 warning set -u cd /Users/zhangxiang/Codes/Novalon/novalon-website || exit 1 LOG=/tmp/final-chain7.log HARNESS=docs/acceptance/2026-09-21-axe/axe-contrast-evidence.mjs CRAWLER=docs/acceptance/2026-09-21-axe/crawl-sitemap.mjs PORTS() { lsof -nP -iTCP:3000 -iTCP:3100 -sTCP:LISTEN 2>/dev/null | grep -c LISTEN; } echo "=== chain7 started $(date -u +%FT%TZ) ===" > "$LOG" echo "PREFLIGHT_LISTENERS=$(PORTS) $(date -u +%FT%TZ)" >> "$LOG" npx next start -p 3100 > /tmp/axe-server8.log 2>&1 & SRV=$! code=000 for i in $(seq 1 40); do code=$(curl -s -o /dev/null -w '%{http_code}' http://localhost:3100/ 2>/dev/null || true) [ "$code" = "200" ] && break sleep 3 done echo "AXE_SERVER_UP=$code $(date -u +%FT%TZ)" >> "$LOG" # 全站清单(口径与 chain6 相同:sitemap ∪ 预渲染产物 ∪ 站内链接 BFS) BASE=http://localhost:3100 SEED=/tmp/axe-sitemap2.xml \ MANIFEST=dist/standalone/dist/server/app OUT=/tmp/axe-sitemap-all5.xml \ node --input-type=module -e "$(cat $CRAWLER)" > /tmp/crawl6.log 2>&1 echo "EXIT_CRAWL=$? $(date -u +%FT%TZ)" >> "$LOG" grep -a "^crawled" /tmp/crawl6.log >> "$LOG" # sanity:只用 2 条路由跑新代码路径,避免 14 分钟后才发现探针本身有 bug python3 - <<'PY' import re src = open('/tmp/axe-sitemap-all5.xml', encoding='utf8').read() blocks = re.findall(r'.*?', src, re.S) open('/tmp/axe-sitemap-sanity.xml', 'w', encoding='utf8').write( '\n\n' + "\n".join(blocks[:2]) + "\n\n") print('sanity urls:', len(blocks[:2])) PY echo "EXIT_SANITY_CROP=$?" >> "$LOG" SITEMAP=/tmp/axe-sitemap-sanity.xml BASE=http://localhost:3100 OUT=/tmp/axe-sanity-out \ node --input-type=module -e "$(cat $HARNESS)" > /tmp/axe-sanity.log 2>&1 echo "EXIT_SANITY=$? $(date -u +%FT%TZ)" >> "$LOG" sed -e 's/\x1b\[[0-9;]*m//g' /tmp/axe-sanity.log | grep -aE "^(chromium|firefox)/|^PASSED|^SUMMARY|FATAL|Error" | head -14 >> "$LOG" # 保留 chain6 证据,再产出最终树的新证据 cp docs/acceptance/2026-09-21-axe/axe-evidence.json \ docs/acceptance/2026-09-21-axe/axe-evidence-chain6-tagonly.json 2>/dev/null SITEMAP=/tmp/axe-sitemap-all5.xml BASE=http://localhost:3100 \ OUT=docs/acceptance/2026-09-21-axe \ node --input-type=module -e "$(cat $HARNESS)" > /tmp/axe-sweep8.log 2>&1 echo "EXIT_AXE_FULL=$? $(date -u +%FT%TZ)" >> "$LOG" node -e "const j=require('./docs/acceptance/2026-09-21-axe/axe-evidence.json');console.log('AXE routeCount='+j.routeCount+' rows='+j.rows.length+' passed='+j.passed+' extraRules='+JSON.stringify(j.extraRules)+' summary='+JSON.stringify(j.summary))" >> "$LOG" 2>&1 kill "$SRV" 2>/dev/null pkill -f 'next start -p 3100' 2>/dev/null sleep 3 echo "POST_AXE_LISTENERS=$(PORTS)" >> "$LOG" { echo echo "===== chain7 lighthouse(移除 3 条死断言后)$(date -u +%FT%TZ) =====" npm run lighthouse 2>&1 } | sed -e 's/\x1b\[[0-9;]*m//g' >> docs/acceptance/2026-09-21-gates/lighthouse.txt 2>&1 echo "EXIT_LIGHTHOUSE=${PIPESTATUS[0]} $(date -u +%FT%TZ)" >> "$LOG" # 只统计本轮(chain7 段)残留的死断言,历史段保留作对照 awk '/chain7 lighthouse/{f=1} f' docs/acceptance/2026-09-21-gates/lighthouse.txt \ | grep -ac "not a known audit" | sed 's/^/CHAIN7_DEAD_AUDIT_WARNINGS=/' >> "$LOG" sleep 3 echo "POST_FINAL_LISTENERS=$(PORTS)" >> "$LOG" echo "=== chain7 done $(date -u +%FT%TZ) ===" >> "$LOG"