Files
cdsl-cad/docs/autonomous-cad-reliability-and-token-target.md
2026-09-01 14:10:23 +08:00

70 KiB
Raw Permalink Blame History

自主 CAD 生成协议:可靠性与 Token 效率目标

1. 目标与结论

本目标直接替换当前自主 CAD 协议,不保留旧任务兼容、迁移或恢复路径。目标是在不降低建模判断能力的前提下,消除当前“先生成大型 Markdown 建模计划,再按计划生成 CDSL”的硬门,并把每一轮 LLM 的输出缩小为可验证的单个建模动作。

必须达成:

  • LLM 决定下一步建模意图和操作。 服务端不生成 CAD 步骤、不替 LLM 选 operation、不把需求编译成几何模板。
  • 服务端只负责事实、约束和状态转换。 它提供不可变需求、当前模型、拓扑、Runtime 合同、已接受动作及复核证据;校验 LLM 的选择,执行 CDSL,持久化真实结果。
  • 不再要求新任务生成或复核 modeling-plan.md,不再出现计划版本、计划解析、计划动作 ID、计划 revision limit 或计划跳步门。
  • 保留 source-requirements.mdrequirements.mdcompletion.md、单 feature CDSL、候选构建、独立候选复核、检查点和最终独立复核。
  • LLM 产生的每一项会改变状态、影响执行或作为验收依据的数据,必须通过固定 Pydantic schema 或 Runtime 动态 JSON Schema 校验。Markdown 和解释文本只由服务端从已验证数据渲染,绝不被解析为状态机输入。
  • 可靠性的含义不是假定任何 LLM 永不产生错误格式,而是错误格式、过期引用和不符合 operation 合同的输出在任何副作用之前被确定性拒绝;它们不能创建候选、污染状态、消耗构建预算或触发无限重试。
  • 文档和动作的格式问题必须是无副作用的可诊断拒绝;内部服务错误必须一次失败并保留检查点,不能被伪装成 LLM/CDSL 错误后循环重试。
  • v3 必须完成架构解耦。 “LLM 决策、Runtime contract、任务状态机、候选构建、持久化、渲染/复核”必须是职责明确、依赖方向受控的独立模块;不能继续集中在一个巨型 runner/service 中,或通过模块全局对象互相访问。
  • 使用真实 API usage(可用时)和服务端上下文字节数度量 token 消耗,验收时以基线任务集比较,不以主观感觉判断。

这不是“取消计划后让服务端推断下一步”。计划能力仍存在,但由 LLM 在每个检查点结合当前事实重新判断;服务端保存的是实际发生过的动作账本,而不是预先要求 LLM 写完整未来路径。

2. 当前基线与已确认问题

当前路径由 backend/app/services/autonomous_cdsl_generation.py 实现:

  1. 服务端创建不可变 source-requirements.md
  2. 作者 LLM 写入并立即冻结 requirements.md
  3. 作者 LLM 写入并立即冻结 completion.md
  4. 作者 LLM 必须写大型 modeling-plan.md,独立模型审查它,失败后重写版本。
  5. 作者 LLM 按计划动作读 Runtime contract,提交一条 CDSL feature。
  6. 服务端构建候选,独立模型审查,接受后提交 checkpoint。
  7. 完成清单覆盖后执行最终重建和视觉复核。

cad_30933fe2fc6b 已在 rev_003 生成正确的法兰:圆盘、中心贯穿孔、四个均布孔均已构建并接受。该任务随后失败的根因包括:

  • _final_review 使用了未赋值的 global_violations,导致每次 complete_task 都触发 NameError。这是确定性的后端缺陷,不是 CDSL 或 LLM 错误。
  • 调度器把上述内部异常归类为 authoring/fragment 错误,并允许重复 complete_task;因此无检查点进展的重试最终命中 NO_PROGRESS_LIMIT
  • 建模计划审查要求精确 operation、selector、盲孔深度和 action 粒度,但计划又允许自然语言。这种“自然语言写入,严格执行含义”的双重合同使法兰计划在 hole_blind | hole_wizard、多孔单 action 和 through-equivalent 深度等问题上反复返工。
  • CDSL_MODELING_PLAN_MAX_REVISIONS=2 的检查在计划已写入及审查后执行,并且后续循环仍可能继续,形成“已到上限却继续调用”的矛盾控制流。

已直接修复第一项:最终重建得到 health 后,现在会先调用 _global_geometry_violations(...),再使用该变量。这一改动必须保留,并以最终复核回归测试覆盖。

2.1 真实 LLM 连通性测试

2026-08-31 在隔离临时任务根目录中,直接使用当前后端的 AgentService._complete_once 和完整 runner 调用配置的真实作者模型,依次发送了三个请求:矩形底板、简单法兰、带肋和四个安装孔的底板。第一个请求尚未产生工具调用或 CAD 工件时,OpenAI 作者请求已连续三次连接失败;runner 随后切换到 DeepSeek,同样连续三次失败。

测试发现 _is_author_transport_error 分支在所有作者 provider 失败后仍以约 4.5 秒间隔无限重试,使任务永久处于 running。测试已手动终止,以避免无意义 API/CPU 消耗;没有生成模型,因此不能把这次测试伪称为模型生成质量结果。该证据证明当前 transport 恢复策略存在流程缺陷,必须在 P0 修复:记录有限的 provider/总调用预算和指数退避,超限后将任务转为 WAITING_RETRY,保留 checkpoint 和调用诊断;只能由显式恢复操作或受控调度重新启动,而不能在同一个 run 中无限循环。

3. 不采用的方案

以下方案不满足本目标:

  • 不保留现有 Markdown 计划,只改提示词。 它仍把未来的操作、selector 和精确 Runtime 语义要求压到一次大输出中,根因未消失。
  • 改成 LLM 一次输出大型 JSON/DAG 执行计划。 JSON 更容易解析,但不能消除大输出遗漏、过期 selector、前后依赖和重试 token 消耗;问题从 Markdown 转移到 JSON。
  • 服务端依据未覆盖需求决定下一步。 这会把建模策略藏在程序规则中,违反“LLM 决定下一步”的边界,也会让复杂零件的 CAD 判断不可审计。
  • 取消独立候选/最终复核。 能减少 token,但会显著降低最终几何可信度;优化应先删除重复的计划复核与冗余上下文,而不是删除实际结果复核。
  • 用盲孔深度大于厚度作为所有通孔的唯一证明。 这只是候选输入条件;最终仍须从拓扑/几何证明孔连接了预期两侧面、孔数和直径满足要求。

4. 新协议中的工件、结构化输出与验证

4.1 统一的结构化输出边界

不得让 LangChain、任何 provider 或 Pydantic 自身成为可信边界。它们只负责请求和解析;服务端必须对原始 tool arguments 再做一次 canonical validation,验证通过后才允许写库、构建候选或改变 revision。

LLM provider
  -> LangChain structured-output adapter
  -> 原始 tool arguments / JSON
  -> Pydantic 或 JSON Schema canonical validator
  -> 当前 task、revision、权限和幂等校验
  -> Runtime / CDSL / 几何验证
  -> SQLite 事务提交

固定业务对象使用 Pydantic v2 模型生成 JSON Schema;例如需求草稿、审查 verdict、动作提案、修复决定都必须是 extra="forbid" 的模型。不同 operation 的 CDSL fragment 由 Runtime contract 生成动态 JSON Schema,不能伪装成一个“所有参数都可选”的静态 Pydantic 模型。需求草稿的外层是固定 Pydantic schema,但每个 acceptance_claim.expected 是 verifier registry 在当前任务启动时生成的 closed oneOf;这同样是动态 schema,不能用 dict[str, Any] 放过未知 claim 数据。

LangChain 仅封装在 cad_agent/adapters/structured_llm.py 或等价 adapter 内:

  • 固定对象使用 with_structured_output(PydanticModel)
  • 动态 operation contract 使用 bind_tools() 或 provider 的等价 tool schema 接口,传入服务端生成的 JSON Schema。
  • 无论 provider 宣称支持 strict JSON、function calling 或 JSON mode,服务端都使用相同的 Pydantic/jsonschema validator 二次验证。
  • 禁止使用 LangChain Agent、Memory、文本 JSON 提取、自动无限 re-ask 或自动 tool 执行。CAD runner 仍是唯一状态机。
  • 不具备成功通过 provider conformance test 的 structured-output / tool-call 能力的模型,不可作为生产作者或审查模型。不能为了“支持任意模型”退回纯文本解析。

