Files
fengqun/examples/run_standard_scenario_acceptance.py
gongzhiyongandOmX c22dc7f573 Codify swarm characteristic acceptance
Make the user's six swarm characteristics first-class acceptance gates by adding S10/A07 tests, a standard document, and synchronized reports.

Constraint: The user asked to set acceptance indicators and test standard details around decentralization, self-organization, emergence, robustness, scalability, and implicit collaboration.

Rejected: Treating the six traits as prose-only documentation | they now run as deterministic tests and scenario matrix gates.

Confidence: high

Scope-risk: moderate

Directive: Future swarm-readiness claims must report F01-F06 explicitly and distinguish local Agent-layer proof from production no-coordinator runtime.

Tested: py_compile; unittest discover ran 41 tests; run_swarm_characteristics_acceptance PASS; run_academic_standard_evaluation A01-A07 PASS; run_standard_scenario_acceptance S01-S10 PASS with S07 run_id 9c7ccc6087c1435694a52efb12c32301; docs/README secret-pattern scan clean; git diff --cached --check clean.

Not-tested: Production no-coordinator distributed runtime and Kubernetes-scale worker telemetry remain outside this minimal local acceptance gate.

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

185 lines
7.2 KiB
Python

from pathlib import Path
import json
import subprocess
import sys
ROOT = Path(__file__).resolve().parents[1]
SCENARIOS = [
{
"id": "S01",
"name": "syntax_import_sanity",
"layer": "static",
"given": "all swarm_minimal, examples, and tests Python files",
"when": "compile every module",
"then": "no syntax or import-time compile errors",
"command": [sys.executable, "-B", "-m", "py_compile", *sorted(str(path.relative_to(ROOT)) for path in ROOT.glob("swarm_minimal/*.py")), *sorted(str(path.relative_to(ROOT)) for path in ROOT.glob("examples/*.py")), *sorted(str(path.relative_to(ROOT)) for path in ROOT.glob("tests/*.py"))],
},
{
"id": "S02",
"name": "unit_regression",
"layer": "unit",
"given": "mock NewAPI clients and in-memory swarm store",
"when": "run the full unittest suite",
"then": "all unit tests pass",
"command": [sys.executable, "-B", "-m", "unittest", "discover", "-s", "tests"],
},
{
"id": "S03-S06",
"name": "deterministic_standard_scenarios",
"layer": "scenario",
"given": "no-network deterministic cases for continuity, dependency policy, scoring, and failure injection",
"when": "run tests.test_standard_scenarios",
"then": "all scenario assertions pass",
"command": [sys.executable, "-B", "-m", "unittest", "tests.test_standard_scenarios"],
},
{
"id": "S07",
"name": "live_external_github_code_reasoning",
"layer": "live-integration",
"given": "local .env with Azure PostgreSQL, Redis, Blob, and NewAPI credentials",
"when": "run seven-step continuous reasoning acceptance against fastapi/fastapi at a pinned GitHub commit",
"then": "model discovery, external GitHub code targeting, PostgreSQL, Redis, Blob artifact, chain cursor, and convergence all pass",
"command": [sys.executable, "-u", "-B", "examples/run_continuous_reasoning_acceptance.py"],
"parse_json": True,
},
{
"id": "S08",
"name": "model_io_report_audit",
"layer": "report-audit",
"given": "generated docs/MODEL_AGNET_IO_REPORT.zh-CN.md",
"when": "audit scenario coverage, task input/output sections, handoff evidence, and obvious secret patterns",
"then": "the report is human-auditable and does not contain obvious secret values",
"command": [sys.executable, "-B", "-m", "unittest", "tests.test_model_io_report_audit"],
},
{
"id": "S09",
"name": "next_boundary_minimal_acceptance",
"layer": "scenario",
"given": "deterministic local harness for SW-AQS-16, candidate fusion, and questioning consensus",
"when": "run the next-boundary acceptance script",
"then": "3/5/7 autonomous claim, multi-candidate fusion, and challenge-revise-revote consensus all pass",
"command": [sys.executable, "-u", "-B", "examples/run_next_boundary_acceptance.py"],
"parse_json": True,
},
{
"id": "S10",
"name": "swarm_six_characteristics_acceptance",
"layer": "swarm-characteristics",
"given": "six swarm characteristics: decentralization, self-organization, emergence, robustness, scalability, and implicit collaboration",
"when": "run the swarm characteristics acceptance script",
"then": "all six swarm characteristic scenarios pass with explicit observable metrics",
"command": [sys.executable, "-u", "-B", "examples/run_swarm_characteristics_acceptance.py"],
"parse_json": True,
},
]
def main() -> None:
results = []
for scenario in SCENARIOS:
completed = subprocess.run(
scenario["command"],
cwd=ROOT,
text=True,
capture_output=True,
timeout=900,
)
evidence = summarize_process_output(completed.stdout, completed.stderr)
parsed = None
if scenario.get("parse_json") and completed.stdout.strip():
parsed = parse_last_json(completed.stdout)
if parsed:
evidence = summarize_live_report(parsed)
result = {
"id": scenario["id"],
"name": scenario["name"],
"layer": scenario["layer"],
"given": scenario["given"],
"when": scenario["when"],
"then": scenario["then"],
"command": " ".join(scenario["command"]),
"passed": completed.returncode == 0,
"evidence": evidence,
}
if parsed:
result["live_summary"] = parsed.get("summary", {})
results.append(result)
if completed.returncode != 0:
break
report = {
"standard": "scenario-matrix-v1",
"status": "PASS" if all(item["passed"] for item in results) and len(results) == len(SCENARIOS) else "FAIL",
"scenarios": results,
}
print(json.dumps(report, ensure_ascii=False, indent=2))
if report["status"] != "PASS":
raise SystemExit(1)
def summarize_process_output(stdout: str, stderr: str) -> dict[str, object]:
combined = "\n".join(part.strip() for part in [stdout, stderr] if part.strip())
tail = combined[-1200:] if combined else "<no output>"
return {"tail": tail}
def parse_last_json(text: str) -> dict[str, object] | None:
stripped = text.strip()
if not stripped:
return None
decoder = json.JSONDecoder()
last = None
index = 0
while index < len(stripped):
brace = stripped.find("{", index)
if brace == -1:
break
try:
value, end = decoder.raw_decode(stripped[brace:])
except json.JSONDecodeError:
index = brace + 1
continue
if isinstance(value, dict):
last = value
index = brace + end
return last
def summarize_live_report(report: dict[str, object]) -> dict[str, object]:
if report.get("standard") == "next-boundary-minimal-acceptance-v1":
checks = report.get("checks", [])
failed_checks = [check["name"] for check in checks if isinstance(check, dict) and not check.get("passed")]
return {
"summary": report.get("scope", {}),
"failed_checks": failed_checks,
"check_count": len(checks) if isinstance(checks, list) else 0,
}
if report.get("standard") == "swarm-six-characteristics-v1":
scenarios = report.get("scenarios", [])
failed_scenarios = [
item.get("id")
for item in scenarios
if isinstance(item, dict) and not item.get("passed")
]
return {
"features": report.get("features", []),
"failed_scenarios": failed_scenarios,
"scenario_count": len(scenarios) if isinstance(scenarios, list) else 0,
}
summary = report.get("summary", {})
checks = report.get("checks", [])
failed_checks = [check["name"] for check in checks if isinstance(check, dict) and not check.get("passed")]
return {
"summary": summary,
"selected_models": report.get("selected_models", []),
"failed_checks": failed_checks,
"check_count": len(checks) if isinstance(checks, list) else 0,
}
if __name__ == "__main__":
main()