回应 HM「#60 落地前需 Swarm 定死的参数清单」。Swarm 侧逐条定死并落实现:
- A.2 KV secret value 格式:JSON {"openai_api_key":"sk-..."}(对齐 callback 签名密钥
约定),解析字段 openai_api_key;裸 sk- 串兼容;解析不到/字段缺失不伪造。实现
agent_launcher._extract_model_key + _resolve_secret_ref。
- A.5 吊销信号(事件驱动):sk- per-user 长存;stop 为唯一终态(completed/failed 经
…/input 可重开故保 key)。某用户全部 run 被 stop(retained 集清空)时,运行时发
恰好一次 swarm.pool_terminated{user_id, secret_ref},HM 据此吊销 sk- + 清 KV。
单 run swarm.stopped 不触发吊销。实现 swarm_runtime.retain_run_for_user /
release_run_and_maybe_terminate_pool(per-user retained 集 + 一次性 flag)。
- A.1 粒度:每用户一把、跨 run 复用;KV 命名 swarm-model-key-<user_id>(文档)。
- A.4 OPENAI_API_BASE:Swarm 部署常量(已实现),不经 create 下发(文档确认)。
- A.3 KV 读 RBAC:⚠ 待定(联调阻塞前置)——如实标注归属未敲定,不伪造已就绪。
- B.1:CLIENT_GUIDE §9 /events 游标改 after=<next_after>(HM 不透明游标,非 sequence)。
swarm.pool_terminated 为 HM 控制面生命周期事件,不入 FROZEN_CLIENT_EVENT_TYPES、
不渲染驾驶舱;payload secret_ref 为 azkv:// 引用(非明文 key)。
文档:runtime-contract §3.3.1(参数表)、event-schema(注册 + 说明)、
security-boundary §6(吊销握手 + RBAC 待定)。测试 scripts/test-key-injection-contract.py
(KV 格式解析 + 吊销握手:单 run/多 run 保留/不重复吊销/teardown 后重新武装)+ CI 步。
不动 Manager 面接口、HMAC 回调、审批链、计费/审计字段语义。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
164 lines
5.7 KiB
YAML
164 lines
5.7 KiB
YAML
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches: ["**"]
|
|
pull_request:
|
|
branches: ["**"]
|
|
|
|
jobs:
|
|
guardrails:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
# Defense in depth: fail if secrets or heavy/generated dirs were ever committed.
|
|
- name: Block secrets & node_modules
|
|
run: |
|
|
if git ls-files | grep -E '(^|/)\.env($|\.)|(^|/)secrets/|\.pem$|\.key$|\.p12$|\.pfx$|(^|/)id_rsa$|(^|/)id_ed25519$'; then
|
|
echo "::error::Secret-like files are tracked — remove them and rotate any exposed credential."; exit 1
|
|
fi
|
|
if git ls-files | grep -E '(^|/)node_modules/'; then
|
|
echo "::error::node_modules is tracked — it must be gitignored."; exit 1
|
|
fi
|
|
|
|
- name: Required standards files present
|
|
run: |
|
|
for f in CLAUDE.md PROJECT_STANDARD.md README.md; do
|
|
test -f "$f" || { echo "::error::Missing required file: $f"; exit 1; }
|
|
done
|
|
|
|
tests:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: "3.13"
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
pip install -r orchestrator/requirements.txt -r agent/requirements.txt
|
|
|
|
# Hermetic: in-memory store, planner forced offline by the tests — no model key needed.
|
|
- name: Manager contract test
|
|
env: { REDIS_FAKE: "1" }
|
|
run: python scripts/test-runtime-contract.py
|
|
|
|
- name: Workflow mechanism smoke test
|
|
env: { REDIS_FAKE: "1" }
|
|
run: python scripts/test-merge-smoke.py
|
|
|
|
- name: End-to-end workflow test
|
|
env: { REDIS_FAKE: "1" }
|
|
run: python scripts/test-workflow-e2e.py
|
|
|
|
- name: Per-user agent cap (MAX_AGENTS_PER_USER)
|
|
env: { REDIS_FAKE: "1" }
|
|
run: python scripts/test-max-agents-per-user.py
|
|
|
|
- name: Swarm agent launcher (plan/limit/key-resolve) (#16)
|
|
run: python scripts/test-agent-launcher.py
|
|
|
|
- name: Model-key injection + revocation handshake (#16/#60)
|
|
env: { REDIS_FAKE: "1" }
|
|
run: python scripts/test-key-injection-contract.py
|
|
|
|
- name: Manager event-contract test
|
|
env: { REDIS_FAKE: "1" }
|
|
run: python scripts/test-contract-events.py
|
|
|
|
- name: Swarm I/O — receive prompt + return result (#40)
|
|
env: { REDIS_FAKE: "1" }
|
|
run: python scripts/test-swarm-io.py
|
|
|
|
- name: Review/rework client timeline events (#34)
|
|
env: { REDIS_FAKE: "1", MAX_REVIEW_CYCLES: "2" }
|
|
run: python scripts/test-review-timeline-events.py
|
|
|
|
- name: Audit / lineage trace (replayable) (#17)
|
|
env: { REDIS_FAKE: "1" }
|
|
run: python scripts/test-audit-trace.py
|
|
|
|
- name: Benchmark metric formulas (v2.1)
|
|
env: { REDIS_FAKE: "1" }
|
|
run: python scripts/test-benchmark-metrics.py
|
|
|
|
- name: Benchmark collector
|
|
env: { REDIS_FAKE: "1" }
|
|
run: python scripts/test-benchmark-collector.py
|
|
|
|
- name: Baseline comparison
|
|
env: { REDIS_FAKE: "1" }
|
|
run: python scripts/test-baseline-comparison.py
|
|
|
|
- name: Code sandbox (in-pod test runner)
|
|
run: python scripts/test-sandbox.py
|
|
|
|
- name: Security boundary enforcement (secret/workspace/sandbox) (#19)
|
|
env: { REDIS_FAKE: "1" }
|
|
run: python scripts/test-security-boundary.py
|
|
|
|
- name: Quality instrumentation (Group B)
|
|
env: { REDIS_FAKE: "1" }
|
|
run: python scripts/test-quality.py
|
|
|
|
- name: Decision-engine pheromone library (τ)
|
|
env: { REDIS_FAKE: "1" }
|
|
run: python scripts/test-decision-engine.py
|
|
|
|
- name: Dispatch scoring formulas
|
|
env: { REDIS_FAKE: "1" }
|
|
run: python scripts/test-dispatch-score.py
|
|
|
|
# --- decentralized swarm flow (the only flow; primitives are unconditional) ---
|
|
- name: Swarm seeder (#6)
|
|
run: python scripts/test-swarm-seed.py
|
|
|
|
- name: Swarm self-selection dispatch
|
|
env: { REDIS_FAKE: "1" }
|
|
run: python scripts/test-swarm-dispatch.py
|
|
|
|
- name: Swarm autonomous task generation (#7)
|
|
env: { REDIS_FAKE: "1", AGENT_PROPOSAL_BUDGET: "3" }
|
|
run: python scripts/test-swarm-autonomous.py
|
|
|
|
- name: Swarm task competition (#8)
|
|
env: { REDIS_FAKE: "1" }
|
|
run: python scripts/test-swarm-competition.py
|
|
|
|
- name: Swarm cross-review (#11)
|
|
env: { REDIS_FAKE: "1" }
|
|
run: python scripts/test-swarm-cross-review.py
|
|
|
|
- name: Swarm convergence (#12)
|
|
env: { REDIS_FAKE: "1" }
|
|
run: python scripts/test-swarm-convergence.py
|
|
|
|
- name: Swarm health guard
|
|
env: { REDIS_FAKE: "1" }
|
|
run: python scripts/test-swarm-guard.py
|
|
|
|
# Pure-module unit tests for the swarm primitives (formulas/policies, infra-free).
|
|
- name: Swarm primitive modules (unit)
|
|
env: { REDIS_FAKE: "1" }
|
|
run: |
|
|
python scripts/test-autonomous-tasks.py
|
|
python scripts/test-task-competition.py
|
|
python scripts/test-cross-review.py
|
|
python scripts/test-convergence.py
|
|
|
|
# --- benchmark baseline runners + suite smoke (Group C, #21) ---
|
|
# HEICODE_SANDBOX_ISOLATED: the runners grade generated code in the fail-closed sandbox; the
|
|
# CI runner is ephemeral/isolated, so confirm isolation here (see security-boundary §8.1).
|
|
- name: Benchmark runners (Group C)
|
|
env: { HEICODE_SANDBOX_ISOLATED: "1" }
|
|
run: python scripts/test-benchmark-runners.py
|
|
|
|
# Offline = pipeline validation only (deterministic, no real G_E). Guards against regressions.
|
|
- name: Benchmark suite smoke (offline)
|
|
env: { HEICODE_SANDBOX_ISOLATED: "1" }
|
|
run: python scripts/run-benchmark-suite.py --taskset coding-set-1
|