36 Commits
Author SHA1 Message Date
gongzhiyongandClaude Opus 4.8 c4c2116122 fix(agent): content 为空时回退 reasoning_content(修思考模型空响应)
CI / guardrails (push) Successful in 6s
CI / tests (push) Successful in 44s
CI / guardrails (pull_request) Successful in 5s
CI / tests (pull_request) Successful in 39s
qwen3.7-max 思考模型常返回空 message.content、答案在 reasoning_content。原代码只读
content → 拿到 "" → json.loads("") → "Expecting value: line 1 column 1 (char 0)" → 任务失败。
新增 _message_text():content → reasoning_content(attr 或 OpenAI SDK model_extra)回退,
_complete 两个返回点都用它。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 03:39:06 +08:00
gongzhiyongandClaude Opus 4.8 c5595cf344 fix(agent): 执行 max_tokens 4000→65535 + 明确全仓已本地 clone(修两个执行 bug)
CI / guardrails (push) Successful in 4s
CI / tests (push) Successful in 41s
#1 全量重写文件的 files JSON 远超 4000 token → JSON 中途截断("Unterminated string")
   → 任务失败。提到 qwen3.7-max 输出上限 65535,env AGENT_EXEC_MAX_TOKENS 可调。
#2 prompt 明确:完整仓库已 clone 在 {workspace_dir}(base_commit),上面列出的文件只是
   片段,绝不能因没列出就当文件/目录缺失(之前 LLM 误判 qutebrowser/utils 不存在 → 联网)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 03:19:19 +08:00
gongzhiyongandClaude Opus 4.8 770adcd8d7 fix(agent): 分解提示词改为蜂群模式 — 按文件归属的代码改动,非过程步骤
CI / guardrails (push) Successful in 8s
CI / tests (push) Successful in 1m1s
CI / guardrails (pull_request) Successful in 13s
CI / tests (pull_request) Successful in 41s
根因:旧提示词"task planning assistant + actionable subtasks + estimated_time"诱导
模型产出人类项目计划式步骤(探索/跑测试/移动文件/复审),而执行端只能"输出完整文件
内容"→ 这些步骤必然失败 → 0 patch。

新提示词按去中心化蜂群运作约束重写:仓库已在本地 base_commit、agent 唯一产物=完整
文件内容、子任务并行自选无共享 FS、产物按路径合并。要求:每个子任务=按文件归属的具体
代码改动(互斥,避免并行覆盖)、最小改动(可单文件就一个)、明确 FORBIDDEN 过程/元步骤。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 01:39:41 +08:00
gongzhiyongandClaude Opus 4.8 3c05fa9ee1 fix(launcher): agent pod imagePullPolicy=Always(同 tag 重建生效)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 01:09:30 +08:00
gongzhiyongandClaude Opus 4.8 b53e32be78 fix(agent): 约束 jina 工具用法,不关闭搜索
- jina 工具砍到 allowlist(默认 search_web,read_url),21→2;其余工具不暴露,
  减少 prompt 膨胀与误用(env JINA_TOOL_ALLOWLIST 可调)。
- prompt 加 workspace/tool 边界:本地 base_commit 代码是唯一真源,本地读改;
  web 搜索/read_url 仅用于外部知识(库文档/语言特性/报错查证),严禁取本仓源码
  (web 版本≠本地 base_commit,会污染 patch);read_url 不接受 file:// 本地路径。

搜索作为模型验证/补能手段保留,仅约束调用边界。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 01:01:36 +08:00
gongzhiyongandClaude Opus 4.8 fb1eeeebfa fix(swebench): 真实仓 patch 捕获 + agent 稳定性
#1 稳定性:HEARTBEAT_TIMEOUT 30→120(可配 AGENT_HEARTBEAT_TIMEOUT)——真实仓 clone/长
模型调用不再误杀 agent。
#2 正确性/忠实度:
- 透传 GIT_BASE_COMMIT;agent clone 改为浅 fetch+checkout 该 commit(在正确基线上读/改,
  且大仓也快);emit_patch 持久化 base_commit + _git_diff 对 SHA 走浅 fetch。
- agent 读文件预算可配并调大(AGENT_CTX_MAX_FILES=40/BYTES=40000),LLM 看到完整文件,
  避免全量重写截断 → diff 失真。launcher 透传这些 env 给 agent pod。

