# MSVC C++ Harness 환경 구축 가이드 이 문서는 Windows에서 이 Harness framework를 설치하고, C++ 제품 저장소의 MSVC 빌드·테스트 및 Codex step 실행을 준비하는 절차를 설명한다. 명령은 별도 표시가 없으면 **대상 저장소 루트의 PowerShell**에서 실행한다. 현재 저장소에는 실행기, 훅, 설정 예제가 있으며 실제 C++ 제품 소스, CMake/Visual Studio 프로젝트, 실행할 `phases/`, Python 테스트 디렉터리는 없다. 따라서 도구 설치 확인과 실제 제품 빌드 성공을 구분해야 한다. 아래 프로젝트명·preset 이름·경로는 설정 형식을 보여 주는 예시이며, 제품의 MSVC toolset·C++ 표준·테스트 프레임워크는 아직 확정되지 않았다. ## 1. 필요한 환경 | 구분 | 요구 사항 | 용도 및 확인 기준 | |---|---|---| | 운영체제 | 선택한 Visual Studio가 지원하는 Windows | 이 가이드는 Windows 네이티브 실행과 x64 빌드를 기준으로 한다. 현재 도구 탐색은 `vswhere.exe`, `MSBuild.exe`를 사용한다. | | 셸 | PowerShell | 설치 점검과 Windows 훅 명령 실행. 아래 UTF-8 파일 작성 예제는 PowerShell 7 기준이다. | | Git | Windows에서 실행 가능한 Git | 저장소 탐색, branch 전환, 자동 commit. `--push` 사용 시에만 원격 저장소 인증이 추가로 필요하다. | | Python | 3.10 이상, `python` 명령으로 실행 가능 | 실행기와 훅은 표준 라이브러리만 사용한다. 일반 실행에 `pip install`이나 가상환경은 필수가 아니다. | | Codex CLI | 아래 옵션·훅 호환성 점검을 통과하는 버전 | `codex exec`, JSON 출력, stdin 프롬프트와 프로젝트 훅을 지원해야 한다. 로그인과 서비스 네트워크 접근이 필요하다. | | C++ 빌드 도구 | Visual Studio 또는 Build Tools의 MSVC x64/x86 도구, MSBuild, Windows SDK | Visual Studio Installer에서 C++ 워크로드를 설치한다. VS Code만 설치해서는 충족되지 않는다. | | CMake 방식 | CMake와 CTest 3.20 이상, 제품이 요구하는 버전 이상 | `ctest --test-dir`와 build/test preset 기능에 필요한 하한이다. generator와 preset schema가 더 높은 버전을 요구할 수 있다. | | MSBuild 방식 | 실제 `.sln` 또는 `.vcxproj`, 테스트 실행 명령 | CMake/CTest는 이 방식의 Harness 검증에 필수가 아니다. | | 선택 도구 | Node.js/npm, Ninja, pytest/uv | Node.js/npm은 Codex의 npm 설치 방식을 선택할 때, Ninja는 해당 generator를 쓸 때만 필요하다. pytest/uv는 Harness 자체 테스트가 있는 checkout에서 사용한다. | CMake 기능의 버전 근거는 [CMake 3.20 릴리스 노트](https://cmake.org/cmake/help/v3.20/release/3.20.html)와 [CTest 명령 문서](https://cmake.org/cmake/help/latest/manual/ctest.1.html)를 참고한다. Windows·Visual Studio·Codex의 정확한 지원 버전 조합은 저장소에서 고정하지 않았다. 팀에서 검증한 버전은 제품 도입 시 별도로 기록한다. ## 2. 기본 도구 설치 ### Git과 Python 1. [Git for Windows 공식 설치 페이지](https://git-scm.com/install/windows)에서 설치하고 PowerShell과 외부 프로그램에서 `git`을 실행할 수 있도록 PATH를 설정한다. 2. [Python Windows 공식 배포 페이지](https://www.python.org/downloads/windows/)에서 3.10 이상의 Python을 설치한다. 실행기뿐 아니라 자식 훅에서도 같은 Python을 찾도록 실제 설치 디렉터리를 사용자 PATH에 등록한다. 3. 새 PowerShell 창을 열고 확인한다. ```powershell git --version python --version python -c "import sys; print(sys.executable); assert sys.version_info >= (3, 10)" Get-Command git, python | Select-Object Name, Source ``` `python`이 Microsoft Store를 열거나 실행되지 않으면 Windows의 앱 실행 별칭과 PATH 순서를 확인한다. `py`만 동작하는 상태는 충분하지 않다. 현재 Windows 훅이 `python` 명령을 사용하기 때문이다. 가상환경을 쓰면 활성화한 동일 터미널에서 Harness를 실행한다. ### Visual Studio와 C++ 도구 1. [Microsoft의 MSVC 설치 안내](https://learn.microsoft.com/en-us/cpp/overview/acquire-msvc)를 따라 Visual Studio Installer를 실행한다. IDE가 필요하면 Visual Studio, 명령줄 빌드만 필요하면 Build Tools 설치를 선택한다. 2. **C++를 사용한 데스크톱 개발(Desktop development with C++)** 워크로드를 선택한다. 3. 설치 세부 정보에서 MSVC x64/x86 빌드 도구, MSBuild, 제품이 요구하는 Windows SDK가 포함되는지 확인한다. 기존 제품이면 해당 `PlatformToolset`과 SDK 버전을 설치한다. 4. CMake 방식이면 **Windows용 C++ CMake 도구**도 선택하거나 CMake를 별도 설치한다. 설치 후 아래 조회에서 실제 설치 경로와 `MSBuild.exe` 경로가 나와야 한다. ```powershell $vswhere = Join-Path ${env:ProgramFiles(x86)} 'Microsoft Visual Studio/Installer/vswhere.exe' Test-Path -LiteralPath $vswhere & $vswhere -latest -products '*' -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath & $vswhere -latest -products '*' -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -find 'MSBuild\**\Bin\MSBuild.exe' ``` Harness도 이 C++ component ID로 설치를 찾는다. 여러 Visual Studio 설치가 있으면 조건에 맞는 최신 설치를 선택하며, `.harness/config.json`에는 Visual Studio 설치 경로를 고정하는 필드가 없다. 특정 toolset 선택은 제품의 preset 또는 프로젝트 metadata에서 한다. ### CMake 사용 시 추가 점검 Harness는 PATH의 `cmake.exe`와 `ctest.exe`를 우선하고, 없으면 탐색한 Visual Studio의 번들 디렉터리를 사용한다. 아래는 번들 경로를 현재 터미널 PATH에 추가하는 예시다. ```powershell $vsInstall = & $vswhere -latest -products '*' -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath $cmakeBin = Join-Path $vsInstall 'Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/bin' if (Test-Path -LiteralPath (Join-Path $cmakeBin 'cmake.exe')) { $env:PATH = "$cmakeBin;$env:PATH" } cmake --version ctest --version Get-Command cmake, ctest | Select-Object Name, Source ``` 두 도구가 같은 CMake 배포본을 가리키도록 맞춘다. 새 터미널에서도 수동 명령을 사용하려면 해당 디렉터리를 사용자 PATH에 등록한다. Visual Studio generator와 직접 MSBuild는 설치된 도구를 활용한다. Ninja preset이나 `cl.exe` 직접 실행을 쓰는 경우에는 **Developer PowerShell for VS** 또는 **x64 Native Tools Command Prompt for VS**로 개발 환경을 먼저 연다. 명령 프롬프트에서 이 문서의 예제를 실행하려면 그 창에서 PowerShell을 시작한다. Harness는 `VsDevCmd.bat`를 자동 실행하지 않으므로 compiler/include/library 환경은 호출자에게서 상속된다. Ninja preset이면 같은 터미널에서 `ninja --version`도 확인한다. ## 3. Codex CLI 설치와 호환성 확인 [공식 Codex CLI 설치 안내](https://developers.openai.com/codex/cli)의 Windows 설치 방법으로 CLI를 설치한 뒤 새 터미널을 연다. npm 방식을 선택한 경우에는 먼저 [Node.js 공식 배포 페이지](https://nodejs.org/en/download)에서 Node.js/npm을 설치한다. Harness는 Codex 앱 설치 여부와 별개로 `codex` 명령을 직접 실행한다. ```powershell codex --version codex login codex login status codex exec --help ``` `codex login`의 안내에 따라 인증한다. Harness 설정에는 계정이나 API 키를 넣지 않는다. 현재 실행기가 사용하는 옵션은 다음과 같다. ```text codex exec --json --sandbox workspace-write --dangerously-bypass-hook-trust --cd - ``` `exec --help`에서 이 옵션들이 지원되는지 확인한다. 저장소는 최소 Codex 버전을 선언하지 않으므로 버전 숫자만으로 호환성을 판단하지 않는다. 문서 작성 시 로컬 CLI `0.153.4`에서 옵션 목록은 확인했지만, 이것이 전체 실행 검증을 의미하지는 않는다. 실행기는 셸 alias나 PowerShell 함수 대신 Python 자식 프로세스로 Codex를 호출한다. 동일한 경로로 실행 가능한지 다음 명령으로 확인한다. 모델 호출은 발생하지 않는다. ```powershell python -X utf8 -c "import subprocess; subprocess.run(['codex', '--version'], check=True)" python -X utf8 -c "import subprocess; subprocess.run(['codex', 'exec', '--help'], check=True)" ``` 터미널의 `codex`는 되는데 위 명령이 실패하면 `Get-Command codex -All`과 `where.exe codex`로 PATH를 확인한다. `.ps1` alias만 보이거나 npm shim이 자식 프로세스에서 실행되지 않으면 공식 Windows 설치 방식으로 CLI를 설치하고 실제 실행 파일 디렉터리를 PATH에 등록한 뒤 다시 점검한다. ## 4. 저장소 준비와 훅 확인 Git으로 저장소를 clone하거나, 기존 제품 저장소에 다음 Harness 구성요소를 가져온다. 기존 `AGENTS.md`와 훅 설정이 있으면 제품 규칙을 유지하면서 병합한다. ```text AGENTS.md .agents/skills/harness/SKILL.md .agents/skills/review/SKILL.md .codex/hooks.json .harness/config.example.json scripts/execute.py scripts/hooks/ scripts/msvc_harness/ docs/HARNESS.md docs/HARNESS_WORKFLOW.md docs/ENVIRONMENT_SETUP.md ``` 실행기와 훅이 경로를 기준으로 저장소를 찾으므로 위 배치를 유지한다. 제품 구현은 `src/`, 공개 header는 `include/`, 테스트는 `tests/`에 배치한다. ```powershell git rev-parse --show-toplevel git status --short git config user.name git config user.email python -X utf8 scripts/execute.py --help ``` Git 작성자 정보가 없으면 대상 저장소에서 아래 예시를 자신의 정보로 바꾸어 설정한다. 실제 실행 전에는 준비한 설정·phase 파일을 검토하여 commit하고, 다른 작업의 변경이 없는 전용 checkout/worktree를 사용한다. 실행기는 `git add -A`와 자동 commit을 수행한다. ```powershell git config --local user.name 'YOUR_NAME' git config --local user.email 'YOUR_EMAIL' ``` 저장소 루트에서 `codex`를 실행하고 `/hooks`에서 `.codex/hooks.json`의 `PreToolUse`와 `Stop`이 로드되는지 확인한다. 프로젝트 신뢰 설정과 훅의 실행 상태도 확인한다. 공식 훅 문서는 프로젝트 훅의 신뢰 요구사항과 Windows용 `commandWindows` 필드를 설명한다. [Codex 훅 문서](https://developers.openai.com/codex/hooks) 현재 실행기는 검토된 자동화용 `--dangerously-bypass-hook-trust`를 사용한다. 실행 전 저장소 훅 내용을 확인해야 하며, 이 옵션은 비활성 훅을 활성화하거나 빌드 설정을 대신하지 않는다. 사용자·관리자 설정에서 훅이 꺼져 있거나 프로젝트 훅이 제한되면 이를 먼저 해결한다. Windows 훅은 `python -X utf8`과 Git 루트 탐색을 사용한다. 따라서 Codex가 실행하는 훅 환경에서도 Python과 Git이 보여야 한다. 아래 직접 호출은 훅 스크립트의 기본 실행만 확인하며, Codex가 훅을 자동 호출하는지까지 검증하지는 않는다. ```powershell '{"tool_name":"Edit","tool_input":{"file_path":"docs/ENVIRONMENT_SETUP.md"}}' | python -X utf8 scripts/hooks/pre_tool_use.py $LASTEXITCODE ``` 통과 기준은 종료 코드 `0`이고 입력 해석 실패 메시지가 없는 것이다. C++ 편집에는 대응 테스트 파일이 먼저 필요하다. 기본 이름은 `{stem}_test.cpp`, `{stem}_tests.cpp`, `test_{stem}.cpp`, `{stem}.test.cpp`이며 실제 실패 테스트 확인은 별도로 수행해야 한다. ## 5. 제품 빌드 설정 `.harness/config.example.json`은 모든 필드를 보여 주는 참고 자료다. `MyProject.sln`, `windows-debug`, 테스트 실행 파일은 이 저장소에 존재하지 않으므로 그대로 복사해 완성된 설정으로 사용하지 않는다. 아래 방식 중 실제 프로젝트에 맞는 하나로 `.harness/config.json`을 작성한다. JSON은 **UTF-8 BOM 없이**, 주석 없이 저장한다. PowerShell 7에서 텍스트를 저장할 때는 `Set-Content -Encoding utf8NoBOM`을 사용할 수 있다. ### A. CMake, preset 없이 사용 실제 루트 `CMakeLists.txt`가 있는 프로젝트의 최소 설정이다. ```json { "version": 1, "projectType": "cmake", "cmake": { "sourceDir": "." } } ``` 이 방식은 Harness가 `.harness/build`, `Debug`, `x64`를 사용한다. 프로젝트에 맞는 Visual Studio generator가 선택되는 환경에서 다음 순서로 확인한다. generator·구성· toolset을 명확히 고정해야 하는 제품은 B 방식의 preset을 사용한다. ```powershell cmake -S . -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 ``` 각 명령이 성공해야 하고, 테스트 발견 JSON의 `tests` 배열에는 적어도 한 개의 테스트가 있어야 한다. 제품 CMake에서 C++ 언어와 테스트를 활성화하고 실제 테스트를 등록한다. Harness는 생성된 `CMakeCXXCompiler.cmake`의 compiler ID가 `MSVC`인지 확인하므로 MinGW/GCC 또는 Clang으로 설정된 build directory는 통과하지 않는다. ### B. CMake preset 사용 다음은 **이미 `windows-debug` configure/build/test preset이 정의된 제품**의 예시다. 실제 `CMakePresets.json` 또는 `CMakeUserPresets.json`의 이름과 binary directory로 바꾼다. ```json { "version": 1, "projectType": "cmake", "cmake": { "sourceDir": ".", "binaryDir": "out/build/windows-debug", "configurePreset": "windows-debug", "buildPreset": "windows-debug", "testPreset": "windows-debug" } } ``` `binaryDir`, `configurePreset`, `buildPreset`, `testPreset`은 네 개를 함께 지정해야 한다. `binaryDir`만 바꾸는 설정은 지원하지 않는다. 세 preset은 동일한 빌드 트리를 사용해야 하며 MSVC generator/toolset·아키텍처·빌드 구성을 제품 요구에 맞게 정의한다. [CMake preset 공식 문서](https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html) 아래 명령은 설정의 `sourceDir`에서 실행한다. 이름은 실제 preset으로 바꾼다. ```powershell cmake --list-presets cmake --build --list-presets ctest --list-presets cmake --preset windows-debug cmake --build --preset windows-debug ctest --preset windows-debug --show-only=json-v1 ctest --preset windows-debug --output-on-failure ``` ### C. Visual Studio solution/project와 MSBuild 사용 아래 파일명·출력 경로를 실제 `.sln` 또는 `.vcxproj`와 테스트 실행 파일로 바꾼다. 테스트 프레임워크는 지정하지 않으며, 실패할 때 nonzero로 종료하는 테스트 명령이 필요하다. ```json { "version": 1, "projectType": "msbuild", "msbuild": { "solution": "MyProject.sln", "configuration": "Debug", "platform": "x64", "testCommand": ["build/tests/Debug/MyProjectTests.exe"] } } ``` `testCommand`는 실행 파일과 인자를 분리한 문자열 배열이다. 명령 전체를 한 문자열로 넣거나 `&&`, 파이프, 셸 변수 확장을 기대하지 않는다. 작업 디렉터리는 저장소 루트다. 실행 파일에 경로를 쓰면 저장소 내부여야 하며, 파일명만 쓰면 PATH에서 찾는다. ```powershell $msbuildExe = & $vswhere -latest -products '*' -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -find 'MSBuild\**\Bin\MSBuild.exe' | Select-Object -First 1 & $msbuildExe MyProject.sln /m /nologo /p:Configuration=Debug /p:Platform=x64 & ./build/tests/Debug/MyProjectTests.exe ``` 빌드와 테스트 각각의 종료 코드가 `0`이어야 한다. 직접 MSBuild 방식에서 CTest 등록은 필수가 아니지만 `msbuild.testCommand`는 필수다. 현재 탐색기는 `.slnx`를 지원하지 않는다. ### 공통 설정 점검 `sourceDir`, `binaryDir`, `solution`, `tdd.testRoots`는 저장소 상대 경로로 지정하며 저장소 밖을 가리킬 수 없다. 알 수 없는 설정 필드는 오류다. `projectType: "auto"`는 루트 CMake metadata → 단일 루트 `.sln` → 단일 루트 `.vcxproj` 순서로 찾는다. 하위 디렉터리 제품이나 빌드 형식이 여러 개인 저장소는 `projectType`과 경로를 명시한다. 구문과 설정 형식을 빌드 없이 확인한다. ```powershell python -X utf8 -m json.tool .harness/config.json python -X utf8 -c "import sys; from pathlib import Path; sys.path.insert(0, 'scripts'); from msvc_harness.config import load_config; print(load_config(Path.cwd()))" ``` 현재 `.gitignore`는 `.harness/build/`를 제외하지만 `.harness/config.json`, `out/build/`, `.venv/`는 제외하지 않는다. 제품 저장소에서 공유할 설정과 로컬 파일· 빌드 산출물을 정하고 자동 staging 전에 필요한 ignore 규칙을 적용한다. ## 6. 구축 완료 확인과 최초 실행 제품 metadata와 설정을 준비한 뒤 Stop 훅 검증을 수동 실행한다. 실제 빌드·테스트와 빌드 산출물 작성이 발생한다. ```powershell python -X utf8 scripts/hooks/stop_validation.py ``` 이 스크립트는 **실패해도 프로세스 종료 코드가 0일 수 있다**. 표준 출력에 `"continue": false`와 `stopReason`이 나오면 검증 실패다. C++ 파일도 metadata도 없는 초기 저장소는 빌드를 수행하지 않고 조용히 종료하므로 MSVC 검증 성공으로 기록하지 않는다. `CODEX_STOP_VALIDATION_ACTIVE=1`이 설정된 재진입 환경이나 docs-only 실행 문맥에서도 검증이 생략될 수 있으므로 수동 점검은 일반 터미널에서 수행한다. 제품 검증 후 [실행 흐름](HARNESS_WORKFLOW.md)과 [Harness 스킬의 phase 형식](../.agents/skills/harness/SKILL.md)에 맞춰 실제 작업의 `phases/index.json`, `phases//index.json`, `stepN.md`를 준비한다. `context_files`에는 존재하는 파일만 넣는다. 현재 checkout에는 기존 문서가 참조하는 `docs/phase/README.md`도 없으므로 기록은 실행기가 명시한 다음 내용을 기준으로 준비한다. - `docs/phase//handoff.md`: 현재 상황, 결정과 이유, 미해결 문제, 검증 결과, 다음 시작점과 상세 기록 링크를 약 60줄로 유지한다. - `docs/phase//stepN.md`: 변경 파일, 결정, 검증, 실패한 접근과 이유를 기록한다. - 실행 상태의 기준은 `phases//index.json`이며 인계 기록은 상태를 대신하지 않는다. ``를 실제 디렉터리 이름으로 바꾸어 실행한다. ```powershell python -X utf8 scripts/execute.py --dry-run python -X utf8 scripts/execute.py ``` `--dry-run`은 첫 pending step의 문맥 경로와 프롬프트 크기만 확인하며 Codex, Git 변경, 인증, 빌드·테스트는 실행하지 않는다. 실제 실행은 branch 전환, 파일 수정과 자동 commit을 수행한다. 원격 전송이 필요할 때만 `--push`를 사용한다. 구축 완료 기준은 다음과 같다. - Python에서 `codex --version`과 `exec --help`를 직접 호출할 수 있고 인증이 되어 있다. - Codex에서 프로젝트 훅이 로드되고 실제 도구 호출·종료 시 동작한다. - 실제 제품의 MSVC build와 테스트가 성공하고 Stop 훅에서 차단 응답이 없다. - 실제 phase의 dry-run에서 필요한 문맥을 읽고 첫 step 실행 결과와 index 상태가 일치한다. Harness 자체를 수정하는 checkout에 Python 테스트가 있다면 별도로 아래를 실행한다. 현재 checkout에는 `tests/`가 없어 pytest 통과를 구축 완료 근거로 사용할 수 없다. ```powershell python -m pip install pytest python -m pytest -v -rs python -m compileall -q scripts ``` ## 7. 자주 발생하는 문제 | 증상 | 확인 및 조치 | |---|---| | `python` 또는 `codex`를 찾지 못함 | 새 터미널에서 PATH와 앱 실행 별칭을 확인한다. Python 자식 프로세스 점검까지 통과해야 한다. | | `unexpected argument` / `unrecognized option` | `codex exec --help`로 실행기의 옵션 지원 여부를 확인하고 호환 CLI를 설치한다. | | `not logged in` / 인증 실패 | Harness를 실행하는 동일 Windows 계정과 Codex 환경에서 다시 로그인한다. | | 훅이 보이지 않거나 실행되지 않음 | `/hooks`, 프로젝트 신뢰, 사용자·관리자 훅 설정, `commandWindows` 지원과 자식 환경의 PATH를 확인한다. | | `vswhere.exe` 또는 MSBuild를 찾지 못함 | Visual Studio Installer에서 C++ x64/x86 도구와 MSBuild를 설치·복구한다. 조회 결과가 빈 문자열인지도 확인한다. | | CMake가 `-A x64`를 거부함 | 기본 generator가 Ninja 등인지 확인한다. Visual Studio generator 환경을 사용하거나 MSVC 개발 환경과 preset을 구성한다. | | MSVC compiler metadata 오류 | 잘못된 compiler로 configure했는지, preset의 실제 binary directory와 `binaryDir`가 같은지 확인한다. | | `CTest discovered no tests` | 제품 CMake의 테스트 활성화·등록, test preset과 구성 필터를 확인한다. 실행 파일 존재만으로는 충분하지 않다. | | 여러 solution / build metadata 없음 | `projectType`과 실제 프로젝트 경로를 명시한다. C++ 파일만 복사한 상태로는 build를 검증할 수 없다. | | `TDD GUARD` 차단 | 대응 테스트를 먼저 추가하고 red 단계 확인 후 제품 파일을 수정한다. | | `dubious ownership` | 가능하면 현재 계정 소유의 checkout을 사용한다. 신뢰하는 공유 경로라면 해당 경로 하나만 Git `safe.directory`에 등록하고 자식 계정에서도 적용되는지 확인한다. | | phase 또는 context 파일을 찾지 못함 | 현재 저장소에는 기본 phase가 없다. 실제 phase/index/step과 참조 파일을 먼저 작성한다. | | 빌드·Codex 시간 초과 | Stop 검증 전체와 Codex 호출 각각의 제한은 1,800초다. 로그의 실패 단계와 도구 경로를 확인한다. | 운영 중 재시도, `error`/`blocked` 복구와 상태 기록은 [Harness 운영 가이드](HARNESS.md)와 [실행 흐름](HARNESS_WORKFLOW.md)을 참고한다.