每次 LLM tool call 都经过同一条严格管线:限制一个允许的 tool name 和一个 call、限制原始 arguments 的字节数/JSON 深度、解析 JSON、schema canonical validation、当前状态与版本绑定、跨字段/几何 preflight,最后才进入事务或候选构建。provider 的 parser、LangChain 的 parser 和 Pydantic 的第一次反序列化都不是最终结论。服务端保留经脱敏的原始 arguments 与字段级错误用于诊断,但不会以“尽量修复”方式补全、重命名或猜测 LLM 字段。

工具的 schema_nameschema_version、当前 working_headcontract_hash 和 selector snapshot 由服务端 route/state 绑定,而不是信任 LLM 声称的版本。固定对象可以在工具 schema 中携带这些字段并做 canonical equality 校验;空参数命令(例如完成请求)则只以服务端暴露它的状态作为版本绑定。任何 schema 或 contract 变更都会使旧 pending action 失效,必须重新读取当前事实和合同。

4.2 需求和完成工件

source-requirements.md 是服务端保存的用户原文,不要求格式。服务端把它按原始段落或附件块生成稳定 source_id,只作为可引用证据,不尝试用规则理解自然语言。

LLM 不直接写 requirements.mdcompletion.md。它提交受严格 schema 约束的、分批且有上限的 RequirementsDraftBatch;服务端校验并保存 JSON,再渲染人类可读 Markdown。草稿阶段还必须使用结构化 RequirementsPatchBatch 修订 reviewer 指出的条目,并以零参数 finalize_requirements_draft() 明确请求进入独立复核。服务端在 source coverage 不完整时拒绝该最后一步,不自行猜测“需求已经写完”:

source-requirements.md                    # 服务端创建,不可变
documents/source-index.json               # 服务端生成:source_id -> 原始文本
documents/requirements-draft-v1.json      # 仅已验证 RequirementsDraftBatch 合并结果
documents/requirements-review-v1.json     # 严格结构化的独立审查结果
requirements-contract.json                # 冻结的机器可验证需求与验收合同
requirements.md                           # 服务端从 contract 渲染,不作为程序输入
completion.md                             # 服务端从 contract 渲染,不作为程序输入
requirements-index.json                   # 服务端生成的 req/claim 索引

每次 submit_requirements_draft_batch 最多提交 8 条 requirement,避免大型一次性文档输出。外层固定 schema 至少包含:

{
  "items": [
    {
      "source_ids": ["src_001"],
      "statement": "法兰为外径 120 mm、厚度 12 mm 的单一连通实体",
      "assumptions": ["未指定标准时采用普通平面法兰"],
      "acceptance_claims": [
        {
          "claim_kind": "solid_count_equals",
          "expected": {"value": 1}
        },
        {
          "claim_kind": "bbox_dimension_mm",
          "expected": {"axis": "z", "value": 12, "tolerance_mm": 0.01}
        }
      ]
    }
  ]
}

source_ids 必须来自服务端 enumclaim_kind 必须来自已注册 verifier enum;每一种 claim_kindexpected 都按该 verifier 专属 JSON Schema 校验。服务端分配不可变的 draft item ID、req_###claim_###,不会接受 LLM 自定义 ID。

RequirementsPatchBatch 的每一项只能是 replaceremove,并且 target_draft_id 必须是当前 draft revision 的 enum。replace 必须携带完整、重新验证过的 requirement 对象,不能提交局部自然语言 patch;remove 必须给出长度受限的原因。这样 reviewer 修改的是可审计的单项,而不是要求模型重写整份文档。删除后若使 source 无覆盖,finalize_requirements_draft() 必须被拒绝。

冻结前,独立 reviewer 必须返回 RequirementsReview。它对每一个 source_id 给出恰好一行 coverage(该行可引用一个或多个 requirement ID),并对每一个 draft item 给出 passrevisewaiting_for_userpass 只有在全部 source 已被映射、全部 claim 的 verifier 可用且不存在冲突时有效。一个 source 可以支撑多条 requirement;因此不要求 source 只被一条 requirement 引用,只要求 reviewer coverage 行唯一且完整。waiting_for_user 必须具有 machine-readable reason code 和受限的提问文本,不能用模糊 prose 隐藏关键尺寸或基准缺失。

requirements.mdcompletion.md 可以是自然、自由的 Markdown,因为它们是 JSON contract 的只读渲染。例如:

- [ ] 单一连通实体,外径 120 mm、厚度 12 mm
- [ ] 同轴直径 40 mm 的中心贯穿孔
- [ ] 节圆直径 90 mm 上四个直径 10 mm 的均布贯穿螺栓孔

程序永远不从上述 Markdown 重新提取 ID、验收项、步骤或状态。任何可测几何需求若没有注册 verifier,必须在需求阶段报 VERIFIER_UNAVAILABLE,不得偷偷降级为“让视觉模型看一看”。确实只能依赖外观判断的要求可显式声明为 visual claim,但其风险必须在任务界面标记。

需求草稿、修订和 review 的 canonical schema 还必须有以下共同约束:所有数组有上下限,所有可见文本有长度上限,所有枚举/ID 来自当前服务端快照,嵌套对象 additionalProperties=false;禁止任意 JSON object、任意键值 metadata 和未注册 claim。若需求是文件命名、材料、单位或展示约束,也必须绑定相应的确定性 verifier;没有 verifier 就不能被冻结为可发布合同。

4.3 LLM 的单动作意图

LLM 不再写模型级执行计划。没有待处理动作时,作者只可调用 propose_next_action。该 tool 的 JSON Schema 由服务端传给模型并在服务端再次校验;不得接受 Markdown、自由 JSON 字符串或未知字段。

{
  "working_head": "head_5f2e...",
  "intent": "在当前法兰顶面加工四个均布螺栓孔",
  "requirement_ids": ["req_003"],
  "atomic_id": "hole_blind",
  "expected_change": "新增四个直径 10 mm、在节圆直径 90 mm 上等角分布并贯穿 12 mm 本体的孔"
}

约束:

  • intentexpected_change 为短文本(建议分别最多 360 字符),只说明当前动作,不复述全任务。
  • requirement_ids 必须来自 requirements-index.json 的 enum,最多引用五项。
  • atomic_id 必须来自当前 Runtime SUPPORTED_ATOMIC_IDS enum。
  • working_head 必须与服务端发出的 opaque current-head token 完全相等;Pydantic 检查其形状,canonical state validator 检查其相等性。
  • 提案不包含 selector、草图、参数、深度、工作平面或 CDSL;这些属于后续读取精确 contract 后的 canonical fragment。
  • 提案必须绑定当前 working_head。检查点变化后旧提案不可提交,需由 LLM 基于新事实重新提出。

因此格式错误无法“完全不发生”,但影响面被限制为一个极小、严格 schema 的无副作用调用:服务端返回字段级错误并保留模型/检查点,不会再生成计划版本、消耗候选构建次数或污染账本。

4.4 服务端动作账本

账本不是 LLM 输出,也不是执行计划。服务端在动作提案、拒绝、候选构建、复核和 checkpoint 后,以 append-only JSON Lines 写入 actions/action-ledger.jsonl。每一行是一个状态事件,便于审计、恢复和增量读取:

{"schema_version":"cad.action-ledger.v1","sequence":7,"event":"proposed","action_id":"act_003","working_head":"main:rev_002","intent":"在当前法兰顶面加工四个均布螺栓孔","requirement_ids":["req_003"],"proposed_atomic_id":"hole_blind","expected_change":"新增四个直径10 mm贯穿孔","at":"2026-08-31T...Z"}
{"schema_version":"cad.action-ledger.v1","sequence":8,"event":"accepted","action_id":"act_003","working_head_before":"main:rev_002","revision_id":"rev_003","actual_atomic_id":"hole_blind","fragment_sha256":"...","selector_snapshot_id":"...","candidate_id":"candidate_...","review_path":"revisions/rev_003/reviews/candidate-review/candidate-review.json","coverage":[{"requirement_id":"req_003","status":"complete"}],"at":"2026-08-31T...Z"}

运行中的 pending action 是事务状态,不从 JSONL 反推。它只保存 action_idworking_head、提案内容、contract hash 和幂等 key。给作者的上下文只包含 pending action 与压缩后的最近动作摘要,完整账本仅用于审计/UI 查询,避免随模型复杂度线性膨胀 prompt。

4.5 CDSL 与完成调用

提交 CDSL 的动态 tool schema 不存在“统一的 feature JSON 模板”。它只暴露当前 pending action 已选择的一个 operation 的 author-owned 字段;下面只是一个形状示意,实际是否有 sketch、是否有 params、是否有 selector/reference token 由 operation contract 决定:

{"fragment": {"sketch": {"...": "仅 contract 要求时存在"}, "feature": {"atomic_id": "与 pending action 相同", "params": {"...": "contract 精确字段"}}}}