import + runtime-contract/result-aggregator/security-boundary 测试全绿。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 00:25:38 +08:00
gongzhiyongandClaude Opus 4.8 74f5ce2f97 feat(launcher): 弹性 agent 池 — 按需扩缩取代固定预起
agent_autoscale_loop(ENABLE_AGENT_AUTOSCALING):初始只起 AGENT_LAUNCH_MIN_POOL 个,
按每个 run 的 PENDING 任务积压超过空闲 agent 时 top-up,上限 MAX_POOL/per-user cap。
plan_launch_specs 加 count_override/id_start 支持非碰撞增补。trivial run 用少量 agent,
重 run 自动扩展。fail-soft,backend=none 时 no-op。

manifest:MIN/POOL 16→2 + ENABLE_AGENT_AUTOSCALING=1(初始小、按需长)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 22:08:55 +08:00
gongzhiyongandClaude Opus 4.8 98fb0d2bdb feat(sandbox): Daytona 云沙箱后端 — 代码执行移出 Pod(SANDBOX_BACKEND=daytona)
§8.1 提到的"专用 sandbox worker"路径:模型生成代码在 Daytona 隔离沙箱执行,不在
本 Pod 跑;只上传生成文件 + sandbox_runner.py,绝不传 env/secret。复用 _runner.py
保证 SandboxResult 一致。fail-soft:Daytona/传输出错回退 Pod 内 subprocess。
双门控(ENABLE_QUALITY_EVAL+HEICODE_SANDBOX_ISOLATED)不变,不削弱 fail-closed。

依赖:加 daytona==0.189.0;为满足其 otel floor 把 otel 1.24→1.42、instrumentation
0.45b0→0.63b1、pydantic 2.9.2→2.13.4(与 agent 对齐)。import + runtime-contract/
security-boundary/result-aggregator 测试在新依赖下验证全绿。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 21:14:07 +08:00
gongzhiyong 5c1ff0ef58 feat(agent): 任务执行加结构化日志(LLM推理/tool调用query与返回/产出)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
(cherry picked from commit 099f270cc2a092a4eae7e5d06d99c4d7e076465e)
2026-06-21 20:45:56 +08:00
gongzhiyong e263dae115 feat(agent): Jina 搜索改用标准 MCP SDK 接入
- agent/task_executor.py: Jina 搜索从手搓 httpx 改为官方 mcp SDK
  (streamablehttp_client + ClientSession);工具经 OpenAI function-calling 暴露给模型
- agent/requirements.txt: +mcp==1.28.0;pydantic 2.9.2->2.13.4(mcp 要求 >=2.11)
- orchestrator/agent_launcher.py: JINA_API_KEY 经 per-swarm Secret 透传给 agent pod
  (SENSITIVE_ENV_KEYS),不内联 PodSpec
- k8s/orchestrator-local.yaml: 本地部署清单(默认 in-pod 沙箱评估开关 + JINA_API_KEY)

沙箱保持默认 in-pod 方案,未引入 OpenSandbox。
影响范围: agent_swarm(agent/orchestrator) + Agent(新增 Jina MCP 工具)。
密钥经 k8s Secret 注入无明文。不影响 Manager 契约/计费/审计/发布链路。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
(cherry picked from commit deb984ac38)
2026-06-21 20:45:56 +08:00
gongzhiyongandClaude Opus 4.8 167adfcb56 fix(deploy): heicode-test 上云修复 — ACR 名/Redis 明文/plan token/聚合阈值/git grant
- launcher 透传 AGENT_PLAN_MAX_TOKENS 给 agent pod(避网关 >32768 → 400 断 fan-out)
- manifest: ACR heicodeest→heicodetest、AGGREGATE_ACCEPTANCE_THRESHOLD=70、
  HEICODE_SECRET_swe_git_1 走 secretKeyRef(SWE-bench clone 凭据)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 20:45:56 +08:00
gongzhiyong 2e7da834c6 Set test orchestrator images to heicodeest ACR 2026-06-20 23:50:47 +08:00
gongzhiyongandClaude Opus 4.8 1288fd19d7 feat(swarm): 协作聚合收敛取代蜂后选优 + sandbox 用 pytest 验证
CI / tests (push) Failing after 15m3s
CI / guardrails (push) Failing after 15m3s
按 juejin 协作聚合模型重构收敛(取代 best-of-N 选优):
- 删蜂后选优(queen.py/test-queen.py)
- 新增聚合节点 result_aggregator.py:共享池收集→同文件 LLM/AST 整合→沙箱验证→单次落 main
- 质量驱动闭环:不达标打回迭代(AGGREGATE_ACCEPTANCE_THRESHOLD + MAX_REVIEW_CYCLES)
- agent 停 git 工作分支,产出走 task.result.files 共享池(AGENT_GIT_PUSH_ENABLED 默认 false)
- sandbox_runner 改用 pytest(原生支持 pytest 风格 class),修 stdlib runner 收集失败
- 文档同步重写为协作聚合模型

