diff --git a/docs/tasks/README.md b/docs/tasks/README.md index a4663d24..875d1ce2 100644 --- a/docs/tasks/README.md +++ b/docs/tasks/README.md @@ -420,3 +420,4 @@ | `TASK-astrologer-rulings-batch4-20261003.md` | `PROGRESS-astrologer-rulings-batch4-20261003.md` | Rath 当前大运进全部领域卡(卡预算 12,000→12,500、总 18,000→18,500,修改 BUG-1160/1161 决定);报告年运强度表改 Tajika 五分法(与年主同口径);校正打分不换,等第六轮 | 已实现待验收(T1–T3 完成) | 分支 `codex/astrologer-rulings-batch4-20261003`(未推送;BUG-1221~1222;校正分数不变、未升版本) | | `TASK-astrologer-rulings-batch5-20261004.md` | `PROGRESS-astrologer-rulings-batch5-20261004.md` | 占星师第六轮:Rath 双主星按 p.43(a)–(e)、罗计尊贵按 Rath Table 9(仅 Narayana 内)、子运方向 p.51 例外与书内分歧标注、Wadiyar 两对标软件特例;年主选不出时不再用 Muntha 主星顶替(对齐上游 03bea6ed);Rath 替换校正 v5 重试算(研究)(BUG 从 1223 起) | 已实现待验收(T2–T5 完成;T1 按红线停下 blocked;T6 研究分支已跑) | 分支 `codex/astrologer-rulings-batch5-20261004`(未推送;BUG-1223~1227;校正分数不变、未升版本);研究分支 `codex/narayana-rath-rectification-trial-20261004`(不合入) | | `TASK-astrologer-rulings-batch6-20261004.md` | `PROGRESS-astrologer-rulings-batch6-20261004.md` | 第七轮裁定(共享仓书面回复,产品采用;问 1 选 A):Rath 版双主星按 p.43 (a)–(e)(BUG-1227 解除 blocked,推翻第五批红线 2 的 Table 17 年数底线);第 5 级宫主度数只倒算计都(p.71 脚注 42);罗计旺陷 ±1 年;同宫两主比经度;BUG 从 1228 起 | 待验收 | 分支 `codex/astrologer-rulings-batch6-20261004`(BUG-1227~1229;校正分数文件未改、未升版本) | +| `TASK-gate-log-volume-20261004.md` | `PROGRESS-gate-log-volume-20261004.md` | 门禁 validate 单步日志 4.4 万行 / 2 MB 网页打不开(run 3170):快速门只打摘要(失败给末 200 行 + 日志文件)、前端测试门禁上 dot + 失败汇总(本机仍 TAP)、拆分 validate 为 7 个 step(产品授权改 workflow,只限拆分与重定向);检查一项不少 | 待领取 | 分支 `codex/gate-log-volume-20261004` | diff --git a/docs/tasks/TASK-gate-log-volume-20261004.md b/docs/tasks/TASK-gate-log-volume-20261004.md new file mode 100644 index 00000000..2474ec6d --- /dev/null +++ b/docs/tasks/TASK-gate-log-volume-20261004.md @@ -0,0 +1,114 @@ +# 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)。