Files
heicodedebug/chek/2026-06-01_Heicode全链路代码评审报告.md

17 KiB
Raw Permalink Blame History

Heicode 全链路代码评审报告

评审日期:2026-06-01 评审范围:HeiCode-Swarm、heicode-mananger、heicode-macos-release、heicode-winos-release 四仓库代码 评审依据(产品内容):taijibaga 组织 Projects —《Heicode 项目书 v0.2》与《Agnet 蜂群能力评价标准 ASCE v0.1》 性质:只读代码核查,所有结论附 文件:行 证据;不代表对外承诺。


0. 一句话结论

当前代码在 happy path 能跑通单 Agent 演示,但与项目书/ASCE 承诺的“可控、可审计、可度量的软件交付”相比,存在一个系统性病根和六类业务级问题:

病根:关键业务概念(“任务完成”“代码交付物”“状态枚举”“默认模型”“谁来编排”“安全边界”)没有单一权威定义,而是在 Runtime / Manager / 客户端 / 文档 里各写一份,再靠下游正则和文档补丁去对齐。补丁越加越多,缺口反而越堵越漏。

最直接的可观测后果:用户让“写一个博客系统”,系统只产出方案总结(无真实代码),却仍判 completed 并显示“已完成”。


1. 评审对象与产品定位对照

仓库 角色(项目书定义) 技术栈 最新状态
heicode-mananger Manager:SaaS 控制台 + 编排控制面 + 模型网关 Go / Gin 生产 1.4.19
HeiCode-Swarm Agnet 执行层:AKS 上多 Agent 运行时 Python(FastAPI + Agent Worker) 单 Agent MVP,多 Agent DAG 灰度
heicode-macos-release macOS 客户端(用户主体验 + 高危审批) Bun/TS + Tauri v0.4.18
heicode-winos-release Windows 客户端(同源) Bun/TS + Tauri v0.4.17(落后 macOS 一版)

产品愿景(项目书 §3)要求:从想法到上线的全 SDLC、AI 团队化协作、真实资源接入、安全边界可控、成本可见、交付可追溯。 ASCE(评价标准)要求蜂群在:任务完成、能力增益、协作、通信、成本、鲁棒性、安全治理七维度可度量,并设强制降级红线。

本报告即以上述两份为标尺,逐项核查代码实现度。


2. 问题分级总表

编号 问题 严重度 影响(对照标尺) 修复依赖
P1 “任务完成”无可信定义:模型自报 status 即算完成,无产出校验 🔴 阻断 违反项目书 §12.4、ASCE §8.1;完成数据全失真 契约 + Runtime 闸门
P2 “代码交付物”被三处各判一遍且发散,补丁互漏 🔴 阻断 ASCE 交付物完整性失真;UI 自相矛盾 结构化契约
P3 状态枚举对不上:completed 不在文档枚举内 🟠 高 客户端状态机漏终态 枚举统一
P4 编排权威不唯一 + 三条接入路径(左右脑) 🟠 高 审计/计费无法归口;心智混乱 产品决策
P5 默认模型四套口径,自相矛盾 🟡 中 照默认走会 400 / 无可用渠道 单一来源
P6 安全治理“关键路径部分强制 + 大量占位”,多处达不到 ASCE 红线 🟠 高 可能触发 ASCE 强制降级到 L1/L2 补齐强制
P7 鲁棒性多为“有代码但缺原子性/边界”:双执行、orphan、重试均有缺陷 🟠 高 ASCE 鲁棒性维度不可标生产级 加锁/reconcile

3. 详细问题

P1. “任务完成”无可信定义(病根的核心表现)🔴

Runtime 端:Agent 的成功判定,直接信任模型在 JSON 里自填的 status,从不校验是否真有代码产出。

# HeiCode-Swarm/agent/task_executor.py:141
success = all(
    r["status"] in ["completed", "handed_off"]
    for r in results
)

模型完全可以返回 status: "completed" + files: [](把内容写进散文字段),执行器照样判成功。更严重的是 Agent 明知“没有任何文件改动”仍按成功上报:

# HeiCode-Swarm/agent/main.py:264
result["git_skipped"] = "No workspace changes to commit"
...
await self.send_task_result(task_id, result["success"], result)  # success=True

校验环是被主动删掉的(注释自述),删完没有补任何“产出门槛”:

# HeiCode-Swarm/agent/task_executor.py:85
# the previous parse-then-verify loop caused useful file edits to be retried away

Orchestrator 端无条件发 status: "completed",且无文件时仍发一个 document 总结 artifact(最新提交把“方案总结当交付”固化为常规输出):

