initial commit
This commit is contained in:
@@ -0,0 +1,310 @@
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
try:
|
||||
import tomllib
|
||||
except ModuleNotFoundError: # pragma: no cover
|
||||
import tomli as tomllib
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
AGENTS_ROOT = ROOT / ".codex" / "agents"
|
||||
SKILLS_ROOT = ROOT / ".codex" / "skills"
|
||||
|
||||
DESIGN_DOC = ROOT / "docs" / "ABAQUS_SUBROUTINE_AGENT_DESIGN.md"
|
||||
|
||||
COMMON_SKILL_SECTIONS = (
|
||||
"## Inputs",
|
||||
"## Workflow",
|
||||
"## Output Contract",
|
||||
"## Boundaries",
|
||||
"## Quality Gate",
|
||||
"## Handoff",
|
||||
)
|
||||
|
||||
SKILLS = {
|
||||
"abaqus-subroutine-requirements": (
|
||||
"Subroutine requirements",
|
||||
"ABAQUS-USUB-REQ-<FEATURE>-###",
|
||||
"Requirement Verification Matrix",
|
||||
"UMAT | VUMAT | UEL",
|
||||
"Do not implement Fortran code.",
|
||||
),
|
||||
"abaqus-subroutine-research": (
|
||||
"Research evidence",
|
||||
"official Abaqus documentation",
|
||||
"books, papers, and benchmark sources",
|
||||
"Separate verified facts from inference.",
|
||||
"Abaqus User Subroutines Reference Guide",
|
||||
),
|
||||
"abaqus-subroutine-formulation": (
|
||||
"Finite element formulation",
|
||||
"stress update",
|
||||
"consistent tangent",
|
||||
"state variables",
|
||||
"Do not design Fortran source layout.",
|
||||
),
|
||||
"abaqus-subroutine-numerical-review": (
|
||||
"Numerical review",
|
||||
"finite-difference tangent check",
|
||||
"state variable update",
|
||||
"stability risks",
|
||||
"pass-for-interface-definition",
|
||||
),
|
||||
"abaqus-subroutine-interface": (
|
||||
"Abaqus ABI Contract",
|
||||
"UMAT",
|
||||
"VUMAT",
|
||||
"UEL",
|
||||
"DDSDDE",
|
||||
"STATEV",
|
||||
),
|
||||
"abaqus-subroutine-test-models": (
|
||||
"TDD test model",
|
||||
"no-Abaqus",
|
||||
"tests/fortran/manifest.json",
|
||||
"references/<feature-id>/<model-id>/",
|
||||
"source hash",
|
||||
"msg/dat/log tail",
|
||||
),
|
||||
"abaqus-fortran-tdd": (
|
||||
"Fortran TDD",
|
||||
"RED -> GREEN -> VERIFY",
|
||||
"python scripts/validate_fortran.py",
|
||||
"Intel oneAPI",
|
||||
"ifx",
|
||||
"ifort",
|
||||
),
|
||||
"abaqus-subroutine-validation": (
|
||||
"Subroutine validation",
|
||||
"HARNESS_ABAQUS_VALIDATION=run",
|
||||
"ready-for-comparison",
|
||||
"source hash",
|
||||
"msg/dat/log",
|
||||
"Do not change tolerance policies.",
|
||||
),
|
||||
"abaqus-subroutine-physics-sanity": (
|
||||
"Physics sanity",
|
||||
"global equilibrium",
|
||||
"reaction consistency",
|
||||
"stress/strain",
|
||||
"state variable",
|
||||
"energy/residual",
|
||||
),
|
||||
"abaqus-subroutine-readiness": (
|
||||
"Readiness audit",
|
||||
"Gate Evidence Inventory",
|
||||
"Known Limitations",
|
||||
"Validation Evidence",
|
||||
"Do not publish, deploy, package, tag, commit, or externally release anything unless the user explicitly asks.",
|
||||
),
|
||||
}
|
||||
|
||||
AGENT_SKILL_REFERENCES = {
|
||||
"coordinator-agent.toml": (
|
||||
"abaqus-subroutine-requirements",
|
||||
"abaqus-subroutine-test-models",
|
||||
"abaqus-subroutine-readiness",
|
||||
),
|
||||
"requirement-agent.toml": ("abaqus-subroutine-requirements",),
|
||||
"research-agent.toml": ("abaqus-subroutine-research", "fem-theory-query"),
|
||||
"formulation-agent.toml": ("abaqus-subroutine-formulation", "fem-theory-query"),
|
||||
"numerical-review-agent.toml": (
|
||||
"abaqus-subroutine-numerical-review",
|
||||
"fem-theory-query",
|
||||
),
|
||||
"io-definition-agent.toml": (
|
||||
"abaqus-subroutine-interface",
|
||||
"fem-theory-query",
|
||||
),
|
||||
"reference-model-agent.toml": (
|
||||
"abaqus-subroutine-test-models",
|
||||
"fem-theory-query",
|
||||
),
|
||||
"implementation-planning-agent.toml": (
|
||||
"abaqus-subroutine-formulation",
|
||||
"abaqus-subroutine-test-models",
|
||||
"abaqus-fortran-tdd",
|
||||
"fem-theory-query",
|
||||
),
|
||||
"implementation-agent.toml": ("abaqus-fortran-tdd",),
|
||||
"build-test-executor-agent.toml": (
|
||||
"abaqus-fortran-tdd",
|
||||
"abaqus-subroutine-validation",
|
||||
),
|
||||
"correction-agent.toml": ("abaqus-fortran-tdd",),
|
||||
"reference-verification-agent.toml": (
|
||||
"abaqus-subroutine-validation",
|
||||
"abaqus-subroutine-interface",
|
||||
),
|
||||
"physics-evaluation-agent.toml": (
|
||||
"abaqus-subroutine-physics-sanity",
|
||||
"fem-theory-query",
|
||||
),
|
||||
"release-agent.toml": ("abaqus-subroutine-readiness",),
|
||||
}
|
||||
|
||||
AGENT_REQUIRED_TERMS = {
|
||||
"coordinator-agent.toml": (
|
||||
"1. Subroutine requirements analysis",
|
||||
"2. Research evidence",
|
||||
"3. Finite element formulation",
|
||||
"4. Abaqus subroutine interface",
|
||||
"5. TDD test models",
|
||||
"6. Fortran implementation",
|
||||
"7. Subroutine validation",
|
||||
),
|
||||
"requirement-agent.toml": ("Subroutine requirements analysis", "ABAQUS-USUB-REQ"),
|
||||
"research-agent.toml": ("books, papers, official Abaqus manuals", "source reliability"),
|
||||
"formulation-agent.toml": ("stress update", "consistent tangent", "state variables"),
|
||||
"numerical-review-agent.toml": (
|
||||
"finite-difference tangent check",
|
||||
"algorithmic consistency",
|
||||
),
|
||||
"io-definition-agent.toml": ("Abaqus ABI Contract", "STRESS", "DDSDDE", "STATEV"),
|
||||
"reference-model-agent.toml": (
|
||||
"tests/fortran/manifest.json",
|
||||
"references/<feature-id>/<model-id>/",
|
||||
),
|
||||
"implementation-planning-agent.toml": (
|
||||
"Fortran source",
|
||||
"no-Abaqus driver",
|
||||
"RED -> GREEN -> VERIFY",
|
||||
),
|
||||
"implementation-agent.toml": ("Fortran source", "Intel oneAPI", "RED -> GREEN -> VERIFY"),
|
||||
"build-test-executor-agent.toml": (
|
||||
"python scripts/validate_fortran.py",
|
||||
"HARNESS_ABAQUS_VALIDATION=run",
|
||||
),
|
||||
"correction-agent.toml": ("Fortran compile", "minimal correction"),
|
||||
"reference-verification-agent.toml": (
|
||||
"metadata.json",
|
||||
"source hash",
|
||||
"Abaqus version",
|
||||
"compiler version",
|
||||
),
|
||||
"physics-evaluation-agent.toml": ("global equilibrium", "stress/strain", "state variable"),
|
||||
"release-agent.toml": ("Gate Evidence Inventory", "Known Limitations"),
|
||||
}
|
||||
|
||||
|
||||
def parse_frontmatter(text):
|
||||
lines = text.splitlines()
|
||||
if not lines or lines[0] != "---":
|
||||
raise AssertionError("SKILL.md must start with YAML frontmatter")
|
||||
|
||||
fields = {}
|
||||
for line in lines[1:]:
|
||||
if line == "---":
|
||||
return fields
|
||||
key, sep, value = line.partition(":")
|
||||
if not sep:
|
||||
raise AssertionError(f"Invalid frontmatter line: {line}")
|
||||
fields[key.strip()] = value.strip()
|
||||
|
||||
raise AssertionError("SKILL.md frontmatter must be closed")
|
||||
|
||||
|
||||
class AbaqusSubroutineCodexConfigTests(unittest.TestCase):
|
||||
def test_abaqus_subroutine_skill_files_exist_with_metadata(self):
|
||||
for skill_name, body_terms in SKILLS.items():
|
||||
with self.subTest(skill=skill_name):
|
||||
skill_path = SKILLS_ROOT / skill_name / "SKILL.md"
|
||||
self.assertTrue(skill_path.exists(), f"{skill_name} SKILL.md is missing")
|
||||
text = skill_path.read_text(encoding="utf-8")
|
||||
fields = parse_frontmatter(text)
|
||||
|
||||
self.assertEqual(set(fields), {"name", "description"})
|
||||
self.assertEqual(fields["name"], skill_name)
|
||||
self.assertIn("Use when", fields["description"])
|
||||
self.assertIn("Abaqus", fields["description"])
|
||||
self.assertIn("User Subroutine", fields["description"])
|
||||
for section in COMMON_SKILL_SECTIONS:
|
||||
self.assertIn(section, text)
|
||||
self.assertIn("AGENTS.md", text)
|
||||
self.assertIn("docs/ABAQUS_SUBROUTINE_AGENT_DESIGN.md", text)
|
||||
for term in body_terms:
|
||||
self.assertIn(term, text)
|
||||
|
||||
def test_abaqus_subroutine_skills_have_ui_metadata(self):
|
||||
for skill_name in SKILLS:
|
||||
with self.subTest(skill=skill_name):
|
||||
metadata = SKILLS_ROOT / skill_name / "agents" / "openai.yaml"
|
||||
self.assertTrue(metadata.exists(), f"{skill_name} openai.yaml is missing")
|
||||
text = metadata.read_text(encoding="utf-8")
|
||||
self.assertIn("interface:", text)
|
||||
self.assertIn("display_name:", text)
|
||||
self.assertIn("short_description:", text)
|
||||
self.assertIn("default_prompt:", text)
|
||||
self.assertIn(f"${skill_name}", text)
|
||||
|
||||
def test_deprecated_fesa_skill_directories_are_removed(self):
|
||||
deprecated = sorted(p.name for p in SKILLS_ROOT.iterdir() if p.name.startswith("fesa-"))
|
||||
self.assertEqual([], deprecated)
|
||||
|
||||
def test_agents_reference_abaqus_subroutine_skills(self):
|
||||
for agent_file, skill_names in AGENT_SKILL_REFERENCES.items():
|
||||
with self.subTest(agent=agent_file):
|
||||
text = (AGENTS_ROOT / agent_file).read_text(encoding="utf-8")
|
||||
data = tomllib.loads(text)
|
||||
self.assertEqual(data["name"], agent_file.removesuffix(".toml"))
|
||||
self.assertEqual(data["model_reasoning_effort"], "extra high")
|
||||
self.assertIn("Abaqus User Subroutine", data["description"])
|
||||
instructions = data["developer_instructions"]
|
||||
self.assertIn("Skill references:", instructions)
|
||||
self.assertIn("Abaqus User Subroutine", instructions)
|
||||
for skill_name in skill_names:
|
||||
self.assertIn(f"${skill_name}", instructions)
|
||||
for term in AGENT_REQUIRED_TERMS[agent_file]:
|
||||
self.assertIn(term, instructions)
|
||||
|
||||
def test_agent_and_skill_text_no_longer_targets_fesa_cpp_solver_work(self):
|
||||
checked_paths = list(AGENTS_ROOT.glob("*.toml"))
|
||||
checked_paths += [SKILLS_ROOT / name / "SKILL.md" for name in SKILLS]
|
||||
checked_paths += list((SKILLS_ROOT / "harness-workflow").glob("SKILL.md"))
|
||||
checked_paths += list((SKILLS_ROOT / "harness-review").glob("SKILL.md"))
|
||||
|
||||
forbidden_terms = (
|
||||
"FESA solver",
|
||||
"FESA FEM",
|
||||
"FESA C++",
|
||||
"C++17/MSVC",
|
||||
"C++/MSVC",
|
||||
"CMake/CTest",
|
||||
)
|
||||
for path in checked_paths:
|
||||
with self.subTest(path=path):
|
||||
text = path.read_text(encoding="utf-8")
|
||||
for forbidden in forbidden_terms:
|
||||
self.assertNotIn(forbidden, text)
|
||||
|
||||
def test_harness_skills_target_fortran_subroutine_workflow(self):
|
||||
for skill_name in ("harness-workflow", "harness-review"):
|
||||
with self.subTest(skill=skill_name):
|
||||
text = (SKILLS_ROOT / skill_name / "SKILL.md").read_text(encoding="utf-8")
|
||||
for term in (
|
||||
"Abaqus User Subroutine",
|
||||
"Fortran",
|
||||
"python scripts/validate_fortran.py",
|
||||
"python scripts/validate_reference_artifacts.py",
|
||||
"HARNESS_ABAQUS_VALIDATION=run",
|
||||
):
|
||||
self.assertIn(term, text)
|
||||
|
||||
def test_design_doc_captures_user_subroutine_process(self):
|
||||
text = DESIGN_DOC.read_text(encoding="utf-8")
|
||||
for term in (
|
||||
"Abaqus User Subroutine development process",
|
||||
"1. Subroutine requirements analysis",
|
||||
"2. Books, papers, and research evidence",
|
||||
"3. Finite element formulation for implementation",
|
||||
"4. Subroutine input/output parameter definition",
|
||||
"5. TDD test model design",
|
||||
"6. Fortran code implementation",
|
||||
"7. Subroutine validation",
|
||||
):
|
||||
self.assertIn(term, text)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user