Files
Agent-System-Documents/docs/proposals/2026-10-07-agent-stack-n1q1i1-plans.md
weichen ec5114d621 Backfill N1/Q1/I1/I2 stage status and scope differences
Why: The planning index listed the stage-record reconciliation as the
preferred next task: N1 WP6b/6c transfers, the Q1 platform-task vs
squad-run boundary, I1 reserved command consumption, and the I2 card's
dangling reference all feed N2/Q3 and RDM dependency judgments.

Evidence: Dev merges #230/#231/#234/#235/#237/#240/#242 verified in
main via git log --merges on 2026-10-08; stage claims are SELF-level
card statements, explicitly not replayed; intent command.go:18-25/78-84
checked for the Cancel/Handoff ruling.

Impact: Adds a status-backfill section (SS7) to the N1/Q1/I1 plan with
per-item done/transferred/todo ownership, an I2 status note in the
stack completion plan (the sole I2 main record), and INDEX navigation
updates; registers the truncated Q2/Q3 archive lines as a new open
item.

Refs: Dev task feature/agent-stack-stage-records; planning index
"next-step" recommendation (2026-10-08).
2026-10-08 06:28:19 +00:00

44 KiB
Raw Permalink Blame History

N1 / Q1 / I1 实施方案:内核 harness、图执行、命令化识别

状态:proposed(2026-10-07);owner:weichen;主任务:Dev 仓 feature/agent-stack-n1q1i1-plans。 上游:2026-10-02-agent-stack-completion.md §5 分期(下称「总提案」,行号以该文件为准);审计:2026-10-02-agent-stack-audit.md。 规范依据:Development-Guidelines(workflows/delivery.md、standards/collaboration.md、standards/agent-execution.md、standards/verification.md);本文是项目级消费,不复制其正文。

本文把总提案的 N1、Q1、I1 三个阶段落成可启动的实施方案:现状基线、工作包分解、文件级落点、测试与验收、风险。本文不实施代码;三个阶段的实现各走各的任务(总提案「每阶段单独任务」)。


1. 共同基线与三任务协调

1.1 现状基线(撰写日实测)