# HeiCode-Swarm/orchestrator/main.py:494 / 519
artifact_type = "deployment_manifest" if files_modified or files_deleted else "document"
...
"status": "completed",

Manager 端收到 completed 直接镜像,不看产出:

// heicode-mananger/heicode/controller/agnet_callback.go:304
case "deployment.status_changed":
    status := callbackStringValue(source, "status")
    if status != "" {
        record.Status = status
        record.RuntimeState = status

后果:项目书 §12.4 要求 completed 至少有“代码分支/测试结果/交付物”,ASCE §8.1 的构建/测试/交付物完整性在此场景全为 0,但系统判“成功”。


P2. “代码交付物”被定义了三遍,补丁互相不一致 🔴

同一个 artifact_type 字段,三处独立解释、无共享契约:

  1. Runtime 硬编码类型:HeiCode-Swarm/orchestrator/main.py:480,494(code_patch / document / deployment_manifest)。
  2. Manager 存为自由字符串、无枚举无校验,判定时还不读 artifact_type,另起一套基于 title/summary/uri 的探测:
// heicode-mananger/heicode/model/agnet_artifact.go:18
ArtifactType  string `gorm:"type:varchar(64);index" json:"artifact_type"`
// heicode-mananger/heicode/controller/agnet_runtime_client.go:670
strings.Contains(uri, "/artifacts/summary") {
  1. 客户端 又用一套中文正则:heicode-mananger/docs/integration/heicode-desktop-sub-agile-api.md:300-319(classifyArtifact)。

“补丁互漏”的冒烟证据:Manager 探测器靠 uri 含 /artifacts/summary,但 Runtime 最新提交发的 uri 是 runtime://{swarm_id}/artifacts/{task_id}(orchestrator/main.py:500)——不含该关键字,Manager 现在抓不到;同时 Runtime 已把“无文件”表达成 artifact_type="document",Manager 探测器却完全不读它。一次上游重构就让下游补丁失效。

后果:同一份 artifact,Manager 认为正常、客户端弹“不是代码交付物”黄条,顶部却仍显示绿色“已完成”——三方结论打架。


P3. 状态枚举对不上:completed 不在文档定义里 🟠

对接文档定义的合法状态值里根本没有 completed:

# heicode-mananger/docs/integration/heicode-desktop-sub-agile-api.md:1399
### Agnet Deployment.status
| accepted | running | stopped | failed |
### Agnet Deployment.runtime_state
| queued | runtime_syncing | runtime_accepted | runtime_sync_failed | not_configured |

但代码实际写入 completed(agnet_callback.go:307),初始态 accepted(agnet_control_plane.go:1076)。客户端若按文档枚举做状态机,会漏掉真实终态。


P4. 编排权威不唯一 + 三条接入路径(“左右脑互搏”)🟠

“创建多智能体任务”存在三条语义不同、审计能力不同的路径:

  1. 生产主路径:客户端 → Manager POST /api/swarms → Runtime(heicode-desktop-sub-agile-api.md:71,但该入口同时背“普通 sub 适配”和“蜂群”两种模式,过载)。
  2. 旁路:HeiCode-Swarm/desktop-client 自带复杂度分析 + 自动扩 Pod,直连 Orchestrator 原生 /tasks,绕过 Manager 契约。
  3. 客户端本地:heicode-{macos,winos}-release 内置整套本地多智能体(heicode/src/utils/swarm/、coordinator/,继承自 Claude Code),与云端蜂群同名同概念(swarm/team/sub-agent/handoff/coordinator)。

项目书 §1.6 明确愿景是“Agent 基础设施不应只在本地”,即云端蜂群才是生产执行层;但客户端那套本地编排仍随包发布、可独立拆任务,造成概念与心智的左右脑互搏,且 ASCE 评测口径无法统一(本地路径不产生 Runtime trace/审计)。


P5. 默认模型四套口径,自相矛盾 🟡

来源 默认/建议模型 证据
代码角色模板 claude-sonnet-4-6 / claude-opus-4-7 agnet_role_template.go:49,82
对接文档示例 agnet-model-backend(占位名) heicode-desktop-sub-agile-api.md:1376
文档明令禁用 禁止用 agnet-model-* 占位名 同上 :48
生产实际验证 仅 gpt-5.4;且说 claude-sonnet-4-6 走普通 sub 可能上游 400 同上 :15,:49

照代码默认值(sonnet)走 → 文档说会 400;照文档示例(agnet-model-backend)走 → 文档自己说禁用。无单一可信来源。


P6. 安全治理:关键路径部分强制 + 大量占位,多处触及 ASCE 红线 🟠

ASCE 强制降级红线:明文密钥进 Git/日志/Markdown/前端→最高 L1;高危无审批→最高 L1;无法追踪资源→最高 L2。代码现状:

治理项 现状 证据
secret_ref 强制 azkv:// ✅ Agnet 部署/回调/KV 读取已强制 agnet_control_plane.go:744、agnet_callback.go:628、secret_store.go:143
同上(Resource CRUD /api/resources) ⚠️ 未校验,可直写任意 secret_ref resource.go:449
明文密钥扫描 ⚠️ 仅按字段名拦截,无值模式扫描(JWT/sk- 等),可绕过(放进非敏感 key / 字符串数组 / secret_ref 列) resource.go:33,244、agnet_control_plane.go:537
Secret Broker(Key Vault) ⚠️ 写/读已实现,轮换/撤销/禁用缺失 secret_store.go:52;docs/plan.md 仍列 P2
短期凭证 lease 派生 ❌ 占位:审批通过只生成 lease:// 引用,不读 KV、不 mint 临时 token agnet_approval.go:213
高危审批阻断 ❌ Manager 不阻断:部署 status: accepted 立即落库,不检查 risk_level/pending approval;阻断依赖 Runtime agnet_control_plane.go:1071
撤销 lease 立即失效 ⚠️ 仅改 DB,不通知 Runtime(approve 有 sync、revoke 无) agnet_approval.go:339
permission manifest 强制 ⚠️ 仅生成下发,无 Manager 运行时 action 校验;allowed_actions 不与 binding 交叉校验 agnet_control_plane.go:870,885、resource.go:366
审计落库 ⚠️ 有结构化表,但best-effort 非 fail-closed,列表 API 不返回 details agnet_audit.go:59、agnet_control_plane.go:1928

结论:安全是“Agnet 控制面 ingress 有可测试的强制校验,但 Secret Broker 半成品、lease 占位、高危阻断在 Runtime、权限 manifest 只给模型看、审计不 fail-closed”。对照 ASCE,明文密钥(值级 bypass + secret_ref 直写)与高危无 Manager 阻断两项有把整体压到 L1/L2 的风险。


P7. 鲁棒性:有代码但缺原子性与边界处理 🟠

README/文档声称“状态恢复、orphan 恢复、失败重试、双执行避免、多 Agent DAG、capability 匹配、一层 handoff”,代码核查为 happy path 有实现、生产可靠性不足:

能力 评级 关键缺陷 证据
双执行避免 ⚠️ 部分/有缺陷 无 Redis 原子领取/租约;get_ready_pending_task(lrange+lrem)与 assign_task 分离,REST /tasks/assign 与 dispatch loop 可并发对同一 task 双 assign;complete 不校验 reporting agent task_queue.py:114,158,242、main.py:1060,1399
orphan / 状态恢复 ⚠️ 部分/有缺陷 Orchestrator 启动无 reconcile;重启后 WS 空集,30s 后可能把仍在执行的任务重新入队 → 与旧 Agent 完成消息叠加双跑;orphan 未 ready 时只 save 不 requeue → 永不调度 main.py:236、task_queue.py:372,386
checkpoint 续跑 ❌ 占位 checkpoint_manager.py 完整实现但无任何地方 import/调用;指数退避同样未接入 checkpoint_manager.py:43,170
失败重试 ⚠️ 基础可用 真 requeue,但无退避;orphan/agent-dead 与业务失败共用 retry 配额 task_queue.py:270
DAG 依赖调度 ✅ 真实现(需开关) 但依赖任务 FAILED/CANCELLED 时下游永久 not ready、仍留在 queue 被空扫 task_queue.py:140、swarm_runtime.py:69
capability 匹配 ⚠️ 部分 required 为空则恒真;取第一个匹配 idle agent,非最优;handoff 子任务无匹配 capability 则永不派发 task_queue.py:151、main.py:131,1234
一层 handoff 父子联动 ⚠️ 部分 只发 handoff_request 未发 blocked_on_handoff 时父仍 BUSY;child_task_id 常为 null;子永远 pending → 父永久 BLOCKED main.py:1361、agent/main.py:175

部署当前 replicas: 1(k8s/orchestrator-deployment.yaml:25)掩盖了部分竞态;一旦多副本且无分布式锁,双执行风险显著放大。


4. 对照 ASCE 强制降级与项目书验收

红线 / 验收项 来源 当前是否满足 关联问题
任务成功必须有可验证产出 项目书 §12.4 / ASCE §8.1 ❌ 否(方案总结即 completed) P1
交付物完整性(代码/测试/部署说明) ASCE §8.1 ❌ 否 P1/P2
明文密钥零暴露 ASCE §10.2 强制降级 ⚠️ 有 bypass 面 P6
高危操作 100% 审批 ASCE §10.2 / 项目书 §8.5 ⚠️ Manager 不阻断,依赖 Runtime P6
可追踪资源使用 ASCE §10.2 ⚠️ 审计非 fail-closed、API 缺 details P6
双执行避免 ASCE §8.6 ⚠️ 无原子保证 P7
状态可回放(trace 完整) ASCE §12.3 ⚠️ 本地编排路径无 Runtime trace P4

按 ASCE §10.1 等级判定,P1(无产出门槛)叠加 P6(密钥/审批)会把当前系统压在 L1~L2,与项目书面向企业 L4/L5 的目标差距明显。


5. 收敛建议(按优先级)

总原则:给每个关键概念定唯一权威定义 + 唯一裁判,由 Runtime 输出“结构化真相”,Manager 据结构化字段裁决,客户端只消费结论。删掉客户端/Manager 各自的本地正则。

  1. P1 + P3(地基,先做):定一份《完成与状态契约》——
    • 终态枚举统一(含 completed 与新增非成功终态 completed_without_deliverable / needs_codegen),文档+Go+客户端三处对齐。
    • 代码任务 completed 的充要条件 = 结构化产出非空(files_modified 非空 / 有 diff / 有 commit)。落点:HeiCode-Swarm/orchestrator/main.py 的 emit_task_completion_events + agent/task_executor.py 成功判定 + agent/main.py 的“无改动”分支。
  2. P2 + P6 责任上移:定一份《交付物与判定契约》——artifact_type 规范枚举;deliverable 判定只依据结构化字段(复用已有的 files_modified / git_skipped / artifact_type=document),Manager 据此裁决并据此降级 completed;删客户端 classifyArtifact 与 Manager runtimeArtifactsAreSummaryOnly 两套正则。
  3. P6 安全补齐:值级密钥扫描(不只字段名)+ Resource CRUD 的 secret_ref 校验;高危操作在 Manager 侧 gate(pending 审批未通过不进入执行/不下发 plan);revoke 同步 Runtime;审计改 fail-closed 或至少告警可观测。
  4. P7 鲁棒性:任务领取改 Redis 原子(Lua/SETNX+租约);Orchestrator 启动 reconcile(重建 queue/状态);接线 checkpoint + 指数退避;DAG 依赖失败的传播与父任务超时解除。
  5. P5(独立低风险):模型默认/允许清单收敛到单一来源,对齐生产 NewAPI,清占位名。
  6. P4(单独立项):明确每模式唯一编排权威(交互式=本地、无人值守/计费/审计=云端经 Manager);废弃 HeiCode-Swarm/desktop-client 的 /tasks 旁路;本地多智能体改名(local-team),“蜂群/swarm”专留云端。

建议顺序:先 1、2(地基与责任上移)→ 3、4(安全与鲁棒)并行 → 5 随手清理 → P4 作为独立产品决策推进。


6. 证据索引(关键文件)

  • Runtime 完成判定:HeiCode-Swarm/agent/task_executor.py:85,141、agent/main.py:264
  • Runtime artifact/状态:HeiCode-Swarm/orchestrator/main.py:445-552
  • Runtime 鲁棒性:HeiCode-Swarm/orchestrator/task_queue.py、agent_registry.py、checkpoint_manager.py、k8s/orchestrator-deployment.yaml:25
  • Manager 回调/状态:heicode-mananger/heicode/controller/agnet_callback.go:304,376,628,682
  • Manager artifact 模型/诊断:heicode-mananger/heicode/model/agnet_artifact.go:18、controller/agnet_runtime_client.go:663
  • Manager 安全治理:controller/agnet_control_plane.go、controller/agnet_approval.go、controller/resource.go、controller/secret_store.go、model/agnet_audit.go
  • Manager 角色模板:controller/agnet_role_template.go:44-115
  • 客户端分类规则 / 状态枚举 / 模型口径:heicode-mananger/docs/integration/heicode-desktop-sub-agile-api.md:48,300,1376,1399
  • 客户端本地编排:heicode-{macos,winos}-release/heicode|. src/utils/swarm/、src/coordinator/

本报告为只读代码核查结论,证据均可在对应仓库 文件:行 复核。修复实现需在确认契约后另行评审。