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

115 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 写进进度记录待议。
## 开工前置命令
```bash
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)。