移除 batch_goalplan_step_idplan_action_id。候选复核的目标、需求映射和 operation 均从 pending action 与真实 fragment 取得,不能由 LLM 在提交时再次声称。

动态 schema 必须由当前 Runtime 的完整、版本化 feature_atomic_contract 唯一生成,并与 contract_hashworking_head、engine/profile schema revision 和 selector snapshot ID 绑定。当前 feature_atomic_contract 仅列出 required/optional 参数,而 cdsl_authoring_schema.py 仍按 operation 名称硬编码很多 JSON 类型、hole 特例和 pattern 注入;这会产生 contract drift,不能作为 v3 的终态。P2 必须把这些信息收拢到 Runtime contract registry,删除 authoring schema 中按 operation 前缀补规则的兜底分支。

每个 operation contract 至少声明以下数据,且 contract 自身先经 JSON Schema / registry integrity validator 验证:

{
  "atomic_id": "hole_blind",
  "contract_version": "3.0",
  "fragment_shape": {
    "sketch": "forbidden",
    "params": "required_object",
    "selector_tokens": "required"
  },
  "author_params_schema": {"type": "object", "additionalProperties": false},
  "selector_policy": {
    "slot": "params.host_face",
    "token_kind": "face",
    "min_items": 1,
    "max_items": 1,
    "snapshot_bound": true
  },
  "server_injected_paths": ["params.host_face"],
  "reference_policy": {"mode": "none"},
  "semantic_preflight": ["host_face_exists", "hole_positions_on_host_plane"],
  "candidate_verifiers": ["cylindrical_bore", "through_cylindrical_bore"]
}

其中 author_params_schema 是 closed JSON Schema,必须递归关闭其嵌套对象。禁止用 {}type: object 未限制 properties、任意 dict 或“其它 operation 以后再解释”的 fallback 暴露给作者。hole_wizardhole_typethreadcountersinkcounterbore 等嵌套对象必须各有枚举/closed 子 schema;当前的开放对象定义不满足此要求,必须在该 operation 可暴露前补齐。

动态 schema 必须精确表达以下 operation 差异,而不能靠 prompt 约定:

  • fragment_shape.sketch=requiredsketch.workplanesketch.profile 必填;forbiddensketch 出现即拒绝。profile 类型和每层字段同样由 closed schema 限制。
  • fragment_shape.params=required_objectparams 必须存在并匹配该 operation 的专属 schema;若 operation 没有 author-owned 参数,contract 明确指定 params 是必填的空 object 还是 forbidden,不能假设所有 feature 均需或均不需参数。
  • selector_policy 只能为 forbiddenrequired 或明确的 optional。required selector 的 token schema 是当前 snapshot 中匹配 kind 的 opaque token enum,并有精确数量上限;没有有效 snapshot 时根本不暴露 fragment tool。host_face、mirror plane 等 server-owned selector 只由 resolver 注入,LLM 提供原始 selector object 或注入字段即拒绝。
  • reference_policy 处理 feature-source、reference plane/axis 等关系。禁止当前实现中“默认把最后一个 committed feature 当 pattern source”的通用猜测;若关系不是 contract 可唯一推导,schema 必须要求来自当前 feature-reference snapshot 的 opaque token,并由服务端解析为 Runtime ID。
  • 每个 operation 只允许自身的 required/optional paramsadditionalProperties=false;例如 extrude_cut_blind.distance_mm 不能替换为 hole 的 depth_mmhole 的 positions 也不能出现在 extrude。所有数字必须是有限值,并满足 Runtime 安全范围、单位和 operation 专属的跨字段限制。
  • atomic_id 必须同时等于 pending action、active contract 和动态 schema 的 const;三者任一不一致均在构建前拒绝。
  • 新增 Runtime operation 时,必须同时新增完整 operation contract、contract integrity fixture、动态 schema fixture、canonical validator 测试、semantic-preflight 测试、引擎执行测试和对应 verifier;缺任一项不得进入作者可选 atomic_id enum。

动态 schema 校验成功后仍必须依次通过:当前 revision/head 校验、contract hash 与 registry revision 校验、selector/reference snapshot 校验、operation semantic preflight、静态 CDSL schema、完整 materialized CDSL validation 和隔离 CDSL-only rebuild。前六项均不产生候选目录;只有通过后才消耗候选构建预算。schema 不能表达的关系必须由 preflight/geometry validator 检查,例如工作平面正交且法向非零、profile 不自交、hole position 位于宿主面、revolve axis 位于草图平面,以及为了满足“贯穿” claim 的 hole_blindextrude_cut_blind 的切削方向、有效行程和出口面连通性。

complete_task 改为无参数 tool。删除 self_review,因为作者的自我声明不能作为完成证据。服务端仅在当前 revision 的独立 coverage 全部完成且没有 pending/rejected repair 时暴露该 tool。

4.6 每类 LLM 输出的可信边界

LLM 输出 输出方式 必须由程序验证 不由它控制的内容
需求草稿/修订/提交复核 RequirementsDraftBatchRequirementsPatchBatchfinalize_requirements_draft() 字段、source/draft-ID enum、批量上限、claim kind 的动态 oneOf、重复项、累计 source coverage Markdown 文档、req/claim ID、draft/review 状态、冻结状态
需求独立审查 RequirementsReview Pydantic schema 每个 source_id 的唯一 coverage 行、每个 draft item verdict、引用的 req/claim 存在、WAITING_FOR_USER reason code 是否冻结由服务端 coverage gate 决定
下一动作 NextAction Pydantic schema requirement ID enum、Runtime operation enum、working head、无 pending action、幂等键 action_id、pending 状态、实际 CDSL ID
观察/测量/contract 请求 固定 Pydantic tool schema,动态 enum 绑定当前 head/snapshot 参数范围、当前 revision、selector kind/limit、operation enum;每回合只接受允许的一个 tool call 观察结果、contract、selector/reference token 均由服务端生成
CDSL feature 当前 operation 的动态 JSON Schema contract hash、const atomic_id、fragment shape、递归 closed params、selector/reference enum、静态 CDSL、语义 preflight、引擎 preflight feature/sketch ID、dependency、host face、selector/reference 解析
诊断、回滚与完成请求 GeometryConclusionRollbackCheckpointcomplete_task() decision enum、当前 evidence ref enum、rollback token、head、文本/数组上限;完成 gate 由服务端先验证 几何诊断证据、回滚可达性、发布判断
候选审查 CandidateReview Pydantic schema candidate/revision enum、claim coverage 的精确集合、verdict enum、证据上限;确定性 verifier 必须先通过 checkpoint 提交、coverage 更新
最终审查 FinalReview Pydantic schema current revision、所有 final claim 的精确集合、verdict enum、证据上限;所有 deterministic claim 必须通过 发布、published revision
可见解释/意图文字 普通文本字段,长度限制 仅编码、安全和长度检查 不参与任何状态转移或 CAD 参数计算

“结构化输出通过”只证明对象格式和引用有效,不证明 CAD 语义必然正确。语义正确性必须由 source coverage、requirement acceptance contract、Runtime、几何 verifier 和独立 review 共同证明;其中 deterministic verifier 失败时,任何 LLM 的 accept verdict 都不能覆盖失败。

4.7 Canonical schema 目录与二次校验

以下目录是 v3 必须实现的唯一 LLM 输入合同。每个固定模型均使用 Pydantic v2 的 strict modelextra="forbid"、显式长度/数量限制),由服务端导出 JSON Schema;动态 enum 和 dynamic oneOf 在每次 tool 暴露时由服务端收窄。任何新的 state-changing LLM tool 必须先加入本表、fixture、conformance test 和错误映射,不能临时添加自由 object 参数。

