# 구현 환경·실행시간·evidence 운영 계획 - Feature ID: `mitc4-shell-feast-eigen` - Owner: `implementation-planning-agent` - Input contract revision: `r2` - 기본 보고서: [implementation-plan](implementation-plan.md) E1/E2의 현재 값과 실행 전 표현은 최초 계획 시점 기록이다. Prep attempt1 종료 뒤 네 runtime 상수만 부분 변경되었고 Hook1800은 남았다. [복구 계획](implementation-recovery.md)의 WIP 보존·명시 승인·status-only checkpoint가 실제 완료되기 전 재실행하거나 main을 활성화하지 않는다. 실제 source echo의 classifier 오판도 prep의 최소 TDD 범위다. 이미 import된 Executor에는 Codex의 classifier source 수정이 자동 반영되지 않는다. 새 process activation과 재차 terminal 차단의 처리 경계는 [복구 계획](implementation-recovery.md)을 따른다. ## E1. 실제 backend와 preflight [현재 환경 evidence](coordination.md#후속-실행-준비-관찰)를 적용한다. 이 계획 단계에서는 Harness, CMake/CTest, C++ 또는 FEAST를 실행하지 않는다. Root의 과거 관찰은 신규 gate 성공이 아니다. | 선택 | 실제 값 | | --- | --- | | Repository | linked worktree, `C:/Users/baram/orca/workspaces/FESADev/Eigen`; Git top-level과 Harness ROOT 동일 | | Baseline | I/O checkpoint `1d4f5ac`; 사용자 branch `Eigen`에서 계획 작성 | | Harness config | `.harness/config.json` 없음; autodetect CMake | | Build | Visual Studio 18 2026 / MSVC / x64 / Debug / `.harness/build` | | GoogleTest | `C:/git/googletest` | | MKL_DIR | `C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl` | | TBB_DIR | `C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb` | | HDF5_DIR | `C:/Program Files/HDF_Group/HDF5/2.1.1/cmake` | | Observed MKL configuration | 2026.1 / dynamic / intel_ilp64 / intel_thread; 실제 FEAST 실행에서 version/ABI를 다시 기록 | | Python / CLI | Python3.11.15; python/uv/cmake/ctest/codex resolved. Codex transport/login은 아직 실행 검증 전 | | Executor role | `.codex/agents/implementation-agent.toml`, gpt-5.6-terra / xhigh / workspace-write | 개인 설치 경로를 C++/CMake source에 고정하지 않는다. 아래는 이 workstation의 local cache 구성 명령이며 이미 Root가 exit0으로 확인했다. 실제 실행 전 cache의 경로/compilers/platform을 다시 읽고 stale/missing이면 동일 환경 준비 명령을 실행한다. ```powershell cmake -S . -B .harness/build -A x64 "-DFESA_GTEST_SOURCE_DIR=C:/git/googletest" "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" ``` 다음부터는 Step의 unadorned configure/build/CTest 명령을 사용한다. Preset은 dependency 환경변수4개를 참조하므로 현재 미설정된 부모 환경에서 preset을 호출하는 계획은 선택하지 않는다. VS generator는 CMake가 MSVC를 선택하고 `--config Debug`/`-C Debug`로 검증한다. 필수는 CMake/MSVC/x64/Debug이며 Ninja 예시 자체가 필수는 아니다. Hook도 같은 absent-config autodetect를 사용한다. Subprocess 환경을 부모 Stop에 전파했다고 가정하지 않는다. ## E2. 최소 deadline 변경과 근거 Actual code의 다음 모두가 유한 제한을 적용한다. 지원되는 CLI/config timeout option은 없다. | 경계 | 현재 | prep 후 | | --- | ---: | ---: | | StepExecutor Codex wrapper | 1800 | 14400 | | 등록 Stop outer | 1800 | 7500 | | Stop discovery/configure/build/discovery/CTest shared | 1800 | 7200 | | CommandSpec default per-command | 1800 | 7200 | | execute_plan의 명시 deadline 없는 default shared | 1800 | 7200 | 전체 regression duration의 기존 합산 추정은1672.67초(약27.9분)다. 이는 여러 run의 값이며 단일 full suite wall time/pass가 아니다. 추가 eigensolver tests와 fresh reference 비용은 미측정이다. 7200초는 기존 약28분 검증에 초기 실행/신규 numerical tests 여유를 두되 유한하게 중단하는 운영 상한이다. Registered7500은 shared7200 종료/진단을 위한300초 여유, wrapper14400은 coding·RED/GREEN·focused·수동 full VERIFY와 등록 Stop을 함께 감싼다. 상한을 더한 값을 실제 소요 시간이라고 보고하지 않는다. Main은8개 Step이다. 각 Step은 하나의 완결된 API/data boundary를 담당하고 동일 session에서 작은 behavior별 RED/GREEN을 반복한다. 통상 coding/focused 약2시간 안, 수동 full과 Stop 각 약30~45분을 고려한 분해다. 이는 실행 예산 설계이며 소요 보장이나 시험 결과가 아니다. 예상보다 늦거나 failure이면 terminal evidence를 남기고 Coordinator가 원인을 분류한다. Timeout을 무한대로 만들거나 test/Hook를 생략하지 않는다. 14개 초기 소단위를8개로 합쳐 불필요한 전체 검증 반복6회를 줄였다. Model+parser는 같은 frequency/density 정의, consistent+lumped+assembly는 같은 moment snapshot, call+search는 하나의 FEAST result/history, validation+procedure는 한 candidate, writer+CLI는 한 transaction, comparator+fresh execution은 한 source matching 결과를 완성한다. Stabilization과 reduction은 각각 기존 static 영향과 analytic positive/null 경계라 독립 Step으로 유지한다. ## E3. One-time bootstrap와 새 process activation 일반1800초 invocation은 prep 중 source self-edit로 이미 시작된 wrapper의 timeout을 늘리지 못한다. Pressure 일부는 same-binary HDF5 cache를 사용하지만 `RunFesaApplicationOnCopiedInput()`은 nonlinear reference solver를 매번 직접 호출한다. 따라서 full VERIFY+registered Stop을 모두 cached/빠르다고 가정하지 않는다. Root와 Coordinator가 사용자 승인된 가역적 운영 준비로 해석한 **one-time module invocation**을 prep에만 사용한다. 기존 CLI option이 아니다. 실제 module을 import하고 한 유한 class timeout만 설정한 뒤 unchanged `main()`을 호출하므로 기존 argparse/preflight/branch/ownership/sandbox/ terminal result/transport retry/commit/finalization 경로를 그대로 실행한다. ```powershell python -B -c "from scripts import execute; execute.StepExecutor.CODEX_TIMEOUT_SECONDS = 14400; execute.main()" mitc4-shell-feast-eigen-execution-prep ``` Bootstrap은 Hook state/reentry flag/execution method를 override하지 않는다. Prep에서 `.codex/hooks.json`을 수정해도 이미 launch된 Codex의 registered Stop outer1800이 유지될 수 있다. 그 세션에 새7500이 반영됐다고 단정하지 않는다. Prep의 actual manual full/registered Stop/Codex exit와 source/control commits를 확인해야 한다. Stop이 실제 cap을 넘거나 실패하면 원시 log와 terminal 상태를 보존한 채 환경 분류로 반환한다. 성공으로 덮어쓰기/즉시 재실행하지 않는다. Prep Executor가 **정상 종료하고 Step0 completed·Codex exit0·등록 Stop 성공·정확 경로 commits· clean 및 Coordinator의 사후 감사 완료**를 확인한 뒤 새 process에서 정상 main invocation을 실행한다. ```powershell python scripts/execute.py mitc4-shell-feast-eigen ``` 새 Executor는 source14400을 새로 읽고 새 Codex session은 변경된 등록7500/Stop7200/command7200 구성으로 시작한다. Source상 cap과 실제 검증 evidence를 함께 기록한다. Prep/main은 `feat-mitc4-shell-feast-eigen-execution-prep`와 `feat-mitc4-shell-feast-eigen` branch를 Executor가 차례로 소유한다. Main branch는 prep 완료 HEAD를 포함해야 한다. ## E4. Git와 활성 실행의 경계 1. Coordinator가 계획 gate를 감사한 뒤 Root가 완료 Feature 문서/계획 및 두 phase 제어 파일의 정확 목록을 checkpoint한다. 두 phase를 만들었으므로 선택되지 않은 phase files까지 미리 commit해 selected-phase allowlist 밖 dirty 파일이 없게 한다. 기존 unrelated pending beam phase/history는 보존하며 invocation 대상으로 삼지 않는다. 2. 실행 직전 `git rev-parse --show-toplevel`, `git status --porcelain=v1 --untracked-files=all`, actual role/config를 읽는다. Linked worktree와 Harness ROOT 동일성을 확인한다. 3. Active Executor 동안 Root/Coordinator/다른 specialist는 non-owned edits/commits를 멈춘다. Implementation은 선택 Step paths와 해당 Step result fields만 수정한다. Commit/branch/ timestamp/attempt_history/phase 진전은 Executor 소유다. 4. Terminal failure는 raw payload·history·logs를 보존한다. Coordinator의 assigned recovery가 없으면 pending reset/재시작하지 않는다. Correction budget과 transport retry는 별개다. 5. Default workspace-write를 사용한다. Danger-full-access는 같은 native command의 실제 실패, 해당 실행 직전 사용자 명시 승인, clean linked worktree, 승인 flag를 모두 요구한다. 이번 timeout 준비는 sandbox 확대 권한이 아니다. Remote push/tag/publish/deploy/package는 없다. ## E5. 실제 실행 evidence 보존 각 Step raw evidence root는 ignored `.harness/build/mitc4-eigen-evidence/stepN/`, prep은 `.../prep/`다. `New-Item -ItemType Directory -Force`와 `Copy-Item -LiteralPath`는 해당 resolved workspace 하위 generated 경로만 대상으로 한다. Recursive delete/move는 계획하지 않는다. 긴 command는 managed process/session으로 실제 exit까지 관찰하며 약60초마다 Coordinator에 의미 있는 진행을 보낸다. Detached/unobserved execution으로 deadline을 피하지 않는다. RED/focused/full command stdout/stderr·actual exit·wall time·CTest discovery JSON·LastTest.log를 각각 고유 이름으로 보존한다. Tee/pipeline 사용 시 `$LASTEXITCODE`를 즉시 보존한다. CTest observer shell exit0을 CTest exit0으로 기록하지 않는다. Hook state를 조작하거나 수동 hook 실행으로 evidence를 만들지 않는다. 등록 Stop 이후의 실제 실패는 manual full pass로 덮어쓰지 않는다. Implementation 보고 시점의 실제 manual evidence와 마지막 Stop/exit 확인 대기를 구분하며 미래 성공을 보고서에 쓰지 않는다. Executor 종료 뒤 Coordinator가 raw output·등록 Hook evidence·actual exit를 management 문서에서 감사한다. Coordinator는 specialist 보고서 본문을 대신 수정하지 않는다. Prep→main activation은 이 사후 감사까지 완료된 뒤에만 가능하다. C++ source 변경 없는 prep의 same-binary 회귀와 새 binary의 fresh eigen/static 비교는 다른 evidence다. Final Step7는 직접 solver invocation·unique generated directory·원본 bytes/hash· binary/lib hash·result/log mtime/hash·call count를 남겨 freshness를 증명한다. 기존 helper가 파일 존재/mtime로 cache를 사용한 사실만으로 fresh라고 주장하지 않는다. ## E6. Correction 후의 Python/pytest와 process TEMP [Correction 실제 기록](corrections.md)의 named venv `pytest-venv/Scripts/python.exe`는 Python3.11.15/pytest9.1.1로 native GREEN37개와 전체153개 collection/실행에 성공했다. 아래 모든 경로의 기준은 workspace의 `.harness/build/mitc4-eigen-evidence/prep/classifier-correction/`다. | 용도 | 확인된 상대 경로 | | --- | --- | | 직접 pytest 및 후속 Executor Python | `pytest-venv/Scripts/python.exe` | | venv의 base runtime | `python-runtime/cpython-3.11.15-windows-x86_64-none/python.exe` | | uv의 workspace cache | `workspace-python-cache` | | pytest cache | `pytest-cache` | Native에서는 direct venv entry를 사용했다. Root의 uv offline 진입도 별도로 관찰됐지만 그 사실을 native uv 실행 성공으로 합치지 않는다. 후속 process의 PATH 앞에 named venv와 base directory를 두고 UV_PYTHON/UV_CACHE_DIR/UV_OFFLINE을 정상 설정하여 child의 기본 python/uv에도 전파한다. Global config·source·Hook command/guard는 바꾸지 않는다. [설치된 FileTracker IL 관찰](../../.harness/build/mitc4-eigen-evidence/prep/classifier-correction/filetracker-initialization-observation.json)의 SHA-256은 `8d47f96ba913a9adc2d89772cef4b27ea2187f613416912d894608be9730c5cc`다. Initializer의 Path.GetTempPath→s_tempPath→GetLongFilePath 유일 호출과 실제 접근 거부 stack이 대응하므로 새 workspace TEMP/TMP가 정상 운영 개선 후보라는 근거가 있다. **이 변경으로 native build가 성공한 evidence는 아직 없다.** FileTracker를 끄거나 DFA가 build 실패까지 해결한다고 추정하지 않는다. 아래 전체 block은 [R6 source checkpoint](implementation-recovery.md#r6-실제-correction-source2의-보존과-남은-실행-조건), R3 status-only checkpoint와 **해당 exact prep DFA run 직전 명시 사용자 승인** 후에만 실행한다. 이 turn에는 어느 것도 실행하지 않는다. 새 ignored TEMP 경로는 workspace 안에서 생성하고 기존 temp/evidence를 지우지 않는다. 기존 finite wrapper14400 및 모든 Executor guard를 유지한다. Process 환경은 native 종료/오류 때 finally로 원래 값(미설정 포함)으로 복원한다. ```powershell $ErrorActionPreference = 'Stop' $mfeRoot = (Get-Location).Path $mfeEvidence = Join-Path $mfeRoot '.harness/build/mitc4-eigen-evidence/prep/classifier-correction' $mfePython = Join-Path $mfeEvidence 'pytest-venv/Scripts/python.exe' $mfeBasePython = Join-Path $mfeEvidence 'python-runtime/cpython-3.11.15-windows-x86_64-none/python.exe' $mfeUvCache = Join-Path $mfeEvidence 'workspace-python-cache' foreach ($mfeFile in @($mfePython, $mfeBasePython)) { if (-not (Test-Path -LiteralPath $mfeFile -PathType Leaf)) { throw "Missing Python: $mfeFile" } } Get-Command uv -ErrorAction Stop | Out-Null $mfeGitRoot = git rev-parse --show-toplevel $mfeIdentityExit = $LASTEXITCODE if ($mfeIdentityExit -ne 0 -or [IO.Path]::GetFullPath($mfeGitRoot) -ne [IO.Path]::GetFullPath($mfeRoot)) { throw 'Workspace root mismatch' } $mfeRunTemp = Join-Path $mfeEvidence ('native-temp-' + [guid]::NewGuid().ToString('N')) if (-not [IO.Path]::GetFullPath($mfeRunTemp).StartsWith([IO.Path]::GetFullPath($mfeEvidence) + [IO.Path]::DirectorySeparatorChar)) { throw 'Temp path outside approved workspace evidence' } $null = New-Item -ItemType Directory -Path $mfeRunTemp $mfeEnvNames = @('PATH', 'UV_PYTHON', 'UV_CACHE_DIR', 'UV_OFFLINE', 'TEMP', 'TMP', 'FEM_HARNESS_CODEX_SANDBOX') $mfeBeforeEnv = @{} foreach ($mfeName in $mfeEnvNames) { $mfeBeforeEnv[$mfeName] = [Environment]::GetEnvironmentVariable($mfeName, 'Process') } if ($null -ne $mfeBeforeEnv['FEM_HARNESS_CODEX_SANDBOX'] -and $mfeBeforeEnv['FEM_HARNESS_CODEX_SANDBOX'] -ne 'workspace-write') { throw 'Unexpected pre-existing sandbox environment' } $mfeNativeExit = $null try { $env:PATH = (Split-Path $mfePython) + ';' + (Split-Path $mfeBasePython) + ';' + $mfeBeforeEnv['PATH'] $env:UV_PYTHON = $mfePython $env:UV_CACHE_DIR = $mfeUvCache $env:UV_OFFLINE = 'true' $env:TEMP = $mfeRunTemp $env:TMP = $mfeRunTemp $env:FEM_HARNESS_CODEX_SANDBOX = 'danger-full-access' & $mfePython -B -X utf8 -c "from scripts import execute; execute.StepExecutor.CODEX_TIMEOUT_SECONDS = 14400; execute.main()" mitc4-shell-feast-eigen-execution-prep --approve-danger-full-access $mfeNativeExit = $LASTEXITCODE if ($null -eq $mfeNativeExit) { throw 'Native Executor exit unavailable' } } finally { foreach ($mfeName in $mfeEnvNames) { [Environment]::SetEnvironmentVariable($mfeName, $mfeBeforeEnv[$mfeName], 'Process') } } exit $mfeNativeExit ``` 재개 Implementation은 inherited 환경을 확인한 뒤 pytest entry를 아래 direct venv 방식으로 사용한다. 기존 Step0의 대상/모든 assertions를 유지하며 collection에서3개 classifier test의 6/16/15 parameter inventory를 확인한다. 각 **호출마다 새** basetemp를 만들어 pytest가 기존 evidence directory를 정리하지 않게 한다. 이전 GREEN은 새 RED가 아니다. ```powershell $ErrorActionPreference = 'Stop' $mfeEvidence = Join-Path (Get-Location).Path '.harness/build/mitc4-eigen-evidence/prep/classifier-correction' $mfePython = Join-Path $mfeEvidence 'pytest-venv/Scripts/python.exe' $mfePytestRuns = @( @{ label = 'classifier'; targets = @('tests/test_execute.py', '-k', 'environment_classifier or successful_source_echo') }, @{ label = 'focused'; targets = @('tests/test_harness_timeouts.py', 'tests/test_execute.py', 'tests/test_execute_ownership.py', 'tests/test_hook_validation_scope.py', 'tests/test_harness_preset_contract.py') }, @{ label = 'full'; targets = @() } ) foreach ($mfeRun in $mfePytestRuns) { $mfeFreshBase = Join-Path $mfeEvidence ('pytest-' + $mfeRun.label + '-' + [guid]::NewGuid().ToString('N')) $mfeCache = Join-Path $mfeEvidence 'pytest-cache' $mfeTargets = $mfeRun.targets & $mfePython -B -X utf8 -m pytest -v -rs -o "cache_dir=$mfeCache" "--basetemp=$mfeFreshBase" @mfeTargets $mfePytestExit = $LASTEXITCODE Write-Output ("pytest {0}: exit {1}; basetemp {2}" -f $mfeRun.label, $mfePytestExit, $mfeFreshBase) if ($null -eq $mfePytestExit -or $mfePytestExit -ne 0) { throw 'pytest verification failed' } } ``` CMake/MSVC/x64/Debug configure/build와 전체 CTest discovery/run은 기존 Step0의 정확한 명령을 같은 inherited TEMP/TMP에서 별도로 실행한다. 실패 시 actual command/exit와 남은 검증을 기록한다. Registered Stop을 수동 full 검증으로 대체하지 않으며 원 보고서 갱신은 Implementation owner, 종료 뒤 사후 감사는 Coordinator 소유다. ## E7. 짧은 TEMP를 사용하는 정상 재개 E6의 긴 TEMP 이름은 attempt2의 `ShellSurfacePressureApplication.InputWithoutPressureRetainsExistingNonlinearBehavior` 실패를 재현했다. [같은 binary의 짧은 경로 비교](../../.harness/build/mitc4-eigen-evidence/prep/attempt2/path-length-probe-e15c1747/observation.json) SHA-256은 `511b30e183759b378e6f33f30aa3be4c940b58d1eabde12068151173a0a91979`다. TEMP152에서 만들어진 result251/lock261과 실패1, TEMP70에서 실제 생성된 lock179와 성공0을 구분한다. 새 `.harness/build/t-<8hex>`는 이 workspace에서70자이며 **TEMP80자 이하**를 검사한다. 관찰된 해당 fixture suffix109자를 더하면 lock189자 이하라는 운영 여유다. 이는 모든 미래 fixture의 길이 보장이 아니므로 기존 전체 suite를 실제 수행한다. Attempt2의 focused도 처음에는 긴 pytest basetemp에서130pass/6fail(exit1)이었고, 같은136대상을 짧은 `.harness/build/mfe-focus-<8guid>`로 바꾼 뒤136pass(exit0)였다. 확인된 named venv/base/UVoffline/cache와 direct pytest entry/대상은 유지하되 TEMP/TMP와 pytest basetemp를 모두 짧게 만든다. Native child와 registered Stop도 같은 process 환경을 상속한다. 기존 temp/evidence 삭제·test skip·FileTracker 비활성화·source/reference 변경은 없다. Full pytest는 attempt2에서 미실행이므로 필수로 남는다. [R7 WIP 및 별도 status checkpoint](implementation-recovery.md#r7-attempt2-실패-보존과-정상-workspace-write-재개) 완료 뒤 Coordinator가 아래 정상 workspace-write invocation을 할당한다. 추가 사용자 승인이나 DFA flag는 없다. 오류·정상 종료 모두 환경을 finally에서 원래 값으로 복원하고 native exit를 즉시 전파한다. 유한14400과 기존 registered Stop7500/shared7200은 유지한다. ```powershell $ErrorActionPreference = 'Stop' $mfeRoot = (Get-Location).Path $mfePhase = 'mitc4-shell-feast-eigen-execution-prep' $mfeEvidence = Join-Path $mfeRoot '.harness/build/mitc4-eigen-evidence/prep/classifier-correction' $mfePython = Join-Path $mfeEvidence 'pytest-venv/Scripts/python.exe' $mfeBasePython = Join-Path $mfeEvidence 'python-runtime/cpython-3.11.15-windows-x86_64-none/python.exe' $mfeUvCache = Join-Path $mfeEvidence 'workspace-python-cache' foreach ($mfeFile in @($mfePython, $mfeBasePython)) { if (-not (Test-Path -LiteralPath $mfeFile -PathType Leaf)) { throw "Missing Python: $mfeFile" } } Get-Command uv -ErrorAction Stop | Out-Null $mfeGitRoot = git rev-parse --show-toplevel $mfeIdentityExit = $LASTEXITCODE if ($mfeIdentityExit -ne 0 -or [IO.Path]::GetFullPath($mfeGitRoot) -ne [IO.Path]::GetFullPath($mfeRoot)) { throw 'Workspace root mismatch' } $mfeTempParent = Join-Path $mfeRoot '.harness/build' $mfeRunTemp = Join-Path $mfeTempParent ('t-' + [guid]::NewGuid().ToString('N').Substring(0, 8)) if ($mfeRunTemp.Length -gt 80) { throw 'TEMP exceeds the approved 80-character budget' } if (-not [IO.Path]::GetFullPath($mfeRunTemp).StartsWith([IO.Path]::GetFullPath($mfeTempParent) + [IO.Path]::DirectorySeparatorChar)) { throw 'Temp path outside approved workspace evidence' } $null = New-Item -ItemType Directory -Path $mfeRunTemp $mfeEnvNames = @('PATH', 'UV_PYTHON', 'UV_CACHE_DIR', 'UV_OFFLINE', 'TEMP', 'TMP', 'FEM_HARNESS_CODEX_SANDBOX') $mfeBeforeEnv = @{} foreach ($mfeName in $mfeEnvNames) { $mfeBeforeEnv[$mfeName] = [Environment]::GetEnvironmentVariable($mfeName, 'Process') } if ($null -ne $mfeBeforeEnv['FEM_HARNESS_CODEX_SANDBOX'] -and $mfeBeforeEnv['FEM_HARNESS_CODEX_SANDBOX'] -ne 'workspace-write') { throw 'Unexpected pre-existing sandbox environment' } $mfeNativeExit = $null try { $env:PATH = (Split-Path $mfePython) + ';' + (Split-Path $mfeBasePython) + ';' + $mfeBeforeEnv['PATH'] $env:UV_PYTHON = $mfePython $env:UV_CACHE_DIR = $mfeUvCache $env:UV_OFFLINE = 'true' $env:TEMP = $mfeRunTemp $env:TMP = $mfeRunTemp $env:FEM_HARNESS_CODEX_SANDBOX = 'workspace-write' & $mfePython -B -X utf8 -c "from scripts import execute; execute.StepExecutor.CODEX_TIMEOUT_SECONDS = 14400; execute.main()" $mfePhase $mfeNativeExit = $LASTEXITCODE if ($null -eq $mfeNativeExit) { throw 'Native Executor exit unavailable' } } finally { foreach ($mfeName in $mfeEnvNames) { [Environment]::SetEnvironmentVariable($mfeName, $mfeBeforeEnv[$mfeName], 'Process') } } exit $mfeNativeExit ``` 현재 block은 미실행이다. Prep 성공·full manual VERIFY·actual registered Stop/CTest exit와 Coordinator 사후 감사 뒤 main을 별도 할당할 때는 같은 block의 `$mfePhase` 값만 `mitc4-shell-feast-eigen`으로 지정한다. Main도 workspace-write이며 해당8개 Step의 실제 C++ TDD/focused/full/reference gate를 그대로 수행한다. Hook7500이 이미 적용됐다는 사실이나 단독 경로 재현 성공을 전체 prep/main 성공으로 보고하지 않는다. 현재 pytest의 정확한 recipe는 아래다. E6의 긴 basetemp 예시는 과거 이력으로 남기고, 각 호출마다 새 `.harness/build/p-<8guid>`(현재70자, 상한80자)를 사용한다. 기존 directory를 재사용하거나 지우지 않는다. 같은 tests/assertions와 실제 exit 확인을 유지한다. ```powershell $ErrorActionPreference = 'Stop' $mfeBuild = Join-Path (Get-Location).Path '.harness/build' $mfeEvidence = Join-Path $mfeBuild 'mitc4-eigen-evidence/prep/classifier-correction' $mfePython = Join-Path $mfeEvidence 'pytest-venv/Scripts/python.exe' $mfePytestRuns = @( @{ label = 'classifier'; targets = @('tests/test_execute.py', '-k', 'environment_classifier or successful_source_echo') }, @{ label = 'focused'; targets = @('tests/test_harness_timeouts.py', 'tests/test_execute.py', 'tests/test_execute_ownership.py', 'tests/test_hook_validation_scope.py', 'tests/test_harness_preset_contract.py') }, @{ label = 'full'; targets = @() } ) foreach ($mfeRun in $mfePytestRuns) { $mfeFreshBase = Join-Path $mfeBuild ('p-' + [guid]::NewGuid().ToString('N').Substring(0, 8)) if ($mfeFreshBase.Length -gt 80 -or (Test-Path -LiteralPath $mfeFreshBase)) { throw 'Pytest basetemp must be short and new' } $mfeCache = Join-Path $mfeEvidence 'pytest-cache' $mfeTargets = $mfeRun.targets & $mfePython -B -X utf8 -m pytest -v -rs -o "cache_dir=$mfeCache" "--basetemp=$mfeFreshBase" @mfeTargets $mfePytestExit = $LASTEXITCODE Write-Output ("pytest {0}: exit {1}; basetemp {2}" -f $mfeRun.label, $mfePytestExit, $mfeFreshBase) if ($null -eq $mfePytestExit -or $mfePytestExit -ne 0) { throw 'pytest verification failed' } } ``` ## E8. Attempt3 후의 정상 backend 대안 이 절은 R8 보존 뒤의 **현재 backend 명령 계약**이다. E1~E7의 당시 실행·실패 기록은 유지한다. [R8 실제 checkpoint 결과](../../.harness/build/mitc4-eigen-evidence/prep/attempt3/r8-wip-checkpoint-result.json)에서 report1 commit `9601b1f53e8a11d3e08d49cf9528fa6f028108cf`, controls2 commit `96efbffa425ff5ce9cd1b7cebe673555273122b9`와 native exit0을 확인했다. 이후 status 변경·Ninja 설정·native 검증은 아직 미실행이다. [기존 preset](../../CMakePresets.json)과 [local config 예시](../../.harness/config.example.json)를 사용한다. 새 binaryDir는 `.harness/build-ninja-msvc-debug`이며 source, 기존 VS `.harness/build` cache와 모든 attempt evidence를 보존한다. [CMake adapter](../../scripts/msvc_harness/adapters/cmake.py)가 지원하는 이 세 preset을 함께 선택하면 manual CMake/CTest와 registered Stop이 같은 graph를 사용한다. 기존 config에 없는 Multi-Config 선택이나 public preset/API를 추가하지 않는다. Single-config에서도 기존 reference helper가 확인하는 실제 library 경로가 `/src/fesa/Debug/fesa_solver.lib`가 되도록 표준 `CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG`를 지정한다. Local CMake help가 설명한 per-configuration archive target 속성 초기화를 사용하며 fake cache 파일·복사·mtime 조작은 허용하지 않는다. 이 정상 MSVC/x64/Debug 대안의 **actual native 성공은 미검증**이다. ### E8.1. Root의 ignored 환경 준비 순서는 Root frozen 관리2/Planning3문서 checkpoint와 clean 확인 → 아래 Root setup의 actual configure/config 검증 → Coordinator의 setup 감사 → 별도 Planning status-only 할당과 [R9 control checkpoint](implementation-recovery.md#r9-e8-활성화-전의-status-only-checkpoint) → clean 확인 → E8.2 새 native invocation이다. 현재 문서 할당은 아래 setup 실행을 포함하지 않는다. Root는 별도 할당을 받은 뒤 repository root의 PowerShell에서 아래 block만 수행한다. Local config는 예시와 정확히 같은 기존 지원 설정만 생성하며 예상 밖 기존 config를 덮어쓰지 않는다. New CMake cache에 archive 경로를 고정하고 native/Stop의 후속 preset configure가 같은 값을 유지하게 한다. Root configure는 준비 evidence이며 native manual VERIFY의 대체가 아니다. ```powershell $ErrorActionPreference = 'Stop' $mfeRoot = (Get-Location).Path $mfeVs = 'C:/Program Files/Microsoft Visual Studio/18/Community' $mfeNinja = Join-Path $mfeVs 'Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja' $mfeEvidence = Join-Path $mfeRoot '.harness/build/mitc4-eigen-evidence/prep/classifier-correction' $mfePython = Join-Path $mfeEvidence 'pytest-venv/Scripts/python.exe' $mfeBasePython = Join-Path $mfeEvidence 'python-runtime/cpython-3.11.15-windows-x86_64-none/python.exe' foreach ($mfeFile in @($mfePython, $mfeBasePython)) { if (-not (Test-Path -LiteralPath $mfeFile -PathType Leaf)) { throw 'Named Python missing' } } Get-Command uv -ErrorAction Stop | Out-Null $mfeNewBuild = Join-Path $mfeRoot '.harness/build-ninja-msvc-debug' $mfeArchive = (Join-Path $mfeNewBuild 'src/fesa/Debug').Replace('\','/') $mfeTempParent = Join-Path $mfeRoot '.harness/build' $mfeTemp = Join-Path $mfeTempParent ('t-' + [guid]::NewGuid().ToString('N').Substring(0,8)) if ($mfeTemp.Length -gt 80 -or (Test-Path -LiteralPath $mfeTemp)) { throw 'TEMP must be short and new' } $null = New-Item -ItemType Directory -Path $mfeTemp $mfeEnvBefore = [Environment]::GetEnvironmentVariables('Process') $mfeExit = $null try { & $mfePython -B -X utf8 -c "from scripts import execute; e=execute.StepExecutor('mitc4-shell-feast-eigen-execution-prep'); assert not e._worktree_paths(); assert e._is_isolated_worktree(); e._preflight_repository(); print('Clean linked worktree verified')" $mfePreflightExit = $LASTEXITCODE if ($mfePreflightExit -ne 0) { exit $mfePreflightExit } $mfeConfig = Join-Path $mfeRoot '.harness/config.json' $mfeExample = Join-Path $mfeRoot '.harness/config.example.json' if (Test-Path -LiteralPath $mfeConfig) { if ((Get-Content -LiteralPath $mfeConfig -Raw | ConvertFrom-Json | ConvertTo-Json -Depth 10 -Compress) -ne (Get-Content -LiteralPath $mfeExample -Raw | ConvertFrom-Json | ConvertTo-Json -Depth 10 -Compress)) { throw 'Preserve unexpected existing local config' } } else { Copy-Item -LiteralPath $mfeExample -Destination $mfeConfig } if ($null -ne $env:FEM_HARNESS_CODEX_SANDBOX -and $env:FEM_HARNESS_CODEX_SANDBOX -ne 'workspace-write') { throw 'Unexpected sandbox environment' } & (Join-Path $mfeVs 'Common7/Tools/Launch-VsDevShell.ps1') -VsInstallationPath $mfeVs -Arch amd64 -HostArch amd64 -SkipAutomaticLocation -NoLogo $env:PATH = (Split-Path $mfePython) + ';' + (Split-Path $mfeBasePython) + ';' + $mfeNinja + ';' + $env:PATH $env:FESA_GTEST_SOURCE_DIR = 'C:/git/googletest' $env:MKL_DIR = 'C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl' $env:TBB_DIR = 'C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb' $env:HDF5_DIR = 'C:/Program Files/HDF_Group/HDF5/2.1.1/cmake' $env:UV_PYTHON = $mfePython $env:UV_CACHE_DIR = Join-Path $mfeEvidence 'workspace-python-cache' $env:UV_OFFLINE = 'true' $env:TEMP = $mfeTemp $env:TMP = $mfeTemp $env:FEM_HARNESS_CODEX_SANDBOX = 'workspace-write' Get-Command cl.exe, ninja.exe, cmake.exe, ctest.exe -ErrorAction Stop | Select-Object Name, Source if ($env:VSCMD_ARG_TGT_ARCH -notin @('x64','amd64')) { throw 'MSVC target must be x64' } git check-ignore --quiet .harness/config.json if ($LASTEXITCODE -ne 0) { throw 'Local config must remain ignored' } git check-ignore --quiet .harness/build-ninja-msvc-debug/ if ($LASTEXITCODE -ne 0) { throw 'New build must remain ignored' } cmake --preset windows-msvc-ninja-debug "-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG=$mfeArchive" $mfePrepareExit = $LASTEXITCODE if ($mfePrepareExit -ne 0) { exit $mfePrepareExit } & $mfePython -B -X utf8 -c "from pathlib import Path; from scripts.msvc_harness.config import load_config; c=load_config(Path.cwd()); assert c.cmake.configure_preset=='windows-msvc-ninja-debug'; assert c.cmake.build_preset==c.cmake.test_preset==c.cmake.configure_preset; assert c.cmake.binary_dir==Path.cwd()/'.harness/build-ninja-msvc-debug'; print('Ninja local config validated')" $mfeConfigExit = $LASTEXITCODE if ($mfeConfigExit -ne 0) { exit $mfeConfigExit } $mfeExit = $mfeConfigExit if ($null -eq $mfeExit) { throw 'Root setup exit unavailable' } } finally { foreach ($mfeName in @([Environment]::GetEnvironmentVariables('Process').Keys)) { if (-not $mfeEnvBefore.Contains($mfeName)) { [Environment]::SetEnvironmentVariable($mfeName, $null, 'Process') } } foreach ($mfeName in $mfeEnvBefore.Keys) { [Environment]::SetEnvironmentVariable($mfeName, $mfeEnvBefore[$mfeName], 'Process') } } exit $mfeExit ``` Installed VS x64 DevShell이 설정하는 INCLUDE/LIB/PATH 등을 포함해 process 환경 전체를 snapshot/finally 복원한다. Config와 새 cache는 ignored 상태로 feature 동안 유지한다. Root setup process의 종료가 다른 parent/tool shell의 환경을 갱신하지는 않는다. Native의 **각 tool shell**도 E8.2의 동일 VS/dependency/Python/TEMP 설정을 실제 적용한 상태에서 명령을 실행해야 한다. 이전 attempt3의 명시적 짧은 TEMP 적용 실패를 환경 누락으로 재분류하지 않는다. Setup 실패 시 실제 exit와 남은 ignored 파일을 보존하고 재실행을 멈춘다. ### E8.2. Coordinator의 새 정상 invocation과 native shell 환경 Root setup과 R9의 실제 완료를 감사한 Coordinator만 다음 invocation을 할당한다. `StepExecutor/main`과 모든 guard는 그대로이며 승인된 유한14400 module invocation을 사용한다. Registered Stop7500/shared·command7200, terminal 보존, transport budget, terra/xhigh 및 workspace-write를 유지한다. 기존 one-time DFA 승인은 소진됐으며 flag가 없다. ```powershell $ErrorActionPreference = 'Stop' $mfeRoot = (Get-Location).Path $mfePhase = 'mitc4-shell-feast-eigen-execution-prep' $mfeVs = 'C:/Program Files/Microsoft Visual Studio/18/Community' $mfeNinja = Join-Path $mfeVs 'Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja' $mfeEvidence = Join-Path $mfeRoot '.harness/build/mitc4-eigen-evidence/prep/classifier-correction' $mfePython = Join-Path $mfeEvidence 'pytest-venv/Scripts/python.exe' $mfeBasePython = Join-Path $mfeEvidence 'python-runtime/cpython-3.11.15-windows-x86_64-none/python.exe' foreach ($mfeFile in @($mfePython, $mfeBasePython)) { if (-not (Test-Path -LiteralPath $mfeFile -PathType Leaf)) { throw 'Named Python missing' } } Get-Command uv -ErrorAction Stop | Out-Null $mfeNewBuild = Join-Path $mfeRoot '.harness/build-ninja-msvc-debug' $mfeArchive = (Join-Path $mfeNewBuild 'src/fesa/Debug').Replace('\','/') $mfeTempParent = Join-Path $mfeRoot '.harness/build' $mfeTemp = Join-Path $mfeTempParent ('t-' + [guid]::NewGuid().ToString('N').Substring(0,8)) if ($mfeTemp.Length -gt 80 -or (Test-Path -LiteralPath $mfeTemp)) { throw 'TEMP must be short and new' } $null = New-Item -ItemType Directory -Path $mfeTemp $mfeEnvBefore = [Environment]::GetEnvironmentVariables('Process') $mfeExit = $null try { if ($null -ne $env:FEM_HARNESS_CODEX_SANDBOX -and $env:FEM_HARNESS_CODEX_SANDBOX -ne 'workspace-write') { throw 'Unexpected sandbox environment' } & (Join-Path $mfeVs 'Common7/Tools/Launch-VsDevShell.ps1') -VsInstallationPath $mfeVs -Arch amd64 -HostArch amd64 -SkipAutomaticLocation -NoLogo $env:PATH = (Split-Path $mfePython) + ';' + (Split-Path $mfeBasePython) + ';' + $mfeNinja + ';' + $env:PATH $env:FESA_GTEST_SOURCE_DIR = 'C:/git/googletest' $env:MKL_DIR = 'C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl' $env:TBB_DIR = 'C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb' $env:HDF5_DIR = 'C:/Program Files/HDF_Group/HDF5/2.1.1/cmake' $env:UV_PYTHON = $mfePython $env:UV_CACHE_DIR = Join-Path $mfeEvidence 'workspace-python-cache' $env:UV_OFFLINE = 'true' $env:TEMP = $mfeTemp $env:TMP = $mfeTemp $env:FEM_HARNESS_CODEX_SANDBOX = 'workspace-write' Get-Command cl.exe, ninja.exe, cmake.exe, ctest.exe -ErrorAction Stop | Select-Object Name, Source if ($env:VSCMD_ARG_TGT_ARCH -notin @('x64','amd64')) { throw 'MSVC target must be x64' } if (-not (Test-Path -LiteralPath (Join-Path $mfeNewBuild 'CMakeCache.txt'))) { throw 'Root cache preparation missing' } & $mfePython -B -X utf8 -c "from pathlib import Path; from scripts.msvc_harness.config import load_config; c=load_config(Path.cwd()); assert c.cmake.configure_preset=='windows-msvc-ninja-debug'; assert c.cmake.build_preset==c.cmake.test_preset==c.cmake.configure_preset; assert c.cmake.binary_dir==Path.cwd()/'.harness/build-ninja-msvc-debug'; print('Ninja local config validated')" $mfeConfigExit = $LASTEXITCODE if ($mfeConfigExit -ne 0) { exit $mfeConfigExit } & $mfePython -B -X utf8 -c "from scripts import execute; execute.StepExecutor.CODEX_TIMEOUT_SECONDS = 14400; execute.main()" $mfePhase $mfeExit = $LASTEXITCODE if ($null -eq $mfeExit) { throw 'Native Executor exit unavailable' } } finally { foreach ($mfeName in @([Environment]::GetEnvironmentVariables('Process').Keys)) { if (-not $mfeEnvBefore.Contains($mfeName)) { [Environment]::SetEnvironmentVariable($mfeName, $null, 'Process') } } foreach ($mfeName in $mfeEnvBefore.Keys) { [Environment]::SetEnvironmentVariable($mfeName, $mfeEnvBefore[$mfeName], 'Process') } } exit $mfeExit ``` 이 block의 환경 설정은 Executor child와 그 registered Stop에 상속된다. Implementation tool shell이 이를 상속하지 않았거나 별도 shell을 시작했다면 동일 block의 환경 설정과 finally를 그 shell에서 적용한다. **Manual 검증용 정확한 composition**은 위 block에서 `& $mfePython -B -X utf8 -c "from scripts import execute; execute.StepExecutor.CODEX_TIMEOUT_SECONDS = 14400; execute.main()" $mfePhase` 한 줄을 E8.3의 해당 검증 명령들로 교체하는 것이다. 나머지 config 검사/DevShell/환경 복원은 그대로 두며 manual shell에서 Executor를 중첩 호출하지 않는다. 각 명령 직후 `$LASTEXITCODE`를 캡처하고 0이 아니면 해당 native exit로 종료하여 finally를 실행한다. Active Executor 동안 Root/Coordinator는 non-owned 편집과 commit을 멈춘다. 구현 owner는 Step0 보고서와 result payload만 할당 범위에서 작성하며 phase/timestamps/history/Git을 변경하지 않는다. 실제 manual evidence와 아직 발생하지 않은 final registered Stop을 구분하고 Coordinator가 native 종료 뒤 raw/Hook/CTest actual exit를 사후 감사한다. Prep 전체 gate를 통과한 뒤 별도 main invocation은 위 block의 `$mfePhase`만 `mitc4-shell-feast-eigen`으로 바꾼다. Main도 workspace-write와 같은 환경/graph를 사용한다. ### E8.3. Prep와 main8의 정확한 명령 대응 및 evidence Prep [Step0](../../phases/mitc4-shell-feast-eigen-execution-prep/step0.md)와 [main8](../../phases/mitc4-shell-feast-eigen/index.json)의 모든 Step은 현재 environment를 필수 입력으로 읽는다. 해당 문서의 과거 config absent/VS 고정 명령은 이번 Coordinator E8 dispatch에서 아래 대응으로 **명시 대체**한다. 이는 선택 backend 변경이며 승인된 owned_paths, TDD 순서, target/test regex/mandatory names, full VERIFY 범위는 그대로다. Phase 파일을 임의 수정하거나 예전 VS 명령과 새 graph를 섞지 않는다. | 기존 Step 명령 | E8에서 실행할 명령 | | --- | --- | | `cmake -S . -B .harness/build -A x64` | `cmake --preset windows-msvc-ninja-debug "-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG=$mfeArchive"` | | `cmake --build .harness/build --config Debug --target fesa_tests` | `cmake --build --preset windows-msvc-ninja-debug --target fesa_tests` | | `cmake --build .harness/build --config Debug` | `cmake --build --preset windows-msvc-ninja-debug` | | `ctest --test-dir .harness/build -C Debug -R '' --show-only=json-v1` | `ctest --preset windows-msvc-ninja-debug -R '<같은 원문 regex>' --show-only=json-v1` | | `ctest --test-dir .harness/build -C Debug -R '' --output-on-failure` | `ctest --preset windows-msvc-ninja-debug -R '<같은 원문 regex>' --output-on-failure` | | `ctest --test-dir .harness/build -C Debug --show-only=json-v1` | `ctest --preset windows-msvc-ninja-debug --show-only=json-v1` | | `ctest --test-dir .harness/build -C Debug --output-on-failure` | `ctest --preset windows-msvc-ninja-debug --output-on-failure` | Table의 regex 표시는 새 선택값이 아니다. 현재 Step 명령의 `-R` 인수 문자열 전체를 byte 의미 그대로 유지한다. Combined selection이 0보다 크다는 것만 확인하지 않고 [V1~V6](implementation-verification.md)의 새 mandatory test 이름도 discovery에서 확인한다. `fesa_tests`는 기존 unit/integration/reference 세 executable을 포함하는 aggregate target이다. Manual full C++ 검증에 넣을 정확한 명령 bundle은 다음과 같다. E8.2의 `$mfeArchive`는 새 binaryDir의 absolute forward-slash 경로다. Ninja preset은 Debug를 명시하므로 VS 전용 `-A x64`나 이전 `--test-dir`를 추가하지 않는다. ```powershell cmake --preset windows-msvc-ninja-debug "-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG=$mfeArchive" $mfeVerifyExit = $LASTEXITCODE if ($null -eq $mfeVerifyExit -or $mfeVerifyExit -ne 0) { exit $mfeVerifyExit } cmake --build --preset windows-msvc-ninja-debug $mfeVerifyExit = $LASTEXITCODE if ($null -eq $mfeVerifyExit -or $mfeVerifyExit -ne 0) { exit $mfeVerifyExit } ctest --preset windows-msvc-ninja-debug --show-only=json-v1 $mfeVerifyExit = $LASTEXITCODE if ($null -eq $mfeVerifyExit -or $mfeVerifyExit -ne 0) { exit $mfeVerifyExit } ctest --preset windows-msvc-ninja-debug --output-on-failure $mfeVerifyExit = $LASTEXITCODE if ($null -eq $mfeVerifyExit -or $mfeVerifyExit -ne 0) { exit $mfeVerifyExit } ``` Python은 E7 말미의 정확한 classifier/focused/full 세 호출을 같은 환경 wrapper 안에서 수행한다. Named venv, UV offline/cache, 기존 대상/assertions, 새 `.harness/build/p-<8hex>` basetemp80자 이하와 TEMP80자 이하를 유지한다. Already GREEN인 timeout/classifier source를 RED로 되돌리지 않는다. 실제 보존된 RED/GREEN을 읽고 classifier37/focused136 및 남은 full pytest를 현재 code로 재검증한다. r2 harness Correction1회는 사용 완료됐으며 두 번째 source correction을 시작하지 않는다. Native configure/build evidence에는 actual MSVC compiler/x64/Debug와 Ninja cache, CMake/CTest 명령·binaryDir, 새 warning0, 실제 `src/fesa/Debug/fesa_solver.lib`의 존재·SHA256·mtime를 기록한다. Library가 계획 위치에 없으면 환경 gate 실패로 반환한다. 기존 helper의 실제 mtime 판단을 유지하고 새 binary에 대한 fresh solve 및 정확 입력복사/hash를 확인한다. 기존 VS 결과를 새 graph의 fresh evidence로 옮기지 않는다. 새 graph의 최초 전체 suite 시간도 실제 측정하며, 이전 약27.9분 추정이나 finite cap을 성공/소요 보장으로 해석하지 않는다. 각 Step의 focused/full 및 registered Stop에 같은 graph가 사용됐는지 실제 raw를 대조한다. 기존 static reference 비교와 새 eigen Value10 비교의 승인 기준은 그대로다. 다음 Implementation은 보고서의 광범위한 reference 미사용 문장을 정정해 static full CTest가 원본 reference를 읽고 비교한다는 사실, 원본 직접 수정 없음, 새 eigen 비교 미실행을 구분한다. 과거 manual build 실패/미실행과 automatic pass도 보존한다. Source·수식·schema·tolerance·reference를 이 환경 준비에서 변경하지 않는다. 정상 native 대안이 실제 실패하면 결과를 보존해 Coordinator에 반환하며, 새 exact-run DFA 결정이 필요한지는 그 evidence로 판단한다. 지금 main까지 권한을 확대하지 않는다.