246 lines
10 KiB
Markdown
246 lines
10 KiB
Markdown
# 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 설정으로 복사한다.
|
|
|
|
```powershell
|
|
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
|
|
|
|
```json
|
|
{
|
|
"version": 1,
|
|
"projectType": "cmake",
|
|
"cmake": {
|
|
"sourceDir": ".",
|
|
"binaryDir": ".harness/build"
|
|
}
|
|
}
|
|
```
|
|
|
|
`binaryDir`은 non-preset plan에서도 사용할 수 있다. Preset을 사용하면 `configurePreset`,
|
|
`buildPreset`, `testPreset`, `binaryDir`를 모두 지정한다. 자동 감지에서도 명시된
|
|
`cmake.sourceDir`을 먼저 검사한다.
|
|
|
|
Preset이 없을 때의 기본 계획은 다음 형태다.
|
|
|
|
```powershell
|
|
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
|
|
|
|
```json
|
|
{
|
|
"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
|
|
|
|
```json
|
|
{
|
|
"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뿐이다.
|
|
|
|
```powershell
|
|
git status --short
|
|
python scripts/execute.py <phase-name>
|
|
```
|
|
|
|
Executor는 다음을 수행한다.
|
|
|
|
1. Safe phase name, repository/phase containment, top-level index, phase metadata, contiguous Step와
|
|
status order 검증
|
|
2. Implementation profile, exact Git top-level, sandbox 권한과 strict worktree preflight
|
|
3. `feat-<phase>` branch checkout/create
|
|
4. Implementation Agent 역할, project guardrail, prior summary와 current Step 주입
|
|
5. Current Step의 Codex session 실행과 최대 2회 transport attempt
|
|
6. Exit code와 Step payload 검증
|
|
7. Implementation path와 phase metadata의 path-scoped local commit
|
|
8. 모든 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에서 다음 두
|
|
조건을 함께 제공한다.
|
|
|
|
```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
|
|
```
|
|
|
|
Primary worktree, dirty worktree, 환경 변수만 설정한 실행은 거부된다. `danger-full-access`는
|
|
hook을 끄지 않지만 hook이 완전한 sandbox라는 의미도 아니다.
|
|
|
|
원격 push는 별도 critical action이다. 사용자가 정확한 branch push를 승인한 경우에만
|
|
실행한다.
|
|
|
|
```powershell
|
|
python scripts/execute.py <phase-name> --push
|
|
```
|
|
|
|
Executor는 force push, history rewrite, tag, publish 또는 deploy를 수행하지 않는다.
|
|
|
|
## 6. Hook 동작
|
|
|
|
`.codex/hooks.json`은 [Codex Hooks contract](https://learn.chatgpt.com/docs/hooks)에 따라
|
|
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_patch` payload의 `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에는
|
|
포함하지 않는다.
|
|
|
|
```text
|
|
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 자체 검증
|
|
|
|
```powershell
|
|
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 기본 권한 밖이다.
|