Commit Graph
97 Commits
Author SHA1 Message Date
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
local 715e7c2fc8 docs: 新增 LOCAL_DEPLOY.md(换机构建+部署完整步骤,无密钥)
CI / tests (push) Successful in 46s
CI / guardrails (push) Failing after 12m41s
2026-06-17 13:32:55 +08:00
local 169e82ce02 docs(CLAUDE.md): 追加本地测试&交接段(部署/底座/密钥清单[无值]/状态/换机续接)
CI / tests (push) Failing after 14m36s
CI / guardrails (push) Failing after 14m37s
2026-06-17 13:06:01 +08:00
local 4d77b9263e chore: 本地测试快照(#7 自底向上分解 + _parse_task 健壮化 + handoff 透传 + 本地部署清单)
CI / tests (push) Failing after 12m5s
CI / guardrails (push) Failing after 12m6s
仅供导出到 xiaohei/Agentswarm 的本地测试镜像快照,非主仓 PR。
2026-06-17 12:58:28 +08:00
FastheiandClaude Opus 4.8 f9df550ac9 fix(agent/#75): 落地 agent 侧自底向上分解(#7 task_proposal)+ _parse_task 健壮化
修 #75:蜂群单任务铺不到多 agent。两层根因 + 对应修复(均经本地 k8s 端到端验证):

1) 真实 agent 执行器从未实现 #7「自主分解提案」(autonomous-task-generation.md §4 标为
   「后续」;此前只有 stub_agent 演示)。编排器侧 handle_task_proposal 早已就绪,缺 agent 侧出口。
   - agent/main.py: 新增 propose_task()(发 WS task_proposal,字段对齐 handle_task_proposal);
     execute_task 传入 proposal_callback;control_messages 接受 task_proposal_ack。
   - agent/task_executor.py: 新增 _maybe_propose_subtasks() —— 执行顶层种子时用 _parse_task 拆分,
     把每个子任务经 proposal_callback 提案入池(由编排器 review→create_task→其他 agent 自选)。
     仅顶层种子提案(parent 为空、source 非 agent_proposed/dynamic_handoff),子任务不再递归提案,无环。
     env ENABLE_AUTONOMOUS_PROPOSALS(默认 on)可关。

