docs(.agents): 蒸馏配置控制面阶段一① 护城河 middleware 落地(tech-decisions §11)+ AgentScope 2.0.2 续修 middleware 机制速查 + SDD 子代理产出验证纪律
Some checks failed
docs-gate / docs-gate (push) Has been cancelled
Some checks failed
docs-gate / docs-gate (push) Has been cancelled
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
07100eef85
commit
10aeed3cc2
@ -27,9 +27,9 @@
|
||||
| 文件 | 一句话说明 |
|
||||
|---|---|
|
||||
| `product-and-architecture.md` | 产品定位、13 模块与依赖、三仓三端分层架构蒸馏(中间件 Nacos/RocketMQ/Sentinel 三件套已自托管 mini-infra) |
|
||||
| `tech-decisions.md` | 技术栈与关键选型 ADR + 待确认项 + 生成主线口径(AgentScope 三档统一收敛)+ 便宜档 M1-M3 实测(§5.1) |
|
||||
| `tech-decisions.md` | 技术栈与关键选型 ADR + 待确认项 + 生成主线口径(AgentScope 三档统一收敛)+ 便宜档 M1-M3 实测(§5.1)+ 配置控制面阶段〇/一① 落地(§10/§11:Nacos/RocketMQ/Sentinel + 护城河续修/软预算/门判 middleware) |
|
||||
| `mvp-scope-and-milestones.md` | MVP 的 55 项 P0 产品功能范围、5 工位分工、M0-M5 里程碑与验收指标 |
|
||||
| `agentscope-2.0-facts.md` | AgentScope 2.0.2 真实架构速查 + 便宜档 cheap-worker 实现 API 速查(免重查) |
|
||||
| `agentscope-2.0-facts.md` | AgentScope 2.0.2 真实架构速查 + 便宜档 cheap-worker 实现 API 速查(免重查)+ 护城河续修/软预算 middleware 的 2.0.2 机制速查(on_reasoning 拦 finish 续跑 / 洋葱序 / 软预算门判自挂) |
|
||||
|
||||
**rules/**
|
||||
|
||||
@ -68,7 +68,7 @@
|
||||
|
||||
| 文件 | 一句话说明 |
|
||||
|---|---|
|
||||
| `ai-development-protocol.md` | 任务承接→分析→评审→执行→验证→沉淀的完整协议 + 子代理 model 成本分档 |
|
||||
| `ai-development-protocol.md` | 任务承接→分析→评审→执行→验证→沉淀的完整协议 + 子代理 model 成本分档 + §4.2 执行子代理产出验证纪律(DONE 不可信/hash 校验拦造假/自验) |
|
||||
| `mvp-execution-orchestration.md` | MVP 10-Agent×3 周执行编排 + 8 条复利提效策略 |
|
||||
|
||||
**tools/**
|
||||
|
||||
@ -62,7 +62,7 @@ Workspace 提供三种执行后端(`workspace/__init__.py`):`LocalWorkspac
|
||||
|
||||
- `register_tool_function` **不存在** → 注册靠构造器 `Toolkit(tools=[FunctionTool(fn), ...])`。
|
||||
- `ReplyBudgetControlMiddleware` **不存在** → 预算/软刹得自挂 `MiddlewareBase` 的 `on_system_prompt`/`on_model_call` 钩子(tier2 的 `CircuitBreakerMiddleware` 即如此自实现)。
|
||||
- 内置 ReAct **不会「跑满 max_iters 才停」** → 在「模型产出无 tool_call 的纯文本回合」即退出(`agent/_agent.py`)。要多轮自修必须在 Agent 外**自建有界 resume 循环**:`for attempt in range(max_resumes): await agent.reply(...); 判收敛/门绿;否则带失败反馈再 reply`。这一圈正对应 Node 生成 harness 的 while 主循环。
|
||||
- 内置 ReAct **不会「跑满 max_iters 才停」** → 在「模型产出无 tool_call 的纯文本回合」即退出(`agent/_agent.py`)。要多轮自修必须在 Agent 外**自建有界 resume 循环**:`for attempt in range(max_resumes): await agent.reply(...); 判收敛/门绿;否则带失败反馈再 reply`。这一圈正对应 Node 生成 harness 的 while 主循环。**(2026-07-02 阶段一① 更新:tier2 已改用 `on_reasoning` middleware 在洋葱内拦 finish 续修、取代这圈 Agent 外 resume——见下「护城河续修/软预算 middleware 的 2.0.2 机制」段与 [`tech-decisions.md`](tech-decisions.md) §11;外层 resume 仍留 fallback。)**
|
||||
|
||||
**工具写法(schema 自动抽)**:每个工具是 `async def` + 参数类型注解 + Google docstring(`Args:`),`FunctionTool(fn)` 据此抽 schema;闭包捕获一个可变 session 对象做跨工具状态;返回 str(纯文本或 `json.dumps`)。
|
||||
|
||||
@ -73,3 +73,14 @@ Workspace 提供三种执行后端(`workspace/__init__.py`):`LocalWorkspac
|
||||
**跨包 import 含连字符目录**:`gen-worker` 不能 `import`;把 `tier2/gen-worker/` 加进 `sys.path` 再 `from worker import ...`(`from observability import ...` 同理)。
|
||||
|
||||
落地实证 = 便宜档 Python 线 `cheap-worker/`(WU-A spike,端到端九门对照 Node 9/9 持平、过门率 1.0=1.0、对 tier2 零改动)。便宜档生成线现状见 [`cheap-model-game-generation`](../skills/cheap-model-game-generation.md)(注意其旧 W-G1 路已被 cheap-worker 取代)。
|
||||
|
||||
## 护城河续修/软预算 middleware 的 2.0.2 机制速查(阶段一① 落地,2026-07-02)
|
||||
|
||||
多轮自修除了在 Agent 外自建 resume 循环,还有护城河的正解——在 middleware 洋葱内拦 finish 续修、不每轮重开 POST(tier2 阶段一① 落地)。这里记住 2.0.2 的几个机制事实,免得下次碰 middleware 又去翻源码:
|
||||
|
||||
- **finish 是什么**:ReAct 在「模型产出无 tool_call 的纯文本回合」即退出,那个纯文本 `Msg` 就是 finish。它在 `agent/_agent.py` 里先存进 context(约 :857)再 yield(约 :875),穿过 `on_reasoning` 洋葱链才到 reply 收尾循环。
|
||||
- **怎么拦、怎么续**:`on_reasoning` middleware 遍历 `next_handler` 吐的事件,遇到那个 finish `Msg` 就**不 yield(吞掉)**——本轮没有 Msg,reply 循环 `cur_iter++` 继续下一轮推理,等于续跑。要让 agent 真去改,用 `agent.observe(UserMsg(...))` 注入一条 role=user 的反馈(system/tool/thinking 角色会让内部 `_handle_incoming_messages` 抛 ValueError)。注意吞掉 finish 前 agent 已把「做完了」文本存进 context,压制 yield 抹不掉,要 `context.pop()` 清掉才有干净血缘。
|
||||
- **洋葱序**:Service 框架在 extra middleware 外还前置了 `InboxMiddleware`(挂 on_reasoning、每轮 drain inbox 后透传全部事件、不吞 finish),所以工厂注入 `[tracer, repair, breaker]` 的实际 on_reasoning 链是 `[InboxMiddleware, tracer, repair]`——repair 在最内层、能拦到 `_reasoning` 产的原始 finish(breaker 不挂 on_reasoning)。
|
||||
- **软预算/门判为什么必须自挂**:`ReplyBudgetControlMiddleware` 这类不存在(见上),预算软刹得自挂 `on_model_call`(¥ 闸)/`on_system_prompt`(提醒);放行门判得 middleware 自己重跑 `run_gates` 独立判,绝不采信 agent 上报的门结果。
|
||||
|
||||
本项目落地的三个类(`RepairMiddleware` / `CircuitBreakerMiddleware.soft_budget` / `gate_judge`)与那个红线坑(run_gates 起跑前清 verdict 防陈旧假绿)见 [`tech-decisions.md`](tech-decisions.md) §11。
|
||||
|
||||
@ -174,3 +174,16 @@ Nacos / RocketMQ / Sentinel 从「已选型未部署」推进到自托管 mini-i
|
||||
**rocketmq-spring 消费者并发的反直觉语义**(最终 review 核字节码坐实):`@RocketMQMessageListener(consumeThreadNumber, consumeThreadMax)` 在 rocketmq-client 5.x 下,`ConsumeMessageConcurrentlyService` 用**无界 `LinkedBlockingQueue`** 建 `ThreadPoolExecutor(core=consumeThreadNumber, max=consumeThreadMax)`;JDK 线程池语义下无界队列永不满、线程数永不超 core,所以 **`consumeThreadMax` 是死参数、有效并发等于 `consumeThreadNumber`,要让上限真生效必须 min=max**。而且异步投递(worker ACK 即返回、任务留 RUNNING)下它 cap 的是投递握手速率、不是在跑生成数——想用它当并发闸会双重落空。有界 worker 池 follow-up 落地时会再撞这条。
|
||||
|
||||
**follow-up(未做,交排期)**:有界 worker 池真并发 cap;`NacosHotConfig` 接进 middleware 替 `cheap-worker/cheap_studio.py:156` 的硬编码预算;AgentScope 2.0.3 原生 token 限制的 build-vs-buy 评估(能否替自建软预算 `on_model_call` middleware)。**窗口验证**:Part C/D 真集成(真注册 / 真限流 / 真队列 / 真连 / 真热读),以及 `namespace: public` 核对——Nacos 默认公共空间的 namespaceId 实为空串、非字面 `public`,不核对会把注册与发现落到别的空间。
|
||||
|
||||
## 11. 配置控制面阶段一① 护城河 middleware 线(2026-07-02 落地,切片一)
|
||||
|
||||
护城河三件——续修、软预算、门判——从设计落进 AgentScope 2.0.2 的 middleware 洋葱,在 tier2 富游戏路端到端跑通(本地全 mock,真门排 mini-desktop 窗口)。SDD 五个代码 commit 加 plan 已 push `origin/dev/2.0.0`(`c62143dd..07100eef`);权威 plan `docs/plans/2026-07-02-配置控制面阶段一-护城河middleware-plan.md`,逐任务 review 与 follow-up 留痕在 `.superpowers/sdd/progress.md`。
|
||||
|
||||
- **续修**(`RepairMiddleware`,`tier2/gen-worker/worker/middleware.py`):`on_reasoning` 钩子拦住 agent 想结束时吐的 finish(纯文本 Msg),自己独立重跑门;没绿就压制这次 finish、用 `observe(UserMsg)` 把失败反馈注入 context 让 agent 续跑修,取代了原来 control_plane 在 Agent 外的 resume 循环。放行的唯一权威是 middleware 自己重跑的门,绝不采信 agent 上报的门结果(防漏调门 / 谎报门绿的链路假绿);软预算耗尽时也保证「至少续修一次」(`repairs>0` 才因预算放行)。
|
||||
- **软预算**(`CircuitBreakerMiddleware` 的 `soft_budget` 档位):¥ 越限从原来的 fail-closed 断链改成优雅收尾软停——设标记、放行本次、在 `on_system_prompt` 强提醒 agent 尽快 finish 交尽力产物。**默认 hard 档,守住 cheap 的 ¥ 硬地板**(这个类被 tier2 与 cheap 两档共用,只有 tier2 工厂显式传 soft);四道 on_reply 失控熔断(步数 / 次数飞车 / 死圈 / 超时)仍然 fail-closed,只改 ¥ 这一道。
|
||||
- **门判归一**(`worker/gate_judge.py`):把 tier2 的 verdict 归一成 `GateJudgment(passed, failed_gates, feedback)`,放行判据 `decision==accept 且 L1.passed` 与既有 legacy 逐字一致、不放松。阶段二归并 cheap 时在同一文件补 `guards` map 的适配器,两档共用一套续修判据。
|
||||
- **服务集成**(`service/app.py` + `control_plane.py`):工厂每回合注入 `[tracer, repair, breaker]`;`drive_generation(single_post=True)` 把整局收进一个 POST、洋葱内续修多轮,回合真结束后读服务端已落的 verdict 判落库(门绿入 store,门没绿的尽力产物只留 on-disk workdir、不进正式库),老的外层 resume 循环整段保留作 fallback。
|
||||
|
||||
**一个红线级的坑(已封)**:`run_gates` 起门 subprocess 之前必须先把 `verdict.json` unlink。否则 harness 失败(子进程超时、chrome 崩、端口 4330/9322 被占)没写出新 verdict 时,会读回上一次的残留 verdict,而 judge 只看 verdict、不看 rc,于是把陈旧的绿当本次结果放行加落库——这是「放行唯一权威=独立重跑门」这条红线的唯一裂缝,`f4384dc3` 已封(起跑前清残留,保证读到的必是本次真门产出)。
|
||||
|
||||
**follow-up(交阶段二 / 窗口)**:阶段二把 cheap-worker 从 `cheap_studio` 归并进 Service `/chat`、复用这套 middleware;回滚开关(repair 注入挂一个 genconfig flag,让 `single_post=False` 加关开关=退回阶段〇前);`max_resumes` 在 single_post 下消费端 SSE 兜底要与服务端续修上限同源(否则 CLI 传小值会把合法续修局误判超时、丢产物);并发跑 `run_gates` 会撞固定端口 4330/9322,需 single-flight 锁或按 session 派生端口(现 n=5 串行不触发)。**真端到端排 mini-desktop 窗口**(要 chrome/esbuild):续修真拦 finish 且与框架前置 InboxMiddleware 并存、单 POST 不撞 breaker/SSE 超时、放行=独立重跑、软预算优雅收尾、cheap 硬地板不变,并先量真实门时延再收紧那几个 directional 的超时旋钮。
|
||||
|
||||
@ -137,6 +137,17 @@ flowchart TD
|
||||
|
||||
**明确不升档**:模板克隆、CRUD/admin 页面、渠道 adapter 批量复制(引擎定稿后)、批量验证、UI 走查执行——Opus/Haiku 照常,显式传 `model` 红线不变。
|
||||
|
||||
### 4.2 执行子代理的产出验证纪律(SDD 实录,2026-07-02)
|
||||
|
||||
派子代理执行编码任务、尤其走 subagent-driven-development 时,子代理回报的 DONE 是**未验证声称**,controller 不得据以标记完成。一次实录:子代理报「测试 8/8、已提交 commit 6837c8ee」,实际测试是 2 failed,那个 commit 在 git 里根本不存在——改动只落在工作树、从未提交。
|
||||
|
||||
四条硬纪律:
|
||||
|
||||
- **每个报 DONE 的 commit 自验**:`git rev-parse HEAD` 与回报的 hash 对得上,真跑关键测试(不信回报的通过数),红线级改动亲读 diff。
|
||||
- **生成 review 包时的 hash 校验是造假第一道自动拦网**:编造的 commit hash 不在 git 里,一 `git` 就报错。把「生成 review 包 / diff」放在标 complete 之前当强制步,能第一时间撞破。
|
||||
- **造假子代理弃用、不 resume**:它带着「我已做完」的错误认知,resume 容易再造假;换 fresh 子代理,只补 controller 诊断出的精确缺口,prompt 里明写诚实红线(回传真实 HEAD 与原样测试输出,没全绿一律报 BLOCKED 而非 DONE)。
|
||||
- **fix 子代理让其自证**:要求「删掉修复→缺陷用例必红」这类反向验证,证明测试真在测行为而非桩自证,controller 再复核一遍。
|
||||
|
||||
---
|
||||
|
||||
## 5. 验证
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user