Files
Jyotisha/docs/tasks/TASK-gate-log-volume-20261004.md
T

8.3 KiB
Raw Blame History

TASK:门禁 validate 日志过大,网页打不开 — 2026-10-04

基线

  • 开工时 git fetch origin --prune 后的最新 origin/staging,写本单时是 baf4ae8b 之后的文档提交。
  • 分支 codex/gate-log-volume-20261004,工作树 .worktrees/gate-log-volume-20261004。

事故实证

  • 第六批 baf4ae8b 的门禁 validate 失败(Gitea task 6691、run 3170),staging 仍部署 153c6e99。
  • 产品负责人打开 job 页面,「Validate backend, package, frontend, and database contracts」这一步日志太大,网页加载不出来,看不到报错。
  • 这一步是 .gitea/workflows/backend-quality-gate.yml 里 validate job 的单个 run: 块,依次跑 ruff、py_compile、run_quality_gate.py --profile quick --skip-yoga-logic --skip-frontend-runtime、commercial_privacy_artifact_scan.py --json、python -m build、npm test --prefix frontend、npm run lint。
  • 本机(10-04)测得的输出量:
来源 行数 字节 原因
npm test --prefix frontend(tsx --test,默认 TAP) 约 26,800 约 1.2 MB 4,932 条测试,每条带 duration_ms 等 YAML 块,通过的也打印;数据库集成测试 tests/database-*.test.ts 也在里面
run_quality_gate.py --profile quick 约 14,000 约 0.66 MB run()(subprocess.run(cmd, …) 不捕获输出)把子脚本整份 JSON 报告直接打到日志:interpretation_source_inventory_gate.py 约 11,000 行,audit_capabilities.py --mode validate 约 2,000 行,character_level_inventory_manifest.py 约 260 行;开头还 print(json.dumps(profile, indent=2))
python -m build 约 2,900 约 0.22 MB setuptools 逐个文件打印 copying … / adding …
合计 4.4 万行以上 2 MB 以上 全部挤在同一个 step,失败点埋在中间

根因

门禁把「全部明细」当默认输出,并且把 7 个检查合成一个 step。成功的检查也刷屏;失败时既看不出是哪一项失败,网页也渲染不出来。

决策记录(产品负责人 2026-10-04)

  1. ①②③ 三项都做。
  2. 授权修改 .gitea/workflows/backend-quality-gate.yml,只限本单 T3 所述的拆分步骤和输出重定向。不改触发条件、paths: 过滤、job 依赖、runner、密钥、超时、发布与部署逻辑。AGENTS §2.7 规定改 workflow 只能由产品负责人触发,本条即为触发。
  3. 本机验收时 npm test 仍输出完整 TAP(我方按测试名逐条比对失败名单,依赖它);只有门禁环境才精简。

硬红线

  1. 检查本身一项都不能少,也不能放宽。 每个检查的命令、参数、退出码语义不变;任何检查失败,门禁照样失败。不得用 || true、continue-on-error,不得吞掉退出码。用管道时必须 set -o pipefail,或者显式取退出码。
  2. 失败时日志里必须能看到:失败的是哪一项;失败测试的名字和报错正文。快速门子步骤失败时,至少给出该子步骤输出的最后 200 行。
  3. 完整明细不能丢:写进 runner 上的文件(如 $RUNNER_TEMP 或工作区内的 gate-logs/),并在失败时把路径打出来。不新增 artifact 上传(上传动作要新的 action 依赖,不在本单范围)。
  4. 本机默认行为不变:
    • npm test 不带 CI 环境变量时输出与现在逐字节同类(TAP);
    • run_quality_gate.py 加 --verbose 时恢复现在的全量输出。
  5. 门禁 workflow 的文本被 frontend/tests/staging-backend-workflows.test.ts 等合同测试断言。改 workflow 必须同步改这些测试,并按 AGENTS §7.3 写三栏。动手前先 grep -rn 一遍 frontend/tests/ 和 tests/(AGENTS §7.8)。
  6. 不用 git stash,不切换别人的工作树,开工前先 df -h /。

任务分解