Tool / 输出模型 必填结构化字段 schema 类型 格式后仍必须程序校验
submit_requirements_draft_batch / RequirementsDraftBatch items[1..8];每项有 source_idsstatementassumptionsacceptance_claims Pydantic outer + verifier registry 的 closed claim oneOf source enum、去重、claim 语义/单位、可用 verifier、draft transaction
patch_requirements_draft / RequirementsPatchBatch patches[1..8]target_draft_id、`op=replace remove`replace 携带完整 item Pydantic + current draft-ID enum
finalize_requirements_draft 空 object fixed empty schema 至少一个 draft item、无缺 source、无不可用 claim 后才可进入 review
review_requirements / RequirementsReview verdict、每个 source 的唯一 coverage row、每个 draft item verdict、issues[] Pydantic + source/draft/claim ID enum coverage 精确集合、issue code、approve gate;服务端而非 reviewer 冻结 contract
propose_next_action / NextAction working_headintentrequirement_idsatomic_idexpected_change Pydantic + Runtime operation/requirement ID enum head equality、无 pending action、operation available、idempotency
事实读取工具 例如 inspect_topology(kind, limit)get_cdsl_operation_contract(atomic_id)render_section(origin_mm, normal) Pydantic,动态 operation/head/snapshot enum 参数范围、访问当前 revision、预算/缓存;结果只能由服务端生成
submit_cdsl_fragment 只有当前 operation contract 定义的 fragment Runtime-generated Draft 2020-12 JSON Schema contract/schema/snapshot hash、引用解析、cross-field semantic preflight、materialized CDSL schema、engine preflight
record_geometry_conclusion / GeometryConclusion working_headevidence_refsroot_causedecision、受限 corrective_intent Pydantic + current evidence enum evidence 属于同一 head、decision 可达;corrective_intent 不直接成为 CDSL
rollback_checkpoint / RollbackCheckpoint working_headcheckpoint_token、受限 reason Pydantic + active lineage enum token 是祖先、没有 candidate/transaction 冲突、原子 branch transition
review_candidate / CandidateReview candidate_idrevision/headverdict、精确 claim coverage、受限 evidence/issues Pydantic + candidate/claim enum candidate identity、确定性 claim gate、reviewer 不能覆盖 deterministic result
complete_task 空 object fixed empty schema 没有 pending action/repair,所有 deterministic claim pass;为 final review 创建幂等工作项
review_final / FinalReview revision/headverdict、精确 final claim coverage、受限 evidence/issues Pydantic + final claim enum final rebuild identity、全局 invariant、deterministic/visual gate、一次发布事务

GeometryConclusion.decision 只能是 return_to_action_selectionrollbackwaiting_for_user;它不包含 feature ID、参数、selector 或下一段 CDSL。选择修复仍由下一次 NextAction 明确作出,避免诊断对象暗中变成第二套执行计划。CandidateReviewFinalReview 允许模型提出 reject/repair;对确定性 claim,服务端只把 reviewer 的 accept 当作额外条件,而不是证明。

5. 完整执行流程及 LLM 边界

阶段 输入/产物 LLM 生成内容 服务端职责 失败后的唯一去向
0. 创建 用户请求 创建 source-requirements.md、任务与 run 请求错误,拒绝创建
1. 需求草稿 source index + 用户上下文 submit_requirements_draft_batch(RequirementsDraftBatch),每次最多 8 项;按需 patch_requirements_draft(RequirementsPatchBatch),最后 finalize_requirements_draft() outer Pydantic、source/draft-ID enum、verifier dynamic schema、去重和批量事务;只保存 JSON AUTHOR_FORMAT_INVALIDREQUIREMENTS_COVERAGE_INCOMPLETE,不写 Markdown、不进入建模
2. 需求独立复核 source index + draft contract review_requirements(RequirementsReview) coverage 行、假设/冲突/验收可行性;通过后冻结 JSON 并渲染 requirements.md / completion.md revise 回到阶段 1;歧义为 WAITING_FOR_USER;缺 verifier 为 VERIFIER_UNAVAILABLE
3. 选择下一动作 frozen contract、claim coverage、当前模型摘要、账本摘要、Runtime operation enum propose_next_action(NextAction) Pydantic、ID enum、head、operation、幂等和 pending-action 校验 无副作用 AUTHOR_DECISION_REJECTED 或 Runtime 前置条件错误
4. 收集事实 当前 checkpoint LLM 自主调用结构化 inspect/measure/render/topology/contract tools 返回真实、版本绑定数据;为动态 fragment 生成 selector/reference enum、限额和缓存 snapshot 过期或 selector/reference 不匹配,保留 checkpoint,重新观察
5. 生成 CDSL pending action + 精确 operation contract + 相关 snapshot submit_cdsl_fragment(DynamicOperationSchema) contract/head/snapshot-bound dynamic JSON Schema、静态 CDSL、语义/引擎零副作用 preflight CDSL_SCHEMA_INVALIDRUNTIME_PRECONDITION_FAILED,只允许修正当前动作;不消耗候选尝试
6. 构建候选 materialized CDSL 隔离 rebuild、健康检查、拓扑、deterministic claim verifier、渲染 CANDIDATE_BUILD_FAILEDCLAIM_VERIFICATION_FAILED,保留基线并进入诊断/修复或回滚
7. 独立候选复核 渲染、真实 CDSL、拓扑、pending action、只读 claim 结果 review_candidate(CandidateReview) 验证结构化 verdict/claim coveragedeterministic claim 失败时强制 reject reject 形成明确 repair cardreview 服务故障为 typed service failure,不让作者重做几何
8. 写账本/检查点 accepted candidate 原子提交 revision,追加 accepted ledger,更新 claim coverage,清除 pending action 存储失败必须原子回滚,不出现半提交
9. 下一轮 新 checkpoint 回到阶段 3,由 LLM 决定下一动作 仅提供最新事实 同上
10. 最终完成 当前 revision、claim coverage、最终渲染 complete_task(),无参数;review_final(FinalReview) 由独立 reviewer 输出 CDSL-only rebuild、全部 deterministic claim、全局几何不变量、结构化最终独立复核、发布 repair 回阶段 3;内部故障一次标为 FAILED_INTERNAL

阶段 3 的“下一步”必须由 LLM 做决定。服务端不可根据未覆盖的 req_003 自动构造“加工螺栓孔”;它只能在 LLM 提出 hole_blind 后检查该选择是否是当前 Runtime 支持的原子操作、是否与 checkpoint/contract 相容,以及是否可安全进入下一阶段。

6. 可靠性规则

6.1 明确错误分类

定义可序列化的错误码和类别,禁止将 Python 异常文本当作 authoring error

  • AUTHOR_FORMAT_INVALIDtool 参数或 canonical CDSL schema 无效;无 CAD 副作用,可限次数修正。
  • AUTHOR_DECISION_REJECTED:动作与当前 pending/head/contract 不一致;无 CAD 副作用,要求重新选择或修订。
  • STALE_WORKING_HEADcommand 的 head、state version、contract 或 selector/reference snapshot 已过期;无 CAD 副作用,返回最新事实,禁止自动合并或覆盖新的 checkpoint。
  • FAILED_AUTHOR_FORMAT:同一 schema 的字段级修正次数达到上限,或 provider 持续不能交付该 schema;终止本 run 并保留 checkpoint,不能改记为 NO_PROGRESS_LIMIT 或降级到自由文本。
  • RUNTIME_PRECONDITION_FAILEDselector 不存在/歧义、body/host 缺失、操作不支持;保留 checkpoint,要求新的观察或动作决策。
  • RUNTIME_CONTRACT_INVALIDoperation registry 缺少 closed field schema、注入/selector/reference policy、semantic preflight 或与 engine schema 不一致;这是部署/代码缺陷,feature 不得暴露给作者,也不能归因于 LLM。
  • CANDIDATE_BUILD_FAILED:BRep/STEP 构建失败;消耗候选预算,进入诊断、修复或回滚。
  • CANDIDATE_REVIEW_REJECTED:几何已构建但不符合动作或需求;保留证据,LLM 决定修复/回滚。
  • VERIFIER_UNAVAILABLE:冻结的 requirement claim 没有已注册且可运行的 verifier;不得创建 task contract 或发布。
  • CLAIM_VERIFICATION_FAILED:候选/最终 deterministic verifier 得到 failLLM reviewer 不能覆盖该结果。
  • MODEL_STRUCTURED_OUTPUT_UNSUPPORTEDprovider/model 未通过当前 schema 的 conformance suite;任务开始前拒绝,不进入 author loop。
  • AUTHOR_TRANSPORT_UNAVAILABLEREVIEW_SERVICE_UNAVAILABLERENDER_SERVICE_UNAVAILABLESTORAGE_FAILURE:基础设施失败;不归入 no-progress、不允许 author 重复 CDSL。使用相同幂等键和有限指数退避重试服务操作,超限后进入 WAITING_RETRY,由显式恢复操作或受控调度重新开始。
  • FAILED_INTERNAL:未预期异常(例如 NameError);记录 traceback/版本/调用幂等键,立即终止该 run,保留最后 checkpoint。
  • WAITING_FOR_USER:源需求冲突、关键尺寸/基准不可合理假设、或多轮文档复核无法消除的语义歧义;不是 failed

NO_PROGRESS_LIMIT 只统计作者在允许的观察/决策阶段反复作出没有状态推进的合法但无效选择;同一无副作用格式错误超过上限应归为 FAILED_AUTHOR_FORMAT。它绝不能统计 FAILED_INTERNALRUNTIME_CONTRACT_INVALID、verifier/review/render/network/storage 故障,也不能把重复 complete_task 视为可继续作者修正的机会。WAITING_RETRY 只用于可恢复的基础设施失败,WAITING_FOR_USER 只用于用户决定缺失,二者都不能掩盖 author format failure。

