diff --git a/docs/BUG_HISTORY.md b/docs/BUG_HISTORY.md index 1cae2087..8ea8e826 100644 --- a/docs/BUG_HISTORY.md +++ b/docs/BUG_HISTORY.md @@ -13425,3 +13425,19 @@ - 相关记录:BUG-1008、BUG-1009;`TASK-report-density-fix-20260923.md` F2 - 复发自:无;既有扫描正确触发,缺的是已核实碰撞的精确登记。 - 修复版本:缺陷引入 `bbd96d3b`;F2 工作树修复待验证,未确认部署。 + +## BUG-1011 | 快照落库的数据库测试把 42 万字节 SQL 当一个命令行参数,Linux 上启动即失败 + +- 状态:investigating(根因已复现,修复待执行;数据库层从未真跑过) +- 首次发现:2026-09-23 +- 最近更新:2026-09-23 +- 影响面:`frontend/tests/database-personal-report-sections.test.ts` 中报告密度快照一例;`backend-quality-gate` 的数据库测试步骤。生产写入走 RPC 请求体,不经命令行,不受影响。 +- 用户现象:无用户界面现象。门禁在含该测试的提交上变红;报告快照行在真实 Postgres 里的写入、幂等与越权隔离从未被验证。 +- 触发条件:在 Linux 上以 Docker 跑 `npm run test:db`(即门禁环境)。 +- 根因:`tests/helpers/postgres-fixture.ts` 的 `psql` / `psqlAs` 用 `psql -Atc ` 把整段 SQL 作为单个 argv 元素传给 `docker compose exec`。该测试把整份快照(含 374,097 字节的附录 Markdown)内联进 SQL,单个参数 428,557 字节,超过 Linux 单参数上限 `MAX_ARG_STRLEN` 131,072 字节。验收时用同一段 SQL 以同样方式调用 `/bin/true`,稳定得到 `spawn E2BIG`。执行方两轮都因 Docker 地址池耗尽未跑数据库测试,验收机无 Docker,因此一直没暴露。 +- 修复:待执行,见 `TASK-report-density-fix2-20260923.md`。 +- 验证:待执行。 +- 防复发:数据库测试辅助函数不得把 SQL 放进命令行参数,一律经标准输入或文件传入;新增一条断言覆盖超过 131,072 字节的 SQL。 +- 相关记录:BUG-1005、BUG-1009 +- 复发自:无 +- 修复版本:— diff --git a/docs/tasks/README.md b/docs/tasks/README.md index 0b23b868..54e269c4 100644 --- a/docs/tasks/README.md +++ b/docs/tasks/README.md @@ -170,7 +170,8 @@ | 任务书 | 进度 | 主题 | 状态 | 落点 | | --- | --- | --- | --- | --- | | `TASK-report-density-20260922.md` | `PROGRESS-report-density-20260922.md` | **报告信息密度与原始附录(BUG-1003~1007)**:与源头仓 PL9 全量报告同资料实测:对照 847,632 字符 / 8,044 表格行,我方 309,357 / 1,478。缺口不在引擎——20 张分盘全表、KP 四表、Ashtakavarga 四类、Shadbala 六分量、Avastha、Sahams、年度都已算得出,但 `personal-report-contract.ts` 的 `REPORT_SECTION_KINDS` **没有表格类型**、`CHART_IDS` 只有 9 种,这些表在产品页报告里没有落脚字段。另测出对外原始附录泄漏 925 种 / 3,797 处工程标识符(`parameter_sensitive` 697、`cmd_full_reading` 68、`PyJHora`/`JHora` 35、`PL9` 页码 59),对照物同项为 0。**产品 2026-09-22 三点拍板**:层 1 按 8 组表 + 分盘扩到 16 张;层 2 原始附录直接给 C 端且先全显示;B 类大运族要显示。**决策记录已写明推翻 BUG-999 的两条红线**(专业参考不得作普通下载 fallback;`parameter_sensitive`/「参数敏感」命中整行剔除)——**仅限附录通道**,普通正文投影不动。硬红线:表格层服务端装配、writer 不得写表;对照物的替代大运族日期与 Shadbala 分量在源头仍未闭环(506 行 date mismatch、`production_tuning_allowed=false`),不得照搬升级。让步顺序与串行依赖(任务 3 → 任务 4 同改契约)见任务书 | **验收未通过**(2026-09-23):任务 1/2/4/5 通过;任务 3 事实表在普通报告里显示 447 个引擎键路径(P1);隐私门新增失败(任务书自身写入真实出生资料 BUG-1008 已清 HEAD,fixture 数值碰撞待登记);当时 BUG-1003~1007、PROGRESS、testing 清单缺失;F3 现已补前两项,testing 新建受工具边界阻塞仍缺。Node 22 前端 0 新增失败、`/` Static、gzip +0.007% | 实现 `bbd96d3b`(原 `f968cb21`,09-23 为清除 BUG-1008 重写历史;已在 staging,未部署);修复单 `TASK-report-density-fix-20260923.md` | -| `TASK-report-density-fix-20260923.md` | `PROGRESS-report-density-20260922.md` | **报告密度验收修复单(BUG-1009/1010 + 补写 1003~1007)**:F1 事实表改成真正的表(逐组规定列,普通报告可见格 0 个引擎键 / 0 个下标 / 最多 2 位小数,`sourcePath` 保留供回查;主运年数不得填出生剩余年数);F2 按既有机制登记 fixture 的数值碰撞(已独立重跑确认是虚构输入);F3 补 Bug 历史 / PROGRESS / 真人清单并更正「未提交推送」;F4 两份清洗规则只留一份(Python 版漏第三方页码);F5 writer 写表拦截补测试与提示;F6 事实表可打印。硬红线:不得弱化隐私扫描、不得强推或重写 staging(历史清除由产品负责人决定);Sade Sati 三轮日期是原任务书错误、不在本单 | **执行中**:F1/F2/F4/F5 分工实施,F6 与独立验收由主会话负责;F3 已补 Bug / 进度 / API 断言三栏,真人清单新建被工具拒绝,文件仍缺。隐私专项因禁读保护文件尚未全绿;未写浏览器或部署通过 | `codex/report-density-fix-20260923`,基线 `0d37bec15`;BUG-1008 原样保留 | +| `TASK-report-density-fix-20260923.md` | `PROGRESS-report-density-20260922.md` | **报告密度验收修复单(BUG-1009/1010 + 补写 1003~1007)**:F1 事实表改成真正的表(逐组规定列,普通报告可见格 0 个引擎键 / 0 个下标 / 最多 2 位小数,`sourcePath` 保留供回查;主运年数不得填出生剩余年数);F2 按既有机制登记 fixture 的数值碰撞(已独立重跑确认是虚构输入);F3 补 Bug 历史 / PROGRESS / 真人清单并更正「未提交推送」;F4 两份清洗规则只留一份(Python 版漏第三方页码);F5 writer 写表拦截补测试与提示;F6 事实表可打印。硬红线:不得弱化隐私扫描、不得强推或重写 staging(历史清除由产品负责人决定);Sade Sati 三轮日期是原任务书错误、不在本单 | **已验收,F1–F6 全部通过**(2026-09-23,`a12f2c0d`):事实表 130 行 / 600 格 0 引擎键 0 下标、主运年数 18、隐私门转绿、两份规则逐字节一致、写表拦截变异测试红→绿;Node 22 前端 3,748 / 26(名单与基线一致)、Python 948/0。剩数据库测试 E2BIG 另开 fix2(BUG-1011) | `a12f2c0d`(门禁 run 6294 红,未部署);真人清单 `docs/testing/report-density-20260922.md` | +| `TASK-report-density-fix2-20260923.md` | — | **快照数据库测试无法启动(BUG-1011)**:测试把 428,557 字节 SQL 作为单个 psql 命令行参数,超过 Linux 131,072 字节上限,门禁上 `spawn E2BIG`,快照行从未在真实 Postgres 跑过。改辅助函数经标准输入传 SQL,不得缩小快照;门禁另有既有红项不在本单 | **待领取** | — | | `TASK-report-sectioned-generation-20260830.md` | `PROGRESS-report-sectioned-20260830.md` | 分章节生成 | 已合入 | 见 PROGRESS | | `TASK-report-skill-parity-20260901.md` | `PROGRESS-report-skill-parity-20260901.md` | 内容对齐 skill 解读深度 | 已验收 | `90bad10d`、`ef1bd6df` | | `TASK-report-blocked-repairs-20260902.md` | `PROGRESS-report-blocked-repairs-20260902.md` | 全主题 blocked 修复 | 已验收 | `7faf8555` | diff --git a/docs/tasks/TASK-report-density-fix2-20260923.md b/docs/tasks/TASK-report-density-fix2-20260923.md new file mode 100644 index 00000000..0ec54f64 --- /dev/null +++ b/docs/tasks/TASK-report-density-fix2-20260923.md @@ -0,0 +1,84 @@ +# TASK-report-density-fix2-20260923 · 报告快照数据库测试无法启动 + +## 基线 commit + +- 被验收实现:`a12f2c0d`(`fix(report): make density facts readable and printable`,已在 `origin/staging`;门禁 run 6294 红,未部署,`/api/health` 仍为 `1bc6a954`) +- 修复分支:`codex/report-density-fix2-20260923`,从 `origin/staging` 起 + +## 上一轮修复单验收结论 + +`TASK-report-density-fix-20260923.md` 的 F1–F6 **全部通过**,只剩本单一项。 + +| 项 | 结论 | 证据 | +|---|---|---| +| F1 事实表可读 | 通过 | fixture 上 8 组、130 行、600 个可见格:引擎键名 0、数组下标 0、超过 2 位小数 0;130 个 `sourcePath` 全部能在 packet 中取回;主运表首段"年数"为 18.00,出生剩余 0.72 年移入说明;年度盘为空是因为 packet 确实没有年度行星位置,说明如实写"未返回" | +| F2 隐私门 | 通过 | 登记只放行那 5 个字符:钉死 fixture 来源、JSON 节点、行号与整行内容;负向测试证明多一处、换输入、换行都会重新报错。本机 `test_repo_privacy_markers.py` 全过 | +| F3 记录 | 通过 | BUG-1003~1007、1009、1010 已写,状态如实为 investigating;PROGRESS 含三栏说明;"未提交、推送"已更正。真人清单执行方被工具拒写,已由 Claude 补写 `docs/testing/report-density-20260922.md` | +| F4 规则一份 | 通过 | 共用 `scripts/reader_appendix_language.rules.json`;同一份 fixture markdown,Python 与 TS 输出逐字节相同,"第 N 页"为 0,行数不变 | +| F5 写表拦截 | 通过 | 去掉拦截后 6 条新测试红 4 条,恢复后全绿;writer 提示词已写明不输出表格 | +| F6 打印 | 通过(真浏览器待清单) | 打印前展开全部 `
`、打印后恢复原状态;打印样式避免行跨页 | +| 前端 | 通过 | Node 22:基线 3,730 / 26 失败 → 3,748 / 26 失败,名单逐条一致 | +| tsc / lint / build | 通过 | 0 错 / 0 error;`/` 仍 `○ Static`;首屏 gzip 623,329(与上一轮相同) | +| Python 快速门 | 通过 | 基线 946 passed / 1 failed(隐私)→ 948 passed / 0 failed | +| 数据库测试 | **未通过(本单)** | 见下 | + +P3 各项未修,按原修复单不算未通过:复合状态译成重复短语 318 次、`unclosed_divisional_chart` 等四个状态词仍在附录、`北交点Rahu` 这类中英拼接来自引擎自带字段。 + +## 事故实证 + +`frontend/tests/database-personal-report-sections.test.ts` 的快照一例把整份快照内联进 SQL,经 `tests/helpers/postgres-fixture.ts` 的 `psqlAs` 以 `psql -Atc ` 传入。按测试同样的构造方式生成的 SQL 为 **428,557 字节**,是单个命令行参数;Linux 单参数上限 `MAX_ARG_STRLEN` 为 131,072 字节。验收时把同一段 SQL 以同样方式传给 `/bin/true`,结果 `spawn E2BIG`。 + +所以这条测试在门禁(Linux + Docker)上启动 psql 之前就失败。快照行在真实 Postgres 里的写入、重复写入保留首版、他人不可读三条性质,**至今没有任何一次真实运行**。执行方两轮都因 Docker 地址池耗尽没跑,验收机没有 Docker。 + +## 根因 + +测试辅助函数把 SQL 放在命令行参数里。以前的数据库测试 SQL 都很短,从未碰到上限。 + +## 决策记录 + +- 本单不推翻任何决策。 +- 修的是测试辅助函数的传参方式,不是缩小测试数据。**不得用更短的 markdown 或裁剪过的快照来"让它过"**:快照体积正是要验证的东西之一。 + +## 硬红线 + +1. 快照内容保持真实全量(fixture 原样)。 +2. 不改 `personal_report_sections` 表结构、RPC 或迁移。 +3. 改辅助函数后,所有既有数据库测试必须照常通过;不得跳过、不得标 skip。 +4. 不得强推、rebase 或重写 `staging`。 +5. 测试总数不得低于 3,748。 + +## 任务分解 + +### G1 · SQL 改走标准输入(BUG-1011) + +`psql` 与 `psqlAs` 改为经标准输入(`execFileSync` 的 `input`)或临时文件(`psql -f`)传 SQL,不再放进 argv。 + +**验收标准**: +- 新增一条辅助函数测试:执行一段超过 131,072 字节的 SQL 并取回结果; +- 在有 Docker 的 Linux 上跑 `npm run test:db --prefix frontend`,快照一例与全部既有数据库测试通过,输出贴进进度记录; +- 若本机仍无法跑 Docker,以门禁 run 的数据库步骤结果为准,把 run 编号与该步通过的测试名写进进度记录。不得写成"本地通过"。 + +### G2 · 记录 + +`docs/BUG_HISTORY.md` 中 BUG-1011 按结果更新;进度记录追加本单一节。 + +## 让步顺序 + +只有 G1、G2 两项,都必须做。 + +## 已知且不属于本单的门禁红 + +staging 门禁自 2026-09-22 起在报告工作之前就一直红。本机与基线共有的前端失败里,除数据库类外还有 `viewport-breakpoint-contract`、`chat-composer-queue`、`chat-panel-scroll-guard`、`model-configuration-security`、`health-deployment`、`staging-backend-workflows`、`identity-auth-integration`、`admin-database`。本单修完后门禁仍可能因这些既有失败保持红色,**需要另开单处理**,不得在本单顺手修。 + +## 开工前置命令 + +```bash +git fetch origin --prune +git status -sb +git worktree add -b codex/report-density-fix2-20260923 .worktrees/report-density-fix2-20260923 origin/staging +docker info # 没有 Docker 就按 G1 最后一条走门禁证据 +``` + +## BUG 编号 + +BUG-1011(已由 Claude 写入 investigating 记录)。开工时核对最大号。 diff --git a/docs/testing/report-density-20260922.md b/docs/testing/report-density-20260922.md new file mode 100644 index 00000000..f42cdb29 --- /dev/null +++ b/docs/testing/report-density-20260922.md @@ -0,0 +1,35 @@ +# 报告密度:真人浏览器清单 + +对应任务书 `TASK-report-density-20260922.md` 与修复单 `TASK-report-density-fix-20260923.md`(BUG-1003~1007、1009、1010)。 + +自动化已验到这里为止(Claude 2026-09-23,实现 `a12f2c0d`):Node 22 前端 3,748 条测试,失败名单与基线逐条一致;事实表在 fixture 上 130 行、600 个可见格里没有引擎键名、数组下标或多位小数;首页仍是静态页。**下面每一条都需要登录态和真浏览器,没有做过,不能写成通过。** + +前提:staging 已部署到含 `a12f2c0d` 的版本(看 `https://staging.jyotisha.chat/api/health` 的 `deployment.gitCommit`)。用受控测试账号;用虚构或公开名人的出生资料,**不要用真实个人资料**。必须是部署之后**新生成**的报告,旧报告不会补出事实表。 + +## 报告页 + +- [ ] 打开 `/reports/`,正文照常,底部多出「分盘核对」和「计算数据核对表」两段。 +- [ ] 「分盘核对」里的盘一张张排开、不互相压住;向下滚动不卡顿、不闪回顶部。 +- [ ] 「计算数据核对表」默认收起。逐个点开 8 组:Vimshottari 主运、SAV 八分力、Shadbala 六分量、功能吉凶、Avastha 行星状态、附属星点与特殊上升点、Sade Sati 阶段框架、年度盘。 +- [ ] 每张表的表头是中文列名;表格里看不到带下划线的英文字段名(形如 `sign_idx`)、方括号编号(形如 `[0]`)或一长串小数。 +- [ ] Vimshottari 主运表里,每段的「年数」是整段长度(例如 18、16、19),不是 0.72 这类零头;出生时剩余年数写在表头下的说明里。 +- [ ] 当前主运、当前分运那一行的「当前」是「是」,其余是「否」。 +- [ ] Sade Sati 表只有上升 / 高峰 / 下降三个阶段和星座,说明里写着没有三轮起止日期。这是已知缺口,不算错。 +- [ ] 手机宽度(约 390px)下,宽表只在表格区域内横向滑动,整页不横向滚动。 + +## 两个下载 + +- [ ] 点「导出报告(.md)」,下载的文件和改动前一样:只有正文,没有事实表,也没有 `parameter_sensitive`、`PyJHora`、`PL9` 这类词。 +- [ ] 点「下载原始附录」,得到一份很长的 Markdown(几千行,上千行表格)。在文件里搜 `parameter_sensitive`、`PyJHora`、`JHora`、`PL9`、`cmd_full_reading`、`第 `+数字+` 页`,全部搜不到;表格里的英文字段名(如 `sign_cn`)保留,这是设计。 +- [ ] 原始附录结尾有「辅助时间轴适用性」表,每个大运族一行,写明适用或不适用的原因。 +- [ ] 对一份部署**之前**生成的旧报告点「下载原始附录」,应提示暂无原始附录或给出旧版附录,不应报错白屏。 + +## 打印 + +- [ ] 在「计算数据核对表」全部收起的状态下点「打印」,打印预览里 8 组表全部展开、表头每页都在、一行不被拆到两页。 +- [ ] 关掉打印预览后,页面上的表恢复成打印前的收起 / 展开状态。 +- [ ] 另存为 PDF,翻到事实表部分,确认 Vimshottari、SAV、BAV、Shadbala 四张表完整。 + +## 记录方式 + +每条写「通过 / 不通过 / 没法测」,不通过的截图(截图里不要带出生资料),附报告生成时间。结果交给 Claude 回填到 `docs/tasks/PROGRESS-report-density-20260922.md`。