From 24a9a635791f328927b076c8aae7ce803d95bc92 Mon Sep 17 00:00:00 2001 From: Jesse_Chen Date: Sun, 27 Sep 2026 22:27:21 +0800 Subject: [PATCH] =?UTF-8?q?docs(tasks):=20cost=20brief=20E0/T1.0=20?= =?UTF-8?q?=E2=80=94=20admin=20model=20form=20has=20no=20price=20fields=20?= =?UTF-8?q?(BUG-1069=20reserved)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_0199rbQDTsUbCVw84wc8BTFe --- docs/tasks/README.md | 2 +- docs/tasks/TASK-cost-accounting-gaps-20260927.md | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/tasks/README.md b/docs/tasks/README.md index 54353df4..7f8edd04 100644 --- a/docs/tasks/README.md +++ b/docs/tasks/README.md @@ -243,7 +243,7 @@ | — | `PROGRESS-react-compiler-20260817.md` | React Compiler 接管首页 | 已回滚 | 结论见 `BLOCKED.md` | | `TASK-engine-runtime-hygiene-20260901.md` | `PROGRESS-engine-runtime-hygiene-20260901.md` | Python 引擎运行时治理 | 已验收 | `124d3990`(staging 实机三条待部署窗口) | | `TASK-billing-pricing-20260830.md` | `PROGRESS-billing-pricing-20260830.md` | 计费闭环与功能级定价 | 已合入 | `aaaa5fb7`~`a499c344` | -| `TASK-cost-accounting-gaps-20260927.md` | — | **成本记账补漏与缓存分价**:七处模型调用不入账(标题 / 摘要 / 校正意图 / 采用旁白 / 校正开场 / 生时引导 / 每日星语);缓存命中按全价算、单价表无缓存列;多事件账本 `metadata.cache` 被覆盖;失败运行无成本记录;测算页不显示 token 分位数。只加「记」不加「扣」,不动售价与会员参数 | 待领取 | BUG-1064~1068 预留;部署后由产品按 `docs/testing/cost-accounting-20260927.md` 采真实成本 | +| `TASK-cost-accounting-gaps-20260927.md` | — | **成本记账补漏与缓存分价**:七处模型调用不入账(标题 / 摘要 / 校正意图 / 采用旁白 / 校正开场 / 生时引导 / 每日星语);缓存命中按全价算、单价表无缓存列;多事件账本 `metadata.cache` 被覆盖;失败运行无成本记录;测算页不显示 token 分位数;**后台模型表单没有单价输入框,单价只能是 0**。只加「记」不加「扣」,不动售价与会员参数 | 待领取 | BUG-1064~1069 预留;部署后由产品按 `docs/testing/cost-accounting-20260927.md` 采真实成本 | | `TASK-cend-ui-claude-alignment-20260916.md` | `PROGRESS-cend-ui-r1/r2/r3-20260916.md` | **C 端界面向 claude.ai 产品界面对齐(三轮串行 R1→R2→R3,都动 `globals.css`,不得并行)**:根因是 `frontend/CLAUDE_DESIGN.md` 扒的是 **claude.com 营销官网**,它自己在 Known Gaps 里写明 claude.ai 产品界面不在范围内,而 `DESIGN.md:3` 把它当成了产品界面的实现契约。**R1**:`--font-display` 里 Tiempos Headline / StyreneB **从未加载**(无 `@font-face`、`public/` 无字体、`layout.tsx` 只 vendor 了 Inter),中文标题全站落到 **宋体 / SimSun**,波及 20 处含助手回答的 h2/h3(BUG-737);亮色强调色 `#85432f` 与暗色 `#d78064` 不同源,产品拍板亮色换 **Claude coral `#cc785c`**,**易漏点**是 `globals.css:16` 的 `--color-ring` 硬编码在 `@theme inline` 里不跟随 `:root`,另有第四个 `:root` 亮色块(`:4358`)必须同步(BUG-738);`.composer-footer` 常驻 44px + 顶栏 68px + `--composer-reserve` 148px,每屏固定吃掉 216px,模型选择器移进输入框内部、删掉底栏、顶栏收到 46px 并删「分析对象」副标题。**R2**:空状态是营销落地页(hero 卡 + 两张 132px 入口大卡 + 3 列 156px 主题卡),输入框被压在 **800px 以上**内容之下,重排成「问候 + 居中输入框 + 两枚入口 pill + 一排 chip」。**R3**:侧栏两个 `
` 拍平成一条「最近」、星盘的两个入口(侧栏分组 + 账户菜单)收敛到一处、删掉逐条助手头像。**决策记录 D3 推翻 DESIGN.md「报告强调色与应用同源」一句**(报告刻意保留深棕)。原型图 https://claude.ai/code/artifact/da275da6-2954-4f50-99aa-32bb8694d38b(三套画面 + 明暗,页面标题就是建议字体栈的实际渲染)。环境缺口:无登录态无 Chrome,四项真机观感留 `docs/testing/`。BUG 段 737–738 | 待领取 | — | | `TASK-cend-surfaces-claude-alignment-20260916.md` | `PROGRESS-cend-shell-20260916.md`、`PROGRESS-cend-report-20260916.md`、`PROGRESS-cend-rectification-20260916.md`、`PROGRESS-cend-chart-eph-20260916.md` | **次级页面对齐(上一单的续篇,R4→R5/R6,R7、R8 可并行)**:星盘 `/chart`、星历 `/ephemeris`、报告 `/reports` **各是脱离 app 外壳的独立全屏页**,顶部只有一个「返回对话」链接、侧栏整个消失,且三家各写了一套一模一样的 `*-shell`/`*-topbar`/`*-hero` 骨架——与上一单 E5 同根因(营销站 band 结构被套到产品界面)。**R4** 抽只读导航外壳 `AppNavRail`(只用现成的 `GET /api/sessions` + `GET /api/account`,会话行走 `sessionHref` 跳 `/?c=`;**刻意不带**重命名/删除/收藏/归档——那套连着 `Home()` 的乐观更新与回滚,搬过来会撞 useState 增长门禁)。**R5** 星盘五 tab 下划线化 + 参数合表 + 行星表横向滚动;星历日期导航改 `‹ 日期 ›`。**R6** 报告中心卡片网格改行式列表;阅读页加常驻目录。**R7** 生时校正把可信区间从盘面板标题行提成常驻条(窄屏 `.is-compact` 下盘面板是 overlay,现在默认看不到区间),五个 `technique-audit` 折叠块收成两段。**R8** 设置内容区收窄(880px 弹窗里表单铺了 690px)、套餐卡三修饰符收敛成两态。**已解锁**:原挡路的设置单已于 `111b4a84`(BUG-698)合入。**两条不得回退**:BUG-698 的 `@supports (height: 1dvh)` 写法(重复声明回退会被 Lightning CSS 折叠)、BUG-616/617 的报告盘面 grid 实现。默认不占 BUG 号 | **R4–R8 全部已实现并验收合入** | R4:抽出 `AppNavRail`(只读,两个 GET,零写操作)+ `SecondaryShell`,三个次级页并入 app 外壳并删掉各自的 shell/topbar/hero;四个路由渲染标记**完全不变**(`/` `/chart` `/ephemeris` 仍 Static);CSS gzip −0.25%。`/reports/[reportId]` 留给 R6 与目录一起做。两处自身健壮性问题被测试抓到:`usePathname()` 可为 null、`fetch` 可能不存在。差点弄丢 BUG-717 的 eyebrow 文案(已放回)。R8:表单分区收窄到 440px(列表分区不变)、套餐卡三修饰符收敛成互斥的 `is-current` / `is-recommended`,`--highlighted` 删除改为滚动定位;手机端 `order:-1` 改挂 `[data-plan-alias]`(版位不是状态)。测试 3350→3354(净增 4),失败清单与基线逐条一致;`/` 仍 Static;我的干净构建实测 CSS gzip −3 字节。**遗留待产品拍板**:`?plan=` 深链现在完全没有视觉指向,只有滚动位置。R6:报告中心卡片网格改行式列表、阅读页并入外壳并把目录挪到右侧常驻。**任务书 E10 过期**——目录在 `cfcd369d` 就已存在,本轮是挪位置定稿而非从零加。挂外壳带出一个真实打印风险已处理:`.chat-app`/`.chat-panel` 是 `height:100%;overflow:hidden`,裸 `window.print()` 会把九节报告裁成一页,阅读页因此多挂一条只在挂载期生效的 print 样式解锁外壳。「生成中的分节进度」做不了——`REPORT_LIST_COLUMNS` 不返回节数,按 VOICE.md 不许前端编。R7:区间常驻条与盘面折叠收敛。**任务书 E9 也不准确**——对话区顶部早有常驻条 `RectificationTimeline` 且窄屏可见,真正只在盘面标题行的是**代表分钟**;因此没另造第二条,在既有条上补齐代表分钟与已答题数(与盘面同一次 `workingRectificationTime()` 调用)。折叠块实际是 **8 个**不是 5 个。**触发让步顺序第 5 条**:收窄进度未做——服务端无该字段,且 `candidate_range` 会放宽(BUG-572),前端相减会把一次放宽报成收窄,已写进 `BLOCKED.md`。顺带修掉一个**静默失效的旧断言**(`slice(indexOf(A), indexOf(B))` 在 B 改名后变成几乎整份文件,四条 `doesNotMatch` 假通过)| | — (产品口头拍板,无任务书) | `PROGRESS-chart-glyphs-20260918.md` | **星盘改用行星符号,度数进行星表(非 Bug,无 BUG 号)**:北印星盘(星盘页 / 校正右栏 / 我的报告三处共用 `VedicChartSvg`)宫内不再画「水 19°」「罗逆 29°」这类文本——一宫三颗星就叠三行、字号压到 8。改成九个彩色符号(☉☽☿♀♂♃♄☊☋),每行最多 3 个、逆行改符号下同色横线、第 1 宫加 `As`、盘下两行图例。颜色只认星不表吉凶,罗计共用中性灰,`--color-planet-*` 九个 token 在 `:root` 与两个深色块各一份;颜色挂 `is-*` 修饰类而非行内 `style`(报告标记合同禁 `style=`)。符号字体是 vendored 的 9 字形 Noto Sans Symbols 子集(OFL,1.5 KB),`--font-planet-glyphs`,♀♂ 带 U+FE0E 防 iOS 画成表情。星盘页行星表四列扩到八列(行星 / 黄道经度 / 速度 / 宫位 / 星宿 / 宿主 / pada / 状态),度数精确到分,首行是上升(`vedic.ascendant` 新字段)。数据来源:`toNorthIndianChart()` 加结构化 `occupantGlyphs`;校正与报告两条路线的模型只有引擎/golden 显示文本,按首字解析并有测试锁住。**星宿未译中文**——仓库无对照表,印度 27 宿与中国二十八宿不同源,不自造 | 已实现,待验收 | `codex/chart-glyphs-20260918`:tsc 0 / lint 0 error(118 warning 不变)/ npm test 3471→3484 条、36 红与基线 `84b293fb` 逐条相同、0 新红 / `○ /` Static / 首屏 JS gzip 1,450,774→1,455,017(+0.29%),CSS gzip +2.23%(构成见 PROGRESS §2)。真机走查欠(iOS 符号呈现、深浅两主题配色、375px 横滚、打印) | diff --git a/docs/tasks/TASK-cost-accounting-gaps-20260927.md b/docs/tasks/TASK-cost-accounting-gaps-20260927.md index 655042bd..90123441 100644 --- a/docs/tasks/TASK-cost-accounting-gaps-20260927.md +++ b/docs/tasks/TASK-cost-accounting-gaps-20260927.md @@ -9,11 +9,15 @@ 产品负责人 2026-09-27 提问「项目怎么做成本计算 / 后台有没有 token 统计 / 缓存开了没有」。按代码逐条核对后的结论: 1. **骨架完整**:`usage_reservations → usage_events → usage_ledger` 三表;`authorize_usage / complete_usage / release_usage` 三个 SQL 函数;`feature_pricing` 按功能定价;后台 `/admin/usage`(每行有 Token、缓存读 tokens、成本列)、`/admin/usage/aggregate`(按功能 30 天 runs / avg / p50 / p95 / max)、`/admin/pricing-simulator`(售价 vs 成本 vs 毛利率 + 缓存命中表)、`/admin/models`(输入 / 输出单价)。 -2. **算出来是 0**:`model_config_versions.input_cost_microusd_per_million / output_cost_microusd_per_million` 默认 0,staging 从未填过;账本里没有一条非零真实成本行。这是运营输入,不是代码问题,产品负责人自己在后台填。 +2. **算出来是 0**:`model_config_versions.input_cost_microusd_per_million / output_cost_microusd_per_million` 默认 0,staging 从未填过;账本里没有一条非零真实成本行。**而且后台没有地方填**:`components/admin/model-management.tsx` 的模型草稿弹窗只有「供应商 / 模型 / 单次点数 / 启用 / 默认模型」五个字段,`saveDraft` 请求体里的 `inputCostMicrousdPerMillion / outputCostMicrousdPerMillion / modelTier / contextWindow` 全部原样回填旧值(新建时为 0 / standard / null)。列表页「成本/百万 Token」一列永远显示 `$0.0000 / $0.0000`。API(`api/admin/models/route.ts` 的 zod schema)是收这几个字段的,缺的只是表单。见 E0。 3. **即使填了单价,账本也系统性低估**,原因就是下面「事故实证」的五条。这才是本单要修的。 ## 事故实证(按符号定位,已逐条读代码确认) +### E0 · 模型单价在后台无处可填 + +`model-management.tsx` → 模型弹窗(`title` 为「新增模型草稿」/「编辑 」)内 `Form.Item` 的 `name` 只有 `providerId / providerModel / creditCost / enabled / isDefault`。`modelTier`(影响 `feature_pricing` 匹配哪一档)、`contextWindow`、两个单价都不可编辑。产品负责人 2026-09-27 在 staging 后台实际打开过测算页,「单位成本」列全部是「无实测数据 / 模型估算 0」,根源之一就是这里。 + ### E1 · 七处模型调用不进账本 | # | 调用点 | 符号 | 现状 | @@ -109,6 +113,7 @@ git worktree add -b codex/cost-accounting-gaps-20260927 \ ### T1(P0)· 缓存分价 + 成本公式收敛 +0. **先把表单补上**(E0,独立可交付,建议第一个 commit):模型草稿弹窗增加「模型档位」(下拉,沿用 `MODEL_TIER_OPTIONS` 标签)、「上下文窗口」、「输入价 $/百万 token」、「输出价 $/百万 token」,以及本任务新增的「缓存读价」「缓存写价」。表单以**美元 / 百万 token** 输入(小数,精度 4 位),提交时乘 1,000,000 取整成微美元;编辑既有版本时回显换算后的值。保存后仍走既有「草稿 → 连接测试 → 发布」流程,不得绕过。列表页「成本/百万 Token」一列加上缓存读价。组件测试断言这六个字段存在且换算正确。 1. migration:`model_config_versions` 新增 `cache_read_cost_microusd_per_million bigint not null default 0 check (>= 0)` 与 `cache_write_cost_microusd_per_million`(同型;DeepSeek 为 0,Anthropic 有写入溢价,留位)。`admin_save_model_config_draft`(或现名)与 `model_catalog.ts` 的读取、`/admin/models` 表单、返回 JSON 一并加字段;旧行默认 0,行为不变。 2. 新建 `computeUsageCostMicrousd(model, usage)`: - `billableInput = inputTokens - cache.readTokens`(下限 0)按输入价; @@ -151,7 +156,7 @@ git worktree add -b codex/cost-accounting-gaps-20260927 \ 1. `pricing-simulator.tsx` 「单功能表」增加列:输入 p50 / 输出 p50 / 缓存读 p50 / 命中率(复用聚合端点已有字段,命中率来自 `metadata.cache`);`source === "unavailable"` 时显示「无实测数据」不显示 0。 2. 表格上方一行说明文字:「成本 = (输入 − 缓存读) × 输入价 + 缓存读 × 缓存价 + 输出 × 输出价;单价在 `/admin/models` 配置;`cache_price_missing` 行表示有命中但未配缓存价」。 -3. 写 `docs/testing/cost-accounting-20260927.md`:产品负责人部署后照做的清单——在 `/admin/models` 填三档单价与汇率 → 用可控账号每类功能跑 ≥5 次(聊天含多领域、校正跑到出卡、报告完整生成、另各触发一次标题 / 摘要 / 开场 / 每日星语)→ 在 `/admin/pricing-simulator` 读表 → 把「功能 → p50 成本 → p95 成本 → 命中率 → 失败成本占比」抄回 PROGRESS。 +3. 写 `docs/testing/cost-accounting-20260927.md`:产品负责人部署后照做的清单——在 `/admin/models` 给当前发布模型新建一版草稿、填三档单价、连接测试、发布(T1.0 之前做不到这一步),在测算页填汇率 → 用可控账号每类功能跑 ≥5 次(聊天含多领域、校正跑到出卡、报告完整生成、另各触发一次标题 / 摘要 / 开场 / 每日星语)→ 在 `/admin/pricing-simulator` 读表 → 把「功能 → p50 成本 → p95 成本 → 命中率 → 失败成本占比」抄回 PROGRESS。 **验收**:`pricing-simulation.test.ts` / 组件测试覆盖新列的空态与有数态;`docs/testing/` 清单存在且每步可照做;`DESIGN.md` 不需要改(后台 antd 页不在 C 端设计合同内),若改了 C 端任何文件必须说明。 @@ -172,6 +177,7 @@ git worktree add -b codex/cost-accounting-gaps-20260927 \ | BUG-1066 | 校正开场轮 agent run 的 token 被 `action !== "message"` 分支丢弃 | E1 #5 / T2.4 | | BUG-1067 | 失败 / 释放运行无成本记录 | E4 / T3 | | BUG-1068 | 多事件账本 `metadata.cache` 被覆盖,命中率失真 | E3 / T4 | +| BUG-1069 | 后台模型草稿表单缺输入 / 输出单价、模型档位、上下文窗口字段,单价只能是 0 | E0 / T1.0 | 每条按 §5 格式写:状态、现象、触发条件、根因、修复、验证、防复发、关联记录(关联 `PROGRESS-billing-pricing-20260830.md` 任务 4 缺口)。**部署前状态写 `resolved(待部署)`**,部署核对后由验收方回填 SHA。