6.2 幂等与事务

  • 每个状态改变 tool call 有 invocation_id;每个候选/最终复核有基于 task_id + working_head + action_id + fragment_hash 的幂等键。
  • 同一 complete_task 对同一 revision 最多执行一次最终重建/复核;调用中断后恢复相同结果或明确失败,不能重新进入作者循环。
  • candidate commit、task revision 更新、pending-action 清除和 ledger append 必须在同一事务内完成。
  • 新协议的权威可变状态采用 SQLite(任务、run、pending action、ledger index、invocation、coverage),STEP/GLB/CDSL/Markdown/渲染仍保留在任务目录作为不可变工件。WorkspaceStore 重构为“数据库状态 + 文件工件”,不允许 JSON 与数据库双写且各自成为事实来源。
  • task.json 可以作为 API/人工查看的派生快照,不能再是并发状态机的权威来源。
  • 外部 build/render/review 不能与 SQLite 假装存在同一事务。候选工件先写入不可见的 staging 目录,并带有输入 head、fragment hash、engine version 和每个文件 sha256 的 manifest;只有所有 preflight/build/verifier 都成功,才原子 rename 到不可变 revision artifact 位置。随后 SQLite 条件事务写入 revision、coverage、ledger index 和已存在 artifact manifest 引用;API 只通过 SQLite 引用读取工件,因此在数据库提交前已发布的文件仍不可见。进程崩溃时恢复器验证 manifest/hash,清理未引用工件或复用已发布的同 hash 工件;不会让 active revision 指向尚未发布的文件。
  • 状态事件写入 transactional outbox,与状态迁移同一 SQLite 事务提交;stream/UI 通知由 outbox dispatcher 幂等发布,不能由 command handler 直接 emit。这样断连、重放或前端失败不会回滚已确认的 CAD checkpoint,也不会导致重复 build。

6.3 几何验证

  • selector 必须来自当前 topology snapshot;零个候选报 selector_not_found,并列候选报 selector_ambiguous,不可默认取第一个。
  • 对“贯穿孔”建立 topology 断言:孔轴对应的圆柱面必须连通目标进/出平面;验证孔数、直径、位置/节圆和穿透方向。depth_mm >= body_thickness 只可作为 preflight 辅助证据。
  • 对需要“等效贯穿”的 hole_blindextrude_cut_blindpreflight 必须从实际宿主面/工作平面、切削方向和目标实体计算最小出口距离;不足则拒绝为 RUNTIME_PRECONDITION_FAILED。候选与最终阶段仍以拓扑连通性为最终结论,不能以参数名称或深度文字代替。
  • 多位置 hole_blind 在同一 host face、孔径和深度一致时必须允许为一个 action/一个 feature;不得被 review 层拆成四条虚假要求。
  • 全局不变量(单实体、显式尺寸等)在候选和最终重建两处都执行,二者使用同一函数;最终复核不得引用未初始化的局部变量。

6.4 验收 verifier registry

requirements-contract.json 中的每一个 acceptance_claim 必须引用一个注册 verifier。每个 verifier 是服务端代码,不是 LLM prompt,至少定义:

claim_kind
expected_json_schema
required_artifacts                # CDSL / rebuild report / topology / render
evaluate(current_revision) -> pass | pending | fail | unavailable
evidence() -> 结构化测量和工件引用

首批必须覆盖当前项目已能可靠观测的内容:

claim_kind 程序化证据
solid_count_equals CDSL-only rebuild 的 solid_count
bbox_dimension_mm rebuild bbox 指定轴和容差
cylindrical_bore topology 的圆柱面、直径、轴线和位置
through_cylindrical_bore bore verifier 加上入口/出口平面连通性
circular_hole_pattern 孔数、直径、节圆半径、角间距、宿主面与穿透状态
coaxial / coplanar topology 几何轴线、法向和容差
single_connected_body rebuild solid count 与连通性
visual 固定 render + 独立 reviewer;必须明确标为非确定性

每个 checkpoint 都计算所有 claims:尚未由前序几何满足的 claim 为 pending,已经被错误几何破坏的 claim 为 fail。候选不得因未来工作仍是 pending 而被拒绝;但如果动作引用的 requirement 已经被 fail、或任何全局 invariant 为 fail,候选必须拒绝。最终发布要求所有 deterministic claim 为 pass,所有 visual claim 获独立 reviewer pass。LLM reviewer 只能拒绝或为 visual claim 提供证据,永远不能把 deterministic fail 改成 pass

verifier registry 的注册也是可靠性边界:registry 启动时必须校验 claim_kind 唯一、expected_json_schema 为有效的 closed schema、required artifacts 可由当前 engine/rebuild 产生、evaluate 可序列化返回结构化 evidence。任何 verifier 在候选/最终运行时不可用都返回 unavailableVERIFIER_UNAVAILABLE,不得把 claim 静默转成 visual。

6.5 Provider conformance 与模型切换

切换模型不得修改 CAD runner、Pydantic 模型、Runtime contract 或 verifier。新增 provider/model 时先运行真实 API conformance suite,成功后才写入 model_capabilities

  • 固定 Pydantic schema:必填字段、enum、嵌套对象、数组上限、additionalProperties=false
  • 强制指定 tool 与模型返回多个 tool call 时的行为。
  • 每一个已注册 Runtime operation 的动态 fragment schema,至少验证 required params、forbidden params、requires_sketch 差异、selector token enum 和 const atomic_id
  • usage、timeout、429、断连、空 choices、无 tool call 和无效 JSON 的统一错误映射。
  • provider 的 strict schema、普通 tool calling、JSON mode 分别记录;只能选择实测通过的模式。

能力档案不通过时拒绝启动任务,返回 MODEL_STRUCTURED_OUTPUT_UNSUPPORTED。格式失败时允许有限次数的同 schema re-ask,错误信息只含 validator 的字段级结果;每次失败均不创建候选、不消耗 build 预算、不改变 revision。达到格式上限必须显式进入 FAILED_AUTHOR_FORMAT;只有 transport/限流等基础设施重试超限才进入 WAITING_RETRY。两者都绝不降级为自由文本执行。

6.6 架构、依赖与状态机边界

v3 采用 Ports and Adapters(六边形)架构、显式 command handler 和有限状态机。目的不是增加抽象层数量,而是让“LLM 选择下一动作”和“程序证明、执行、持久化该动作”在代码上无法相互越界。autonomous_cdsl_generation.py 当前同时承担 prompt、tool schema、状态迁移、CDSL materialization、文件读写、候选构建、review 和重试;v3 不得保留这种万能 service。

依赖方向只能由外向内:API/UI 与 adapter 可依赖 applicationapplication 可依赖 domain 与 portdomain 不得导入 FastAPI、LangChain、SQLite、文件路径、engine、renderer 或 settings。adapter 只能实现 port,不能直接改变 task state 或绕开 command handler。composition root 是唯一可以同时 import application、adapter 和 settings 的位置。

API / worker / stream
        -> application: command handlers + workflow coordinator
        -> domain: immutable state, transitions, contracts, policies
        <- ports: TaskRepository, ArtifactStore, ModelGateway, CadRuntime,
                  ReviewGateway, VerifierExecutor, EventPublisher, Clock
        <- adapters: SQLite/files, LangChain/providers, CDSL engine,
                     renderer, reviewer, outbox dispatcher

模块职责固定如下:

层级 模块/对象 允许做什么 明确禁止
domain TaskStatePendingActionRevisionOperationContract、claim/verifier policy、transition function 不可变 value object、跨字段规则、合法状态迁移、typed error/result I/O、网络、文件、SQL、prompt 拼接、选择下一 CAD action
application CommandHandlerWorkflowCoordinatorUnitOfWork 使用方、context assembler 接收已验证 command、读取 snapshot、调用 port、安排幂等 side effect、提交 transition/outbox 直接解析原始 LLM JSON、直接访问 SQLite/路径、按 operation 名称写参数规则、从 requirement 推导下一动作
ports Python Protocol/interface 声明 repository、artifact、LLM、runtime、review、event 等依赖的输入输出和 failure contract 保存业务状态、提供默认实现、泄漏 provider/engine 私有对象
adapters StructuredModelGateway、SQLite repository、artifact store、CDSL runtime、renderer/reviewer、outbox dispatcher 调用外部系统并翻译为 port 的 typed result/error 决定 workflow transition、修改 domain object、吞掉/重新归类内部异常
delivery FastAPI、worker、stream、frontend mapper 鉴权、请求/响应、启动 command、消费 outbox event CAD 规则、状态迁移、直接读写 task 文件

