fix: preserve implementation step boundaries

This commit is contained in:
KOKO\Mimi
2026-08-15 03:57:29 +09:00
parent 869b6ce241
commit 79a3c1c666
15 changed files with 187 additions and 33 deletions
+18 -6
View File
@@ -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/<feature-id>/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/<feature-id>/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/<feature-id>/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/<feature-id>/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/<feature-id>/implementation-report.md`, `docs/<feature-id>/build-test.md`, and `docs/<feature-id>/reference-comparison.md`.
- FINAL VERIFICATION GATE REPORT: complete `docs/<feature-id>/implementation-report.md`, `docs/<feature-id>/build-test.md`, and `docs/<feature-id>/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/<feature-id>/implementation-report.md`, `docs/<feature-id>/build-test.md`, and `docs/<feature-id>/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/<feature-id>/implementation-report.md`, `docs/<feature-id>/build-test.md`, and
`docs/<feature-id>/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.
+13 -7
View File
@@ -25,7 +25,8 @@ Read these first:
- `docs/<feature-id>/implementation-report.md` when present
- `docs/<feature-id>/build-test.md` when present
- `docs/<feature-id>/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/<feature-id>/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/<feature-id>/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/<feature-id>/implementation-plan.md` for one Implementation Agent handoff. Implementation returns `docs/<feature-id>/implementation-report.md`, `docs/<feature-id>/build-test.md`, and `docs/<feature-id>/reference-comparison.md`; send `pass-for-physics-evaluation` to Physics Evaluation Agent through Coordinator Agent. Correction returns `docs/<feature-id>/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/<feature-id>/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/<feature-id>/implementation-report.md`, `docs/<feature-id>/build-test.md`, and `docs/<feature-id>/reference-comparison.md`; send `pass-for-physics-evaluation` to Physics Evaluation Agent through Coordinator Agent. Correction returns `docs/<feature-id>/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.
@@ -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`
+1 -1
View File
@@ -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`
+1 -1
View File
@@ -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`
+1 -1
View File
@@ -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`
+1 -1
View File
@@ -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`
+1 -1
View File
@@ -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`
+1 -1
View File
@@ -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`
+1 -1
View File
@@ -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`
+1 -1
View File
@@ -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`
+1 -1
View File
@@ -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`
+1 -1
View File
@@ -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`
+3 -3
View File
@@ -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`
+142 -6
View File
@@ -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/<feature-id>/" 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"]