Files
FESADev/docs/HARNESS_WORKFLOW.md
T
2026-09-06 00:52:59 +09:00

30 KiB

Harness Framework 동작 과정

이 문서는 자연어 요구사항을 받은 뒤 Harness Framework가 계획을 만들고, 독립된 Codex 세션에서 Step을 실행하고, MSVC로 C++ 프로젝트를 검증하는 전체 과정을 설명한다. 설치 및 설정 예시는 Harness 운영 가이드를 참고한다.

Feature의 9개 정규 stage와 Coordinator의 gate 전이는 Agent 계약, 역할별 절차는 Harness skill, 문서 소유권은 Feature 문서 관리를 따른다. Harness는 그중 할당된 구현 계획·Step 실행을 지원하며, solver workflow 전체를 대신하지 않는다.

1. 핵심 구조

Harness Framework는 다음 세 계층으로 구성된다.

  1. 계획 계층: 승인된 요구사항과 Coordinator dispatch를 실행 가능한 Step으로 변환한다.
  2. 실행 계층: Step Executor가 Step마다 독립 Codex 세션을 실행하고 상태와 Git 커밋을 관리한다.
  3. 검증 계층: PreToolUse 훅이 편집 전 정책을 검사하고, Stop 훅이 종료 전 MSVC 빌드와 테스트를 실행한다. 유효한 문서 전용 편집 기록이면 조건부로 생략한다.

전체 흐름은 다음과 같다.

사용자 요구사항
    ↓
Feature의 선행 계약·gate 확인
    ↓
Coordinator의 bounded Planning dispatch
    ↓
Planning Agent의 자기완결적 Step 작성
    ↓
phases/index.json, task index, stepN.md 생성
    ↓
실행까지 할당된 경우 Step Executor 시작
    ↓
각 Step을 독립 Codex 세션에서 실행
    ├─ 도구 호출 전: PreToolUse 정책 검사
    └─ 응답 종료 전: Stop 검증 또는 문서 전용 조건부 생략
    ↓
성공: 커밋 후 다음 Step
transport 실패: 최초 포함 최대 2회 시도
구현 실패·차단: Coordinator로 반환

자연어 요구사항이나 계획 요청만으로 Executor가 자동 시작되지는 않는다. 승인된 Feature와 dispatch 안의 일반 계획 파일 작성·할당된 실행에 반복 승인 gate를 추가하지 않는다. 권한 상승, 원격·파괴 작업, licensed reference solver 실행은 별도 명시적 승인이 필요하다.

2. 요구사항 탐색과 구체화

예를 들어 사용자가 다음 요구사항을 전달했다고 가정한다.

아래 Calculator 예시는 Harness Step 구조를 설명하기 위한 것으로 FESA 제품 요구사항이나 새 기능 구현 지시가 아니다.

CMake 기반 C++20 라이브러리에 divide() 함수를 추가하고, 0으로 나누면 예외를 발생시키며 GoogleTest 테스트를 작성한다.

계획을 작성하기 전에 다음 자료를 확인한다.

  • AGENTS.md
  • docs/PRD.md
  • docs/ARCHITECTURE.md
  • docs/ADR.md
  • Coordinator dispatch와 docs/<feature-id>/의 승인된 선행 계약
  • 해당 Feature의 FEATURED_AGENTS.md, PRD.md, ADR.md
  • 관련 제품 코드와 테스트
  • .harness/config.json이 있으면 그 설정, 없으면 preset·metadata·프로젝트 지침과 감지 기본값

이 탐색을 통해 다음 조건을 구체화한다.

  • 사용하는 MSVC toolset과 C++ 표준
  • CMake 프로젝트인지 Visual Studio solution/project인지
  • 테스트 프레임워크와 테스트 실행 방법
  • public header와 implementation의 의존성 방향
  • 수정할 모듈과 범위 밖 항목
  • 실행 가능한 Acceptance Criteria 명령

