Merge branch 'main' into feat/audit-trace-freeze

This commit is contained in:
Fasthei
2026-06-10 21:39:22 +08:00
committed by GitHub
37 changed files with 1424 additions and 67 deletions
@@ -59,7 +59,7 @@
2. **中成本**:~~`reward`~~(✅ 已关闭,本仓)— `Q_quality` 主输入已由 fixture 沙箱采集;剩余为**扩充统一任务集** + 接入 `CodeReview`/`UserAcceptance` 评审/验收信号(部分需 Product/Manager)。
3. **高成本**:
- ~~`p_decision`~~(✅ 已关闭,本仓,Option A)— `τ/η/P` 决策引擎与信息素历史库已落地(`ENABLE_ACO_DISPATCH` 门控);剩余为 Option B 双边匹配与决策质量验证(依赖 Group C)。
- `gain`(及由其驱动的 `Benchmark_Agent`、`G_E,c`、「Swarm > baselines」验收)— 实现 4 类基线运行器 + 统一数据集 + 对比/显著性,属跨团队与基础设施工作(见 baseline-comparison)。**这是最后一块,也是唯一动验收的一块。**
- `gain`(及由其驱动的 `Benchmark_Agent`、`G_E,c`、「Swarm > baselines」验收)— 🟡 **基线对比管线已落地**(`benchmark/runners/` + `tasksets/` + `reports/` + `replay/`,#21/#22),CI offline smoke 跑通;但 **Offline 仅验证管线(G_E=0、无偏)**,真实 `G_E>0` 仍需 `--backend openai` + 足量冻结任务集 + 多次运行(方差/显著性)+ Quality 评审/验收输入。**这是最后一块,也是唯一动验收的一块**(见 baseline-runners.md)。
## 6. 影响
+10 -4
View File
@@ -55,10 +55,16 @@
| 组件 | 位置 | 状态 |
|---|---|---|
| 基线运行器 A–D | `benchmark/baselines/` | 🔴 未实现 |
| 统一任务集 / 数据集 | `test-data/` + `benchmark/baselines/` | 🔴 未实现 |
| 指标采集 | `benchmark/collectors/` | 🔴 未实现 |
| 对比与显著性 | `benchmark/` | 🔴 未实现 |
| 基线运行器 A–D + Swarm | `benchmark/runners/`(single/strong/chain/sub_agent/swarm + base/backend) | 🟡 已实现(管线);真实数值需模型 key |
| 共享执行后端(公平网关) | `benchmark/runners/backend.py`(Offline + OpenAI) | 🟡 Offline 已实现(确定性、无偏);OpenAI 需 `OPENAI_API_KEY` |
| 统一任务集 / 数据集 | `benchmark/tasksets/`(`coding-set-1`) | 🟡 1 个示例任务集;其余场景待建 |
| 指标采集(评分) | held-out fixture + 沙箱(Group B)→ runner | 🟡 TestPassRate 真实;CodeReview/UserAcceptance 掩码缺 |
| 对比 + 报告 + 回放 | `benchmark/reports/`、`benchmark/replay/`、`baselines/comparison.py` | ✅ 已实现 |
| 显著性(多 run 方差) | — | 🔴 未实现(confidence 现按 run 数标注) |
> ⚠️ **Offline 后端为管线验证**:所有系统拿到同一参考解 → quality 相同 → **G_E=0、swarm_valid=False**,
> **刻意不显示蜂群优势**(防造假)。真实 `G_E>0` 需 `--backend openai` + 足量冻结任务集 + 多次运行。
> 入口:`scripts/run-benchmark-suite.py`;说明见 [`baseline-runners.md`](./baseline-runners.md)。
## 6. 待对齐
+4 -2
View File
@@ -1,8 +1,10 @@
# Baseline Run Record Schema(基线运行记录 · 共享契约)
> 状态:**Schema + 比较评估器已落地;记录生产(尤其 Quality)未落地**。
> 状态:**Schema + 评估器 + 记录生产(runner)均已落地;Quality 仅 TestPassRate 真实,CodeReview/UserAcceptance 仍缺;真实数值需模型 key**。
>
> 依据:**Agent 蜂群指标量化与标准 v2.0 §6, §9**。实现:`benchmark/baselines/comparison.py`(`BenchmarkRunRecord` / `compare` / `evaluate`)。配套:[`baseline-comparison.md`](./baseline-comparison.md)、[`emergence-evaluation.md`](./emergence-evaluation.md)、[`cost-normalized-gain.md`](./cost-normalized-gain.md)、[`IMPORTANT-metric-coverage-gaps.md`](./IMPORTANT-metric-coverage-gaps.md)。
> 依据:**Agent 蜂群指标量化与标准 v2.0 §6, §9**。实现:`benchmark/baselines/comparison.py`(`BenchmarkRunRecord` / `compare` / `evaluate`)+ `benchmark/runners/`(5 系统产出记录,见 [`baseline-runners.md`](./baseline-runners.md))。配套:[`baseline-comparison.md`](./baseline-comparison.md)、[`emergence-evaluation.md`](./emergence-evaluation.md)、[`cost-normalized-gain.md`](./cost-normalized-gain.md)、[`IMPORTANT-metric-coverage-gaps.md`](./IMPORTANT-metric-coverage-gaps.md)。
>
> 更新:`code_review_score`/`user_acceptance` 现为 **Optional**(runner 仅采 TestPassRate 时传 None,`quality()` 掩码归一;None ≠ 0)。
## 1. 目的
+59
View File
@@ -0,0 +1,59 @@
# 基线运行器与基准套件(Benchmark Group C · #21/#22)
把「swarm vs 基线」从纸面公式变成**可运行的管线**:统一任务集 → 5 个系统各跑一遍 → 统一
`BenchmarkRunRecord` → 评估器算 `G_E`/`G_E,c` → 报告 + 回放归档。本文是 Group C 的唯一入口。
## 1. 管线
```
benchmark/tasksets/<id> ──┐
├─ runners.run_all(taskset, backend) ──► {system: BenchmarkRunRecord}
共享 ExecutionBackend ──────┘ │(5 系统同后端同任务集,仅拓扑不同)
▼
reports.build_report ──► G_E / G_E,c / coverage / confidence / swarm_valid
▼
replay.save_archive ──► records.json / report.json / report.md / meta.json
```
入口:`scripts/run-benchmark-suite.py --taskset coding-set-1 [--backend offline|openai]`。
## 2. 五个系统(标准 §9.1,仅拓扑不同)
| system | 文件 | 拓扑(公平:同后端同任务集) | n_agent |
|---|---|---|---|
| single | `runners/single.py` | 1 次生成,无评审 | 1 |
| strong | `runners/strong.py` | 1 次生成,**更强/更贵后端**(×0.95 最难超) | 1 |
| chain | `runners/chain.py` | 串行 impl→test→doc,无协作/评审 | 3 |
| sub | `runners/sub_agent.py` | 主管分解 + 3 子агент,无对等/评审(×0.90 最近邻) | 4 |
| swarm | `runners/swarm.py` | **去中心化**:种子 → 自选 + 自主分解 → 专家执行 → **同伴交叉评审** → 收敛 → 综合(calls=6, review=1) | 3 |
> swarm 拓扑已对齐**去中心化重构**(播种/自选/自主分解/竞争/交叉评审/收敛,见 `docs/swarm/decentralized-rework-plan.md`),非旧 Master「分解→派发→单评审」。仍用**同一离线后端**建模以保证公平对比;驱动活体编排器会换后端→记录不可比,故另计(见 `runners/swarm.py` 说明),活体全流程由 `scripts/test-workflow-e2e.py` 验证。
每个系统的产出物用 **fixture 留出测试**在 Group B 沙箱里评分得 `TestPassRate`(权威,非自评)。
## 3. 执行后端(公平网关,`runners/backend.py`)
- **OfflineBackend**(默认):确定性、无 key、无网络。回显 fixture 的 `reference_solution/`,按调用数计名义成本。**对所有系统完全相同** → 管线可验证,但**不可能也不应显示蜂群质量优势**(防造假)。
- **OpenAIBackend**:真实 OpenAI 兼容生成(需 `OPENAI_API_KEY`),产出真实文件 + token/成本。**真实 `G_E` 由它产生。**
## 4. 当前能得到什么 / 不能得到什么
**能**(Offline,CI 每次跑):完整管线、5 份非 NaN 记录、`G_E`/`G_E,c`/coverage/confidence、回放归档、Markdown 报告。
**不能**(诚实):
- Offline `G_E=0`、`swarm_valid=False`——同一参考解,无差异。**这是正确的反造假结果,不是 bug。**
- 真实 `G_E>0` 需 `--backend openai` + **足量冻结任务集**(当前仅 1 个示例任务)+ **多次运行求方差**(当前 confidence=none/low)。
- `CodeReview`/`UserAcceptance` 未采集(掩码忽略)。
- 完整 `Benchmark_Agent` 需**活体 swarm run 的 SwarmMetrics**(S_swarm/Reward/Observability,来自 Group A/B 的 collector)与本套件 `G_E` 的合成——报告里标为 NOT AVAILABLE,**不猜数**。
## 5. 与验收(#13/Issue #2)的关系
本套件是 #13 验收的**必要管线**,但**本身不构成验收**。验收要求:真实后端、冻结任务集、多次运行、
对**全部** A–D 满足 `G_E>0` 且 `G_E,c>0`、并能排除「靠堆 Agent/Token 变强」。在拿到这些真实结果前,
**不得关闭 Issue #2/#13,不得宣称 Agent Swarm 正式验收通过。**
## 6. 测试
- `scripts/test-benchmark-runners.py`:5 runner 产出有效记录、offline 质量一致(G_E=0 反造假)、
报告/coverage/confidence、回放归档(hermetic)。
- `scripts/run-benchmark-suite.py`:CI offline smoke gate(防回归)。
+45 -29
View File
@@ -1,6 +1,12 @@
# Swarm 运行时事件 Schema(回调 / 事件流)
> 状态:**已对齐 HM 实现**(依据 `heicode-mananger/heicode/controller/agent_callback.go`,handler `POST /api/agent/callbacks/runtime-events`)。本文是 Swarm → HM 回调与 `GET …/{id}/events` 事件流的统一 schema。
> 状态:**FROZEN v1(契约冻结)** —— 回应 `agent_swarm#15`(来自 HM #28/#45/#46 客户端「任务驾驶舱」消费需求)。本文是 Swarm → HM 回调与 `GET …/{id}/events` 事件流的统一 schema,已对齐 HM 实现(`heicode-mananger/heicode/controller/agent_callback.go`,handler `POST /api/agent/callbacks/runtime-events`)。
>
> 冻结要点(实现见 `orchestrator/swarm_runtime.py`,契约测试 `scripts/test-contract-freeze.py`):
> 1. envelope 带 **per-swarm 严格递增 `sequence`**(从 1、无空洞,供客户端 `events?after=` 去重/续传,§2)。
> 2. **客户端 13 类事件**(§4 标 ⭐)冻结为 `FROZEN_CLIENT_EVENT_TYPES`(`swarm_runtime.py`)。
> 3. **artifact** 扁平字段 `{uri, checksum, task_id, size_bytes?, created_at}`(§3)。
> 4. **凭据红线**:`secret_ref`/`credential_ref`/`signing_secret_ref` 为 `azkv://` 引用(非明文),Swarm 侧 `_redact_sensitive` 透传引用、剔除明文 `*_token/_secret/_key/password`;客户端可见视图由 HM 再做递归脱敏。
>
> 配套:生命周期与签名见 [`runtime-contract.md`](./runtime-contract.md)。
@@ -22,6 +28,7 @@
{
"event_id": "evt-...", // 必填;去重主键
"idempotency_key": "...", // 可选;缺省回退 event_id
"sequence": 12, // 必填;per-swarm 严格递增(从 1、无空洞);客户端按此去重/升序/续传
"event_type": "task.completed", // 必填;取值见 §4
"deployment_id": "runtime-dep-...",// 运行时部署 ID
"swarm_id": "swarm-...", // 工作流 ID(事件按此持久化)
@@ -44,41 +51,47 @@
"artifact_type": "code_patch | document | deployment_manifest",
"title": "...",
"summary": "...",
"uri": "git://repo#branch | runtime://...",
"uri": "git://repo#branch | runtime://...", // 仅 uri,绝不含 secret_ref/凭据
"checksum": "<commit_sha>",
"task_id": "...", // 缺省回填 envelope.task_id(#15.4)
"size_bytes": 1234, // 可选;未知则省略(不伪造,规则 #9)
"created_at": "2026-06-08T...Z", // 缺省回填 envelope.occurred_at
"metadata": { "redacted": true, "agent_role": "...", "files_modified": [] }
}
```
> 客户端 artifact 视图(HM #28)取扁平 `{uri, checksum, task_id, size_bytes?, created_at}`;HM 由 `artifact.created` envelope 的上述字段直接产出,无 `secret_ref`/密钥。
## 4. 事件类型注册表(与 HM 一致)
⭐ = **冻结的客户端 13 类**(`FROZEN_CLIENT_EVENT_TYPES`,驾驶舱据此渲染;HM `agent_callback.go` 据此对齐注册表)。其余为 Swarm 也发的辅助/运行时事件(HM 仍消费,但非客户端必需)。
| event_type | payload 必填字段(HM 校验) | 分类 | Swarm 是否发出 |
|---|---|---|---|
| `deployment.status_changed` | `status` | deployment | ✅ |
| `phase.changed` | `stage` 或 `checkpoint` | ordinary_sub | ❌(暂未用) |
| `agent.started` | `agent_role` | ordinary_sub | ❌ |
| `agent.completed` | `agent_role` | ordinary_sub | ❌ |
| `agent.crashed` | `agent_role`, `reason` | ordinary_sub | ❌ |
| `task.created` | `task_id`, `title` | swarm_task_flow | ✅ |
| `task.claimed` | `task_id`, `agent_role` | swarm_task_flow | ✅ |
| `task.running` | `task_id`, `agent_role` | swarm_task_flow | ✅ |
| ⭐ `task.created` | `task_id`, `title` | swarm_task_flow | ✅ |
| ⭐ `task.claimed` | `task_id`, `agent_role` | swarm_task_flow | ✅ |
| ⭐ `task.running` | `task_id`, `agent_role` | swarm_task_flow | ✅ |
| ⭐ `task.completed` | `task_id` | swarm_task_flow | ✅ |
| ⭐ `task.failed` | `task_id`, `reason` | swarm_task_flow | ✅ |
| ⭐ `handoff.created` | `task_id`, `from_role`, `to_role` | swarm_task_flow | ✅(child 任务建立时,与 `handoff.requested` 并发) |
| ⭐ `approval.requested` | `approval_id`, `operation`, `risk_level` | approval | ✅ |
| ⭐ `approval.approved` | `approval_id` | approval | ✅(审批决定落地时) |
| ⭐ `approval.rejected` | `approval_id` | approval | ✅(审批决定落地时) |
| ⭐ `artifact.created` | `artifact_id`, `uri`, `checksum` | artifact | ✅(带 §3 扁平字段) |
| ⭐ `swarm.completed` | `status` | swarm_terminal | ✅(终态,与 `deployment.status_changed` 并发) |
| ⭐ `swarm.failed` | `status` | swarm_terminal | ✅(终态) |
| ⭐ `swarm.stopped` | `status` | swarm_terminal | ✅(`stop_run`) |
| `deployment.status_changed` | `status` | deployment | ✅(HM 用于 AgentDeployment.Status;客户端用 swarm.* 终态) |
| `task.heartbeat` | `task_id`, `agent_role` | swarm_task_flow | ✅ |
| `task.blocked` | `task_id`, `reason` | swarm_task_flow | ✅ |
| `task.retried` | `task_id`, `attempt` | swarm_task_flow | ✅ |
| `task.released` | `task_id`, `agent_role` | swarm_task_flow | ⚠️ 未发出(见 §6) |
| `task.failed` | `task_id`, `reason` | swarm_task_flow | ✅ |
| `task.completed` | `task_id` | swarm_task_flow | ✅ |
| `task.released` | `task_id`, `agent_role` | swarm_task_flow | ✅ |
| `handoff.requested` | `task_id`, `from_role`, `to_role` | swarm_task_flow | ✅ |
| `handoff.completed` | `task_id`, `from_role`, `to_role` | swarm_task_flow | ⚠️ 缺 `from_role`/`to_role`(见 §6) |
| `approval.requested` | `approval_id`, `operation`, `risk_level` | approval | ✅ |
| `artifact.created` | `artifact_id` | artifact | ✅ |
| `timeline.updated` | `title` | timeline | ⚠️ 发出 `summary`,缺 `title`(见 §6) |
| `sk_tool.called` | `tool_name`, `tool_invocation_id` | sk | ❌(无 SK 工具) |
| `sk_tool.completed` | `tool_name`, `tool_invocation_id` | sk | ❌ |
| `sk_tool.failed` | `tool_name`, `tool_invocation_id`, `reason` | sk | ❌ |
| `budget.alert` | `threshold_pct` | budget | ⚠️ 发出 `threshold`,缺 `threshold_pct`(见 §6) |
| `timeline.updated` | `title` | timeline | ✅(emit 时回填 `title`=`summary`) |
| `budget.alert` | `threshold_pct` | budget | ✅(emit 时回填 `threshold_pct`) |
| `phase.changed` / `agent.*` / `sk_tool.*` | — | ordinary_sub / sk | ❌(本运行时不产生) |
> 说明:评审/重做循环复用 `task.retried` + `timeline.updated`(`Review cycle N`)表达,无单独 review 事件类型;如 HM 前端需要独立 review 事件,列为待对齐项。
> 说明:评审/重做循环复用 `task.retried` + `timeline.updated`(`Review cycle N`)表达,无单独 review 事件类型;蜂群内部遥测(提案/竞价/交叉评审/收敛/health)**不经回调外发**(见各协议文档「事件不进 Manager 流」),故不在本表。`swarm.completed/failed/stopped` 与 `approval.approved/rejected`、`handoff.created` 为本次冻结**新增**,HM 注册表需据此登记(agent_swarm#15.2)。
## 5. HM 响应
@@ -86,13 +99,16 @@
{ "success": true, "event_id": "evt-...", "inserted": true, "idempotent": false, "deduplicated": false, "deployment_id": "dep_..." }
```
## 6. 已知对齐缺口(需在 Swarm 代码修正)
## 6. 对齐状态(冻结时已修正 / 剩余小项)
下列为本仓 `orchestrator/` 当前发出字段与 HM 校验的差异,应在对应 emit 处修正后再宣称完全对齐:
冻结时 `orchestrator/swarm_runtime.emit_event` 已统一处理下列历史缺口:
1. **`timeline.updated`**:HM 要求 `title`;当前发 `summary`。修正:payload 增加 `title`(可复用 `summary`)。
2. **`budget.alert`**:HM 要求 `threshold_pct`;当前发 `threshold`(如 `0.8`)。修正:增加 `threshold_pct`(百分比,如 `80`)。
3. **`handoff.completed`**:HM 要求 `from_role`/`to_role`;当前缺。修正:在 `finalize_parent_after_child` / handoff 完成处补 `from_role`/`to_role`。
4. **`task.released`**:HM 注册表含此事件;`task_queue.release_task` 当前静默。修正:释放任务时发 `task.released`(`task_id`, `agent_role`)。
1. ✅ **`timeline.updated`**:emit 时若缺 `title` 自动回填(复用 `summary`)。
2. ✅ **`budget.alert`**:emit 时若缺 `threshold_pct` 由 `threshold` 自动换算(≤1 视为比例 ×100)。
3. ✅ **`sequence`**:每事件带 per-swarm 严格递增序号(INCR 计数键 `swarm_event_seq:{swarm_id}`)。
4. ✅ **artifact 扁平字段**:`created_at`/`task_id` 自动回填,`size_bytes` 透传(未知则省略,不伪造)。
> 这些是确定性的小修,建议配 contract test(按 HM 必填字段断言每类事件 payload)。
剩余小项(不影响客户端 13 类冻结):
- `handoff.completed` 的 `from_role`/`to_role`:辅助事件,客户端 13 类用 `handoff.created`(已带 from/to);如 HM 仍消费 `handoff.completed`,在 handoff 完成处补两字段为后续小修。
> 契约由 `scripts/test-contract-freeze.py` 守护(断言 sequence 单调、13 类 round-trip、artifact 形状、审批/停止真实发出、明文凭据脱敏);`scripts/test-workflow-e2e.py` 在全流程 e2e 中额外断言 `swarm.completed` + sequence 无空洞。
+32 -8
View File
@@ -1,12 +1,16 @@
# Manager ↔ Swarm Runtime Contract(Swarm 侧拥有)
> 状态:**草案(Swarm 侧拥有,待 HM 对齐)** · 对齐对象:Heicode Manager Runtime Team
> 状态:**FROZEN v1(契约冻结)** —— 回应 `agent_swarm#14`(来自 HM #28/#45 客户端「任务驾驶舱」查询面:stop 端点 + ID 映射 + 状态机)。对齐对象:Heicode Manager Runtime Team。
>
> 冻结结论(供 HM #45 接 stop 真实调用):
> - **stop 端点**:`POST /api/agent/swarm/deployments/{id}/stop`(§3),已实现,幂等键 `X-Idempotency-Key`。
> - **ID 映射**:`deployment_id ↔ swarm_id ↔ manager_deployment_id`(§3.2),`get_run_by_identifier` 支持任一 id 查询。
> - **状态机**:运行时真实状态见 §4;与客户端 #28 期望(含 `preparing/degraded/verifying`)的**映射表见 §4.1**(运行时不新增臆造状态,规则 #9)。
>
> 依据:
> - HM 侧裁定 `heicode-mananger/docs/integration/heicode-swarm-deferred.md`:**HM 当前不实现 swarm runtime**;多 Agent 蜂群归 `agent_swarm` / `HeiCode-Swarm`(本仓);HM 侧待本仓给出正式 `/api/agent/swarm/*` 接口后,在 HM 的 `docs/integration/` 另立契约跟踪。
> - HM 侧裁定 `heicode-mananger/docs/integration/heicode-swarm-deferred.md`:**HM 当前不实现 swarm runtime**;多 Agent 蜂群归 `agent_swarm` / `HeiCode-Swarm`(本仓)。
> - 既有运行时集成范式 `heicode-mananger/docs/integration/heicode-am-contract.md`(单 Agent 模板 Agent,经 AM 启动)。本契约沿用其鉴权、回调、env、路径覆盖等约定。
>
> 本文是 HM 侧 deferred 锚点所要求的「Swarm 侧正式接口」起草。冻结需 Manager Runtime Team 评审。
> - 事件 envelope/类型见 [`event-schema.md`](./event-schema.md)(同批冻结,`agent_swarm#15`)。
## 1. 角色与边界
@@ -65,7 +69,23 @@ create 响应 `data`:`deployment_id`、`runtime_deployment_id`、`manager_depl
| `failed` | 存在失败且不可恢复 | 任务终态含 failed |
| `stopped` | Manager 主动停止 | `…/stop` |
每次状态变更通过回调 `deployment.status_changed` 推送(见 §5)。
每次状态变更通过回调 `deployment.status_changed` 推送(见 §5);**终态另发** `swarm.completed`/`swarm.failed`/`swarm.stopped`(客户端驾驶舱据此切终态横幅,见 event-schema §4)。
### 4.1 与客户端期望状态的映射(#14.3 决议:映射,不新增运行时状态)
客户端 #28 期望 `created/preparing/running/waiting_approval/degraded/verifying/completed/failed/stopped`。本运行时**不臆造** `preparing/degraded/verifying` 等中间态(规则 #9:无真实信号不造态),由 HM/客户端按下表映射现有真实状态:
| 客户端期望态 | 运行时真实来源 | 映射口径 |
|---|---|---|
| `created` | create 成功、尚无在途任务 | 初始 `running` 前的瞬态;HM 可在落 `runtime_swarm_id` 后、首个 `task.*` 前显示 |
| `preparing` | 同上(播种中) | 映射到 `running`(种子已注入、Agent 尚未自选);无独立状态 |
| `running` | `running` | 直通 |
| `waiting_approval` | `waiting_approval` | 直通 |
| `degraded` | `blocked` | `blocked`(移交/依赖/审批驳回阻塞)映射为 `degraded`;P-guard `run.metadata["health"]` 不健康亦可佐证 |
| `verifying` | `running` + 交叉评审进行中 | 评审期仍是 `running`;如需细分,由 `timeline.updated`(`Review cycle N`) / `run.metadata["cross_review"]` 提示 |
| `completed`/`failed`/`stopped` | 同名终态 | 直通;并有 `swarm.{completed,failed,stopped}` 终态事件 |
> 即:运行时真实状态集 = `waiting_approval/running/blocked/completed/failed/stopped`(§4 表);`created/preparing/degraded/verifying` 是**展示层别名**,不改变运行时语义,也不进入回调 `status` 字段。如客户端坚持要真实细分态,需另立工单评估状态机扩展(非本次冻结范围)。
## 5. 回调(已与 HM 处理器对齐)
@@ -88,9 +108,13 @@ HM 侧可用 env 覆盖:`AGENT_RUNTIME_BASE_URL`、`AGENT_RUNTIME_SERVICE_TOKE
- `env`/请求体不得含明文密钥;凭据经 `secret_ref`(`azkv://`)注入。详见 [`security-boundary.md`](./security-boundary.md)。
- Swarm 启动接口必须 HTTPS / 私网;回调走 HTTPS。
## 8. 待对齐项(冻结前需 Manager Runtime Team 确认)
## 8. 冻结状态与剩余对齐项
- [ ] resume / retry 是否需要独立外部端点,还是沿用 approvals + 内部重做。
本次冻结(agent_swarm#14)已定稿:stop 端点(§3)、ID 映射(§3.2)、状态机 + 客户端映射表(§4/§4.1)、终态 swarm.* 事件。HM #45 可据此接 stop 真实调用。
剩余非阻塞项(不影响 #45 Phase1 接入):
- [ ] resume / retry 是否需要独立外部端点,还是沿用 approvals + 内部重做(当前:无独立端点)。
- [ ] HM 是否以 AM 同款 `/agents` 生命周期(而非 `/api/agent/swarm/*`)调用 Swarm;若是,需路径映射。
- [ ] `event-schema` 中各 event_type 的必填字段与 HM 注册表逐项核对(见 event-schema.md)。
- [ ] HM 注册表(`agent_callback.go`)登记本次新增的 `swarm.completed/failed/stopped`、`approval.approved/rejected`、`handoff.created`(见 event-schema §4 ⭐)。
- [ ] 更新 HM 侧 `heicode-swarm-deferred.md` 锚点,登记本契约。
- [ ] #46 Phase2(SSE 长连 + 追加输入写语义):待本契约 + event-schema 冻结后由 HM 把轮询升级 SSE(见 frontend-event-api.md §4)。
+17 -9
View File
@@ -1,6 +1,10 @@
# 安全边界(Secret / Workspace / Tool / Approval / Tenant / Sandbox)
> 状态:**部分已实现,部分待接入**(依据 `heicode-mananger/docs/heicode.md §六/七`、`docs/heicode-runtime-auth-newapi-secret-design.md §三/五`、`docs/integration/heicode-am-contract.md §3.1/§4`)。
> 状态:**已强制边界 FROZEN v1(可验证)+ 部分待接入**(依据 `heicode-mananger/docs/heicode.md §六/七`、`docs/heicode-runtime-auth-newapi-secret-design.md §三/五`、`docs/integration/heicode-am-contract.md §3.1/§4`)。回应 issue #19。
>
> **本仓强制并可验证的边界**(契约测试 `scripts/test-security-boundary.py`,CI 守护):① secret 仅 `azkv://` 引用、明文密钥入口拒绝、回调/持久化脱敏;② workspace 写入路径越界(绝对路径 / `..` 逃逸)拒绝;③ 代码沙箱 **fail-closed**(未确认隔离则拒绝执行)。
>
> **本次不扩展(确认的边界/后续层,非本仓可改)**:tool/MCP 权限引擎(**无 SK/MCP 工具层**可治理)、租户隔离(**有意**按 `user/channelId` 归因、不引入 tenant)、Pod 级强化沙箱(seccomp/只读根/NetworkPolicy,归 Infra/Security)。详见 §9。
>
> 配套:[`runtime-contract.md`](./runtime-contract.md)、[`usage-billing-schema.md`](./usage-billing-schema.md)。
@@ -84,17 +88,21 @@
## 9. 覆盖与缺口
✅✔ = 已实现**且有契约测试**(`scripts/test-security-boundary.py`)。
| 边界 | 状态 |
|---|---|
| `azkv://` `secret_ref` 强校验 / 明文拒绝 / 脱敏 / `.gitignore` | ✅ 已实现(本仓) |
| Workspace 路径越界校验 | ✅ 已实现 |
| 审批状态机(waiting_approval + approvals 回执) | ✅ 已实现(逐项校验待加强) |
| `azkv://` `secret_ref` 强校验 / 明文拒绝 / 脱敏 / `.gitignore` | ✅✔ 已实现 + 测试(`validate_create_request`/`_reject_plaintext_secrets`/`_redact_sensitive`) |
| Workspace 路径越界校验(绝对路径 / `..` 逃逸拒绝) | ✅✔ 已实现 + 测试(`task_executor._resolve_workspace_path`) |
| 代码沙箱 fail-closed(`assert_isolated`:未确认隔离拒绝执行;启动 `assert_quality_eval_safe`) | ✅✔ 已实现 + 测试(§8.1 双门控 `ENABLE_QUALITY_EVAL`+`HEICODE_SANDBOX_ISOLATED`) |
| 审批状态机(waiting_approval + approvals 回执) | ✅ 已实现(逐项 TTL/范围校验待加强) |
| 短期凭证派生注入、Workload Identity | 🟡 AM/K8s 侧 |
| Tool/MCP 权限引擎 | 🔴 未实现 |
| allowed_paths 运行时强制、强隔离 | 🔴 未实现 |
| 代码测试沙箱(Pod 内纵深防御 + 环境清洗 + 超时/限额;**fail-closed 双门控** `ENABLE_QUALITY_EVAL` + `HEICODE_SANDBOX_ISOLATED`,启动/运行时硬失败) | ✅ 已实现(本仓,§8.1);OS 级隔离仍依赖 Pod |
| 强化执行沙箱(seccomp/只读根/网络策略/能力裁剪,Pod 层) | 🔴 未实现(Infra/Security) |
| 租户隔离 | ⛔ 不在本仓(归因按 user/channelId) |
| Tool/MCP 权限引擎 | ⏸ 本次不做 —— **无 SK/MCP 工具层可治理**;待工具层落地后随其设计权限边界 |
| allowed_paths 运行时强制(按 grant 限定)、强隔离 | ⏸ 本次不做 —— 当前仅 workspace 根越界强制;按 grant 的 allowed_paths 待资源授权链接入 |
| 强化执行沙箱(seccomp/只读根/网络策略/能力裁剪,Pod 层) | ⏸ 本次不做 —— 归 Infra/Security(Pod manifest) |
| 租户隔离 | ⛔ **有意**不在本仓(归因按 `user/channelId`,不引入 tenant 概念) |
> ⏸ = 确认的后续/外部层,非本仓本次范围(按规则 #9 不伪造「已强制」)。本仓**已强制**的三类边界均可由 `scripts/test-security-boundary.py` 验证。
## 10. 待对齐对象