T1 快速门只打摘要(scripts/run_quality_gate.py)

  • run() 改为捕获子进程的 stdout / stderr:
    • 成功时只打一行:✓ <步骤名> <用时 s>;
    • 失败时打 ✗ <步骤名> exit=<码>,再打该步输出的最后 200 行,并把完整输出写到 gate-logs/<序号>-<步骤名>.log,打出路径。
  • 开头的 profile JSON 改成一行摘要。
  • 新增 --verbose:恢复现状(不捕获,直接透传)。
  • 捕获输出时要保留子进程的超时与退出码语义,现有 test_timeout_seconds 等参数照旧生效。
  • 验收:
    • 本机 --profile quick 输出不超过 150 行;
    • 人为让一个子步骤失败(测试里用假命令),能看到 ✗、最后 200 行和日志路径,退出码非 0;
    • --verbose 时的输出与改前同类;
    • 新增 tests/test_run_quality_gate_output.py。

T2 前端测试在门禁上精简(frontend/)

  • 新增启动脚本(例如 frontend/scripts/run-tests.mjs),package.json 的 test 改为调用它,测试文件范围保持 tests/*.test.ts tests/*.test.tsx:
    • 没有 CI / GITEA_ACTIONS 环境变量时:与现在完全相同(TAP 到 stdout);
    • 门禁环境:用 Node 内置的 dot reporter 输出到 stdout,同时用 tap reporter 写到 gate-logs/frontend-tests.tap。跑完后从 TAP 文件里提取并打印:# tests / pass / fail / cancelled 汇总,以及每条 not ok 的测试名和其后的报错块(每条最多 60 行)。
  • 退出码等于测试进程的退出码(AGENTS §10:同时看 cancelled 和退出码,BUG-995)。
  • test:db、test:deployment 不动。
  • 验收:
    • 本机 npm test 输出与改前同类,按测试名比对失败名单相同;
    • CI=true npm test 输出不超过 600 行,末尾能看到 24 条本机已知失败(DB / Docker 类)的名字和报错;
    • 测试总数不变。

T3 拆分门禁步骤(.gitea/workflows/backend-quality-gate.yml)

把「Validate backend, package, frontend, and database contracts」拆成按顺序执行的独立 step,每个都 set -euo pipefail、export PATH="$PWD/.venv/bin:$PATH":

  1. Lint and compile Python:ruff 和 py_compile;
  2. Python quality gate (quick):run_quality_gate.py …(T1 之后已精简);
  3. Privacy artifact scan;
  4. Build Python package:python -m build > gate-logs/python-build.log 2>&1,失败时打最后 200 行;
  5. Frontend and database tests:npm test --prefix frontend(T2 之后已精简);
  6. Frontend lint;
  7. Frontend production build (non-push):保留原有 $GITEA_EVENT_NAME 判断和 600 秒超时。
  • 每一步一行命令对应原来的一行命令,不增不减(红线 1)。
  • gate-logs/ 目录在第一步前创建。
  • 验收:
    • staging-backend-workflows.test.ts 等合同测试按新结构更新(三栏),全部通过;
    • 推 staging 后,Gitea 页面每个 step 都能打开,总日志量(各 step 合计)不超过 3,000 行;
    • 拆分前后执行的检查集合逐项相同(在进度记录里列表对照)。

T4 记录

  • docs/BUG_HISTORY.md 新增一条(门禁日志不可读,排查失败被阻塞),关联 run 3170 / task 6691。
  • CHANGELOG.md;docs/tasks/PROGRESS-gate-log-volume-20261004.md(改前 / 改后行数表、检查集合对照表);docs/tasks/README.md 改为「已实现待验收」。

让步顺序

T1 → T2 → T3 → T4。T3 碰到 workflow 合同测试改不动时,先交 T1 + T2(不改 workflow 也能把日志压到几千行),T3 写进进度记录待议。

开工前置命令

cd /workspace/Jyotisha && git status -sb | head -1
git fetch origin --prune
git worktree add -b codex/gate-log-volume-20261004 .worktrees/gate-log-volume-20261004 origin/staging
df -h /
grep -oE "BUG-1[0-9]{3}" docs/BUG_HISTORY.md | sort -u | tail -1
grep -rn "backend-quality-gate\|run_quality_gate" frontend/tests tests | cut -c1-120 | head -40

验收口径

  • Python 快速门(默认精简模式与 --verbose 各跑一次);新增测试通过;英文对照、隐私测试通过。
  • 前端:tsc 0 错;lint 0 error;本机 npm test 失败名单与开工基线逐条相同;CI=true npm test 行数与汇总正确。
  • 门禁 workflow 的合同测试全部通过。
  • 不 push,由 Claude 验收后推 staging;推送后第一次门禁运行时,由产品负责人确认网页能打开各 step。

BUG 编号起点

开工时核对最大号 +1(10-04 实测最大号 BUG-1229)。