import unittest from pathlib import Path ROOT = Path(__file__).resolve().parents[1] SKILLS_ROOT = ROOT / ".codex" / "skills" COMMON_SECTIONS = ( "## Inputs", "## Workflow", "## Output Contract", "## Boundaries", "## Quality Gate", "## Handoff", ) SKILLS = { "fesa-requirements-baseline": { "description_terms": ( "Use when", "FESA solver", "requirements", "acceptance criteria", "verification matrix", ), "body_terms": ( "docs/requirements/.md", "Requirement Verification Matrix", "shall", "FESA-REQ--###", "Verification Quantities", "Tolerance Policy", "Reference Artifact Requirements", "Do not implement C++ code.", ), }, "fesa-research-evidence": { "description_terms": ( "Use when", "FESA solver", "research", "FEM theory", "benchmarks", ), "body_terms": ( "docs/research/-research.md", "Source Inventory", "Source Reliability Tier", "Candidate Benchmarks", "Verification Relevance", "Applicability Limits", "Separate verified facts from inference.", ), }, "fesa-formulation-spec": { "description_terms": ( "Use when", "FESA FEM", "formulation", "element equations", "output recovery", ), "body_terms": ( "docs/formulations/-formulation.md", "Strong Form", "Weak or Variational Form", "Discretization", "Kinematics", "Element Equations", "Jacobian", "Output Recovery", "Do not design C++ APIs.", ), }, "fesa-numerical-review": { "description_terms": ( "Use when", "FESA FEM", "numerical review", "stability", "implementation planning", ), "body_terms": ( "docs/numerical-reviews/-review.md", "pass-for-implementation-planning", "rigid body modes", "patch test", "hourglass", "locking", "Jacobian", "Do not edit formulations directly.", ), }, "fesa-io-contract": { "description_terms": ( "Use when", "FESA solver", "Abaqus .inp", "HDF5", "CSV view", "I/O", ), "body_terms": ( "docs/io-definitions/-io.md", "Abaqus Input Scope", "Internal Model Contract", "Output HDF5 Schema", "Deterministic CSV View Schemas", "results.h5", "csv/displacements.csv", "*NODE", "*ELEMENT", "*MATERIAL", "*BOUNDARY", "*STEP", "Do not implement parsers.", ), }, "fesa-reference-models": { "description_terms": ( "Use when", "FESA", "reference model", "Abaqus input", "artifact", ), "body_terms": ( "docs/reference-models/-reference-models.md", "references///", "model.inp", "metadata.json", "reference.h5", "csv/displacements.csv", "csv/reactions.csv", "csv/element_forces.csv", "csv/stresses.csv", "Coverage Matrix", "Do not generate reference HDF5 files or deterministic CSV views.", ), }, "fesa-cpp-msvc-tdd": { "description_terms": ( "Use when", "FESA solver", "C++", "MSVC", "TDD", ), "body_terms": ( "docs/implementation-plans/-implementation-plan.md", "RED -> GREEN -> VERIFY", "python -m unittest discover -s scripts -p \"test_*.py\"", "python scripts/validate_workspace.py", "ctest", "configure | compile | link | test | reference-comparison", "Do not change requirements.", ), }, "fesa-reference-comparison": { "description_terms": ( "Use when", "FESA solver", "HDF5", "CSV view", "tolerance", "comparison", ), "body_terms": ( "docs/reference-verifications/-reference-verification.md", "ARTIFACT CHECK -> COMPARE -> CLASSIFY -> REPORT", "results.h5", "reference.h5", "deterministic CSV view", "max absolute error", "max relative error", "RMS error", "missing rows", "extra rows", "pass-for-physics-evaluation", "Do not change tolerance policies.", ), }, "fesa-physics-sanity": { "description_terms": ( "Use when", "FESA solver", "physical plausibility", "equilibrium", "physics", ), "body_terms": ( "docs/physics-evaluations/-physics-evaluation.md", "global equilibrium", "reaction consistency", "displacement direction", "symmetry", "element force balance", "model coverage", "pass-for-release-agent", "Do not approve release readiness.", ), }, "fesa-release-readiness": { "description_terms": ( "Use when", "FESA solver", "release readiness", "release notes", "known limitations", ), "body_terms": ( "docs/releases/-release.md", "GATE AUDIT -> TRACEABILITY CHECK -> RELEASE DOCUMENTATION -> RELEASE VERDICT", "ready-for-release", "Known Limitations", "Release Notes Draft", "pass-for-reference-verification", "pass-for-physics-evaluation", "pass-for-release-agent", "Do not publish, deploy, package, tag, commit, or externally release anything unless the user explicitly asks.", ), }, } def read_skill(skill_name): return (SKILLS_ROOT / skill_name / "SKILL.md").read_text(encoding="utf-8") 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 FesaSolverSkillTests(unittest.TestCase): def test_all_solver_skill_files_exist_with_required_frontmatter(self): for skill_name, spec 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") fields = parse_frontmatter(read_skill(skill_name)) self.assertEqual(set(fields), {"name", "description"}) self.assertEqual(fields["name"], skill_name) for term in spec["description_terms"]: self.assertIn(term, fields["description"]) def test_all_solver_skills_define_common_contract_sections(self): for skill_name in SKILLS: with self.subTest(skill=skill_name): body = read_skill(skill_name) for section in COMMON_SECTIONS: self.assertIn(section, body) self.assertIn("AGENTS.md", body) self.assertIn("docs/SOLVER_AGENT_DESIGN.md", body) self.assertNotIn("docs/SOLVER_SKILL_DESIGN.md", body) def test_solver_skills_define_skill_specific_contracts(self): for skill_name, spec in SKILLS.items(): with self.subTest(skill=skill_name): body = read_skill(skill_name) for term in spec["body_terms"]: self.assertIn(term, body) def test_solver_skills_have_openai_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) if __name__ == "__main__": unittest.main()