立项策划:落地 M1C-0 合入复核结论,三条 M1C-1 前置与一条哨兵订正
生产代码零改动(delegation.rs 三个 hunk 全在 mod tests 内),本次只补回归与文档。 复核确认「今天行为零变化」成立且可证:contract_status 生产赋值点只有两处且都从 客观事实派生;StaticDelegateClaimRecord 全仓库唯一构造点是运行时构造,不是 agent 提交的 JSON;durable sidecar 在 .agent/runtime/** 下被 file_ops 与 filesystem 各 三处拒写;前端无 contractStatus 消费者。lineage 三个 fail-closed 出口全部返回 (u32::MAX, u32::MAX),新分支的哨兵检查接得住。 三条 M1C-1 前置写进技术方案第 23.7、23.8 节与 decision-log: ① UserRevisionRequested 不进 repair_required_count / user_input_required_count 任一 barrier,写入方落地即意味着 Supervisor run 可在用户修订未派出时完成; ② validate_static_delegate_structured_result 对该变体只有否定约束,缺正向一致性 分支,UserRevisionRequested + failed + 缺产物 能通过校验落盘; ③ 前向兼容失败粒度是整个子系统——list_static_delegate_deliveries_at 逐条 ? 上抛, 一条解析失败即整个目录枚举失败。bump schema version 救不了(版本校验在 parse 之后)。 文档订正:STATIC_DELEGATE_LINEAGE_MAX_HOPS = 32 限的是链上节点数不是跳数 (判据排在入链之前),真实跳数上限 31,第 23.7 节原写 32 跳已订正。 测试: - static_delegate_user_revision_preserves_existing_clarification_round 名不副实, 它把 UserRevisionRequested 放在目标位置,而计数循环只遍历父节点集合,新分支 从未被执行。改名为 ..._parent_hop_preserves_depth_and_clarification_round,补 一跳真正以用户修订为父的续跑并加反证;原断言留作对照组并注明性质。 - 新增 concurrent_user_revision_dispatch_creates_exactly_one_delivery,父节点为 UserRevisionRequested 且 depth 已为 1,两侧同时钉住并发下恰好放行一条。 - user_revision_continuation_... 补兄弟检查断言(depth 门对用户修订失效后,它是 该路径上唯一剩下的扇出约束)。 变异测试:摘掉 counters 分支 4 条变红(含新增反证 left (2,0) / right (1,1)); 摘掉 gate 分支 3 条变红(并发用例 left 0 / right 1)。两处守卫各自有回归覆盖。 验证:定向 41 passed / 0 failed;npm run check:encoding 通过(5374 files); git diff --check 干净。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,18 @@
|
||||
# 决策记录
|
||||
|
||||
## 2026-08-14 M1C-0 合入复核:三条 M1C-1 前置、一条文档订正、一条已排除假设
|
||||
|
||||
合入 `M1C-0`(见本文件同日条)后对该包做整组复核。**结论:包本身可合,「今天行为零变化」成立且可证**;但新变体在 `M1C-1` 写入之日会同时点亮三个默认值,而这三个默认值都不是裁决出来的,是「给用 `==` 比较(而非穷尽 `match`)的 durable enum 加变体,编译器不报,新变体静默落到作者没想过的那一侧」的结果——与本文件「修复 M1A-2 引入的回归」条同源,是同一失败模式的第二次出现。(复核完成后 `M1B-2` 已合入;其对 `delegation.rs` 的改动是 rustfmt 换行、无语义变化,本条结论不受影响。)
|
||||
|
||||
- **不可达性已实证,不是靠注释。** `contract_status` 的生产赋值点只有两处(终态回执构造与 `build_static_delegate_structured_result_at`),都从客观事实派生(终态、缺失产物、verification、问题数),模型选不了;`StaticDelegateClaimRecord` 全仓库**唯一**构造点在 `delegation.rs` 的 claim 准备路径,是运行时构造而非 agent 提交的 JSON,所以「claim payload 自带 `contractStatus`」这条路不存在;durable sidecar 位于 `.agent/runtime/delegation-deliveries/`,被 `is_agent_runtime_private_control_path` 覆盖,`file_ops.rs` 与 `project/filesystem.rs` 各三处拒绝写入;前端无 `contractStatus` 消费者。哨兵侧同样成立:`static_delegate_lineage_counters` 的三个 fail-closed 出口(成环、超长、上游缺失)**全部**返回 `(u32::MAX, u32::MAX)`,两个分量都是 MAX,新分支的 `== u32::MAX` 检查全接得住;合法累加上限 31,不会误触。
|
||||
- **前置一:新变体不进任何 barrier。** `repair_required_count` 的判据是 `== NeedsRepair || (== NeedsUserInput && 有澄清答案)`,`user_input_required_count` 要求 `== NeedsUserInput`,`UserRevisionRequested` 两边都不落,因此 `barrier.is_clear()` 可能为真——`M1C-1` 写入方一落地就意味着 **Supervisor run 可以在用户修订尚未派出时完成**。同源的还有 `swarm_cli/terminal_classification.rs` 的 `static_delegate_delivery_has_repairable_contract`(`is_none_or(|r| == NeedsRepair)` → 新变体判为不可返工,影响面小但同样是默认选的)。`M1C-1` 须显式裁决补或不补。
|
||||
- **前置二:`validate_static_delegate_structured_result` 缺正向一致性分支。** `EvidenceReady` 有(终态/产物/verification 对账),`NeedsUserInput` 有(问题数 + 指纹),`UserRevisionRequested` 只继承了「不得携带 `user_input_questions`」这条否定约束,于是 `UserRevisionRequested + terminal_status="failed" + 缺产物` 能通过校验落盘。`M1C-0` 新增的 real-gate 回归恰好依赖这一点才能构造 fixture。
|
||||
- **前置三:前向兼容失败的粒度是整个子系统,不是单条记录。** `list_static_delegate_deliveries_at` 对每条 sidecar 用 `?` 上抛,一条解析失败即整个目录枚举失败,barrier、lineage、返工校验、run status 投影同时不可用。`M1C-0` 有意不 bump `STATIC_DELEGATE_DELIVERY_SCHEMA_VERSION` 且把「未知状态 serde 直接报错」记为安全属性——该性质成立,但**粒度当时没写**。注意 bump 版本号救不了:版本号校验排在 serde parse 之后。三条均已写进技术方案第 23.7 节「落地约束」与第 23.8 节 `M1C-1` 行。
|
||||
- **文档订正:`STATIC_DELEGATE_LINEAGE_MAX_HOPS = 32` 限的是链上节点数,不是跳数。** 判据 `chain.len() >= MAX_HOPS` 排在入链之前,故链最多 32 个节点 = **31 跳**。第 23.7 节原写「真实上限就是 32 跳」,已订正为 31。产品阈值 16 远低于两者,不受影响;`M1C-0` 自己的测试注释(「32 条 delivery(31 跳)」)一直是对的。之所以要订正:`M1C-0` 之前 `depth=1` 才是主刹车,用户修订路径上现在只剩这个哨兵,写错的数字从此是承重的。
|
||||
- **已排除的假设,后续不要重走。** 怀疑过「派一个子委派 → 抑制 → 再派一个」可绕开兄弟检查、在用户修订父节点下无限扩宽度。打不通:`suppress_static_delegate_delivery_at` 对 `ClaimedByParent` 直接原样返回、拒绝抑制,且生产侧唯一调用者是 `suppress_static_delegate_deliveries_for_parent_terminal_at`(父 run 终态清理),彼时同一 `parent_run_id` 已不能再派委派。另确认新分支**没有**跳过兄弟检查:if/else-if 链在前、兄弟检查在后且无提前返回,扇出仍是一条。
|
||||
- **测试侧本次一并处置。** ① `static_delegate_user_revision_preserves_existing_clarification_round` 名不副实:计数循环只遍历 `chain[..len-1]`(父节点集合),目标自身 status 从不参与判定,而该用例把 `UserRevisionRequested` 放在了**目标**位置,新分支根本没被执行。已改名为 `static_delegate_user_revision_parent_hop_preserves_depth_and_clarification_round`,补一跳真正以用户修订为父的续跑,并加反证(同一条链只把该父节点改回 `NeedsRepair`,结果必须变成 `(2, 0)`);原断言保留为对照组并注明其性质。② `user_revision_continuation_passes_real_gate_at_depth_one_but_stays_single_child`(原 `static_delegate_user_revision_requested_continuation_...`)补兄弟检查断言。③ 新增 `concurrent_user_revision_dispatch_creates_exactly_one_delivery`,与既有 `project_supervisor_concurrent_repair_dispatch_creates_exactly_one_delivery` 同构但父节点为 `UserRevisionRequested` 且链上 depth 已为 1,两侧同时钉住:并发下恰好放行一条,且不是零条(新分支被删则两条都会被 depth 门拒,用例变红)。
|
||||
- 教训(与 `M1A-2` 回归条合看):**给用 `==`/`!=` 比较的 durable enum 加变体,等于在每一个比较点上替作者做了一次没人复核的裁决。** 这类 PR 即使「无写入方、行为零变化」也必须逐个枚举比较点并写下每处落点,否则这些默认值会在写入方落地的那个 PR 里一次性生效,而那个 PR 的复核者只会看它自己的 diff。
|
||||
|
||||
## 2026-08-14 M1B-2 实现合同收口:Provider binding、结构化注入与提交恢复边界
|
||||
|
||||
- **状态与基线**:`M1B-1` 已通过门禁并合入,作为 `.agent/planning/` storage 基线;`M1B-2` 工作包已通过本包门禁并以 `27c3eb847` 合入本分支。当前包接 `plan.submit_gdd`、exact planning Provider 请求身份、提交点和恢复;`gdd-approval` planning pending、审批等待、receipt、审批命令与 UI 继续属于 `M1C-1` 及之后。本状态只表示 M1B-2 工作包完成,不表示完整产品可交付。
|
||||
|
||||
Reference in New Issue
Block a user