필수 계약이 없으면 Coordinator를 통해 해당 owner로 반환한다. 예외 타입, 수치 타입, public API·ABI처럼 승인된 의미를 바꾸는 선택은 critical decision 기준에 따라 사용자에게 올린다. 이미 승인된 계약 안의 파일 배치나 테스트 분해는 담당자가 결정한다.

3. 요구사항을 Step으로 분해

사용자가 구현 계획 작성을 요청하면 요구사항을 작은 Step으로 나눈다. Step 설계 규칙은 Harness Workflow에 정의되어 있다.

각 Step은 다음 조건을 만족해야 한다.

  • 하나의 모듈 또는 명확한 한 가지 책임만 다룬다.
  • 다른 대화 내용을 참조하지 않아도 실행할 수 있도록 자기완결적으로 작성한다.
  • 먼저 읽을 문서와 이전 Step의 관련 파일을 명시한다.
  • Feature 관리 문서와 승인된 선행 계약의 정확한 경로·revision을 명시한다.
  • 클래스와 함수 시그니처 수준으로 작업 범위를 설명한다.
  • 수정할 소스·테스트·보고서 파일과 수정하지 않을 upstream 파일을 명시한다.
  • 실제 실행 가능한 빌드·테스트 명령을 Acceptance Criteria로 사용한다.
  • 성공, 오류, 사용자 개입 필요 상태의 판정 기준을 적는다.
  • 범위 밖 기능과 기존 테스트 회귀를 명시적으로 금지한다.

예시 Step은 다음과 같은 내용을 포함할 수 있다.

Step 0: division-api

읽어야 할 파일
- AGENTS.md
- include/calculator.hpp
- src/calculator.cpp
- tests/calculator_test.cpp

작업
- divide(double lhs, double rhs)의 실패 테스트를 먼저 추가한다.
- rhs가 0이면 std::invalid_argument가 발생하도록 최소 구현한다.

Acceptance Criteria
- CMake/MSBuild 빌드가 성공한다.
- 전체 테스트가 성공한다.
- 새로운 컴파일러 경고가 없다.

TDD와 Step 경계

프로젝트 규칙은 실패하는 테스트를 먼저 요구하지만 Stop 훅은 Codex가 Step을 종료할 때 전체 테스트 성공을 요구한다. 따라서 다음처럼 실패 상태를 Step 사이에 남겨둘 수 없다.

Step 0: 실패하는 테스트만 추가하고 종료
Step 1: 제품 코드를 구현해 테스트 통과

실제 red-green 순서는 하나의 Codex 실행 안에서 완료되어야 한다.

테스트 작성
→ 테스트 실패 확인
→ 최소 제품 코드 구현
→ 테스트 성공 확인
→ Step 종료

즉, 테스트가 구현보다 먼저 작성되는 순서는 지키되 각 Step은 최종적으로 green 상태여야 한다.

4. 할당된 계획 산출물

Planning Agent는 Coordinator가 할당한 다음 파일을 생성한다. 기존 산출물을 재개할 때는 덮어쓰지 않고 승인된 변경 범위만 갱신한다. Step 번호는 0부터 연속으로 둔다.

phases/
├── index.json
└── add-division/
    ├── index.json
    ├── step0.md
    ├── step1.md
    └── ...

4.1 Top-level index

phases/index.json은 여러 task의 상태를 관리한다.

{
  "phases": [
    {
      "dir": "add-division",
      "status": "pending"
    }
  ]
}

4.2 Task index

phases/add-division/index.json은 task 내부 Step의 상태를 관리한다.

{
  "project": "Calculator",
  "phase": "add-division",
  "steps": [
    {
      "step": 0,
      "name": "division-api",
      "status": "pending",
      "owned_paths": ["include/calculator.hpp", "src/calculator.cpp", "tests/calculator_test.cpp"]
    }
  ]
}

상태별 기록은 다음과 같이 나뉜다.

