回应 Fasthei 的 Request changes 两个阻塞项:
1) 安全 / fail-closed 沙箱隔离(原仅靠 ENABLE_QUALITY_EVAL + 运维约定):
- 新增第二道显式确认 HEICODE_SANDBOX_ISOLATED(断言运行在隔离 Pod 内)。
- sandbox.run_tests() 与 quality.evaluate_run_quality() 执行任何代码前调用
assert_isolated(),未确认即抛 SandboxIsolationError——不写文件、不起子进程。
- 启动期 assert_quality_eval_safe():ENABLE_QUALITY_EVAL 开但隔离未确认 → 拒绝启动
(平台级硬失败,非运维口头约定)。
- 文档(security-boundary §8.1/§9、CLAUDE.md)与测试同步:test-sandbox/test-quality
先断言未确认时硬失败,再显式确认后继续。
2) #10 DecisionTrace 可回放(原仅存被选中任务的标量):
- Decision 现记录完整重放上下文:整个候选集(每候选 tau/eta/weight/p_norm/dependents)、
alpha/beta/epsilon、seed、free_slots、total_weight、explore_draw、select_pick、
select_index、explored 分支。
- 新增 DecisionEngine.replay_decision(trace):仅凭一条 trace(无 RNG/活体状态)复现被选任务;
test-decision-engine 断言「重放==实选」跨 50 次决策(探索+利用)成立。
- decision-engine.md §3.3 更新为可回放 DecisionTrace。
附:新增 docs/TESTING.md(reviewer 速查:依赖安装 + 每套测试命令,复审者此前因缺 fakeredis
未能跑到断言)。本地 11 项 gate 全绿。
影响范围:Swarm(orchestrator + 测试 + 文档)。不改 Manager↔Swarm 契约;新增开关
HEICODE_SANDBOX_ISOLATED(默认未设=拒绝执行)。仍非验收:gain/Benchmark_Agent 仍 NaN。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
6.6 KiB
6.6 KiB
ACO 决策引擎(Benchmark Group A):τ / η / P_decision
让标准 §3 的决策层指标由 NaN 转为可测:派发从「确定性贪心首配」变为「信息素 × 启发式的概率采样」。本文档是该机制的唯一入口。
1. 方案选型:Option A(score-at-pull,单边)
派发是双边匹配(任务挑 Agent / Agent 挑任务)。本实现取 Option A:
- 候选集 = 「当前空闲 Agent 视角下的全部就绪任务」。Agent 由到达顺序固定,任务由
P_i = τ_i^α·η_i^β / Σ采样选出(ε-greedy 探索,ε=0.10)。 - 已知局限(单边):τ 影响的是「该 Agent 先做哪个任务」,而非「该任务给谁做」——强专家若晚到,仍可能输给先拉取的弱者。全局双边匹配(Option B:matchmaker 调度 tick + hold 策略)推迟到 Group C 基线就绪后再评估,因为「更优匹配」是一个当前无法度量的优化命题。
- A 是 B 的严格子集:信息素库、η 评分、采样、遥测、collector 全部复用,B 只需更换选择触发点。
2. 双半开关(核心设计)
| 半边 | 开关 | 默认 | 行为 |
|---|---|---|---|
| 学习(信息素沉积) | 无(常开) | 开 | 任务到达终态即更新 τ trail。纯被动观察,不改变任何派发行为;为未来开启选择积累「实测声誉」而非冷启动先验 |
| 行动(概率选择) | ENABLE_ACO_DISPATCH |
关 | 关闭时派发与原贪心逐字节一致;开启时走采样路径并记录决策遥测 |
CI 同时跑两条:默认全套(flag off,证不变性)+ ENABLE_ACO_DISPATCH=1 ACO_SEED=42 的 e2e(证开启后工作流仍完整收敛)。
3. 机制
3.1 信息素 τ(pheromone:{agent_role}:{agent_id},Redis)
- 更新(标准 §3.1):
τ(t+1) = (1−ρ)·τ(t) + Δτ,ρ=0.10,夹紧到[0.05, 1.0](正性保证τ^α良定义;上界即 trail 饱和)。 Δτ = metrics.pheromone(...),只喂真实信号:success(1/0)、quality(暂 = success,run 级 fixture 评分发生在任务完成之后、沉积之时不可得)、cost(任务成本/run 预算,未知则 0)。acceptance/time/risk/rollback 无信号 → 0,不伪造(规则 #9)。- 冷启动 τ₀ = 0.5(中性先验);单次 run 的 τ 多为先验,需多 run 积累才是「挣来的声誉」——已如实标注。
- trail 按
(agent_role, agent_id)键控、跨 run 持久(这正是 τ 的意义)。
3.2 启发式 η(纯函数,无新状态)
metrics.heuristic(...) 输入全部来自编排器既有状态:match(required∩caps 的 Jaccard,奖励专精)、urgency(任务等待时长,300s 饱和)、dependency(下游依赖数,3 饱和)、resource(Agent 空闲槽位)、confidence=0.5(无信号 → 对所有候选同值中性常数,不扭曲排序)、risk/budget_pressure=0(无信号)。下限夹紧 0.05。
3.3 选择与遥测
P_i = τ^α·η^β / Σ(α=1, β=2),ε-greedy 均匀探索防饿死(低 τ Agent 仍偶得任务,从而有机会重建 trail)。- 可回放 DecisionTrace(PR #24 复审整改):每次采样记录的不只是被选中任务,而是重放/解释该选择所需的全部上下文:
- 被选中:
task_id/agent_id/agent_role/tau/eta/p_norm/p_score; - 完整候选集
candidates[]:每个候选的task_id/agent_role/tau/eta/weight/p_norm/dependents; - 超参与上下文:
alpha/beta/epsilon/seed/free_slots/total_weight; - RNG 与分支:
explore_draw(与 ε 比较的抽样)、explored(探索/利用分支)、select_pick(利用分支的绝对 pick)、select_index(解析出的候选下标)。 存入SwarmRun.decisions(内部状态,不进 Manager 事件流,上限 1000 条)。
- 被选中:
- 重放验证:
DecisionEngine.replay_decision(trace)仅凭一条 trace(无 RNG、无活体状态)即可复现被选中的task_id,逻辑与select()完全一致。test-decision-engine.py断言「重放 == 实选」跨 50 次决策(探索+利用两分支)成立 → 满足 #10「DecisionTrace 可回放」DoD。 p_score = τ^α·η^β·100(标准 §3.3 的 P_decision 公式);p_norm为该候选集内的归一化概率,两者并存以免混淆。- collector:run 级
tau/eta/p_decision= 决策记录的均值;无记录 → NaN +coverage=False。
3.4 确定性与 CI
随机源可经 ACO_SEED 固定(CI 用),生产不固定。超参可经 ACO_ALPHA/ACO_BETA/ACO_RHO/ACO_EPSILON 覆盖,默认取标准 §7.2 推荐值。
4. 文件
| 文件 | 职责 |
|---|---|
orchestrator/decision_engine.py |
τ 存取/沉积、η 评分、ε-greedy 采样、Decision 遥测载体 |
orchestrator/task_queue.py: get_ready_pending_tasks |
候选枚举(不出队;选中后再 remove_pending_task) |
orchestrator/main.py |
派发环 ACO 分支 + 四个任务终态处的 deposit_pheromone + 决策落库 |
orchestrator/swarm_runtime.py: SwarmRun.decisions / record_decision |
决策遥测存储 |
benchmark/collectors/run_collector.py |
tau/eta/p_decision 聚合 |
scripts/test-decision-engine.py |
22 项断言(trail 数学/夹紧/键控、η 排序、种子化采样分布、探索、遥测→collector、枚举不出队) |
5. 与 #9(dispatch scoring)的边界
Issue #9(调度评分)与 #10(τ/η/P 决策模型)耦合但分工明确:
- #9 出「打分输入」:候选 Agent×任务的可解释评分维度(capability_match、load、budget_pressure、risk、historical_success、estimated_cost/time),以及每次派发的候选列表与排除原因(
dispatch.decision_made)。 - #10 出「概率决策」:把这些维度归一为 τ(历史)与 η(先验),按
P=τ^α·η^β/Σ概率采样,并产出可回放的DecisionTrace。
本仓 decision_engine.py 已实现 #10 的概率决策层与 τ/η 的最小喂入;#9 的「完整打分 schema + 候选/排除可解释性」为独立增量(docs/scheduling/dispatch-score-schema.md、dispatch.decision_made 事件),不在 #10 关闭范围内。
6. 诚实边界(本机制未关闭的)
- 决策质量未证:概率派发是否优于贪心是经验命题,需 Group C 的对比 harness 才能回答;在此之前生产默认关闭。
- τ 的 quality 输入暂 = success(无每任务质量信号);acceptance/time/risk 无信号 → 0。
- 单边匹配(见 §1);Option B 推迟。
gain/s_swarm/g_e/g_e_cost/benchmark仍 NaN——Group A 不动验收的针。