test: define consolidated agent workflow contract
This commit is contained in:
@@ -0,0 +1,221 @@
|
||||
from pathlib import Path
|
||||
import tomllib
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
AGENT_DIR = ROOT / ".codex" / "agents"
|
||||
SKILL_DIR = ROOT / ".codex" / "skills"
|
||||
|
||||
EXPECTED_AGENTS = {
|
||||
"coordinator-agent",
|
||||
"correction-agent",
|
||||
"formulation-agent",
|
||||
"implementation-agent",
|
||||
"implementation-planning-agent",
|
||||
"io-definition-agent",
|
||||
"numerical-review-agent",
|
||||
"physics-evaluation-agent",
|
||||
"release-agent",
|
||||
"requirement-agent",
|
||||
"research-agent",
|
||||
}
|
||||
|
||||
EXPECTED_SKILLS = {
|
||||
"fem-theory-query",
|
||||
"fesa-cpp-msvc-tdd",
|
||||
"fesa-formulation-spec",
|
||||
"fesa-io-contract",
|
||||
"fesa-numerical-review",
|
||||
"fesa-physics-sanity",
|
||||
"fesa-release-readiness",
|
||||
"fesa-requirements-baseline",
|
||||
"fesa-research-evidence",
|
||||
}
|
||||
|
||||
LEGACY_OUTPUT_DIRS = {
|
||||
"coordination",
|
||||
"requirements",
|
||||
"research",
|
||||
"formulations",
|
||||
"numerical-reviews",
|
||||
"io-definitions",
|
||||
"reference-models",
|
||||
"implementation-plans",
|
||||
"build-test-reports",
|
||||
"corrections",
|
||||
"reference-verifications",
|
||||
"physics-evaluations",
|
||||
"releases",
|
||||
}
|
||||
|
||||
FEATURE_FILES = {
|
||||
"linear-static-3d-euler-beam": {
|
||||
"coordination.md",
|
||||
"requirements.md",
|
||||
"research.md",
|
||||
"formulation.md",
|
||||
"numerical-review.md",
|
||||
"reference-model.md",
|
||||
"io.md",
|
||||
"implementation-plan.md",
|
||||
"implementation-report.md",
|
||||
"build-test.md",
|
||||
"reference-comparison.md",
|
||||
"physics-evaluation.md",
|
||||
"release.md",
|
||||
},
|
||||
"linear-static-mitc4-shell": {
|
||||
"coordination.md",
|
||||
"requirements.md",
|
||||
"research.md",
|
||||
"formulation.md",
|
||||
"numerical-review.md",
|
||||
"reference-model.md",
|
||||
"io.md",
|
||||
"implementation-plan.md",
|
||||
"build-test.md",
|
||||
"reference-comparison.md",
|
||||
"physics-evaluation.md",
|
||||
"release.md",
|
||||
},
|
||||
}
|
||||
|
||||
LIVE_CONTRACT_FILES = (
|
||||
ROOT / "AGENTS.md",
|
||||
ROOT / "docs" / "SOLVER_AGENT_DESIGN.md",
|
||||
ROOT / "docs" / "SOLVER_SKILL_DESIGN.md",
|
||||
)
|
||||
|
||||
RETIRED_TOKENS = (
|
||||
"reference-model-agent",
|
||||
"reference model agent",
|
||||
"build-test-executor-agent",
|
||||
"build/test executor agent",
|
||||
"reference-verification-agent",
|
||||
"reference verification agent",
|
||||
"fesa-reference-models",
|
||||
"fesa-reference-comparison",
|
||||
"docs/coordination/",
|
||||
"docs/requirements/",
|
||||
"docs/research/",
|
||||
"docs/formulations/",
|
||||
"docs/numerical-reviews/",
|
||||
"docs/io-definitions/",
|
||||
"docs/reference-models/",
|
||||
"docs/implementation-plans/",
|
||||
"docs/build-test-reports/",
|
||||
"docs/corrections/",
|
||||
"docs/reference-verifications/",
|
||||
"docs/physics-evaluations/",
|
||||
"docs/releases/",
|
||||
)
|
||||
|
||||
|
||||
def read(path: Path) -> str:
|
||||
return path.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def live_contract_text() -> str:
|
||||
paths = list(LIVE_CONTRACT_FILES)
|
||||
paths.extend(sorted(AGENT_DIR.glob("*.toml")))
|
||||
paths.extend(sorted(SKILL_DIR.glob("*/SKILL.md")))
|
||||
return "\n".join(read(path) for path in paths)
|
||||
|
||||
|
||||
def test_agent_inventory_is_consolidated():
|
||||
actual = {path.stem for path in AGENT_DIR.glob("*.toml")}
|
||||
assert actual == EXPECTED_AGENTS
|
||||
|
||||
|
||||
def test_project_skill_inventory_is_consolidated():
|
||||
actual = {
|
||||
path.name
|
||||
for path in SKILL_DIR.iterdir()
|
||||
if path.is_dir() and (path / "SKILL.md").is_file()
|
||||
}
|
||||
assert actual == EXPECTED_SKILLS
|
||||
|
||||
|
||||
def test_existing_feature_artifacts_are_bundled():
|
||||
docs_dir = ROOT / "docs"
|
||||
for legacy_dir in LEGACY_OUTPUT_DIRS:
|
||||
assert not (docs_dir / legacy_dir).exists(), legacy_dir
|
||||
|
||||
for feature_id, expected_files in FEATURE_FILES.items():
|
||||
feature_dir = docs_dir / feature_id
|
||||
actual_files = {path.name for path in feature_dir.glob("*.md")}
|
||||
assert actual_files == expected_files
|
||||
|
||||
|
||||
def test_numerical_review_absorbs_reference_model_contract():
|
||||
assert not (AGENT_DIR / "reference-model-agent.toml").exists()
|
||||
assert not (SKILL_DIR / "fesa-reference-models").exists()
|
||||
text = read(SKILL_DIR / "fesa-numerical-review" / "SKILL.md").lower()
|
||||
for marker in (
|
||||
"numerical-review.md",
|
||||
"reference-model.md",
|
||||
"reference case inventory",
|
||||
"source identity",
|
||||
"row precheck",
|
||||
"tolerance",
|
||||
"pass-for-io-definition",
|
||||
):
|
||||
assert marker in text
|
||||
|
||||
|
||||
def test_implementation_absorbs_build_test_and_reference_comparison():
|
||||
assert not (AGENT_DIR / "build-test-executor-agent.toml").exists()
|
||||
assert not (AGENT_DIR / "reference-verification-agent.toml").exists()
|
||||
assert not (SKILL_DIR / "fesa-reference-comparison").exists()
|
||||
text = read(SKILL_DIR / "fesa-cpp-msvc-tdd" / "SKILL.md").lower()
|
||||
for marker in (
|
||||
"implementation-report.md",
|
||||
"build-test.md",
|
||||
"reference-comparison.md",
|
||||
"artifact check -> compare -> classify -> report",
|
||||
"pass-for-physics-evaluation",
|
||||
):
|
||||
assert marker in text
|
||||
|
||||
|
||||
def test_agent_hierarchy_is_explicit():
|
||||
coordinator = read(AGENT_DIR / "coordinator-agent.toml").lower()
|
||||
assert "main agent" in coordinator
|
||||
assert "docs/<feature-id>/coordination.md" in coordinator
|
||||
assert "worklist" in coordinator
|
||||
assert "sub-agent dispatch" in coordinator
|
||||
|
||||
for path in sorted(AGENT_DIR.glob("*.toml")):
|
||||
if path.name == "coordinator-agent.toml":
|
||||
continue
|
||||
text = read(path).lower()
|
||||
assert "sub-agent" in text, path.name
|
||||
assert "coordinator agent" in text, path.name
|
||||
|
||||
|
||||
def test_live_contracts_have_no_retired_names_or_paths():
|
||||
text = live_contract_text().lower()
|
||||
assert "docs/<feature-id>/" in text
|
||||
for token in RETIRED_TOKENS:
|
||||
assert token not in text, token
|
||||
|
||||
|
||||
def test_live_guidance_declares_eight_stage_workflow():
|
||||
for path in LIVE_CONTRACT_FILES:
|
||||
text = read(path)
|
||||
assert "8단계" in text, path
|
||||
assert "docs/<feature-id>/" in text, path
|
||||
|
||||
|
||||
def test_agent_toml_and_skill_ui_metadata_are_parseable():
|
||||
for path in sorted(AGENT_DIR.glob("*.toml")):
|
||||
parsed = tomllib.loads(read(path))
|
||||
assert parsed["name"] == path.stem
|
||||
assert parsed["model_reasoning_effort"] == "extra high"
|
||||
|
||||
for skill_name in EXPECTED_SKILLS:
|
||||
skill_dir = SKILL_DIR / skill_name
|
||||
skill_text = read(skill_dir / "SKILL.md")
|
||||
ui_text = read(skill_dir / "agents" / "openai.yaml")
|
||||
assert f"name: {skill_name}" in skill_text
|
||||
assert f"${skill_name}" in ui_text
|
||||
Reference in New Issue
Block a user