feat: add chart waiting states and report block exports
Independent Staging Quality Gate / validate (push) Successful in 10m34s
Independent Staging Quality Gate / publish (push) Successful in 3m36s

Add bounded chart loading, per-layer retry states, and shared SVG skeletons. Add report block downloads with SVG, localized metadata, and inline deletion.

Record verification and retain CRLF export, full-build, and controlled-device acceptance blockers. User authorized staging delivery with these gaps documented.

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
jesse-ux
2026-09-24 12:33:09 +08:00
co-authored by Claude Code
parent 5ff43b47f3
commit 1420471ab1
51 changed files with 1858 additions and 219 deletions
+68 -2
View File
@@ -11155,7 +11155,7 @@
- 根因:`chart/page.tsx` `force-dynamic` 且 `await loadChartView()`,而 `loadChartView` 先串行 `/api/chart` 再并行四个后续调用。文档卸载重载期间浏览器里什么都没有。
- 修复:`/chart` 改为静态壳,客户端先画标题和返回,再取 `/api/chart-view`。进页只算主盘;分盘 / Chara / 西洋 / 七政按 tab 或非 D1 chip 按需取。超时改为 10 秒(实测主盘 0.60 秒,10 秒约 16 倍余量,避免再盯 45 秒空白)。等待句用「还没拿到」,不转圈。
- 验证:无 `view` 时外壳可见;挂起主盘不再依赖四个后续调用;源码合同禁止 `force-dynamic` / `loadChartView` 出现在 `chart/page.tsx`。
- 防复发:`/chart` 首字节不得等待四个后续引擎调用。揭幕后填 tab 不得再上 spinner / 骨架 / 「正在加载」。
- 防复发:`/chart` 首字节不得等待四个后续引擎调用。揭幕后填 tab 不得再上 spinner / 「正在加载」。2026-09-24 BUG-1016 产品决策仅允许星盘页 D1、非 D1 分盘、西洋盘位置复用 SVG 空盘骨架;表格区及其它页面仍禁止骨架。
- 相关记录:BUG-715、BUG-717、TASK-chart-page-blocking-open-20260915
- 复发自:无
- 修复版本:待发布
@@ -12564,7 +12564,7 @@
- 根因:三页各写各的等待布局——先渲染 46px 标题加一行短等待文案,数据到达后整块换成高正文。`SecondaryHeader` 的 `note` 未到时不渲染,标题区二次填充。`use-chart-page` 进页才 fetch,零缓存,每次都重放中间态。产品 2026-09-18 选定方案一:消灭中间态,不加 spinner,红线不动。
- 修复:三页共用 `SecondaryPageShell`(标题行高度固定、note 槽占位不塌、内容区撑满剩余视口,等待文案居中在该区)。星盘 / 星历 / 报告首屏进模块级缓存,同一会话再进直接用上次结果并后台静默刷新。侧栏三项在 `pointerenter` / `pointerdown` 预热数据。等待句仍是静态句(「这一张盘还没拿到。」等),没有 spinner / 骨架 / 「正在加载」。
- 验证:`frontend/tests/secondary-page-entry.test.ts`(三页 import 共享外壳、暖缓存第二次不经 null 等待、预取命中同一 inflight、CSS 内容区 min-height:0 且等待居中);既有 `chart-page-view` / `ephemeris-page` / sidebar 合同。浏览器量高度见 `docs/testing/secondary-page-entry-20260918.md`(无 Chrome)。
- 防复发:次级页进入不得再各写一套等待布局。揭幕后不得加 spinner / 骨架 / 「正在加载」。缓存必须模块级,组件 unmount 不能丢掉。
- 防复发:次级页进入不得再各写一套等待布局。揭幕后不得加 spinner / 「正在加载」;骨架禁令仅在星盘盘位被 2026-09-24 BUG-1016 决策有限推翻,其它页不变。缓存必须模块级,组件 unmount 不能丢掉。
- 关联记录:BUG-716、BUG-717、BUG-745
- 复发自:无
- 修复版本:`9ccb65b7`
@@ -13490,6 +13490,30 @@
- 复发自:无;与 BUG-745 同入口但不同根因。
- 修复版本:本次提交(执行分支 `codex/secondary-new-chat-intent-20260923`,基线 `1c95eb397`);2026-09-24 产品授权推 staging 供远程 review,精确 SHA 以实际推送及远端核对为准,部署尚待核验。
## BUG-1018 | 报告列表元信息直接显示英文深度与主题 id
- 状态:blocked(本地针对性回归通过;受控登录与部署未验证,不预写 resolved)
- 首次发现 / 最近更新:2026-09-24。
- 现象 / 触发:打开有报告的列表,元信息出现 standard、career 等内部 id,日期未按产品要求中文全写。
- 根因:`rowMeta` 直接拼 `report.depth` 与 `report.themes`;已存在主题中文映射但此入口未复用,深度映射缺失。旧入口测试只锁状态 / 导出路径,没有执行元信息 formatter。
- 修复:深度映射与主题映射同置 progress helper;rowMeta 使用中文全日期、中文深度和主题,未知 id 原样回退,非法日期显示时间未知;不改 GET 字段。
- 验证:真实 formatter 回归覆盖 standard / career、未知 id、空主题及无效日期;真实组件挂载显示中文。定向测试、类型与独立浏览器证据由本轮进度汇总,未以源码断言冒充真人。
- 防复发:新增 `report-row-delete.test.tsx` 的元信息执行测试;既有报告 API 日期投影、列表 cardSummary 合同保留。
- 关联:BUG-352(日期序列化 / 失败码)、BUG-574(列表字段查询);不是这两项复发,本轮不改路由。
- 修复版本:未提交,`codex/report-chapter-export-20260924`,固定基线 `5ff43b47f`。
## BUG-1019 | 报告 DELETE 接口存在但列表没有删除入口
- 状态:blocked(客户端实现及针对性回归通过;真实持久化 / 部署未验证)
- 首次发现 / 最近更新:2026-09-24。
- 现象 / 触发:报告列表没有删除按钮,用户无法管理已完成、生成中或未完成记录。
- 根因:owned DELETE API 已存在且有鉴权测试,但列表没有装配调用;旧测试只覆盖服务端删除,不检查用户可达入口。
- 修复:每行 44px 菜单只有删除;行内确认 / 取消;same-origin DELETE,in-flight ref 阻止双发。失败保留行和短错误,成功移除并 invalidate reports cache。cache epoch 拒绝旧 GET 回写,组件 tombstone 拒绝旧快照使行复活,旧 finally 不清掉新请求。
- 验证:真实挂载覆盖取消不请求、HTTP / 网络失败保留、重复点击仅一个 DELETE、成功回调;整个 Center 挂载覆盖成功移除及旧 GET 返回仍不复活;独立 cache race 验证 reset / 新旧请求。服务端鉴权 / owned-delete 既有 API 回归保留;不声称受控账号删除持久化已验证。
- 防复发:`report-row-delete.test.tsx` 动态交互与 race 锁;不用 window.confirm,不新增接口 / 数据库 / GET 字段。
- 关联:BUG-154(报告列表入口)、BUG-574(列表查询);分块导出是功能变更另记 CHANGELOG,普通投影继续遵守 BUG-999 / 1003。
- 修复版本:未提交,`codex/report-chapter-export-20260924`,固定基线 `5ff43b47f`。BUG-1016 / 1017 由并行星盘任务预留,本分支不抢号。
## BUG-1014 | 输入框源码合同未跟上已删除人物的发送限制
- 状态:resolved(run 2857 的 H3 门禁通过;staging 总门禁仍因 BUG-1011 失败,尚未部署)
@@ -13505,3 +13529,45 @@
- 相关记录:BUG-1000、BUG-1002;TASK-staging-gate-red-20260923.md。
- 复发自:无;源码合同落后于授权业务改动。
- 修复版本:`36a737616c67a251610662ccab76845b193993fb`(staging;未部署)。
## BUG-1016 | 星盘主盘等待句没有超时与登录出口,缓存异常路径留空
- 状态:blocked(本地动态回归、独立审查、首轮组合全量对比及隔离Chrome通过;完整构建、受控真人与部署未验收,不提前标resolved)
- 首次发现 / 最近更新:2026-09-24
- 影响面:星盘首屏 hook、共享快照缓存、fetch JSON 读取、盘位等待渲染。
- 现象 / 触发:请求不返回时一直显示等待句;401 跳转前仍为空;初始请求失败而缓存刚由其它路径补齐时 state 仍 null。
- 根因:只有 null / view,没有客户端期限;unauthenticated 快照映射为 null;catch 命中缓存后早退。预取与首次请求共用在途 promise,因此超时必须由共享请求持有,不能仅约束挂载后的新 fetch。
- 修复:共享请求(含预取和身份重试)25 秒 timeout signal;client_timeout 独立 status 对应 timedOut 文案;响应 JSON 的 abort 不误判 schema;缓存快照回填 state;401 在跳转前可见登录失败体。主盘空模型复用 VedicChartSvg,不复制几何,五 Tab 可见禁用;空盘与西洋盘共享唯一呼吸 CSS,减弱动态效果静止。
- 验证:chart-page-hook.test.ts 实际挂载 React hook,模拟期限触发、预取复用、缓存后到、401 缓存与响应、旧身份失败;chart-page-view.test.tsx 渲染骨架、禁用 Tab、空几何和 reduced-motion。完整成绩见本轮 PROGRESS,未把 Node 生命周期渲染当作浏览器证据。
- 防复发:BUG-716 / 966「不得骨架」条款由 2026-09-24 D1 仅限星盘盘位推翻;其它页面、表格和 spinner 禁令不动。首屏共享期限从预取起计时,旧身份完成或异常不得覆盖新缓存,读响应体同样受期限约束。
- 相关记录:BUG-715、716、717、723、966、996;TASK-chart-page-skeleton-wait-20260924。
- 复发自:BUG-966 的同一等待链覆盖不足;旧测试仅检验静态壳、缓存与无动画,未模拟挂起请求和后到缓存。BUG-996 的账户指纹与旧响应防线保留并追加旧异常回归。
- 修复版本:基线 5ff43b47f 上的本地工作树 codex/chart-page-skeleton-wait-20260924,未提交 / 未推送 / 未部署。
## BUG-1017 | 分盘与按需层失败仍永久显示等待句
- 状态:blocked(本地动态回归、独立审查、首轮组合全量对比及隔离Chrome通过;完整构建、受控真人 / 部署待验收)
- 首次发现 / 最近更新:2026-09-24
- 影响面:星盘 varga、Chara、西洋、七政按需数据与失败投影。
- 现象 / 触发:引擎忙、按需请求失败或抛错后 pending 清除,却无失败出口;分盘一直「这一分盘还没拿到」。
- 根因:hook 无 layerFailures,只接受顶层 ok;真实 assembleChartView 对后续层失败经 enginePayload 压为 null,外层仍 ok,连引擎 429 原因也在投影前丢失。该事实是任务书未覆盖的必要透传缺口。
- 修复:最小可选 layerFailures 投影保留既有引擎原因,未改路由、超时或并发;客户端逐层失败,重试先清失败再 pending,成功仅合并请求层,不抹其它已完成层。BFF rate_limited 保持原类,实际引擎429保留 engine_busy。分盘/西洋等待用空盘,大运/七政仍静态;失败均撤等待图并写对应原因。返回缺层不能标已加载,旧资料层结果不能写回。
- 验证:chart-page-hook.test.ts 真实 assemble→fetch解析→React hook 四层429、catch重试、响应体超时、BFF限流、无效429体、并发乱序、401及资料指纹过期;chart-page-view.test.tsx 分盘、西洋、七政、Chara 的失败句与等待图互斥。详见 PROGRESS。
- 防复发:层失败不能经 null 投影丢失;只有完整成功层可进入 loaded;失败不自动重试,显式点原 Tab/chip 重试,不增加入口。BUG-715/723 的429独立档及 BUG-717 按需、并发红线保留。
- 相关记录:BUG-715、716、717、723、966、996、1016。
- 复发自:BUG-715/723 的失败分档未覆盖按需层投影与组件出口;旧测试仅验主盘错误和端点不可用说明,未串联真实 busy 层响应到 hook。
- 修复版本:基线 5ff43b47f 上本地工作树,未提交 / 未推送 / 未部署。
## BUG-1020 | CRLF 普通报告下载保留图盘 JSON 围栏
- 状态:blocked(已独立复现,修复与D5旧导出逐字节合同冲突,未获有限例外授权)
- 首次发现 / 最近更新:2026-09-24。
- 影响面:旧普通Markdown下载与新分块导出的正文组。
- 现象 / 触发:真实引擎虚构golden仅将LF换成CRLF,正文下载残留22段图盘JSON;新分盘组仍可提取22盘。
- 根因:report-chart-block.ts的FENCE_RE在jyotish-chart语言标记后仅匹配LF,stripReportChartBlocks共用它;旧测试验证LF剥除和CRLF字节等价,没有覆盖含真实围栏的CRLF无JSON。
- 修复:尚未实施。建议仅支持语言标记后的CRLF,保留其余换行、SVG与投影;需先授权D5只对错误JSON残留作有限例外,D13不是该授权。
- 验证:独立只读审查,转换golden后正文25块/残留22围栏/仍与旧导出byte-equal;相关105/105通过不能替代此未通过项。
- 防复发:待补真实golden CRLF/混合换行无JSON回归及冻结旧LF输出字节锁;禁止只比较两个共同改过剥离器的函数而声称历史输出不变。
- 相关记录:BUG-999/1003;TASK-report-chapter-export-fix-20260924.md。
- 复发自:BUG-999同输出边界的未覆盖换行路径,继承剥离器缺陷,非本轮新增回归。
- 修复版本:未修复 / 未提交 / 未部署。
+7
View File
@@ -2,6 +2,13 @@
Purpose: read this file before substantial project work. It exists to stop repeat mistakes caused by multiple Codex windows, WorkBuddy mirrors, local drafts, backup folders, and partial cloud-git visibility.
## 2026-09-24 · 星盘与报告组合版本推送预检
- 产品在获知CRLF合同冲突及构建/真机缺口后授权push到staging。fetch成功,HEAD与origin/staging均为5ff43b47f;写入成功仍须push与ls-remote另核。
- Python3.11.7运行pre_work_check:remote verified,适配器/碎片扫描步骤成功,focused 22通过/2失败;缺历史workbuddy镜像断言、candidate_count=4小于workspace_residue_count=105,整体fail。未伪造目录、清理他人资料或修改测试。
- 首次调用输出重定向误落主工作目录,目标日志目录不存在、脚本未执行;随后明确进入组合树运行,日志仅存artifacts/combined-final-verification/push-pre-work-check.log。没有写主目录文件。
- 两单最终验证与剩余事项见对应PROGRESS;允许push不等于全部验收或部署通过。
## 2026-09-24 · 次级页新建意图交付预检
- 产品授权推送供远程 review;fetch 与 pre_work_check 远端可见性均成功,推送仍须另核 SHA,不将远端可读等同写入成功。
@@ -0,0 +1,109 @@
# PROGRESS · 星盘页盘位骨架与等待出口(2026-09-24)
## 交付授权(2026-09-24)
产品已明确要求“请你帮我push到staging”,授权将两单组合版本提交并快进推送。实际交付以push成功和远端SHA核对为准,不将推送当作完整构建、受控真机或部署通过。下述未提交状态描述的是验证时快照,BUG仍blocked,不提升main。
## 当前结论
T1–T4 已实现,通过定向、独立review与隔离真实Chrome,已串行整合到 `codex/chart-report-integration-20260924`。首轮组合全量已对照固定基线,无新增失败;完整构建、受控真机与部署仍有缺口。报告末次depth修正后的最终组合重验亦已完成,详见末节。未 commit / push / stash / 部署。BUG-1016 / 1017 暂 blocked,不以任务书要求的 resolved 字样替代真实验收。
- 实施基线:主会话已 fetch 并创建的 `5ff43b47f`;任务书旧基线 `8902e484` 仅作事故实证。本轮没有再切分支或改动主检出。
- 分支 / 工作树:`codex/chart-page-skeleton-wait-20260924` / `.worktrees/chart-page-skeleton-wait-20260924`。
- 依赖:仅建立授权的 `frontend/node_modules` junction,未安装或升级。固定 `D:/nvm/installs/v22.23.2/node.exe` v22.23.2,与主会话基线相同。
- 已读 AGENTS / CLAUDE、frontend AGENTS / DESIGN / VOICE、任务书、本地 Next `use-client` guide;本单纯前端与现有 BFF 投影,不运行基础设施预检。骨架只是既有空几何,没有数据编码或新分类调色板;不改原盘色。
## 逐项实施
| 项 | 实现 | 本地证据 / 尚欠 |
| --- | --- | --- |
| T1 主盘出口 | 共享 fetch(含侧栏预取、资料指纹重试)持有25秒 signal;client_timeout 映射 timedOut;JSON读取中超时不误判 schema;缓存已有view回填;401先呈现失败体再跳转 | React真实生命周期与模拟fetch,含预取、缓存、过期身份、401;真人/部署尚欠 |
| T1 层出口 | Map逐层记录失败;再次点原入口清失败并pending;失败不置loaded;成功只合并请求层,保留其它已成功层;BFF rate_limited不冒充engine_busy | assemble→fetch→hook四层429、catch重试、超时、坏429体、乱序成功与身份失效 |
| T2 盘位骨架 | VedicChartSvg导出空模型并支持skeleton,强制不画数据;西洋复用原SVG空模型;ChartPageSkeleton仅供星盘盘位;初始Tab可见禁用,主盘到后解禁 | 空盘几何与标签、busy、五禁用Tab、失败替换、静态表格均有渲染合同 |
| T2 动效与边界 | 唯一CSS keyframe:2.4s ease-in-out / 0.35↔0.6,reduced-motion静止0.5;无spinner/旋转/扫光 | CSS合同;真机视觉未验 |
| T3 规则 | AGENTS §6有限例外,DESIGN §9/§15及共享壳说明同步,VOICE新增唯一timedOut句 | BUG-716/966防复发条款同时注明有限推翻;其它页不变 |
| T4 记录 | BUG-1016/1017、CHANGELOG、BLOCKED、状态板、本记录与真机清单 | 未将本地实现当上线;Skill不bump |
## 任务书勘误与必要范围
1. 真实 `assembleChartView` 的后续层失败先经 `enginePayload` 变成 null,再返回 HTTP200/status=ok。单改 hook 无法恢复 429 原因。主会话确认必要范围后,给 `ChartViewOk` 增加可选 `layerFailures`,在 `chart-view-load.ts` 保留既有 engine_busy / engine_timeout / engine_bad_payload / engine_http_error 分类。未改 `/api/chart-view` 路由、引擎10秒期限、HEAVY_COMPUTE_PATHS、并发或任何Python文件。
2. 任务书 D5 写超时→timedOut;T1要求 status=client_timeout,以 T1 的明确状态要求为准:`client_timeout` 是状态,`timedOut` 仅是文案key。不把客户端超时加进出生资料失败原因数组。
3. 首次请求真正从共享缓存发出,故超时由 `refreshChartSnapshot` 建立而非 hook 单独建一个被已在途promise忽略的signal。预取起计时、资料指纹重试共用同一期限;过期epoch失败转当前刷新,不写回旧fallback。
4. BFF 自身 `rate_limited` 与引擎429不是同类,前者保留既有频繁打开句;只有引擎busy或没有有效业务体的HTTP429显示busy句。JSON读到一半发生abort仍是超时。
5. 各层响应带D1与其它未请求层的空占位,整体覆盖会在西洋成功后点D9丢西洋结果。客户端仅合并当前请求层;暖缓存进页的后台D1刷新迟到时,同身份已成功层也保留,动态乱序与暖刷新回归确保成功数据不退化。
6. 真机清单“断网→timedOut”并非浏览器必然行为:网络立即拒绝应unavailable,持续挂起才达25秒期限;已写明两种测试,不伪造速度承诺。AbortSignal按活动时间计时,后台休眠不承诺墙钟25秒。
7. grep `chart-skeleton-breathe` 本身会命中声明与引用两行;按意图只允许CSS一个文件、一个keyframe定义、一处动画规则,不把合法引用误当第二套动画。
## 历史检索与旧防线核查
以等待原句、`/api/chart-view`、hook、层日志关键词检索并完整阅读 BUG-715/716/717/718/723/966/996(最大号1015,本轮1016/1017未被占用)。
| 原防线 | 核查 |
| --- | --- |
| BUG-715/723:引擎失败分档、429独立、日志不吞 | chart-view-engine 与既有定向测试仍在;此次补后续层到UI透传,不改既有引擎分类 |
| BUG-716:静态壳、只取D1、其它层按需 | 静态route未改,engine/route合同通过;仅“不得骨架”按授权有限推翻 |
| BUG-717:不改并发、不预取西洋/七政、不写速度成本眉标 | 路径/并发未动、按需入口不变,成功和失败视图合同保留 |
| BUG-718:跳过页面无需的外部证据 | birthPayload标志未动,route合同仍通过 |
| BUG-966:模块缓存、同inflight、稳定壳 | 缓存/共享壳不搬;预取共享期限补上;星历/报告无骨架断言不改 |
| BUG-996:账户+资料指纹、旧结果不可回写、错误分档 | 原定向全过;新增旧请求异常与旧层完成不得写新身份缓存 |
## 验证实测
日志均只在本树 artifacts,不纳入提交。
| 命令 / 范围 | 基线 | 当前 |
| --- | ---: | ---: |
| 固定5套定向:chart-page-view / secondary-page-entry / chart-profile-update-consistency / chart-view-engine / chart-view-route | 49 pass / 0 fail / 0 skip | 54 pass / 0 fail / 0 skip |
| 新增 chart-page-hook 真React生命周期 | 不存在 | 18 pass / 0 fail / 0 skip |
| 合计定向 | 49 | 72 pass / 0 fail / 0 skip |
| tsc --noEmit | 主会话持有 | 0错,exit0 |
| npm run lint | 主会话持有 | 0error / 119warning,exit0;不顺修既有warning |
| 组合首轮全量npm test | 3717 /3633pass/84fail | 3763 /3679pass/84fail;新增46全过、名称消失0、旧状态变化0 |
| 组合首轮build、Static、gzip | 默认junction失败;webpack Skill symlink EPERM | 两类失败相同;webpack编译/类型过,Static与gzip仍未验证 |
| 隔离Chrome | — | 星盘单树及组合树分别13/13通过 |
| 受控登录、iOS与staging health | 未执行 | 环境/验收缺口,见BLOCKED与真机清单 |
使用 `node --import tsx --test`,不是新增测试运行器;日志 `artifacts/chart-targeted-baseline.log`、`chart-targeted-final.log`、`chart-tsc.log`、`chart-lint.log`。新增测试真实执行 hook 与 fetch/schema/assemble,不仅匹配源码;仍不替代浏览器布局或后端线上压测。
## 既有断言变更(三栏)
| 原值 | 新值 | 原因 |
| --- | --- | --- |
| chart-page-view 冷主盘等待不得骨架 | 必须data-skeleton + aria-busy、五Tab禁用,仍无spinner/正在加载 | D1有限授权,增加反向约束 |
| chart-page-view 西洋pending不得skeleton | 必须data-skeleton,仍保留原等待句且禁止InlineSpinner | D2复用西洋空模型 |
| secondary-page-entry 星盘源码禁止skeleton | 必须ChartPageSkeleton引用,仍禁止InlineSpinner/正在加载 | 只放开星盘;星历与报告原断言不变 |
定向日志名称实测:原49个名称无消失,新增23个全通过。所有原测试名称保留,未删除测试;主会话最终还需对全量名称多重集合与基线逐项比较。
## 独立复核与隔离浏览器(2026-09-24)
- 独立只读审查未发现需阻断交付的正确性缺陷;复跑 hook/缓存/引擎/路由55条与视图17条全部通过;独立暖缓存乱序复现确认慢D1不会覆盖已成功D9。
- 系统 Chrome 153、全新临时profile、真实 ChartPageRoute→useChartPage→fetchChartView、真实CSS,接口白名单mock消费真实assembler与虚构golden,13/13场景通过,pageerror=0。覆盖375/390/1280冷进、D9 429与原入口重试、西洋骨架、七政/大运静态等待、减弱动态、主盘/分盘超时、BFF限流及401导航。
- 超时测试只在浏览器harness把原25000ms映射为500ms;未改业务源码。401证据为导航前DOM提交且布局可见,不保证实际快速跳转时足够读完。
- 证据仅本地 `artifacts/chart-report-browser-20260924/chart-2026-09-24T03-24-29-908Z/results.json`。浏览器已关闭,不使用真实资料、账号或凭据。该证据不替代完整Next服务器、真实后端、登录staging、iOS真机或部署验收。
## 组合验收与剩余事项
- 已完成两个工作树串行整合:secondary-page-data同时保留chart身份逻辑与reports通用cache epoch;VedicChartSvg同时保留骨架与报告hook-free Drawing,无第二份几何。
- 首轮84失败名称多重集合一致,83项完整诊断直接一致;appendices owner-read一项首轮fixture槽位pid ENOENT,单项复跑恢复基线duplicate migration诊断,未写成通过。Docker本轮可用,不套用上一单地址池结论。
- 固定基线失败分类:migration symlink文本38、Skill references文本9、Windows symlink EPERM13、双盘符路径6、POSIX路径/权限/UID/install11、python3/rsync不可用4、底因未证实exit1共3。明细在基线artifacts及组合 `artifacts/combined-verification`,不提交。
- 首轮3305非md文件起止hash相同:`e95f3f18801d10fa757e52622fa3fb850af2258fc0ff7c5667300b588f73a90c`。此后仅追加报告未知depth透传/测试断言,最终重验结果见末节。
- 待完整构建环境补Static/gzip,按真人清单完成受控验收后再决定BUG是否resolved;没有本轮commit/push/部署,不改main。
- 报告独立审查的CRLF/D5冲突是另单未通过项,不冒称两单全部完成验收。
## 最终组合快照复验(含报告depth末次修正)
- tsc0错;lint0error/119warning;3763 tests/3679pass/84fail/skip0。相对固定基线新增46全通过、名称多重集合消失0、旧状态变化0,84失败名称及84份归一化完整诊断全部一致;首轮fixture槽位竞态未复现。
- 开始/结束3305非md文件hash同为 `b076a2c2f40d1fdac1520fa88b38818f14847b7e4710047571a0f73052d580ce`,无代码漂移,仅文档变化。
- 默认build仍junction失败;webpack编译/类型过,Skill symlink EPERM未解除,本轮先报/api/consult而非基线daily-starlanguage(并行worker先报路径不同,底层原因相同)。Static/gzip仍未验,不写成通过。
- 证据:组合树 `artifacts/combined-final-verification`;首轮日志保留。
## 最终组合Chrome复验
- 组合树重新运行星盘13/13、报告14/14,pageerror/非白名单请求0;真实合并代码,不复用单树成绩。
- 合并VedicChartSvg同时经星盘骨架与报告无原SVG fallback实际下载验证,SHA256 `c59bced71cc9433a32c09c68d5aa437f3b8de8e95f3cb9c8b88baeecc19a2a00`,两runner记录前后稳定;chart10个/report9个核心文件无漂移。
- 组合星盘证据:主仓本地 `artifacts/chart-report-browser-20260924/chart-2026-09-24T03-59-56-966Z/results.json`;报告为 `report-2026-09-24T04-01-33-428Z/results.json`。浏览器已关闭;mock API边界、超时harness映射与无受控登录/iOS/部署的限制不变。
## 最终范围与根tests合同
独立审计未见两共享文件合并遗漏、无关源码或冲突marker;精选整合点8/8通过。根Python前端合同四文件18条:17通过、1既有失败。主题合同test_frontend_theme_contract.py:29期待旧ink-secondary #676762,基线HEAD的CSS已为#5f5f59,内存重放基线同样失败;未改CSS迎合旧合同。另三个session/daily/rectification/birth journey入口合同通过。无Python/API路由/依赖/workflow/并发改动,diff --check通过。
@@ -0,0 +1,145 @@
# PROGRESS · 报告分块导出与列表管理(2026-09-24)
## 交付授权(2026-09-24)
产品在获知下述未通过项与环境缺口后明确要求“请你帮我push到staging”。本轮按此授权提交组合版本并快进推送staging;实际交付以push成功与远端SHA核对为准,不代表CRLF合同已获变更授权或部署验收通过。以下“未提交/未推送”均为推送前验证快照;BUG仍blocked,不提升main。
## 当前结论
T1–T4 已实现并串行整合,但**不是全部验收通过**:独立审查复现 CRLF 输入保留图盘 JSON 的旧缺陷,与 D5 逐字节合同冲突,未授权改变 D5,记为未通过。构建、受控登录与真机仍有缺口。未 commit / push / 部署。
- 固定执行基线 `5ff43b47f38e378918c8b6bd967228185d7f02fe`,替代任务书事故实证旧基线。
- 实现树 `.worktrees/report-chapter-export-20260924`;最终组合树 `.worktrees/chart-report-integration-20260924`,分支 `codex/chart-report-integration-20260924`。
- Node v22.23.2 / npm10.9.8,复用已有依赖 junction,不安装或升级;42项顶层非可选依赖与 lock 精确匹配。
- 两份新记录最初受子代理报告写入限制,未绕过。用户随后明确选择“由主会话补齐”,本记录与 testing 清单由主会话按该授权创建。
## 实现与逐项验收
| 项 | 实现 / 证据 | 结论 |
| --- | --- | --- |
| T1 正文分块 | 唯一来源 buildLongformOutline(projectOrdinaryReportMarkdown(...));补 sourcePreamble/sourceMarkdown 无损切片,原阅读字段不变;LF golden 正文全选等于旧导出 | 主路径通过;CRLF 无 JSON 合同未通过 |
| T1 盘表 | 22个盘出现项(D9两次)+8组表;安全SVG优先复用,fallback共用 VedicChartSvgDrawing,无第二份几何或 react-dom/server;表格与页面共用显示转换 | golden与定向通过 |
| T2 抽屉 | 原生底部dialog、三组/三套餐、替换式选择、手动取消高亮、全选/清空、实际字符计数、0选禁用 | 组件与隔离Chrome通过 |
| T3 入口 | 旧整篇按钮替换为分块导出,#export ready后消费一次并清hash;打印及原始附录保留;只用已有数据/下载器 | 组件与隔离Chrome通过 |
| T4 列表 | 中文日期/深度/主题,未知字符串原样回退;三色状态;行内确认删除、防重复DELETE、失败留行、成功移除与cache epoch/tombstone防旧GET回写 | 定向通过;真实持久化未验 |
| T5 记录 | DESIGN、VOICE、CHANGELOG、BUG-1018/1019、任务书D13、本进度及真人清单 | 已补齐;BUG仍blocked |
无新网络请求用于导出,无剪贴板,无 spinner/骨架,不改数据库、GET API字段、生成管线、report-chart-grid-rehype、workflow、DNS或main。
## 决策与技术勘误
1. 用户执行中明确“分盘导出也需要带出svg”,随后要求继续。任务书 D13 有限替代 D4/T1 禁 SVG,不追溯声称原单已授权。
2. D5 保持不变:常用/正文全选与旧普通导出逐字节一致;**所有组全选**额外附盘/表,不与旧纯正文文件相等。
3. golden 为25正文+22盘出现项+8表=55块;D9出现两次,不按id去重。
4. 文件名helper返回stem,`.md`由既有下载器追加;实际字符数含Markdown/SVG标记,按Array.from计算。
5. fallback SVG共用hook-free绘图与受限序列化,离线presentation attributes不依赖应用CSS;不放宽普通投影安全边界。
6. 实际主题使用既有success/warning/danger/canvas token,不新增不存在的别名。
7. 组合SVG同时保留星盘empty/skeleton与报告Drawing出口;secondary缓存同时保留星盘身份epoch、报告失效epoch及未知depth透传。
## 独立审查:CRLF 合同缺口(未通过)
审查复跑105/105相关测试,但另以内存把真实虚构golden的LF转换为CRLF,发现正文下载仍有22个 `jyotish-chart` JSON围栏,同时仍与旧导出逐字节相同。已有测试通过不等于该边界安全合同通过。
根因:`report-chart-block.ts` 的 FENCE_RE 在语言标记后仅匹配 `\n`,不接受 `\r\n`;旧 ordinaryReportDownloadMarkdown 与新正文块共用此剥离器。这是**继承缺陷,不是本单新增回归**。新分盘提取已能识别CRLF,所以同一输入另可生成22盘块。
D13只授权SVG,不授权改变D5。本轮未静默修改剥离器或弱化JSON禁出断言。建议对CRLF围栏输入授权D5有限例外后,仅修语言标记后的换行匹配,冻结旧LF输出作独立回归;详见 `TASK-report-chapter-export-fix-20260924.md`。本项阻止把报告单称为全部验收通过。
另有非阻断观察:优先复用的旧golden引擎SVG实际为南印矩形布局,标题沿用chartAriaLabel的“北印度盘”;按D13保留原SVG,未擅改几何或原输出,图式/标题对齐待后续确认。
## 验证实测
| 项目 | 固定基线 | 本轮 |
| --- | ---: | ---: |
| 报告八套件 | 140/140 | 扩展定向205/205 |
| 报告基线测试名消失 | — | 0 |
| 报告本单新增 | — | 23(纯块12、抽屉6、删除/元信息/cache5) |
| 星盘定向 | 49/49 | 72/72 |
| 组合首轮全量 | 3717 /3633pass/84fail | 3763 /3679pass/84fail |
| 组合首轮名称多重集合 | — | 消失0,新增46全通过,既有状态变化0 |
| 组合首轮tsc | 0错 | 0错 |
| 组合首轮lint | 0error/119warning | 0error/119warning |
| 默认build | junction越Turbopack root失败 | 同类失败 |
| webpack build | 编译/类型过,Skill symlink EPERM失败 | 同类失败 |
| Static / 动态路由标记、首页gzip±2% | 未取得完整构建产物 | 未验证 |
205与140的差额包含42条既有共享回归,不能写成本单新增65条。全量按名称**多重集合**比较,不只看汇总、不去重。
首轮84失败名称相同,83项归一化完整诊断直接一致;appendices owner-read用例首轮遇fixture `slot-1/pid ENOENT`,独立复跑恢复基线 `duplicate migration filename`。保留原失败日志,未将复跑写成通过。本轮Docker可用,不继承上一单地址池耗尽结论。
基线失败分类:migration symlink检出为文本38、Skill references链接文本9、Windows symlink EPERM13、双盘符路径6、POSIX路径/权限/UID/install11、python3/rsync不可用4、exit1且底因未证实3,共84。
首轮源码3305非md文件开始/结束SHA256均为 `e95f3f18801d10fa757e52622fa3fb850af2258fc0ff7c5667300b588f73a90c`。之后仅补未知depth parser与一条既有测试内断言,最终快照重验已完成,见末节;不将首轮数字冒称覆盖此末次修正。
证据均为本地artifacts,不提交:实现树 `report-baseline.log`、`report-final-targeted.log`、`report-tsc.log`、`report-lint.log`;固定基线树 `artifacts/chart-report-baseline-20260924`;组合树 `artifacts/combined-verification`(summary、名称/状态、完整诊断、单项复跑、源码hash)。
## 隔离真实浏览器
系统Chrome153、全新profile、真实组件/CSS/缓存函数、虚构golden和白名单mock;单报告树13/13通过,pageerror及非白名单请求0,8个核心文件hash前后相同,浏览器已关闭。覆盖套餐/手选/空选、4种真实下载、Esc/遮罩回焦、hash一次、375/390/1280布局/44px/两列/避侧栏、删除失败/重复/旧GET/缓存重挂载。
| 实际下载 | 字节 |
| --- | ---: |
| 常用/全部正文 | 221792 |
| 全部分盘(22 SVG) | 88288 |
| 仅核对表 | 7512 |
| 所有组全选 | 317596 |
LF常用逐字节等旧导出,所有下载ordinaryOutputLeaks为空;无应用CSS的SVG截图可读。证据:主仓本地 `artifacts/chart-report-browser-20260924/report-2026-09-24T03-50-59-992Z/results.json`。组合树另跑14/14通过(新增真实fallback下载),详见末节。
仓内交互测试使用真实React reconciler/state/effect及已挂载handler,不模拟事件冒泡或布局。浏览器宿主提供Next router、mock接口,**不等于完整Next集成、真实数据库、iOS/微信、登录staging或部署验收**。
## 既有断言三栏
| 原值 | 新值 | 原因 |
| --- | --- | --- |
| entry:Center含旧下载helper | #export且无旧helper/exportingReportId/exportError | D10改深链,删旧请求路径 |
| entry:download含GET URL/filename helper | 无fetch,保留ordinaryReportDownloadMarkdown/projection | 保留历史纯转换,抽屉复用唯一下载器 |
| entry:Center export error alert | 每行ReportRowDelete及错误role=alert | 导出移抽屉,删除失败行内反馈 |
| view:旧下载helper | ReportExportDrawer且无旧helper | D1/D10 |
| view:print disabled含exportBusy | exportOpen,仍保留printBusy/capability | 抽屉打开期间不同时打印 |
| longform-md:导出报告(.md) | 分块导出 | 授权入口替换,其余writer断言保留 |
原测试名称保留;新测试无SVG要求按D13替换为安全SVG+无JSON/泄漏。未知depth追加真实readReports→rowMeta断言,不只直接喂rowMeta。
## 历史核查
执行方已检索并阅读 BUG-125/154/156/247/352/455/486/496/526/534/574/610/966、999及1000–1015相关段。
- BUG-999/1003:普通投影、安全SVG、内部字段过滤不改;LF golden块leak=0与正文byte lock执行。CRLF围栏另列未通过,不据旧测试预写通过。
- BUG-154:报告入口不绑会话、生成/失败/未登录分支保留,API/entry回归通过,创建链不改。
- BUG-352/574:日期/card_summary/列表字段投影保留,当前路由读取独立card_summary。
- BUG-496:failure摘要fallback保留,不改writer预算/分类。
- BUG-526:仍用loadReportCandidateRange共享路径,不增加直接校正表SELECT。
- BUG-534:progress phase仍用isValidPersonalReportJobProgressPhase,不改job链。
- BUG-455:reports路由pricing_configuration_unavailable映射保留。
- BUG-966:共享壳、缓存、预热不搬;新增失效epoch回归,不增加报告等待动画。
- BUG-125/247/156/486/610:旧入口、生成/适配、引擎路径本轮未改,不以历史部署数字充当本轮证据,旧符号不保证逐字存在。
- BUG-1018/1019保持blocked,真实受控登录/持久化/部署未验。
## 剩余事项
1. 最终depth快照全量/类型/lint及组合Chrome已完成,见下。
2. CRLF无JSON与D5冲突按修复单保留blocked,不擅改已确认合同。
3. 在可完整构建环境验证四路由标记和首页gzip;iPhone、微信、受控登录持久化与health SHA按testing清单补验。
4. 无commit/push/部署,不改main/workflow/DNS,不清共享Docker资源,不修任务外warning,不提交artifacts或依赖链接。
## 最终组合快照复验(含未知depth修正)
- tsc exit0;lint0error/119warning;全量3763/3679pass/84fail/skip0。
- 对固定基线3717/3633pass/84fail:新增46全部通过,名称多重集合消失0、旧状态变化0;84失败名称及84份归一化完整诊断全部一致。首轮fixture槽位竞态未复现,首轮日志仍保留。
- 3305个非md文件开始/结束SHA256均为 `b076a2c2f40d1fdac1520fa88b38818f14847b7e4710047571a0f73052d580ce`;无代码漂移,期间仅文档变化。
- 默认build仍因跨root junction失败;webpack编译/类型通过,但Skill symlink EPERM。本轮15worker中先报路由/api/consult,基线先报daily-starlanguage,不能把报错路由差异藏掉;相同底层链接权限原因,完整Static/动态标记及gzip依然未验。
- 证据独立存放组合树 `artifacts/combined-final-verification`,没有覆盖首轮。上述自动化不消除CRLF独立审查未通过项。
## 最终组合Chrome复验
- 同一组合树重新打包并运行:星盘13/13,报告14/14,共27/27通过;pageerror与非白名单页面请求均0,两个context均已关闭。
- 人工合并VedicChartSvg的骨架与导出路径均实际执行。报告额外用真实golden去掉原SVG来源,真实Actions/Drawer下载触发VedicChartSvgDrawing fallback;离线无CSS时12宫轮廓、行星、星座号、图例、逆行线可读,截图已查看。
- fallback文件6095B、SHA256 `74c9e17eb97bcde581777c9dd0a2ffca80eed2ab89e4c2d0554205196921edd6`;其它四份下载hash与单树完全一致。D5证据限于该LF golden,不掩盖CRLF未通过项。
- 合并绘图文件SHA256 `c59bced71cc9433a32c09c68d5aa437f3b8de8e95f3cb9c8b88baeecc19a2a00`;chart10个/report9个源码hash前后均稳定。
- 主仓本地证据:`artifacts/chart-report-browser-20260924/chart-2026-09-24T03-59-56-966Z/results.json`、`report-2026-09-24T04-01-33-428Z/results.json`,后者目录含download-fallback.md及无CSS截图。仅专属artifacts,不提交;仍不等于登录staging、DB或iOS/微信真机。
## 最终范围与跨语言合同复核
独立只读审计确认共享SVG/缓存两单逻辑并存,没有API路由、Python、依赖/锁文件、workflow、部署或引擎并发配置改动,无冲突marker,diff --check通过。精选整合点8/8通过。
根tests四套前端源码合同实跑18条:17通过、1失败。`tests/test_frontend_theme_contract.py:29`仍期待 `--color-ink-secondary: #676762;`,基线HEAD原始CSS已是 `#5f5f59`;同一测试以内存基线CSS重放亦失败,确认既有合同欠账,未顺修。其它session management / daily and rectification / birth time journey入口合同通过。此项不混入前端npm test的84失败数字。
+3 -2
View File
@@ -170,7 +170,8 @@
| 任务书 | 进度 | 主题 | 状态 | 落点 |
| --- | --- | --- | --- | --- |
| `TASK-report-chapter-export-20260924.md` | — | **我的报告:分块导出抽屉 + 列表页中文元信息 / 状态色 / 删除**(原型 https://claude.ai/artifact/TM7SQetho1p3cDpVwj3RgE ,主按钮已由「复制」改为下载)。列表页 `rowMeta` 直接输出 `standard` / `career` 等英文 id(BUG-1018);`DELETE /api/reports/:id` 有接口无 UI(BUG-1019);阅读页只能整篇导出。**产品 09-24 拍板(两次)**:形态是部分导出——勾选章节后下载一个 .md,**不写剪贴板**;阅读页与列表页原「导出报告(.md)」按钮都删,全选 = 整篇导出(回归锁:全选文件逐字节等于旧导出);章节全列不做白名单(以 `projectOrdinaryReportMarkdown` 后的 H2 为准、`buildLongformOutline` 唯一切分器);盘 22 块 + 核对表 8 块另成两组;手机与桌面都是底部原生 `<dialog>` 抽屉,桌面限宽 760 不盖侧栏、≥860 两列;套餐常用 / 全部分盘 / 仅核对表。红线:导出文本过 `ordinaryOutputLeaks()`、零新请求、只走现有 `downloadMarkdownReport`、不做 PDF / 分享 | 待领取 | — |
| `TASK-report-chapter-export-fix-20260924.md` | `PROGRESS-report-chapter-export-20260924.md` | **CRLF图盘JSON残留(BUG-1020)**:旧剥离器只匹配LF;建议D5对错误围栏残留作有限例外,D13不构成该授权。 | 待裁决(blocked,未执行) | 组合候选未提交 |
| `TASK-report-chapter-export-20260924.md` | `PROGRESS-report-chapter-export-20260924.md` | **我的报告:分块导出 + 中文元信息 / 状态色 / 行内确认删除(BUG-1018/1019)**。旧整篇按钮由抽屉取代;常用 / 全部正文保持 D5 逐字节,所有组全选另附盘和核对表。后续产品裁决 D13:分盘必须带安全 SVG,有限替代原无 SVG 约束;JSON 围栏及内部字段仍禁。原生底部 dialog、760px、70%、860 两列、零额外请求、保留打印 / 原始附录。 | 待验收(CRLF合同未通过;完整构建 / 受控真机缺口) | 已整合 `codex/chart-report-integration-20260924`,未提交 / 未部署 |
| `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–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` | `PROGRESS-report-density-fix2-20260923.md` | **快照数据库测试无法启动(BUG-1011)——staging 恢复部署前的唯一阻塞**:门禁 run 2857 为 3,762 / 1 fail,唯一失败即此。测试把 428,557 字节 SQL 作为单个 psql 参数,超过 Linux 131,072 上限 → `E2BIG`。**09-23 更正做法**:不得改共享 `psql`/`psqlAs`(29 文件 522 次调用依赖 `-c` 单事务语义,`selectAsAuthenticated` 的事务内 `set_config` 会失效);新增单事务 + 标准输入 + 显式 `maxBuffer` 的专用函数,只给本测试用。修通后若真实断言失败是产品缺陷,不得改断言 | **已验收并部署 staging** | `018b2b48`;run 2858 / validate 6349:3,764/3,764、0 fail/skip,名称无删除新增2;47个DB名称全过。migrate 2859、deploy 2860 成功,health 双 SHA 已核对;本机 Docker/Windows 缺口见 PROGRESS |
@@ -195,7 +196,7 @@
| 任务书 | 进度 | 主题 | 状态 | 落点 |
| --- | --- | --- | --- | --- |
| `TASK-chart-page-skeleton-wait-20260924.md` | — | **星盘页骨架盘等待态 + 三个「永远还没拿到」死角**:「这一张盘还没拿到。」只代表 `view === null`,是唯一等待态,失败各有句子;但客户端无超时(A)、401 跳转前(B)、分盘层失败 / 429 后 `ChartVedicTab` 只看 `!selected` 不看 pending(C)三条路都让这句永远挂着。**产品 09-24 拍板推翻 09-18 方案一(BUG-966)**:星盘页盘位用骨架盘 + 呼吸动效(复用 `VedicChartSvg` 空模型,不复制几何;`prefers-reduced-motion` 静止),范围只限星盘页会出盘轮的位置,首页 / 侧栏 / 星历 / 报告的「不放骨架」合同不动;`AGENTS.md` §6 与 `DESIGN.md` §9 / §15 追加例外。三死角出口:客户端 25s 超时 → `timedOut` 句、401 先写失败体、按层失败态 `layerFailures`(429 独立档,BUG-715/723)。BUG-1016 / 1017 | 待领取 | — |
| `TASK-chart-page-skeleton-wait-20260924.md` | `PROGRESS-chart-page-skeleton-wait-20260924.md` | **星盘页骨架盘等待态 + 三个「永远还没拿到」死角**:「这一张盘还没拿到。」只代表 `view === null`,是唯一等待态,失败各有句子;但客户端无超时(A)、401 跳转前(B)、分盘层失败 / 429 后 `ChartVedicTab` 只看 `!selected` 不看 pending(C)三条路都让这句永远挂着。**产品 09-24 拍板推翻 09-18 方案一(BUG-966)**:星盘页盘位用骨架盘 + 呼吸动效(复用 `VedicChartSvg` 空模型,不复制几何;`prefers-reduced-motion` 静止),范围只限星盘页会出盘轮的位置,首页 / 侧栏 / 星历 / 报告的「不放骨架」合同不动;`AGENTS.md` §6 与 `DESIGN.md` §9 / §15 追加例外。三死角出口:客户端 25s 超时 → `timedOut` 句、401 先写失败体、按层失败态 `layerFailures`(429 独立档,BUG-715/723)。BUG-1016 / 1017 | 待验收(独立审查、隔离Chrome、全量对比完成;完整构建及受控真机缺口) | 已整合 `codex/chart-report-integration-20260924`,未提交 / 未推送 |
| `TASK-smalltalk-test-stdout-mock-20260921.md` | `PROGRESS-smalltalk-test-stdout-mock-20260921.md` | **测试基础设施(BUG-995)**:`consultation-smalltalk.test.ts` 为验证「SDK 不得把私密文本写进日志」,用 `t.mock.method(process.stdout/stderr, "write", …)` 全局接管标准输出——而 `node:test` 的 TAP 报告也走 `process.stdout`,于是运行器自己的 `# Subtest:` / `ok` 行被吞进测试的 `logs` 数组。实测四次全量:`default Mastra adapter` 四条用例只上报 4 / 2 / 1 / 1 条(`Subtest` 声明本身就少,不是 grep 锚点问题),`# tests` 因此 ±3 抖;单跑该文件 33 条静态展开只报 30 条,仅循环最后一个 `provider_error` 稳定可见。**更要紧**:注入必失败探针后,`invalid_schema` / `bad_json` 只剩一行 `not ok 1 - <文件绝对路径>`,**没有用例名、没有断言消息**(退出码仍是 1,门禁不会漏掉失败,不夸大)。定位 BUG-987 时靠的就是从门禁日志 grep `not ok` 抓用例名,红在这三条上那条路会断。**决策**:mock 改为记录后**透传给原始 `write`**(保留隐私断言,不换报告通道,不改 `npm test` 脚本);F3 把「比用例名列表 diff、不比 `# tests` 总数」写进 `frontend/AGENTS.md`。全仓只此一个文件用了这个手法(已 grep 确认)| 待验收 | `2503c019` |
| `TASK-frontend-optimization-20260828.md` | `PROGRESS-frontend-optimization-20260828.md` | 前端优化九条 | 待核对 | 分支 `codex/frontend-optimization-20260828` |
| `TASK-frontend-followup-20260829.md` | `PROGRESS-frontend-followup-20260829.md` | 九条收尾 | 待核对 | — |
@@ -44,6 +44,15 @@
- **D11 列表页**:`rowMeta` 改中文——日期全写(`2026年9月23日`)、深度映射 `REPORT_DEPTH_LABELS = {concise:"简版", standard:"标准深度", deep:"深度", research:"研究级"}`(放在 `personal-report-progress.ts` 与 `REPORT_THEME_LABELS` 并排)、主题走 `REPORT_THEME_LABELS`;状态 chip 分色(已完成 `--ok`、生成中 `--warn`、未完成 `--bad`,用 `color-mix` 12% 底);已完成行底色 `--report-paper`,其它行 `--color-surface`;行右上 `⋯` 菜单只有「删除」,点击后行内展开「确定删除这份报告? 删除 / 取消」,不用 `window.confirm`;删除成功后行移除并使列表缓存失效。仍是单列行列表,不做卡片网格(D12)。
- **D12 不做**:不做剪贴板、不做 PDF、不做分享链接、不改生成管线、不改数据库、不改 `GET /api/reports` 字段;微信内置浏览器下载限制沿用现有 `client-report-export.ts` 的检测与提示。
### D13 · SVG 后续裁决(2026-09-24,执行中追加)
原任务 D4 的“盘纯文本、不含 SVG”及 T1“每块无 SVG”与 D5 冲突:旧普通导出实际保留安全引擎 SVG。执行中提出该冲突后,产品明确回答“分盘导出也需要带出svg”,随后要求“请你继续”。此为后续授权,不追溯声称原单已经授权。
- D5 保持不变:常用 / 全部正文逐字节等于旧普通导出(包括已有安全 SVG)。
- 新增分盘块必须包含安全 SVG,可同时保留落宫纯文本。优先复用投影后原有 SVG;无现成 SVG 时复用现有报告图盘组件,不另造几何、不增加请求。
- 有限替代 D4 的“不含 SVG”及 T1 的无 SVG 断言;JSON 图盘围栏仍禁止导出,每块 `ordinaryOutputLeaks()` 仍必须为空,不放宽投影安全边界。
- “所有组全选”包含附加分盘 / 核对表,不等于“全部正文”。真人清单③的逐字节对照针对常用 / 正文全选;所有组全选需另验附加内容。
## 硬红线
1. 导出文本必须过 `ordinaryOutputLeaks()` = 空(BUG-999 / 1003):合同测试把 golden fixture 每一块都跑一遍。
@@ -0,0 +1,63 @@
# TASK · 报告导出 CRLF 围栏合同冲突(2026-09-24)
## 状态 / 基线
**blocked,待D5有限例外裁决;本文件不是执行授权。**
基线 `5ff43b47f38e378918c8b6bd967228185d7f02fe`,发现于尚未提交的 `codex/report-chapter-export-20260924`,组合候选 `codex/chart-report-integration-20260924`。原报告单完成本地实现后,独立审查发现本项;继承旧剥离器缺陷,不是新增回归。后续必须在两单组合版本之后串行执行,不覆盖在途工作。
## 事故实证
- `frontend/src/lib/report-chart-block.ts` 的 `FENCE_RE`(当前83行)在语言标记后仅允许LF;`stripReportChartBlocks`(当前202–204行)直接使用该正则。
- 新 `report-export-blocks.ts` 的正文块与旧 `ordinaryReportDownloadMarkdown()` 都调用旧剥离器。
- 只将真实引擎虚构fixture `frontend/tests/fixtures/report-density-fictional-reader.json` 的markdown从LF转为CRLF,构造正文块并join:正文25块,下载中残留22个 `jyotish-chart` JSON围栏;仍与旧导出逐字节相等。分盘另能正确提取22个出现项。
- 相关105条测试通过未覆盖“含真实图盘围栏的CRLF输入无JSON”;已有CRLF字节等价测试不足以证明禁止JSON合同。
复现核心(在既有Node22/tsx环境运行,仅读虚构fixture,不写资料):
```ts
const markdown = fixture.markdown.replace(/\n/g, "\r\n");
const body = buildReportExportBlocks({ markdown }).filter(b => b.group === "body");
const output = joinExportBlocks(body);
console.log({
residualJsonFences: (output.match(/```jyotish-chart/g) ?? []).length,
equalsOldExport: output === ordinaryReportDownloadMarkdown(markdown),
});
// 实测:{ residualJsonFences: 22, equalsOldExport: true }
```
## 根因与旧防线
语言标记后 `\n` 不匹配 `\r\n`;投影允许供阅读组件消费的图盘结构,普通导出还需剥除围栏。BUG-999/1003投影及安全SVG防线不应撤销,当前缺的是下载剥离器换行边界;不能把ordinaryOutputLeaks为空替代无JSON独立断言。
## 决策记录
- 原单D5明确不可让步:正文全选与**旧版本**普通导出逐字节相同。
- 原单T1同时禁止JSON图盘围栏,CRLF输入下这两条无法同时成立。
- 用户后续D13只允许并要求SVG,不授权保留JSON,也未授权改变D5。
- **建议但尚未批准**:仅对CRLF图盘围栏的错误残留授权D5有限例外,新导出删除JSON;其它正文/安全SVG和LF输出不变。
- 未获该裁决前只记录blocked,不改剥离器、不将两个共同修改后的helper比较当成旧行为等价。
## 硬红线
不标准化整篇换行,不改SVG几何/投影allowlist,不改生成/API/数据库,不新请求,不动依赖或workflow。保留单一大纲、既有下载器、全部测试名称与三栏断言记录。
## 任务分解(获准后)
1. 冻结基线LF golden旧导出结果及hash;另记录CRLF旧输出与22围栏事实。
2. 最小修改语言标记后的换行匹配为 `\r?\n`,检查边缘空白处理而非全篇replace。
3. 新增真实golden转换CRLF/混合换行测试:所有正文无JSON围栏;原安全SVG、其它文本字节与顺序保持;ordinaryOutputLeaks为空;分盘出现数不变。
4. LF golden必须与冻结旧版本结果逐字节相等。CRLF差异必须仅为获准移除的围栏,不得仅比较两个共用修改后helper的函数。
5. 跑tsc/lint/全量名称多重集合与失败诊断对照、实际下载;更新D5有限例外、PROGRESS、BUG-1020、BLOCKED、testing。构建/真机缺口如实保留。
## 让步顺序
不让步安全投影或JSON禁止,不静默改D5;无授权则保持blocked。构建环境缺口可留清单,不能写成通过。
## 开工前置命令
先 `git status -sb`,再 `git fetch origin --prune`,核对两单实际交付基线;获准后创建独立worktree,不在脏树切分支/reset/stash。重读AGENTS/frontend约束及本次BUG记录,Node22下跑报告定向基线。没有真实账号不得借凭据验收。
## BUG编号
组合候选核对最大号1019,本项暂记BUG-1020。正式领取时再次核对远端;若被占用顺延,不覆写其它会话记录。
@@ -0,0 +1,21 @@
# 星盘盘位等待态真机清单(2026-09-24)
状态:受控登录及真机待执行。单星盘与最终组合工作树分别完成隔离真实Chrome153组件验收13/13(真实组件/CSS、mock接口、虚构golden、全新profile);这不替代本表真人和部署验收,证据见PROGRESS。仅使用产品提供的受控账户和明确虚构的出生资料;不借用他人登录态。只记录脱敏结果,不保存Cookie、姓名、出生数据或完整响应。
| 项目 | 操作 | 通过标准 | 结果 |
| --- | --- | --- | --- |
| 冷进与尺寸 | 375px、390px、桌面冷进 `/chart`,在受控网络中延迟主盘响应 | 五个 Tab 可见禁用;空北印盘轻缓呼吸,下面原等待句;盘到后可用且标题/侧栏不抖动,页面无横滚 | 待验 |
| 暖进 | 主盘成功后离开再进入 | 缓存立即显示,不重放骨架;后台更新不抹已完成的分盘/西洋结果 | 待验 |
| 非 D1 | 冷点 D9、D10 | 空北印盘与分盘等待句;成功移除骨架,不残留假度数/星体 | 待验 |
| 西洋 | 冷点西洋 | 复用原西洋轮廓空盘,不显示星体/星座/上升标签;返回后正常渲染 | 待验 |
| 429 与恢复 | 在受控测试环境连续点西洋/七政/D9/D10,或由测试代理对所请求层返回引擎忙响应 | busy 显示「算盘的服务正忙,稍等几秒再打开就好。」而非永久等待;再点原 Tab/chip 清失败、重新 pending 后可恢复。不要修改共享服务器并发来造故障 | 待验 |
| 两类限流 | 分别注入引擎 busy 与 BFF rate_limited | 前者 busy 句;后者「刚才打开得太勤,稍等再试。」;不混淆 | 待验 |
| 真超时 | 已下载页面脚本的标签页清星盘内存缓存,通过受控网络让 `/api/chart-view` 持续不响应 | 前台活动约25秒内显示「这张盘等了太久没有回来,再打开一次试试。」且骨架结束。浏览器休眠会暂停 AbortSignal 活跃时间,不据此承诺墙钟期限 | 待验 |
| 断网 | 已下载脚本后断网打开星盘 | 立即网络失败可显示既有 unavailable;只有持续挂起才显示 timedOut,不把断网立即拒绝误写为超时。恢复网络重新打开可重试 | 待验 |
| 未登录 | 受控退出登录后进页;另测查看时会话过期点分盘 | 先出现「请先登录后再看星盘。」再去 `/login`,不留空盘等到超时 | 待验 |
| 减弱动态效果 | 开系统减弱动态效果,再冷进或延迟 D9 | 空盘静止 opacity 0.5,等待句清楚可读;无旋转/扫光 | 待验 |
| 表格与其它页 | 点大运/七政;打开星历/报告列表 | 大运和七政只有静态等待句,失败给原因;星历/报告列表无新骨架或呼吸 | 待验 |
| 资料失效 | 请求延迟时保存新虚构出生资料,再进星盘,随后释放旧响应 | 只显示新资料对应盘,不用旧层结果覆盖新主体 | 待验 |
| 无障碍 | 键盘与读屏进入,数据挂起/成功/失败 | 骨架容器 busy,装饰盘不重复朗读;文字在容器下方;失败后无 busy,Tab 可操作 | 待验 |
部署前还需主会话全量名称/失败比较、构建 `/` 和 `/chart` Static、首屏 gzip ±2% 与 staging health SHA;这些不是本清单未执行即可宣称通过的项目。
@@ -0,0 +1,38 @@
# 报告分块导出 / 列表管理真人清单(2026-09-24)
## 状态与安全边界
受控登录/iPhone/微信真人验收尚未执行。仅使用受控账号与明确虚构资料,不借用登录态,不保存报告个人信息、Cookie或JWT。登记系统、浏览器版本、实际部署SHA与通过/未通过/环境缺口。
单报告工作树隔离Chrome153组件验收13/13,最终组合树另跑14/14(额外覆盖真实fallback SVG下载)通过:真实CSS与组件,白名单mock接口、虚构golden、全新profile,无pageerror;4种实际.md下载及SVG离线呈现通过。此证据不替代完整Next服务器、数据库持久化或真机。详情与本地证据见 `../tasks/PROGRESS-report-chapter-export-20260924.md`。
**已知未通过项**:CRLF输入会继承旧剥离器缺陷,正文保留图盘JSON;当前不满足“所有输入无JSON”验收。修复涉及D5有限例外,未获授权,见 `../tasks/TASK-report-chapter-export-fix-20260924.md`。不要据LF golden成功勾掉本项。
## 待真人逐项执行
- [ ] iPhone Safari ready报告点「分块导出」:底部抽屉、默认常用、头尾可见、中部滚动;计数来自实际文本(包括Markdown/SVG标记)。
- [ ] 套餐替换选择;手动勾选取消套餐高亮;取消全选后按钮禁用。
- [ ] 仅勾三章,下载一个文件名含 `-节选` 的 `.md`;文件App打开后内容/顺序正确,没有图盘JSON或工程字段。
- [ ] 选「常用」即全部正文:文件名不含节选,与升级前同一报告旧导出逐字节相同,原安全SVG保留。**D5针对正文全选,不是所有组全选。** CRLF已知例外必须单独记录失败。
- [ ] 所有组全选:正文后附分盘/核对表,比旧正文增加内容;每张分盘有SVG,重复D9两个出现项不丢,核对表子表/列/显示精度一致。
- [ ] 仅分盘/仅核对表独立下载正常,文件名含节选。
- [ ] 无原引擎SVG时fallback可离线打开,宫位、符号、图例可读,不依赖应用CSS或新请求。
- [ ] 对照盘图式与标题:当前复用旧引擎SVG可能是南印矩形图式,标题沿用“北印度盘”;登记差异,不以新造几何掩盖。
- [ ] 桌面展开/折叠侧栏、平板:抽屉不盖侧栏、最大760px/70%,860px起两列,窄屏一列,无横向溢出,控件至少44px。
- [ ] Tab/Shift+Tab不会激活背景控件;Esc/遮罩/关闭可退出,点内容不退出,焦点回入口且不滚动正文。Chrome浏览器工具栏焦点中转不误判为背景控件获焦。
- [ ] 列表ready行「分块导出」直达抽屉;ready后只开一次、清#export且保留query;关闭后不重开;其它状态无导出入口。
- [ ] 列表日期、深度、主题中文;未知id原样回退;状态同时有文字和三色,ready纸色,其它canvas。
- [ ] 每种状态菜单只有删除,取消不请求;重复确认只发一次DELETE;HTTP失败/断网留行并报短错误,重试成功移除。
- [ ] 删除期间旧GET在途,返回后不复活;刷新/离开重进不出现。**持久化须受控账号实测,mock不能代替。**
- [ ] 成功触发下载后关闭并提示一次「已导出N块」;下载器可检测失败时保留抽屉/选择、不发成功提示。浏览器不能保证用户最终保存文件,不能把toast当磁盘持久化证明。
- [ ] 微信真机沿用系统浏览器提示,不下载、不关闭、不误报成功;切系统浏览器后可下载。
- [ ] 返回、打印、核对表打印前展开/打印后恢复、原始附录下载仍可用;普通导出无额外GET、服务端PDF或clipboard。
- [ ] CRLF真实golden无JSON回归在获准修复后重验,同时保留冻结旧LF输出逐字节比较,不能仅比较两个共享修改后helper的函数。
- [ ] 完整构建后核对 `/`、`/chart` Static,`/reports`、`/reports/[reportId]` 与基线动态标记一致;首页gzip±2%。
- [ ] staging发布后health deployment.gitCommit等于本轮含代码提交;未发布前不填通过。
## 记录模板
| 环境 / 版本 / 部署SHA | 条目 | 通过 / 未通过 / 环境缺口 | 脱敏证据与说明 |
| --- | --- | --- | --- |
| 待填 | 待填 | 待执行 | 不放真实身份、报告内容或凭据 |