2) _parse_task 又脆又静默退化为单任务(原 max_tokens=2000 截断 + 严格 json.loads + except 兜底):
   - max_tokens 可配 AGENT_PLAN_MAX_TOKENS(默认 65536;注:qwen3.7-max 网关上限即 65536,>之 400);
   - 新增 _coerce_subtasks 宽容解析(裸数组 / ``` 围栏 / {"subtasks":[...]} / 从文本抠 [...]);
   - 解析失败重试 1 次再退化;成功打 INFO "Decomposed into N",退化打明确 WARNING(可观测)。

派发:提案子任务 required_capabilities 置空(像种子,任意空闲 agent 可自选)。否则 LLM 给的具体能力
不是固定能力池子集 → can_agent_run_task 永远拒 → 子任务卡 PENDING(本地实测到的死锁)。能力提示保留在
agent_role(不门控派发);能力感知路由(把子任务能力映射到能力池)作为后续增强,见 #75。

本地验证(Docker Desktop k8s,qwen3.7-max,池16):两次 run 复现「种子→拆 6/8 子任务→派给 6/8 个不同
agent 并行执行」,此前恒为单 agent。

测试(本地全过):test-runtime-contract / test-contract-freeze / test-merge-smoke / test-workflow-e2e /
test-autonomous-tasks / test-agent-launcher / test-convergence。

影响:仅 agent/(执行单元);不动 Manager↔Swarm 冻结契约 / 计费 / 审计 / 编排器接口。
Refs #75

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 02:14:18 +08:00
zsbgnw12andGitHub 35109e5882 Merge pull request #74 from xmindlab-heicode/fix/swarm-73-empty-repo-worktree
fix(agent/git): 空仓自动播种基线提交,结果可 push 回仓 (#73)
2026-06-16 22:37:26 +08:00
FastheiandClaude Opus 4.8 c38b5fd80d fix(agent/git): seed baseline commit for empty repos so results push back (#73)
Binding an empty repo (no commits) made `git clone` land an unborn HEAD with no
`origin/main`. `add_task_worktree` / `create_result_branch` then fell back to
base_ref=HEAD, and `git worktree add ... HEAD` failed with "invalid reference:
HEAD". The agent silently degraded to "executing on repo root without git push",
so the result branch never reached the remote.

Fix: after clone (and after refreshing an existing checkout), detect an empty
repo via `git rev-parse --verify HEAD` and plant one empty baseline commit on the
configured base branch. Worktree/branch creation and push then work normally and
the result branch is created on the (previously empty) remote.

Adds scripts/test-git-empty-repo.py covering the empty-repo path; existing
scripts/test-git-workflow.py still passes (no regression). Verified end-to-end
against a real empty GitHub repo: result branch pushed successfully.

Impact: Swarm agent git layer only (agent/git_operations.py). No change to
Manager<->Swarm contract, callbacks, billing, secret_ref, or audit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 22:35:27 +08:00
FastheiandGitHub 5cf3b88c09 Merge pull request #72 from xmindlab-heicode/fix/70-relanded
fix(swarm/#70): 超时透传+提默认 / 时间线降噪 / 失败reason准确(重新落到 main + 修 main 红测试)
2026-06-16 18:31:24 +08:00
FastheiandClaude Opus 4.8 1edf73aba4 fix(swarm/#70): 任务超时透传+提默认 / 事件时间线降噪 / 失败 termination_reason 准确
真机端到端实测(#70)暴露三问题,本 PR 全部修复(仅 agent + orchestrator,不跨仓):

问题1【阻断】单任务超时只有 60s,生成类任务必挂
- agent/main.py: TASK_TIMEOUT_SECONDS 默认 60→300(仅对外部/独立启动 agent 生效)。
- agent_launcher.py: 新增 DEFAULT_TASK_TIMEOUT_SECONDS=300、_budget_duration_seconds、
  resolve_task_timeout(base=env 默认 300,与 run budget.duration_seconds 取较小);
  plan_launch_specs 把 TASK_TIMEOUT_SECONDS 透传进每个 agent env(非敏感,inline,
  k8s 不进 Secret)。

问题2【体验】事件时间线全是内部噪音(纯附加,未碰冻结契约)
- swarm_runtime.py: is_client_visible(=event_type∈FROZEN_CLIENT_EVENT_TYPES,单一真源);
  emit_event 给 envelope 加 metadata.client_visible 布尔 + 关键客户端事件回填可选
  payload.message(人话进度,仅取已有字段,不伪造)。task.heartbeat/retried/
  deployment.status_changed/timeline/budget 标 client_visible=false,仍持久化+回调
  但客户端据此过滤出时间线。冻结事件集/类型/sequence/artifact 形状一字未动。
- event-schema.md: 文档化两个附加字段 + 新增 §6.1,明确未解冻。

问题3【正确性】失败/超时 termination_reason 仍报 "tasks_completed"
- convergence.py: 新增 TIMEOUT/MAX_RETRIES_EXCEEDED/TASK_FAILED;classify_failure_reason
  按 timeout→max_retries→task_failed 取最具体(仅凭真实 per-task 信号);FAILED 分支
  再不会返回 tasks_completed(该 reason 仅用于成功),budget/rounds 仅在通用失败时才覆盖。
- task_queue.py: fail_task 永久失败时把 reason 落到 task.result({"success":false,"error":reason}),
  不覆盖已有结果,供 convergence 读取。
- main.py: compute_convergence_report 快照补 retry_count/max_retries。

测试:新增 test_resolve_task_timeout、扩 test-convergence(failed_timeout/max_retries/
generic + "FAILED 永不报 tasks_completed"不变量)。本地全过:test-agent-launcher /
test-convergence / test-runtime-contract / test-contract-freeze / test-merge-smoke /
test-workflow-e2e / test-security-boundary。

影响:agent + orchestrator + 文档;不动 Manager↔Swarm 冻结契约字段(问题2 纯附加)。
栈在 #64(agent_swarm git 注入)之上,#64 合并后本 PR base 自动转 main。

Closes #70

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 18:29:39 +08:00
FastheiandGitHub bcb4abfdf5 Merge pull request #69 from xmindlab-heicode/fix/orphan-agent-lifecycle
fix(swarm): 孤儿 agent 终态回收 + 重试退避 + 任务错误上浮
2026-06-16 15:44:06 +08:00
zsbgnw12andGitHub bdddef2c23 Merge branch 'main' into fix/orphan-agent-lifecycle 2026-06-16 12:07:27 +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
zsbgnw12andGitHub 02f940f219 Merge pull request #64 from xmindlab-heicode/fix/63-launcher-inject-git-grant
fix(launcher/#63): 拉起 agent 注入 git 绑定(GIT_REPO_URL + azkv 凭据)— 修 HM #92
2026-06-15 13:08:47 +08:00
FastheiandClaude Opus 4.8 efa865cac4 fix(launcher/#63): 拉起 agent 注入 git 绑定(GIT_REPO_URL + azkv 凭据)— 修 HM #92
现象(HM #92):蜂群"需绑定 git 仓库才能使用",但 agent 实际拿不到仓库。

根因:HM 已在 swarm create 的 resource_grants 下发 git 绑定(resource_type=git +
metadata.repo_url + secret_ref=azkv://),但 swarm 拉起侧只把 grant 用于校验/脱敏/审批,
launcher 从不消费它 → 被拉起 agent 的 env 没有 GIT_REPO_URL/凭据 → 无法 clone。
(agent 侧 agent/main.py + agent/git_operations.py 早已读取这些 env,缺的纯是注入。)

修复(仅 launcher 注入,比照模型 key 的服务端解析路径):
- 新增 resolve_git_grant(body):从 resource_grants(含 per-agent)取首个 git grant,
  repo_url(metadata) → GIT_REPO_URL(非密文 inline);secret_ref(azkv) 服务端解析 →
  GIT_USERNAME/GIT_PASSWORD。复用 azkv 读取(workload identity;dev/CI 用
  HEICODE_SECRET_<name>)。有 repo 无凭据仍注入 GIT_REPO_URL(公有仓可 clone;私有仓
  报错,不伪造)。
- plan_launch_specs 增加 git_env 合并;create 路径解析并透传。
- k8s 后端:GIT_PASSWORD 与模型 key 同走 per-swarm Secret 的 secretKeyRef,绝不内联
  PodSpec;GIT_REPO_URL/GIT_USERNAME 为非密文 inline。SENSITIVE_ENV_KEYS 统一管控。
- git KV secret 值约定 JSON {"git_username","git_password"}(接受 git_token/token 形式
  + 裸 token),待 HM #92 对齐。

git 凭据不入 create 请求体/回调/日志/argv(_reject_plaintext_secrets 已覆盖
resource_grants)。

文档:runtime-contract §3.3 env 表 + 约束、security-boundary §6 增 git 绑定解析口径。
测试:scripts/test-agent-launcher.py 增 resolve_git_grant/凭据提取/k8s git secret 用例。

影响:仅 agent_swarm(Swarm/Agent + 密钥/secret_ref + 文档);不改 Manager/客户端/release/
契约状态机/计费/审计字段。HM 侧 binding_id(B 路径)解析另在 HM #92 处理,与本 PR 无关。

验收:
  python scripts/test-runtime-contract.py
  python scripts/test-contract-freeze.py
  REDIS_FAKE=1 python scripts/test-key-injection-contract.py
  python scripts/test-security-boundary.py
  python scripts/test-agent-launcher.py
  python scripts/test-git-workflow.py
  python scripts/test-merge-smoke.py
  python scripts/test-workflow-e2e.py
(全部通过)

Refs HM #92, Closes #63

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 12:17:51 +08:00
FastheiandGitHub 719fe80b98 Merge pull request #61 from xmindlab-heicode/fix/56-k8s-deploy-artifacts
docs+feat(benchmark): 环境变量清单 & 默认启用 Cosmos+Blob 导出
2026-06-15 00:29:19 +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
FastheiandGitHub 9beecf982b Merge pull request #60 from xmindlab-heicode/fix/56-k8s-deploy-artifacts
docs: 新增全量环境变量清单 ENV_VARS.md
2026-06-15 00:14:22 +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
zsbgnw12andGitHub d6f7f5ea6a Merge pull request #59 from xmindlab-heicode/fix/56-k8s-deploy-artifacts
fix(#56): 补齐 k8s 部署产物(kubectl / RBAC secrets / Deployment 拉起 env + workload-identity)
2026-06-14 20:17:42 +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
FastheiandGitHub ae7afc4525 Merge pull request #58 from xmindlab-heicode/fix/56-surface-stuck-run-diagnosis
feat(#56): 补 azkv SECRET_RESOLVER —— 用 Pod workload identity 从 heicod…
2026-06-14 19:31:39 +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
FastheiandGitHub 893352fcf5 Merge pull request #57 from xmindlab-heicode/fix/56-surface-stuck-run-diagnosis
Fix/56 surface stuck run diagnosis
2026-06-14 18:26:22 +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
FastheiandGitHub 43479dbb86 Merge pull request #54 from xmindlab-heicode/docs/reconcile-hmac-callback-status
docs: 统一 HMAC 签名回调状态口径(README ↔ event-schema)
2026-06-14 14:40:30 +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
FastheiandGitHub 9852df8cb4 Merge pull request #53 from xmindlab-heicode/docs/benchmark-collector-landed
docs(README): benchmark 采集器已落地,仅评分标准待定
2026-06-14 13:05:24 +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
FastheiandGitHub 1faa407aed Merge pull request #52 from xmindlab-heicode/feat/sse-events-stream-51
feat(#51): SSE 实时事件流 GET /api/swarms/{id}/events/stream(驾驶舱实时流,HM 反代给客户端)
2026-06-13 23:45:58 +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
FastheiandGitHub a978244cdd Merge pull request #50 from xmindlab-heicode/fix/rbac-naming-swarm-system-44
fix(k8s/#44): RBAC 清单对齐 swarm-system + swarm-orchestrator (Bug2)
2026-06-12 18:37:41 +08:00
FastheiandClaude Opus 4.8 f8b42d373b fix(k8s/#44): RBAC 清单对齐 swarm-system + swarm-orchestrator(修 #44 Bug2)
orchestrator-deployment.yaml 用 ns swarm-system + SA swarm-orchestrator,但
rbac/* 仍是 ns default + SA orchestrator-sa → 按官方清单 apply 后 SA 不匹配,
orchestrator 无权拉 agent pod(#44 Bug2)。

统一三件套到 swarm-system + swarm-orchestrator(= 生产实际运行的命名):
- serviceaccount: swarm-orchestrator / swarm-system
- role: orchestrator-role / swarm-system
- rolebinding: subject swarm-orchestrator/swarm-system, roleRef orchestrator-role

至此「从仓库 apply」可复现生产 RBAC。

影响范围:agent_swarm k8s 部署物料。不改契约/计费/审计/密钥/运行时代码。
注:agent-deployment-*/orchestrator-deployment-simple 等备用清单仍引用旧 orchestrator-sa,
属独立清理项(非 #44 Bug2 范围),另行跟进。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 18:37:04 +08:00
FastheiandGitHub b8dec09054 Merge pull request #49 from xmindlab-heicode/feat/redis-tls-auth-url
fix(redis/#44): 补回漏合的 keys() 集群 fan-out + Dockerfile COPY benchmark/ (2b0f2fe)
2026-06-12 18:26:22 +08:00
zsbgnw12andGitHub 019e404a77 Merge pull request #47 from xmindlab-heicode/feat/benchmark-selfcert-collector
feat(benchmark): 自证采集器(阶段0+1) + 真实 run 数据采集落库(阶段2)
2026-06-12 18:20:35 +08:00
FastheiandClaude Opus 4.8 27739af446 feat(benchmark): 导出器接入 Cosmos NoSQL + Blob 存储账户(可组合多 target)
阶段3 数据落库:BENCHMARK_EXPORT_TARGET 支持逗号组合 cosmos,blob(默认 none)。
- CosmosExporter:Cosmos DB for NoSQL,一 run 一文档(id=swarm_id,分区键 /swarm_id)。
- BlobExporter:存储账户归档 <scenario>/<swarm_id>.json。
- get_exporters() 解析多 target;某 target 缺凭据/未知则跳过+告警,不影响其它与 run。
- capture 对每个 exporter 独立 to_thread 导出,互不影响。
- orchestrator/requirements:加 azure-cosmos/azure-storage-blob/azure-identity(懒导入)。

安全:所有连接串/AccountKey 仅从环境读(经 Secret/secret_ref 注入),
绝不写进代码/日志/提交(组织安全规则)。

验证:新增 test-benchmark-export.py(target 解析/隔离/doc 成形) + capture/selfcert/
collector 回归全 PASS。

影响范围:agent_swarm benchmark 导出层 + 依赖;运行时只读钩子不变;导出默认关、无密钥落地。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 18:12:46 +08:00
FastheiandClaude Opus 4.8 94ef894ace feat(benchmark): 阶段2 数据采集 — 真实 run 终态自动采集 SwarmMetrics 并落库(+可选导出)
把采集器接进真实运行,让数据自己累积,为后续【经验标定】O/系数/S_gain 攒真实
用户数据(这些量只能由真实运行事后标定,不能先验写死)。本阶段不编任何公式。

- orchestrator/main.py:run 终态(completed/failed)在终态事件后调 capture_run_metrics。
  只读 run 状态、try/except 包裹绝不失败 run;默认开,BENCHMARK_CAPTURE=0 可关。
- orchestrator/swarm_runtime.py:record_benchmark_metrics → 落 run.metadata['benchmark']。
- benchmark/collectors/capture.py:collect(run_collector) → 持久化 → 可选导出(to_thread)。
- benchmark/export/:MetricsExporter;默认 NoopExporter(无依赖/无凭据);
  BENCHMARK_EXPORT_TARGET=blob 启用 Azure Blob(连接串或 Workload/Managed Identity,
  凭据经环境注入,绝不写进代码),归档 <scenario>/<swarm_id>.json。

诚实:缺项指标 NaN→null,不伪造(规则#9)。

验证:新增 test-benchmark-capture.py + 现有 collector/selfcert + 契约冒烟(runtime/
merge/freeze)全 PASS。

影响范围:agent_swarm。运行时新增**只读**终态钩子(不改派发/执行/契约/计费/审计字段);
导出默认关,无密钥落地。Client/Manager/Agnet/CodeGW/发布链路不涉及。
依赖:benchmark/ 需在镜像内(quality.py 早已 import benchmark;由 #44 Dockerfile 修复覆盖)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 17:57:59 +08:00
FastheiandClaude Opus 4.8 b5cc68c977 feat(benchmark): 落地自证采集器(阶段0+1)— S_gain≡G_E 接通 S_swarm + leaderboard
阶段0(定口径,docs/benchmark/emergence-evaluation.md §6 v2.1-impl):
- S_gain ≡ G_E(差值,不强制归一 [0,100],与标准「见涌现增益」字面一致)。
- 聚合 S_gain 取对最强基线(Q_base 最大)的 G_E(最保守,避免挑弱基线虚高)。
- Q ≡ Q_quality;swarm_valid 仍要求对全部基线 G_E>0 且 G_E,c>0。

阶段1(采集器):
- 新增 benchmark/collectors/selfcert_collector.py:把套件 5 份 BenchmarkRunRecord
  (swarm+4基线)+ 可选活体 SwarmMetrics 合流,经 baselines.compare 算 G_E/G_E,c,
  补全 run_collector 无法自算的 s_gain/g_e/g_e_cost/s_swarm,可能时产出 Benchmark_Agent。
- benchmark/leaderboard:实现排行榜聚合+渲染(标准 §11 字段)。
- run-benchmark-suite.py 接入自证 + leaderboard 输出。

诚实纪律(组织规则 #9):缺真实输入一律 NaN+coverage False,不伪造。
- O(可观测性)标准无公式 → 恒 NaN;Gov 计数器未实现 → 无活体治理则 NaN。
- 故完整 Benchmark_Agent 数字仍待 O 公式 + Gov 计数器(阶段2),采集器明列缺口。

验证:新增 test-benchmark-selfcert.py(17 项)+ 现有 benchmark 测试(metrics/
collector/comparison/runners)+ offline suite + 契约冒烟(runtime/merge/freeze)全 PASS。

影响范围:仅 agent_swarm benchmark 模块 + docs;不改 Manager↔Swarm 契约/计费/审计/密钥/发布链路。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 17:38:19 +08:00
FastheiandClaude Opus 4.8 2b0f2fe6f2 fix(redis): cluster 模式 keys() 跨所有主分片 fan-out + 修 Dockerfile 漏拷 benchmark/(#44)
实测 heicode-rd(OSSCluster,2 分片):默认 keys() 只命中单节点,
漏掉其它分片上的 key → agent_registry/task_queue 枚举不全。
cluster 模式下改用 target_nodes=PRIMARIES,redis-py 合并各节点结果。

附带修 agent_swarm#44 Bug1:Dockerfile.orchestrator 漏 COPY benchmark/
(orchestrator/quality.py 启动即 import benchmark.fixtures/metrics)→
原镜像 CrashLoopBackOff。新增 .dockerignore 控制构建上下文。

影响范围:仅 agent_swarm orchestrator(连接层 + 构建物料);
不改契约/计费/审计/密钥落地。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 17:11:28 +08:00
FastheiandGitHub 161a369c0e Merge pull request #46 from xmindlab-heicode/feat/redis-tls-auth-url
feat(redis): 支持 TLS + 密码 + REDIS_URL(接托管 Redis,如 heicode-rd)
2026-06-12 17:01:10 +08:00
FastheiandClaude Opus 4.8 35aab3a643 feat(redis): 加 REDIS_CLUSTER 支持 OSS Cluster 端点(heicode-rd 必需)
heicode-rd(Azure Redis Enterprise)database clusteringPolicy=OSSCluster,
裸 redis.Redis 客户端在多分片下 keys()/跨 slot 操作会误路由/抛 MOVED。

- REDIS_CLUSTER truthy → 用 redis.asyncio.cluster.RedisCluster(URL 或
  host/port 两种入参,密码/TLS 同样支持)。cluster 模式无 DB select,
  REDIS_DB 被忽略(仅逻辑 DB0)。
- 不设时维持 standalone 行为,完全向后兼容。
- 测试加 cluster 用例;manifest/DELIVERY 补 REDIS_CLUSTER 说明。

验证:连接配置单测 4 项 + REDIS_FAKE 回退 + test-runtime-contract /
test-contract-freeze / test-merge-smoke 全 PASS。

影响范围:仅 agent_swarm orchestrator 连接层;不改契约/计费/审计/密钥落地。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 17:00:37 +08:00
FastheiandClaude Opus 4.8 aa498fc318 feat(redis): 支持 TLS + 密码 + REDIS_URL(接托管 Redis,如 heicode-rd)
orchestrator/redis_client.py 之前只支持裸 redis.Redis(host,port,db)
明文连接,无法连 Azure Redis Enterprise(强制 TLS + access key)。

改动:
- 新增 REDIS_URL(优先),rediss:// 自动启用 TLS,凭据写在 URL;
  否则用离散 REDIS_HOST/PORT/DB + 可选 REDIS_PASSWORD / REDIS_SSL。
- 完全向后兼容:都不设时维持现有明文 redis-service:6379 行为。
- 凭据只读 env(经 Secret/secret_ref 注入),日志只打脱敏目标,
  绝不输出 URL / 密码。
- 新增 scripts/test-redis-connection-config.py(无需真实 redis)。
- k8s manifest 补 Secret 引用示例;DELIVERY.md 补环境变量表。

验证:新单测 3 项 + REDIS_FAKE 回退 + test-runtime-contract /
test-contract-freeze / test-merge-smoke 全 PASS。

影响范围:仅 agent_swarm(orchestrator 连接层)。
不改 Manager↔Swarm 契约 / 计费 / 审计字段 / 发布链路。
涉及密钥:仅新增「从环境读取」路径,无任何密钥写入代码或日志。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 16:50:27 +08:00
FastheiandGitHub b83638a475 Merge pull request #42 from xmindlab-heicode/feat/agent-launcher-k8s-backend
agent_launcher:补回一等 kubernetes 后端(每 agent 一 Pod,key 经 Secret 引用不内联)(Refs #16)
2026-06-11 23:05:38 +08:00
FastheiandGitHub d7c9cd64b6 Merge branch 'main' into feat/agent-launcher-k8s-backend 2026-06-11 23:05:02 +08:00