固定采用以下模式和约束:

  • Command + Result。 每个 state-changing tool 映射到一个 typed commandhandler 只返回 AcceptedRejected(typed_error)WaitingFailedInternal 这类结果。预期业务失败不以 Python exception 驱动控制流;adapter 未预期 exception 在边界转为 FAILED_INTERNAL 并携带 correlation ID。
  • 有限状态机。 持久化状态至少为 DRAFTING_REQUIREMENTSREVIEWING_REQUIREMENTSAWAITING_ACTIONACTION_PENDINGCANDIDATE_BUILDINGCANDIDATE_REVIEWFINAL_VALIDATIONWAITING_RETRYWAITING_FOR_USERCOMPLETEDFAILED。观察/测量是只读 command,不新增持久化 phasetool 可见性由 state、pending action 和 snapshot 派生,不能由 prompt 文本隐式决定。
  • Strategy + registry。 operation contract、semantic preflight 和 verifier 以已验证 registry entry 注册;不得以 if atomic_id.startswith(...) 在 runner 中散落规则。registry 选择由已验证 atomic_id 完成,不能演变为 service locator 或反射执行任意插件。
  • 不可变快照与乐观并发。 command 带 working_head、schema/contract hash、必要的 selector/reference snapshotrepository 以 task state version/head 做 compare-and-swap。冲突返回 STALE_WORKING_HEAD,不会合并或覆盖较新的 checkpoint。
  • Unit of Work + transactional outbox。 SQLite 是唯一状态提交点;工件、LLM、engine、renderer 等非事务性副作用通过 invocation/candidate staging 和 outbox 与状态机衔接,不允许“先更新 task.json,再希望文件/stream 成功”。
  • 依赖注入和 composition root。 handler 构造时显式传入 ports;测试替换为 in-memory/fake adapter。禁止 handler/validator 内部调用 load_engine()、读取全局 settings、创建 HTTP client 或直接 new WorkspaceStore

状态迁移必须集中在纯函数/transition table 中,并作为架构测试覆盖。一个 handler 的标准过程是:读取 immutable snapshot -> canonical/schema/state validation -> 注册或复用 invocation idempotency record -> 调用必要 port -> 以 expected state version 计算 domain transition -> 单一 Unit of Work 提交 state、ledger index、outbox。build/review 这类长时操作先持久化 processing invocation/candidate 状态,重启后从该记录恢复;同一 idempotency key 只能得到一个最终 result,不允许重新生成第二个候选。每一次 command、adapter call、candidate、review 和 outbox event 都记录同一 task_idrun_idinvocation_id、head/state version 的结构化 correlation fields;日志不得保存密钥、完整用户附件或未脱敏 prompt。

LLM 的回合管理也服从这个边界:WorkflowCoordinator 只根据当前 workflow state 请求 ModelGateway 输出允许的一个 structured command,然后交给对应 handler;它不分析 requirement 文本、不了解某个 hole 的字段,也不自行选择 operation。prompt/context assembly 是 application service,输入只能是 domain projection 和 port 返回的事实快照;operation schema 由 runtime contract adapter 提供。

为防止架构随时间退化,测试必须检查 import dependency rules、每个 port 的 adapter conformance、domain transition table、crash recovery/outbox 重放和并发 CAS 冲突。autonomous_cdsl_generation.py 只能在过渡期作为迁移入口;v3 发布前必须删除其中的业务实现,替换为薄 composition/compatibility-free bootstrap,不能只是把原函数移动到新文件。

6.7 真实 LLM 端到端评测与 Codex 执行门

provider conformance 只证明某个模型在小型、受控 schema 提示下能返回合法 tool arguments;它不能证明该模型在完整 requirements、动态 operation contract、真实 CAD 结果和多轮状态机中能稳定完成零件。因此 v3 必须提供可由 Codex 非交互执行的真实评测入口,并将其作为完成该目标与发布的硬门。实现本目标的 Codex 必须实际运行它、读取失败工件与诊断、修复可修复的实现缺陷后重新运行;不得只运行 mock/unit tests 后声称目标完成。

必须新增命令:

cd backend
python -m app.cad_agent.evals.live --suite release --require-live

该命令默认从当前 Settings 取得已选择的 author provider/model 和独立 reviewer provider/model;允许以显式、非秘密的 provider/model ID 覆盖,便于逐个验证已配置模型。凭据只从现有配置来源读取,CLI 参数、输出、工件和日志绝不回显密钥。它必须经由生产 StructuredModelGateway、生产 CadRuntime、生产 ReviewGateway、v3 WorkflowCoordinator、SQLite repository 与 ArtifactStore adapter 运行,测试代码不得替换 LLM、CAD engine、reviewer、状态机或动态 schema validator 为 mock/fake。唯一允许的隔离是每次评测创建临时 v3 SQLite 数据库和独立 artifact root,绝不读取、修改或发布普通用户 task。

命令开始时先以实际 provider 请求执行选定模式的 conformance preflightauthor 与 reviewer 均需成功。配置缺失、凭据无效、网络不可达、provider 限流、模型未通过 structured-output capability 或引擎不可用时,命令写出结构化 LIVE_EVAL_BLOCKED/对应 typed error 并以非零退出。--require-live 禁止任何 skip、离线 fallback、mock fallback 或把 WAITING_RETRY 记为通过。只有用户显式选择不执行 live eval 的开发场景才允许 --allow-skip;该模式产生 skipped,永远不满足本目标的完成或发布验收。

评测分层以控制成本但保留真实覆盖:

  • smoke:矩形底板和简单法兰各一次,用于 Codex 在完成高风险改动后快速验证真实 author/reviewer/engine 串联。
  • release:矩形底板、法兰、带肋和安装孔的支架、含 face/edge selector 的修饰特征;每个场景至少连续运行三次,以独立 task/run 执行。任务需求、units、验收 claims、最大 author/reviewer turn 数、最长 wall time、总 token/调用预算和期望终态作为版本化 fixture 保存在仓库。
  • 新增或修改 operation contract、selector/reference policy、verifier 或动态 schema 时,release 还必须包含该 operation 的最小真实生成场景;不能只补 unit fixture。

每个 live run 的成功只取决于当前 revision 的可验证结果,不取决于 LLM 是否恰好选择某个预期 feature sequence。它必须:完成到 COMPLETED、通过全部 deterministic claims 和必要 visual review、生成可读取的 immutable artifacts;无 FAILED_INTERNALNO_PROGRESS_LIMIT、未终止 running、重复 revision、重复 complete/build invocation 或未分类异常;所有 state-changing LLM 输出均有 raw-arguments hash、canonical validation、head/contract/snapshot binding 的审计记录;任何格式拒绝均在候选创建前发生。reference happy-path fixture 的 schema/decision rejection 计数必须为零;若出现,即使系统后来恢复,也视为 live quality failureCodex 必须报告字段级原因并调整 schema/context/contract 或模型 capability,而不能隐藏为普通重试。

每次运行写入 live-evals/<run_id>/report.json 和链接到隔离工件的 manifest。报告至少包含:git revision、protocol/contract/verifier 版本、author/reviewer provider+model ID、实际 structured-output mode、每场景和每重复的最终 lifecycle、typed failure、所有 invocation/candidate/revision IDs、每个 claim 结果、schema rejection/重试/rollback 计数、token usage/上下文字节/耗时、预算是否超限,以及脱敏后的 correlation ID。保存 JSON summary、ledger、CDSL、拓扑、rebuild/verifier evidence 和 reviewer verdict;禁止保存密钥、完整未脱敏 prompt、附件原文或 provider 响应中的敏感 metadata。

Codex 的最终交付必须在结果中逐项说明实际执行的 live command、author/reviewer model、通过/失败场景、可定位的 report/artifact 路径、token 用量与任何失败的根因。发生网络/凭据等外部阻塞时,Codex 必须明确报告 LIVE_EVAL_BLOCKED,而不是宣称真实模型质量已验证;这会阻止把本目标标记为完成。运行有成本,因此开发中先跑相关 smoke,但实现完成前必须运行一次无 skip 的完整 release suite。

7. Token 优化目标与实现规则

