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
21 KiB
21 KiB
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/staging77057a819 - 判定口径:从 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-20260924D2 已授权「/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. 硬红线
- 只删不改:除下面列明的测试改写、DESIGN.md 一行、BLOCKED.md 划线、BUG_HISTORY/PROGRESS 外,不改任何生产文件的逻辑。删一个文件导致的编译错误只能通过「继续删死代码」或「删 import」解决,不得改业务代码去迁就。
- 否定合同必须保留:
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)。删组件后,这些测试里读被删文件源码的行删掉,否定断言原样保留。 ordinaryReportDownloadMarkdown与其 4 个测试不动;report-export-blocks.test.ts的冻结 sha256 不动。- 改既有断言按 §7.3 写「原值 / 新值 / 原因」三栏注释;整条测试删除的,写进 PROGRESS「删除测试清单」。
- 不改数据库结构与迁移(RPC
accept_agentic_rectification_candidate*等保留,只删 TS 调用方);frontend/src/app/(app)/page.tsx不增长;scripts/jyotish_api_server.py不增长(本单不碰);不改.gitea/workflows/**;不升级、不删除依赖(drizzle-orm、@mastra/*都不动)。 - 不碰
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 --noEmit0 错;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.pySAFE_LINES删frontend/tests/agent-evals.test.ts一项(文件已删;参数化用例少 1 条,PROGRESS 列名)。
- 验收:再跑 §1 脚本,输出只剩
personal-report-longform-download.ts;tsc --noEmit0 错;npm run lint0 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 删除」一行。
- 新增本单 BUG(标题建议:「未登录即可调用
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.css497–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. 后续阶段(本单不做)
drizzle-orm依赖:lib/db/client.ts删除后仓内零引用,但@better-auth/drizzle-adapter在 lock 里有 peer 关系,移除前需单独核实,另立单。- 疑似无前端调用方的路由(写作时字面量检索无命中,未核实是否被 Agent 工具/后台/运维使用):
/api/reports/[reportId]/professional-reference、/api/rectification/cases/[caseId]/{close,tie-break,upgrade-skill,adopt-skill}、/api/locations/search。另立单逐个核实后再删。 - 全站
app/api/**/route.ts鉴权盘点(本单只删一个未鉴权入口;chart-view、birth-sky在 service 内部鉴权,未在本单复核)。 legacy-guided-v1旧协议退役(需存量数据迁移决策)。