docs: align guidance with simplified agent and harness workflow

This commit is contained in:
KOKO\Mimi
2026-09-07 22:12:48 +09:00
parent d7e9629640
commit 5e2a30fce0
10 changed files with 593 additions and 1304 deletions
+91 -117
View File
@@ -1,84 +1,46 @@
# Harness 운영 가이드
## Requirements
## 목적과 준비 환경
Windows와 Codex CLI가 필요하다. Executor는 Python 3.10 이상을 사용하며, 이 저장소의
계약 테스트는 표준 `tomllib`을 사용하므로 검증 환경은 Python 3.11 이상으로 준비한다.
Harness는 명시적으로 호출하는 repository build/test 실행기다.
[Agent 운영](SOLVER_AGENT_DESIGN.md)과 [Harness skill](../.agents/skills/harness/SKILL.md)에
따라 필요한 검증을 수행하며 내부 Codex 호출, phase 관리, 자동 Git 처리와 대화 종료
hook을 사용하지 않는다. 현재 운영 결정은 [ADR-028](ADR.md#adr-028)을 따른다.
Runner에는 Windows와 Python 3.10 이상이 필요하다. 저장소의 `tomllib` 기반 Python 검사는
Python 3.11 이상을 사용한다. Runner 자체는 Codex CLI를 필요로 하지 않는다.
FESA는 Visual Studio의 Desktop development with C++ 워크로드, CMake/CTest와 Ninja를
사용한다. MSVC x64 developer 환경과 dependency 경로는 [AGENTS.md](../AGENTS.md)의
최소 검증 진입점을 따른다.
사용한다. MSVC x64 developer 환경에서 `FESA_GTEST_SOURCE_DIR`, `MKL_DIR`, `TBB_DIR`,
`HDF5_DIR`를 설치된 dependency 경로로 설정한다. 상세 기준은
[프로젝트 지침](../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
python scripts/execute.py
```
승인된 Feature와 Coordinator dispatch에 따라 Planning Agent가 할당된 phase 파일을
작성한다. 일반 계획 파일 작성에 반복 승인을 요구하지 않는다. 실행까지 할당된 경우에만
다음 명령을 사용하며, 계획 작성 요청만으로 Executor를 시작하지 않는다.
개발 중 focused check는 선택된 backend의 실제 명령을 직접 실행한다. 솔버 기능 완료 시
구성된 전체 build/test와 계약상 필수 reference 비교를 수행하고 이후 변경·실패가 없으면
반복하지 않는다. 문서만 변경하는 작업에서는 정적 검토를 하고 build/test를 실행하지 않는다.
```powershell
python scripts/execute.py <phase-name>
```
Runner는 자신의 script 위치를 기준으로 저장소 root를 정하고 `.harness/config.json`을
읽는다. 설정이 없으면 기본 자동 감지를 사용한다. 선택 순서는 명시한 `projectType`,
설정된 CMake source directory의 metadata, root의 단일 `.sln`, 단일 `.vcxproj`다.
여러 solution/project로 선택이 모호하면 명시 설정이 필요하다. C++ source 전체를
scan하거나 metadata 없는 C++ 파일의 존재로 별도 gate를 적용하지 않는다.
`--push`는 해당 원격 push를 사용자가 명시적으로 승인했을 때만 추가한다. 실행 전
Git top-level은 Harness root와 같고 선택된 phase 제어 파일 밖의 worktree는 clean이어야
한다. 실행 중 동시 편집과 커밋 범위의 한계는 [동작 과정](HARNESS_WORKFLOW.md)을 따른다.
현재 [config 예시](../.harness/config.example.json)는 `projectType=cmake`와
`cmake.sourceDir=.`만 지정한다. 개인 설정이 필요할 때 참고하되 기존 설정을 무조건
덮어쓰지 않는다. Preset 없는 기본 binary directory는 `.harness/build`다.
모든 `pending` Step에는 승인된 정확한 상대 파일 목록인 `owned_paths`가 필요하다.
누락된 기존 phase는 Planning의 할당된 준비 작업에서 목록을 보완한 뒤 실행한다.
`[]`는 구현 파일 변경이 없음을 뜻하며 완료 이력에는 목록을 소급 추가하지 않는다.
Executor는 실행 후와 staging/commit 경계에서 소유권을 검사하며 범위 밖 변경은
보존하고 중단한다. 상세 schema와 제한은 [Harness skill](../.agents/skills/harness/SKILL.md)을 따른다.
## FESA CMake preset 설정
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/`처럼 격리된 경로에 둔다.
FESA의 현재 [CMakePresets.json](../CMakePresets.json)을 사용하려면 다음 필드를
`.harness/config.json`에 함께 지정한다. Preset 파일의 존재나 config 예시 복사만으로
Runner가 preset 이름을 선택하지는 않는다.
```json
{
@@ -94,6 +56,9 @@ uv run --with pytest python -B -m pytest -v -rs
}
```
`configurePreset`, `buildPreset`, `testPreset`, `binaryDir`는 함께 지정해야 한다.
이에 대응하는 backend 명령은 다음과 같다.
```powershell
cmake --preset windows-msvc-ninja-debug
cmake --build --preset windows-msvc-ninja-debug
@@ -101,10 +66,8 @@ 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 구성을 함께 확인한다.
아래는 preset 없는 CMake adapter의 기본 명령 형태다. FESA에서는 승인된 MSVC x64 Debug
구성과 dependency 경로를 함께 확인한다.
```powershell
cmake -S . -B .harness/build -A x64
@@ -113,14 +76,14 @@ ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
Runner는 configure 후 MSVC compiler metadata를 확인하고 CTest discovery가 0개이면
실패로 처리한다. Build/test 성공이 물리·수치 correctness나 별도 필수 reference 비교의
통과를 대신하지 않는다. Runner는 Feature 문서에서 추가 비교 명령을 추론하지 않는다.
## 직접 MSBuild 설정
다음은 재사용 가능한 Harness adapter의 예시다. FESA 제품 검증은 CMake/CTest를 사용하며
이 예시로 solution-only MSBuild 검증을 대체 승인하지 않는다.
`projectType`을 `msbuild`로 설정하면 `msbuild.solution`, `configuration`, `platform`을
지정한다. 직접 MSBuild 프로젝트에서는 `msbuild.testCommand`가 필수이며, 테스트 실행
파일과 인수를 JSON 배열로 적는다.
다음은 재사용 Harness adapter의 예시다. FESA 제품 검증은 CMake/CTest를 사용하며
solution-only MSBuild를 승인된 대체 검증으로 간주하지 않는다.
```json
{
@@ -135,46 +98,57 @@ ctest --test-dir .harness/build -C Debug --output-on-failure
}
```
`msbuild.testCommand`는 필수 argv 배열이며 실행 파일은 repository-relative 경로로
지정한다. 선택한 solution/project를 build한 뒤 testCommand를 한 번 실행한다.
## 결과와 실패 진단
| 상황 | Runner 결과 |
| --- | --- |
| 구성된 build/test와 결과 검사가 모두 성공 | exit 0, 명령·cwd·exit code와 test 출력 요약 |
| 잘못된 config, 모호한 감지, toolchain/adapter 오류, backend 실패·timeout | exit 1 |
| 명시한 projectType의 metadata가 없음 | exit 1 |
| Non-MSVC compiler 또는 CTest 0개/잘못된 discovery 결과 | exit 1 |
| 자동 감지에서 CMake/MSBuild metadata가 없음 | `not configured`, exit 2 |
| 지원하지 않는 CLI 인자 | usage error, exit 2; 검증 미시작 |
Backend nonzero는 실패 진단에 원래 값으로 남지만 runner의 반환값은 1이다.
대상 부재나 미실행을 검증 통과로 표시하지 않는다. 실패 시 stage, argv, cwd와 가능한
출력 tail을 확인한다. 실패 후 자동 재시도나 후속 단계를 실행하지 않는다.
- Visual Studio 도구가 없으면 C++ workload와 설치 경로를 확인한다.
- Solution/project 선택이 모호하면 `projectType`, `msbuild.solution`을 명시한다.
- Compiler가 MSVC가 아니면 선택된 환경과 toolchain 설정을 확인한다.
- CTest가 0개이면 `enable_testing()`과 테스트 등록을 확인한다.
- MSBuild test command가 없으면 실제 테스트 실행 파일과 인수를 설정한다.
- Timeout·실패 원인은 현재 구현 owner가 수정한다. 새 근거나 변경 없이 반복 실행하지 않는다.
Runner 전체 deadline은 config·discovery·toolchain 탐색을 포함해 1,800초다. 각 명령에는
남은 전체 시간과 명령별 timeout 중 짧은 값을 적용한다. 실행·검사 경계는
[동작 과정](HARNESS_WORKFLOW.md)을 따른다.
## 이전 운영 방식에서 달라진 점
옛 `python scripts/execute.py <phase>` 호출과 `--push`,
`--approve-danger-full-access` 인자는 usage error로 거부한다. Phase import나 상태
migration은 제공하지 않으며 기존 `phases/` 기록을 읽거나 수정하지 않는다.
Legacy `tdd` config는 설정 로드 때 폐기 안내를 한 번 출력하고 무시한다.
`testRoots`·`testPatterns`·`exclude`에 의한 대응 파일명 gate는 없다. 개인 config는
자동 수정하지 않으므로 사용자가 필요할 때 해당 항목을 제거할 수 있다.
전용 phase executor, 자동 branch/commit/push·retry, PreToolUse/Stop과 자체 sandbox 승인
환경변수는 사용하지 않는다. Git 상태를 변경하거나 commit할 권한은 runner 실행에서
생기지 않는다. Config·preset·명령은 검토할 실행 입력이며 `shell=False`와 경로 검사는
완전한 sandbox가 아니다. 실제 도구 권한과 외부 실행의 명시적 승인 경계는 유지한다.
## Harness Python 검증
Harness 구현을 변경하여 Python 검증이 필요할 때 다음 명령을 사용한다. 개발 중에는
관련 검사만 선택하고 전체 검사가 필요한 최종 변경 후 한 번 실행한다.
```powershell
MSBuild.exe MyProject.sln /m /p:Configuration=Debug /p:Platform=x64
.\build\tests\Debug\MyProjectTests.exe
uv run --with pytest python -B -m pytest -v -rs
```
## 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를 따른다.
실제 검사 결과와 미실행 항목을 구분해 보고한다. 문서만 갱신할 때는 이 명령을 실행하지 않는다.