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

181 lines
8.9 KiB
Markdown

# Harness 운영 가이드
## Requirements
Windows와 Codex CLI가 필요하다. Executor는 Python 3.10 이상을 사용하며, 이 저장소의
계약 테스트는 표준 `tomllib`을 사용하므로 검증 환경은 Python 3.11 이상으로 준비한다.
FESA는 Visual Studio의 Desktop development with C++ 워크로드, CMake/CTest와 Ninja를
사용한다. MSVC x64 developer 환경과 dependency 경로는 [AGENTS.md](../AGENTS.md)의
최소 검증 진입점을 따른다.
역할·승인·상태 전이는 [Agent 계약](SOLVER_AGENT_DESIGN.md)과
[Harness skill](../.agents/skills/harness/SKILL.md)을 따른다. 이 문서는 설치·실행 참고이며
solver Feature의 9개 stage와 evidence gate를 대신하지 않는다.
## 프로젝트 자동 감지
프로젝트 형식은 다음 순서로 결정한다: `.harness/config.json`의 명시적 type, 루트의
CMake metadata, 하나의 `.sln`, 하나의 `.vcxproj` 순서다. C/C++가 아닌 저장소는
건너뛰며, C/C++ 파일은 있지만 CMake/solution metadata가 없는 orphan-C++ 저장소는
오류로 처리한다.
설정 파일은 선택 사항이다. 기본 자동 감지와 `.harness/build` 경로를 그대로 사용할
때는 만들지 않아도 된다. 프로젝트별 override가 필요하면 다음처럼 예시를 복사한다.
```powershell
Copy-Item .harness/config.example.json .harness/config.json
```
승인된 Feature와 Coordinator dispatch에 따라 Planning Agent가 할당된 phase 파일을
작성한다. 일반 계획 파일 작성에 반복 승인을 요구하지 않는다. 실행까지 할당된 경우에만
다음 명령을 사용하며, 계획 작성 요청만으로 Executor를 시작하지 않는다.
```powershell
python scripts/execute.py <phase-name>
```
`--push`는 해당 원격 push를 사용자가 명시적으로 승인했을 때만 추가한다. 실행 전
Git top-level은 Harness root와 같고 선택된 phase 제어 파일 밖의 worktree는 clean이어야
한다. 실행 중 동시 편집과 커밋 범위의 한계는 [동작 과정](HARNESS_WORKFLOW.md)을 따른다.
모든 `pending` Step에는 승인된 정확한 상대 파일 목록인 `owned_paths`가 필요하다.
누락된 기존 phase는 Planning의 할당된 준비 작업에서 목록을 보완한 뒤 실행한다.
`[]`는 구현 파일 변경이 없음을 뜻하며 완료 이력에는 목록을 소급 추가하지 않는다.
Executor는 실행 후와 staging/commit 경계에서 소유권을 검사하며 범위 밖 변경은
보존하고 중단한다. 상세 schema와 제한은 [Harness skill](../.agents/skills/harness/SKILL.md)을 따른다.
Executor가 시작하는 Codex 세션은 기본적으로 `workspace-write` sandbox를 사용한다.
Windows native sandbox에서 MSVC compiler-id의 `cl.exe`가 정지하는 것이 재현되고 같은
명령이 sandbox 밖에서 정상 완료되는 경우에만, 사용자 승인을 받은 격리된 clean
linked Git worktree에서 다음처럼 해당 실행에 한정해 fallback을 지정할 수 있다.
```powershell
$env:FEM_HARNESS_CODEX_SANDBOX = "danger-full-access"
python scripts/execute.py <phase-name> --approve-danger-full-access
Remove-Item Env:FEM_HARNESS_CODEX_SANDBOX
```
허용값은 `workspace-write`와 `danger-full-access`뿐이다. 후자는 Codex Step에 workspace
밖의 파일 접근 권한도 부여하므로 일반 기본값으로 설정하지 않는다. 어느 모드에서도
`.codex/hooks.json`의 등록된 hook을 비활성화하지 않는다. 환경변수만으로 권한이 승인되지
않으며 Executor는 승인 flag가 없거나 primary/dirty worktree인 권한 상승 실행을 거부한다.
Stop은 유효한 동일 session/turn 편집 기록의 대상이 모두 저장소 내부 `.md`일 때만
build/test를 생략한다. 기록 누락·손상 또는 비문서 편집은 정상 검증 경로를 따른다.
Shell 쓰기나 편집 기록 없는 읽기 전용 요청도 자동 생략을 보장하지 않는다. 문서 작업에서
사용자가 실행을 제외하면 수동으로 Hook·build/test를 실행하지 않고 미검증 사실을 보고한다.
## Harness Python 검증
이 저장소의 테스트와 최종 acceptance 검증은 pytest를 시스템 Python에 설치하지 않고
다음 명령으로 실행한다.
```powershell
uv run --with pytest python -B -m pytest -v -rs
```
## CMake preset 설정
`projectType`을 `cmake`로 지정하거나 자동 감지를 사용한다. `cmake.sourceDir`,
`binaryDir`, `configurePreset`, `buildPreset`, `testPreset`은 preset을 사용할 때 함께
지정해야 한다. 빌드 산출물은 저장소의 `.harness/build/`처럼 격리된 경로에 둔다.
```json
{
"version": 1,
"projectType": "cmake",
"cmake": {
"sourceDir": ".",
"binaryDir": ".harness/build-ninja-msvc-debug",
"configurePreset": "windows-msvc-ninja-debug",
"buildPreset": "windows-msvc-ninja-debug",
"testPreset": "windows-msvc-ninja-debug"
}
}
```
```powershell
cmake --preset windows-msvc-ninja-debug
cmake --build --preset windows-msvc-ninja-debug
ctest --preset windows-msvc-ninja-debug --show-only=json-v1
ctest --preset windows-msvc-ninja-debug --output-on-failure
```
위 예시는 현재 [CMakePresets.json](../CMakePresets.json)과
[config 예시](../.harness/config.example.json)에 맞춘다. Preset 파일이 존재하는 것만으로
Stop이 그 preset을 선택하지는 않는다. 아래는 preset을 쓰지 않는 adapter의 명령 형태이며,
FESA에서는 dependency 경로와 승인된 build 구성을 함께 확인한다.
```powershell
cmake -S . -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
```
## 직접 MSBuild 설정
다음은 재사용 가능한 Harness adapter의 예시다. FESA 제품 검증은 CMake/CTest를 사용하며
이 예시로 solution-only MSBuild 검증을 대체 승인하지 않는다.
`projectType`을 `msbuild`로 설정하면 `msbuild.solution`, `configuration`, `platform`을
지정한다. 직접 MSBuild 프로젝트에서는 `msbuild.testCommand`가 필수이며, 테스트 실행
파일과 인수를 JSON 배열로 적는다.
```json
{
"version": 1,
"projectType": "msbuild",
"msbuild": {
"solution": "MyProject.sln",
"configuration": "Debug",
"platform": "x64",
"testCommand": ["build/tests/Debug/MyProjectTests.exe"]
}
}
```
```powershell
MSBuild.exe MyProject.sln /m /p:Configuration=Debug /p:Platform=x64
.\build\tests\Debug\MyProjectTests.exe
```
## TDD 확장
`tdd.testRoots`와 `tdd.testPatterns`로 테스트 위치와 이름을 확장한다. 패턴마다
`{stem}`이 필요하다. `main`, 테스트, 외부 의존성, 생성 파일, build directory 같은
기본 제외 항목은 Harness가 관리하며, `tdd.exclude`의 사용자 제외 항목은 이를
대체하지 않고 추가한다.
```json
{
"version": 1,
"tdd": {
"testRoots": ["tests", "integration-tests"],
"testPatterns": ["{stem}_test.cpp", "test_{stem}.cpp"],
"exclude": ["legacy/generated/**"]
}
}
```
## 실패 복구
Executor는 명시적 `error/blocked`를 비정상 종료에서도 보존하며 자동 재시도하지 않는다.
인식된 sandbox helper 환경 오류는 종료 코드 0에서도 Step과 상위 phase를 `blocked`로
기록한다. 실제 wrapper timeout으로 결과를 받지 못했을 때만 최초 포함 최대 두 번 시도한다.
원인 미분류 nonzero와 `completed`/nonzero 불일치는 `error`다. 환경 차단은 종료 코드 2,
일반 실패는 1이며 preflight 실패는 branch/state 변경 전에 반환한다.
- Visual Studio C++ workload가 없으면 Installer에서 Desktop development with C++를 설치한 뒤 다시 실행한다.
- solution 또는 project가 여러 개라서 모호하면 `projectType`과 `msbuild.solution`을 명시한다.
- MSVC가 아닌 컴파일러가 감지되면 MSVC Developer Command Prompt에서 실행하거나 toolchain을 MSVC로 전환한다.
- CTest가 0개 테스트를 보고하면 `enable_testing()`과 테스트 등록을 확인한다.
- 직접 MSBuild 구성에 test command가 없으면 `msbuild.testCommand` 배열을 추가한다.
- timeout 또는 명령 실패 시 Stop 응답의 stage, 안전한 argv 배열, 작업 디렉터리,
종료 코드와 출력 tail을 확인한다. 실행이 할당된 범위에서만 재현 명령을 수행하며
문서 작업의 검증 제외 지시를 덮어쓰지 않는다. Stop은 별도의 빌드 로그 파일을 만들지 않는다.
- 실패 분류와 재시작 결정은 Coordinator가 기록한다. Planning Agent는 명시적으로 할당된
복구 작업에서만 현재 실패 Step의 status를 `pending`으로 바꾸고, Executor가 재시작 시
오래된 outcome 필드와 timestamp를 정리하되 `attempt_history`는 보존한다. 실패 evidence를 먼저 보존하며
상세 절차는 [Harness skill](../.agents/skills/harness/SKILL.md)의 Recovery and handoff를 따른다.