- README.md is now the product/repo front door (architecture, repo map, local dev, test tiers, delivery flow, doc map). Engine positioning, VedAstro/Codex setup and the oracle/benchmark command reference move verbatim to docs/engine/README.md, docs/engine/vedastro-gateway.md and docs/benchmark/README.md. Capability badges realigned with the registry (91/78/8/0); tests/test_readme_badges.py was red on staging. - AGENTS.md: Part A (environment truth, delivery, worktrees, record placement, bug workflow, growth freeze, frontend red lines, privacy, pre-work check, test tiers) and Part B (reading-rigor constraints). GitHub issue-tracker/triage boilerplate removed: GitHub is a read-only mirror. All strings locked by tests/ are preserved. - CLAUDE.md added: roles, three working modes, task-brief sections, acceptance criteria, session discipline; imports AGENTS.md. - 50 tracked TASK-*/PROGRESS-* files and 3 never-committed briefs move to docs/tasks/ with an index; REPO_LAYOUT.md merged into README. Docs-only change (no gated path touched). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P
13 KiB
任务书 · 第二轮:真实成本与交付物(2026-08-31)
基线:origin/staging @ 3a4396a4。
下面所有行号只是线索,请按选择器/函数名定位。
为什么要做
前两份任务书(TASK-billing-pricing-20260830.md、TASK-rectification-convergence-20260830.md)已完成大部分实现。按代码逐条核对后,剩余缺口集中在两类:
A 类 · 卡在缺真实数据,不是实现问题。 计费任务 0 的聚合端点已就绪,但 staging 没有跑出真实单位成本,于是会员参数不敢动、缓存降幅无法验证、定价测算页只能显示估算。上一轮拒绝凭估算改参数是对的,本轮负责把这个输入补上。
B 类 · 交付物本身还是空的。 校正任务 7(逐条回答 → 区间收窄归因表)是 P0,且不依赖任何外部数据,但排在 8/9/10 后面一起没做。用户为一次校正付的钱,买的就是这张表。
还有一个上一轮遗留的阻塞项:上下文缓存目前只对 Anthropic 生效,若生产 provider 不是 Anthropic,则「随便聊」会员档的毛利模型不成立。
已完成,不要重做
计费任务 0/1/2/3/6,校正任务 0/1/2/3/6。核对依据见两份 PROGRESS 末尾的「外部核对(2026-08-31)」。
硬红线
- 任务 0 是门控。 会员参数、售价、公平使用上限的任何调整,必须在任务 0 产出真实单位成本之后。不得凭估算改数——上一轮正确地拒绝了这件事,本轮不得倒退。
- 不得用生产用户数据做压测。 任务 0 的数据采集用真实调用,但必须是可控账号,且不得为了凑数据而批量刷接口造成成本与容量浪费。
- 归因表的收窄贡献必须来自服务端打分,不得由模型叙述生成。 一张看起来专业、实则模型编的归因表比没有更糟。
- 零贡献证据必须显式标注,不得静默丢弃。这是诚实性的一部分。
- 禁止答案回流(沿用上一轮红线 3):任何以已知答案调出来的规则不得进入生产打分链路。
- 上游同步必须过污染审查(沿用上一轮红线 4):不得同步带
pl9_1993、observed_*_case_only、target_minute标记的打分逻辑。 - 诚实性不可让渡:不得放宽
confirmation-gate.ts的 blocker,不得降低 sealed holdout 门槛。 - 不得修改既有测试断言 —— 除非该断言锁的正是本轮要改的缺陷本身;那种情况必须在断言上方注明原值与原因,并在 PROGRESS 单列。
- 推 staging 前必须
./node_modules/.bin/tsc --noEmit通过。不要用npx tsc,本仓库环境下会装到空包tsc@2.0.4。 - 数据库测试必须真跑。
npm run test:db需要 Docker。没有 Docker 就不要推 —— 写进BLOCKED.md并停下。 - 不得改
.gitea/workflows/**。不得在有未提交改动的工作树上切分支。不得自行把 staging 提升到 main。
让步顺序:诚实性不回退 > 数据不损坏 > 功能与测试不回归 > 可验证的改进 > 成本 > 代码整洁。
开工前置
git fetch origin --prune
git worktree add -b codex/round2-cost-delivery-20260831 \
../.worktrees/round2-cost-delivery-20260831 origin/staging
读 pre_work_error_ledger.md,跑 scripts/pre_work_check.py,读 frontend/AGENTS.md。改前在 docs/BUG_HISTORY.md 检索同类记录。
先读这些:
- 两份 PROGRESS 末尾的「外部核对(2026-08-31)」——本轮范围的依据
frontend/src/app/api/admin/usage/aggregate/route.ts—— 任务 0 的现成入口frontend/src/lib/agent-generation-settings.ts——cachedSystemMessage()的 provider 分支frontend/src/lib/rectification-agentic/v9/evidence-model.ts与core/rectification-decision.ts—— 任务 2 要接归因的地方references/upstream/1993-session-correction-rerun.txt—— 归因表的目标形态就在这份记录里
任务 0(P0,门控)· 在 staging 采到真实单位成本
事实
计费任务 0 已交付聚合端点,但 report.full 从未有过真实行(上一轮才接上计费),chat.standard 与 rectification 也缺分叉后的新数据。没有这批数据,任务 3(会员参数)与任务 1 的降幅验证都无法进行。
要做什么
- 把当前 staging 部署起来,确认
/api/health的 SHA 与origin/staging一致,并在 PROGRESS 记录。 - 用可控账号跑出每类功能的真实调用,每类至少 5 次、覆盖典型与偏长两种形态:
chat.standard:含多领域计算的完整咨询rectification:至少一个跑到证据停止或预算耗尽的完整 casereport.full:至少一份分章节完整生成
- 用聚合端点导出 per-feature 的
runs / p50 / p95 / max的cost_microusd、input_tokens、output_tokens、duration_ms,以及metadata.cache的命中情况。 - 结果写进 PROGRESS,形成一张表:功能 → p50 成本 → p95 成本 → 缓存命中率。
验收
- 三类功能各有不少于 5 条真实
usage_ledger记录。 - PROGRESS 里有上述表格,数值可复核到 request_id(脱敏,只列聚合值)。
- 明确记录当前生产/staging 实际使用的 provider 与 model_id —— 任务 1 依赖这个结论。
停止条件
若 staging 无法部署或无法产生真实调用,写进 BLOCKED.md 并停下。任务 2 不受影响,可并行开工;任务 1、3 必须等本任务。
任务 1(P0,依赖任务 0 的 provider 结论)· 让上下文缓存对生产 provider 真正生效
事实
frontend/src/lib/agent-generation-settings.ts:
/** Adds only Anthropic's message-level cache marker; other providers keep current behavior. */
export function cachedSystemMessage(content: string, model?: unknown) {
if (modelProviderId(model) !== "anthropic") return null;
...
}
用量解析覆盖全 provider,但缓存标记只对 Anthropic 下发。同文件顶部注释与 api/daily-starlanguage/route.ts:105(deepseek-v4-flash)都指向 DeepSeek 系。
会员「随便聊」档的毛利模型完全依赖这项降本,因此这是上线阻塞项。
要做什么
- 按任务 0 确认的生产 provider,查清其上下文缓存契约——以 provider 官方文档为准,不要凭记忆写。要弄清:怎么声明、命中如何计价、最小可缓存长度、前缀稳定性要求。
- 为该 provider 实现缓存声明,保证 system + skill 前缀落在缓存边界内。校正的 system message 内嵌绑定 Skill 全文(
v9/agent-run.ts的bootstrap),是最值得缓存的稳定前缀。 - 不支持缓存的 provider 保持现有行为,返回
null,不报错、不改变请求形状。 - 降幅必须实测:用任务 0 的同一批 case 形态再跑一轮,对比 p50
cost_microusd。没有前后对比就不许在 PROGRESS 声称降本。
验收
- 生产 provider 的请求能在账本
metadata.cache看到非零命中。 - 对话与校正的 p50
cost_microusd相对任务 0 基线有可测量下降,降幅写进 PROGRESS。 - 非目标 provider 行为不变,既有测试全绿。
任务 2(P0,无依赖,可立即开工)· 逐条回答 → 区间收窄归因表
这是
TASK-rectification-convergence-20260830.md的任务 7,原文保留有效,本节为可独立执行的展开。
事实
references/upstream/1993-session-correction-rerun.txt 里,整场真实会话最有价值的产物是用户主动索要的那张表:
| 你的回答 | 压缩后的分钟区间 | 作用 |
|---|---|---|
| 2017 入职,岗位内容不合 | 14:48–14:50 | 很强的收窄点 |
| 2023 末起量,一改风格就稳 | 14:48–14:50 | 最接近最终分钟的一条 |
本仓没有这个概念:v9/evidence-model.ts 与 core/*.ts 中不存在 narrow / contribution / attribution 语义,只有「这条证据支持哪个候选」,没有「这条回答把区间从 X 压到了 Y」。
同一份记录也证明了产品价值的真实边界:用户的 8 条生平锚点把窗口从 30 分钟压到 3 分钟,收窄是真的。归因表就是把这件事变得可见。
要做什么
- 每次证据写入后记录区间快照:写入前宽度、写入后宽度、该条证据的归属贡献。持久化,不靠事后重算(重算会因候选集变化而不可复现)。沿用既有 receipt / SQL 函数模式,状态留在 Postgres。
- 报告(校正任务 3 的产物)新增归因表:用户原话(走
display_date_label口径)→ 收窄前后区间 → 一句作用说明。 - 收窄贡献由服务端打分产出,模型只做措辞(红线 3)。
- 无贡献的证据也要列出并标注「未产生收窄」(红线 4)。
- 归因表要能回答用户那句真实提问:「这个结论有多少来自我的回答?」 ——若最终区间主要由声明窗口或先验决定,必须说出来。
验收
- 报告含归因表,条目数等于已确认证据数。
- 每条的收窄前后宽度与该轮实际候选集一致,可复核。
- 零贡献证据被显式标注,不被静默丢弃。
- 归因数据来自持久化快照,重开页面结果一致。
任务 3(P1,依赖任务 0 与任务 1)· 会员参数与售价重设
这是
TASK-billing-pricing-20260830.md的任务 5,上一轮正确地保留未改,本轮在有数据后执行。
事实
product_entitlements 的公平使用参数仍为种子值(20260806020000_billing_products_subscriptions.sql:146-155):月卡 billingLimit 2000、年卡 24000、Pro 月卡 5000、Pro 年卡 60000。上一轮已完成语义澄清与文案约束,只差参数本身。
要做什么
- 用任务 0 / 任务 1 的实测 p50、p95 成本重设
minuteLimit/dayLimit/billingLimit。按 p95 定,不按均值——公平使用要挡的是尾部。 billingLimit的定位是熔断,不是对用户承诺的配额;「随便聊」靠minuteLimit+dayLimit保护真人容量。语义已在上一轮写入 admin 文案,本轮只改数。- 按产品已定规则,移除 standard 月卡/年卡的
rectification与report.full权益(改为单独计费)。移除前必须核查存量订阅依赖,有在期会员依赖这些配额时给出兼容处理,不得让权益凭空消失。 - 售价(
billing_products.price_cents)改动需产品确认后再执行,本任务只准备迁移,不擅自调价。 - 全部走幂等迁移或既有
admin_save_product_draft审计路径,不得手改生产库。
验收
- 迁移幂等,
npm run db:migrate:check在隔离 Docker PostgreSQL 里 apply / check / reapply 三次退出码均为 0。 - 新参数下,按 p95 成本估算的会员毛利写进 PROGRESS。
- 存量订阅的兼容路径有明确记录。
- 定价测算页读到新参数后,输出表与 PROGRESS 的数字一致。
任务 4(P1)· 「为什么是这个结论」的质疑通道
TASK-rectification-convergence-20260830.md的任务 8,原文有效。
真实会话里用户问「你是信息记忆联想了吗?还是靠印度占星专业技术推理出来的?」——这一问是全部真相的来源。本仓没有任何「为什么」入口(v9/choice-card.ts 的 why 是每个选项的说明,不是结论来源)。
内容全部来自服务端已有的 claimCards / evidenceRefs / confirmation-gate blocker,不得由模型即兴生成。与任务 2 的归因表共用同一份服务端数据,不要建第二套。
任务 5(P1)· 中途改窗口与保留证据重跑
TASK-rectification-convergence-20260830.md的任务 9,原文有效。
要点重申:同一 case 内重跑不重复扣费(沿用 rectification:case:<caseId> 幂等键);重跑必须留痕;新窗口与既有证据冲突时如实呈现,不得静默丢弃。
任务 6(P1)· 首轮批量出题
TASK-rectification-convergence-20260830.md的任务 10,原文有效。
src/mastra/agentic-rectification.ts 中「一次一问」仍在。上游手册的节奏是第 1 轮 3–5 道 A/B/C/D 一起出。批量轮在轮次预算里记为一轮。
建议执行顺序
- 任务 2 —— 无依赖,交付物核心,立即开工
- 任务 0 —— 与任务 2 并行,它是任务 1、3 的输入
- 任务 1 —— 拿到 provider 结论后立即做,它是「随便聊」上线的阻塞项
- 任务 3 —— 有成本数据后执行
- 任务 4 / 5 / 6 —— 依次
交付
- PROGRESS 写进
PROGRESS-round2-cost-delivery-20260831.md,任务 0 的成本表与任务 1 的降幅对比单列。 - 每个任务一个提交。
- 推 staging 前:
./node_modules/.bin/tsc --noEmit通过、npm run lint无新增 error、npm run test:db在 Docker 下 fail=0、npm run build通过。 - 全量
./node_modules/.bin/tsx --test tests/*.test.ts的失败清单与基线逐条比对,确认无新增。