owned_paths는 Planning이 작성하는 정확한 저장소 상대 파일 목록이다. Step 본문의 소유 파일과 일치해야 하며 source/header/test/build/report를 필요한 만큼 명시한다. 디렉터리, glob, 절대 경로, 경로 이탈, Git 내부와 phases/ 제어 경로는 허용하지 않는다. 연결된 파일·디렉터리 경로도 지원하지 않는다. []는 구현 파일 변경 없음이며 누락과 다르다. 기존 완료 Step은 필드 없이 읽을 수 있지만 모든 pending Step은 실행 전에 목록이 필요하다. 기존 phase를 일괄 변환하거나 Markdown에서 파일 권한을 자동 추출하지 않는다.

상태 Codex가 기록 Executor가 기록
completed summary completed_at
error error_message failed_at
blocked blocked_reason blocked_at

Executor는 task의 created_at과 Step의 started_at, attempt_history도 기록한다. History에는 단조 증가하는 attempt, recorded_at, exit_code(프로세스 미기동은 null), reported_status, reported_reason, 로컬 classification·판정 reason과 diagnostic을 보존한다. 진단은 stderr 우선, 없으면 stdout의 마지막 4,000자이며 raw output 전체의 대체가 아니다. Implementation은 owned_paths·history·timestamp를 수정할 수 없다. summary는 다음 독립 Codex 세션이 이전 Step의 핵심 산출물과 결정을 이해할 수 있도록 한 줄로 작성한다.

4.3 Step 파일

각 stepN.md에는 다음 내용이 들어간다.

  • 읽어야 할 파일
  • 작업 범위와 인터페이스
  • 핵심 동작 및 불변 조건
  • Acceptance Criteria 명령
  • 아키텍처·ADR·CRITICAL 규칙 확인 절차
  • 성공, 오류, 차단 상태 기록 방법
  • 범위 밖 변경 금지사항

Step은 독립 Codex 실행의 전체 작업 지시서이므로 이전 대화만 참조하는 표현을 넣지 않는다.

5. Step Executor 시작

계획 파일이 준비되고 실행까지 할당된 경우 다음 명령으로 실행한다.

python scripts/execute.py add-division

완료된 브랜치의 원격 push를 사용자가 명시적으로 승인한 경우에만 --push를 추가한다.

python scripts/execute.py add-division --push