优化优先级是减少无效轮次,其次再压缩每轮上下文;不能通过删除必要的运行时合同或独立复核来换 token。

  1. 删除新任务的大型 modeling-plan.md、它的 parser、一次或多次计划 review 和重写循环。
  2. requirements contract 由最多 8 项的结构化 batch 构成;requirements.md / completion.md 由服务端渲染,作者不再生成或重写 Markdown。复核通过后,建模循环不再重复发送 source-requirements.md,只发送冻结 contract 的紧凑摘要、requirement/claim ID 和未完成状态。最终复核仍发送 source,以防冻结 contract 遗漏源需求。
  3. 每轮作者上下文固定为:冻结 requirements、ID/coverage 摘要、当前模型紧凑测量、pending action 或最近动作摘要、最近一次相关错误、Runtime operation 名称。只在 LLM 调用 inspect_topology 后附带当前 selector token bank,只在调用 contract 后附带该 operation 的精确 schema。
  4. 一次 LLM 回合最多执行一个 tool call;每个候选只允许一个 feature。此约束已经存在,必须保留。
  5. tool 结果按结构化摘要持久化,prompt 只保留最新且仍与当前 working_head 有关的内容;历史完整证据在工件/账本中按需读取。
  6. batch_goal、plan step/action 文本和 author self_review 从反复 prompt/调用中删除,改为服务端引用 pending action。
  7. 记录每次 author/reviewer 调用的 provider usage.prompt_tokensusage.completion_tokens(支持时)、序列化 context 字符数、工具名、重试原因和缓存命中。没有 usage 的 provider 使用 context 字符数作为次级指标,不伪造 token 数据。

验收指标以一组固定代表任务为准:矩形底板、简单法兰、带肋和安装孔的支架、含 selector 的修饰特征。与当前协议对比,目标是:

  • 计划相关作者/审查调用降为零;
  • 无失败的常规零件中,每一检查点只发生一次作者 fragment 调用和一次独立 candidate review
  • 无副作用格式错误不进入候选构建、不创建 revision;
  • 因内部异常产生的重复完成调用为零;
  • 总 author+plan-review prompt tokens 的中位数下降至少 30%,同时完成率、最终复核通过率和几何断言通过率不低于基线。

30% 是初始验收线,不是凭空承诺。实现前须在现有协议上记录相同任务集的实际 usage,实施后以同一模型、温度、运行时版本和需求文本复测。

8. 实现范围与顺序

P0:立即修复和回归(可直接实施)

  • 保留已修复的 _final_review global_violations 初始化。
  • 让未预期异常进入 FAILED_INTERNAL;不要走 _fragment_diagnostic 或增加 no_progress
  • complete_task 加 revision-scoped idempotency,排除内部/基础设施错误对 NO_PROGRESS_LIMIT 的影响。
  • 将 author transport fallback 改为有界状态机:每 provider 有限重试、最多一次 provider failover、全 run 总预算和指数退避;超限后进入 WAITING_RETRY,绝不保持 running 无限循环。
  • 修复 modeling-plan revision-limit 的后检查控制流,直到 P2 完成前也不得出现“报上限后继续写计划”。
  • 添加最小测试:最终审计全局不变量、内部错误只失败一次、同 revision 完成调用幂等、法兰四位置 hole_blind 单 feature 允许、贯穿孔拓扑断言。

P1:文档先复核后冻结(可直接实施,独立于 P2)

  • 建立 v3 domainapplicationportsadapters 包边界与 composition root;先迁移 requirements draft/review 这条窄路径作为样板。新增代码不得继续写入 AutonomousCdslGenerationRunner,也不得让 domain import 当前 services/engine/storage。
  • backend/requirements.txt 显式加入并锁定兼容的 Pydantic v2 与 LangChain core / 已配置 provider integration 依赖;adapter 需要保留 raw_arguments_json(固定 schema 可使用 with_structured_output(..., include_raw=True) 或等价 raw tool-call 模式),不能只接收 LangChain 已解析的对象。依赖升级必须通过现有 API、timeout 和 usage 回归测试。
  • 新增 Pydantic RequirementsDraftBatchRequirementsPatchBatchRequirementsReview 和空参数 finalize tool,由 cad_agent/adapters/structured_llm.py 的 LangChain adapter 调用,并在服务端原始 arguments 上二次验证。每 batch 最多 8 项,禁止 Markdown 写入工具。
  • TaskRepositoryArtifactStore adapter 增加 source index、requirements JSON draft、requirements contract、review 和 render API;不得覆盖冻结 contract 或由 Markdown 反向读入状态。
  • 实现 verifier registry、每种 claim 的 expected dynamic oneOf schema、registry integrity check 和 requirements-contract.json renderer;缺少 verifier 的可测需求必须明确失败。
  • 在 runner 中替换“首次写入即 freeze”为结构化草稿状态机;复核失败有明确修改次数,达到上限时 WAITING_FOR_USER,不能无限重试或静默降级。
  • 冻结 contract 后一次性生成 requirements.mdcompletion.mdrequirements-index.json

P2:以单动作协议替换建模计划(主要改动)

  • 实现第 6.6 节的 finite state machine、typed command/result、port interfaces、Unit of Work、invocation idempotency、candidate staging/immutable publish 和 transactional outbox;先通过 domain/handler 测试,再接入真实 LLM、runtime 与 UI adapter。
  • 新增固定 Pydantic NextActionGeometryConclusionRollbackCheckpointCandidateReviewFinalReviewautonomous_tools() 仅暴露第 4.7 节列出的严格结构化工具,移除 write_modeling_planskip_satisfied_plan_step、自由 self_review 和 plan 专属字段。
  • _author_tools()_prompt_messages()_execute_tool() 拆为 context assembler、LLM turn coordinator 与独立 command handlercandidate metadata、coverage、repair 路径使用 pending action/ledger/claim result,不再读取或写入 modeling plan。handler 不得直接 import file/SQLite/provider/engine implementation。
  • profile_schema.json 中的 feature contract 升级为完整 versioned operation contract registryauthor param JSON Schema、fragment shape、selector/reference policy、server injection、semantic-preflight 和 verifier binding 都由此处声明。删除 cdsl_authoring_schema.pycdsl_fragment.pyautonomous_cdsl_generation.py 中按 operation 名称/前缀推断 params、selector 或默认 pattern source 的兜底规则。
  • submit_cdsl_fragment 从完整 feature_atomic_contract 生成并绑定动态 schema;不得用一个宽松通用模型容纳不同 operation 的 params、sketch、selector、reference 或注入字段。schema 必须使用当前 snapshot 的 token enum,而不是任意 string 后补检。
  • candidate/final 先执行 verifier registry,再调用结构化独立 review;ReviewGateway 接收 action card、claim IDs 和只读验证结果,而非 plan_step/plan_action。requirements review 是独立的 application command handler,不把它伪装成 completion Markdown review。
  • complete_task 无参数;最终完成门检查所有 claim、pending action、repair 与最终复核。
  • 增加 provider/model conformance suite 和 model_capabilities 持久化;不通过时禁止启动。
  • 设计并实现 SQLite 状态层、账本 append 和幂等事务;文件工件由独立 ArtifactStore adapter 管理。

P3:删除旧协议、API 和 UI

  • 将任务 schema 直接升级为 3.0;不实现 2.0 迁移器、只读读取器或恢复逻辑。旧任务目录不由运行时扫描、打开或恢复,可在部署前由运维单独归档。
  • 删除 AutonomousCdslGenerationRunner 的巨型实现及其 module-global helper 状态;入口仅负责 dependency composition 和发起 WorkflowCoordinator。旧 WorkspaceStore 不能继续同时是 repository、artifact store、task JSON writer 和状态机。
  • WorkspaceStore、runner、API、前端类型和测试中删除 modeling_plan_*、plan step/action、write_modeling_planskip_satisfied_plan_step 及其 Markdown parser/reviewer。新协议中不得保留隐藏 fallback、遗留 tool 参数或分支。
  • GET /v1/tasks/{id} 和前端 cad-types.ts 替换 modeling-plan 字段为 requirements contract/review、claim summary、pending action、action ledger summary 和 protocol version;不再有 completion Markdown review 字段。
  • agent_service.pycad-stream.ts 删除“建模计划 / 计划独立复核 / 计划步骤已满足”事件,增加“需求合同独立复核 / 动作选择 / 候选独立复核 / 最终独立复核 / 动作账本”事件。
  • 前端显示事实和状态,不能把 ledger 误显示为 LLM 的未来计划。

