Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE
8.3 KiB
8.3 KiB
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里validatejob 的单个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)
- ①②③ 三项都做。
- 授权修改
.gitea/workflows/backend-quality-gate.yml,只限本单 T3 所述的拆分步骤和输出重定向。不改触发条件、paths:过滤、job 依赖、runner、密钥、超时、发布与部署逻辑。AGENTS §2.7 规定改 workflow 只能由产品负责人触发,本条即为触发。 - 本机验收时
npm test仍输出完整 TAP(我方按测试名逐条比对失败名单,依赖它);只有门禁环境才精简。
硬红线
- 检查本身一项都不能少,也不能放宽。 每个检查的命令、参数、退出码语义不变;任何检查失败,门禁照样失败。不得用
|| true、continue-on-error,不得吞掉退出码。用管道时必须set -o pipefail,或者显式取退出码。 - 失败时日志里必须能看到:失败的是哪一项;失败测试的名字和报错正文。快速门子步骤失败时,至少给出该子步骤输出的最后 200 行。
- 完整明细不能丢:写进 runner 上的文件(如
$RUNNER_TEMP或工作区内的gate-logs/),并在失败时把路径打出来。不新增 artifact 上传(上传动作要新的 action 依赖,不在本单范围)。 - 本机默认行为不变:
npm test不带 CI 环境变量时输出与现在逐字节同类(TAP);run_quality_gate.py加--verbose时恢复现在的全量输出。
- 门禁 workflow 的文本被
frontend/tests/staging-backend-workflows.test.ts等合同测试断言。改 workflow 必须同步改这些测试,并按 AGENTS §7.3 写三栏。动手前先grep -rn一遍frontend/tests/和tests/(AGENTS §7.8)。 - 不用
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 内置的
dotreporter 输出到 stdout,同时用tapreporter 写到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":
Lint and compile Python:ruff 和 py_compile;Python quality gate (quick):run_quality_gate.py …(T1 之后已精简);Privacy artifact scan;Build Python package:python -m build > gate-logs/python-build.log 2>&1,失败时打最后 200 行;Frontend and database tests:npm test --prefix frontend(T2 之后已精简);Frontend lint;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各跑一次);新增测试通过;英文对照、隐私测试通过。 - 前端:
tsc0 错;lint 0 error;本机npm test失败名单与开工基线逐条相同;CI=true npm test行数与汇总正确。 - 门禁 workflow 的合同测试全部通过。
- 不 push,由 Claude 验收后推 staging;推送后第一次门禁运行时,由产品负责人确认网页能打开各 step。
BUG 编号起点
开工时核对最大号 +1(10-04 实测最大号 BUG-1229)。