# Scale Router PRD 日期:2026-09-28 版本:v1.0 状态:PRD v1.0 定稿;产品评审 GO、技术定向复审 GO,进入 Phase 2;设计确认后进入开发。文档定稿不代表代码测试或整周效果验收通过。 设备:Mac mini,本地普通用户执行。技术标识:`scale-router`,Python 包标识:`scale_router`。 依据:方向研究 v0.4(本地记录,未公开)、真实实验结果 v0.1(本地记录,未公开)、运行时契约(本地记录,未公开)、产品评审 GO(本地记录,未公开)、技术审查(第二轮 GO)(本地记录,未公开)。历史实验只证明有限接入可行,不是本产品通过验收。 ## 1. 产品与完成定义 Scale Router 是 Codex 中的任务分派 Skill,附带按需启动的 Python runner 和本地账本。用户描述要完成的代码工作,Scale 形成可验收任务,在独立候选副本中调用 worker,独立验证结果;失败时先诊断,最多修复一次、升级一次,最终交回可集成补丁和完整收据。 首版解决明确范围的本地代码修改、测试和可重复验证的工程维护。它必须交付真实项目改动,不能把选出模型、API 连通或生成任务分类当作完成。 用户的最终目标保持不变:同等真实周工作量和验收要求下,质量、交付效率与人工负担不劣于正常全程 Astra Ultra 工作方式,原有 Codex 订阅撑住整周,OpenAI 付费 API 调用为零。首版可用与该目标成立是两项独立结论。只有完成第 13 节的证据要求,才能宣称整周目标已验证。 ### 1.1 首版必须交付 1. 可安装、可显式调用的 Codex Skill;清楚说明如何查看进度、暂停、取回补丁和继续工作。 2. 严格校验任务包,冻结基准与验收,在隔离副本真实编辑、测试;默认规则分派 DeepSeek Flash,必要时使用官方 Codex 订阅 worker。 3. 独立验收、失败分类、有限修复及升级;每次调用前重新核验能力、授权范围和预算。 4. SQLite 唯一运行状态源,包含原子预留、幂等、防重复派发、取消、超时、恢复和逐任务收据。 5. 对目标工作树进行相关路径漂移检查、补丁预检、集成及集成后验收,保留既有未提交工作;不自动提交、推送或发布。 6. 离线故障测试和至少一个真实端到端项目修改;可用性结论与尚未验证的节省效果分别展示。 ### 1.2 可后置 常驻服务、跨设备队列、定时启动、公网执行 API、Web 控制台、自动部署、任意连接器透传、开放式商业决策、自动合并冲突、Jev 主路由和任务级精确订阅计费。官网和 PRD 在线页按项目流程建设,但不参与私人任务执行,也不接收账本、代码或密钥。 ## 2. 用户入口与可见体验 日常入口仍是 Codex。显式说“用 Scale 完成这个修改”是首版可验证入口;Skill 自动把自然语言整理为 task-card,用户不必手写 JSON。Skill 的隐式触发只能作为便捷能力,不能保证每个聊天或每条输入必经。安装 Skill 不会把用户其他聊天的调用纳入 runner 控制。 建议用户把较轻且已验证可用的订阅配置设为日常入口,复杂任务再升级。Scale 不修改全局默认模型;如果入口仍是 Astra Ultra,读取输入、分派和汇总产生的 Astra 消耗仍然存在,不能算作节省。 | 时刻 | 用户看到的内容 | 程序必须完成的检查 | |---|---|---| | 接到目标 | 一句话说明范围、验收、初始模型、最多尝试数 | 缺验收或必要材料时不启动 worker;可独立完成的部分继续 | | 派发前 | 任务 ID、候选模型、预算与超时、是否会使用订阅 | 仓库、基准、权限、沙箱、能力、预算、幂等、取消标志 | | 执行中 | 编辑、验收、修复、升级等阶段变化 | 阶段日志带 task/attempt;无变化时不高频调用模型汇报 | | 完成 | 通过项、补丁摘要、测试证据、费用、订阅观测、集成状态 | 程序独立验收;仅 worker 自述完成不能通过 | | 阻塞 | 明确原因、已保留成果、恢复所需最小动作 | 不静默扩大权限、换付费 OpenAI API或抬预算 | 很小且没有合理分派收益的任务由主聊天直接完成,说明没有经过 Scale 执行账本。不能制造空任务或额外 worker 以提高分派数量。 ## 3. 核心流程与授权范围 1. Skill 从用户目标形成任务包;记录目标仓库、已授权修改范围、明确验收与优先级。同一原始工作项持久化 `work_item_id`;拆分任务记录 `parent_task_id`,重做/重新基线记录 `supersedes_task_id`。每项必须有独立验收;首版串行执行,不递归分派。 2. runner 校验协议、冻结任务包与基准及已有测试的基线结果,建立预算预留和持久任务 ID。基线失败如实记录,不能因此削弱最终验收。相同幂等键与相同包只对应同一任务;同键不同内容报冲突。 3. 冻结基准 commit 及当前工作树的受控快照,在独立候选副本运行 worker。快照包含任务所需的已跟踪文件当前内容、删除状态与明确选入的未跟踪文件,记录 manifest/hash;已有未提交修改属于输入基准。排除 `.git`、凭据、缓存与生成产物,不能靠删除或提交用户改动来准备任务。 4. worker 只得到最小上下文、公开验收要求、可修改范围与工具能力。隐藏验收代码及其他任务答案不进入它的可读范围。 5. worker 结束后先检查修改范围、文件类型及冻结文件完整性,再运行已冻结的验收方案。验收进程不携带模型凭据;普通工程模式要求回归证据与独立补丁 review,强行为模式由可信父 validator 产生断言结果,不把候选 stdout 当通过证明。 6. 验收失败产生失败记录。基础设施故障走有界重试;行为不符合且证据可定位时允许一次修复;再次失败才根据配置考虑一次升级。不是每次失败都推断模型能力不足。 7. 验收通过产生补丁、摘要和收据,状态为 `validated`,此时尚未写入用户目标工作树。 8. `integrate` 是明确的代码命令与校验边界。在已授权范围内检查相关路径仍与输入快照一致,持久化写入 journal 后应用相对于快照的增量补丁,再在受限只读环境或目标状态快照中验收,成功为 `integrated`。Skill 可在原任务已授权代码修改且验收通过时自动调用,不要求用户重复确认。无关未提交修改原样保留;相关路径漂移或无法安全合并时返回冲突与补丁,不覆盖、不强制清理工作树。 首版 worker 不允许支付、发消息、发布、部署、改账号、管理密钥或执行生产数据库写入。任务要求此类动作时回到父聊天已有授权流程,不由模型判断自动越界。源任务文本、仓库文件和模型输出均不能修改执行白名单、预算或验收标准。 ## 4. CLI 与内部 API 公开入口为 `python -m scale_router`;所有命令支持 `--json`,机器结果使用 UTF-8 JSON,日志写 stderr。默认不监听网络端口。安装后的便捷命令可以为 `scale-router`,但必须调用同一实现。 | 命令 | 输入与行为 | 输出 | |---|---|---| | `doctor` | 检查 Python、Codex 路径/版本、订阅认证类型、模型目录、沙箱、账本和凭据是否可用 | 每项 `ok/blocked/unknown`;从不输出密钥或 token | | `init-task --repo PATH --output FILE` | 生成待填写任务模板,不调用模型、不启动执行 | 模板路径及缺失字段 | | `run --task FILE` | 校验、幂等创建并同步执行到终态/阻塞;不自动集成 | 任务 ID、状态、补丁与收据路径 | | `status [TASK_ID]` | 查看单任务或最近任务;只读本地状态 | 状态、当前阶段、已用预算、阻塞原因 | | `receipt TASK_ID` | 导出稳定收据;运行中返回明确的暂定值 | 第 10 节收据对象 | | `cancel TASK_ID` | 持久化取消请求并清理 worker 同 PGID 残留,即使 leader 已退出;重复调用安全 | 取消已确认或仍待进程确认,不能提前宣告已取消 | | `resume TASK_ID [--review FILE]` | 对账、验证候选及验收哈希;可导入独立 review 记录;重新经过必要预算门,从安全检查点继续 | 恢复结果或明确阻塞;不盲目重复未知动作 | | `integrate TASK_ID` | 仅允许 validated;相关路径快照守卫通过后应用增量补丁、重验,保留无关脏改动 | 集成后的证据;失败保留补丁 | 稳定退出码:`0` 操作成功;`2` 协议/参数无效;`3` 被能力、权限或预算阻塞;`4` 验收/执行失败;`5` 已取消;`6` 超时;`7` 内部错误。`status` 和 `receipt` 成功读取失败任务仍返回 `0`,任务状态在 JSON 内表达。 JSON 响应包含 `schema_version/task_id/status/code/message/artifacts`,可空字段用 `null`,不能把未知消费写为 0。内部适配器至少提供 `probe()`、`execute(attempt)`、`cancel(handle)`;配额适配器提供 `read_usage()`,验收器提供 `validate(candidate, frozen_acceptance)`。控制策略和状态转换由 Python 实现,模型只返回候选产物与说明。 ## 5. 任务协议 v1 下面是协议示例。Skill 从用户自然语言生成,无须用户手写。现金/超时参数可继承安装配置;任务只在需要收紧时覆盖。 ```json { "schema_version": 1, "work_item_id": "csv-export-2026-09-28", "idempotency_key": "csv-export-2026-09-28-01", "title": "修复 CSV 导出特殊字符", "goal": "正确输出逗号、引号、换行、空值和 Unicode,并保持列顺序", "requirements": [{"id": "csv-escaping", "criterion": "特殊字符可被标准 CSV 解析器还原,空值为空字段且列顺序不变"}], "repo": "{REPOSITORY}", "base_ref": "HEAD", "allowed_paths": ["src/export.py"], "context_paths": ["README.md", "src/export.py"], "validation_profile": "engineering", "acceptance": [{"id": "csv-contract", "covers": ["csv-escaping"], "argv": ["python3", "-m", "unittest", "discover", "-s", "tests"], "timeout_seconds": 60, "evidence_kind": "regression", "evidence_format": "unittest", "min_checks": 7}], "protected_paths": ["tests"], "priority": "normal", "route": "auto", "allow_subscription": true, "allow_escalation": true, "budget": {"currency": "CNY", "cash_limit": "5.00"}, "limits": {"max_attempts": 3, "max_total_seconds": 900, "attempt_timeout_seconds": 300}, "constraints": ["不得修改公开测试或添加依赖"] } ``` 必填为版本、原始工作项 ID、幂等键、标题、目标及可检查的 requirements、绝对仓库路径、基准、修改范围和至少一个验收条件;预算/限额省略时继承安装配置并把解析后的有效值冻结进任务。每个 requirement 必须映射到 acceptance 的 `covers`,不得只拿不相关的旧测试充数。`parent_task_id/supersedes_task_id` 可选,必须指向同一工作项已有任务。`base_ref` 提交时解析成不可变 commit,并冻结当前工作树 overlay 与 manifest;后续恢复不能重新解释 HEAD 或重新读取输入覆盖原快照。`context_paths` 默认最小集合;`priority` 为 `low/normal/high`;`route` 为 `auto/deepseek/subscription`,指定模型只能来自本机配置白名单。 路径必须位于仓库内,禁止 `..` 越界、绝对修改路径、外部软链接、设备文件和与受保护路径重叠的修改。默认不允许二进制文件、子模块、依赖安装、任意网络或大文件任务;需要支持时扩展能力契约并补测试,不能用 prompt 临时开启。 验收命令为调用者提供的 argv 数组,不使用 `shell=True`,不执行模型生成的新验收命令。公开测试可以存在候选内但必须冻结并保护;隐藏验收必须放在 worker 不可读位置。worker 可在授权路径新增测试,新增测试不能单独构成独立验收。基线命令、测试器及其依赖清单均冻结,修改它们进入 `acceptance_invalid` 阻塞复核;不能通过改 test config、跳过发现路径或替换断言依赖获得通过。没有自动验收的任务首版不自动标记成功。 `validation_profile` 分为 `engineering`(默认)与 `strong_behavior`,收据必须保留证据强度,不得混称安全保证: - **engineering:** 面向可信本地工程的通用代码任务,可运行既有 unittest、构建、CLI 集成或其他冻结项目验收。回归输出至少解析检查数量,满足 `check_count >= min_checks >= 1`、无失败;零测试、缺输出或仅 exit 0 均不通过。此模式还必须有独立角色对实际 diff、目标覆盖和验收证据做 patch review。review 记录绑定 task/attempt、candidate hash、acceptance hash、reviewer role、逐 requirement 结论和 `GO/NO_GO`,由可信控制端导入;worker 不能写入该记录。记录缺失为 `blocked:independent_review_required`,输入可经 `resume --review FILE` 补齐。模型评审仍可能犯错,因此这一组合是工程质量证据,不宣称可抵抗任意恶意候选、stdout 伪造或测试框架 monkeypatch。 - **strong_behavior:** 至少一项覆盖目标行为的 trusted 父 validator 持有期望值、断言和检查计数。候选运行在隔离子进程,通过限定的参数/标准输入/文件/CLI 结果接口交回待验证数据;父 validator 自行比较数据并产生最终结果,绝不导入候选模块或把候选的 pass/计数当结果。提前退出、缺响应、额外响应、超时、格式不符均失败。父进程不执行候选返回的代码,结果记录通道对候选不可写;`structured_json` 只有来自此可信通道时才是强结果,候选 stdout 永远只是输入。该接口可验证真实多模块程序的 CSV/JSON/文件产物及 CLI 行为,不局限于单函数题目。 非测试类 lint/build 使用冻结完成标记/rubric,不能伪报测试数量。未要求强模式的常规工程任务可按 engineering 完成交付,不因无法把全部内部测试迁入父 validator 而永久阻塞;遇到不可信任意代码或用户明确要求强保证,则不能降级为 engineering。独立 patch review 由现有 Skill/验证角色承担,若调用模型,其开销同样计入全任务成本。 在 worker 启动前,由上层独立验收角色确认目标覆盖并冻结测试:行为变更必须有能区分基线与目标行为的证据,优先为基线失败而候选通过的断言;无法用此形式表达时保存独立 review 的等价证据。旧套件全绿不能单独证明新需求完成。无补丁且基线已满足所有目标时记录 `no_change_needed` 与已有证据,不调用 integrate,不计作新增代码交付;缺少区分证据则 blocked,而非用模型自述补足。 runner 从任务路径与验收依赖计算 `integration_guard_paths` 并冻结内容/hash/存在性/文件模式。候选增量相对于输入快照生成,不包含原来已有的 dirty diff;集成前逐项核对守卫路径,HEAD 改变但相关路径未变时可以继续,相关路径改变则返回冲突。多文件写入与撤回使用第 6.2 节的持久 journal;不能把 `git apply --check`、进程退出或数据库标记等同于跨文件原子提交。 协议拒绝未知字段、空白目标、无验收、无边界的预算、非法数值、超过本地最大限制的任务。模型自然语言不得填入 argv 后直接执行;Skill 生成的包也必须通过同样代码检查。 ## 6. 数据模型与状态机 默认状态根目录 `{STATE_DIR}`,可用 `SCALE_ROUTER_HOME` 指向独立测试目录。该目录下 `ledger.sqlite3` 是状态权威源;`tasks//` 存不可变输入、候选、补丁、日志和证据。项目源路径与 Codex 路径统一写在安装配置,运行时收据记录解析值,禁止多处硬编码。 | 实体 | 关键字段与约束 | |---|---| | `tasks` | ID、work_item_id、parent_task_id/supersedes_task_id、幂等键唯一、input hash、schema/version、repo/base commit、snapshot/overlay manifest hash、相关路径守卫、状态、优先级、限额、创建/结束时间、取消标志、阻塞原因、集成状态 | | `attempts` | task、序号唯一、角色 initial/repair/escalation、provider/model/effort、请求/确认模型、launch token、owner generation、shim/worker PID/进程起始标识/PGID、permit/ready 状态、开始/结束、原因、退出码、usage 状态 | | `reservations` | task/attempt、金额/币种、归属日/时区、订阅保留观测、held/settled/released/unknown;与 launch intent 原子提交,不声称与 OS spawn 原子 | | `usage_snapshots` | 来源、采集时间、完整多桶/窗口、许可/限额状态、完整性、桶选择策略、是否新鲜、是否存在其他使用;禁止把任务 token 转成实际订阅百分比 | | `validations` | attempt、profile/evidence_kind、冻结验收 hash、命令 ID、计数/退出码、超时、stdout/stderr 路径、独立 review 记录、变更范围检查、证据 hash | | `integration_journals` | integration ID、repo lock key、task/patch hash、phase、每路径 pre/post 内容引用与 hash/模式/存在性、写入/撤回进度、验收快照及证据 hash | | `events` | 单调事件 ID、task/attempt、UTC ISO 时间、阶段、事件码、经脱敏上下文;不得存认证响应正文 | 任务主状态:`queued → preparing → running → validating → validated → integrating → integrated`。失败分支为 `diagnosing → repairing/escalating → running`;任意执行阶段可进入 `blocked/failed/cancelled/timed_out`。`cancel_requested` 为持久标志,不替代实际进程退出确认。`validated` 表示补丁通过,`integrated` 才表示目标工作树交付完成。 `blocked` 需记录可恢复原因,例如 `quota_unknown/auth_required/base_changed/missing_context/reconciliation_required`。恢复保留历史 attempt,不能清零预算或重试计数。`failed/cancelled/timed_out/integrated/no_change_needed` 为运行终态;再次执行需新任务键,避免把失败从统计中抹去。异常退出的在途任务先进入对账流程,不直接设回 queued。 首版同一账本最多一个活动 worker,采用数据库事务和进程租约防跨聊天重复派发。租约到期只说明控制进程失联,不能证明 worker 已退出;复核 PID 与启动标识后才能回收。 每次提交均记录接纳、协议拒绝或幂等重复事件;拒绝只留脱敏输入摘要/hash,不保存不合法或敏感原文。操作统计保留全部有效任务及拒绝事件。交付 benchmark 按事前登记的原始 `work_item_id` 判定,所有子任务/重做/修复的时间、费用与失败归并到同一工作项;重复提交不增加完成量,失败重做不能另算新增成功任务。 ### 6.1 启动握手与崩溃恢复 SQLite 提交和 OS 创建进程不是一个原子动作。启动按以下协议分步执行: 1. 事务内创建唯一 attempt、`launch_intent`、随机 launch token、owner/fencing generation、取消代数与预算预留,执行许可为 `pending`;落盘后才允许 spawn。 2. 只启动受控本地 shim。shim 用 token/generation 自登记 PID、进程启动标识和 PGID,写入 `ready`,等待持久许可;在此之前不得启动 Codex worker 或发出模型请求。注册失败、过期 generation 或超时立即退出。 3. 控制器确认 ready 身份、当前 generation、无取消及预算/认证仍允许后,在事务内将许可改为 `granted`。shim 用条件更新一次性领取许可,写 `execution_started` 后才能执行模型 worker。同 attempt/token 只能有一个 shim 领取成功。 4. shim 记录执行结束、事件位置和费用证据,控制器幂等结算。恢复者先按 token、启动标识和 PGID 对账;旧 generation 不可取得新许可。已发放/领取许可但缺少可靠完成或退出证据时保留预留并 blocked,不能因控制器租约过期自动再发一个 worker。 5. 许可前取消:持久取消代数使领取失败,确认 shim 退出后可释放未用预留。许可后取消:清理已登记同 PGID 进程并保存费用;收费未知仍保留预留。能证明尚未领取许可的崩溃可恢复同 intent 或安全终止,不消除审计轨迹。 该协议保证一个 attempt 最多一个被许可的本地执行者;供应商已经收到请求但响应丢失仍可能无法确认,产品不承诺跨供应商 exactly-once,不以恢复之名自动重发未知请求。 ### 6.2 多文件集成与安全撤回 1. 按规范化目标仓库路径取得集成锁,冻结 integration ID、patch hash 和相关守卫。锁只约束采用本协议的进程,不阻止外部编辑器;每一步仍检查路径存在性、模式与内容 hash。 2. **首次写入前**,持久保存所有受影响路径的 preimage 与预期 postimage(内容、模式、存在性;新增/删除均有明确状态),刷新内容文件及 journal。SQLite journal 状态为 `prepared` 后才写目标文件。 3. 按固定顺序逐文件应用;每步写前需仍为预期 preimage,采用同目录临时文件与原子替换等适合该操作的方式,刷新文件/目录并记录步骤。模式变更、删除及新增都单列。已观测到任何其他写入立即 blocked,不强制覆盖。 4. 全部应用后对当前目标状态生成受控快照,在只读沙箱或该快照验收,不给测试进程模型凭据或任意写目标工作树的权限。验收证据绑定快照与 postimage hash;目标未再漂移且验收通过后,事务记 `integrated`。 5. 重启逐路径判定 `before/after/other`。全部 after 且有匹配的可信验收证据时可补记成功;没有匹配证据则重新验收。before/after 混合且无 other 时,按 journal 确定继续或撤回;不能重复应用已是 after 的文件。任何 other 都保留现场、原补丁和 journal,状态 blocked。 6. 取消或验收失败时撤回自己的步骤:只有当前路径仍精确匹配其 postimage 才恢复 preimage;已是 before 则跳过,other 则停止撤回并报告冲突。每个撤回步骤也持久记录;绝不 reset 整个工作树或覆盖后来观察到的用户改动。 普通文件系统无法用此锁对不合作的编辑器提供系统级事务隔离;产品不宣称消除检查与写入之间的所有竞态。pre/postimage 与 journal 必须始终保留到明确完成恢复,保障已观察漂移可停止并有可审计恢复材料。 ## 7. 模型能力与路由 | 分支 | 首版策略 | 硬约束 | |---|---|---| | DeepSeek | 默认经济 worker,`deepseek-flash` / `high` | 仅官方 DeepSeek endpoint、独立 provider 配置;不能改 Codex 主配置 | | OpenAI | 按用户已授权的模型选择策略,官方 Codex CLI 的 ChatGPT 订阅认证执行 | provider 必须为官方订阅路径;无 API key fallback;当前模型/effort 必须 probe 成功 | | Jev | 默认关闭,可选 OpenRouter Decisions shadow | 仅 `typesafe/jev-1.13` 对有限任务卡判断;结果不决定 worker、权限或预算 | 初始可配置模型池:DeepSeek Flash high(经济默认)、GPT-5.6 Sol medium、GPT-6 Sol medium、Astra medium/ultra;实际选择必须通过当次 catalog 校验。已有推理实测仅包括 DeepSeek low/high 与 GPT-5.6 Sol medium;其他候选真实调用与回收需补验,不能预先写成已验证或按型号声称便宜排序。高价值复杂任务可明确选择 Astra ultra,仍须通过预算门。配置保存模型目录来源与版本,不能因用户别名“middle”而向接口传未知 effort。 规则顺序:先排除越权/不支持能力,再确认验收与材料,然后执行用户显式模型意图,最后在满足能力及预算的候选中选经济配置。明确机械修改或局部可测问题可默认 DeepSeek;跨模块根因不清时先收集证据,不能直接用关键词保证廉价模型适用。 本用户已授权在 DeepSeek 与官方 Codex 订阅模型之间选择,安装策略应保存该授权并允许范围内的自动升级,不逐任务重复询问。`allow_subscription/allow_escalation` 可省略并继承本机策略;任务字段只能收紧已授权范围,不能自行放宽全局预算/模型/能力。用户明确指定模型或禁止升级时优先遵从,并持久化到该任务包;需要改变全局授权时由明确用户指令更新配置,而非模型输出覆盖。 OpenAI 子进程使用允许列表环境,移除继承的 OpenAI API 凭据与 endpoint 覆盖;程序固定 `model_provider="openai"`、`forced_login_method="chatgpt"`,预检 `account.type="chatgpt"`。runner 不导出、复制或代理登录 token。每次修复和升级同样执行认证检查。强制禁止递归启动其他模型 worker;必要工具能力白名单在程序层校验。 请求配置与后端确认分别记录:CLI 只报告请求模型时,`confirmed_model=null`,`model_evidence=request_config_only`;不能把发送成功解释为后端模型已独立确认。 ## 8. 两本账与预算规则 ### 8.1 API 现金 用户已授权便宜 API 支出;安装写入可配置默认值:DeepSeek 每任务 ¥5、每日 ¥50;Jev 每任务 $0.05、每日 $1,但默认关闭。任务省略预算时继承,不重复要求手填;任务覆盖只能收紧。首版支持任务与日两级上限、币种分账,人民币与美元不未经汇率来源混算。配置文件缺失或损坏时阻塞 API,不能把缺值当无限。 金额使用有限非负十进制定点数,协议可用十进制字符串,禁止 float 累加。预算日按 `Asia/Shanghai`、attempt 获得执行许可的本地日期归属;跨日运行/未知费用的未结预留同时占用当前可派发余额,防止午夜释放,结算只计一次且保留原归属日。若需要按供应商实际账单日对账,另存账单日期,不能静默重写原派发审计。 每次启动前原子预留该 attempt 配置的最大可接受开销,检查已消费、未知费用预留和新预留之和。所有失败、修复、升级和判断都入账。拿到可靠 usage 后结算;没有 usage 时保留预留并标记 `unknown`,禁止当作免费释放后继续循环。 费用分为 `provider_reported/estimated/unknown`;按价格估算需保存价格版本、缓存 token 与推理 token 口径。DeepSeek 初始沿用已核实的计费方式,模型/价格变动需重新验证。 本地预留与停发不等于供应商账单的精确硬封顶。Codex 外部 worker 可能已经产生在途费用,只有已证实的 provider 输出/调用限制才能声称上界。首版收据明示 `cash_enforcement=admission_and_reconciliation` 及潜在在途偏差;到达上限立即终止本地执行并禁止后续调用,不能声称零超额保证。若用户要求绝对现金硬上限而 provider 无对应机制,该任务必须阻塞。 ### 8.2 Codex 订阅 通过已实测可用的只读 RPC `account/rateLimits/read` 读取多桶账户额度,默认快照有效期 5 分钟,未知、过期或认证失败时阻塞新订阅 worker。adapter 输出包含 `sampled_at/schema_version/complete/ordinary_usage_allowed/bucket_selection`,每桶保留本地不可逆别名、`spend_control_reached/rate_limit_reached_type` 以及各窗口的 `used_percent/window_duration_mins/resets_at`,不保存原始私有账户标识。 优先完整解析 `rateLimitsByLimitId`;只有该字段不存在且已通过旧单桶契约测试时使用 `rateLimits`,不能在多桶响应存在时只看 legacy。首版默认选择 `conservative_all`:对完整响应内每一个桶、每一个实际存在的窗口施加同样限制,不要求存在精确模型桶映射,也不跳过 `normalModelSlug=null` 的桶;收据不宣称模型独立配额。可选精确映射只有经验证时使用,映射未知就退回已确认完整的 conservative_all,不能漏桶放行。 普通自动订阅派发必须同时满足:`ordinaryUsageAllowed` 明确为 true;每个选中桶 `spendControlReached` 明确为 false 且 `rateLimitReachedType` 字段存在并为 null;必需字段类型和桶清单完整;至少一个可用窗口,所有实际存在窗口都新鲜、数值合法且有足够余量。`ordinaryUsageAllowed=false/null`、阻断类型非空、spend-control true/null、字段缺失、桶清单不完整或类型错误均拒绝派发;其中不可用/缺失为 `quota_unknown`,明确禁止为 `quota_blocked`。负百分比无效,百分比 >=100 视为用尽。 `primary/secondary` 不能硬编码为五小时/一周,按 `windowDurationMins` 解读;schema 允许且明确为 null 的 secondary 表示没有该窗口,不等同字段缺失或零消费。本机实测 primary 可以直接为周窗口、secondary=null。到达 `resetsAt` 只触发重新读取,禁止本地把用量归零或自行恢复许可。通知不能单独取代完整新鲜快照。接口变化时失败关闭;历史 28% 停止线已随 Phase 0 收口,不是产品配置或当前账户事实。 本地配置保存手动使用保留比例、每次派发安全余量和停止线。默认保留 20% 供正常手动/关键工作;这是保守策略参数,不是实测周节省结论。在后端许可条件全部满足后,仍要求所有选中窗口观测剩余量高于保留量加派发余量,且无其他本 runner 活动订阅 worker。接近执行许可释放时再次核验快照时效与取消状态。 真实扣量由账户服务决定,整数百分比、延迟和其他聊天使用使单任务精确归因不可得。收据只报告带时间的前后观测与是否混杂;不得把差值直接写成单任务成本。Scale 无法拦截根聊天或其他聊天的消耗,无法保证它们不触及订阅上限。 ## 9. 故障、修复与恢复 首版默认 `max_attempts=3`,含初次、一次修复、一次升级;所有启动过的模型进程都占用 attempt,即使认证或网络失败。基础设施重试也占总数,不能另开无限计数器。总超时包含准备、排队、执行、验收和修复;单次超时不得延长总期限。 | 证据类型 | 动作 | 禁止事项 | |---|---|---| | 参数/材料不足 | blocked,指出缺失项;父聊天可补包创建新版本 | 不替用户编造目标 | | 网络、429、暂时服务失败 | 总次数内有界退避;保留费用未知预留 | 不直接换更强付费配置 | | 环境/测试器故障 | 分析表面现象、直接原因、系统性根因、影响,再修复运行环境或阻塞 | 不把测试启动失败当作代码通过/模型能力不足 | | 代码未满足冻结验收 | 带具体失败证据修复一次;再失败可升级 | 不放宽验收、不让 worker 重写隐藏测试 | | 范围越界、密钥风险、沙箱失效 | 立即停止,保留审计,failed/blocked | 不以用户希望完成为由绕过边界 | | 超时/取消 | SIGTERM 后按限时升级 SIGKILL 并检查同 PGID 残留;即使 leader 已退出也继续清理,保存部分补丁与日志 | 不以父进程退出证明所有子进程结束 | | runner 崩溃/重启 | 按 launch token/ready/持久许可门识别 worker,按 integration journal 复核写入,幂等结算;不能确定时 blocked | 不把SQLite提交等同spawn,不自动重发未知调用或重复集成 | | 集成相关路径变化 | 集成阻塞,保留已验证补丁;重新基线需新任务;无关路径变化保留并允许集成 | 不强制覆盖用户改动或要求清理整个工作树 | 修复/升级的输入为原任务、冻结验收要求、当前 diff、失败日志与剩余限制;不给下一 worker 无边界完整聊天。升级重新检查用户允许、模型能力、订阅状态与总限额。预算不足时返回已完成部分与剩余问题,不能标成功。 密钥只从对应环境变量或权限不高于 600 的私有 secrets 文件读取。worker 环境、验收环境分别构建;日志、输入副本、SQLite 和补丁不得保存密钥。对实际密钥值的扫描仅输出命中数量及脱敏位置。 已知进程限制:本机技术探针证明 SIGTERM 可使 leader 退出而留下忽略信号的同 PGID 子进程;也证明 `setsid` 可使子进程脱离原进程组。因此同 PGID 清理不是完整进程树强隔离。`doctor` 必须显示 `process_tree_strict=false` 及能力范围;首版只接受可信本地工程的有界代码/测试任务,不接受启动 daemon、分离会话或不可信任意代码。若任务要求完整进程树安全保证,当前能力不足应阻塞,不通过静态关键词检查冒充强制隔离。 ## 10. 收据与可追溯性 每任务收据至少包含:协议/runner/策略版本,任务 ID、输入 hash、仓库与基准 commit;requested provider/model/effort 与 confirmed evidence;每次角色、时间、退出原因、启动许可状态及失败分类;修改文件、patch hash、验收 profile/证据强度/hash/结果、独立 review;API usage、费用来源/币种、未知费用与预留;订阅前后快照、桶选择、后端许可和归因限制;取消/恢复事件及 integration journal;最终状态、是否集成、目标基准;所有证据本地路径。 成功摘要必须能回答“改了什么、怎样验证、经历几次尝试、花了什么、是否已集成”。运行中显示暂定值;失败同样有收据。没有来自模型的 usage 时不能生成伪造 token 或费用。主聊天消耗无法由 runner 精确采集时在汇总中明确标记未归因,不能删除该成本维度。 ## 11. 安装与首次使用 正式源目录:`{PROJECT_ROOT}`;Python 要求 3.11+,本机实测版本 3.14.7,其余版本须通过兼容测试才能称已验证。Codex 固定已测入口 `{CODEX_CLI}`,当前已测版本 `0.158.0-alpha.2.1`。`doctor` 显示实际解析路径、版本、二进制/schema 指纹;版本变化重新做契约测试,不能认为更新版本必然兼容,也不能默用 PATH 中旧 CLI。 安装配置是路径、模型与默认预算的唯一入口;技能位置为 `{SKILL_DIR}`,状态目录仍为 `{STATE_DIR}`。官网独立部署到 VPS 的 `{PUBLIC_SITE_ROOT}`,通过已配置的 `ssh {DEPLOY_HOST}` 目标操作,正式注册表由项目负责人登记;不把源码、账本、任务或凭据同步到官网。 1. 在批准的项目目录安装 runner,将 Skill 安装为 `scale-router`;安装只管理自身文件,不改主 Codex 登录、全局模型或用户项目。 2. 安装器写入已确认的 Codex 路径、状态目录、候选模型、订阅授权和默认现金限额;用户可在单一配置中调整,无须每任务再填。已有 ChatGPT 登录沿用官方机制;DeepSeek/OpenRouter 凭据按私有来源提供,文档只写变量名。 3. 运行 `doctor --json`,缺订阅能力不阻止离线自检;缺现金预算不擅自发起 API 调用。 4. 在临时 Git 仓库完成一次真实“生成任务包 → run → receipt → integrate → 目标测试”流程,并验证既有相关输入修改和无关 dirty 改动均得到正确保留。 5. 在 Codex 显式调用 Skill 处理一个真实小任务;最后给用户三条日常用法:直接描述修改、查看任务 ID 的收据、取消/恢复指定任务。 CLI 示例:`python -m scale_router run --task task.json`;查看 `python -m scale_router receipt TASK_ID`;取回并应用已验证结果 `python -m scale_router integrate TASK_ID`。安装文档必须替换真实路径与验证过的命令,不能把未实现的示例写成已可用。 卸载只移除 Skill 和运行入口;任务账本与证据默认保留,用户可显式清理。更新先备份账本、执行兼容测试,恢复旧版本时不静默修改已记录任务语义。 ## 12. 首版验收清单 每项结果记录为 `PASS/FAIL/BLOCKED/NOT_RUN` 并链接证据。`BLOCKED/NOT_RUN` 不算通过。离线模拟证明控制逻辑,真实运行证明 provider 接入,二者分别报告。 | 编号 | 必须通过的标准 | 验证方法 | |---|---|---| | V1-01 | 输入空值、空白、单值、特殊字符、非法 enum/数值/未知字段均确定性处理 | 协议边界测试,不启动付费 worker | | V1-02 | 同键同包只执行一次,同键不同包拒绝;每attempt最多一个许可执行者,取消在许可前不得触发调用 | 在intent提交、spawn、自登记、ready、许可领取、完成未结算各边界注入崩溃;两恢复者竞争;未知执行不得重发,预留不重复增减 | | V1-03 | 候选隔离;父目录、外部软链接、隐藏验收、凭据与网络越界均被阻止;doctor 如实标识进程树限制 | 原生沙箱负向探针与 setsid 能力探针,不把进程组当完整安全沙箱 | | V1-04 | 越界或冻结文件篡改、worker自述成功/假完成事件不能绕过验收;strong模式不信候选pass/计数 | 范围与事件负例;strong候选伪造unittest/JSON计数、import提前exit、monkeypatch退出均不得使父validator判pass;engineering如实标示保证边界 | | V1-05 | DeepSeek 实际完成项目编辑、公开测试、独立冻结验收、产生可应用补丁 | 一次真实 worker,完整收据 | | V1-06 | 官方 Codex 订阅实际完成同类闭环,认证可核对,OpenAI API 路径为零 | 一次真实订阅 worker;主配置前后 hash 一致 | | V1-07 | 真实首轮失败后带证据修复或升级,再通过同一验收;失败成本未遗漏 | 预先冻结的有缺陷首轮候选或真实失败任务;故障注入来源明示 | | V1-08 | 总尝试/时间/预留有效;额度充分但后端许可false/null、spend-control/限额触发、缺字段或多桶任一耗尽均阻塞 | 覆盖primary为周窗口、secondary显式null、conservative_all含null模型桶、legacy兼容、reset已过但许可仍false;现金未知及模型不支持不fallback | | V1-09 | 取消/超时结束同 PGID 进程且无后续写入,包含 leader 先退出和子进程忽略 SIGTERM;恢复不重复调用/集成 | 真实进程组与崩溃测试;分离会话能力不足单列,不声称完全覆盖 | | V1-10 | 验收覆盖目标并区分基线/目标;engineering必须绑定独立patch review,strong由父validator持断言;新增测试不能代替独立验收 | hash/依赖篡改/zero-test/旧测试全绿/空交付负例;review缺失、hash失配、builder自填review不得通过;正常及失败结果各测 | | V1-11 | dirty输入和无关改动得到保留;journal可逐文件恢复,取消/失败撤回不覆盖观察到的用户新改动 | 多文件新增/修改/删除/模式变化每步、验收前后、DB最终提交前后崩溃;同仓竞争、用户同/异路径改动;before/after/other分类且不重复应用 | | V1-12 | 每个任务、attempt、失败均有一致收据,消费与未知状态可追溯 | 数据库/文件 hash/收据对账;实际凭据扫描零泄露 | | V1-13 | Skill 显式触发在修改前调用 runner,完成一项真实项目修改并教用户使用 | 在 Codex 正常聊天现场验收;不能仅检查 SKILL.md 存在 | | V1-14 | 预标注中文卡至少覆盖执行任务、闲聊、简单查询和越权任务;记录隐式触发遗漏与误触发 | 首版报告观察数据,不把隐式选择宣传成硬拦截 | | V1-15 | Jev 关闭/超时/输出非法均不阻断主路径或改变权限 | shadow 开关与 schema 测试;真实 Jev 调用可选 | 发布判定:V1-01 至 V1-13 全部通过,V1-14 有完整记录,V1-15 在实现 shadow 时通过;若某适配器真实验收缺失,可交付明确受限的预览版,但不能称完整首版验收通过。超过 100 行的新实现必须完成 Builder → 独立 Validator 审查,最多三轮;核心模块边写边测,不以最终测试总数替代逐模块验证。 ## 13. 整周目标与 benchmark 首版不要求先跑完整周才允许用户试用,但产品状态必须持续显示“整周非劣目标未验证”,直到以下证据齐备。 | 编号 | 目标 | 判定与边界 | |---|---|---| | E-01 | 冻结代表性工作负载 | 事前登记原始 work_item_id、仓库、任务族、优先级、期限、验收和正常手动使用;以全部原始提交工作项为分母,保留 blocked/failed/cancelled/拒绝/延期;子任务和重做统一归并,不增加完成量 | | E-02 | 公平配对 | A 正常 Astra Ultra(保留正常原生子 agent 能力);B 最佳固定经济配置;C 确定规则;D 仅在需要证明 Jev 增益时增加。相同原始输入、权限、冻结验收,干净副本,随机交错,不泄露答案 | | E-03 | 质量不劣 | 总体与高价值任务单列,报告通过率差、严重缺陷和 95% 区间;不得自设质量下降容差;样本不足明确未证实,差异不显著不等于非劣 | | E-04 | 效率/人工负担不劣 | 包含准备、分派、排队、重试、验收、交接的 p50/p95 与按时完成率;人工介入次数/返工时间不增加 | | E-05 | 订阅撑住整周 | 完整 7 天真实运行,约定工作完整交付且符合所有订阅窗口;无额外额度购买、重置或 OpenAI API 补齐。账户混杂观测和批次推算不能冒充单任务实测 | | E-06 | 成本完整 | DeepSeek/Jev 失败和修复全部记账,API 在配置约束下;主聊天开销不漏记为免费 | | E-07 | 可靠性 | 在完整 72 小时窗口内分批故障注入并恢复,无丢任务、盲目重跑或取消失效;按需 runner 不承诺机器睡眠时执行 | 先采集不超过 12 项代表性真实工作并保留自然失败,随后采用 30 项校准、60 项独立保留 pilot,至少 3 个仓库且任务族隔离。用 pilot 估计正式样本量并冻结分析时点和最大预算;不得追加直到出现有利结果。7 天时间窗口与足够统计证据均不可用本轮三个小合成题代替。 ## 14. 阶段与待决事项 Phase 1 定稿前,技术专家定向复核 v0.2 的后端额度许可、启动握手、集成 journal、验收证据强度四项契约。已有运行时测试能复用;实现阶段仍必须执行对应故障注入,文档通过不等于实现验证通过。 Phase 2 先创建项目官网首页与 PRD 在线页,再给出与本 PRD 一致的可交互高保真流程,用户确认设计后进入开发。前端仅承担项目说明和使用引导,不引入公网执行接口。Phase 3 依序实现协议与账本、隔离执行、验收和失败处理、集成与收据、Skill 安装;每模块通过相应测试后进入下一模块。 已确定源路径、Python 下限/已测版本、Codex 已测入口版本、默认预算、候选模型与官网目标;注册表由项目负责人登记。实现阶段待验证:沙箱实际运行时白名单、DeepSeek 在途费用可观测范围、未实跑候选模型、各故障窗口恢复测试及安装后的真实 Skill 触发。未知项明确列为待验,不用模型推测补齐,不额外扩大为后台平台。