From 79a3c1c6666b2b609cc9fc82ca2a8c5a1d5817b2 Mon Sep 17 00:00:00 2001 From: "KOKO\\Mimi" Date: Sat, 15 Aug 2026 03:57:29 +0900 Subject: [PATCH] fix: preserve implementation step boundaries --- .codex/agents/implementation-agent.toml | 24 ++- .codex/skills/fesa-cpp-msvc-tdd/SKILL.md | 20 ++- .../numerical-review.md | 2 +- phases/linear-static-3d-euler-beam/step0.md | 2 +- phases/linear-static-3d-euler-beam/step1.md | 2 +- phases/linear-static-3d-euler-beam/step2.md | 2 +- phases/linear-static-3d-euler-beam/step25.md | 2 +- phases/linear-static-3d-euler-beam/step26.md | 2 +- phases/linear-static-3d-euler-beam/step27.md | 2 +- phases/linear-static-3d-euler-beam/step28.md | 2 +- phases/linear-static-3d-euler-beam/step3.md | 2 +- phases/linear-static-3d-euler-beam/step4.md | 2 +- phases/linear-static-3d-euler-beam/step5.md | 2 +- phases/linear-static-3d-euler-beam/step6.md | 6 +- tests/test_agent_skill_workflow_contract.py | 148 +++++++++++++++++- 15 files changed, 187 insertions(+), 33 deletions(-) diff --git a/.codex/agents/implementation-agent.toml b/.codex/agents/implementation-agent.toml index a8aadba..7bdc0b4 100644 --- a/.codex/agents/implementation-agent.toml +++ b/.codex/agents/implementation-agent.toml @@ -60,21 +60,29 @@ Execution contract: later pending Step. - Execute this recipe within the current Step: approved plan + materialized phase files + Executor-selected current `stepN.md` -> read prerequisites and previous summaries -> RED -> - OBSERVED FAILURE -> MINIMAL GREEN -> FOCUSED VERIFY -> FULL MSVC BUILD/CTEST -> ARTIFACT CHECK - -> COMPARE -> CLASSIFY -> REPORT -> update only current Step status plus + OBSERVED FAILURE -> MINIMAL GREEN -> the Step's declared FOCUSED/FULL VERIFY acceptance commands + -> update only current Step status plus `summary`/`error_message`/`blocked_reason` -> stop without starting the next Step. +- A non-final Step is complete when its declared acceptance commands pass. It must not fail merely + because final solver output, reference artifacts, or `reference-comparison.md` are not yet available. +- Only when the approved implementation plan places the Executor-selected current Step after all + prerequisite implementation Steps as the final Implementation-owned verification Step/gate, + continue with `ARTIFACT CHECK -> COMPARE -> CLASSIFY -> REPORT`, require generated `results.h5`, + and complete `docs//reference-comparison.md`. - Always work in RED -> GREEN -> VERIFY order. - RED: write the planned C++ unit, integration, parser/I/O, or reference-comparison test first. - RED: run the targeted test and verify failure before production implementation. - GREEN: implement the minimum code needed for the planned task and acceptance criterion. -- VERIFY: resolve commands from `.harness/config.json` first, then Harness project defaults; run the targeted CTest command, then the full MSVC x64 Debug build/test commands in the configured order. +- VERIFY: resolve commands from `.harness/config.json` first, then Harness project defaults; run the + targeted command and any focused/full MSVC x64 Debug build/test commands declared by the current + Step in the configured order. - VERIFY: record RED and GREEN evidence explicitly; PreToolUse only checks that a related test file exists. - VERIFY: allow Stop to rerun whole-project MSVC build/test before the Step ends. - BUILD/TEST REPORT: record command, exit code, duration, stdout/stderr tail, failed test names, environment, and project-selection path in `docs//build-test.md` with `owner_agent: implementation-agent`. - BUILD/TEST REPORT: stop after the first decisive failure unless the approved plan requires another diagnostic command. -- ARTIFACT CHECK -> COMPARE -> CLASSIFY -> REPORT: require the exact declared input/CSV paths, generated `results.h5`, HDF5 projection from `docs//io.md`, source identity/component matching, row uniqueness/finite checks, and approved tolerance. +- FINAL VERIFICATION GATE — ARTIFACT CHECK -> COMPARE -> CLASSIFY -> REPORT: require the exact declared input/CSV paths, generated `results.h5`, HDF5 projection from `docs//io.md`, source identity/component matching, row uniqueness/finite checks, and approved tolerance. - COMPARE: reject missing, extra, duplicate, or nonfinite required rows before tolerance; preserve warning-only behavior and never alter tolerance or artifacts to obtain a pass. -- REPORT: write `docs//implementation-report.md`, `docs//build-test.md`, and `docs//reference-comparison.md`. +- FINAL VERIFICATION GATE REPORT: complete `docs//implementation-report.md`, `docs//build-test.md`, and `docs//reference-comparison.md`. - `.codex/hooks.json` is authoritative: PreToolUse runs `scripts/hooks/pre_tool_use.py` and Stop runs `scripts/hooks/stop_validation.py` automatically. Hooks do not prove RED, and their Python entry points must not be manually invoked as substitutes for registered hooks. @@ -139,7 +147,11 @@ Reference comparison quality gate: - Do not calculate, invent, or treat a metric as required when the approved feature contract does not make it applicable. Return contract: -- Return `docs//implementation-report.md`, `docs//build-test.md`, and `docs//reference-comparison.md`, plus status, evidence summary, and blockers, to Coordinator Agent. +- For a non-final Step, return only that Step's owned status/summary and applicable evidence without + requiring final solver output or a completed reference comparison. +- From the final Implementation-owned verification Step/gate, return + `docs//implementation-report.md`, `docs//build-test.md`, and + `docs//reference-comparison.md`, plus status, evidence summary, and blockers, to Coordinator Agent. - Return `pass-for-physics-evaluation` only when the full build/test and all blocking comparisons pass. - Return repeated or unclear implementation failures as a Correction Agent request through Coordinator Agent. diff --git a/.codex/skills/fesa-cpp-msvc-tdd/SKILL.md b/.codex/skills/fesa-cpp-msvc-tdd/SKILL.md index 4fabef7..dcf8535 100644 --- a/.codex/skills/fesa-cpp-msvc-tdd/SKILL.md +++ b/.codex/skills/fesa-cpp-msvc-tdd/SKILL.md @@ -25,7 +25,8 @@ Read these first: - `docs//implementation-report.md` when present - `docs//build-test.md` when present - `docs//reference-comparison.md` when present -- Generated FESA `results.h5` and the exact feature-declared reference `.inp` and Abaqus CSV paths +- For the final Implementation-owned verification Step/gate, generated FESA `results.h5` and the + exact feature-declared reference `.inp` and Abaqus CSV paths For Harness implementation, also read `.agents/skills/harness/SKILL.md`, `.codex/hooks.json`, the materialized phase indexes, and the Executor-selected current @@ -47,16 +48,21 @@ For Harness implementation, also read `.agents/skills/harness/SKILL.md`, 5. RED: write the planned unit, integration, parser/I/O, or reference-comparison test first. 6. RED: run the targeted test and verify the expected failure before production code. 7. GREEN: implement the minimum C++17/MSVC-compatible code needed for the task. -8. VERIFY: resolve commands from `.harness/config.json` first, then Harness defaults; run the targeted command, then the full MSVC x64 Debug build/test commands in order. +8. VERIFY: resolve commands from `.harness/config.json` first, then Harness defaults; run the + targeted command and any focused/full MSVC x64 Debug build/test commands declared by the current + Step in order. 9. For C++ production changes, require a related C++ test file in the same patch or already present. 10. Treat PreToolUse as a test-file-existence guardrail, not proof that RED was observed. Record the RED and GREEN commands and results in the implementation report. 11. Let Stop perform the final whole-project MSVC build/test before the Step ends. 12. Record every build/test command, exit code, duration, stdout/stderr tail, failed test names, environment, and project-selection path. Stop after the first decisive failure unless the implementation plan requires another diagnostic command. 13. For failure triage, classify as `configure | compile | link | test | reference-comparison | harness | environment | upstream-contract`. -14. Run reference comparison in this literal order: `ARTIFACT CHECK -> COMPARE -> CLASSIFY -> REPORT`. -15. ARTIFACT CHECK requires exact declared input/CSV paths, generated `results.h5`, the `docs//io.md` HDF5 projection, source identity/component matching, row uniqueness/finite checks, and approved tolerance. -16. COMPARE matches HDF5 and CSV rows by declared source identity and component, never by row order. Reject missing, extra, duplicate, and nonfinite required rows before tolerance; preserve warning-only behavior. -17. Fix implementation-owned failures only and keep changes traceable to the implementation plan. +14. A non-final Step ends after its declared `RED -> observed failure -> minimal GREEN -> focused/full VERIFY` acceptance commands and owned status/summary update. Do not fail it merely because final solver output, reference artifacts, or `reference-comparison.md` are not yet available. +15. Only when the approved implementation plan places the current Step after all prerequisite + implementation Steps as the final Implementation-owned verification Step/gate, run reference + comparison in this literal order: `ARTIFACT CHECK -> COMPARE -> CLASSIFY -> REPORT`. +16. At that final gate, ARTIFACT CHECK requires exact declared input/CSV paths, generated `results.h5`, the `docs//io.md` HDF5 projection, source identity/component matching, row uniqueness/finite checks, and approved tolerance. +17. COMPARE matches HDF5 and CSV rows by declared source identity and component, never by row order. Reject missing, extra, duplicate, and nonfinite required rows before tolerance; preserve warning-only behavior. +18. Fix implementation-owned failures only and keep changes traceable to the implementation plan. ## Output Contract @@ -133,4 +139,4 @@ uv run --with pytest python -m pytest -v -rs ## Handoff -Return the applicable canonical outputs, status, evidence summary, and blockers to Coordinator Agent. Implementation Planning returns `docs//implementation-plan.md` for one Implementation Agent handoff. Implementation returns `docs//implementation-report.md`, `docs//build-test.md`, and `docs//reference-comparison.md`; send `pass-for-physics-evaluation` to Physics Evaluation Agent through Coordinator Agent. Correction returns `docs//corrections.md` and a rerun request to Implementation Agent through Coordinator Agent. Return upstream-contract failures to Coordinator Agent for the owning upstream sub-agent. +Return the applicable canonical outputs, status, evidence summary, and blockers to Coordinator Agent. Implementation Planning returns `docs//implementation-plan.md` for one Implementation Agent handoff. A non-final Implementation Step returns only its owned status/summary and applicable evidence. The final Implementation-owned verification Step/gate returns `docs//implementation-report.md`, `docs//build-test.md`, and `docs//reference-comparison.md`; send `pass-for-physics-evaluation` to Physics Evaluation Agent through Coordinator Agent. Correction returns `docs//corrections.md` and a rerun request to Implementation Agent through Coordinator Agent. Return upstream-contract failures to Coordinator Agent for the owning upstream sub-agent. diff --git a/docs/linear-static-mitc4-shell/numerical-review.md b/docs/linear-static-mitc4-shell/numerical-review.md index fca5607..73a7c1e 100644 --- a/docs/linear-static-mitc4-shell/numerical-review.md +++ b/docs/linear-static-mitc4-shell/numerical-review.md @@ -9,7 +9,7 @@ - source_io_definition: `docs/linear-static-mitc4-shell/io.md` - source_reference_inventory: `docs/linear-static-mitc4-shell/reference-model.md` - repository_policy: `AGENTS.md`, `docs/SOLVER_AGENT_DESIGN.md`, - `docs/numerical-reviews/README.md` + `.codex/skills/fesa-numerical-review/SKILL.md` - reviewed_head: `cf769aa` (`mathematical implementation baseline`) - prior_pass_commit: `60b42f4` (`context-only; verdict not inherited`) - status: `pass-for-implementation-planning` diff --git a/phases/linear-static-3d-euler-beam/step0.md b/phases/linear-static-3d-euler-beam/step0.md index c234c74..2122ad3 100644 --- a/phases/linear-static-3d-euler-beam/step0.md +++ b/phases/linear-static-3d-euler-beam/step0.md @@ -15,7 +15,7 @@ - `/docs/ARCHITECTURE.md` - `/docs/ADR.md` - `/docs/SOLVER_AGENT_DESIGN.md` -- `/docs/requirements/README.md` +- `/.codex/skills/fesa-requirements-baseline/SKILL.md` - `/docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md` - `/docs/linear-static-3d-euler-beam/formulation.md` - `/reference/cantilever beam/cantilever beam.inp` diff --git a/phases/linear-static-3d-euler-beam/step1.md b/phases/linear-static-3d-euler-beam/step1.md index f0a6e6d..3619395 100644 --- a/phases/linear-static-3d-euler-beam/step1.md +++ b/phases/linear-static-3d-euler-beam/step1.md @@ -10,7 +10,7 @@ - `/AGENTS.md` - `/docs/SOLVER_AGENT_DESIGN.md` -- `/docs/research/README.md` +- `/.codex/skills/fesa-research-evidence/SKILL.md` - `/docs/linear-static-3d-euler-beam/requirements.md` - `/docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md` - `/docs/linear-static-3d-euler-beam/formulation.md` diff --git a/phases/linear-static-3d-euler-beam/step2.md b/phases/linear-static-3d-euler-beam/step2.md index fc622a6..dc54fc6 100644 --- a/phases/linear-static-3d-euler-beam/step2.md +++ b/phases/linear-static-3d-euler-beam/step2.md @@ -10,7 +10,7 @@ - `/AGENTS.md` - `/docs/SOLVER_AGENT_DESIGN.md` -- `/docs/formulations/README.md` +- `/.codex/skills/fesa-formulation-spec/SKILL.md` - `/docs/linear-static-3d-euler-beam/requirements.md` - `/docs/linear-static-3d-euler-beam/research.md` - `/docs/linear-static-3d-euler-beam/formulation.md` diff --git a/phases/linear-static-3d-euler-beam/step25.md b/phases/linear-static-3d-euler-beam/step25.md index 4d1d611..1292089 100644 --- a/phases/linear-static-3d-euler-beam/step25.md +++ b/phases/linear-static-3d-euler-beam/step25.md @@ -11,7 +11,7 @@ - `/AGENTS.md` - `/docs/ARCHITECTURE.md` - `/docs/ADR.md` -- `/docs/build-test-reports/README.md` +- `/.codex/skills/fesa-cpp-msvc-tdd/SKILL.md` - `/docs/linear-static-3d-euler-beam/requirements.md` - `/docs/linear-static-3d-euler-beam/implementation-plan.md` - `/docs/linear-static-3d-euler-beam/implementation-report.md` diff --git a/phases/linear-static-3d-euler-beam/step26.md b/phases/linear-static-3d-euler-beam/step26.md index a64499c..538b62a 100644 --- a/phases/linear-static-3d-euler-beam/step26.md +++ b/phases/linear-static-3d-euler-beam/step26.md @@ -11,7 +11,7 @@ - `/AGENTS.md` - `/docs/ARCHITECTURE.md` - `/docs/ADR.md` -- `/docs/reference-verifications/README.md` +- `/.codex/skills/fesa-cpp-msvc-tdd/SKILL.md` - `/docs/linear-static-3d-euler-beam/build-test.md` - `/docs/linear-static-3d-euler-beam/reference-model.md` - `/docs/linear-static-3d-euler-beam/io.md` diff --git a/phases/linear-static-3d-euler-beam/step27.md b/phases/linear-static-3d-euler-beam/step27.md index df3cd3d..ad9c1eb 100644 --- a/phases/linear-static-3d-euler-beam/step27.md +++ b/phases/linear-static-3d-euler-beam/step27.md @@ -11,7 +11,7 @@ - `/AGENTS.md` - `/docs/ARCHITECTURE.md` - `/docs/ADR.md` -- `/docs/physics-evaluations/README.md` +- `/.codex/skills/fesa-physics-sanity/SKILL.md` - `/docs/linear-static-3d-euler-beam/reference-comparison.md` - `/docs/linear-static-3d-euler-beam/reference-model.md` - `/docs/linear-static-3d-euler-beam/requirements.md` diff --git a/phases/linear-static-3d-euler-beam/step28.md b/phases/linear-static-3d-euler-beam/step28.md index 744622d..e35654e 100644 --- a/phases/linear-static-3d-euler-beam/step28.md +++ b/phases/linear-static-3d-euler-beam/step28.md @@ -12,7 +12,7 @@ - `/docs/PRD.md` - `/docs/ARCHITECTURE.md` - `/docs/ADR.md` -- `/docs/releases/README.md` +- `/.codex/skills/fesa-release-readiness/SKILL.md` - `/docs/linear-static-3d-euler-beam/requirements.md` - `/docs/linear-static-3d-euler-beam/research.md` - `/docs/linear-static-3d-euler-beam/formulation.md` diff --git a/phases/linear-static-3d-euler-beam/step3.md b/phases/linear-static-3d-euler-beam/step3.md index ef62b97..2489460 100644 --- a/phases/linear-static-3d-euler-beam/step3.md +++ b/phases/linear-static-3d-euler-beam/step3.md @@ -10,7 +10,7 @@ - `/AGENTS.md` - `/docs/SOLVER_AGENT_DESIGN.md` -- `/docs/numerical-reviews/README.md` +- `/.codex/skills/fesa-numerical-review/SKILL.md` - `/docs/linear-static-3d-euler-beam/requirements.md` - `/docs/linear-static-3d-euler-beam/research.md` - `/docs/linear-static-3d-euler-beam/formulation.md` diff --git a/phases/linear-static-3d-euler-beam/step4.md b/phases/linear-static-3d-euler-beam/step4.md index 0d11d3e..fd6efe7 100644 --- a/phases/linear-static-3d-euler-beam/step4.md +++ b/phases/linear-static-3d-euler-beam/step4.md @@ -10,7 +10,7 @@ - `/AGENTS.md` - `/docs/SOLVER_AGENT_DESIGN.md` -- `/docs/io-definitions/README.md` +- `/.codex/skills/fesa-io-contract/SKILL.md` - `/docs/linear-static-3d-euler-beam/requirements.md` - `/docs/linear-static-3d-euler-beam/formulation.md` - `/docs/linear-static-3d-euler-beam/numerical-review.md` diff --git a/phases/linear-static-3d-euler-beam/step5.md b/phases/linear-static-3d-euler-beam/step5.md index a69842f..70b6bca 100644 --- a/phases/linear-static-3d-euler-beam/step5.md +++ b/phases/linear-static-3d-euler-beam/step5.md @@ -10,7 +10,7 @@ - `/AGENTS.md` - `/docs/SOLVER_AGENT_DESIGN.md` -- `/docs/reference-models/README.md` +- `/.codex/skills/fesa-numerical-review/SKILL.md` - `/docs/linear-static-3d-euler-beam/requirements.md` - `/docs/linear-static-3d-euler-beam/research.md` - `/docs/linear-static-3d-euler-beam/formulation.md` diff --git a/phases/linear-static-3d-euler-beam/step6.md b/phases/linear-static-3d-euler-beam/step6.md index 8b2c220..806ef16 100644 --- a/phases/linear-static-3d-euler-beam/step6.md +++ b/phases/linear-static-3d-euler-beam/step6.md @@ -10,9 +10,9 @@ - `/AGENTS.md` - `/docs/SOLVER_AGENT_DESIGN.md` -- `/docs/implementation-plans/README.md` -- `/docs/build-test-reports/README.md` -- `/docs/corrections/README.md` +- `/.codex/skills/fesa-cpp-msvc-tdd/SKILL.md` +- `/.codex/agents/implementation-planning-agent.toml` +- `/.codex/agents/correction-agent.toml` - `/docs/linear-static-3d-euler-beam/requirements.md` - `/docs/linear-static-3d-euler-beam/research.md` - `/docs/linear-static-3d-euler-beam/formulation.md` diff --git a/tests/test_agent_skill_workflow_contract.py b/tests/test_agent_skill_workflow_contract.py index 16f0630..2ace34b 100644 --- a/tests/test_agent_skill_workflow_contract.py +++ b/tests/test_agent_skill_workflow_contract.py @@ -1,4 +1,6 @@ +import json from pathlib import Path +import re import tomllib @@ -86,6 +88,55 @@ LIVE_CONTRACT_FILES = ( ROOT / "docs" / "SOLVER_SKILL_DESIGN.md", ) +AGENT_STAGE_GUIDANCE_FILES = ( + ROOT / "AGENTS.md", + ROOT / "docs" / "SOLVER_AGENT_DESIGN.md", +) + +EXPECTED_AGENT_STAGE_MAPPING = ( + ("1. 요구조건", "requirement-agent", "requirements.md"), + ("2. 연구", "research-agent", "research.md"), + ("3. 정식화", "formulation-agent", "formulation.md"), + ( + "4. 수치 검토 + reference model 계약", + "numerical-review-agent", + "numerical-review.md, reference-model.md", + ), + ("5. I/O 정의", "io-definition-agent", "io.md"), + ( + "6. 구현 계획 + C++ 구현 + build/test + reference comparison", + "implementation-planning-agent, implementation-agent", + "implementation-plan.md, implementation-report.md, build-test.md, reference-comparison.md", + ), + ("7. 물리 검토", "physics-evaluation-agent", "physics-evaluation.md"), + ("8. 배포 준비", "release-agent", "release.md"), +) + +CANONICAL_FEATURE_DIRS = ( + ROOT / "docs" / "linear-static-3d-euler-beam", + ROOT / "docs" / "linear-static-mitc4-shell", +) + +# Plans and specs intentionally retain deleted source paths as migration history. +HISTORICAL_PATH_EXEMPT_DIRS = ( + ROOT / "docs" / "superpowers" / "plans", + ROOT / "docs" / "superpowers" / "specs", +) + +LEGACY_README_PATTERN = re.compile( + r"docs/(?:coordination|requirements|research|formulations|numerical-reviews|" + r"io-definitions|reference-models|implementation-plans|build-test-reports|" + r"corrections|reference-verifications|physics-evaluations|releases)/README\.md", + re.IGNORECASE, +) + +EXPECTED_SKILL_FRONTMATTER_KEYS = ("name", "description") +EXPECTED_SKILL_INTERFACE_KEYS = ( + "display_name", + "short_description", + "default_prompt", +) + RETIRED_TOKENS = ( "reference-model-agent", "reference model agent", @@ -122,6 +173,65 @@ def live_contract_text() -> str: return "\n".join(read(path) for path in paths) +def markdown_stage_mapping(path: Path) -> tuple[tuple[str, str, str], ...]: + rows = [] + for line in read(path).splitlines(): + columns = [column.strip().replace("`", "") for column in line.strip().split("|")[1:-1]] + if len(columns) >= 4 and re.fullmatch(r"[1-8]\. .+", columns[0]): + rows.append((columns[0], columns[1], columns[3])) + return tuple(rows) + + +def operational_markdown_paths() -> tuple[Path, ...]: + paths = [ + path + for feature_dir in CANONICAL_FEATURE_DIRS + for path in sorted(feature_dir.glob("*.md")) + ] + paths.extend(sorted(ROOT.glob("phases/**/step*.md"))) + return tuple(paths) + + +def parse_skill_frontmatter(path: Path) -> dict[str, str]: + lines = read(path).splitlines() + assert lines and lines[0] == "---", path + assert "---" in lines[1:], path + closing_index = lines.index("---", 1) + field_lines = lines[1:closing_index] + assert len(field_lines) == len(EXPECTED_SKILL_FRONTMATTER_KEYS), path + + parsed = {} + for line in field_lines: + match = re.fullmatch(r"([a-z_]+): ([^\s].*)", line) + assert match is not None, (path, line) + key, value = match.groups() + assert key not in parsed, (path, key) + parsed[key] = value + + assert tuple(parsed) == EXPECTED_SKILL_FRONTMATTER_KEYS, path + assert re.fullmatch(r"[a-z0-9]+(?:-[a-z0-9]+)*", parsed["name"]), path + assert parsed["description"].startswith("Use when "), path + return parsed + + +def parse_skill_interface(path: Path) -> dict[str, str]: + lines = [line for line in read(path).splitlines() if line] + assert lines and lines[0] == "interface:", path + assert len(lines) == len(EXPECTED_SKILL_INTERFACE_KEYS) + 1, path + + parsed = {} + for line in lines[1:]: + match = re.fullmatch(r' ([a-z_]+): ("(?:[^"\\]|\\.)*")', line) + assert match is not None, (path, line) + key, quoted_value = match.groups() + assert key not in parsed, (path, key) + parsed[key] = json.loads(quoted_value) + + assert tuple(parsed) == EXPECTED_SKILL_INTERFACE_KEYS, path + assert all(parsed.values()), path + return parsed + + def test_agent_inventory_is_consolidated(): actual = {path.stem for path in AGENT_DIR.glob("*.toml")} assert actual == EXPECTED_AGENTS @@ -178,6 +288,20 @@ def test_implementation_absorbs_build_test_and_reference_comparison(): assert marker in text +def test_implementation_steps_keep_final_comparison_in_a_final_gate(): + paths = ( + AGENT_DIR / "implementation-agent.toml", + SKILL_DIR / "fesa-cpp-msvc-tdd" / "SKILL.md", + ) + for path in paths: + text = read(path).lower() + assert "final implementation-owned verification step/gate" in text, path + assert "non-final step" in text, path + assert "artifact check -> compare -> classify -> report" in text, path + assert "results.h5" in text, path + assert "reference-comparison.md" in text, path + + def test_agent_hierarchy_is_explicit(): coordinator = read(AGENT_DIR / "coordinator-agent.toml").lower() assert "main agent" in coordinator @@ -200,12 +324,24 @@ def test_live_contracts_have_no_retired_names_or_paths(): assert token not in text, token -def test_live_guidance_declares_eight_stage_workflow(): +def test_live_guidance_declares_exact_ordered_eight_stage_workflow(): for path in LIVE_CONTRACT_FILES: text = read(path) assert "8단계" in text, path assert "docs//" in text, path + for path in AGENT_STAGE_GUIDANCE_FILES: + assert markdown_stage_mapping(path) == EXPECTED_AGENT_STAGE_MAPPING, path + + +def test_operational_documents_do_not_use_deleted_stage_readmes(): + paths = operational_markdown_paths() + assert paths + for path in paths: + assert not any(path.is_relative_to(directory) for directory in HISTORICAL_PATH_EXEMPT_DIRS) + match = LEGACY_README_PATTERN.search(read(path)) + assert match is None, (path, match.group(0) if match else None) + def test_mitc4_live_authority_links_use_feature_bundle(): text = read(ROOT / "docs" / "MITC4_SUPP.md") @@ -232,7 +368,7 @@ def test_mitc4_live_authority_links_use_feature_bundle(): assert legacy_path not in authority_section -def test_agent_toml_and_skill_ui_metadata_are_parseable(): +def test_agent_toml_and_limited_skill_yaml_schemas_are_parseable(): for path in sorted(AGENT_DIR.glob("*.toml")): parsed = tomllib.loads(read(path)) assert parsed["name"] == path.stem @@ -240,7 +376,7 @@ def test_agent_toml_and_skill_ui_metadata_are_parseable(): 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 + frontmatter = parse_skill_frontmatter(skill_dir / "SKILL.md") + interface = parse_skill_interface(skill_dir / "agents" / "openai.yaml") + assert frontmatter["name"] == skill_name + assert f"${skill_name}" in interface["default_prompt"]