本地验证:产物仓单分支 main + 三函数完整 + pytest 12/12 pass_rate=100 一次达标。
影响:Swarm 收敛/聚合层;Manager/客户端契约不变(artifact字段/sequence/状态机;契约测试全过)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 22:03:00 +08:00
gongzhiyongandClaude Opus 4.8 28a6c618ab feat(benchmark): SC-10 P_rework 计入评审重开(#10)
CI / tests (push) Failing after 11m18s
CI / guardrails (push) Failing after 11m19s
修正 P_rework 已知低估:此前 ReworkCount 仅由 retry_count>0 派生,漏了 cross_review/queen
质量门的重开(reopen_task 不增 retry_count——是质量决策非失败)。
- cross_review + queen_quality_gate 重开时累计 run.metadata["rework_reopens"]
- run_collector:rework_count = retry 派生 + rework_reopens

测试 test-benchmark-collector/metrics 通过。影响:仅 benchmark 度量(P_rework 更准),不改运行路径。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 22:51:49 +08:00
gongzhiyongandClaude Opus 4.8 2672a3d4b6 feat(orchestrator): SC-7 蜂后落 main — git push 最优产物(#16)
CI / guardrails (pull_request) Successful in 11s
CI / tests (pull_request) Failing after 11m52s
CI / tests (push) Failing after 11m53s
CI / guardrails (push) Failing after 11m53s
让蜂后选最优后把产物合并到产物仓 main,run 交付一份连贯产物而非 N 个碎片分支:
- create 存 git grant 引用(repo_url + secret_ref,均非明文)到 run.metadata;凭据不存
- queen.promote_to_main:从 secret_ref 现取凭据 → clone base_branch → 写最优产物 → commit → push;
  _auth_url 嵌入并 URL-encode 凭据(不入日志);best-effort 不破坏终态
- main.py 终态:winner → promote_to_main → deliverable.promoted_to_main{branch,commit_sha}
- Dockerfile.orchestrator 加 git CLI
- test-queen 扩展(auth_url 编码 + no_git_grant 分支),14 检查全过;全套契约通过

注:真实 git push e2e 需重建 orchestrator 镜像 + 部署 + gitea 产物仓验证(后续);
当前纯代码 + 单元测完成。凭据经 secret_ref 现取、不存 run、不入日志(组织规则#8)。

影响:仅 orchestrator 终态聚合;不涉及 Manager 契约/计费/发布链路。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 21:38:43 +08:00
gongzhiyongandClaude Opus 4.8 0c3af0425d docs: 蜂后收敛闭环(SC-3/4) — convergence-protocol §7 + rework-plan P-后续
CI / tests (push) Successful in 39s
CI / guardrails (push) Failing after 10m54s
CI / tests (pull_request) Failing after 14m26s
CI / guardrails (pull_request) Failing after 14m26s
记录已实现的蜂后闭环(M2-M4+P0)现状与诚实差距,标注剩余(SC-7 落main/SC-8 authoritative/M5 北极星)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 19:40:41 +08:00
gongzhiyongandClaude Opus 4.8 7314662f97 feat(orchestrator): M4 失败隔离 + P-guard 确认(SC-11/12)
SC-12 失败隔离:单 task 失败不再拖垮整个 run。
- refresh_swarm_run_status:next_status 仅在"有失败且无任何完成产物"时 failed;
  有完成工作则走 completed,交蜂后/convergence 判定(失败仍由 termination_reason 反映)。
- 解决那次 LLM 网关 404 致单 task 失败 → 整 run FAILED 的单点问题。

SC-11 P-guard:guard.diagnose 已由 assess_swarm_health 在派发循环接入(探索确认,零改动);
检测无 Agent/无模型/依赖死锁/预算耗尽/种子不可分解。

全套测试通过:runtime-contract / merge-smoke / workflow-e2e / contract-freeze
+ task-competition / queen / run-isolation。

影响:仅 orchestrator 终态判定;Manager status 映射不变(failed/completed)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 19:25:43 +08:00
gongzhiyongandClaude Opus 4.8 50bc8b019f feat(orchestrator): M3 蜂后质量门打回 — 质量驱动迭代(SC-9)
把收敛从"任务完成即停"升级为"质量驱动":
- queen.should_bounce(纯函数):最优候选已评分且 < 阈值且未触顶 → 打回;无阈值/未评分/达标/触顶 → 接受(诚实,不在算不出的分上打回,组织规则#9)
- queen_quality_gate(接入 refresh_swarm_run_status,在 cross_review 之后/状态提交之前):
  评分不达标 → reopen_task 回灌 impl 任务 + review_cycles++ → run 保持 RUNNING 迭代;
  达标/触顶 → 继续终态,winner 标到 deliverable
- _queen_threshold:QUEEN_ACCEPTANCE_THRESHOLD(env / run.metadata),默认 None=禁用,
  保持现有完成语义不变(可由 operator 启用)
- 717 复用门已聚合的 run.metadata[queen],不重复聚合
测试 scripts/test-queen.py 扩展 should_bounce(5 检查),共 11 检查全过。

注:SC-8 convergence 全 authoritative(BLOCKED→override run.status)动 Manager 终态语义,
需契约评审,列为后续;质量驱动收敛的核心已由 queen_quality_gate 实现。
SC-10 P_rework 计入评审重开属度量层(E),后续。

影响:仅 orchestrator 终态/重开路径;门默认禁用,不改 Manager 契约/完成语义。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 19:16:42 +08:00
gongzhiyongandClaude Opus 4.8 c2413b5edd feat(orchestrator): M2 蜂后结果聚合 — best-of-N 选最优(SC-5/6/7)
新增 orchestrator/queen.py(蜂后:不执行/不分配,只仲裁最终结果):
- collect_candidates:各 completed task 的 impl 产物为候选(复用 quality.collect_generated_files)
- score_candidates:用 swarm 共享 test 跑各候选 impl 评分(复用 sandbox.run_tests;
  fail-closed:未确认隔离则不评分,unscored!=0,组织规则#9)
- select_best:纯函数,测试通过率最高者胜(best-of-N — 单模型没有的涌现杠杆)
- aggregate_run:终态收集→评分→选最优,best-effort 不破坏终态路径
接入 main.py completed 分支:winner 标到 deliverable.selected,verdict 存 run.metadata[queen]。
测试 scripts/test-queen.py(6 检查全过)。

注:SC-7 的 git push 最优到产物仓 main 待端到端阶段(需 orchestrator git CLI + 凭据持久化);
当前先标记 winner(SWE-bench 语境产物是 patch,选最优即够)。

影响:仅 orchestrator 终态聚合;不涉及 Manager 契约/计费/发布链路。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 19:00:15 +08:00
gongzhiyongandClaude Opus 4.8 c257e7e562 feat(orchestrator): P0 run 边界隔离 — 蜂后防跨 run 抢夺(agent_swarm#8)
run-boundary isolation:agent 只能竞争/认领属于自己 run 的 task,杜绝跨 run 抢夺
(A run 的 agent 抢 B run 的 task → 计费错账/结果污染)。
- 新增 extract_swarm_from_agent / _agent_belongs_to_run(复用 -agent- 前缀)
- swarm_dispatch:候选过滤为本 run 的 task
- handle_task_bid/yield/takeover:拒绝跨 run 请求(cross_run_denied)
- 测试 scripts/test-run-isolation.py(7 检查全过)

影响:仅 orchestrator 派发/竞争路径;不涉及 Manager 契约/计费字段/发布链路。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 18:42:39 +08:00
gongzhiyongandClaude Opus 4.8 26a40c7770 fix(agent): failure reason leads with model's diagnosis, not the task prompt
之前聚合用 "<任务描述前80字>: <error>",失败 reason 被整段 prompt 污染,
真正的"看到什么/缺什么"被挤到后面。改为以模型 summary 为主、附上 distinct error,
reason 直接就是诊断本身(例:"No source files found...; only README/jsonl present.
(Required files like src/database/redis/main.js are missing.)")。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 05:23:04 +08:00
gongzhiyongandClaude Opus 4.8 62d6fdf78c fix(agent): per-task git worktree so concurrent tasks each get an isolated repo copy
取代上一版 Option B(执行器共用仓库根 + 串行 1 任务)。每个任务从本 agent 自己的 clone
切出独立 git worktree(完整仓库内容 + 独立分支/索引),执行器在其中读写真实源码,
任务级 GitOperations 在该 worktree 提交/推送结果分支,完成后回收 worktree。

- 单 agent 可并发多任务(MAX_CONCURRENT_TASKS 恢复 4),互不共用 checkout/index
- worktree 置于仓外 /tmp/agent-worktrees(AGENT_WORKTREE_BASE 可配),主 checkout 不受污染
- _git_admin_lock 仅串行 worktree add/remove 等共享 .git plumbing,任务执行仍并行
- 跨 agent 隔离不变:每个 agent 仍各自 clone 一份(各自 pod)
- 根治 "Empty workspace: no files detected"(worktree 自带仓库文件,已端到端验证)

GitOperations 新增 add_task_worktree / remove_task_worktree。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 05:01:25 +08:00
gongzhiyongandClaude Opus 4.8 6152235c96 fix(agent): execute against cloned repo root, not empty per-task subdir
每个 SWE 任务都因 "Empty workspace: no files detected" 失败:仓库 clone 到 /workspace,
但 TaskExecutor 用的是空的 /workspace/.agent_tasks/<task_id> 子目录(从未播种仓库内容),
模型看不到任何源码 → 正确地拒绝执行。

Option B(架构裁定 2026-06-16):TaskExecutor.workspace_dir 改为仓库根 self.workspace_dir,
context.workspace_dir 同步。git(workspace_git 同根)即可 commit/push 真实改动。
MAX_CONCURRENT_TASKS 默认 1:单一 /workspace git checkout 非并发安全,蜂群并行靠多 agent。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 04:52:40 +08:00
gongzhiyongandClaude Opus 4.8 b394ce99d5 fix(swarm): reap orphan agents on terminal run + retry backoff + surface task errors
孤儿 agent 事故修复(2026-06-15 swarm-69e470561bd7-seed 跨 workspace 执行)。
不改去中心化认领逻辑(swarm_dispatch 不动),仅治理 agent pod 生命周期与可观测性:

- B1 终态回收: refresh_swarm_run_status 终态后 best-effort stop_launched 回收 pod+secret
  (此前仅 Manager stop 才回收,自然完成/失败的 run agent 残留 → 孤儿留在共享池抢别的 swarm 任务)
- B2 防驱逐: agent pod 加 karpenter.sh/do-not-disrupt(AGENT_POD_ALLOW_DISRUPTION=1 可关)
- stop_launched: backend=kubernetes 时按标签删,不再被内存集合 _k8s_swarms 门控(跨重启可靠)
- C 重试退避: Task.next_retry_at + fail_task 指数退避 5→30→180s(cap 300, TASK_RETRY_BACKOFF_*),
  is_task_ready 门控;TASK_MAX_RETRIES 可配
- D 错误上浮: task_executor 失败时聚合 subtask error 到顶层 error(根治通用 "Task failed"),
  _execute_subtask 打印 LLM 响应片段
- 配额硬上限 16: _clamp_user_cap

契约测试全过: runtime-contract / merge-smoke / workflow-e2e / contract-freeze /
max-agents-per-user / security-boundary。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 04:33:01 +08:00
gongzhiyongandClaude Opus 4.8 f9f1d9a6d5 fix: 注入 GIT_REPO_URL,让 agent 克隆绑定仓库到 workspace(修复任务因空 workspace 必败)
根因(实测复现): agent 启动未注入 GIT_REPO_URL → 从不 clone → /workspace 为空 →
任何"读/改仓库代码"的任务被 LLM 以 "no source files to analyze or repair" 判 failed。
对照: 简单建文件任务在空 workspace 下仍 success,证明执行管线/模型/解析/落盘均正常。
公开库只需 GIT_REPO_URL(无凭据)。

- agent_launcher.git_launch_env(body): 从 resource_grants[].metadata.repo_url 提取仓库,
  注入 GIT_REPO_URL(+GIT_PROVIDER/GIT_DEFAULT_BRANCH/GIT_BASE_BRANCH)。纯函数,无 I/O。
- plan_launch_specs(git_env=...): 合并进每个 agent 的 env。
- launch_swarm_agents: 解析并传入 git_env; 记 agent_launch.repo_bound 诊断字段。
- 私有库凭据(GIT_TOKEN 经 grant secret_ref + 入 k8s Secret)留作干净后续。
- tests: test-agent-launcher 新增 test_git_launch_env + plan_specs 的 git_env 合并断言。

Refs #66

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 01:41:06 +08:00
gongzhiyongandClaude Opus 4.8 4309eac2ce fix(#66): 退役 _manager_provided_agents 逃生门 + pod 数[3,16]上下限 + 消费 metadata.max_agents_per_user
去中心化是唯一行为(对齐 runtime-contract §3.3): 所有蜂群统一播种单一目标任务 + Swarm 自己拉 agent 池;
orchestration_plan.agents 不再控制拉起/任务创建, 退化为无害元数据。修复"任务建了但无 agent 认领、永久 pending"。

- main.py: 删除 _manager_provided_agents 两处分支(任务创建改无条件播种、拉起永远执行) + 函数退役
- agent_launcher.py: launch_count clamp 到 [AGENT_LAUNCH_MIN_POOL=3, AGENT_LAUNCH_MAX_POOL=16]
- main.py: max_agents_per_user(body) 消费 metadata.max_agents_per_user(HM 下发; >0 优先, 否则 env)
- main.py: WS 注册兜底按 agent 所属 run 的 metadata cap 反查(fail-soft 回退 env), 与拉起口径一致
- docs/integration/runtime-contract.md §3.3: 同步架构师裁定口径(2026-06-15)
- tests: test-agent-launcher / test-max-agents-per-user / test-merge-smoke 同步断言

Refs #66

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 00:19:14 +08:00
gongzhiyongandClaude Sonnet 4.6 ffe9277050 feat(benchmark): 默认启用 Cosmos + Blob 导出
BENCHMARK_EXPORT_TARGET 默认值从 none 改为 cosmos,blob,
每次真实 run 终态自动落库。凭据未配置时降级 noop + warning,不影响主路径。
同步更新 ENV_VARS.md 默认值说明。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 00:20:26 +08:00
gongzhiyongandClaude Sonnet 4.6 521a227e58 docs: 新增全量环境变量清单 ENV_VARS.md
整理 agent/、orchestrator/、benchmark/、scripts/、k8s/ 下所有环境变量,
共 65+ 项,含安全敏感标注、解析优先级链和三套最小可运行配置示例。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 00:13:20 +08:00
gongzhiyongandClaude Opus 4.8 aa4679f610 fix(#56): 补齐 k8s 部署产物 —— 编排器镜像装 kubectl、RBAC 加 secrets、Deployment 接拉起 env + workload-identity label
让 k8s 拉起链路在仓内"可部署即可用"(此前线上实测全缺):

- Dockerfile.orchestrator:装 `kubectl`(pin AKS 1.34;linux/amd64)。launcher 靠 shell
  `kubectl apply/delete` 建/删 agent Pod + 每-swarm key Secret,镜像无 kubectl 则 k8s 后端必失败。
- k8s/rbac/orchestrator-role.yaml:加 `secrets`(create/delete/list/get)——否则建不了模型 key
  Secret、agent keyless。并注明 Role 命名空间须与 AGENT_POD_NAMESPACE 一致。
- k8s/orchestrator-deployment.yaml:
  - pod 模板加 `azure.workload.identity/use: "true"`(AKS webhook 注入 token,配合已注解的
    SA + UAMI 读 heicode-vault)。
  - 接入拉起 env:`AGENT_LAUNCH_BACKEND=kubernetes`、`AGENT_POD_IMAGE=heicode.azurecr.io/swarm-agent:latest`、
    `AGENT_POD_NAMESPACE=swarm-system`(同 RBAC ns)、`ORCHESTRATOR_PUBLIC_URL=ws://orchestrator-service...:8000`、
    `AGENT_OPENAI_API_BASE=https://code.heicode.cc/v1`、`SECRET_RESOLVER=azkv`。
  - image 指向 ACR(`heicode.azurecr.io/swarm-orchestrator`,tag 部署时 pin)。

校验:两个 manifest YAML 解析通过(label/env/secrets 均在);test-agent-launcher / test-swarm-guard /
test-contract-freeze 全绿。无明文密钥。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 19:39:10 +08:00
gongzhiyongandClaude Opus 4.8 207e027fbb feat(#56): 补 azkv SECRET_RESOLVER —— 用 Pod workload identity 从 heicode-vault 读模型 key
#56 缺口:`_resolve_secret_ref` 此前只读 dev 环境映射 `HEICODE_SECRET_<name>`,
没有生产从 Azure Key Vault 取 key 的实现(原注释写"适配器在仓外",实际缺)。
本次在仓内补上,走刚建好的 Pod workload identity:

- `_resolve_from_keyvault`:`DefaultAzureCredential` + `SecretClient` 读 azkv:// ref;
  **lazy import** azure SDK,任何失败(未启用/不可解析/SDK 缺/无凭证/网络/secret 不存在)
  返回 None —— 不伪造、不抛。
- `_azkv_enabled`:**仅当** Pod 注入了 workload identity(`AZURE_FEDERATED_TOKEN_FILE`)
  或显式 `SECRET_RESOLVER=azkv` 才真连 KV —— dev/CI/测试保持 hermetic、不碰网络。
- `_parse_azkv_ref`:解析 `azkv://<vault>/secrets/<name>[/<ver>]`(裸名→`https://<name>.vault.azure.net`,
  全 host 保留,兼容短形式)。
- `_resolve_secret_ref` 顺序:dev 环境映射 → KV(workload identity),保持既有 dev 行为不变。
- requirements:加 `azure-keyvault-secrets`(lazy import;`azure-identity` 已在)。

测试 `test-agent-launcher.py` 新增:azkv 解析、gating(默认关、两种开关)、disabled→None。
`test-agent-launcher` / `test-key-injection-contract` 全绿。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 19:17:29 +08:00
gongzhiyongandClaude Opus 4.8 185c0033b1 docs(#56): 模型网关域名 A.4 更正 code.xinghanlab.com → code.heicode.cc(HM 权威口径)
HM #56 评论:code.heicode.cc 为正式地址,code.xinghanlab.com 为前期过渡域名。
runtime-contract §3.3.1 A.4 的 AGENT_OPENAI_API_BASE 示例同步更正为
https://code.heicode.cc/v1。纯文档,无代码改动。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 18:21:36 +08:00
gongzhiyong a117c02e3f docs(#56): 更正模型 key 库名 heicode-kv → heicode-vault(HM 实测口径)
agent_swarm#56 评论:模型 key 的真实 Key Vault 库名是 `heicode-vault`
(`https://heicode-vault.vault.azure.net`),早期契约文档误写为 `heicode-kv`;
且生产 `SECRET_RESOLVER` 须指向 `heicode-vault`。

- runtime-contract.md §3.3.1 A.3:库名更正 + 标注 SECRET_RESOLVER 指向 heicode-vault
  + 明确 Swarm 需提供 Pod 身份的 clientId+objectId 给 HM 授权(只读、限 swarm-model-key-*)。
- security-boundary.md:secret_ref 示例 host 同步更正。
- test-key-injection-contract.py:模型 key fixture host 同步更正(resolver 仅取末段名,
  功能不变;测试仍全绿)。

纯文档/fixture 更名,无事件 schema/契约字段改动。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 17:12:27 +08:00
gongzhiyongandClaude Opus 4.8 9aadc802df fix(#56): surface why a swarm run produces nothing (no silent black box)
#56: a created run only seeds the task; if no expert agent connects, the run hangs
at `running` forever with no `agent.*` events and an empty /result — and the cause
(P-guard already detects NO_AGENTS_CONNECTED) was only in run.metadata["health"] /
/diagnostics, never on the surfaces HM/cockpit actually poll (/events, /result).

This makes a stuck run explain itself (no new Manager event type, no contract change):

- launch_swarm_agents now records run.metadata["agent_launch"]
  {backend, planned, launched, launched_ids, model_key_resolved, note}. The note
  pinpoints WHY there are 0 agents — e.g. AGENT_LAUNCH_BACKEND=none (no auto-launch),
  k8s launch failed (kubectl/RBAC + Pod Workload Identity, #16/#60 A.3), or the model
  key didn't resolve. No secret recorded — only a model_key_resolved bool.
- /result and /diagnostics now carry `health` (P-guard blockers) + `agent_launch`.
- assess_swarm_health emits ONE `timeline.updated` per distinct blocker-set (registered
  event; dedup by summary, reset when healthy) so /events and the cockpit (#39) show
  "swarm blocked: no_agents_connected" instead of silence. Still NO unregistered
  swarm.health event.

Scope: this surfaces the diagnosis. Actually executing a run still requires the
deployment to set AGENT_LAUNCH_BACKEND=kubernetes AND the #16/#60 A.3 Pod Workload
Identity / KV grant (infra, cross-team) — called out in the launch note.

Tests (scripts/test-swarm-guard.py): blocked run emits timeline.updated exactly once
(dedup) + still no swarm.health; /result + /diagnostics carry health w/ no_agents_connected;
launch_swarm_agents records the backend=none note. test-contract-freeze + test-agent-launcher
still green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 16:52:44 +08:00
gongzhiyongandClaude Opus 4.8 e32f711f26 docs: 统一 HMAC 签名回调状态口径(README ↔ event-schema)
README 将该项标 🟡「事件 envelope 与签名待 Manager 对齐」,暗示规范尚未
确定;而 event-schema.md §1 写「已实现,与 HM 一致」并给出完整规范串/头/
容差。两处口径不一致(组织规则:文档冲突应点出、不自行裁定——本次按总架构
指示统一)。

依据代码实证(swarm_runtime.py:691-702 HMAC-SHA256(timestamp.event_id.body)
→ X-Agent-Signature/Timestamp,_post_callback httpx 投递)+ event-schema §1
已含 HM 侧参数(容差 300s、去重顺序),统一为:
**机制已实现、规范与 HM 对齐、待主链路端到端联调验收**。

- README 行 11:改为「机制已实现,待主链路联调验收」并分别指向 runtime-
  contract §3 与 event-schema §1。
- event-schema.md §1:「已实现,与 HM 一致」→「机制已实现,规范与 HM 对齐;
  待主链路端到端联调验收」。

纯文档措辞,未改任何事件 schema 字段/类型/sequence/artifact(契约冻结不受影响)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 13:17:18 +08:00
gongzhiyongandClaude Opus 4.8 4aaf63cea5 docs(README): benchmark collector has landed — only scoring standard pending
The capability table claimed "🔴 规划中(采集器尚未落地)", but the benchmark
collector is in fact implemented under benchmark/: metric formulas (metrics.py:
S_swarm/G_E/G_E,c/Benchmark_Agent + governance/collaboration/communication/
robustness), live-run collection (collectors/), the 4 baseline runners (runners/),
G_E/G_E,c comparison (baselines.compare), self-cert merge (selfcert_collector),
and telemetry export to Cosmos/Blob (export/).

Updated the row to 🟡: collector landed; the remaining piece is the scoring
standard — the O (observability) formula, BASE_COEFFICIENTS, and S_gain thresholds
must be empirically calibrated from accumulated real user usage data (long-term
ticket). Keeps the honesty rule: metrics lacking real inputs return NaN, never
fabricated scores.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 01:12:43 +08:00
gongzhiyongandClaude Opus 4.8 9d07bfeb76 feat(#51): add SSE endpoint GET /api/swarms/{id}/events/stream
Real-time event stream for the cockpit, reverse-proxied by HM to the client
EventSource (orchestrator SSE → HM → client). The SSE overlay over the existing
GET /events?after=<sequence>:

- Replays history after `after`, then holds the connection and pushes new events.
- Reuses the existing swarm_events:{swarm_id} store + per-swarm INCR sequence — no
  new storage, no schema change.
- Each frame: `id: <sequence>` / `event: message` / `data: <envelope JSON>`, where
  data is byte-identical to /events so SSE and polling share one cursor space (a
  dropped SSE can fall back to /events?after=<last id> with no gap/dup).
- Supports Last-Event-ID header (takes precedence over the `after` query) for
  end-to-end resume through HM.
- Heartbeat `: ping` every ~15s + X-Accel-Buffering:no to survive nginx ingress /
  HM reverse-proxy buffering.
- Closes after a terminal event (swarm.completed/failed/stopped); releases on client
  disconnect (request.is_disconnected).
- Auth: require_runtime_auth (service token) — caller is HM, never the client direct.

Adds TERMINAL_CLIENT_EVENT_TYPES to swarm_runtime. Events are already redacted at
emit time, so frames are streamed as-is. No change to the callback POST path,
event schema, sequence, or terminal definitions (event-schema v1 frozen).

Verified: contract-freeze / runtime-contract / merge-smoke / workflow-e2e all pass;
plus a dedicated SSE check (history replay, id ordering, Last-Event-ID resume,
byte-identical envelope, terminal close).

Part of #40 (the SSE half). HM reverse-proxy side = heicode-mananger#46.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 23:07:35 +08:00