Files
Agentic-AI-Template/Codex/Coding/harness framework cs/docs/HARNESS_WORKFLOW.md
T
2026-09-08 10:30:07 +09:00

8.4 KiB

Harness 실행 흐름

Harness는 승인된 phase를 독립 Codex 세션으로 실행하고 C#·.NET 8 제품 규칙을 검증한다. 설정 예시는 HARNESS.md, phase 기록 형식은 phase README를 참고한다.

1. 계획

AGENTS.md와 변경에 관련된 제품 문서·코드·테스트를 확인하고 작업을 한 가지 책임의 step으로 나눈다. 각 step은 목표와 범위, 관련 파일, 핵심 제약, 실제 Acceptance Criteria를 가진다. 공개 계약이 필요한 경우에만 시그니처를 적는다. 이전 대화에 의존하지 않으며 문서 전체를 step 본문에 복사하지 않는다.

제품 기능의 red-green 작업은 한 step 안에서 끝낸다.

실패 테스트 작성·확인 → 최소 구현 → 전체 관련 테스트 성공 → step 종료

2. Phase 파일

phases/
  index.json
  <phase>/
    index.json
    step0.md
docs/phase/<phase>/
  handoff.md
  step0.md

phases/{phase}/index.json이 실행 상태의 기준이다. context_files는 기존 참고 문서, validation은 full 또는 docs-only를 선택한다.

{
  "project": "<제품명 또는 미정>",
  "phase": "add-parser",
  "steps": [
    {
      "step": 0,
      "name": "implement-parser",
      "status": "pending",
      "context_files": ["docs/ARCHITECTURE.md"],
      "validation": "full"
    }
  ]
}

3. 읽기 전용 확인

python scripts/execute.py <phase> --dry-run

첫 pending step의 현재 주입 경로, 경로별 문자 수와 전체 프롬프트 문자 수를 출력한다. Codex, Git, timestamp와 파일을 변경하지 않는다. --push와 동시 사용은 오류다.

4. 프롬프트 구성

각 호출 직전에 index, context_files와 handoff를 다시 읽고 다음 순서로 한 번만 결합한다.

AGENTS.md
→ 공통 작업 규칙
→ context_files
→ 현재 phase handoff 또는 호환 summary
→ 직전 실패 요약
→ 현재 step

context_files 생략은 추가 문서 없음이다. 잘못된 배열, 없는 파일, UTF-8로 읽을 수 없는 파일, 절대 경로, 저장소 밖 경로와 외부를 가리키는 symlink/junction은 Codex나 Git 변경 전에 거부한다. 경로 표기와 대소문자만 다른 중복도 한 번만 넣는다.

handoff가 없을 때만 현재 step보다 앞선 완료 step 중 가장 최근 하나의 summary를 최대 1,000자로 전달한다. 이후 step이나 모든 과거 summary를 누적하지 않는다.

5. 실행과 상태

Executor는 feat-{phase} branch에서 각 pending step을 독립 codex exec 프로세스로 실행한다. Codex는 종료 전에 현재 docs/phase/{phase}/stepN.md, handoff와 phase index를 갱신한다.

상태 의미
completed exit code 0과 executor 독립 검증 통과 후 timestamp와 commit 처리
error 자동 시도 예산 소진, 이유와 timestamp 기록 후 중단
blocked 사용자 또는 외부 환경 조치 필요, 추가 호출 없이 중단

프로세스가 nonzero로 끝나면 index에 completed가 있어도 성공으로 처리하지 않는다. Stop 실패가 exit code 0으로 끝나는 경우도 있으므로 완료 보고 직후 executor가 제품을 다시 검증한다. 실패하면 성공 상태를 취소하고 같은 최대 3회 호출 예산에서 재시도한다. 독립 검증에도 실제 docs-only 판정과 별도의 총 1,800초 검증 제한을 적용한다.

6. 재시도와 로그

Executor의 호출 예산은 최초 호출을 포함해 총 3회다. 한 Codex 세션 안의 일반적인 red-green 수정 횟수를 별도로 3회로 제한하지 않는다.

재시도 입력의 오류 본문은 총 4,000자로 제한한다. 앞 1,500자와 끝부분 최대 2,500자를 남기고 중간 생략 marker를 제한 안에 포함한다. 전체 stdout/stderr 결과는 phases/{phase}/stepN-output.json에 저장하지만 다음 시도에서 같은 파일을 덮어쓴다. 장기 보관할 시행착오는 step 기록에 요약한다. timeout도 같은 호출 예산의 실패이며 인증·CLI 옵션 같은 환경 오류는 즉시 중단한다.

7. 편집 전 정책

