10 KiB
Harness Operations Guide
1. 역할과 현재 상태
Harness는 agent가 작성한 implementation Step을 독립 Codex session에서 실행하고, C/C++ 변경의 TDD guard, configured MSVC build/test, 상태와 local Git commit을 관리한다.
현재 repository에는 solver C++ source와 build metadata가 없다. 따라서 repository 자체에서는 Python Harness regression suite를 검증하며, C++ build 성공을 주장하지 않는다. Solver feature가 CMake 또는 Visual Studio metadata를 추가하면 Stop hook이 해당 project를 검증한다.
2. 요구 환경
- Windows와 Python 3.11 이상
- Git과 Codex CLI
- Harness test 실행용
uv - C++ project를 검증할 때 Visual Studio Desktop development with C++, MSBuild, CMake/CTest
실제 toolchain, generator, configuration과 test command는 .harness/config.json 및 project
build metadata가 source of truth다.
3. 설정
설정이 없으면 Harness는 자동 감지를 사용한다. Override가 필요할 때만 tracked example을 machine-local 설정으로 복사한다.
Copy-Item .harness/config.example.json .harness/config.json
.harness/config.json은 ignore되며 code와 같은 실행 가능한 신뢰 경계다. Preset과 test
executable은 arbitrary child process를 실행할 수 있으므로 review 없이 외부에서 받은 설정을
사용하지 않는다.
지원하는 projectType은 auto, cmake, msbuild다. Unknown field, absolute/escaping path와
불완전한 preset은 거부된다. TDD pattern은 directory separator가 없는 safe basename이어야 하며
format field로 {stem}만 사용할 수 있다.
CMake
{
"version": 1,
"projectType": "cmake",
"cmake": {
"sourceDir": ".",
"binaryDir": ".harness/build"
}
}
binaryDir은 non-preset plan에서도 사용할 수 있다. Preset을 사용하면 configurePreset,
buildPreset, testPreset, binaryDir를 모두 지정한다. 자동 감지에서도 명시된
cmake.sourceDir을 먼저 검사한다.
Preset이 없을 때의 기본 계획은 다음 형태다.
cmake -S <sourceDir> -B <binaryDir> -A x64
cmake --build <binaryDir> --config Debug
ctest --test-dir <binaryDir> -C Debug --show-only=json-v1
ctest --test-dir <binaryDir> -C Debug --output-on-failure
Harness는 compiler metadata가 MSVC인지, CTest가 한 개 이상의 test를 발견했는지도 확인한다.
Visual Studio/MSBuild
{
"version": 1,
"projectType": "msbuild",
"msbuild": {
"solution": "Solver.sln",
"configuration": "Debug",
"platform": "x64",
"testCommand": ["build/tests/Debug/SolverTests.exe"]
}
}
testCommand는 필수이며 첫 항목은 repository-relative executable path여야 한다. Bare PATH
program, absolute path와 repository escape는 허용되지 않는다. 인수는 배열의 후속 항목으로
전달된다.
TDD path mapping
{
"version": 1,
"tdd": {
"testRoots": ["tests", "integration-tests"],
"testPatterns": ["{stem}_test.cpp", "test_{stem}.cpp"],
"exclude": ["generated/**"]
}
}
Project exclude는 Harness의 build/vendor/generated 기본 exclude에 추가된다. Production C/C++ 파일을 편집하려면 mapping되는 test 파일이 먼저 존재해야 한다.
4. 계획과 실행
Coordinator가 승인된 feature bundle로 planning/execution을 dispatch하면 routine local 작업을
위해 별도 사용자 승인을 반복하지 않는다. Planning Agent는 .agents/skills/harness/SKILL.md에
따라 phases/ index와 self-contained Step을 만든다.
Executor 시작 전 worktree는 선택한 phase의 선언된 control file 밖에서 깨끗해야 한다. 허용되는
control file은 top/phase index, phase index에 선언된 stepN.md와 해당 local raw output뿐이다.
git status --short
python scripts/execute.py <phase-name>
Executor는 다음을 수행한다.
- Safe phase name, repository/phase containment, top-level index, phase metadata, contiguous Step와 status order 검증
- Implementation profile, exact Git top-level, sandbox 권한과 strict worktree preflight
feat-<phase>branch checkout/create- Implementation Agent 역할, project guardrail, prior summary와 current Step 주입
- Current Step의 Codex session 실행과 최대 2회 transport attempt
- Exit code와 Step payload 검증
- Implementation path와 phase metadata의 path-scoped local commit
- 모든 Step 완료 시 phase closure
일반 implementation failure는 Executor가 반복 수정하지 않는다. Step을 error로 기록하고
Coordinator가 normalized retry_key와 correction budget으로 route한다.
5. Sandbox와 외부 변경
기본 sandbox는 workspace-write다. Windows native sandbox가 실제 compiler process를 막는
것이 재현된 경우에만 사용자가 해당 실행을 명시 승인하고 clean linked worktree에서 다음 두
조건을 함께 제공한다.
$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
Primary worktree, dirty worktree, 환경 변수만 설정한 실행은 거부된다. danger-full-access는
hook을 끄지 않지만 hook이 완전한 sandbox라는 의미도 아니다.
원격 push는 별도 critical action이다. 사용자가 정확한 branch push를 승인한 경우에만 실행한다.
python scripts/execute.py <phase-name> --push
Executor는 force push, history rewrite, tag, publish 또는 deploy를 수행하지 않는다.
6. Hook 동작
.codex/hooks.json은 Codex Hooks contract에 따라
PreToolUse와 Stop hook을 등록한다. Hook은 자동 실행하며 검증 대체를 위해 수동 호출하지
않는다.
PreToolUse
- 위험한 Git/delete/database command pattern을 exit code 2로 차단한다.
- Implementation session의 commit, push, branch/switch, tag, merge/rebase와 history 변경 Git command를 차단한다. 이 동작은 Executor 또는 별도 승인된 외부 작업만 소유한다.
- 공식
apply_patchpayload의tool_input.command에서 patch path를 추출한다. - C/C++ production path에 대응 test가 없으면 편집을 차단한다.
- Malformed/unknown edit payload는 fail closed한다.
Test path 존재 검사는 실제 RED, assertion 품질 또는 coverage를 증명하지 않는다.
Stop
- Payload의
cwd에서 Git root를 찾고 재진입을 방지한다. - Config/discovery/toolchain/adapter plan을 전체 deadline 안에서 실행한다.
- 실패 시 current Codex hook contract의
{"decision":"block","reason":"..."}을 반환해 같은 session이 수정하게 한다. stop_hook_active재진입은 즉시 허용한다.- Config argument의 control character를 거부하고 예상하지 못한 일반 예외도 block response로 변환한다.
- C/C++ source와 build metadata가 모두 없으면 검증 target 없음으로 정상 종료한다.
- C/C++ source만 있고 build metadata가 없으면 orphan project로 차단한다.
7. Git과 runtime artifact
Preflight 이후 생성된 implementation path만 feature commit에 stage한다. 각 commit 직전에 working tree는 보존한 채 index를 초기화한 다음 대상 path만 다시 stage하므로 agent가 미리 stage한 metadata가 feature commit에 섞이지 않는다. Selected phase index, Step과 timestamps는 별도 metadata commit에 stage한다. 관련 없는 pre-existing worktree 변경이나 phase 안의 미선언 파일이 있으면 branch checkout 전에 실행을 거부한다.
각 Codex attempt 전후에는 symbolic branch와 HEAD도 비교한다. Session이 자체 commit, checkout 또는 branch 변경으로 hook을 우회하면 결과를 신뢰하지 않고 current Step을 error로 고정한다.
Raw Codex stdout/stderr는 다음 local diagnostic file에 저장하지만 source control에는
포함하지 않는다.
phases/<phase>/step<N>-output.json
.gitignore는 위 파일, .harness/config.json, build output와 Python cache를 제외한다. Raw
output은 credential을 포함할 수 있으므로 공유하거나 artifact로 게시하기 전에 검토한다.
Control file은 non-link regular file로 읽고 phase/root containment를 매번 확인한다. Index,
instruction 복구와 raw output write는 같은 directory의 임시 파일을 os.replace하는 atomic
write를 사용해 symlink·hardlink target을 따라가 덮어쓰지 않는다.
8. 상태와 복구
| Step status | 필수 payload | 다음 처리 |
|---|---|---|
pending |
없음 | Executor가 선택 가능 |
completed |
summary |
timestamp와 commits 후 다음 Step |
error |
error_message |
Coordinator classification 전 중단 |
blocked |
blocked_reason |
환경/권한/critical decision 해결 전 중단 |
Nonzero Codex exit는 Step이 completed를 썼더라도 신뢰하지 않는다. 두 transport attempt가
실패하면 error와 failed_at을 기록한다. 재개는 Coordinator가 owner와 evidence를 확인한 뒤
current Step을 pending으로 돌리는 방식으로 수행한다. Executor는 stale outcome timestamp를
정리한다.
Codex session 전후로 top-level index와 모든 stepN.md를 byte 비교하고 phase index의 current
Step outcome 외 변경을 거부한다. Future Step, instruction 또는 control metadata가 바뀌면 snapshot을
복원하고 current Step을 trusted error로 기록하므로 다음 실행에서 조작된 완료 상태를 수락하지
않는다.
9. Harness 자체 검증
uv run --with pytest python -B -m pytest -v -rs
python -B scripts/execute.py --help
실제 Executor 기능 시험은 현재 repository에서 직접 실행하지 않는다. Branch/commit/Codex를 변경하기 때문이다. Regression suite가 temporary Git repository와 hook subprocess를 사용해 state, Git, payload와 failure behavior를 검증한다.
10. 한계
shell=False와 repository-relative executable은 shell injection을 줄이지만 configured executable/preset의 side effect를 격리하지 않는다.- PreToolUse는 shell redirection 등 모든 파일 쓰기를 완전하게 해석하지 않는다.
- Stop pass는 configured target의 build/test 결과이며 formulation과 physics correctness를 대신하지 않는다.
- External solver reference execution과 reference artifact 생성은 Harness 기본 권한 밖이다.