仓 pin 说明
Agent-Native 3a110a728cf520cfbbbafc0c4c75f14bf78bec3f durable-rewind-3 与 permission-hooks(PR #173)之后
Agent-Squad 5a57636cc0b8426a86a72bbbdd5b7f30e4fcac88 同上
Agent-Intent 65aaebca1ea69ab7d48eda51d33ef1d4eea5a0bf agent-stack-d1(R2)之后
Backend e7fb276ee9b3af51329a0c6df27517184b26edee v0.1.0-4
Core 0b5c7747a3165bf0d0f2219204b7b70ec3ed7645 v0.1.0

两个要点:

  • 审计基线已旧。审计写于 native c6d867c / squad 590fd86;R1/R2 之后多条审计项在当前 pin 已修(native 侧 N1/N7/N8/N21/N22/N30/X4,squad 侧 Q1–Q5/Q7/Q14–Q16/Q18/Q19)。本文逐节标注「已修 / 仍开放」,实施时不得以审计原文为唯一依据,须以当前代码为准。
  • D1 的借力点已成:三库核心互不依赖(native go.mod 只依赖 error-code-system 与 logging-system)、Options 已按端口拆分、跨库类型只出现在 adapters 子模块。N1/Q1/I1 都假设这个地基,不再返工。

1.2 分支与合入协调

按 AGENTS.md「同批互不依赖的子任务用同一 R0 的兄弟分支」:

  • 三个任务分支:feature/agent-stack-n1、feature/agent-stack-q1、feature/agent-stack-i1,从同一权威 origin/main(同一 R0)切出,互不嵌套。
  • 每个任务的 PR 链固定为三段、按序合入:库仓 PR → Backend 仓 PR(bump 嵌套 pin + 适配)→ Dev 仓 gitlink PR(bump 顶层 pin 与 modules/backend)。R0 已落地的检查脚本核对 Backend deps/ 与 Dev 指针一致,不允许只推一层。
  • 三任务并行时的冲突面:N1 与 I1 都动 Backend(N1 在 internal/app、internal/runtime、internal/runmgr;I1 在 internal/server、internal/intentgate、internal/runmgr),internal/runmgr 是唯一重叠文件,后合入者按 make task-sync 并入最新 main 后解决;Dev 仓 gitlink pin 同理,后到者 sync 后重指。
  • Q1 若涉及 modules/backend/internal/squadadapter 消费方适配,改动限制在「驱动循环跟上新引擎 API」范围内;编排收敛(WorkflowDef 编译、internal/workflow 退役)是 Q3,不在 Q1。

1.3 共同验收纪律

  • 每阶段都带 E 评测(总提案 §5 E 节):Native 的对照用脚本化模型输出,不把模型自报当通过。
  • 证据按 AGENTS.md「证据与验证门禁」:完成声明的 precheck / task-sync / 测试三段输出由 make evidence 写入任务卡;测试通过的权威源是 CI(PR HEAD 上 make test+make build),本地输出是 SELF 级辅助线索。
  • 各阶段验收条款在本文 §2.6 / §3.6 / §4.6 给出机器可核对的形式,与总提案对应条目逐条映射。

2. N1 内核 harness

总提案原文(§5 N1):「AgentSpec、HookBus、PermissionPolicy、三类 guardrail。CompletionGate 与提醒从 Backend 下沉。adapters/native 透传钩子。Backend 改为消费,A/B 对照直连行为。」

2.1 现状与 gap

需求项 现状(证据) gap
AgentSpec 不存在(全库无此类型)。最接近的是 deps/agent-native/runtime/subagent/subagent.go:21-33 的委派 Request(Goal/Inputs/WriteScope/NonGoals/DoneCriteria/Deliverables + Deadline/MaxToolCalls);backend 子代理画像是 prompts.SubagentSpec + fallbackSubagentSpec(modules/backend/internal/runtime/sub_loop.go:18-27) 类型、文件格式、插件校验入口全缺
HookBus 已有:runtime/hooks/hooks.go:56-107(On/Emit,决策优先级 block/deny>ask>modify>allow)。事件枚举 hooks.go:9-20 有 SessionStart/UserPromptSubmit/PreToolUse/PermissionRequest/PostToolUse/PostToolUseFailure/Stop/SubagentStart/SubagentStop/PreCompact。实际发射点只有 3 处:runtime/loop.go:512(Stop)、:532(PreToolUse)、:557(PostToolUse/Failure) 缺 PostToolBatch、SessionEnd 两个事件;6 个已枚举事件无发射点;无「已在续跑中」防递归标志(hooks.go:33-43);Ask 决策被当拒绝处理(loop.go:534-540),无 ask→宿主审批→放行回路
PermissionPolicy 以函数式存在:runtime/policy/policy.go 三档 Mode(:9-13)、Rule(:30-34)、Decide(:55-93,deny>计划禁写>本会话放行>ask>auto_edit>allow)、TraitsFor(:113-128)、ClassifyCommand(:145-158)、Visible(:96-101)。backend 直接消费(internal/runmgr/runmgr.go:681-685) 无 Policy 命名类型、无规则序列化形态;会话放行记忆在 backend 内存 map(runmgr.go:265-286),未下沉
三类 guardrail 不存在(输入/输出/工具三层全无,grep 无命中);内核只有 RepeatGuard 布尔(loop.go:93-95) 三层端口与执行点全缺
CompletionGate 下沉 在 backend 直连路径三层串联:deliverableGate(internal/runtime/llm.go:477-510,上限 maxDeliverableGuards=2)→ checkDeliverables(runtime/verify.go:48-84,工件存在+非空+quality.ScoreBytes)→ runVerifier(verify.go:86-122,开关 runtime.verify,提示词 aux.verify.final)。经自建 hooks 总线挂一个 Stop 处理器注册进内核(internal/runtime/llm_direct.go:162-172) 依赖 core.ArtifactRef、rc.Artifact、quality.ScoreBytes、提示词库——未端口化;子代理(sub_loop.go:98-112 无 Stop/Hooks)与小队步骤(app.go:202-217 未注入 Stop)都无此门禁;小队只有事后 claimsFalseDeliverable 判失败(runtime/squad_runner.go:90-92)
提醒下沉 backend 侧 directRun.reminders(verify.go:223-250,连续 3 个工具轮未更新计划/待办则提醒,reminderToolGap=3、maxChecklistReminders=3,用库侧 reminders.Bus 节流去重)。内核有通用 Reminders func(turn) 回调(loop.go:90-92) rc.Todos()/Plan() 与 core.TodoList/PlanSnapshot 是产品接口,未端口化;小队/子代理路径未注入
adapters/native 透传 库侧管道已修:GateOptions(adapters/native/backend.go:70-80,含 BeforeTool/AfterTool/Stop/Reminders/RepeatGuard/Hooks/Ask)、透传(:370-372)、gateBus(:464-496);squad 侧映射(deps/agent-squad/adapters/native/register.go:39-49,92-96) 装配未接通(N31 剩余部分):backend 组合根只注入 RepeatGuard:true 与 plan 模式 BeforeTool(internal/app/app.go:207-217);直连与子代理绕过 exec.Backend 直接调 nruntime.Run(llm_direct.go:173、sub_loop.go:98)
Backend 改为消费 adapters/native.Backend 只实现旧门面 exec.Backend(backend.go:130/140),未实现 ContractBackend;conformance.Suite(conformance/fake.go:106,三条用例)无真实实现调用方 ContractBackend 实现与 conformance 接入

2.2 工作包分解

WP1 AgentSpec 与插件校验(新类型,库侧 runtime/subagent 或新 runtime/agentspec 包)

  • 定义 AgentSpec{Name, Description, Prompt, Tools, DisallowedTools, Model, PermissionMode, Skills, MaxTurns, MemoryScope, Effort, Background, WorktreeIsolation, OutputSchema},字段对齐总提案 §2.1 子代理行(Claude subagents frontmatter 集 + outputSchema)。
  • 文件格式:Markdown frontmatter(agent-*.md),加载器在库侧;backend 现有 prompts.SubagentSpec 迁移为读 AgentSpec 文件,fallbackSubagentSpec 保留为内置兜底。
  • 校验红线:插件清单里的 AgentSpec 不得声明 hooks、MCP、权限模式(总提案 §2.1 权限行),校验在插件装载期 fail-closed。
  • 测试:字段 round-trip、缺省值、插件声明 hooks/权限模式被拒、backend 旧画像到 AgentSpec 的等价映射。

WP2 HookBus 补全与 ask 回路

  • 事件枚举加 PostToolBatch、SessionEnd(对齐总提案 §2.1 事件名单);Call 增加「已在续跑中」标志位,hook 触发续跑时下游可见、禁止递归触发 Stop 系事件。
  • 发射点补齐:SessionStart(Run 入口)、UserPromptSubmit(用户消息入列)、PermissionRequest(gateTool ask 时)、SubagentStart/SubagentStop(委派创建/收口)、PreCompact(compact 前)、SessionEnd(Run 出口)、PostToolBatch(工具批结束)。
  • ask 回路(本阶段最关键的行为变化):gateTool 收到 ask 不再当拒绝(loop.go:534-540 现状),改为发 PermissionRequest 并等待宿主决策端口;宿主默认实现 = backend HITL 确认卡(runmgr.go:384-424 现有 AskHITL/waitHITL 机制接为端口实现)。deny 语义不变;block 不变。
  • 风险与兜底:ask 从「拒绝」变「挂起审批」是行为变化;用 A/B 对照(WP6)证明「无 hook 注册时行为与现状逐字节一致」,把行为变化严格限制在「注册了审批端点」的场景。
  • 测试:每个新发射点一例;ask→批准→执行、ask→拒绝→配对结果两条回路;续跑标志防递归;与既有 ab_gate_test.go 对照不回归。

WP3 PermissionPolicy 命名类型与会话放行下沉

  • 在 runtime/policy 增加 Policy 结构体:{Mode, Rules []Rule, SessionAllow AllowStore},Decide 收为方法;AllowStore 是端口(Get/Add/List,key = 工具+参数模式),库内给内存实现,backend 把 sessionAllows(runmgr.go:265-286)替换为该端口的实现(本会话内存即可,持久化形态留给 N3 的 Memory/RunState)。
  • Visible、模式切换(含 ExitPlanMode,runmgr.go:257-263)改走 Policy。
  • 测试:规则优先级矩阵在结构体形态下全等复现现有 policy_test.go 四例 + backend perm_test.go;会话放行跨调用存活。

WP4 三类 guardrail 端口

  • 端口定义:InputGuardrail(只作用于入口智能体的用户输入)、OutputGuardrail(只作用于给出最终结果的那个智能体)、ToolGuardrail(每次工具调用)。形态 = func(ctx, payload) (allow / deny / modify + 原因),与 HookBus 决策词汇一致。
  • 执行点:输入在 UserPromptSubmit 处、输出在 Stop 判定前、工具在 PreToolUse 链内。guardrail 与 hook 的关系写清:guardrail 是类型化语义层,hook 是通用事件层,guardrail 以 hook 实现注册。
  • 测试:三层各自 deny/modify/allow 各一例;只入口、只最终输出的作用域限定各一例。

WP5 CompletionGate 与提醒下沉

  • 下沉的不是实现而是组合点:库侧新增「输出 guardrail 注册位 + 提醒源注册位」,产品依赖端口化:
    • 工件存在/非空/质量分:端口 ArtifactVerifier(backend 用 rc.Artifact + quality.ScoreBytes 实现,verify.go:48-84 逻辑迁入 adapters 侧实现);
    • 独立验证器:端口 FinalVerifier(backend 用 aux.verify.final 提示词 + 独立模型调用实现,verify.go:86-122 迁入);
    • 计划/待办提醒源:端口 ProgressProbe(backend 用 rc.Todos()/Plan() 实现,verify.go:223-250 迁入);maxDeliverableGuards=2、maxVerifyContinuations=3、reminderToolGap=3、maxChecklistReminders=3 等阈值随端口配置走,默认值不变。
  • 迁移后 deliverableGate/checkDeliverables/runVerifier/directRun.reminders 在 backend 只剩端口实现与装配,判定逻辑(正则族、续跑上限、节流)进库。
  • 测试:库内脚本化夹具复现 backend llm_test.go/llm_verify_test.go 的全部门禁用例(GuardTwiceThenNotice、验证器拒绝后通过、垃圾失败关闭、提醒节流等),确保下沉后逐条等价。

WP6 Backend 装配接通与 A/B 对照(N31 收口)

  • internal/app/app.go:直连、子代理(sub_loop.go:98-112)、小队(squadadapter AgentNativeOptions,app.go:207-217)三条路径注入同一套 Hooks/Stop/Reminders/Ask;小队经 squad→native 两级 GateOptions 透传(管道已在,只装配)。
  • 直连与子代理改为经 adapters/native 消费(不再裸调 nruntime.Run);adapters/native.Backend 实现 ContractBackend(补 Descriptor),conformance.Suite 挂到 native 后端跑(现有三条用例起步)。
  • A/B 对照(提案验收核心):同一组脚本化模型输出(含停止、提醒、工具拒绝、HITL 分支),分别在「旧直连装配」与「新下沉装配」下跑,断言停止原因、提醒次数、工具拒绝序列一致。runtime/ab_gate_test.go 是库内雏形,本 WP 把它扩成 backend 侧对照。
  • 小队路径行为变化明示:小队步骤首次获得 Stop 门禁与提醒——这是本阶段有意的行为拉齐,写进 PR 影响段。

2.3 涉及仓与落点汇总

  • Agent-Native:runtime/hooks、runtime/policy、runtime/loop.go、runtime/subagent(或新 agentspec 包)、新 runtime/guardrails(或并入 hooks)、adapters/native、conformance。
  • Backend:internal/app/app.go、internal/runtime/{llm.go,llm_direct.go,verify.go,sub_loop.go,squad_runner.go}、internal/runmgr/runmgr.go(AskHITL 接端口、sessionAllows 替换)、internal/squadadapter(透传配置)。
  • Dev:两层 pin。

2.4 实施顺序

WP2(ask 回路)与 WP3(Policy 类型)先行(其余都依赖决策与权限语义)→ WP1 AgentSpec、WP4 guardrail 端口 → WP5 下沉 → WP6 装配与 A/B。每 WP 单独提交,库内测试绿了再进下一 WP。

2.5 风险

  • ask 语义变化是最大风险点:必须有 A/B 对照证明默认行为不变(见 WP2/WP6)。
  • 下沉搬移正则族与阈值时容易丢行为:WP5 的「逐条等价」测试先行(先在库内写好对现网行为的刻画,再搬)。
  • 小队首次上门禁可能暴露存量提示词的虚假交付习惯:claimsFalseDeliverable 与 Stop 门禁并存期要观察误报率,必要时给小队入口单独的宽松阈值(配置项,不硬编码)。

2.6 N1 验收(对照总提案 §5 N1 验收逐条)

总提案条款 机器可核对的验收
同一组脚本化模型输出,下沉前后停止原因、提醒次数、工具拒绝一致 backend 侧 A/B 对照测试在 CI 通过;对照夹具覆盖 deliverableGate 命中/未命中、verifier 拒绝/通过/垃圾、提醒触发/节流、工具拒绝
插件里的 AgentSpec 不能带钩子和权限模式 插件装载测试:声明 hooks/permissionMode 的 AgentSpec 被拒且错误可定位到字段

3. Q1 图执行

总提案原文(§5 Q1):「superstep、三档检查点、attempt id、interrupt / resume。Needs 驱动依赖。读写集。可组合 Termination。Store 接口。platform 的 SQLite 成为 Store 的一个实现,不再单独驱动一套运行。」

3.1 现状与 gap

需求项 现状(证据) gap
superstep 无。执行是「线性步骤数组 + 状态机扫描」:flowDriver.advance(deps/agent-squad/squad/workflow.go:22-101)一个大循环扫到挂起/终态;leader 是独立大循环(leader.go:178-372);WorkflowPlan.CurrentStepIndex(models.go:124)是从未写入的死字段 整个推进模型
三档检查点 无 checkpoint 类型。最接近的是「步骤完成即 st.save() 全量落盘」(workflow.go:367-371,同步单档)+ 挂起时 pending.json。原子写已修(AtomicWrite,workspace.go:307-349) 检查点类型与退出时/异步/同步三档全缺
attempt id 只有计数器 Attempts(models.go:93-94)与不变的 ExecutionID = runID+"-"+stepID(workflow.go:286);恢复靠「running + Attempts>=2 + HITL 模式」启发式(engine.go:879-925),无产物校验 attempt id、幂等键、「副作用次数=1」的判定基础
interrupt/resume 同一对原语 挂起原语面向人:hitlGate/pending.json + Respond/Resume(engine.go:481,928);事件唤醒是旁路 WaitCondition + SweepWakeups(engine.go:1080-1163);SweepExpired(engine.go:1107-1130)无调用方,是死代码 统一原语;SweepExpired 接线
Needs 驱动依赖 字段已声明(models.go:90)但调度完全不读(全仓唯一引用即声明行);调度只看「相邻 Parallel 标记」(workflow.go:44-72) DAG、拓扑排序全缺
读写集 无 Reads/Writes 字段;「写同一工件必须串行」无判定;并行安全靠 st.mu 串行化写回 字段与调度判定全缺
可组合 Termination 无该类型。四个停止条件硬编码分散:leader 轮次(leader.go:207/371,达上限直接 leaderFail 无降级,Q23 仍开放)、修复预算(engine.go:36-37 默认 1,workflow.go:583-596 扣减,engine.go:698 人工 retry 加预算无上限,Q26 仍开放)、唤醒上限(hitl.go:68 MaxWakeupFires=5)、StepTimeout/HITL 超时(engine.go:32-33、hitl.go:23-30、hitl.go:119-137) 类型与 AND/OR 组合全缺
Store 接口 squad 核心无 Store 端口;运行状态由引擎直接管文件(runstate.go:52-76 一次写六文件);store.FileStore 只管 roles/blueprints;store/eventsink.go 是事件 jsonl 装饰器 接口不存在
platform 收编 adapters/sqlite(包名 platform)是独立第二套运行系统:23 张表无 run/step/checkpoint 表(db.go:51-149);task 队列自有一套 Claim/FinishTask/RecoverOrphans(queue.go:194-348);RunInProcess 绕过 Executor 端口直驱 agent-native(runtime.go:201-229,X6 仍开放);与 squad 文件态 runs 双真相源并列挂载(cmd/agent-squad/server/server.go:31-41,94-96) 双系统合一 + schema 扩展 + X6
顺带瑕疵(Q1 会踩到) 并行组 wg.Wait() 等全部结束才收口(workflow.go:172);黑板是快照不是增量(blackboard.go:12-38);动态调整直接 splice Steps(workflow.go:510-534)——与「图结构不变」的恢复要求冲突;产品侧消费方是 squadadapter 的外层 Run/Resume 循环(modules/backend/internal/squadadapter/adapter.go:92-117、entry.go:115-139) 在设计中显式裁定,见 §3.2 WP1/WP4

已修不再返工(R1/R2 已落):原子写、授权/预算落盘、批准键写入(Q1)、中断步骤挂起分流(Q4 部分)、跨进程锁(Q5)、Respond 幂等(Q7)、WAL(Q19)、事件 seq 续号(Q18)。

3.2 工作包分解

WP1 图模型与 Needs 调度

  • StepSpec 增补 Writes []string(写集,工件路径)与 Reads []string(读集,可空=不声明);Needs 从死字段激活为依赖声明。
  • 编译期(planAndExecute 入口)把 Steps 编译成图:节点=步骤,边=Needs;拓扑分层(Kahn),同层可并行。兼容映射:无 Needs 的旧蓝图按「相邻 Parallel」规则自动分层(相邻且 Parallel=true 的步骤入同层),行为不变量由现有测试保证。
  • 动态调整裁定(与恢复语义冲突的解决):AllowDynamicAdjustment 步骤的 splice(workflow.go:510-534)改为「追加节点生成新图版本」——图带 version,已完成的 superstep 结果按节点 id+图版本键保存;恢复时要求图版本与检查点一致,不一致则拒绝恢复并提示重新规划(对齐总提案 §2.2「恢复要求图结构不变」)。
  • 调度隔离:同层内写同一工件(Writes 交集非空)的步骤强制串行;只读步骤并行。交集判定在分层时做,拒绝或串行化在调度时做(默认串行化 + 事件提示,不拒绝)。
  • 测试:Needs 分层顺序、环检测拒绝、旧蓝图兼容映射等价、写集交集串行化、图版本不一致拒绝恢复。

WP2 superstep 推进

  • advance 重写为 superstep 循环:每 superstep = 「取当前可执行层 → 层内调度(写集串行)→ 层结束做检查点」。leader 循环映射为「leader 节点 + 动态追加成员节点」的图形态(委派=追加,close=终止边),leader.json 的状态并入检查点。
  • CurrentStepIndex 死字段删除或改作「当前 superstep 序号」。
  • 并行组 fail-fast 裁定:保持 cancel 传播(现状),superstep 边界统一收口失败,不再 wg.Wait() 空等——失败即终止本 superstep 剩余节点。
  • 测试:多蓝图(standard/router/leader)在新循环下现有 engine_test/leader_test 全绿;层边界事件序列断言。

WP3 attempt id 与幂等

  • 每次执行生成 AttemptID = runID/stepID/N(N=Attempts+1),随步骤状态落盘;执行事件、产物、副作用记录都挂 AttemptID。
  • 恢复判定升级:recoverInterrupted(engine.go:879-925)从启发式改为「attempt 记录 + 产物校验」——步骤标 running 且其 attempt 无完成记录时,按 HITL 模式分流(现状三分支保留),选择 retry 时新 attempt 执行前校验该步骤已登记副作用(产物文件存在性)并在事件流标注「第 N 次尝试」。
  • 验收硬指标「副作用次数=1」的判定基础:已完成(有完成记录)的 attempt 永不重跑;瞬态重试(MaxTransientStepInvocations=2,workflow.go:260)共享同一 AttemptID 的「子尝试」标记,不计为新 attempt。
  • 测试:杀进程于每个 superstep 边界(见 §3.6);retry/skip/abort 三分支;瞬态重试不增 AttemptID。

WP4 Store 端口与三档检查点

  • 新端口 Store(squad 包内):SaveRun/LoadRun/SaveStep/LoadStep/SaveAttempt/AppendEvent/LoadEvents/SaveCheckpoint/LoadCheckpoint/ListRuns,以 run(thread)为键。
  • 现状文件态收编为 FileStore(runs/ 目录六文件 + pending.json + leader.json 的全部读写走 Store 接口);检查点三档:sync(superstep 边界同步写,默认)、async(批量刷盘)、on_exit(进程退出时)——档位在 RunOptions 声明,默认 sync。
  • 黑板裁定:Q1 只把黑板快照纳入检查点载荷;「可回放增量」留给 Q2 拓扑(总提案 §2.2 把黑板增量列在拓扑行)。
  • 测试:三档各自的一致性;检查点以 run 为键的隔离;FileStore 与现状文件布局的读取兼容(老 runs 目录可恢复)。

WP5 SQLiteStore 与 platform 收编

  • adapters/sqlite schema 增加 run / step / attempt / checkpoint / event 五表;SQLiteStore 实现 Store 端口。
  • 收编裁定(双真相源合一):platform 的 task 队列不再自行驱动执行——Claim 到的任务翻译为 squad run 并交给引擎(Store=SQLiteStore),RunInProcess 改走 Executor 端口(修 X6);platform 的 wakeup 表与 squad 的 WaitCondition 合并为一处(保留 squad 语义,platform 表改为投影或下线,迁移期双写只读旧表)。
  • 过渡:platform 现有 23 表中非运行类(workspace/member/issue/skill/autopilot/webhook/chat/project 等)不动;本 WP 只合一「运行」这一层。
  • 测试:同一蓝图分别在 FileStore 与 SQLiteStore 上跑通 conformance(见 §3.6);孤儿恢复(RecoverOrphans)在合并后语义不变;server 并列挂载改为单引擎。

WP6 可组合 Termination

  • 新类型 Termination = And(...)|Or(...)|MaxTurns(n)|RepairBudget(n)|MaxWakeups(n)|Timeout(d)|StepTimeout(d);四处硬编码收编为默认组合:And(MaxLeaderTurns(8), RepairBudget(1), MaxWakeups(5)) + 步骤级 StepTimeout(默认 10min,语义不变:重试共享截止,Q24 维持现状并写进文档)。
  • 顺手关账:leader 达上限的降级收口(Q23:不再裸 leaderFail,走一次收口质检或挂起人工);人工 retry 加预算设上限(Q26:默认累计不超过初始值的 2 倍,可配);SweepExpired 接入 serve 周期循环(与 SweepWakeups 并列),补 Q6 另一半。
  • 测试:AND/OR 组合矩阵;三个关账项各一例回归。

WP7 interrupt/resume 统一原语

  • 把「HITL 挂起(pending.json)」与「事件等待(WaitCondition/SweepWakeups)」统一为 Interrupt{Kind: human|event|expired, Key, Payload} / Resume(Key, Response) 一对原语;pending.json 与 wakeup 成为 interrupt 的两种持久化形态。
  • 对外 API(Respond/Resume/steer)语义不变,内部改走统一原语。
  • 测试:两种 interrupt 的挂起/恢复/过期三态;API 兼容(现有 server_test、engine_test 绿)。

3.3 涉及仓与落点汇总

  • Agent-Squad:squad/{workflow.go,engine.go,leader.go,models.go,runstate.go,blackboard.go,hitl.go}(重写面大)、新 squad/{graph.go,superstep.go,store.go,termination.go,interrupt.go}、adapters/sqlite(schema+Store)、store/(FileStore 归位)、cmd/agent-squad/server(挂载合一、SweepExpired 接线)。
  • Backend:internal/squadadapter(驱动循环跟上引擎 API;入口/步进循环适配)。
  • Dev:两层 pin。

3.4 实施顺序

WP1 图模型 → WP2 superstep(旧行为兼容先绿)→ WP3 attempt id → WP4 Store+检查点 → WP7 统一原语 → WP6 Termination → WP5 SQLite 收编排最后(风险最高,前面 WP 已各自可独立交付)。

3.5 风险

  • advance 重写是心脏手术:WP2 必须先建立「旧蓝图兼容等价」的测试网(现有 engine/leader/recovery/r2_regression 套件就是网底),重写中任何一绿变红即停。
  • 动态调整与图版本:产品端目前依赖动态调整的蓝图(如有)在恢复时会被要求重新规划——行为变化写进 PR 影响段,并把「图版本不一致」的报错做成可操作提示。
  • platform 收编(WP5)触及双系统合一与 X6,体量接近一个小阶段:允许 WP5 在 Q1 任务内再拆子 PR 序列(Store 实现先行、驱动合一随后),但不允许只交一半——「不再单独驱动一套运行」是验收条款。
  • 消费方只有 squadadapter 一处(backend)与 squad CLI/serve 一处,适配面可控。

3.6 Q1 验收(对照总提案 §5 Q1 验收逐条)

总提案条款 机器可核对的验收
在每个 superstep 边界杀进程再恢复,已成功步骤的副作用次数为 1 新测试:脚本化蓝图(≥3 个 superstep),逐边界 kill -9 后 Resume,断言每个已完成步骤的产物写入次数=1、事件流无重复完成记录
两个写同一工件的步骤不会并行 调度测试:写集交集步骤的执行区间不重叠(事件时间戳断言)
文件 run 与 SQLite 不再各记一份步骤状态 conformance 套件在 FileStore 与 SQLiteStore 双实现上通过;server 单引擎挂载;platform 侧无独立 run 状态表残留(schema 断言)

4. I1 命令化识别

总提案原文(§5 I1):「命令列表与 ActionRef。中文匹配的词界或最短词长。同分时可按 priority 决胜。Catalog 白名单与 top-k。Backend 唯一 Router 消费 ActionRef。」验收点名审计 I1、I2、I3、I5 有回归(I1/I2 在当前 pin 已修并有测试,I3/I5 开放,见下)。

4.1 现状与 gap

需求项 现状(证据) gap
命令列表 不存在。Result = {Input, Branch, Top *Candidate, Candidates, SnapshotRevision}(deps/agent-intent/intent/result.go:44-50),输出是单 Top 意图;ActionRef/Start/SetSlot 全仓零代码命中 命令类型、序列化、校验全缺
ActionRef 统一 四种动作键并存:(a) IntentSpec.Handler(spec.go:81,squadintent Runner 消费);(b) Metadata["blueprint"](adapters/intent/gate.go:123-131 → engine.go:228-237);(c) CommandSpec.ID(agent-command,backend server.go:653-654 把意图 ID 当命令 ID);(d) WorkflowDef.IntentID(core plugin.go:60,workflow/registry.go:40-42 索引) 统一表示与迁移映射
Backend 唯一 Router 不存在。消费分散三处:chat 路由内联 if-else(internal/server/server.go:647-660,命令优先于工作流写死)、HITL 自由输入转轨(internal/runmgr/runmgr.go:1203-1248)、装配(internal/app/app.go:300-301,316,381)。squad 的蓝图意图链 backend 完全没接(squadadapter/entry.go:98-110 不设 IntentGate/IntentCatalog/IntentRunner;全 backend grep squadintent 零命中) Router 组件与优先级裁定
中文词界/最短词长(I3) 纯子串 strings.Contains(registry.go:142/147/154);无词界设施、无最短词长告警(grep 零命中);NFKC 已落地(fold.go:11-28)但两个宿主都没开(backend intentgate gate.go:57 只设 TopN;squadintent gate.go:37-44 只设 Guard/Protected 域);语料中文负例只有一条靠 excludes_any 硬回避(testdata/corpus.json 第 6 行 + specs/base.json:10) 词界设施、lint 告警、负例语料、宿主开 NFKC
同分 priority 决胜(I5) Priority 字段已在(spec.go:74)且是排序第二键(registry.go:327-335、recognizer.go:172-183);但裁决要求分差 ≥ margin(recognizer.go:92),AmbiguityMargin <= 0 强制回 0.1(registry.go:61-63)——同分恒 ambiguous,priority 不参与决胜 裁决逻辑调整
Catalog 白名单与 top-k Metadata 白名单已有(fold.go:61-64,只放 blueprint/guidance 两键);但 CatalogSpec.Handler 仍进 JSON 视图(catalog.go:20-30);目录全量输出无 top-k、无相关度(catalog.go:34-62) top-k 与相关度参数;Handler 是否进目录的裁定
eval intentctl eval 单轮(cmd/intentctl/main.go:229-292,recognizer 以 nil expectation/classifier 构建于 main.go:254);语料 10 条(testdata/corpus.json);输出只有 PASS/FAIL 计数(main.go:285-290) 多轮夹具格式与逐轮命令期望(precision/recall 指标输出属 I2,I1 先扩格式)
命令层前置概念 否定只认 excludes_any(recognizer.go:66 注释明说「不要写入」交给命令层 Cancel——命令层尚不存在,审计 I12);ExpectationProvider 接口在(expectation.go:7-19)但宿主侧零实现;L2 Classifier 同理(classifier.go:9-15,全部 NewRecognizer 传 nil) I1 只需命令层与宿主编排;L2 实现、语义端口在 I2

另外注意:overlay 解析 DisallowUnknownFields(loader.go:21-24、51)——spec 加字段不做显式注册会硬失败旧配置;backend 插件读的是裸 spec 数组(internal/plugins/host.go:216-222),不是 {intents, disable} overlayDoc——两种载体的兼容都要照顾。

4.2 工作包分解

WP1 命令模型(库侧核心)

  • 新类型:Command 联合 {Kind, ...}——Start{ActionRef, Slots} / SetSlot{Name, Value} / ChangeSlot{Name, Value} / Cancel{Scope} / Clarify{Question, Missing} / Chitchat{} / Handoff{Target};ActionRef{Kind: command|workflow|blueprint|handler, ID string}。
  • Result 增加 Commands []Command(Branch/Top 保留作诊断与兼容,逐步退役由 Router 封装);从候选到命令的展开规则:Top 命中 → Start(带 ActionRef 推导);槽位缺失 → Clarify(或 ExpectationProvider 命中时 SetSlot/ChangeSlot);多候选 → Clarify 消歧或 Ambiguous 保持(见 WP4/WP5 裁决);否定/取消语义 → Cancel(命令层首次承认否定,收编 recognizer.go:66 的注释承诺)。
  • 命令的校验与现有候选校验同级(ID 集合、槽位作用域);序列化进 schema 包并给 JSON 样例(对齐 D1 的「三库发布 JSON Schema 样例」做法)。
  • 测试:每种命令的展开路径;校验拒绝;round-trip。

WP2 ActionRef 推导与四种动作键迁移

  • spec 增加显式字段承载 ActionRef(action: {kind, id}),DisallowUnknownFields 下注册;推导规则(兼容期):action 缺省时按旧键推导——Handler → {handler, <值>}、Metadata["blueprint"] → {blueprint, <值>}、命中 backend 命令总线 → {command, <ID>}、命中 workflow 索引 → {workflow, <IntentID>}。
  • backend 插件装载(host.go:216-222 裸数组)与库 overlay 两种载体都接受新字段;旧字段在 I1 不删除(退役留给 I2 之后的发版任务)。
  • 测试:四种旧键的推导等价于现状路由结果(对照 server.go:647-660 现行为刻画测试先行);新字段优先于旧键。

WP3 Backend 唯一 Router

  • 新组件(建议 internal/route,或收进 internal/server 的独立文件):输入 = 命令列表 + 会话状态,输出 = 路由决策(command 分发 / workflow 启动 / squad 入口 / 普通回合 / 澄清回问)。
  • 收编两处现有消费:server.go:647-660 的内联 if-else 与 runmgr.go:1203-1248 的 HITL 自由输入转轨,统一改调 Router;slash 命令(server.go:741-758)保持旁路不过在优先级文档里写明。
  • 优先级明文(提案 §6 要求 I1 写明):command > workflow > blueprint > 普通回合;PromptTrigger(技能触发)与 Intent 同命中时的裁定:技能触发是提示词装配、不参与路由决胜;若 Intent 产出 Start/SetSlot 类命令则路由优先,纯提示词命中不产生命令——写进 Router 文档与测试。
  • squad 蓝图链({blueprint, key})经 ActionRef 到达 Router 后,Router 调 squad 入口;backend 接入 squadintent 适配器(entry.go:98-110 的缺口)在本 WP 一并补上——这是「blueprint 经 ActionRef 到 Router」验收的必要条件,范围可控(装配 + 映射,不改 squad 库)。
  • 测试:命令优先于工作流(现有 TestCommandBusBeatsWorkflow 迁移)、workflow 经 ActionRef 启动、blueprint 经 ActionRef 进 squad 入口、HITL 自由输入转轨走同一路由、fallback 进普通回合。

WP4 中文词界与最短词长(I3)

  • MatchSpec 增加 boundary(词界模式:CJK 按「非汉字或首尾」为界,拉丁按词字符边界)与 min_len(词条最短长度,低于则 lint 告警)——二选一还是并存由实施期原型定,但 lint 告警(intentctl lint)必须覆盖「短词条 + 无词界」组合。
  • 两宿主开启 NFKC:backend intentgate.Rebuild(gate.go:57)与 squadintent(gate.go:37-44)的 Options 显式开 NFKC:true,并补开启前后对照测试。
  • 语料补负例:中文子串误命中系列(如「配置」误中「配置项」、「写入」误中「不要写入」的否定场景交给 Cancel 的正例对照)。
  • 测试:词界开/关矩阵、最短词长告警、新负例全过、既有 10 条语料不回归。

WP5 同分 priority 决胜(I5)

  • 裁决调整:前两名置信度同分(差 < margin)时,若 Priority 不同则高优先者判 matched;priority 也相同才 ambiguous。AmbiguityMargin 语义不变(仍防分数过近误判),margin 强制下限 0.1 保留。
  • 测试:同分高 priority 命中、同分同 priority 标歧、margin 边界三例;既有漏斗测试不回归。

WP6 eval 格式扩展

  • 语料格式 v2:用例带 turns: [{input, expect: {commands: [...]}}],逐轮期望命令列表;intentctl eval 读 v2 时构建 ExpectationProvider 夹具实现(库内给测试用 Provider),逐轮比对命令序列;v1 单轮格式兼容读取并自动映射为单 turn。
  • 指标输出在本阶段只加「逐轮命令匹配率」明细(precision/recall 的正式定义与输出属 I2,不在 I1 提前承诺)。
  • 测试:v2 多轮夹具端到端(含 SetSlot+Start 组合用例——验收条款的载体)、v1 兼容、误期望 FAIL。

4.3 涉及仓与落点汇总

  • Agent-Intent:intent/{result.go,recognizer.go,registry.go,spec.go,loader.go,catalog.go}、新 intent/command.go、schema/、cmd/intentctl、testdata/。
  • Backend:internal/server/server.go、internal/server/(新 Router)、internal/intentgate/(Recognize 返回命令、NFKC 开启)、internal/runmgr/runmgr.go(HITL 转轨改调 Router)、internal/squadadapter/entry.go(接 squadintent)、internal/plugins/host.go(spec 新字段)。
  • Agent-Squad:adapters/intent 只在映射 ActionRef 时动(blueprint 键推导),核心不动。
  • Dev:两层 pin。

4.4 实施顺序

WP1 命令模型 → WP2 ActionRef 迁移(刻画测试先行)→ WP5 决胜 + WP4 词界(库内独立,可并行)→ WP3 Router(依赖 WP1/WP2)→ WP6 eval(收尾,验收载体)。

4.5 风险

  • 路由行为变化面:Router 收编两处消费 + squad 蓝图链接入,是产品可见行为。对策:WP2 的刻画测试先把现路由行为钉死,Router 切换后逐条等价;蓝图链接入属新增能力,单独一组测试,不改动有路由。
  • overlay 严格解析:spec 新字段必须同步注册进 loader 与 backend 裸数组装载两处,漏一边即硬失败——测试覆盖两种载体。
  • NFKC 默认开启是行为变化:只动两个宿主的显式配置,库默认不变(库保持 fail-closed 哲学,宿主显式选择)。
  • 命令列表与「单 Top」并存期,Result.Top 的消费方(squadintent gate 等)保持可用;退役由后续发版任务评估,不在 I1。

4.6 I1 验收(对照总提案 §5 I1 验收逐条)

总提案条款 机器可核对的验收
审计 I1、I2、I3、I5 有回归 I1(分类器篡改拒绝,recognizer_test.go:188/238/269 现存)与 I2(作用域校验器,slots_catalog_test.go:70 现存)保持绿;I3 新增词界/负例测试;I5 新增决胜测试——四个测试名写进任务卡
一条用户话可以产出 SetSlot 加 Start eval v2 多轮夹具含该用例并通过
命令 id、工作流 IntentID、小队 blueprint 都通过 ActionRef 到达 Router Router 测试三条各一;插件清单字段名不变的 diff 断言(装载测试比对字段名清单)
插件清单不改字段名 插件装载兼容测试:现有插件 intents/workflows 清单零修改装载通过

5. 三任务之外的说明

  • N2/Q2/I2 及更后的阶段不在本文范围;本文的 WP 划分假定 N1/Q1/I1 全部合入后才启动它们。
  • 三任务的验收都依赖「脚本化模型 + 库内夹具」,不依赖真实模型密钥;真实任务 A/B(总提案 E 节「少量真实任务加人工复核」)在各阶段验收时由所有者安排。
  • 本文档本身不修任何代码;如评审要求改设计,在本文档上修订后再启动对应任务。

6. 验收(本文)

  • 三个阶段的实施方案各自满足:工作包可独立派生任务卡、验收条款可机器核对、与总提案逐条映射(§2.6 / §3.6 / §4.6 的表)。
  • 现状陈述均有 file:line 证据(撰写日 pin 见 §1.1);评审重放 = 按表中证据抽查。
  • 三任务协调规则(§1.2)与 AGENTS.md 分支层级一致。

7. 实施状态回填与范围差异(2026-10-08)

本节回填三个阶段的实施结果与本文原设计的范围差异,来源为已归档任务卡(SELF 声明)与 Dev main 的合入记录(2026-10-08 经 git log --merges 核对,#230/#231/#234/#235/#237/#240 均在 main)。本节不重放各任务测试,不把闭卡文案升级为重新验收;「完成」指卡内验收条款 声明 PASS 且 PR 已合入。每个转出/待做项标注依据、归属与适用版本,供 N2/Q3 之后的工作 与 RDM 依赖判断使用。

7.1 N1 内核 harness

已合入:Dev #230(merge 42f5ac4)/ #231(merge b6974fa);组件链 Agent-Native #17–#20、Agent-Squad #16–#18、Backend #69–#73(卡内记录,CI 在各 merge 前 success,GATE)。 卡内验收两条(A/B 对照、插件 AgentSpec 校验)声明 PASS(SELF)。

与本文 §2.2 的范围差异(依据:N1 卡增量三/四及「影响与剩余项」):

项 本文原设计 实施结果 状态 归属/载体
WP6b 小队成员级 deliverable Stop/提醒拉齐 §2.2 WP6「三条路径注入同一套…」的小队成员级部分 任务内裁定转出:需 adapters 成员级执行信号(工件产出追踪+工具轮计数) 待做;原建议载体 Q1 未承接(Q1 卡剩余项无此项,Q2/Q3 亦未涉及) owner weichen;载体待定
WP6c 直连/子代理改经 adapters 消费 §2.2 WP6「不再裸调 nruntime.Run」 转出:需 exec.Request 表达 History/工件追踪/证据回收;ContractBackend+conformance 部分已落地(卡增量四②) 待做;未承接 owner weichen;载体待定
prompts.SubagentSpec 迁移 §2.2 WP1「迁移为读 AgentSpec 文件」 裁定不迁移:与 agent-*.md 两套格式并存,新字段暂无消费者(卡增量三) 有意搁置 owner weichen;有消费者时再启动
runmgr 派生路径 Start/Stop §2.2 WP2 发射点补齐的产品侧外延 裁定不覆盖:非工具调用、无总线上下文(卡增量三) 有意搁置 同上
AllowStore 持久化 §2.2 WP3「持久化形态留给 N3」 N3 再转出(N3 卡「影响与剩余项」:memory 回合后抽取接线与 AllowStore 持久化转后续) 待做;已经 N3 二次转出 见 N3 卡记录

7.2 Q1 图执行

已合入:Dev #237(merge 3bf2441)/ #240(merge ba36d47);组件链 Agent-Squad #23–#26、 Backend #79–#82。卡内验收三条声明 PASS(SELF)。

与本文 §3 的范围差异(依据:Q1 卡增量四及「影响与剩余项」;Q2/Q3 卡对照):

项 本文原设计 实施结果 状态 归属/载体
platform task 队列翻译成 squad run §3.2 WP5 收编裁定「Claim 到的任务翻译为 squad run 并交给引擎」 Store 层合一已做(SQLiteStore、X6 改走 Executor 端口、serve 单库挂载);task 队列本身的翻译转出为「更深的产品合一,Q 系列/EXT 范畴」;Q2 卡明确记非目标(「平台队列桥接…(后续)」),Q3 未涉及 待做;Q 系列已收口仍未承接 owner weichen;按 RDM 总案 §3.3 走 EXT 申请或后续产品任务
黑板可回放增量与 Reads 读集 §3.2 WP4「留给 Q2 拓扑」 Q1 卡转出至 Q2;Q2 卡通篇无黑板/读集内容(实施为拓扑注册表等) 待做;Q2 未承接 owner weichen;载体待定
leader 模式 SQLite 端到端 §3.2 WP2「leader.json 的状态并入检查点」 Store 已实现 SaveLeader/LoadLeader;leader 模式回归在 FileStore 上证明(卡「影响与剩余项」) 待做(回归补证) owner weichen
验收表「schema 断言」 §3.6 第三条「platform 侧无独立 run 状态表残留(schema 断言)」 卡内验证记录为 TestSQLiteStoreRoundTrip、TestEngineRunsOnSQLiteStore 与单库挂载;未见 schema 断言测试记录 证据口径差异;补断言或由负责人裁定豁免 owner weichen
拓扑库 Q1 卡转出至 Q2 Q2 已落地(Dev #250/#251) 完成(在 Q2) —

7.3 I1 命令化识别

已合入:Dev #234(merge 1f7217f)/ #235(merge eafe1e1);组件链 Agent-Intent #6–#8、 Agent-Squad #19–#22、Agent-Native #21/#22、Backend #74–#78。卡内验收四条声明 PASS(SELF)。

与本文 §4.2 的范围差异(依据:I1 卡「影响与剩余项」;代码核对 command.go:18-25/78-84):

项 本文原设计 实施结果 状态 归属/载体
blueprint per-run entry 覆盖 §4.2 WP3 squad 蓝图链接入的延伸 裁定为独立设计项;blueprint 决策已达 Router 待做 owner weichen
ambiguous→Clarify 产品化 §4.2 WP1 消歧路径 Router v1 保持普通回合;产品化需澄清 UI/HITL 待做 owner weichen
SetSlot/Cancel/Handoff 的产出与消费 §4.2 WP1「否定/取消语义 → Cancel(收编 recognizer.go:66 注释承诺)」与命令展开 Command 类型已定义且有意裁定「规则漏斗不产出 Cancel/Handoff」(command.go:78-84 注释:留给声明 action 的意图与语义层);运行时消费(会话槽位状态机)未做 待做;原记「I2 附近」,I2 已收口未承接(I2 卡同项转出) owner weichen;无阶段载体,需排期

7.4 对后续依赖的提示

  • N2/N3/Q2/Q3/I2 均已各自合入(见规划索引阶段导航),但上表转出项无一被 这些阶段承接;引用「N1/Q1/I1 已完成」作依赖判断时,须扣除上表待做项。
  • RDM MS3 依赖的 Q1 图执行与 Q3 编排收敛不受上表影响;受影响的是「platform task 队列 合一」与「SetSlot/Cancel/Handoff 消费」两条产品化路径。
  • 本节维护规则与索引一致:状态再次变化时先更新本节并同步索引导航。