Files
Jyotisha/docs/tasks/TASK-frontend-dead-code-20261013.md
T
Jesse_ChenandClaude Opus 5.5 0be4cb299c docs(tasks): code-health + performance audit briefs, 16 tasks (BUG-1323 onward)
Batch 1 (dispatch now): rect-scoring-perf, node-runtime-resources,
home-sidebar-rerender, api-disk-cache-retention, report-reference-perf,
consult-prep-parallel, frontend-dead-code.
Batch 2 (queued on predecessors): api-chart-subprocess-gate, answer-effort-ab,
consult-route-split, pl9-render-split, python-hygiene, dasha-unify,
api-server-service-extract, data-layer-types, contracts-helpers-dedupe.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014Ad9rqAB8pXXvyzh7f4X8v
2026-10-14 00:34:35 +08:00

21 KiB
Raw Blame History

TASK · 前端死代码与无调用方接口清理(issue #待定)

  • 日期:2026-10-13
  • 来源:「2026-10-13 全仓屎山与性能排查」· 前端死代码条目
  • 执行方:Grok(Windows + Docker),分支 codex/frontend-dead-code-20261013,只推这个分支
  • 验收:Claude(Linux)
  • BUG 编号:本单发现 1 个真实缺陷(§2.3,未登录可触发的引擎重计算),编号 BUG-1342(写作时最大号 BUG-1317,1323~1341 已被同批任务书占用;开工时核对 docs/BUG_HISTORY.md 最大号)。其余删除是重构,无 BUG 号,记 PROGRESS。(另:TASK-upstream-sync7-20261014 占 BUG-1318~1322,本批号段整体从 BUG-1323 起)
  • 开工前置:无(第一批,立即派发)。后续 contracts-helpers-dedupe 依赖本单合入。

1. 基线

  • 基线 commit:origin/staging 77057a819
  • 判定口径:从 Next 约定入口(src/app/** 下 page/layout/route/loading/error/not-found/...、src/instrumentation.ts)出发,沿 @/、相对路径、动态 import() 做可达性遍历;再补查字符串引用(readFileSync(new URL(...)))、Python 测试、deploy/、文档对外承诺。
  • 复现命令(写作时用的脚本,Grok 可直接用;在 frontend/ 下运行):
python3 - <<'EOF'
import os,re
imp=re.compile(r'''(?:from\s+|import\s*\(\s*|import\s+|require\(\s*)['"]([^'"]+)['"]''')
files=[os.path.join(d,f) for d,_,fs in os.walk('src') for f in fs if f.endswith(('.ts','.tsx'))]
def res(src,spec):
    if spec.startswith('@/'): b=os.path.join('src',spec[2:])
    elif spec.startswith('.'): b=os.path.normpath(os.path.join(os.path.dirname(src),spec))
    else: return None
    b2=re.sub(r'\.(ts|tsx|js)$','',b)
    for c in [b,b2+'.ts',b2+'.tsx',os.path.join(b,'index.ts'),os.path.join(b,'index.tsx')]:
        if os.path.isfile(c): return os.path.normpath(c)
g={f:{r for m in imp.findall(open(f,encoding='utf8').read()) if (r:=res(f,m))} for f in files}
conv=re.compile(r'(^|/)(page|layout|route|loading|error|not-found|global-error|forbidden|template|default|instrumentation|middleware|proxy)\.(ts|tsx)$')
seen=set(); st=[f for f in files if conv.search(f)]
while st:
    x=st.pop()
    if x not in seen: seen.add(x); st+=g.get(x,())
for f in sorted(set(files)-seen): print(f, sum(1 for _ in open(f,encoding='utf8')))
EOF

2. 事故实证(77057a819)

2.1 生产入口不可达的源文件(脚本输出,17 个,共 3,028 行)

文件 行 引用方(全仓) 结论
src/mastra/rectification-tools.ts 736 仅 rectification-agentic/session.ts + tests/rectification-agentic-tools.test.ts 删
src/lib/rectification-agentic/session.ts 351 tests/rectification-agentic-session.test.ts、tests/database-local-business.test.ts(DB 测试,2 处断言) 删
src/lib/rectification-agentic/date-range.ts 53 仅 rectification-tools.ts 删(传递死)
src/lib/agent-evals.ts 796 tests/agent-evals.test.ts(+ fixture tests/fixtures/agent-golden-dataset-v1.json) 删
src/components/personal-report/personal-report-document-view.tsx 630 personal-report-view.test.ts(渲染)、personal-report-progress.test.ts:208-209、personal-report-export.test.ts:49(读源码) 删;阅读页 09 月起走 personal-report-markdown-view.tsx
src/lib/think-step-gate.ts 17 public-thinking.test.ts、rectification-step-answer.test.ts:64(读源码) 删;最后一个生产调用方在 eef0cb748(BUG-1053)移除
src/lib/birth-time-candidate-completion.ts 14 birth-time-candidate-completion.test.ts 删(函数恒返回 null;顺带消掉 BLOCKED.md 登记的 2 条 lint warning)
src/components/birth-time-life-events.tsx 207 无(BUG-1193 已注明「无引用方」) 删
src/components/evidence-audit-panel.tsx 64 evidence-audit-panel.test.ts 读源码 删,保留否定断言(见红线)
src/components/claim-boundary-badge.tsx 13 claim-boundary-badge.test.ts 读源码 删,保留否定断言
src/components/birth-time-soft-notice.tsx 36 只有否定断言(doesNotMatch) 删
src/components/personal-report/raw-appendix-download.tsx 33 personal-report-raw-appendix.test.ts:106 读源码 删(09-24 已授权,见 §4)
src/lib/chart-library-view.ts 18 无 删
src/lib/db/client.ts 18 无(仓内唯一 drizzle-orm 引用方) 删;依赖不动,见后续阶段
src/lib/rectification-agentic/core/index.ts 23 rectification-decide-next-action.test.ts:587 读源码 删 barrel,对应测试改写
src/lib/rectification-agentic/v9/index.ts 11 无 删 barrel
src/lib/personal-report-longform-download.ts 8 4 个测试 不删——见下

修正排查结论:personal-report-longform-download.ts::ordinaryReportDownloadMarkdown 是 TASK-report-chapter-export-20260924 D5 明文保留的逐字节回归锁(report-export-blocks.test.ts:55-57「全选导出 ≡ 旧普通导出」与冻结 sha256),文件头注释也写明「retained as the full-body byte regression lock」。本单不动它。

2.2 无前端调用方的接口

接口 行 现状
POST /api/birth-rectification(src/app/api/birth-rectification/route.ts) 49 全仓无 fetch;只被 tests/test_daily_and_rectification_entrypoints.py::test_birth_rectification_api_proxies_active_questionnaire_with_boundary 读源码钉住(07 月「入口产品化」时代的源码文本断言,首页卡片入口 BUG-1247 后早已删除)。唯一依赖 src/lib/birth-rectification-payload.ts(41 行),后者另被 global-birth-profile-routes.test.ts:43 一处断言使用
POST /api/birth-time-candidate-completion 20 无调用方;恒返回 400/409 的「旧客户端兼容」桩(07-21 起),任何客户端都不会再发
POST /api/reports/[reportId]/raw-appendix 48 唯一调用方就是上面的死组件 raw-appendix-download.tsx;releaseRawReportAppendix(src/lib/personal-report-raw-appendix.ts,13 行)只剩这条路由 + 测试使用

对外承诺核查:deploy/、skills/、references/、MCP、文档对外章节都没有这三个路径(references/oracle/...json 中的 birth-rectification 是无关英文词)。

2.3 真实缺陷:未登录即可触发约 20 秒的引擎重计算

  • /api/birth-rectification 不鉴权(src/ 下没有 middleware/proxy;该 route 不读会话),Caddy 把 /api/* 全部反代到 web(deploy/Caddyfile.staging、Caddyfile.production.selfhosted)。
  • 它把请求转发到 Python /api/active_rectification_questions(uncertainty_minutes: 30, step_minutes: 2),该路径不在 scripts/api_heavy_compute_gate.py::HEAVY_COMPUTE_PATHS 中,不受并发 2 的闸门限制。
  • 实测(本机,虚构盘 1990-01-01 12:00 新德里,build_questionnaire 同参数,3 次):20.7 s / 25.6 s / 23.6 s,中位 23.6 s 单核 CPU。
  • Next 侧 2.5 s 后 abort,但 Python 是同步处理,中止不会打断计算(推断,未在 staging 实打)。即:任何人无需登录,每发一次 POST 就消耗生产 API 容器约 20 秒 CPU(主机 2 vCPU),且无并发上限。
  • 复现命令:
python3 -c "
import sys,time; sys.path[:0]=['.','scripts']
from scripts.active_rectification_questions import build_questionnaire
t=time.time(); build_questionnaire('1990-01-01 12:00',uncertainty_minutes=30,step_minutes=2,lat=28.6139,lon=77.2090,tz=5.5,ayanamsa='lahiri',node_mode='mean'); print(round(time.time()-t,1))"

(运行后若工作树产生 scratch/ 缓存,它在 .gitignore 里,不入库。)

3. 根因

  • 这些文件是历次改版的残留:旧 agentic 校正(被 v9 取代)、旧结构化报告阅读页(被 Markdown 阅读页取代)、内部审计面板(BUG-011/298 从聊天里摘掉后没删组件)、09-24 原始附录下线时删除被权限系统拒绝(BUG-1004 修订条)。每次只摘入口、不删实现,测试又在读源码文本,所以死代码一直「有测试、看起来活着」。
  • /api/birth-rectification 是 07 月早期首页卡片的后端;卡片删了,路由没删;写它时还没有鉴权约定与重计算闸门。不是回归,是遗留入口从未收口。
  • 关联:BUG-011、BUG-298(内部面板不得重新挂载)、BUG-953(think 门保留的来由)、BUG-1004(原始附录下线时删除被拒)、BUG-1053(移除 think 门最后调用方)、BUG-1178(注明旧 rectification-tools.ts 仅 legacy 引用)、BUG-1193(birth-time-life-events.tsx 无引用方)。

4. 决策记录

  • 2026-10-13 产品负责人同意按排查结论全部立单交 Grok 执行;产品偏好「多余入口宁可删除也不修」(CLAUDE.md)。
  • 测试总数下降是产品授权的例外:AGENTS.md §7.3 规定测试总数不得低于基线;本单删除的是「只测死代码」的测试,授权其随实现一起删除。条件:PROGRESS 里逐条列出删掉的测试名(文件 + 测试标题)与原因;否定合同(「不得再挂载 X」)不在例外内,必须保留或改写成等价断言。
  • 原始附录路由:TASK-report-reader-actions-20260924 D2 已授权「/api/reports/[reportId]/raw-appendix 路由与 releaseRawReportAppendix 若全仓再无调用者一并删除(含其测试,三栏说明)」,当时被权限系统拒绝。本单完成该授权,不新增授权。
  • /api/birth-rectification:删除即修复 §2.3 缺陷,不给它补鉴权(多余入口删除而不修)。Python 端 /api/active_rectification_questions 只在 Docker 内网,不动(jyotish_api_server.py 冻结)。
  • ordinaryReportDownloadMarkdown 保留(09-24 D5 回归锁),不推翻。
  • 不在本单:旧协议 legacy-guided-v1 全链路、裸 textarea(存量数据还在用);drizzle-orm 依赖移除;其它疑似无调用方路由(见后续阶段)。

5. 硬红线

  1. 只删不改:除下面列明的测试改写、DESIGN.md 一行、BLOCKED.md 划线、BUG_HISTORY/PROGRESS 外,不改任何生产文件的逻辑。删一个文件导致的编译错误只能通过「继续删死代码」或「删 import」解决,不得改业务代码去迁就。
  2. 否定合同必须保留:chat-message-row.tsx / chat-message-content.tsx / technique-audit 不得出现 EvidenceAuditPanel、ClaimBoundaryBadge、techniqueTruth/workflowReceipt 挂载(BUG-011/298);<BirthTimeSoftNotice 否定断言;report-actions 不得出现 RawAppendixDownload;step-answer 对 reasoning-delta 一律丢弃(BUG-953)。删组件后,这些测试里读被删文件源码的行删掉,否定断言原样保留。
  3. ordinaryReportDownloadMarkdown 与其 4 个测试不动;report-export-blocks.test.ts 的冻结 sha256 不动。
  4. 改既有断言按 §7.3 写「原值 / 新值 / 原因」三栏注释;整条测试删除的,写进 PROGRESS「删除测试清单」。
  5. 不改数据库结构与迁移(RPC accept_agentic_rectification_candidate* 等保留,只删 TS 调用方);frontend/src/app/(app)/page.tsx 不增长;scripts/jyotish_api_server.py 不增长(本单不碰);不改 .gitea/workflows/**;不升级、不删除依赖(drizzle-orm、@mastra/* 都不动)。
  6. 不碰 legacy-guided-v1 相关文件(birth-time-journey*、birth-time-scoring*、birth-time-legacy-rectification.tsx 等)。

6. 任务分解

T1 · 删旧 agentic 校正链(Grok 自跑 + Claude 复验)

  • 删:src/mastra/rectification-tools.ts、src/lib/rectification-agentic/session.ts、src/lib/rectification-agentic/date-range.ts、tests/rectification-agentic-tools.test.ts(14 条)、tests/rectification-agentic-session.test.ts(16 条)。
  • tests/database-local-business.test.ts:删第 11 行 import 与两处 loadLatestAgenticRectificationResult(...) 断言(约 842–852、1040–1043 行),同一测试里的 psql 权限断言、RPC 断言原样保留;三栏注释。
  • 验收:grep -rn "rectification-tools\"\|rectification-agentic/session\|date-range" frontend/src frontend/tests 无结果;tsc --noEmit 0 错;npm run test:db 由 Grok 跑,失败清单与 tools/agent-loop/windows-known-failures.txt 逐条比对,多一条即未通过;Docker 没开就写「未跑」。

T2 · 删旧报告阅读视图、think 门、评测、零引用组件与 barrel

  • 删:personal-report-document-view.tsx、think-step-gate.ts、agent-evals.ts + tests/agent-evals.test.ts(11 条)+ tests/fixtures/agent-golden-dataset-v1.json、birth-time-candidate-completion.ts + 其测试(1 条)、birth-time-life-events.tsx、evidence-audit-panel.tsx、claim-boundary-badge.tsx、birth-time-soft-notice.tsx、chart-library-view.ts、lib/db/client.ts、rectification-agentic/core/index.ts、rectification-agentic/v9/index.ts、tests/public-thinking.test.ts(5 条)。
  • 测试改写(三栏):
    • personal-report-view.test.ts:删掉渲染 PersonalReportDocumentView 的用例(约 32–283 行之间,Grok 逐条判断:凡调用 render(...)/PersonalReportDocumentView 的删,测 parseReportEnvelope、路由、阅读页外壳、TOC、打印的保留)。若「v1/v2 fixture 通过契约解析」等用例只依赖 personal-report-contract,保留并去掉 view import。
    • personal-report-progress.test.ts:200-209:去掉对 document-view 源码的两条断言,保留「章节名只定义一处」对其它文件的断言。
    • personal-report-export.test.ts:18-19, 49:去掉 documentViewSource 读取与断言,pageSource 否定断言保留。
    • rectification-step-answer.test.ts:64-65:去掉读 gate 源码两行,reasoning-delta 丢弃断言保留。
    • rectification-decide-next-action.test.ts:586-594「core barrel re-exports…」:barrel 删除后整条删除(PROGRESS 列名)。
    • evidence-audit-panel.test.ts、claim-boundary-badge.test.ts:删 panelSource/badgeSource 读取与对其的正向断言;对 rowSource/contentSource 的否定与 TechniqueAuditDisclosure 断言保留;对 globals.css 中 .evidence-audit-panel、.claim-boundary-badge、.raw-evidence-receipt 的「存在」断言删除(T5 删 CSS 时这些类将不存在)。
    • tests/test_repo_privacy_markers.py SAFE_LINES 删 frontend/tests/agent-evals.test.ts 一项(文件已删;参数化用例少 1 条,PROGRESS 列名)。
  • 验收:再跑 §1 脚本,输出只剩 personal-report-longform-download.ts;tsc --noEmit 0 错;npm run lint 0 error(预期 warning 减少 2 条:birth-time-candidate-completion.ts:10,11);改到的测试文件单跑 fail=0、cancelled=0;.venv 下 pytest tests/test_repo_privacy_markers.py -q 通过。

T3 · 删三个无调用方接口(含本单 BUG)

  • 删:src/app/api/birth-rectification/route.ts、src/lib/birth-rectification-payload.ts、src/app/api/birth-time-candidate-completion/route.ts、src/app/api/reports/[reportId]/raw-appendix/route.ts、src/components/personal-report/raw-appendix-download.tsx、src/lib/personal-report-raw-appendix.ts。
  • tests/test_daily_and_rectification_entrypoints.py::test_birth_rectification_api_proxies_active_questionnaire_with_boundary 改写为否定合同(测试数不降):断言 frontend/src/app/api/birth-rectification/route.ts 不存在,且 frontend/src/app/api 下没有任何 route 源码含 /api/active_rectification_questions。三栏注释(原值:钉住代理源码;新值:路由不存在且无代理;原因:本单 BUG,未鉴权的重计算入口)。
  • global-birth-profile-routes.test.ts:43-49:删 payloadFromProfile 那段断言与 import,daily/synastry 断言保留;三栏。
  • tests/personal-report-raw-appendix.test.ts:整文件删除(4 条 + 11 条路由守卫参数化)。
  • tests/personal-report-density-retry.test.ts:第 9、33、55、124 行使用 releaseRawReportAppendix。Grok 逐条判断:只为验证原始附录输出的断言随之删除;验证快照写入/恢复本身的断言保留(把对 releaseRawReportAppendix(...) 结果的检查改成对快照字段的检查,不得弱化快照合同);每处三栏。若无法在不弱化的前提下改写,本条退回:保留 personal-report-raw-appendix.ts(仅删路由与组件),写进 PROGRESS。
  • 验收:grep -rn "birth-rectification\b\|birth-rectification-payload\|birth-time-candidate-completion\|raw-appendix\|releaseRawReportAppendix" frontend/src 无结果(birth-rectification-card 否定断言在 tests 中仍在);.venv/bin/python -m pytest tests/test_daily_and_rectification_entrypoints.py -q 通过;相关前端测试单跑通过。

T4 · 记录(Grok)

  • docs/BUG_HISTORY.md:
    • 新增本单 BUG(标题建议:「未登录即可调用 /api/birth-rectification,每次触发约 20 秒、不受闸门限制的引擎计算」),状态 resolved(分支),写实测数字、根因、修复(删除)、验证(否定合同测试)、防复发(新增 app/api/**/route.ts 必须鉴权或显式列为公开;重计算路径必须进 HEAVY_COMPUTE_PATHS——本单只记录,不改 gate 文件)。
    • BUG-1004 追加「2026-10-13 frontend-dead-code 完成 09-24 D2 删除」一行;BUG-953 追加「acceptThinkStepText 最后调用方 BUG-1053 移除,10-13 删除」一行。
  • BLOCKED.md 第 631 行附近 birth-time-candidate-completion.ts:10,11 两条 warning:划掉并注明已随文件删除(不删原文)。
  • frontend/DESIGN.md:1084「个人报告页走 personal-report-document-view.tsx」改为 personal-report-markdown-view.tsx。
  • docs/tasks/PROGRESS-frontend-dead-code-20261013.md:删除文件清单(路径 + 行数)、删除测试清单(文件 + 测试标题 + 原因)、改写断言三栏汇总、test:db 比对结果、§1 脚本前后输出。
  • CHANGELOG.md:一行「删除三个无调用方接口(含一个未鉴权的重计算入口)与约 3,000 行死代码」,Skill 版本不 bump。

T5 · 死 CSS(可砍)

  • 只删选择器里的类名在 frontend/src/**/*.{ts,tsx} 中 0 引用的规则:预期包括 globals.css 497–506 行(.claim-boundary-badge、.evidence-audit-panel*、.raw-evidence-receipt*)与 1148 行 .birth-time-life-events。.personal-report-document 等被 Markdown 阅读页共用的类不得删。每删一个类前 grep -rn "<类名>" frontend/src frontend/tests。
  • 验收:Claude next build 后首屏 gzip 只减不增。

7. 让步顺序

时间不够依次砍:T5 → T3 中 raw-appendix 部分(退回为 PROGRESS 待办)→ T2 中 personal-report-view.test.ts 拆分(保留 document-view 文件,写 PROGRESS)。T3 的 /api/birth-rectification 删除与 T4 BUG 记录不得砍。

8. 验收命令分工

谁 命令
Grok 自跑 tsc --noEmit;npm run lint;改到/删到的前端测试文件逐个单跑(fail、cancelled 均为 0);.venv/bin/python -m pytest tests/test_daily_and_rectification_entrypoints.py tests/test_repo_privacy_markers.py -q;npm run test:db(动了 database-local-business.test.ts,以 Grok 为准,按 windows-known-failures.txt 比对)。前端全量、Python 快速门、next build 不跑
Claude 验收 上述全部 + 前端全量 npm test:失败清单与基线逐条一致,总数下降量 = PROGRESS 删除测试清单条数(逐名核对)+ Python 快速门 + next build(/ 仍 Static,首屏 gzip 不增)+ 重跑 §1 脚本

9. 开工前置命令

git fetch origin --prune
git worktree add -b codex/frontend-dead-code-20261013 .worktrees/frontend-dead-code-20261013 origin/staging
cd .worktrees/frontend-dead-code-20261013
git log -1 --format=%h          # 应为 77057a819 或其后代
grep -n "^## BUG-" docs/BUG_HISTORY.md | tail -3   # 核对最大号
# 开工基线:前端测试文件数与测试数(写进 PROGRESS)
ls frontend/tests/*.test.ts frontend/tests/*.test.tsx | wc -l
grep -rn "EvidenceAuditPanel\|ClaimBoundaryBadge\|BirthTimeSoftNotice\|RawAppendixDownload\|think-step-gate\|document-view\|rectification-agentic/core/index" frontend/tests tests

10. 交付物

  • 分支 codex/frontend-dead-code-20261013;docs/tasks/PROGRESS-frontend-dead-code-20261013.md;docs/BUG_HISTORY.md 新号 + BUG-1004/953 追记;BLOCKED.md 划线;CHANGELOG.md 一行;frontend/DESIGN.md 一行修正(不是 UI 改动)。

11. 后续阶段(本单不做)

  1. drizzle-orm 依赖:lib/db/client.ts 删除后仓内零引用,但 @better-auth/drizzle-adapter 在 lock 里有 peer 关系,移除前需单独核实,另立单。
  2. 疑似无前端调用方的路由(写作时字面量检索无命中,未核实是否被 Agent 工具/后台/运维使用):/api/reports/[reportId]/professional-reference、/api/rectification/cases/[caseId]/{close,tie-break,upgrade-skill,adopt-skill}、/api/locations/search。另立单逐个核实后再删。
  3. 全站 app/api/**/route.ts 鉴权盘点(本单只删一个未鉴权入口;chart-view、birth-sky 在 service 内部鉴权,未在本单复核)。
  4. legacy-guided-v1 旧协议退役(需存量数据迁移决策)。