Files
fengqun/examples/run_next_boundary_acceptance.py
T
gongzhiyongandOmX 2fd6e4ab9a Close next-boundary swarm gaps
Turn the remaining minimal-boundary items into executable behavior: locked autonomous claim scaling for 3/5/7 agents, multi-candidate fusion, and challenge-revise-revote consensus.

Constraint: The user asked to implement code directly, complete testing and acceptance, and explain the test standards rather than only updating the comparison document.

Rejected: Leaving SW-AQS-16, candidate fusion, and questioning consensus as documentation-only future work | each now has deterministic code paths and S09 acceptance evidence.

Confidence: high

Scope-risk: moderate

Directive: Future claims about full production readiness must still distinguish this local deterministic S09 acceptance from real runtime/Kubernetes scaling and Manager/Agnet platform integration.

Tested: .venv/bin/python -B -m py_compile swarm_minimal/*.py examples/*.py tests/*.py; .venv/bin/python -B -m unittest tests.test_standard_scenarios; .venv/bin/python -B -m unittest discover -s tests; .venv/bin/python -u -B examples/run_next_boundary_acceptance.py; .venv/bin/python -u -B examples/run_academic_standard_evaluation.py; .venv/bin/python -u -B examples/run_standard_scenario_acceptance.py; .venv/bin/python -B examples/export_model_agnet_io_report.py; .venv/bin/python -B -m unittest tests.test_model_io_report_audit; docs secret pattern scan; git diff --check.

Not-tested: Real Kubernetes/worker runtime 3/5/7 scaling, Redis Stream consumer-driven replanning, and Manager/Agnet approval integration remain outside this local minimal acceptance.

Co-authored-by: OmX <omx@oh-my-codex.dev>
2026-05-16 17:09:03 +08:00

178 lines
6.3 KiB
Python

from __future__ import annotations
import json
from pathlib import Path
import sys
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
from swarm_minimal.core import ( # noqa: E402
Agent,
CandidateOutput,
ConsensusVote,
InMemorySwarmStore,
QuestioningAgent,
QuestioningConsensusSwarm,
SwarmCoordinator,
Task,
TaskStatus,
fuse_candidate_outputs,
)
def main() -> None:
checks = [
scaled_autonomous_claim_acceptance(),
candidate_fusion_acceptance(),
questioning_consensus_acceptance(),
]
report = {
"standard": "next-boundary-minimal-acceptance-v1",
"status": "PASS" if all(check["passed"] for check in checks) else "FAIL",
"scope": {
"sw_aqs_16": "3/5/7 Agent autonomous claim and scale stress",
"candidate_fusion": "merge multiple valid candidates instead of selecting one winner only",
"questioning_consensus": "challenge, revise, and re-vote before final acceptance",
},
"checks": checks,
}
print(json.dumps(report, ensure_ascii=False, indent=2))
if report["status"] != "PASS":
raise SystemExit(1)
def scaled_autonomous_claim_acceptance() -> dict[str, object]:
cases = []
for agent_count in (3, 5, 7):
store = InMemorySwarmStore()
run_id = f"s09-scaled-claim-{agent_count}"
task_count = agent_count * 2
store.shared_state[f"run:{run_id}:goal"] = "scaled autonomous claim"
store.shared_state[f"run:{run_id}:status"] = "running"
for index in range(task_count):
store.add_task(Task(kind="stress", input=f"claim target {index}"))
agents = [
Agent(
id=f"claim-agent-{index}",
capability="stress",
run=lambda task, shared_state, index=index: (
f"agent={index}; task={task.input}; autonomous_claim=ok",
0.7 + index / 100,
),
)
for index in range(agent_count)
]
report = SwarmCoordinator(store=store, agents=agents).run_autonomous_until_converged(run_id)
claimed_agents = {event.agent_id for event in report.claim_events}
case = {
"agent_count": agent_count,
"task_count": task_count,
"completed_tasks": report.completed_tasks,
"failed_tasks": report.failed_tasks,
"duplicate_claims": list(report.duplicate_claims),
"participating_agents": len(claimed_agents),
"converged": report.converged,
"passed": (
report.converged
and report.completed_tasks == task_count
and report.failed_tasks == 0
and report.duplicate_claims == ()
and len(claimed_agents) == agent_count
and all(task.status == TaskStatus.DONE for task in store.tasks.values())
),
}
cases.append(case)
return {
"name": "sw_aqs_16_scaled_autonomous_claim_3_5_7",
"passed": all(case["passed"] for case in cases),
"evidence": cases,
}
def candidate_fusion_acceptance() -> dict[str, object]:
fused = fuse_candidate_outputs(
[
CandidateOutput("quality", "保留质量门\n保留 fallback 补救", 0.91, "quality"),
CandidateOutput("coverage", "保留 fallback 补救\n加入候选融合输出", 0.86, "coverage"),
CandidateOutput("noise", "低分噪声", 0.2, "below-threshold"),
],
min_score=0.5,
)
expected_terms = ["保留质量门", "保留 fallback 补救", "加入候选融合输出"]
passed = (
fused.source_candidate_ids == ("quality", "coverage")
and all(term in fused.text for term in expected_terms)
and "低分噪声" not in fused.text
)
return {
"name": "candidate_fusion_output",
"passed": passed,
"evidence": {
"source_candidate_ids": list(fused.source_candidate_ids),
"score": fused.score,
"contains": expected_terms,
"evidence": fused.evidence,
},
}
def questioning_consensus_acceptance() -> dict[str, object]:
result = QuestioningConsensusSwarm(
[
make_questioning_agent("critic", "反驳", "revise_again"),
make_questioning_agent("repairer", "修正", "revise_again"),
make_questioning_agent("verifier", "验收", "approve_fused_candidate"),
],
threshold=0.7,
min_margin=0.2,
max_rounds=3,
evaporation=0.85,
).run("questioning consensus", "初始候选:质量门后的最高分输出")
passed = (
result.converged
and result.accepted_candidate == "approve_fused_candidate"
and len(result.rounds) >= 2
and not result.rounds[0].consensus_round.converged
and result.rounds[-1].consensus_round.converged
and all(item.challenges for item in result.rounds)
and all(item.revisions for item in result.rounds)
)
return {
"name": "question_revise_revote_consensus",
"passed": passed,
"evidence": {
"accepted_candidate": result.accepted_candidate,
"round_count": len(result.rounds),
"first_round_converged": result.rounds[0].consensus_round.converged,
"last_round_converged": result.rounds[-1].consensus_round.converged,
},
}
def make_questioning_agent(agent_id: str, role: str, first_vote: str) -> QuestioningAgent:
return QuestioningAgent(
id=agent_id,
role=role,
weight=1.0,
challenge=lambda candidate, state, round_index, role=role: f"{role} 质询 round={round_index}: 需要补充证据",
revise=lambda candidate, challenges, state, round_index, role=role: (
f"{candidate}\n{role} 修正 round={round_index}: 已回应 {len(challenges)} 个质询"
),
vote=lambda candidate, state, round_index, agent_id=agent_id, role=role, first_vote=first_vote: ConsensusVote(
agent_id=agent_id,
role=role,
candidate=first_vote if round_index == 1 else "approve_fused_candidate",
confidence=0.55 if round_index == 1 else 0.78,
evidence=f"{role} 已检查反驳、修正和再投票",
),
)
if __name__ == "__main__":
main()