PreToolUse 훅은 위험한 삭제, 강제 push, hard reset과 SQL 파괴 명령을 차단한다. Windows 셸의 종료 코드 변환에 의존하지 않도록 JSON permissionDecision: "deny"로 거부한다. 실제 Codex 편집 payload의 tool_input.command에서 patch 경로를 읽는다. C# 제품 .cs 편집에는 대응 테스트 파일 존재 여부를 검사한다. 기본 루트는 저장소 tests/이며 편집 파일 옆 tests/, test/도 대응 테스트를 찾는다. Foo.cs의 대응 이름은 FooTests.cs 또는 FooTest.cs다. 테스트 루트의 보조 코드, 중첩 bin/·obj/ 등 산출물, 외부 의존성·명시 generated 경로는 제외한다. Program.cs나 .Designer.cs라는 이름만으로 면제하지 않는다. 필요한 면제는 정확한 tdd.exclude 경로와 이유를 기록한다. 이 설정은 제품 존재 탐색을 우회하지 않는다. 테스트 파일 존재와 실제 red-green 증거를 구분한다.

tdd.testPatterns는 {stem}을 포함하는 C# 파일명 패턴이다. 경로 구분자는 허용하지 않으며 테스트 위치는 testRoots로 지정한다. 한 검사 호출 안에서 후보 목록을 재사용하고 다음 호출에는 파일 추가·삭제를 반영한다. 제품 탐색에서 제외한 산출물·fixture 경로의 파일을 대응 테스트 증거로 사용하지 않는다.

8. 종료 전 검증

validation 생략 또는 full이면 Stop 훅이 발견한 C# 제품 전체를 검증한다.

  • 저장소 루트 global.json에 따른 .NET 8 SDK 선택 확인
  • target의 실제 각 프로젝트와 모든 test project의 TargetFramework/TargetFrameworks를 SDK로 평가해 .NET 8인지 확인; 상속된 props·속성 및 ProjectReference 그래프도 평가하며 빈 값·비지원 TFM·저장소 밖 참조는 거부
  • version 2 설정의 target과 명시된 모든 testProjects를 restore/build; build 경고는 오류로 처리하고 solution에 빠진 test project도 직접 build
  • 각 test project를 VSTest로 실행하고 현재 호출의 고유 디렉터리에 생성된 모든 TRX 검사
  • 실행 0건·skip-only·누락·손상·실패 TRX는 실패; 과거 결과를 성공 근거로 사용하지 않음
  • 지원 metadata 없음: 제외되지 않은 C# 소스가 있으면 orphan 오류
  • 제품과 metadata 모두 없음: 제품 검증 대상 없음; 제품 build 성공으로 기록하지 않음

전체 검증은 1,800초 deadline을 공유하며 SDK·TFM 평가·restore·build·test 중 실패한 단계에서 중단한다. tests/fixtures/는 제품 자동 탐색에서 제외하는 도구 검증용이다. Stop 프로세스 종료 코드만으로 통과를 판정하지 않는다. continue: false와 stopReason 응답은 검증 실패이며 실제 자동 훅 호출은 별도로 확인한다.

docs-only이면 executor가 현재 phase를 자식 프로세스 환경으로 전달하고 Stop 훅이 실제 Git 변경을 다시 검사한다. 루트 AGENTS.md, docs/**/*.md, 현재 phase의 index.json과 stepN-output.json만 허용하며 실제 문서 변경이 있어야 생략한다. rename은 원래 경로와 새 경로를 모두 검사한다. Git 실패, 빈 변경, bookkeeping만 있는 변경, untracked C# 또는 다른 파일이 하나라도 있으면 전체 검증으로 돌아간다. symlink나 junction으로 해석되는 변경 경로도 보수적으로 전체 검증한다.

9. Commit, 완료와 재개

step 성공 시 executor는 제품 변경과 metadata를 분리해 commit한다. 모든 step이 성공하면 phase와 top-level 상태를 completed로 바꾸고 --push가 있으면 origin/feat-{phase}에 push한다. 실행기는 광범위한 staging을 할 수 있으므로 깨끗한 전용 worktree에서 실행한다.

재개 절차:

  1. error 또는 blocked 원인을 해결한다.
  2. 해당 step status를 pending으로 바꾼다.
  3. error_message/failed_at 또는 blocked_reason/blocked_at을 제거한다.
  4. handoff, 직전 원본 출력과 index를 확인한 뒤 다시 실행한다.

강제 종료로 handoff가 낡았을 수 있으므로 index 상태를 우선한다. 이 저장소의 fixture 검증은 제품 요구사항이나 실제 제품 build 완료를 의미하지 않는다. 실행한 명령과 결과, SDK·테스트 건수와 남은 미검증 항목은 해당 phase 기록에서 확인한다.