P4:验证与发布门

  • 单元:所有固定 Pydantic model 的 valid/invalid fixtures、每个 Runtime operation 的动态 schema fixture、operation mismatch、stale head、selector ambiguity、single multi-position hole、through topology、每个 verifier、ledger/transaction/idempotency、typed errors。
  • 架构:domain transition table 的全部合法/非法状态边、每个 command handler 的纯 result、port adapter conformance、dependency-rule test、SQLite CAS 冲突、staged artifact crash recovery、outbox 至少一次投递与消费者幂等;不得依赖端到端 LLM run 才发现状态机错误。
  • 集成:每个配置 provider/model 的真实 conformance suite;实现过程中按第 6.7 节调用真实 LLM smoke,并在完成前由 Codex 实际执行 python -m app.cad_agent.evals.live --suite release --require-live。release 报告必须保存匿名化调用指标与工件路径;分别覆盖成功、格式拒绝、候选拒绝、verifier fail、review service 失败、内部异常。任何 LIVE_EVAL_BLOCKED、skip、预算超限或场景失败均阻止发布,不能以 mock/integration test 替代。
  • 回归:全量 backend 测试、前端类型/stream 测试,以及不识别旧任务 schema 的拒绝测试。
  • 发布:一次性切换到 v3;部署前停止旧 worker 并归档旧任务目录。上线后删除 v2 plan 生成路径、parser/reviewer 和全部关联测试,不保留 feature flag 双轨或历史工件读取能力。

9. 主要代码触点

位置 必须修改
backend/app/services/autonomous_cdsl_generation.py 删除巨型 runner 的业务实现;迁移期间只可作为入口 shim,v3 发布前移除,不能继续承载状态、CAD、LLM、文件和复核逻辑
backend/app/cad_agent/domain/*.py(新增) 不可变 task/action/revision value objects、workflow state/transition table、operation/claim policy、typed domain result/error;无任何 I/O import
backend/app/cad_agent/application/*.py(新增) command schemas 到 domain command 的转换、command handlers、workflow coordinator、context assembler、Unit of Work 使用;不直接依赖 adapter 实现
backend/app/cad_agent/application/llm_contracts.py(新增) Pydantic v2 固定 LLM input/output DTO;只负责 schema,不包含 persistence、Runtime 或 transition 规则
backend/app/cad_agent/ports.py(新增) TaskRepositoryArtifactStoreModelGatewayCadRuntimeReviewGatewayVerifierExecutorEventPublisher 等 Protocol 与 typed failure contract
backend/app/cad_agent/adapters/*.py(新增) SQLite/file、CDSL engine、render/review、provider、outbox 的 port 实现;所有外部异常在此映射为 typed adapter error
backend/app/cad_agent/adapters/structured_llm.py(新增) 唯一 LangChain provider adapter;固定 Pydantic 和动态 JSON Schema 调用、原始 arguments 捕获、canonical 二次验证入口、provider capability mapping;不含 CAD 状态机
backend/app/cad_agent/evals/live.pybackend/app/cad_agent/evals/fixtures/*.json(新增) 非交互真实 provider/engine/reviewer release runner、版本化场景/预算/claim fixtures、隔离 SQLite/artifact root、脱敏 report/manifest--require-live 时任何 skip 或 fake adapter 都必须失败
backend/requirements.txt(及实际使用的 lock file 显式 Pydantic v2、LangChain core 和对应 provider integration 的兼容范围;不能依赖 FastAPI 间接安装的 Pydantic 版本
backend/app/cad_agent/application/requirements_review.py(新增) 结构化 requirements review command handler、coverage gate、draft patch feedback;不解析或写入 Markdown
backend/app/cad_agent/domain/verifier_registry.py(新增) claim schema registry、contract integrity、针对 typed verification facts 的纯 deterministic evaluator;启动时拒绝不可用 verifier
backend/app/services/cdsl_authoring_schema.pybackend/app/services/cdsl_fragment.pybackend/engine/cdsl_engine/profile_schema.json 迁移为 CadRuntime adapter 的完整 versioned operation contract、dynamic fragment schema、selector/reference resolver、semantic preflight;删除按 atomic ID 的重复/开放式 author schema 和默认 source 注入
backend/app/services/storage.py 拆分为 SQLite TaskRepository/UnitOfWork adapter 与不可变 ArtifactStore adapter;加入 invocation、state version、candidate staging manifest、ledger index、outbox;删除 task.json 权威状态和 v2 兼容
backend/app/services/visual_review.py 迁移为 ReviewGateway adapteraction-based candidate/final review,不再承担 requirement 或 completion Markdown review
backend/app/services/agent_service.py delivery/worker adapter,只启动 WorkflowCoordinator、记录 usage 并消费 typed result;不得重试内部失败为 author turn
backend/app/settings.py protocol version、文档修订上限、action/context/usage 配置;删除 plan 配置
backend/app/main.py API 输出 v3 文档审核和动作账本摘要
frontend/src/lib/cad-types.tsfrontend/src/lib/cad-stream.ts 新事件与字段,删除 plan 特有状态
backend/tests/*frontend/src/lib/*.test.ts 删除 v2 plan 行为测试,新增 P0-P4 回归

10. 需要确认的架构决策

以下是本目标已作出的绑定选择,不留作实现期间临时决定:

  1. 采用 SQLite 作为 v3 可变状态的唯一权威来源。 当前 task.json/agent-state.json 的文件读写无法为 checkpoint、pending action、幂等调用和 ledger append 提供真正的原子事务。保留 JSONL 账本和文件工件,但它们不是可变状态源。代价是 WorkspaceStore 持久化层重构;这是达到可靠性目标的必要改动。
  2. 不兼容旧任务。 不应把已有 modeling-plan.md 任务转换为 pending action,因为无法无歧义地映射历史计划状态;v3 运行时只识别新协议工件。
  3. 建议把无法可靠消除的需求歧义显式置为 WAITING_FOR_USER 对“简单法兰”一类可合理假设的请求,LLM 仍可写明假设并继续;只有冲突、关键基准/尺寸导致多种同等合理且会明显改变模型的情况才暂停。
  4. 采用第 6.6 节的六边形边界和显式状态机。 这不是可选重构或文件整理;不允许以“赶进度”为由把 Runtime/LLM/SQLite 直接重新接回 workflow handler。

11. 非功能验收

实现完成时必须能证明:

  • 法兰任务不会因 global_violations、重复 complete_task 或 plan revision limit 失败;最终复核若故障,任务保留 rev_003 类的最后健康 checkpoint 和精确错误类别。
  • LLM 看到 requirements、coverage、当前模型和账本摘要后,自己提出“下一动作”;服务端日志可证明它没有自动替 LLM 推导该动作。
  • hole_blind 的四个同宿主位置作为一个 action/feature 通过,中心/螺栓通孔通过最终 topology 断言而非仅靠盲孔深度文字。
  • 任意 action proposal 或 CDSL 格式错误均不产生 revision、不改变 active head、不消耗候选构建预算。
  • 每个接受的 checkpoint 都能从 ledger 追到 author intent、真实 atomic/fragment hash、selector snapshot、独立复核和 coverage 证据。
  • 静态 dependency-rule test 证明 domain 不导入 FastAPI、LangChain、SQLite、文件、engine、render 或 settingsapplication 不导入 adapter 实现。状态迁移只存在于 domain transition table/command handlerAPI、stream、adapter 和 reviewer 均不能直接写任务状态。
  • 进程在 candidate build、artifact publish、SQLite commit、outbox dispatch 或 stream publish 的任一点终止后,恢复测试均证明:系统要么保留原 checkpoint,要么通过同一 invocation/manifest 完成一次提交;不会出现公开半工件、双 revision、重复 build 或丢失已提交 ledger event。
  • 所有会改变状态、影响 CAD 执行或作为验收依据的 LLM 输出均对应第 4.7 节的一项 canonical schema,并在状态变更前通过 schema、state binding 和适用的 domain validator;不存在 Markdown/自由文本/开放 object 的旁路。
  • 每个 Runtime operation 均通过完整 contract integrity、valid/invalid dynamic-schema fixture、selector/reference snapshot、semantic preflight 和 engine-execution 测试;缺少参数、无参数、草图、非草图、required/forbidden selector 和 nested option 的差异均由 schema 而非 prompt 表示。
  • task 开始前,选定 provider/model 在全部固定 schema 与每个已注册 dynamic operation schema 的真实 API conformance suite 中通过;未通过只报 MODEL_STRUCTURED_OUTPUT_UNSUPPORTED,不允许回退为自由文本。
  • 实现目标的 Codex 已实际运行第 6.7 节的无 skip release 命令,使用当前配置的真实 author/reviewer 模型、真实 CAD engine 和 v3 状态机完成固定任务集三次重复;结果报告和工件 manifest 可定位,且没有 LIVE_EVAL_BLOCKED、失败场景、预算超限或隐藏的 schema/decision rejection。
  • 发布前全部 deterministic claim 必须以当前 revision 的程序化 evidence passLLM review 只作为 visual/语义的独立补充,永远不能覆盖 failunavailable
  • P4 固定任务集给出实施前后真实调用指标,满足第 7 节的可靠性及 token 目标。