接受删除旧报告页,并跟上最新 staging
Independent Staging Quality Gate / validate (push) Failing after 8m31s
Independent Staging Quality Gate / publish (push) Skipped

旧的结构化报告页已由另一单删除,标识留在现在用的阅读页。测试不再读取那个文件。更新日志和 Bug 历史两边都保留。

自测:tsc 退出码 0;lint 0 error、123 warning;修复单点名的 3 个测试 7 通过、0 失败、0 取消。

Co-Authored-By: Grok (agent loop)
This commit is contained in:
jesse-ux
2026-10-14 12:27:33 +08:00
co-authored by Grok (agent loop)
95 changed files with 22839 additions and 7984 deletions
@@ -0,0 +1,51 @@
# PROGRESS · API 磁盘缓存留存(2026-10-14)
- 分支:`codex/api-disk-cache-retention-20261013`
- 任务书基线写的是 `77057a819`。本分支从当时的 `origin/staging` `66cd60081f37a57680274633fcb3fb942d01bb2f` 拉出。A/B 的父提交用的是这个 SHA,不是任务书里的旧基线。
- 接口文件行数:10946(验收口径 ≤ 10970)。类方法数和伪造点没有增加。
## 做了什么
- T1:新增 `scripts/api_scratch_retention.py`。启动时清理全部已登记目录,并按 `JYOTISH_SCRATCH_PRUNE_INTERVAL_SECONDS`(默认 1800,0 表示不启后台线程)周期清理。排盘缓存新文件改为仅本人可读,先写临时文件再换上。`prune_expired_async_jobs` 只留同名薄包装。
- T2:`VEDASTRO_WRITE_AUDIT_ARTIFACTS` 默认关。关掉时不写审计文件,`artifact_path` 为 `None`。打开时写紧凑 JSON,仅本人可读,先写临时文件再换上。成功快照仍用原 TTL;失败、不完整、被挡住的用短 TTL,默认 300 秒,并且不超过成功 TTL。旧缓存没有 `negative` 标记时仍按成功的长期限读。状态接口改报含回落的成功期限,并多报失败期限。`.env.cn.example` 只加了注释,两个 604800 没改。
- 成功的判据:`available is True` 且 `status == "ok"`。`partial` 即使 `available` 为真也算失败缓存。
- T3:年月日能整除才收成整数,不截断 1990.5。时分秒和经纬度、时区能解析成有限数字就收成浮点,不四舍五入。解析不了的保持原值。日期取前 10 位,空值仍是空值。缓存格式版本 5 → 6。快速排盘和完整排盘仍是两把键。
- T4:前台快照、负缓存、网关任务、分盘段都进了登记表。只删符合原文件名的过期文件。网关排队中和进行中的不删。读写逻辑和键没改。
- T5:脚本在 `scripts/research/api_disk_cache_ab.py`,逐字节比较在 `scripts/research/api_chart_cache_byte_diff.py`。记录在 `docs/testing/api-disk-cache-retention-ab-20261013.md`。
- T6:没有改咨询卡片缓存。数字用任务书 §2.5,没有重测:未命中构建 1.9 秒;文件 5097751 字节;命中时解析中位 68.5 毫秒;整次命中 82.5 毫秒;两天大约每个活跃用户 10 MB。可选方向仍是两条:按领域切片只读需要的部分;清理改为每隔几分钟一次,而不是每次读取都扫全目录。没有做进程内已解析包缓存。
- T7:BUG-1330、BUG-1331、BUG-1332。变更说明一句。任务索引改为待验收。没有改界面说明。
## 命令和结果
| 检查 | 命令 | 结果 |
| --- | --- | --- |
| 新留存、异步任务、增长合同 | `pytest tests/test_api_scratch_retention.py tests/test_api_async_job_contract.py tests/test_api_server_growth_contract.py -q` | 26 通过 |
| 安全缓存 | `pytest tests/test_api_server_security.py -q -k cache` | 6 通过 |
| 任务书列出的 VedAstro / 咨询套件 | 见任务书 §8 那一条 | 4 失败,见下。其余通过 |
| 需要审计文件的执行器测试 | `pytest tests/test_vedastro_service_adapter_executor.py::test_vedastro_range_scan_records_hashes_and_artifact_path -q` | 1 通过 |
| 逐字节比较与 A/B | `python scripts/research/api_disk_cache_ab.py` | 退出码 0。命中率 B/A = 1.333。七天后 B 剩 40 个文件,等于当天键数。审计文件 0。负缓存剩 1。一万个文件的清理 20.174 秒 |
| 接口行数 | 按换行计数 | 10946 |
既有断言改动只有一处,在 `tests/test_vedastro_service_adapter_executor.py`:原值是子进程沿用进程环境;新值是显式打开审计落盘;原因是默认关闭后这条测试仍要检查文件存在。这是测试前置,不是放宽断言。
## 未达到的目标(目标不改)
- 混合写法再重复 3 次时,命中率只是 A 的 1.333 倍,不是 2.5 倍。重复本身已经让 A 命中三分之二。
- 一万个过期文件的清理用了 20.174 秒,不是 2 秒内。清理不在请求线程。默认间隔和失败短期限没有因此改掉。
## 本机套件里原先就会红的三条
- `tests/test_vedastro_gateway.py` 要求原始响应文件权限是 0600。Windows 报出来的是可写,不是 0600。这条断言没改。新测试在 Linux 上仍检查 0600,Windows 上只检查文件写出来了。
- `tests/test_vedastro_runtime_ops.py` 要求已安装的 VedAstro 是 1.23.25,本机是 1.23.30。与这次缓存改动无关。
- `tests/test_three_engine_parity_runner.py` 的公开盘回放把 PyJHora 记成 raw_imported,不是 structured_captured,同时在下载星历。运行器没改。
## 环境缺口
- 生产和测试环境里成功缓存的实际秒数,这份仓库读不到。部署后看状态接口的两个期限数字即可。
- 生产卷上已经堆了多少文件,这里不知道。
- 主测量挡住了 VedAstro 导入。本机有 SDK,官方端口能连通。不挡 SDK 的探针仍关闭外网取数,一次完整排盘 4.167 秒,没有报错,没有拉真实快照。
## 未做
- 没有改部署文件、生产环境变量、数据库,也没有手工清生产卷。
- 没有把咨询卡片缓存并进周期清理。
@@ -42,3 +42,22 @@ T6:`scratchpad/beta-smoke-checklist-20261014.md` 不在这棵树上。冒烟
- 英文对话说明没有画在界面上,因为对话外壳只有中文。句子留在 VOICE。
- T2b 按让步顺序跳过。
- 冒烟草稿不在树里,改的是已经落盘的清单,没有另起一份。
## 第 1 次打回(2026-10-14)
接受最新 `origin/staging` 的合并。旧报告页 `personal-report-document-view.tsx` 按修复单删除,标识留在现在用的 Markdown 阅读页。AI 标识测试不再读取那个已删文件。更新日志和 Bug 历史两边都留着。Bug 历史在 staging 上本来就有前后两份,合并后仍是两份,本单只多了 BUG-1347 这一条。任务索引里补上修复单,并写上进度文件。
### 断言三栏(本轮)
| 位置 | 原值 | 新值 | 原因 |
| --- | --- | --- | --- |
| `frontend/tests/ai-generated-notice-20261014.test.ts` 报告阅读用例 | 渲染已删除的旧结构化报告页,并检查中文标识和 `id="report-disclaimer"` | 删掉对旧页面的读取和这两条断言;Markdown 中英文标题下的断言、输入框断言保留 | 第 1 次打回:旧页面已由另一单删除,现行报告页已有标识 |
### 本轮自测
| 检查 | 命令 | 结果 |
| --- | --- | --- |
| 类型 | `frontend\node_modules\.bin\tsc --noEmit -p frontend` | 退出码 0 |
| 规范 | `npm run lint --prefix frontend` | 退出码 0,0 error,123 warning(原有警告,本轮没有新增 error) |
| 定向测试 | 在 `frontend` 下 `tsx --test` 跑修复单点名的 3 个文件 | tests 7,pass 7,fail 0,cancelled 0,退出码 0 |
| 全量前端测试 / 构建 / 数据库 | 未跑 | 修复单不要求。数据库上一轮已过,这轮没改迁移 |
@@ -0,0 +1,70 @@
# PROGRESS · 发问准备并行(2026-10-14)
- 分支:`codex/consult-prep-parallel-20261013`
- 基线:`origin/staging` `66cd60081f37a57680274633fcb3fb942d01bb2f`(任务书写的 `77057a819` 的后代;计划评论里的 `2994588ad` 更早,不因此停工)
- 个人长报告写作开关仍是关闭,本轮没有改报告章节
- 编号:本分支上的 `docs/BUG_HISTORY.md` 最大号是 BUG-1322。BUG-1323~1336 被其它未合并任务书占用。本单用 BUG-1337~1339
## 开关
三个都保持代码里的默认,没有单独提交去打开:
| 开关 | 默认 | 原因 |
| --- | --- | --- |
| `CONSULT_PREP_PARALLEL` | 关 | 没有本机 Postgres 中位数,不满足首帧快两成 |
| `MODEL_VERSION_CACHE_TTL_MS` | 0 | 没有量到「准备模型」快一半 |
| `CONSULT_DOMAIN_CONCURRENCY` | 1 | 没有带星盘网络库的镜像重测;起草试算预计达不到快两成五 |
因此没有写 `CHANGELOG.md`,也没有改 `frontend/DESIGN.md`。
## 做了什么
- T1:开流前的登录、注销检查、请求体、会话、模型收进 `loadConsultTurnHead`。并行时注销检查和后面三条同时开始,失败仍按旧的先后返回。423 仍在任何扣点之前。
- T2:并行打开时,审核在开流前启动、在扣点前等待。拦住时不扣点,并且比资料错误优先。关掉时仍是开流前等待审核。
- T3:按模型和版本缓存成功的解析,最长 15 秒;失败和空结果不缓存;管理端清目录缓存时一并清掉。地址检查函数本身没改。已发布版本的供应商代码、类型和地址不可变,但启用开关和密钥仍可变,所以不能超过目录缓存的 15 秒。
- T4:问题保存成功后立刻读标题,和分类同时进行,用到标题时再等。分类仍在扣点和保存之后。
- T5:领域并发开关。为 1 时仍是原来的逐个循环,含时间预算。为 2 时一起算,结果按计划顺序组装,不再逐个套时间预算,领域个数上限不变。
- T6:准备阶段记一条 `consultation-prep-v1`,只有阶段名、毫秒和状态,没有问题原文。
- T7:见 `docs/testing/consult-prep-parallel-ab-20261013.md`。假时钟并行 160、串行 210。这不是开启依据。
- 测试注入:模型目录增加 `setModelCatalogIoForTests`,只给测试替换查库、解密和地址检查。生产路径仍调用原来的函数。
## 改过的既有断言
| 文件 | 原值 | 新值 | 原因 |
| --- | --- | --- | --- |
| `content-moderation.test.ts` | 源码含 `await moderate(visibleQuestion, "input"` 且早于 `reserve_consultation_usage` | `await settleInputModeration()` 早于扣点;准备服务里 `beforeReserve` 早于 `input.reserve()`;拦住时扣点次数是 0 | 审核挪到流内、扣点前。关掉开关时开流前的等待还在 |
| `model-catalog.test.ts` | `return await readVersion(modelId, configVersion)` | `const model = await readVersion(...)`,只有非空才写入短缓存 | 绑版本的解析可以缓存,失败和空结果不写 |
| `model-catalog.test.ts` | 咨询路由里 `if (!sessionModel)` 后面是 503 | 准备函数里 `if (!sessionModel)` 返回 `modelUnavailable()`,状态 503 | 模型不可用仍是开流前的 503,文案随准备步骤搬走 |
| `consult-first-frame-and-pacing-20260928.test.tsx` | 401、请求体、会话不存在、会话类型、模型已变这些字面量在路由的 `runTurn` 之前 | 字面量在 `turn-prep.ts`;路由在 `runTurn` 之前调用 `loadConsultTurnHead` 并返回失败 | 开流前的判断收进同一个函数,状态码仍在开流前 |
| `rectification-session-composer-guard.test.ts` | 咨询路由里会话缺失返回 404,类型不对返回 `session_not_consultation` | 同样两句在 `turn-prep.ts` | 会话判断搬走,文案和状态码没变 |
`consultation-agentic-runtime.test.ts` 的领域循环帮助函数现在也接受异步的假计算,以便断言「后完成的领域仍排在计划后面」。原有断言没有改松。
## 并发为 2 时的时间预算
领域数仍先被原来的上限截断(现在是 2)。开关为 2 时,这两个领域一起开始,不再逐个问「剩下的时间还够不够下一个」。开关为 1 时,原来的逐个判断还在。
## 自测
test:db 未跑:本轮没有改查询语句,任务书也不要求。前端全量和 Python 快速门留给验收。`npm run lint` 0 error,原有 warning 没动。
| 检查 | 命令 | 结果 |
| --- | --- | --- |
| 类型 | `node frontend/node_modules/typescript/bin/tsc --noEmit -p frontend` | 0 错 |
| 规范 | `npm run lint --prefix frontend` | 0 error,125 条原有 warning |
| 准备与审核 | `tsx --test` 下列文件:`consult-turn-prep-20261013`、`consult-prep-gate-20261013`、`content-moderation`、`model-catalog`、`consult-first-frame-and-pacing-20260928`、`rectification-session-composer-guard` | 准备函数 3 通过;门禁文件 5 通过;其余在同一次 41 例里通过(当时缓存测试还在改,后来单文件 5 通过、失败 0、取消 0) |
| 计费、注销、标题、寒暄、领域 | 同上命令:`application-billing-contract`、`account-deletion`、`session-title-persist-contract`、`consultation-smalltalk`、`consultation-agentic-runtime` | 136 通过,失败 0,取消 0 |
| 假时钟 | `consult-prep-parallel-ab.mts` | 并行 160,串行 210,同时步数 2 对 1 |
| 领域镜像 | `consult-domain-concurrency-ab.py` | 退出 0,写明没有跑镜像 |
## 第 1 次打回
合并最新 `origin/staging`。业务代码没改,三个开关默认值没改。
| 文件 | 原值 | 新值 | 原因 |
| --- | --- | --- | --- |
| `chat-session-authority.test.ts` | 在 `route.ts` 里找 `if (!chatSession)` 后的 404 | 在 `turn-prep.ts` 里锁 `sessionMissing()` 的 404,和分开的 `notConsultation()` 409 | 判定搬走了。仍不许并成一个判断 |
| `consultation-workflow-contract.test.ts` | `beforeReserve: ({ consultationMode }) => createConsultationPlan({`,以及 `reserve: () => reserveConsultationModel(` | `beforeReserve` 的 async 函数体里调用 `createConsultationPlan({`,并且早于 `reserve`;`reserve` 的 async 函数体里调用 `reserveConsultationModel(` | 改成了 async。没有放宽成「文件里出现过函数名」 |
| `consult-prep-parallel-ab.mts` | `frontend/scripts/research/`,从 `frontend/tests` 导入 | `frontend/tests/consult-prep-parallel-ab.mts` | 镜像会复制 scripts、不复制 tests。另一个新增的领域脚本是 Python,不导入测试目录 |
这次自测:上述合同测试加出生时间模式、镜像导入检查,40 通过,失败 0,取消 0。假时钟脚本挪走后仍是并行 160、串行 210。`tsc --noEmit` 0 错。`npm run lint` 0 error,125 条原有 warning。全量 `npm test` 留给验收。`git diff a0e223e2` 到本修复会带上合并进来的测试环境前端文件;相对那次合并的 `origin/staging`,`frontend/src` 没有新增改动。
@@ -0,0 +1,243 @@
# PROGRESS · 前端死代码与无调用方接口清理
- 日期:2026-10-14
- 分支:`codex/frontend-dead-code-20261013`
- 基线:本分支从当前 `origin/staging` `0a4ba236580df6e6cbb0faa28e48d1e66ff7dfff` 拉出(任务书写作基线 `77057a819` 的后代)
- 结论:删掉三个没有调用方的接口(含一个不用登录就会做大约 20 秒计算的入口)和任务书点名的死代码。普通导出的逐字节锁没动。Skill 版本不 bump。
## 开工基线
- 前端测试文件:600(`frontend/tests/*.test.ts` 与 `*.test.tsx`)。做完 594,少 6 个整文件。
- `docs/BUG_HISTORY.md` 最大已有号是 BUG-1345。BUG-1342 当时空着,按任务书使用,不另开新号。
## 可达性脚本(正斜杠)
Windows 上 `os.walk` 给出反斜杠,任务书里的入口正则匹配不到。脚本先把路径换成 `/` 再判断。
删之前,不可达 17 个文件、3028 行,与任务书表一致:
```
src/components/birth-time-life-events.tsx 207
src/components/birth-time-soft-notice.tsx 36
src/components/claim-boundary-badge.tsx 13
src/components/evidence-audit-panel.tsx 64
src/components/personal-report/personal-report-document-view.tsx 630
src/components/personal-report/raw-appendix-download.tsx 33
src/lib/agent-evals.ts 796
src/lib/birth-time-candidate-completion.ts 14
src/lib/chart-library-view.ts 18
src/lib/db/client.ts 18
src/lib/personal-report-longform-download.ts 8
src/lib/rectification-agentic/core/index.ts 23
src/lib/rectification-agentic/date-range.ts 53
src/lib/rectification-agentic/session.ts 351
src/lib/rectification-agentic/v9/index.ts 11
src/lib/think-step-gate.ts 17
src/mastra/rectification-tools.ts 736
```
删之后还剩 2 个:
```
src/lib/personal-report-longform-download.ts 8
src/lib/reader-appendix-language.ts 32
```
偏离:任务书 T2 写「只剩 `personal-report-longform-download.ts`」。那是在原始附录路由还在时的口径。T3 删掉路由和 `personal-report-raw-appendix.ts` 之后,净化函数 `reader-appendix-language.ts` 没有生产入口了,但密度测试和 `reader-appendix-language-parity.test.ts` 仍直接调用它。任务书没把它列入删除,删掉会放宽净化合同,所以保留。`ordinaryReportDownloadMarkdown` 仍在。
## 删除的源文件(行数按 git 删除计)
| 路径 | 行 |
| --- | ---: |
| `frontend/src/mastra/rectification-tools.ts` | 736 |
| `frontend/src/lib/agent-evals.ts` | 796 |
| `frontend/src/components/personal-report/personal-report-document-view.tsx` | 630 |
| `frontend/src/lib/rectification-agentic/session.ts` | 351 |
| `frontend/src/components/birth-time-life-events.tsx` | 207 |
| `frontend/src/components/evidence-audit-panel.tsx` | 64 |
| `frontend/src/lib/rectification-agentic/date-range.ts` | 53 |
| `frontend/src/app/api/birth-rectification/route.ts` | 49 |
| `frontend/src/app/api/reports/[reportId]/raw-appendix/route.ts` | 48 |
| `frontend/src/lib/birth-rectification-payload.ts` | 41 |
| `frontend/src/components/birth-time-soft-notice.tsx` | 36 |
| `frontend/src/components/personal-report/raw-appendix-download.tsx` | 33 |
| `frontend/src/lib/rectification-agentic/core/index.ts` | 23 |
| `frontend/src/app/api/birth-time-candidate-completion/route.ts` | 20 |
| `frontend/src/lib/chart-library-view.ts` | 18 |
| `frontend/src/lib/db/client.ts` | 18 |
| `frontend/src/lib/think-step-gate.ts` | 17 |
| `frontend/src/lib/birth-time-candidate-completion.ts` | 14 |
| `frontend/src/components/claim-boundary-badge.tsx` | 13 |
| `frontend/src/lib/personal-report-raw-appendix.ts` | 13 |
| `frontend/src/lib/rectification-agentic/v9/index.ts` | 11 |
源文件合计 3191 行。`drizzle-orm` 与 `@mastra/*` 依赖没删。`globals.css` 另删 11 行死样式(见 T5)。没改 `page.tsx`,没改 `scripts/jyotish_api_server.py`,没改表。
## 删除测试清单
整文件删除的原因都是:只测已经删掉的死代码。否定合同留在还活着的测试里。
### `frontend/tests/rectification-agentic-tools.test.ts`(14)
- gate tool posts the birth profile to /api/rectification_gate
- score tool normalizes year-precision events into the V5 date range contract
- scan tool derives its center and uncertainty from the server-owned range
- gate keeps period-only profiles on the server-owned range without inventing a minute
- scan defers an unknown full-day range instead of using a fake noon birth time
- score rejects an Agent-invented range
- save tool rejects before a confirmation gate exists
- save tool rejects a time that does not equal the confirmed minute
- confirm then save with the matching minute applies the write
- confirm serializes event dates to the legacy precision contract
- confirm persists ranked candidates with relative support totaling 100
- confirm distinguishes skipped external validation from a failed VedAstro run
- confirm offers non-unique candidates only when the Agent explicitly ends evidence collection
- accept candidate tool delegates the exact persisted candidate and preserves accepted status
### `frontend/tests/rectification-agentic-session.test.ts`(16)
- loadAgenticRectificationProfile derives birth fields, accuracy and baseline
- loadAgenticRectificationProfile normalizes a persisted ISO birth date
- loadAgenticRectificationProfile normalizes a PostgreSQL Date birth date
- loadAgenticRectificationProfile rejects an invalid persisted birth date
- loadAgenticRectificationProfile treats hospital source as minute accuracy
- loadAgenticRectificationProfile accepts a period-only declaration without a fake minute
- loadAgenticRectificationProfile uses a custom declared window instead of the leftover period
- loadAgenticRectificationProfile accepts an unknown time as the full day
- loadAgenticRectificationProfile preserves a cross-midnight uncertainty range
- loadAgenticRectificationProfile rejects a missing birth date
- applyConfirmedBirthTime calls the service-role RPC with the confirmed minute
- applyConfirmedBirthTime rejects a malformed time before calling the RPC
- applyConfirmedBirthTime surfaces an RPC error as a failure
- candidate persistence binds the engine result to user, session and profile baseline
- candidate acceptance calls the service-role RPC with exact ownership and result identity
- latest candidate result maps persisted support and selection state for session recovery
### `frontend/tests/agent-evals.test.ts`(11)+ `frontend/tests/fixtures/agent-golden-dataset-v1.json`
- golden fixture is deidentified and exactly covers every PR-8 10.1 subscenario and tag
- a conforming rectification run passes every applicable deterministic scorer
- deterministic scorers expose contract, evidence, theme, timing, focus, economy, and budget failures
- catalog-only citations fail until the run actually makes the evidence available
- fact and timing claims cannot disable deterministic evidence requirements
- minute candidate and accepted states pass while unconsented confirmation fails
- consented exact-minute confirmation passes only in the explicit confirmation case
- requested theme coverage is independent from prose and uses structured theme ids
- naturalness, repetition, follow-up relevance, and model fact review remain explicit pending inputs
- latency and cost statistics use deterministic nearest-rank percentiles and report budget breaches
- privacy scanner rejects identity fields, raw user bodies, credentials, dates, times, and internal paths
### `frontend/tests/birth-time-candidate-completion.test.ts`(1)
- unconfirmed candidate results cannot directly become the active consultation time
### `frontend/tests/public-thinking.test.ts`(5)
- incident English salad never reaches the public think channel
- pure Chinese thinking is unchanged
- CJK sentences are accepted whole; English words are not stripped
- English-only process narration is dropped even without a terminator
- an unterminated fragment is dropped rather than rewritten
### `frontend/tests/personal-report-raw-appendix.test.ts`(4 + 11 条参数化)
- raw appendix retains status rows and raw columns without changing ordinary projection
- raw appendix cleans old cache vocabulary but leaves English prose intact
- raw appendix keeps established HTML URL secret and chart-fence safety boundaries
- raw appendix UI is independent of ordinary export and accepts no birth payload
- raw appendix route guards anonymous
- raw appendix route guards cross-origin
- raw appendix route guards foreign
- raw appendix route guards invalid-id
- raw appendix route guards generating
- raw appendix route guards missing
- raw appendix route guards pending
- raw appendix route guards wrong-report
- raw appendix route guards wrong-owner
- raw appendix route guards wrong-request
- raw appendix route guards ready
### `frontend/tests/personal-report-view.test.ts` 里删掉的 15 条(文件留下,不再渲染旧阅读页)
- renders the selected answer-first order: cover -> summary -> D1 -> themes -> appendix -> disclaimer
- accepted and confirmed birth times render as distinct report metadata states
- v2 renders scope, natal foundation, themes, current phase, actions, blocked disclosures and provenance
- v2 currentPhase is omitted when null, without hiding the remaining v2 sections
- v2 chart evidence refs link to the appendix and every real structured chart uses the SVG renderer
- v2 model-authored text stays escaped and cannot inject HTML, CSS or SVG
- 技法审计表不会出现在核心判断之前
- evidence appendix is collapsed by default in default mode and expanded in research mode
- expandedByDefault=true expands the appendix even in default mode
- birth-time sensitivity alone keeps the appendix visible and shows minute changes
- D1 SVG renders when real houses exist; D9/D10 are never fabricated
- each house owns its occupant coordinates and dense houses stay clipped and bounded
- evidenceRefs only produce in-page anchors for ids present in the appendix
- no dangerous HTML: no script tags, no external resources, no dangerouslySetInnerHTML
- long theme sections are not forced to avoid page breaks; only small elements are
留下的 8 条:契约解析、路由信封、失败摘要、畸形文档、导出按钮、阅读外壳、打印、目录。
### `frontend/tests/rectification-decide-next-action.test.ts` 删 1 条
- core barrel re-exports decideNextAction without duplicating session helpers
原因:barrel 文件已删。旁边的决定逻辑测试还在。
### `tests/test_repo_privacy_markers.py`
- 参数化用例 `test_exact_synthetic_line_permission_rejects_mutations` 少 1 条:原来指向 `frontend/tests/agent-evals.test.ts` 的合成路径许可。文件没了,许可项一起删。函数名还在,其余许可项还在。
## 改写断言(三栏写在源码注释里)
| 位置 | 原值 | 新值 | 原因 |
| --- | --- | --- | --- |
| `database-local-business.test.ts` 两处读取 | 用已删的 session 读取器核对候选 | 删掉读取。权限与 RPC 断言留着 | 读取器已删,库合同不变 |
| `personal-report-progress.test.ts` | 旧阅读页必须引用共享章节名 | 删这两条。共享表断言留着 | 旧阅读页已删 |
| `personal-report-export.test.ts` | 旧阅读页源码不得内嵌 HTML | 删这条。页面不得出现旧视图名字的断言留着 | 文件已删 |
| `rectification-step-answer.test.ts` | 读思考门源码,不得有组装函数 | 删这两行。连续 reasoning-delta 必须丢弃留着 | BUG-953,文件已删 |
| `evidence-audit-panel.test.ts` | 内部面板文案和死样式必须存在 | 删正向断言。聊天不得挂内部面板、读者审计表样式留着 | 面板已删,否定合同不放宽 |
| `claim-boundary-badge.test.ts` | 徽章文案和死样式必须存在 | 删正向断言。聊天行不得挂徽章留着 | 同上 |
| `global-birth-profile-routes.test.ts` | 旧校正载荷构造器用同一组坐标 | 删这段。每日与合盘断言留着 | 构造器已删 |
| `personal-report-density-retry.test.ts` | 原始附录出口不含内部词,并再打一次已删接口 | 直接核对快照:旧缓存没有计算快照;其余快照的适用性原文和正文与已保存的一致。净化函数的断言留着 | 出口已删,快照合同不放宽 |
| `test_daily_and_rectification_entrypoints.py` | 钉住代理源码 | 路由文件不存在,且网页 API 目录下没有路由再转发到内网问卷路径。测试名保留,测试数不降 | BUG-1342 |
| `test_repo_privacy_markers.py` 自检 | 替换已删除许可项里的那条合成路径 | 改为替换仍留在许可表里的另一条合成路径 | 改了许可原文仍必须被扫到,不放宽 |
## T5 死样式
删前在 `frontend/src` 与 `frontend/tests` 里,这些类只出现在即将删除的组件和即将改写的测试里。删后源码不再引用:`.claim-boundary-badge`、`.evidence-audit-panel`、`.evidence-audit-table`、`.evidence-audit-row`、`.raw-evidence-receipt`、`.birth-time-life-events`。`.personal-report-document`、`.technique-audit`、`.markdown-table` 没动。
## 自测
| 检查 | 命令 | 结果 |
| --- | --- | --- |
| 类型 | `frontend\node_modules\.bin\tsc --noEmit -p frontend` | 0 错 |
| lint | `npm run lint --prefix frontend` | 0 error,123 warning(开工口径 125,少 2,就是随 `birth-time-candidate-completion.ts` 消失的那两条;其余未改) |
| 改过的前端测试 | `node node_modules\tsx\dist\cli.mjs --test` 在 `frontend` 下跑点名的文件 | fail=0,cancelled=0。含密度 10 个模式与阅读页留下的 8 条 |
| Python | `.venv\Scripts\python -m pytest tests/test_daily_and_rectification_entrypoints.py tests/test_repo_privacy_markers.py -q` | 4 + 62 收集,exit 0 |
| 数据库 | `npm run test:db --prefix frontend` | 80 条:通过 67,失败 13,cancelled 0。失败名与 `windows-known-failures.txt` 逐条相同,没有多出来的。改过的本地业务库测试通过 |
没跑前端全量 `npm test`、Python 快速门、`next build`。
## test:db
`npm run test:db --prefix frontend` 退出码 1,因为 Windows 上那 13 条本来就会失败。失败名与 `tools/agent-loop/windows-known-failures.txt` 一致,没有新增:
- staging backups are encrypted, atomic, private, and retain the newest three
- rejects destructive backup directory aliases and symlink components before mutation
- rejects unsafe writable backup parents before creating the target
- rejects a direct canonical sticky shared backup directory before chmod
- creates every absent backup path component privately despite a permissive caller umask
- same-second backups publish once without overwriting the completed archive
- find enumeration failures preserve existing backups and do not report completion
- refuses full disks and removes a failed-pipeline partial file
- database env validator accepts punctuated literal required secrets
- database env validator enforces an explicit staging owner uid without printing values
- database env validator accepts a private valid file without printing values
- personal report job migration is atomic, lease-bound, recoverable, and owner read-only
- personal report sections enforce owner-read RLS and service-owned durable transitions
改过的 `database-local-business.test.ts`(local PostgreSQL applies the reviewed business schema and serves authenticated business calls)通过。权限和 RPC 断言还在。
## 第 1 次打回
合并最新 `origin/staging`。从 `knownUnstyled` 删掉 `personal-report-additional-charts`。其它白名单里没有被删组件留下的类名。业务代码没改。类名合同和两条否定合同 6 通过,失败 0,取消 0。`tsc` 0 错。`lint` 0 error,123 条原有 warning。
@@ -0,0 +1,44 @@
# PROGRESS · 长报告出稿提速(2026-10-14)
- 分支:`codex/report-reference-perf-20261013`
- 实际基线:`origin/staging` `66cd60081f37a57680274633fcb3fb942d01bb2f`(任务书写的 `77057a819`、计划评论里的 `2994588ad` 都更早,按当前 staging 开工)
- `scripts/jyotish_api_server.py`:10335 行,零改动
- 历史最大号在本基线上是 BUG-1322。BUG-1323~1334 已被其它未合入任务书占用。本单用任务书指定的 BUG-1335、BUG-1336。
## 做了什么
1. 两个开关在调用时读环境变量。渲染快捷路径默认关,同盘缓存默认开。
2. 中文和英文的大运密度补句:正则预编译,行内先看必出现的字面量,没有才不搜索;向前看的五行只在可能命中时才拼。术语替换:正文里没有这个词就原样返回,编译结果按词缓存。
3. 溯源哈希在开关打开时,一次遍历同时删掉 `**.键` 并做键名规范化。覆盖范围和排除集没变。没有跳过中间那次绑定,因为那会改 `format=json` 的键顺序。
4. 咨询卡缓存的单飞和两天清理多了一个子目录参数,咨询卡自己的键和目录不变。长报告只在完整数据版 + markdown、开关开、并且 `GITHUB_SHA` 是具体版本号时,才把整份响应放进 `scratch/local/report_reference_cache/`。查缓存发生在重计算之前。命中打一行不含资料的日志。
## 自测
| 检查 | 命令 | 结果 |
| --- | --- | --- |
| 任务书列出的 pytest | `.venv\Scripts\python.exe -m pytest` 后接任务书第 8 节那一串文件 `-q` | 退出码 0。缓存默认改成开之后又跑了一遍,仍是退出码 0 |
| 屏蔽 PyJHora 的 A/B | `python scripts/research/report_reference_perf_ab.py --mask-pyjhora` | 四张盘五字段 sha 相同;端到端下降 20%~23%,未达 35%;缓存命中中位约 0.06 秒 |
| 同一份解盘的 json / reference | 同上脚本 `--side-only` | 退出码 0。时钟钉死且复用同一次解盘后,两版 sha 相同 |
| 不屏蔽 | 未跑 | 本机没有 PyJHora,和屏蔽走同一条导入失败路径 |
数字见 `docs/testing/report-reference-perf-ab-20261013.md`。
## 改既有断言
无。原值 / 新值 / 原因:没有改旧断言。
## 未做
- 整篇替换逐条预检(让步顺序里最先砍的一项)。中文渲染只降了 20%~28%,不到 40%,没有为了过线改输出。
- 跳过中间绑定。
- 关掉没人读的质量门。任务书写明这要另开单,本单不动。
- 旧路径退役。开关还在。
## 默认值
- `JYOTISH_REPORT_RENDER_FAST` 默认关。字节一致,内存还降了约 12%,但端到端没到 35%。
- `JYOTISH_REPORT_REFERENCE_CACHE` 默认开。命中与未命中字节一致,命中中位约 0.06 秒。版本号缺失或是 `unknown` 时不缓存。
## 第 1 次打回
合并最新 `origin/staging` 后,把 `report_reference_cache` 登记进 `OFFLINE_SCRATCH_NAMES`。清理逻辑没改:这个目录仍由 `consult_full_data_cache.get_or_build` 在每次调用时删掉两天前的文件。没有改两个缓存模块的行为。
+9 -5
View File
@@ -332,7 +332,8 @@
| `TASK-rectification-refresh-r3-r4-20260913.md` | `PROGRESS-rectification-refresh-r3-r4-20260913.md` | 刷新阶段 R3(MIN_BOUNDARY_DAYS 45→30)+ R4(pratyantar 与 D9/D10 上升 Narayana);首轮出题不变。即使放宽仍有 0 题例子,定向补事另线保留(BUG-664/665) | 已实现 `ab1ade59`,已部署;2026-09-13 验收通过(实现单由执行方自拟,无产品决策记录段;收益口径见研究文档) | `codex/rectification-refresh-r3-r4-20260913` |
| `TASK-upstream-sync6-20261007.md` | [PROGRESS-upstream-sync6-20261007.md](PROGRESS-upstream-sync6-20261007.md) | **上游同步第六轮(`23be1807`)**:10-05 五个计算修正一行未合——D5/D6/D8/D11 映射(乔布斯盘四张分盘星座全不同)、Vimsopaka 权重、Yogini 顺序与出生余额、Panchadhikari 宫位参照、Narayana 并列、特殊上升、出生秒数、Neecha Bhanga 两条件、首段大运子运、岁差被覆盖;逐项对照原书核实;最先做 | 已验收(门禁补修 `2df6ee72`,已部署 staging) | [PROGRESS-upstream-sync6-20261007.md](PROGRESS-upstream-sync6-20261007.md) |
| `TASK-upstream-sync7-20261014.md` | [PROGRESS-upstream-sync7-20261014.md](PROGRESS-upstream-sync7-20261014.md) | **上游同步第七轮(BUG-1318 起)**:婚恋评级断语改证据档位、DK「婚姻质量 X/100」改对;KP 宫头到宫头判宫;瑜伽宫主排序去重;api_server 大运年长 365.25;星历路径只核查。不动校正打分。Grok 执行(agent 循环) | 待验收 | `codex/upstream-sync7-20261014`(BUG-1318~1321 已改;BUG-1322 星历路径核查中,未改代码) |
| `TASK-beta-main-path-20261014.md` | `PROGRESS-beta-main-path-20261014.md` | **内测主路径**:BUG-1063 他人报告 worker 读档案(逐列只读授权 + test:db);对话与报告「AI 生成,仅供参考」标识与免责;BUG-1080/283 状态;状态板按事实清账;冒烟清单 `docs/testing/beta-smoke-20261014.md`。与发布单并行 | 待验收 | `codex/beta-main-path-20261014` |
| `TASK-beta-main-path-20261014.md` | `PROGRESS-beta-main-path-20261014.md` | **内测主路径**:BUG-1063 他人报告 worker 读档案(逐列只读授权 + test:db);对话与报告「AI 生成,仅供参考」标识与免责;BUG-1080/283 状态;状态板按事实清账;冒烟清单 `docs/testing/beta-smoke-20261014.md`。与发布单并行 | 第 1 次打回后已修,待验收 | `codex/beta-main-path-20261014` |
| `TASK-beta-main-path-fix-20261014.md` | `PROGRESS-beta-main-path-20261014.md` | **#73 第 1 次打回**:`fca62fda` 内容通过;与 #63 删除的旧报告视图有代码冲突,接受删除即可 | 待验收 | `codex/beta-main-path-20261014` |
| `TASK-release-path-production-20261014.md` | — | **发布通路 + 生产首发**:产品 10-14 授权改生产工作流(发布 SHA = 最近门禁成功提交 + 其后纯文档);63 个迁移清单与演练脚本、首发 runbook;生产拒绝测试验证码。Grok 不 dispatch 生产工作流 | 待执行 | — |
| `TASK-beta-safety-net-20261014.md` | — | **内测安全网**:每日备份 + 恢复演练、探活告警、本地错误汇总、日志轮转、按 requestId 查日志。**等发布通路单合入、#58 合入后开工** | 待前置 | — |
| `TASK-beta-capacity-20261014.md` | — | **内测容量**:按用户限流、重计算短排队与对话重试、兑换码当邀请码、staging 10/20 并发压测。**等 #58 合入后开工,压测等 #57 合入** | 待前置 | — |
@@ -472,10 +473,13 @@
| `TASK-node-runtime-resources-fix-20261014.md` | `PROGRESS-node-runtime-resources-20261013.md` | **#58 第 1 次打回**:`4c3485bc` 其余全过;压测脚本放在 `frontend/scripts/` 却从 `frontend/tests/` 导入,镜像构建会失败(BUG-1140 形状,任务书指定的路径有误)。挪到 `frontend/tests/` 下非 `.test` 文件名 | 待验收 | `codex/node-runtime-resources-20261013` |
| `TASK-home-sidebar-rerender-20261013.md` | `PROGRESS-home-sidebar-rerender-20261013.md` | 流式回答时侧栏每帧整栏重渲染(BUG-1329,A/B) | 待验收 | `codex/home-sidebar-rerender-20261013` |
| `TASK-home-sidebar-rerender-fix-20261014.md` | `PROGRESS-home-sidebar-rerender-20261013.md` | **#59 第 1 次打回**:`63509431` 其余全过;`chat-navigation-a11y-contract` 按源码文本断言 `onOpenBilling` 旧写法未跟改(§7.8) | 待验收 | `codex/home-sidebar-rerender-20261013` |
| `TASK-api-disk-cache-retention-20261013.md` | — | API 磁盘缓存只进不出、VedAstro 审计文件留存出生资料、失败快照久缓存、缓存键规范化(BUG-1330~1332,A/B) | 待领取 | `codex/api-disk-cache-retention-20261013` |
| `TASK-report-reference-perf-20261013.md` | — | 长报告出稿提速:术语替换命中预检、哈希单次遍历、同盘复用(BUG-1335~1336,A/B) | 待领取 | `codex/report-reference-perf-20261013` |
| `TASK-consult-prep-parallel-20261013.md` | — | 普通对话发问前准备步骤并行、模型版本短缓存、多领域并发开关(BUG-1337~1339,A/B) | 待领取 | `codex/consult-prep-parallel-20261013` |
| `TASK-frontend-dead-code-20261013.md` | — | 前端死代码 17 文件与无调用方接口删除,含未登录重计算接口(BUG-1342) | 待领取 | `codex/frontend-dead-code-20261013` |
| `TASK-api-disk-cache-retention-20261013.md` | `PROGRESS-api-disk-cache-retention-20261013.md` | API 磁盘缓存只进不出、VedAstro 审计文件留存出生资料、失败快照久缓存、缓存键规范化(BUG-1330~1332,A/B) | 待验收 | `codex/api-disk-cache-retention-20261013` |
| `TASK-report-reference-perf-20261013.md` | `PROGRESS-report-reference-perf-20261013.md` | 长报告出稿提速:术语替换命中预检、哈希单次遍历、同盘复用(BUG-1335~1336,A/B) | 待验收 | `codex/report-reference-perf-20261013` |
| `TASK-report-reference-perf-fix-20261014.md` | `PROGRESS-report-reference-perf-20261013.md` | **#61 第 1 次打回**:`69c739fb` 本单全过;与清理规则合并后,长报告缓存目录补进自行清理名单 | 待验收 | `codex/report-reference-perf-20261013` |
| `TASK-consult-prep-parallel-20261013.md` | `PROGRESS-consult-prep-parallel-20261013.md` | 普通对话发问前准备步骤并行、模型版本短缓存、多领域并发开关(BUG-1337~1339,A/B) | 待验收 | `codex/consult-prep-parallel-20261013` |
| `TASK-consult-prep-parallel-fix-20261014.md` | `PROGRESS-consult-prep-parallel-20261013.md` | **#62 第 1 次打回**:两条源码文本检查改认新位置,对照脚本挪进测试目录 | 待验收 | `codex/consult-prep-parallel-20261013` |
| `TASK-frontend-dead-code-20261013.md` | `PROGRESS-frontend-dead-code-20261013.md` | 前端死代码 17 文件与无调用方接口删除,含未登录重计算接口(BUG-1342) | 待验收 | `codex/frontend-dead-code-20261013` |
| `TASK-frontend-dead-code-fix-20261014.md` | `PROGRESS-frontend-dead-code-20261013.md` | **#63 第 1 次打回**:类名白名单去掉已删组件留下的条目 | 待验收 | `codex/frontend-dead-code-20261013` |
| `TASK-api-chart-subprocess-gate-20261013.md` | — | 合盘不带 skip 串行排盘、报告无效子进程、名额轻重混用(只模拟)(BUG-1333~1334,A/B) | 待领取(排队:api-disk-cache-retention + report-reference-perf) | `codex/api-chart-subprocess-gate-20261013` |
| `TASK-answer-effort-ab-20261013.md` | — | 答题步推理强度开关 + A/B(需模型 key) | 待领取(排队:consult-prep-parallel) | `codex/answer-effort-ab-20261013` |
| `TASK-consult-route-split-20261013.md` | — | consult POST 拆分第一阶段:开流前加载 + 计费结算 | 待领取(排队:consult-prep-parallel、answer-effort-ab) | `codex/consult-route-split-20261013` |
@@ -0,0 +1,36 @@
# TASK · 内测主路径修复单(issue #73,第 1 次打回:与 #63 代码冲突)
- 日期:2026-10-14
- 原任务书:`docs/tasks/TASK-beta-main-path-20261014.md`
- 被验 SHA:`fca62fda43b3f8b7bb76303bf0c83427d25c63ee`(`codex/beta-main-path-20261014`)
- 执行方:Grok,同一分支续做(merge 最新 `origin/staging`,不改写已推历史)
- BUG 编号:沿用 BUG-1063 等本单编号
## 1. 验收结论:内容通过,与 staging 合并有代码冲突
| 检查 | 结果 | 证据 |
| --- | --- | --- |
| 迁移 `20261014010000_chart_profiles_service_role_select.sql` | 通过 | 只加逐列 SELECT,列与 `CHART_SUBJECT_SELECT` 一致;不授写、不改 RLS、不动 authenticated;只增不删,对已部署代码向后兼容(§7.6) |
| `test:db` | 以 Grok 为准 | 82 项 / 失败 13,与 `windows-known-failures.txt` 逐名相同 |
| AI 生成标识 | 通过 | 输入框下一行、报告标题下一行;英文句只锁不显示 |
| 状态板清账 | 通过 | 写「已部署 staging `xxxx`」的 11 个提交号,我逐个核对都在 `origin/staging` 上;未把任何一条标成 resolved |
| 与最新 staging 合并 | **未通过** | `CONFLICT (modify/delete): frontend/src/components/personal-report/personal-report-document-view.tsx deleted in origin/staging and modified in HEAD` |
**原因**:#63(BUG-1342,已在 staging)把从不挂载的旧报告视图 `personal-report-document-view.tsx` 整个删了;本单给它的 `ReportCover` 加了一行 AI 标识。两单同时在做,不是你的疏漏。
## 2. 修法要求
1. `git merge origin/staging`,冲突里**接受删除**(`git rm frontend/src/components/personal-report/personal-report-document-view.tsx`)。现行报告页是 `personal-report-markdown-view.tsx`,那里的标识已经加上,不需要再找新位置。
2. `frontend/tests/ai-generated-notice-20261014.test.ts` 里若有读取 / 断言该已删文件的,删掉那部分,按 §7.3 写三栏;markdown 视图、输入框的断言保留不动。
3. `CHANGELOG.md`、`docs/BUG_HISTORY.md` 的文档冲突两边都保留。
4. 合并后在本机跑:`tsc --noEmit`、`npm run lint`、`npx tsx --test tests/ai-generated-notice-20261014.test.ts tests/runtime-sources-no-test-imports.test.ts tests/class-name-definition-contract.test.ts`,fail 与 cancelled 都为 0。
5. 业务代码除上面这处外不改。PROGRESS 末尾记一行。
## 3. 验收标准
- `git merge-base --is-ancestor origin/staging <新 SHA>` 成立;
- Claude 前端全量 `npm test` 失败清单与 staging 基线逐名相同。
## 4. 让步顺序
无。第 1 次打回。
@@ -0,0 +1,41 @@
# TASK · 发问准备并行修复单(issue #62,第 1 次打回)
- 日期:2026-10-14
- 原任务书:`docs/tasks/TASK-consult-prep-parallel-20261013.md`
- 被验 SHA:`a0e223e20cebcce3479accb60f6aec44d1caadda`(`codex/consult-prep-parallel-20261013`)
- 执行方:Grok,同一分支续做(先 merge 最新 `origin/staging`,不改写已推历史)
- BUG 编号:沿用 BUG-1337~1339
## 1. 验收结论:业务逻辑通过;前端全量多出 3 条真失败
| 检查 | 结果 | 证据 |
| --- | --- | --- |
| 开关全关时的顺序 | 通过 | `turn-prep.ts` 串行分支与原 `route.ts` 的 401→423→400→503→404→409→409→503 逐条同序 |
| 开关开时 | 通过 | 删号判定仍最先返回、在任何写库扣点之前;审核结论在 `beforeReserve` 内等齐,被拦不 reserve |
| `readVersion` 缓存 | 通过 | 只缓存成功结果,`invalidateLanguageModelCatalog` 同时清;默认 TTL 0 |
| tsc / lint | 通过 | 0 错 / 0 error |
| 前端全量 `npm test`(与 staging 逐名比对) | **未通过:新增 3 条** | 见下 |
1. `frontend/tests/chat-session-authority.test.ts`「consult POST on a rectification session is 409, a missing id is 404」:第 65 行在 `route.ts` 源码里找 `/if \(!chatSession\) \{[\s\S]*status: 404/`——这段判定挪进了 `frontend/src/lib/consult/turn-prep.ts`(`sessionMissing()`),断言没跟着挪。
2. `frontend/tests/consultation-workflow-contract.test.ts`「consultation plans are server-owned and bounded」:第 160 行找 `/beforeReserve: \(\{ consultationMode \}\) => createConsultationPlan\(\{/`,第 161 行找 `reserve: () => reserveConsultationModel(`——两处都改成了 `async` 函数体。
3. `frontend/tests/runtime-sources-no-test-imports.test.ts`:`frontend/scripts/research/consult-prep-parallel-ab.mts` 第 9 行从 `../../tests/support/stub-server-only.mjs` 导入。web 镜像不复制 `frontend/tests`,推上 staging 后镜像构建会失败(BUG-1140;#58 刚因同一形状打回过一次)。
原任务书 §5 第 7 条已经列出要先 grep 的源码文本断言;这次漏的两条不在那份清单里,但属于同一类(AGENTS.md §7.8)。
## 2. 修法要求
1. **1、2 两条**:按 §7.3 写「原值 / 新值 / 原因」三栏改断言,**意图不得放宽**:
- 1:改为在 `turn-prep.ts` 里锁「查不到会话 → 404」「类型不是 consultation → 409 `session_not_consultation`」,并保留第 70 行那条「不得合并成一个判断」的反向断言(针对新文件)。
- 2:改为锁「`beforeReserve` 里调用 `createConsultationPlan`」「`beforeReserve` 在 `reserve` 之前」「`reserve` 调用 `reserveConsultationModel`」,允许 `async` 写法,但不得只查函数名存在。
2. **第 3 条**:把 `consult-prep-parallel-ab.mts` 挪到 `frontend/tests/` 下(文件名不得以 `.test.ts` / `.test.tsx` 结尾),导入改相对路径;同步改 PROGRESS 与 `docs/testing/consult-prep-parallel-ab-20261013.md` 里的命令路径。`frontend/scripts/research/` 下其它新增文件同样检查。
3. 再 grep 一遍 `route.ts` 被挪走 / 改写的语句在 `frontend/tests`、`tests` 里还有没有按源码文本断言的:`grep -rn "chatSession\.session_type\|getUser()\|refuseWhenAccountDeletionPending\|resolveSessionLanguageModel(\|reserveConsultationModel(\|createConsultationPlan(" frontend/tests tests`,命中的逐条确认。
4. 业务代码不改;三个开关默认值不变。
## 3. 验收标准
- 前端全量 `npm test` 失败清单与 staging 基线逐名相同(本机另有 Docker 类失败,以基线为准);
- `git diff a0e223e2..<新 SHA> -- frontend/src` 为空。
## 4. 让步顺序
无。第 1 次打回。
@@ -0,0 +1,33 @@
# TASK · 前端死代码删除修复单(issue #63,第 1 次打回)
- 日期:2026-10-14
- 原任务书:`docs/tasks/TASK-frontend-dead-code-20261013.md`
- 被验 SHA:`1f9947a0d733e34b7754cce058e20b023791fdd8`(`codex/frontend-dead-code-20261013`)
- 执行方:Grok,同一分支续做(先 merge 最新 `origin/staging`,不改写已推历史)
- BUG 编号:沿用 BUG-1342
## 1. 验收结论:一条未通过,其余全部通过
| 检查 | 结果 | 证据 |
| --- | --- | --- |
| 删除范围 | 通过 | 删掉的文件与三个路由都在原任务书清单内;全仓 grep 三个路由路径、被删模块名,`frontend/src`、`scripts`、`deploy`、`.gitea` 无残留引用 |
| 改既有断言 | 通过 | 每处三栏齐全;否定合同(不得挂内部徽章 / 内部面板)保留;`/api/birth-rectification` 改成「路由不存在且无代理」 |
| tsc / lint / next build | 通过 | 0 错 / 0 error(warning 125→123)/ `/` 仍 Static;首屏 gzip −312 字节 |
| Python 改动的两份测试 | 通过 | — |
| 前端全量 `npm test`(与 staging 逐名比对) | **未通过:新增 1 条** | `frontend/tests/class-name-definition-contract.test.ts`「the knownUnstyled allowlist has no stale entries」:`actual: ['personal-report-additional-charts']` |
**根因**:`class-name-definition-contract.test.ts` 第 62 行的 `knownUnstyled` 白名单里有 `personal-report-additional-charts`,这个类名唯一的使用者是已删除的 `personal-report-document-view.tsx`。合同要求白名单里不能有已经没人用的条目。
## 2. 修法要求
1. 从 `knownUnstyled` 删掉 `"personal-report-additional-charts"` 这一项,旁边按 §7.3 写三栏(原值:白名单含该项;新值:删除;原因:唯一使用者随 BUG-1342 删除,白名单不得留陈旧条目)。
2. 再查一遍:被删文件里用到的其它类名,是否还出现在别的白名单 / 合同里(`grep -rn "knownUnstyled\|allowlist" frontend/tests` 后逐个核对)。
3. 业务代码不改。PROGRESS 末尾记一行。
## 3. 验收标准
前端全量 `npm test` 失败清单与 staging 基线逐名相同(本机 Docker 类失败除外)。
## 4. 让步顺序
无。第 1 次打回。
@@ -0,0 +1,36 @@
# TASK · 长报告提速修复单(issue #61,第 1 次打回)
- 日期:2026-10-14
- 原任务书:`docs/tasks/TASK-report-reference-perf-20261013.md`
- 被验 SHA:`69c739fbee3f5af6deed911482d82e49ed429bf7`(`codex/report-reference-perf-20261013`)
- 执行方:Grok,同一分支续做(先 merge 最新 `origin/staging`,不改写已推历史)
- BUG 编号:沿用 BUG-1335、1336
## 1. 验收结论:本单自身全部通过;与 #60 合并后一条合同测试红
| 检查 | 结果 | 证据 |
| --- | --- | --- |
| 与最新 staging 合并后的定向测试 | **未通过** | `tests/test_api_scratch_retention.py::test_new_scratch_local_dirs_are_registered_or_whitelisted`:`AssertionError: ['report_reference_cache']` |
| 逐字节一致(Claude 在 Linux、屏蔽 PyJHora 复跑 A/B) | 通过 | 四张虚构盘 A / B 未命中 / B 命中 / 缓存首算的五个字段 sha 全部相同;`format=json`、`edition=reference` 两条 sha 相同 |
| 耗时 | 与回报一致 | 未命中中位数 21.1→15.6 s(day)等,降约 22–26%,未到 35% 门槛 → 渲染提速默认关正确;命中 0.02–0.03 s |
| 缓存键含 `today` | 通过 | `_high_rigor_birth_payload` 在缺省时把当天日期写进 `birth`,跨天不会命中 |
| `GITHUB_SHA` | 通过 | 部署编排已传入;缺失或 `unknown` 时不缓存 |
| `jyotish_api_server.py` | 通过 | 零改动 |
**根因**:#60(BUG-1330~1332,已在 staging)新增了合同测试:`scripts/` 里写 `scratch/local/<子目录>` 的地方,必须登记在 `scripts/api_scratch_retention.py` 的 `REGISTRY`(服务器周期清理)或 `OFFLINE_SCRATCH_NAMES`(自己会清理的缓存)里。本单新增的 `scratch/local/report_reference_cache/` 两边都没登记。两单各自都对,合在一起才红——这不是你的疏漏,是两单同时在做。
## 2. 修法要求
1. 合并最新 `origin/staging`(含 #60)。
2. 在 `scripts/api_scratch_retention.py::OFFLINE_SCRATCH_NAMES` 加 `"report_reference_cache"`,旁边写一行注释:它与 `consult_full_data_cache` 同走 `consult_full_data_cache.get_or_build`,每次调用先 `prune_cache(name=…)` 删两天前的文件,自己会清;含出生资料,保留期 2 天。
3. 不改两个模块的任何逻辑。
4. PROGRESS 末尾记一行。
## 3. 验收标准
- `python -m pytest tests/test_api_scratch_retention.py tests/test_report_reference_perf.py tests/test_consult_card_full_source.py -q` 全绿;
- Claude 全量 pytest 与 staging 基线逐条比对无新增。
## 4. 让步顺序
无。第 1 次打回。