Step Executor는 시작할 때 다음 작업을 수행한다.

  1. phase 경로와 top-level/phase index schema, Step 번호·이름·상태를 검사한다.
  2. 현재 첫 미완료 Step이 error 또는 blocked이면 복구 결정 전까지 중단한다.
  3. 모든 pending Step의 owned_paths, Implementation Agent profile, Git top-level, sandbox 승인 조건과 clean 상태를 검사한다. 기본 모드는 선택된 phase 제어 파일 allowlist 밖의 변경을 허용하지 않는다.
  4. feat-{phase-name} 브랜치를 생성하거나 checkout한다.
  5. AGENTS.md와 docs/*.md를 guardrail로 읽는다.
  6. task/Step timestamp와 재개 상태를 정리하고 첫 번째 pending Step부터 순차 실행한다.

AGENTS.md와 모든 docs/*.md 내용은 각 Codex 프롬프트에 직접 삽입된다. 따라서 이 문서들도 실행 입력에 포함된다. 역할·승인·상태 전이에서는 Agent 계약과 Harness skill의 권한 경계를 따르며, 설치 예시를 Feature의 요구사항으로 사용하지 않는다. Feature 관리 문서는 자동으로 로드되지 않으므로 dispatch와 Step의 필수 입력 경로에 명시해야 한다.

6. Step마다 독립 Codex 세션 실행

Executor는 각 Step을 다음 형태의 독립 프로세스로 실행한다.

codex exec
  --disable unified_exec
  --json
  --model <implementation-agent profile model>
  --config model_reasoning_effort="<profile effort>"
  --sandbox <workspace-write|danger-full-access>
  --dangerously-bypass-hook-trust
  --cd <repository-root>
  -

기본값은 workspace-write다. FEM_HARNESS_CODEX_SANDBOX 환경 변수는 workspace-write 또는 danger-full-access만 허용한다. Windows native sandbox에서 MSVC compiler-id의 cl.exe 정지가 재현되고 동일 명령이 sandbox 밖에서 통과하는 환경에서는, 해당 실행 직전 사용자 승인을 받은 clean linked Git worktree 실행에 한해서 danger-full-access fallback을 사용할 수 있다. Executor의 --approve-danger-full-access flag도 필요하며 환경변수만으로 승인되지 않는다. 이 override는 등록된 hook을 비활성화하지 않는다.

Codex에 전달하는 프롬프트는 다음 내용의 조합이다.

Implementation Agent profile의 역할·수정 경계
+ AGENTS.md와 docs 문서
+ 이전에 완료된 Step의 summary
+ 이전 시도의 오류(재시도인 경우)
+ Executor 공통 작업 규칙
+ 현재 stepN.md

이전 Step의 전체 대화나 Codex 세션은 전달하지 않는다. task index에 기록한 summary만 다음 Step에 누적한다.

Codex 실행 결과의 exit code, stdout, stderr는 다음 파일에 저장한다.

phases/{task-name}/step{N}-output.json

7. 도구 호출 전 PreToolUse 검사

.codex/hooks.json은 shell 및 파일 편집 도구에 PreToolUse 훅을 등록한다. Codex가 실제 명령이나 편집을 수행하기 전에 이 훅이 요청을 검사한다.

7.1 위험 명령 차단

다음 유형의 명령은 요구사항과 관계없이 차단한다.

  • git reset --hard
  • git push --force 또는 --force-with-lease
  • rm -rf
  • Remove-Item -Recurse -Force
  • rmdir /s /q
  • DROP TABLE

위험 패턴이 발견되면 훅은 차단 이유를 stderr로 출력하고 종료 코드 2를 반환한다. 그러면 해당 도구 호출은 실행되지 않는다.

7.2 C++ TDD 검사

apply_patch, Edit, MultiEdit, Write로 다음 C/C++ 확장자의 파일을 편집하려 하면 TDD 정책을 검사한다.

.c .cc .cpp .cxx .h .hpp .hxx

일반 제품 코드를 수정하려면 대응되는 테스트 파일이 먼저 존재해야 한다. 예를 들어 src/calculator.cpp의 기본 대응 테스트 이름은 다음과 같다.

calculator_test.cpp
calculator_tests.cpp
test_calculator.cpp
calculator.test.cpp

테스트는 다음 위치에서 검색한다.

  • .harness/config.json의 tdd.testRoots
  • 제품 파일과 같은 디렉터리 아래 tests/
  • 제품 파일과 같은 디렉터리 아래 test/

다음 파일과 디렉터리는 대응 테스트 존재 검사가 면제된다.

  • 테스트 파일 자체
  • main.cpp
  • .harness/build/**, build/**, out/**
  • cmake-build-*/**
  • third_party/**, external/**, vendor/**
  • generated/**
  • tdd.exclude에 추가한 경로

tdd.exclude는 기본 제외 항목을 대체하지 않고 추가한다.

7.3 TDD 검사가 보장하는 범위

현재 TDD 훅이 직접 보장하는 것은 대응되는 이름의 테스트 파일이 존재한다는 사실이다. 다음 항목까지 증명하지는 않는다.

  • 테스트가 이번 요구사항을 실제로 검증하는가
  • 구현 전에 테스트가 실제로 실패했는가
  • 테스트의 assertion과 경계 조건이 충분한가
  • 기존 테스트 파일을 이번 변경과 함께 수정했는가

또한 shell 명령의 리다이렉션 등으로 C++ 파일을 쓰는 경우 shell 위험 패턴 검사는 적용되지만 경로 기반 TDD 검사는 적용되지 않는다. 따라서 이 훅은 완전한 TDD 증명기가 아니라 테스트 우선 편집을 유도하는 guardrail이다.

PreToolUse는 허용된 편집 도구의 대상 경로를 .harness/hook-state/에 기록한다. 이 ignored 기록은 Stop의 문서 전용 판정 입력일 뿐 RED나 실제 편집 성공의 증거가 아니다.

8. Codex 종료 전 Stop 검증

Codex가 Step 작업을 끝내고 응답을 종료하려 하면 Stop 훅이 실행된다. 유효한 동일 session/turn 기록에서 편집 대상이 모두 저장소 내부 .md이면 build/test를 생략한다. 기록 누락·손상 또는 비문서 편집이면 정상 검증 경로에서 발견된 C/C++ 프로젝트 전체를 빌드하고 테스트한다.

Shell 쓰기는 완전히 추적되지 않으며, 편집 기록 없는 읽기 전용 요청도 자동 생략을 보장하지 않는다. 사용자가 문서 작업의 실행을 제외하면 수동 Hook·build/test를 실행하지 않고 정적 검토 범위와 미실행 항목을 보고한다. Hook state를 조작해 생략을 만들지 않는다.

8.1 저장소 루트와 재진입 방지

Stop 훅은 git rev-parse --show-toplevel로 프로젝트 루트를 결정한다. Git 저장소를 찾을 수 없으면 현재 디렉터리를 사용한다.

빌드나 테스트의 자식 프로세스에는 CODEX_STOP_VALIDATION_ACTIVE=1을 전달한다. 같은 훅이 자식 프로세스에서 다시 진입하면 즉시 성공 처리하여 검증 재귀를 막는다.

8.2 설정 로드

설정 로더는 .harness/config.json을 읽는다. 파일이 없으면 다음 기본값을 사용한다.

  • version: 1
  • projectType: auto
  • CMake source: 저장소 루트
  • preset 미사용 시 binary directory: .harness/build
  • configuration: Debug
  • platform: x64
  • 테스트 루트: tests, test
  • 기본 테스트 이름 패턴 네 개

설정은 다음 조건을 엄격하게 검사한다.

  • 알 수 없는 필드를 거부한다.
  • version은 숫자 1만 허용한다.
  • projectType은 auto, cmake, msbuild만 허용한다.
  • 저장소 상대 경로만 허용한다.
  • 저장소 밖으로 해석되는 경로를 거부한다.
  • CMake preset을 사용하면 configurePreset, buildPreset, testPreset, binaryDir를 모두 요구한다.
  • 모든 tdd.testPatterns에 {stem}을 요구한다.

8.3 프로젝트 자동 감지

프로젝트 탐색기는 다음 순서로 프로젝트를 선택한다.

  1. projectType: cmake 또는 projectType: msbuild 명시 설정
  2. 루트의 CMakePresets.json
  3. 루트의 CMakeUserPresets.json
  4. 루트의 CMakeLists.txt
  5. 루트의 단일 .sln
  6. 루트의 단일 .vcxproj

자동 감지 결과는 다음처럼 처리한다.

저장소 상태 결과
CMake metadata가 있음 CMake 프로젝트 선택
하나의 .sln 또는 .vcxproj가 있음 MSBuild 프로젝트 선택
여러 solution/project가 있음 설정으로 하나를 지정하라는 오류
C/C++ 파일과 build metadata가 모두 없음 검증할 프로젝트가 없으므로 통과
C/C++ 파일은 있지만 build metadata가 없음 orphan C++ 프로젝트 오류

8.4 MSVC 도구 탐색

도구 탐색기는 vswhere.exe로 다음을 확인한다.

  • Visual Studio 설치 경로
  • Desktop development with C++ workload
  • MSBuild.exe

CMake 프로젝트에서는 다음 우선순위로 CMake와 CTest를 선택한다.

  1. PATH에서 발견한 독립 cmake.exe와 ctest.exe
  2. Visual Studio에 번들된 CMake와 CTest

따라서 새로 설치한 CMake의 bin 디렉터리가 PATH에 반영되어 있으면 독립 CMake를 우선 사용한다.

9. 빌드 시스템별 검증 계획

9.1 CMake preset 미사용

CMake adapter는 다음 검증 계획을 만든다.

cmake -S <source> -B .harness/build -A x64
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure

명령 성공 외에 다음 결과도 검사한다.

  • 생성된 CMake compiler metadata의 CMAKE_CXX_COMPILER_ID가 MSVC인가
  • CTest JSON에 한 개 이상의 테스트가 있는가

따라서 빌드가 성공해도 MinGW 등 다른 컴파일러를 사용했거나 CTest가 테스트를 한 개도 발견하지 못하면 실패한다.

9.2 CMake preset 사용

.harness/config.json에 preset을 완전히 지정하면 다음 형태로 실행한다.

cmake --preset <configurePreset>
cmake --build --preset <buildPreset>
ctest --preset <testPreset> --show-only=json-v1
ctest --preset <testPreset> --output-on-failure

이 경우 모든 명령은 cmake.sourceDir에서 실행하고 compiler metadata 검사는 설정한 binaryDir에서 수행한다.

9.3 직접 MSBuild

MSBuild adapter는 다음 순서로 실행한다.

MSBuild.exe <solution-or-vcxproj> /m /nologo `
  /p:Configuration=<configuration> `
  /p:Platform=<platform>

<msbuild.testCommand>

직접 MSBuild 프로젝트는 표준 테스트 탐색 명령이 없으므로 .harness/config.json의 msbuild.testCommand가 반드시 필요하다. 이 값이 없으면 Stop 검증이 실패한다.

10. 명령 실행 안전성과 제한시간

검증 실행기는 다음 안전 규칙을 적용한다.

  • 명령을 shell 문자열이 아닌 argv 배열로 실행한다.
  • shell=False를 사용한다.
  • 각 명령의 working directory가 저장소 내부인지 검사한다.
  • 명령별 제한시간과 Stop 전체 제한시간 중 더 짧은 값을 적용한다.
  • 종료 코드가 0이 아니면 즉시 해당 stage를 실패 처리한다.

Stop 훅의 전체 제한시간은 저장소 탐색, toolchain 탐색, configure, build, test discovery, test를 모두 포함해 1,800초다. .codex/hooks.json의 Stop command timeout도 1,800초다.

실패 메시지에는 다음 진단 정보를 포함한다.

  • 실패 stage
  • 안전하게 표현한 argv 배열
  • working directory
  • 종료 코드
  • stdout과 stderr의 마지막 8,000자

Harness는 별도 빌드 로그 파일을 생성하지 않는다.

11. 성공, 실패, 차단 처리

11.1 Stop 검증 성공

빌드와 테스트가 모두 성공하거나 문서 전용 생략 조건을 충족하면 Stop 훅은 출력 없이 종료한다. 생략은 build/test 통과 evidence가 아니다. Codex가 정상 종료하면 Executor는 branch/HEAD, 제어 파일과 현재 Step 외 상태의 변경 여부를 검사하고 task index를 읽는다. Codex 종료 코드가 0이 아니면 completed 기록만으로 성공 처리하지 않는다.

Codex가 Step을 다음처럼 기록한 경우:

{
  "step": 0,
  "name": "division-api",
  "status": "completed",
  "owned_paths": ["include/calculator.hpp", "src/calculator.cpp", "tests/calculator_test.cpp"],
  "summary": "divide API와 0 나누기 테스트를 추가함"
}

Executor는 completed_at을 기록하고 변경사항을 커밋한 뒤 다음 pending Step을 실행한다.

11.2 Stop 검증 실패

Stop 훅은 Codex hook protocol에 따라 다음 형태의 응답을 출력한다.

{
  "decision": "block",
  "reason": "build failed ..."
}

훅 자체의 종료 코드는 0이지만 decision: block이 종료 차단 이유를 전달한다. 수정은 할당된 역할·Step·retry budget 안에서만 수행하며, Hook 실패가 상위 계약 변경이나 무제한 반복 권한을 주지 않는다.

11.3 Executor 재시도

Executor는 branch/HEAD·제어 파일·결과 형식과 변경 경로의 소유권을 먼저 검증한 뒤 Step 보고와 프로세스 종료 코드를 함께 판정한다.

결과 처리 자동 재시도
인식된 sandbox helper 환경 오류(종료 코드 무관), CLI 미설치 Step과 상위 phase blocked, 종료 2 없음
명시적 blocked 또는 error(종료 코드 무관) 원래 사유 보존, 각각 종료 2 또는 1 없음
completed + 종료 0 소유권·staged 경로 검증 후 커밋 없음
completed + nonzero error, 종료 1 없음
결과 미보고 + Executor wrapper의 실제 TimeoutExpired transport timeout 최초 포함 최대 2회
결과 미보고 + 종료 0, 원인 미분류 nonzero error, 종료 1 없음

종료 코드 124만으로 timeout을 추정하지 않는다. Wrapper가 실제 timeout을 관찰했을 때만 raw output에 transportFailure: "timeout"을 기록한다. 제어·소유권 위반은 이 재시도보다 우선하여 중단한다. 실패 결과를 pending으로 덮어쓰지 않고 원래 보고와 프로세스 진단을 Executor 소유 history에 구분해 남긴다.

첫 번째 transport 시도 실패
→ 오류를 다음 프롬프트에 삽입
→ 두 번째 독립 Codex 실행
→ 두 번째도 실패하면 error 기록 후 종료

Coordinator의 workflow correction은 별도 budget이다. 정규화된 feature_id|failing_gate|failure_classification|contract_revision별로 Correction을 최대 한 번, 그 뒤 Implementation rerun을 한 번만 허용한다. 계약·환경·물리 실패를 transport 재시도로 숨기거나 문구만 바꾸어 새 retry key를 만들지 않는다.

11.4 사용자 개입 필요

인증, API 키, 수동 설치처럼 Codex가 자동으로 해결할 수 없는 문제가 있으면 Step을 blocked로 기록한다. Executor는 blocked_at과 top-level 상태를 갱신하고 종료 코드 2로 중단한다.

재개 전 Coordinator가 원인 분류, 실패 evidence, retry key와 허용된 다음 작업을 coordination.md에 보존한다. Coordinator는 phase 파일을 직접 편집하지 않는다. 명시적으로 할당받은 Planning Agent가 Executor가 중단된 상태에서 phase index의 현재 실패/차단 Step status만 pending으로 변경한다. 다른 Step, top-level 상태와 timestamp는 변경하지 않는다. Executor가 재시작 시 오래된 outcome 필드·timestamp를 정리하되 attempt_history는 유지한다. 기존 Step에 owned_paths가 없으면 승인 목록을 작성하는 별도 Planning 할당이 필요하며 status 복구 권한만으로 목록을 추가·확대하지 않는다. 이는 할당된 파일 편집 절차이며 자동 복구 명령이나 추가 correction 허용이 아니다.

12. Git 커밋과 phase 완료

Step이 성공하면 제품 변경과 Harness metadata를 분리해 다음 형식으로 커밋한다.

feat(add-division): step 0 - division-api
chore(add-division): step 0 output

두 번째 커밋의 output은 task index의 Step 상태와 summary 같은 Harness metadata를 뜻한다. 원시 Codex 실행 기록인 stepN-output.json은 .gitignore 대상이며 커밋에 포함되지 않는다.

모든 Step이 완료되면 Executor는 다음 작업을 수행한다.

  • task의 completed_at 기록
  • phases/index.json의 task 상태를 completed로 변경
  • 최종 metadata 커밋
  • --push 사용 시 origin/feat-{phase-name}으로 push

Executor는 신뢰된 owned_paths snapshot으로 매 시도 후와 staging 직전의 변경 경로를 검사한다. tracked/untracked, staged/unstaged, 생성·수정·삭제와 rename 양쪽 경로가 대상이다. Windows 경로 구분자·대소문자 alias를 정규화하며 디렉터리·링크 대체도 다시 검사한다. 범위 밖 변경이 있으면 index를 정리하기 전에 중단하고 해당 경로와 사용자 파일을 보존한다.

검사 후 검증된 경로 snapshot에 한정해 index만 정리하고 git --literal-pathspecs add -A -- <선택 경로>를 사용한다. 저장소 전체 index를 reset하지 않는다. Commit 직전에는 git diff --cached --name-only --no-renames -z의 실제 staged 경로도 선택된 커밋 그룹과 대조한다. 구현 커밋에 phase metadata가 섞이는 것도 거부한다. 범위 위반 시 추가 stage/commit·재시도·다음 Step을 중단하며 파일을 되돌리거나 allowlist를 자동 확대하지 않는다. staging 후 발견한 위반은 당시 index를 남기므로 재개 전 검토가 필요하다.

동시 writer에 대한 원자적 격리는 보장하지 않으므로 실행 중 동시 편집을 피한다. 구현·metadata 커밋도 단일 transaction이 아니다. 구현 커밋 후 metadata 커밋이 실패하면 기존 커밋을 되돌리지 않고 Step을 error로 기록해 Coordinator에 반환한다.

13. 요구사항 종류별 동작

받은 요구사항 또는 변경 PreToolUse 동작 Stop 동작
새 C++ 제품 파일 추가 대응 테스트가 먼저 없으면 차단 전체 빌드·테스트
기존 C++ 구현 또는 header 수정 대응 테스트 파일 존재 여부 검사 전체 빌드·테스트
테스트 파일 추가 TDD 차단 없이 허용 모든 테스트가 성공해야 종료
main.cpp 수정 TDD 대응 테스트 검사 면제 전체 빌드·테스트
유효한 동일 session/turn 기록의 내부 .md 편집만 있음 C++ TDD 검사 없이 경로 기록 build/test 생략, 통과 evidence 아님
JSON, Python 또는 다른 비문서 편집 C++ TDD 검사 없음 C++ 프로젝트가 있으면 전체 검증
편집 기록 없음·손상 또는 shell 쓰기 완전한 편집 추적을 보장하지 않음 문서 전용 자동 생략을 보장하지 않음
위험한 Git 또는 삭제 명령 즉시 차단 도달하지 않음
C++ 파일은 있지만 build metadata 없음 편집은 허용될 수 있음 orphan 프로젝트 오류
직접 MSBuild인데 testCommand 없음 편집은 허용될 수 있음 설정 오류로 종료 차단
C/C++가 전혀 없는 저장소 관련 편집 검사 없음 검증할 프로젝트가 없어 통과

14. 적용 전 준비사항

FESA는 실제 구조해석 솔버 프로젝트이며 Harness는 재사용 가능한 개발 운영 인프라다. 일반 Feature 실행 전에 다음을 확인한다.

  1. AGENTS.md, 공통 PRD·ARCHITECTURE·ADR와 승인된 Feature 범위를 읽는다.
  2. Feature 관리 문서·선행 계약·revision과 Planning/Implementation dispatch를 확인한다. 일반 Feature 작업에서 프로젝트 공통 문서를 템플릿처럼 다시 작성하지 않는다.
  3. 기본 자동 감지로 충분하지 않을 때만 .harness/config.example.json을 참고해 .harness/config.json을 만든다.
  4. FESA의 CMake/MSVC x64 Debug·CTest 명령과 dependency 경로를 확인한다. 다른 저장소에 Harness를 적용할 때만 그 프로젝트의 승인된 adapter를 선택한다.
  5. phase 파일이 없다면 Planning Agent가 할당된 파일을 작성한다. 실행 권한은 별도로 확인한다.
  6. 시작 전 clean 범위와 실행 중 동시 편집 여부를 확인한다. 권한 상승은 clean linked worktree, native sandbox 실패 증거와 해당 실행 직전 승인·flag가 모두 필요하다.

특히 AGENTS.md와 docs/*.md는 각 Codex 실행에 그대로 주입된다. C++ 프로젝트에서 TypeScript 예시나 미완성 placeholder가 남아 있으면 실제 작업 지시와 충돌할 수 있다.