docs: align guidance with simplified agent and harness workflow
This commit is contained in:
+80
-664
@@ -1,693 +1,109 @@
|
||||
# Harness Framework 동작 과정
|
||||
# Harness 동작 과정
|
||||
|
||||
이 문서는 자연어 요구사항을 받은 뒤 Harness Framework가 계획을 만들고, 독립된
|
||||
Codex 세션에서 Step을 실행하고, MSVC로 C++ 프로젝트를 검증하는 전체 과정을
|
||||
설명한다. 설치 및 설정 예시는 [Harness 운영 가이드](HARNESS.md)를 참고한다.
|
||||
## 개발 작업과 명시적 검증
|
||||
|
||||
Feature의 9개 정규 stage와 Coordinator의 gate 전이는
|
||||
[Agent 계약](SOLVER_AGENT_DESIGN.md), 역할별 절차는
|
||||
[Harness skill](../.agents/skills/harness/SKILL.md), 문서 소유권은
|
||||
[Feature 문서 관리](FEATURE_DOCUMENTATION.md)를 따른다. Harness는 그중 할당된
|
||||
구현 계획·Step 실행을 지원하며, solver workflow 전체를 대신하지 않는다.
|
||||
|
||||
## 1. 핵심 구조
|
||||
|
||||
Harness Framework는 다음 세 계층으로 구성된다.
|
||||
|
||||
1. **계획 계층**: 승인된 요구사항과 Coordinator dispatch를 실행 가능한 Step으로 변환한다.
|
||||
2. **실행 계층**: Step Executor가 Step마다 독립 Codex 세션을 실행하고 상태와 Git
|
||||
커밋을 관리한다.
|
||||
3. **검증 계층**: PreToolUse 훅이 편집 전 정책을 검사하고, Stop 훅이 종료 전 MSVC
|
||||
빌드와 테스트를 실행한다. 유효한 문서 전용 편집 기록이면 조건부로 생략한다.
|
||||
|
||||
전체 흐름은 다음과 같다.
|
||||
메인 assistant가 관련 계약과 변경 범위를 확인하고 필요한 전문 작업만 위임한다.
|
||||
현재 역할과 사용자 결정 경계는 [Agent 운영](SOLVER_AGENT_DESIGN.md),
|
||||
문서 관리는 [Feature 문서 관리](FEATURE_DOCUMENTATION.md),
|
||||
운영 결정은 [ADR-028](ADR.md#adr-028)을 따른다.
|
||||
|
||||
```text
|
||||
사용자 요구사항
|
||||
↓
|
||||
Feature의 선행 계약·gate 확인
|
||||
↓
|
||||
Coordinator의 bounded Planning dispatch
|
||||
↓
|
||||
Planning Agent의 자기완결적 Step 작성
|
||||
↓
|
||||
phases/index.json, task index, stepN.md 생성
|
||||
↓
|
||||
실행까지 할당된 경우 Step Executor 시작
|
||||
↓
|
||||
각 Step을 독립 Codex 세션에서 실행
|
||||
├─ 도구 호출 전: PreToolUse 정책 검사
|
||||
└─ 응답 종료 전: Stop 검증 또는 문서 전용 조건부 생략
|
||||
↓
|
||||
성공: 커밋 후 다음 Step
|
||||
transport 실패: 최초 포함 최대 2회 시도
|
||||
구현 실패·차단: Coordinator로 반환
|
||||
관련 계약·현재 evidence 확인 → 변경 → 관련 test/build → 결과 확인
|
||||
│
|
||||
└─ 기능 완료 시 전체 build/test·필수 reference 비교
|
||||
```
|
||||
|
||||
자연어 요구사항이나 계획 요청만으로 Executor가 자동 시작되지는 않는다. 승인된 Feature와
|
||||
dispatch 안의 일반 계획 파일 작성·할당된 실행에 반복 승인 gate를 추가하지 않는다.
|
||||
권한 상승, 원격·파괴 작업, licensed reference solver 실행은 별도 명시적 승인이 필요하다.
|
||||
동작 변경에는 해당 의미를 확인하는 테스트를 추가·수정한다. 버그는 가능한 경우 실패를
|
||||
재현한 뒤 최소 수정한다. 충분한 기존 coverage가 있는 rename/refactor에는 형식적인
|
||||
새 테스트를 요구하지 않는다. 계획·소스·테스트·evidence는 할당된 범위 안에서 변경한다.
|
||||
|
||||
## 2. 요구사항 탐색과 구체화
|
||||
개발 중 focused check는 실제 configured backend 명령으로 수행한다.
|
||||
`python scripts/execute.py`는 구성된 전체 build/test를 한 번 실행한다. 사용자가 요청하거나
|
||||
넓은 변경 영향으로 전체 검증이 필요한 경우에도 실행하되, 이후 변경·실패가 없으면 반복하지
|
||||
않는다. 계획 작성만 요청받은 경우에는 실행하지 않는다.
|
||||
|
||||
예를 들어 사용자가 다음 요구사항을 전달했다고 가정한다.
|
||||
## 변경 종류별 검증
|
||||
|
||||
아래 Calculator 예시는 Harness Step 구조를 설명하기 위한 것으로 FESA 제품 요구사항이나
|
||||
새 기능 구현 지시가 아니다.
|
||||
| 작업 | 수행할 작업과 확인 |
|
||||
| --- | --- |
|
||||
| 문서 수정 | 관련 문서·소스·링크·diff 정적 확인. Solver build, 새 테스트, 별도 specialist 호출을 의무화하지 않음 |
|
||||
| 일반 구현 버그 | 메인 또는 기존 구현 owner가 가능한 실패 재현 → 최소 수정 → 관련 검사. 변경 영향·기능 완료 조건에 따라 전체 검증 |
|
||||
| 새 수치 기능 | 필요한 요구·정식화·I/O 정의, 독립 numerical review → 구현·관련 테스트 → 전체 build/test와 필수 analytical/invariant·물리·reference 검증 |
|
||||
|
||||
> CMake 기반 C++20 라이브러리에 `divide()` 함수를 추가하고, 0으로 나누면 예외를
|
||||
> 발생시키며 GoogleTest 테스트를 작성한다.
|
||||
수식·요소·재료·적분·상태 갱신 변경에는 독립 numerical review를 수행한다. 물리/수치
|
||||
검증은 각 계약에 따라 수행하며 역할이나 보고서 수를 줄였다는 이유로 생략하지 않는다.
|
||||
Release-readiness 감사는 명시적으로 요청할 때만 수행한다.
|
||||
|
||||
계획을 작성하기 전에 다음 자료를 확인한다.
|
||||
## Runner의 실행 순서
|
||||
|
||||
- `AGENTS.md`
|
||||
- `docs/PRD.md`
|
||||
- `docs/ARCHITECTURE.md`
|
||||
- `docs/ADR.md`
|
||||
- Coordinator dispatch와 `docs/<feature-id>/`의 승인된 선행 계약
|
||||
- 해당 Feature의 `FEATURED_AGENTS.md`, `PRD.md`, `ADR.md`
|
||||
- 관련 제품 코드와 테스트
|
||||
- `.harness/config.json`이 있으면 그 설정, 없으면 preset·metadata·프로젝트 지침과 감지 기본값
|
||||
[Runner](../scripts/execute.py)는 자신의 경로에서 저장소 root를 정한 뒤 아래를 수행한다.
|
||||
|
||||
이 탐색을 통해 다음 조건을 구체화한다.
|
||||
1. [Config](../scripts/msvc_harness/config.py)를 읽고 타입·허용 field·경로·preset 조합을 확인한다.
|
||||
2. [Discovery](../scripts/msvc_harness/discovery.py)가 명시된 projectType 또는 CMake/MSBuild metadata로 backend를 선택한다.
|
||||
3. [Toolchain](../scripts/msvc_harness/toolchain.py)이 필요한 Visual Studio/MSBuild·CMake/CTest 도구를 찾는다.
|
||||
4. 선택된 adapter가 argv·cwd·stage·timeout·결과 검사를 포함한 검증 계획을 만든다.
|
||||
5. [Process](../scripts/msvc_harness/process.py)가 명령을 순서대로 실행하고 각 결과를 검사한다.
|
||||
6. 성공 시 실행한 명령·cwd·exit code와 test 출력 요약을 반환한다. 실패 시 원인 진단과 nonzero를 반환한다.
|
||||
|
||||
- 사용하는 MSVC toolset과 C++ 표준
|
||||
- CMake 프로젝트인지 Visual Studio solution/project인지
|
||||
- 테스트 프레임워크와 테스트 실행 방법
|
||||
- public header와 implementation의 의존성 방향
|
||||
- 수정할 모듈과 범위 밖 항목
|
||||
- 실행 가능한 Acceptance Criteria 명령
|
||||
여기서 검증 계획은 backend 명령 목록이다. Feature phase/index/step 파일이나 LLM
|
||||
프롬프트가 아니다. Runner는 Git branch·HEAD·index를 관리하거나 Feature 문서를
|
||||
해석해 추가 명령을 생성하지 않는다.
|
||||
|
||||
필수 계약이 없으면 Coordinator를 통해 해당 owner로 반환한다. 예외 타입, 수치 타입,
|
||||
public API·ABI처럼 승인된 의미를 바꾸는 선택은 critical decision 기준에 따라 사용자에게
|
||||
올린다. 이미 승인된 계약 안의 파일 배치나 테스트 분해는 담당자가 결정한다.
|
||||
### Backend별 실행
|
||||
|
||||
## 3. 요구사항을 Step으로 분해
|
||||
| Backend | 실행과 결과 검사 |
|
||||
| --- | --- |
|
||||
| CMake/CTest | configure → compiler metadata의 MSVC 확인 → build → CTest JSON discovery/0개 거부 → test |
|
||||
| MSBuild | 선택된 solution/project build → 명시된 repository-relative testCommand 실행 |
|
||||
|
||||
사용자가 구현 계획 작성을 요청하면 요구사항을 작은 Step으로 나눈다. Step 설계
|
||||
규칙은 [Harness Workflow](../.agents/skills/harness/SKILL.md)에 정의되어 있다.
|
||||
FESA는 CMake/MSVC x64/Debug와 CTest를 제품 검증 기준으로 사용한다.
|
||||
MSBuild adapter가 있다는 사실이 solution-only 검증을 대체 승인하지 않는다.
|
||||
Preset 선택과 정확한 명령·설정 예시는 [Harness 운영 가이드](HARNESS.md)를 따른다.
|
||||
|
||||
각 Step은 다음 조건을 만족해야 한다.
|
||||
## 실행 경계와 실패 처리
|
||||
|
||||
- 하나의 모듈 또는 명확한 한 가지 책임만 다룬다.
|
||||
- 다른 대화 내용을 참조하지 않아도 실행할 수 있도록 자기완결적으로 작성한다.
|
||||
- 먼저 읽을 문서와 이전 Step의 관련 파일을 명시한다.
|
||||
- Feature 관리 문서와 승인된 선행 계약의 정확한 경로·revision을 명시한다.
|
||||
- 클래스와 함수 시그니처 수준으로 작업 범위를 설명한다.
|
||||
- 수정할 소스·테스트·보고서 파일과 수정하지 않을 upstream 파일을 명시한다.
|
||||
- 실제 실행 가능한 빌드·테스트 명령을 Acceptance Criteria로 사용한다.
|
||||
- 성공, 오류, 사용자 개입 필요 상태의 판정 기준을 적는다.
|
||||
- 범위 밖 기능과 기존 테스트 회귀를 명시적으로 금지한다.
|
||||
Config의 경로와 명령 cwd는 repository 범위 안인지 확인한다. MSBuild testCommand의
|
||||
실행 파일도 repository-relative 경로여야 한다. Subprocess는 argv 배열과 `shell=False`로
|
||||
실행하며 stdout/stderr를 수집한다. Config·preset·실행 파일 자체의 side effect까지 격리하는
|
||||
sandbox는 아니므로 실제 실행 입력과 도구 권한을 확인한다.
|
||||
|
||||
예시 Step은 다음과 같은 내용을 포함할 수 있다.
|
||||
전체 deadline은 시작부터 1,800초다. 각 명령의 timeout은 남은 전체 시간과 명령별 제한 중
|
||||
짧은 값이며, 실행 전 남은 시간이 없으면 실패한다. Backend nonzero, timeout, MSVC 확인
|
||||
실패나 CTest 0개 등 결과 검사 실패가 발생하면 후속 단계를 실행하지 않는다.
|
||||
|
||||
```text
|
||||
Step 0: division-api
|
||||
명령 실패 진단에는 stage·argv·cwd, 가능한 원래 exit code와 출력 tail이 포함된다.
|
||||
현재 구현 owner가 원인을 확인하고 필요한 수정 또는 환경 조치 후 관련 검사를 수행한다.
|
||||
새 근거나 변경 없이 같은 명령·agent 호출을 반복하지 않으며 자동 transport retry나
|
||||
별도 correction 예산은 없다.
|
||||
|
||||
읽어야 할 파일
|
||||
- AGENTS.md
|
||||
- include/calculator.hpp
|
||||
- src/calculator.cpp
|
||||
- tests/calculator_test.cpp
|
||||
Runner는 성공 시 exit 0, config/toolchain/backend 등 실행 실패 시 exit 1을 반환한다.
|
||||
자동 감지에서 metadata가 없거나 CLI 인자가 잘못되면 exit 2다. 명시된 projectType에 필요한
|
||||
metadata가 없는 경우는 exit 1이다. Backend 원래 nonzero와 runner exit를 구분한다.
|
||||
전체 목록은 [결과와 실패 진단](HARNESS.md#결과와-실패-진단)을 참조한다.
|
||||
|
||||
작업
|
||||
- divide(double lhs, double rhs)의 실패 테스트를 먼저 추가한다.
|
||||
- rhs가 0이면 std::invalid_argument가 발생하도록 최소 구현한다.
|
||||
## 수치 evidence와 완료 확인
|
||||
|
||||
Acceptance Criteria
|
||||
- CMake/MSBuild 빌드가 성공한다.
|
||||
- 전체 테스트가 성공한다.
|
||||
- 새로운 컴파일러 경고가 없다.
|
||||
```
|
||||
Harness 성공은 build/test 실행 결과다. 필요한 reference comparison을 자동 탐색하거나
|
||||
솔버 correctness 전체를 판정하지 않는다. 메인·구현 담당자는 계약이 요구하는 다음
|
||||
검증을 별도로 확인한다.
|
||||
|
||||
### TDD와 Step 경계
|
||||
- Unit·coordinate·부호·DOF/component·source identity와 결과 위치의 일치
|
||||
- Analytical solution, invariant·equilibrium·energy·convergence 등 적용되는 검증
|
||||
- Missing·extra·duplicate·nonfinite required row를 tolerance 전에 거부하는 비교
|
||||
- [TOLERANCE](TOLERANCE.md)와 승인된 Feature의 비교량·판정 구분
|
||||
- Trial/committed state·실패 보존·결정론과 필요한 독립 물리 판단
|
||||
|
||||
프로젝트 규칙은 실패하는 테스트를 먼저 요구하지만 Stop 훅은 Codex가 Step을 종료할
|
||||
때 전체 테스트 성공을 요구한다. 따라서 다음처럼 실패 상태를 Step 사이에 남겨둘 수
|
||||
없다.
|
||||
Reference artifact와 tolerance를 통과에 맞춰 수정하지 않는다. 명령·exit code와 결정적
|
||||
판정값은 필요한 보고서에 한 번 기록하고 원시 로그는 원본 경로로 연결한다. 실패·미실행·
|
||||
stale evidence와 미해결 항목을 명확히 남기며 검사를 생략한 사실을 통과로 보고하지 않는다.
|
||||
|
||||
```text
|
||||
Step 0: 실패하는 테스트만 추가하고 종료
|
||||
Step 1: 제품 코드를 구현해 테스트 통과
|
||||
```
|
||||
## 과거 phase·hook·Git 처리
|
||||
|
||||
실제 red-green 순서는 하나의 Codex 실행 안에서 완료되어야 한다.
|
||||
현재 runner는 내부 Codex 세션, phase 상태기계·result payload, `owned_paths`·
|
||||
`attempt_history`, 자동 branch/commit/push, PreToolUse/Stop을 사용하지 않는다.
|
||||
`coordination.md`와 기존 phase·hook 기록은 이력으로 보존하고 새 실행 입력으로 만들지 않는다.
|
||||
|
||||
```text
|
||||
테스트 작성
|
||||
→ 테스트 실패 확인
|
||||
→ 최소 제품 코드 구현
|
||||
→ 테스트 성공 확인
|
||||
→ Step 종료
|
||||
```
|
||||
|
||||
즉, 테스트가 구현보다 먼저 작성되는 순서는 지키되 각 Step은 최종적으로 green
|
||||
상태여야 한다.
|
||||
|
||||
## 4. 할당된 계획 산출물
|
||||
|
||||
Planning Agent는 Coordinator가 할당한 다음 파일을 생성한다. 기존 산출물을 재개할 때는
|
||||
덮어쓰지 않고 승인된 변경 범위만 갱신한다. Step 번호는 0부터 연속으로 둔다.
|
||||
|
||||
```text
|
||||
phases/
|
||||
├── index.json
|
||||
└── add-division/
|
||||
├── index.json
|
||||
├── step0.md
|
||||
├── step1.md
|
||||
└── ...
|
||||
```
|
||||
|
||||
### 4.1 Top-level index
|
||||
|
||||
`phases/index.json`은 여러 task의 상태를 관리한다.
|
||||
|
||||
```json
|
||||
{
|
||||
"phases": [
|
||||
{
|
||||
"dir": "add-division",
|
||||
"status": "pending"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 Task index
|
||||
|
||||
`phases/add-division/index.json`은 task 내부 Step의 상태를 관리한다.
|
||||
|
||||
```json
|
||||
{
|
||||
"project": "Calculator",
|
||||
"phase": "add-division",
|
||||
"steps": [
|
||||
{
|
||||
"step": 0,
|
||||
"name": "division-api",
|
||||
"status": "pending",
|
||||
"owned_paths": ["include/calculator.hpp", "src/calculator.cpp", "tests/calculator_test.cpp"]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
상태별 기록은 다음과 같이 나뉜다.
|
||||
|
||||
`owned_paths`는 Planning이 작성하는 정확한 저장소 상대 파일 목록이다. Step 본문의 소유
|
||||
파일과 일치해야 하며 source/header/test/build/report를 필요한 만큼 명시한다. 디렉터리,
|
||||
glob, 절대 경로, 경로 이탈, Git 내부와 `phases/` 제어 경로는 허용하지 않는다. 연결된
|
||||
파일·디렉터리 경로도 지원하지 않는다. `[]`는 구현 파일 변경 없음이며 누락과 다르다.
|
||||
기존 완료 Step은 필드 없이 읽을 수 있지만 모든 pending Step은 실행 전에 목록이 필요하다.
|
||||
기존 phase를 일괄 변환하거나 Markdown에서 파일 권한을 자동 추출하지 않는다.
|
||||
|
||||
| 상태 | Codex가 기록 | Executor가 기록 |
|
||||
|---|---|---|
|
||||
| `completed` | `summary` | `completed_at` |
|
||||
| `error` | `error_message` | `failed_at` |
|
||||
| `blocked` | `blocked_reason` | `blocked_at` |
|
||||
|
||||
Executor는 task의 `created_at`과 Step의 `started_at`, `attempt_history`도 기록한다.
|
||||
History에는 단조 증가하는 `attempt`, `recorded_at`, `exit_code`(프로세스 미기동은 null),
|
||||
`reported_status`, `reported_reason`, 로컬 `classification`·판정 `reason`과 `diagnostic`을 보존한다.
|
||||
진단은 stderr 우선, 없으면 stdout의 마지막 4,000자이며 raw output 전체의 대체가 아니다.
|
||||
Implementation은 `owned_paths`·history·timestamp를 수정할 수 없다. `summary`는 다음
|
||||
독립 Codex 세션이 이전 Step의 핵심 산출물과 결정을 이해할 수 있도록 한 줄로
|
||||
작성한다.
|
||||
|
||||
### 4.3 Step 파일
|
||||
|
||||
각 `stepN.md`에는 다음 내용이 들어간다.
|
||||
|
||||
- 읽어야 할 파일
|
||||
- 작업 범위와 인터페이스
|
||||
- 핵심 동작 및 불변 조건
|
||||
- Acceptance Criteria 명령
|
||||
- 아키텍처·ADR·CRITICAL 규칙 확인 절차
|
||||
- 성공, 오류, 차단 상태 기록 방법
|
||||
- 범위 밖 변경 금지사항
|
||||
|
||||
Step은 독립 Codex 실행의 전체 작업 지시서이므로 이전 대화만 참조하는 표현을 넣지
|
||||
않는다.
|
||||
|
||||
## 5. Step Executor 시작
|
||||
|
||||
계획 파일이 준비되고 실행까지 할당된 경우 다음 명령으로 실행한다.
|
||||
|
||||
```powershell
|
||||
python scripts/execute.py add-division
|
||||
```
|
||||
|
||||
완료된 브랜치의 원격 push를 사용자가 명시적으로 승인한 경우에만 `--push`를 추가한다.
|
||||
|
||||
```powershell
|
||||
python scripts/execute.py add-division --push
|
||||
```
|
||||
|
||||
[Step Executor](../scripts/execute.py)는 시작할 때 다음 작업을 수행한다.
|
||||
|
||||
1. phase 경로와 top-level/phase index schema, Step 번호·이름·상태를 검사한다.
|
||||
2. 현재 첫 미완료 Step이 `error` 또는 `blocked`이면 복구 결정 전까지 중단한다.
|
||||
3. 모든 pending Step의 `owned_paths`, Implementation Agent profile, Git top-level,
|
||||
sandbox 승인 조건과 clean 상태를 검사한다.
|
||||
기본 모드는 선택된 phase 제어 파일 allowlist 밖의 변경을 허용하지 않는다.
|
||||
4. `feat-{phase-name}` 브랜치를 생성하거나 checkout한다.
|
||||
5. `AGENTS.md`와 `docs/*.md`를 guardrail로 읽는다.
|
||||
6. task/Step timestamp와 재개 상태를 정리하고 첫 번째 `pending` Step부터 순차 실행한다.
|
||||
|
||||
`AGENTS.md`와 모든 `docs/*.md` 내용은 각 Codex 프롬프트에 직접 삽입된다. 따라서
|
||||
이 문서들도 실행 입력에 포함된다. 역할·승인·상태 전이에서는 Agent 계약과 Harness skill의
|
||||
권한 경계를 따르며, 설치 예시를 Feature의 요구사항으로 사용하지 않는다. Feature 관리
|
||||
문서는 자동으로 로드되지 않으므로 dispatch와 Step의 필수 입력 경로에 명시해야 한다.
|
||||
|
||||
## 6. Step마다 독립 Codex 세션 실행
|
||||
|
||||
Executor는 각 Step을 다음 형태의 독립 프로세스로 실행한다.
|
||||
|
||||
```text
|
||||
codex exec
|
||||
--disable unified_exec
|
||||
--json
|
||||
--model <implementation-agent profile model>
|
||||
--config model_reasoning_effort="<profile effort>"
|
||||
--sandbox <workspace-write|danger-full-access>
|
||||
--dangerously-bypass-hook-trust
|
||||
--cd <repository-root>
|
||||
-
|
||||
```
|
||||
|
||||
기본값은 `workspace-write`다. `FEM_HARNESS_CODEX_SANDBOX` 환경 변수는
|
||||
`workspace-write` 또는 `danger-full-access`만 허용한다. Windows native sandbox에서
|
||||
MSVC compiler-id의 `cl.exe` 정지가 재현되고 동일 명령이 sandbox 밖에서 통과하는
|
||||
환경에서는, 해당 실행 직전 사용자 승인을 받은 clean linked Git worktree 실행에 한해서
|
||||
`danger-full-access` fallback을 사용할 수 있다. Executor의
|
||||
`--approve-danger-full-access` flag도 필요하며 환경변수만으로 승인되지 않는다.
|
||||
이 override는 등록된 hook을 비활성화하지 않는다.
|
||||
|
||||
Codex에 전달하는 프롬프트는 다음 내용의 조합이다.
|
||||
|
||||
```text
|
||||
Implementation Agent profile의 역할·수정 경계
|
||||
+ AGENTS.md와 docs 문서
|
||||
+ 이전에 완료된 Step의 summary
|
||||
+ 이전 시도의 오류(재시도인 경우)
|
||||
+ Executor 공통 작업 규칙
|
||||
+ 현재 stepN.md
|
||||
```
|
||||
|
||||
이전 Step의 전체 대화나 Codex 세션은 전달하지 않는다. task index에 기록한
|
||||
`summary`만 다음 Step에 누적한다.
|
||||
|
||||
Codex 실행 결과의 exit code, stdout, stderr는 다음 파일에 저장한다.
|
||||
|
||||
```text
|
||||
phases/{task-name}/step{N}-output.json
|
||||
```
|
||||
|
||||
## 7. 도구 호출 전 PreToolUse 검사
|
||||
|
||||
[`.codex/hooks.json`](../.codex/hooks.json)은 shell 및 파일 편집 도구에
|
||||
[PreToolUse 훅](../scripts/hooks/pre_tool_use.py)을 등록한다. Codex가 실제 명령이나
|
||||
편집을 수행하기 전에 이 훅이 요청을 검사한다.
|
||||
|
||||
### 7.1 위험 명령 차단
|
||||
|
||||
다음 유형의 명령은 요구사항과 관계없이 차단한다.
|
||||
|
||||
- `git reset --hard`
|
||||
- `git push --force` 또는 `--force-with-lease`
|
||||
- `rm -rf`
|
||||
- `Remove-Item -Recurse -Force`
|
||||
- `rmdir /s /q`
|
||||
- `DROP TABLE`
|
||||
|
||||
위험 패턴이 발견되면 훅은 차단 이유를 stderr로 출력하고 종료 코드 2를 반환한다.
|
||||
그러면 해당 도구 호출은 실행되지 않는다.
|
||||
|
||||
### 7.2 C++ TDD 검사
|
||||
|
||||
`apply_patch`, `Edit`, `MultiEdit`, `Write`로 다음 C/C++ 확장자의 파일을 편집하려
|
||||
하면 [TDD 정책](../scripts/msvc_harness/tdd_policy.py)을 검사한다.
|
||||
|
||||
```text
|
||||
.c .cc .cpp .cxx .h .hpp .hxx
|
||||
```
|
||||
|
||||
일반 제품 코드를 수정하려면 대응되는 테스트 파일이 먼저 존재해야 한다. 예를 들어
|
||||
`src/calculator.cpp`의 기본 대응 테스트 이름은 다음과 같다.
|
||||
|
||||
```text
|
||||
calculator_test.cpp
|
||||
calculator_tests.cpp
|
||||
test_calculator.cpp
|
||||
calculator.test.cpp
|
||||
```
|
||||
|
||||
테스트는 다음 위치에서 검색한다.
|
||||
|
||||
- `.harness/config.json`의 `tdd.testRoots`
|
||||
- 제품 파일과 같은 디렉터리 아래 `tests/`
|
||||
- 제품 파일과 같은 디렉터리 아래 `test/`
|
||||
|
||||
다음 파일과 디렉터리는 대응 테스트 존재 검사가 면제된다.
|
||||
|
||||
- 테스트 파일 자체
|
||||
- `main.cpp`
|
||||
- `.harness/build/**`, `build/**`, `out/**`
|
||||
- `cmake-build-*/**`
|
||||
- `third_party/**`, `external/**`, `vendor/**`
|
||||
- `generated/**`
|
||||
- `tdd.exclude`에 추가한 경로
|
||||
|
||||
`tdd.exclude`는 기본 제외 항목을 대체하지 않고 추가한다.
|
||||
|
||||
### 7.3 TDD 검사가 보장하는 범위
|
||||
|
||||
현재 TDD 훅이 직접 보장하는 것은 대응되는 이름의 테스트 파일이 존재한다는
|
||||
사실이다. 다음 항목까지 증명하지는 않는다.
|
||||
|
||||
- 테스트가 이번 요구사항을 실제로 검증하는가
|
||||
- 구현 전에 테스트가 실제로 실패했는가
|
||||
- 테스트의 assertion과 경계 조건이 충분한가
|
||||
- 기존 테스트 파일을 이번 변경과 함께 수정했는가
|
||||
|
||||
또한 shell 명령의 리다이렉션 등으로 C++ 파일을 쓰는 경우 shell 위험 패턴 검사는
|
||||
적용되지만 경로 기반 TDD 검사는 적용되지 않는다. 따라서 이 훅은 완전한 TDD
|
||||
증명기가 아니라 테스트 우선 편집을 유도하는 guardrail이다.
|
||||
|
||||
PreToolUse는 허용된 편집 도구의 대상 경로를 `.harness/hook-state/`에 기록한다.
|
||||
이 ignored 기록은 Stop의 문서 전용 판정 입력일 뿐 RED나 실제 편집 성공의 증거가 아니다.
|
||||
|
||||
## 8. Codex 종료 전 Stop 검증
|
||||
|
||||
Codex가 Step 작업을 끝내고 응답을 종료하려 하면
|
||||
[Stop 훅](../scripts/hooks/stop_validation.py)이 실행된다. 유효한 동일 session/turn 기록에서
|
||||
편집 대상이 모두 저장소 내부 `.md`이면 build/test를 생략한다. 기록 누락·손상 또는 비문서
|
||||
편집이면 정상 검증 경로에서 발견된 C/C++ 프로젝트 전체를 빌드하고 테스트한다.
|
||||
|
||||
Shell 쓰기는 완전히 추적되지 않으며, 편집 기록 없는 읽기 전용 요청도 자동 생략을
|
||||
보장하지 않는다. 사용자가 문서 작업의 실행을 제외하면 수동 Hook·build/test를 실행하지
|
||||
않고 정적 검토 범위와 미실행 항목을 보고한다. Hook state를 조작해 생략을 만들지 않는다.
|
||||
|
||||
### 8.1 저장소 루트와 재진입 방지
|
||||
|
||||
Stop 훅은 `git rev-parse --show-toplevel`로 프로젝트 루트를 결정한다. Git 저장소를
|
||||
찾을 수 없으면 현재 디렉터리를 사용한다.
|
||||
|
||||
빌드나 테스트의 자식 프로세스에는 `CODEX_STOP_VALIDATION_ACTIVE=1`을 전달한다.
|
||||
같은 훅이 자식 프로세스에서 다시 진입하면 즉시 성공 처리하여 검증 재귀를 막는다.
|
||||
|
||||
### 8.2 설정 로드
|
||||
|
||||
[설정 로더](../scripts/msvc_harness/config.py)는 `.harness/config.json`을 읽는다.
|
||||
파일이 없으면 다음 기본값을 사용한다.
|
||||
|
||||
- `version`: 1
|
||||
- `projectType`: `auto`
|
||||
- CMake source: 저장소 루트
|
||||
- preset 미사용 시 binary directory: `.harness/build`
|
||||
- configuration: `Debug`
|
||||
- platform: `x64`
|
||||
- 테스트 루트: `tests`, `test`
|
||||
- 기본 테스트 이름 패턴 네 개
|
||||
|
||||
설정은 다음 조건을 엄격하게 검사한다.
|
||||
|
||||
- 알 수 없는 필드를 거부한다.
|
||||
- `version`은 숫자 1만 허용한다.
|
||||
- `projectType`은 `auto`, `cmake`, `msbuild`만 허용한다.
|
||||
- 저장소 상대 경로만 허용한다.
|
||||
- 저장소 밖으로 해석되는 경로를 거부한다.
|
||||
- CMake preset을 사용하면 `configurePreset`, `buildPreset`, `testPreset`,
|
||||
`binaryDir`를 모두 요구한다.
|
||||
- 모든 `tdd.testPatterns`에 `{stem}`을 요구한다.
|
||||
|
||||
### 8.3 프로젝트 자동 감지
|
||||
|
||||
[프로젝트 탐색기](../scripts/msvc_harness/discovery.py)는 다음 순서로 프로젝트를
|
||||
선택한다.
|
||||
|
||||
1. `projectType: cmake` 또는 `projectType: msbuild` 명시 설정
|
||||
2. 루트의 `CMakePresets.json`
|
||||
3. 루트의 `CMakeUserPresets.json`
|
||||
4. 루트의 `CMakeLists.txt`
|
||||
5. 루트의 단일 `.sln`
|
||||
6. 루트의 단일 `.vcxproj`
|
||||
|
||||
자동 감지 결과는 다음처럼 처리한다.
|
||||
|
||||
| 저장소 상태 | 결과 |
|
||||
|---|---|
|
||||
| CMake metadata가 있음 | CMake 프로젝트 선택 |
|
||||
| 하나의 `.sln` 또는 `.vcxproj`가 있음 | MSBuild 프로젝트 선택 |
|
||||
| 여러 solution/project가 있음 | 설정으로 하나를 지정하라는 오류 |
|
||||
| C/C++ 파일과 build metadata가 모두 없음 | 검증할 프로젝트가 없으므로 통과 |
|
||||
| C/C++ 파일은 있지만 build metadata가 없음 | orphan C++ 프로젝트 오류 |
|
||||
|
||||
### 8.4 MSVC 도구 탐색
|
||||
|
||||
[도구 탐색기](../scripts/msvc_harness/toolchain.py)는 `vswhere.exe`로 다음을
|
||||
확인한다.
|
||||
|
||||
- Visual Studio 설치 경로
|
||||
- Desktop development with C++ workload
|
||||
- `MSBuild.exe`
|
||||
|
||||
CMake 프로젝트에서는 다음 우선순위로 CMake와 CTest를 선택한다.
|
||||
|
||||
1. PATH에서 발견한 독립 `cmake.exe`와 `ctest.exe`
|
||||
2. Visual Studio에 번들된 CMake와 CTest
|
||||
|
||||
따라서 새로 설치한 CMake의 `bin` 디렉터리가 PATH에 반영되어 있으면 독립 CMake를
|
||||
우선 사용한다.
|
||||
|
||||
## 9. 빌드 시스템별 검증 계획
|
||||
|
||||
### 9.1 CMake preset 미사용
|
||||
|
||||
[CMake adapter](../scripts/msvc_harness/adapters/cmake.py)는 다음 검증 계획을 만든다.
|
||||
|
||||
```powershell
|
||||
cmake -S <source> -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
|
||||
```
|
||||
|
||||
명령 성공 외에 다음 결과도 검사한다.
|
||||
|
||||
- 생성된 CMake compiler metadata의 `CMAKE_CXX_COMPILER_ID`가 `MSVC`인가
|
||||
- CTest JSON에 한 개 이상의 테스트가 있는가
|
||||
|
||||
따라서 빌드가 성공해도 MinGW 등 다른 컴파일러를 사용했거나 CTest가 테스트를 한
|
||||
개도 발견하지 못하면 실패한다.
|
||||
|
||||
### 9.2 CMake preset 사용
|
||||
|
||||
`.harness/config.json`에 preset을 완전히 지정하면 다음 형태로 실행한다.
|
||||
|
||||
```powershell
|
||||
cmake --preset <configurePreset>
|
||||
cmake --build --preset <buildPreset>
|
||||
ctest --preset <testPreset> --show-only=json-v1
|
||||
ctest --preset <testPreset> --output-on-failure
|
||||
```
|
||||
|
||||
이 경우 모든 명령은 `cmake.sourceDir`에서 실행하고 compiler metadata 검사는 설정한
|
||||
`binaryDir`에서 수행한다.
|
||||
|
||||
### 9.3 직접 MSBuild
|
||||
|
||||
[MSBuild adapter](../scripts/msvc_harness/adapters/msbuild.py)는 다음 순서로 실행한다.
|
||||
|
||||
```powershell
|
||||
MSBuild.exe <solution-or-vcxproj> /m /nologo `
|
||||
/p:Configuration=<configuration> `
|
||||
/p:Platform=<platform>
|
||||
|
||||
<msbuild.testCommand>
|
||||
```
|
||||
|
||||
직접 MSBuild 프로젝트는 표준 테스트 탐색 명령이 없으므로
|
||||
`.harness/config.json`의 `msbuild.testCommand`가 반드시 필요하다. 이 값이 없으면
|
||||
Stop 검증이 실패한다.
|
||||
|
||||
## 10. 명령 실행 안전성과 제한시간
|
||||
|
||||
[검증 실행기](../scripts/msvc_harness/process.py)는 다음 안전 규칙을 적용한다.
|
||||
|
||||
- 명령을 shell 문자열이 아닌 argv 배열로 실행한다.
|
||||
- `shell=False`를 사용한다.
|
||||
- 각 명령의 working directory가 저장소 내부인지 검사한다.
|
||||
- 명령별 제한시간과 Stop 전체 제한시간 중 더 짧은 값을 적용한다.
|
||||
- 종료 코드가 0이 아니면 즉시 해당 stage를 실패 처리한다.
|
||||
|
||||
Stop 훅의 전체 제한시간은 저장소 탐색, toolchain 탐색, configure, build, test discovery,
|
||||
test를 모두 포함해 1,800초다. `.codex/hooks.json`의 Stop command timeout도 1,800초다.
|
||||
|
||||
실패 메시지에는 다음 진단 정보를 포함한다.
|
||||
|
||||
- 실패 stage
|
||||
- 안전하게 표현한 argv 배열
|
||||
- working directory
|
||||
- 종료 코드
|
||||
- stdout과 stderr의 마지막 8,000자
|
||||
|
||||
Harness는 별도 빌드 로그 파일을 생성하지 않는다.
|
||||
|
||||
## 11. 성공, 실패, 차단 처리
|
||||
|
||||
### 11.1 Stop 검증 성공
|
||||
|
||||
빌드와 테스트가 모두 성공하거나 문서 전용 생략 조건을 충족하면 Stop 훅은 출력 없이
|
||||
종료한다. 생략은 build/test 통과 evidence가 아니다. Codex가 정상 종료하면 Executor는
|
||||
branch/HEAD, 제어 파일과 현재 Step 외 상태의 변경 여부를 검사하고 task index를 읽는다.
|
||||
Codex 종료 코드가 0이 아니면 `completed` 기록만으로 성공 처리하지 않는다.
|
||||
|
||||
Codex가 Step을 다음처럼 기록한 경우:
|
||||
|
||||
```json
|
||||
{
|
||||
"step": 0,
|
||||
"name": "division-api",
|
||||
"status": "completed",
|
||||
"owned_paths": ["include/calculator.hpp", "src/calculator.cpp", "tests/calculator_test.cpp"],
|
||||
"summary": "divide API와 0 나누기 테스트를 추가함"
|
||||
}
|
||||
```
|
||||
|
||||
Executor는 `completed_at`을 기록하고 변경사항을 커밋한 뒤 다음 `pending` Step을
|
||||
실행한다.
|
||||
|
||||
### 11.2 Stop 검증 실패
|
||||
|
||||
Stop 훅은 Codex hook protocol에 따라 다음 형태의 응답을 출력한다.
|
||||
|
||||
```json
|
||||
{
|
||||
"decision": "block",
|
||||
"reason": "build failed ..."
|
||||
}
|
||||
```
|
||||
|
||||
훅 자체의 종료 코드는 0이지만 `decision: block`이 종료 차단 이유를 전달한다.
|
||||
수정은 할당된 역할·Step·retry budget 안에서만 수행하며, Hook 실패가 상위 계약 변경이나
|
||||
무제한 반복 권한을 주지 않는다.
|
||||
|
||||
### 11.3 Executor 재시도
|
||||
|
||||
Executor는 branch/HEAD·제어 파일·결과 형식과 변경 경로의 소유권을 먼저 검증한 뒤
|
||||
Step 보고와 프로세스 종료 코드를 함께 판정한다.
|
||||
|
||||
| 결과 | 처리 | 자동 재시도 |
|
||||
| --- | --- | --- |
|
||||
| 인식된 sandbox helper 환경 오류(종료 코드 무관), CLI 미설치 | Step과 상위 phase `blocked`, 종료 2 | 없음 |
|
||||
| 명시적 `blocked` 또는 `error`(종료 코드 무관) | 원래 사유 보존, 각각 종료 2 또는 1 | 없음 |
|
||||
| `completed` + 종료 0 | 소유권·staged 경로 검증 후 커밋 | 없음 |
|
||||
| `completed` + nonzero | `error`, 종료 1 | 없음 |
|
||||
| 결과 미보고 + Executor wrapper의 실제 `TimeoutExpired` | transport timeout | 최초 포함 최대 2회 |
|
||||
| 결과 미보고 + 종료 0, 원인 미분류 nonzero | `error`, 종료 1 | 없음 |
|
||||
|
||||
종료 코드 124만으로 timeout을 추정하지 않는다. Wrapper가 실제 timeout을 관찰했을 때만
|
||||
raw output에 `transportFailure: "timeout"`을 기록한다. 제어·소유권 위반은 이 재시도보다
|
||||
우선하여 중단한다. 실패 결과를 `pending`으로 덮어쓰지 않고 원래 보고와 프로세스 진단을
|
||||
Executor 소유 history에 구분해 남긴다.
|
||||
|
||||
```text
|
||||
첫 번째 transport 시도 실패
|
||||
→ 오류를 다음 프롬프트에 삽입
|
||||
→ 두 번째 독립 Codex 실행
|
||||
→ 두 번째도 실패하면 error 기록 후 종료
|
||||
```
|
||||
|
||||
Coordinator의 workflow correction은 별도 budget이다. 정규화된
|
||||
`feature_id|failing_gate|failure_classification|contract_revision`별로 Correction을 최대
|
||||
한 번, 그 뒤 Implementation rerun을 한 번만 허용한다. 계약·환경·물리 실패를 transport
|
||||
재시도로 숨기거나 문구만 바꾸어 새 retry key를 만들지 않는다.
|
||||
|
||||
### 11.4 사용자 개입 필요
|
||||
|
||||
인증, API 키, 수동 설치처럼 Codex가 자동으로 해결할 수 없는 문제가 있으면 Step을
|
||||
`blocked`로 기록한다. Executor는 `blocked_at`과 top-level 상태를 갱신하고 종료 코드
|
||||
2로 중단한다.
|
||||
|
||||
재개 전 Coordinator가 원인 분류, 실패 evidence, retry key와 허용된 다음 작업을
|
||||
`coordination.md`에 보존한다. Coordinator는 phase 파일을 직접 편집하지 않는다.
|
||||
명시적으로 할당받은 Planning Agent가 Executor가 중단된 상태에서 phase index의 현재
|
||||
실패/차단 Step status만 `pending`으로 변경한다. 다른 Step, top-level 상태와 timestamp는
|
||||
변경하지 않는다. Executor가 재시작 시 오래된 outcome 필드·timestamp를 정리하되
|
||||
`attempt_history`는 유지한다. 기존 Step에 `owned_paths`가 없으면 승인 목록을 작성하는
|
||||
별도 Planning 할당이 필요하며 status 복구 권한만으로 목록을 추가·확대하지 않는다.
|
||||
이는 할당된 파일 편집 절차이며 자동 복구 명령이나 추가 correction 허용이 아니다.
|
||||
|
||||
## 12. Git 커밋과 phase 완료
|
||||
|
||||
Step이 성공하면 제품 변경과 Harness metadata를 분리해 다음 형식으로 커밋한다.
|
||||
|
||||
```text
|
||||
feat(add-division): step 0 - division-api
|
||||
chore(add-division): step 0 output
|
||||
```
|
||||
|
||||
두 번째 커밋의 `output`은 task index의 Step 상태와 summary 같은 Harness metadata를
|
||||
뜻한다. 원시 Codex 실행 기록인 `stepN-output.json`은 `.gitignore` 대상이며 커밋에
|
||||
포함되지 않는다.
|
||||
|
||||
모든 Step이 완료되면 Executor는 다음 작업을 수행한다.
|
||||
|
||||
- task의 `completed_at` 기록
|
||||
- `phases/index.json`의 task 상태를 `completed`로 변경
|
||||
- 최종 metadata 커밋
|
||||
- `--push` 사용 시 `origin/feat-{phase-name}`으로 push
|
||||
|
||||
Executor는 신뢰된 `owned_paths` snapshot으로 매 시도 후와 staging 직전의 변경 경로를
|
||||
검사한다. tracked/untracked, staged/unstaged, 생성·수정·삭제와 rename 양쪽 경로가 대상이다.
|
||||
Windows 경로 구분자·대소문자 alias를 정규화하며 디렉터리·링크 대체도 다시 검사한다.
|
||||
범위 밖 변경이 있으면 index를 정리하기 전에 중단하고 해당 경로와 사용자 파일을 보존한다.
|
||||
|
||||
검사 후 검증된 경로 snapshot에 한정해 index만 정리하고
|
||||
`git --literal-pathspecs add -A -- <선택 경로>`를 사용한다. 저장소 전체 index를 reset하지 않는다.
|
||||
Commit 직전에는 `git diff --cached --name-only --no-renames -z`의 실제 staged 경로도
|
||||
선택된 커밋 그룹과 대조한다. 구현 커밋에 phase metadata가 섞이는 것도 거부한다.
|
||||
범위 위반 시 추가 stage/commit·재시도·다음 Step을 중단하며 파일을 되돌리거나 allowlist를
|
||||
자동 확대하지 않는다. staging 후 발견한 위반은 당시 index를 남기므로 재개 전 검토가 필요하다.
|
||||
|
||||
동시 writer에 대한 원자적 격리는 보장하지 않으므로 실행 중 동시 편집을 피한다. 구현·metadata
|
||||
커밋도 단일 transaction이 아니다. 구현 커밋 후 metadata 커밋이 실패하면 기존 커밋을
|
||||
되돌리지 않고 Step을 `error`로 기록해 Coordinator에 반환한다.
|
||||
|
||||
## 13. 요구사항 종류별 동작
|
||||
|
||||
| 받은 요구사항 또는 변경 | PreToolUse 동작 | Stop 동작 |
|
||||
|---|---|---|
|
||||
| 새 C++ 제품 파일 추가 | 대응 테스트가 먼저 없으면 차단 | 전체 빌드·테스트 |
|
||||
| 기존 C++ 구현 또는 header 수정 | 대응 테스트 파일 존재 여부 검사 | 전체 빌드·테스트 |
|
||||
| 테스트 파일 추가 | TDD 차단 없이 허용 | 모든 테스트가 성공해야 종료 |
|
||||
| `main.cpp` 수정 | TDD 대응 테스트 검사 면제 | 전체 빌드·테스트 |
|
||||
| 유효한 동일 session/turn 기록의 내부 `.md` 편집만 있음 | C++ TDD 검사 없이 경로 기록 | build/test 생략, 통과 evidence 아님 |
|
||||
| JSON, Python 또는 다른 비문서 편집 | C++ TDD 검사 없음 | C++ 프로젝트가 있으면 전체 검증 |
|
||||
| 편집 기록 없음·손상 또는 shell 쓰기 | 완전한 편집 추적을 보장하지 않음 | 문서 전용 자동 생략을 보장하지 않음 |
|
||||
| 위험한 Git 또는 삭제 명령 | 즉시 차단 | 도달하지 않음 |
|
||||
| C++ 파일은 있지만 build metadata 없음 | 편집은 허용될 수 있음 | orphan 프로젝트 오류 |
|
||||
| 직접 MSBuild인데 `testCommand` 없음 | 편집은 허용될 수 있음 | 설정 오류로 종료 차단 |
|
||||
| C/C++가 전혀 없는 저장소 | 관련 편집 검사 없음 | 검증할 프로젝트가 없어 통과 |
|
||||
|
||||
## 14. 적용 전 준비사항
|
||||
|
||||
FESA는 실제 구조해석 솔버 프로젝트이며 Harness는 재사용 가능한 개발 운영 인프라다.
|
||||
일반 Feature 실행 전에 다음을 확인한다.
|
||||
|
||||
1. `AGENTS.md`, 공통 PRD·ARCHITECTURE·ADR와 승인된 Feature 범위를 읽는다.
|
||||
2. Feature 관리 문서·선행 계약·revision과 Planning/Implementation dispatch를 확인한다.
|
||||
일반 Feature 작업에서 프로젝트 공통 문서를 템플릿처럼 다시 작성하지 않는다.
|
||||
3. 기본 자동 감지로 충분하지 않을 때만 `.harness/config.example.json`을 참고해
|
||||
`.harness/config.json`을 만든다.
|
||||
4. FESA의 CMake/MSVC x64 Debug·CTest 명령과 dependency 경로를 확인한다. 다른 저장소에
|
||||
Harness를 적용할 때만 그 프로젝트의 승인된 adapter를 선택한다.
|
||||
5. phase 파일이 없다면 Planning Agent가 할당된 파일을 작성한다. 실행 권한은 별도로 확인한다.
|
||||
6. 시작 전 clean 범위와 실행 중 동시 편집 여부를 확인한다. 권한 상승은 clean linked
|
||||
worktree, native sandbox 실패 증거와 해당 실행 직전 승인·flag가 모두 필요하다.
|
||||
|
||||
특히 `AGENTS.md`와 `docs/*.md`는 각 Codex 실행에 그대로 주입된다. C++ 프로젝트에서
|
||||
TypeScript 예시나 미완성 placeholder가 남아 있으면 실제 작업 지시와 충돌할 수 있다.
|
||||
옛 phase/push/권한 상승 CLI와 legacy `tdd` 설정의 처리는
|
||||
[이전 운영 방식 안내](HARNESS.md#이전-운영-방식에서-달라진-점)를 따른다.
|
||||
사용자 config와 이력을 자동 migration하거나 실패 evidence를 지우지 않는다.
|
||||
로컬 검증은 commit·push·tag·release 또는 외부 solver 실행 권한을 부여하지 않는다.
|
||||
|
||||
Reference in New Issue
Block a user