docs: prepare MSVC Ninja environment recovery

This commit is contained in:
KOKO\Mimi
2026-09-06 16:28:38 +09:00
parent 96efbffa42
commit 7d714c2713
5 changed files with 344 additions and 32 deletions
@@ -53,8 +53,8 @@ Reference artifact와 공통 정책은 수정하지 않는다. 외부 solver 실
| [io-schema.md](io-schema.md) | io-definition-agent | r2 | 기존 static 보존·eigen discriminant·N vectors/all-c evidence·self-check |
| [io-mapping.md](io-mapping.md) | io-definition-agent | r2 | 책임·candidate 보존·TXT Value-only·27개 요구/11개 I/O 검증 obligation |
| [implementation-plan.md](implementation-plan.md) | implementation-planning-agent | r2 | Prep 1/main 8개 step 및 실행 계획 gate pass |
| [implementation-environment.md](implementation-environment.md) | implementation-planning-agent | r2 | 실제 backend·유한 deadline·bootstrap/activation·Git/사후 evidence 경계 |
| [implementation-recovery.md](implementation-recovery.md) | implementation-planning-agent | r2 | R8 attempt3 실패 보존 명령 감사 완료; E8 정상 backend 요약은 미실행이며 상세 활성화 미확정 |
| [implementation-environment.md](implementation-environment.md) | implementation-planning-agent | r2 | E8 기존 Ninja preset의 exact Root setup/native·registered same graph 명령 감사 완료; actual native 성공은 미검증 |
| [implementation-recovery.md](implementation-recovery.md) | implementation-planning-agent | r2 | R8 실패 보존 실제 완료; R9 별도 status-only/Executor checkpoint 계획 감사 완료, 실행 상태는 coordination |
| [implementation-interfaces.md](implementation-interfaces.md) | implementation-planning-agent | r2 | 기존 확장점·API/source-test·vendor/state/transaction 책임 |
| [implementation-verification.md](implementation-verification.md) | implementation-planning-agent | r2 | 요구27/NR27/I/O11·신규 test40·독립 oracle·fresh evidence·실제 validator |
| [implementation-prep-evidence.md](implementation-prep-evidence.md) | implementation-agent | r2 | attempt1/2 역사와 attempt3 classifier37/focused136 pass·manual build 환경 차단; 별도 registered362 pass와 terminal 판정은 coordination 참조 |
+9 -1
View File
@@ -5,7 +5,7 @@
- Contract revision: `r2` (사용자 승인 stabilization 개선·영향받는 정적/eigen 재검증 범위)
- Stage: `implementation` (E7 attempt3 종료; native build 환경 복구 검토)
- Outcome: `blocked-environment`
- Next owner: `Executor` (R8 exact report1/blocked controls2 보존; 이후 Planning의 E8 상세 delta)
- Next owner: `Root` (E8.1 exact ignored 환경 setup; 이후 Planning의 R9 status-only 할당)
- Attempt: `3` (실제 blocked/history3; 기존 history2 보존)
- Completion: 미완료
- Failure classification: `environment`
@@ -45,6 +45,14 @@ Root의 intake 시작 Git 조사에서는 worktree clean을 확인했다. 당시
## 현재 bounded dispatch
Owner의 [E8](implementation-environment.md#e8-attempt3-후의-정상-backend-대안)·[R9](implementation-recovery.md#r9-e8-활성화-전의-status-only-checkpoint) 상세를 owner/r2/현재 hash와 대조해 계획 gate `pass`로 수락했다. 실제 adapter의 preset 명령4/7200 cap·기존 guard, PowerShell18 blocks/errors0, Python AST7, local links91/missing0, 고정 hash7·Executor AST·blocked/history3 보존과 diffcheck가 exit `0`이다. Root는 설치 DevShell의 실제 인수, config.example/preset의 `.harness/build-ninja-msvc-debug`, load_config 필드 및 process 환경 전체 finally 복원을 read-only 확인했다. Native Ninja 성공은 아직 미검증이다.
동결된 management2/Planning3 정확5문서의 Root checkpoint 이후 **E8.1 첫 PowerShell block 그대로**를 Root 환경 지원에 할당한다. Owned 범위는 기존 예시와 같은 ignored `.harness/config.json`, 새 `.harness/build-ninja-msvc-debug` cache 및 새 짧은 ignored TEMP뿐이다. Source/Hook/reference/기존 VS cache/phase/status/Git은 setup에서 변경하지 않는다. Actual configure 및 config-selected graph/exit·전후 tracked bytes/clean 확인이 setup gate다. 이 prepare configure를 native build/full 검증으로 대체하지 않는다. 실패하면 실제 결과와 남은 ignored 설정을 보존하고 재실행하지 않는다. 성공 후 Coordinator가 audit하고 별도 Planning의 R9 status 한 값 복구와 actual Executor checkpoint를 할당한다. E8.2 native invocation은 그 이후 clean 상태에서 별도로 시작한다.
Root exact5문서 commit `c0f3dc7c11eca7959a10ca9f8aecb5343b831d13` 뒤 [R8 실제 보존 실행](../../.harness/build/mitc4-eigen-evidence/prep/attempt3/r8-wip-checkpoint-result.json)은 native/managed exit `0`, `2.094`초로 완료했다. Actual unchanged Executor가 report1을 `9601b1f53e8a11d3e08d49cf9528fa6f028108cf`, blocked controls2를 `96efbffa425ff5ce9cd1b7cebe673555273122b9`로 구분 commit했다. [실제 stdout](../../.harness/build/mitc4-eigen-evidence/prep/attempt3/r8-wip-checkpoint-stdout.log)은 exact paths, 전후 bytes/전체 JSON/history3/raw/branch 보존과 clean을 확인한다. `_commit_step` 또는 성공 전환은 없었다.
후속 Planning의 소유는 기존 plan/environment/recovery 3문서다. 이미 확인한 정상 Ninja preset과 표준 archive output 설정의 exact Root local setup, 별도 build directory, Step0/main8·registered Stop의 같은 graph 명령 mapping 및 실제 library 존재/hash/mtime 확인을 구체화한다. Source/기존 VS cache/reference 및 검사 guard를 보존하고, default workspace-write·명시 DevShell/dependency/Python/짧은 TEMP 환경과 기존 finite14400/7500/7200 한도를 유지한다. 이후 별도 할당의 status 한 값 복구/actual Executor checkpoint와 native 검증 순서도 문서화한다. 현재 config/status/재실행은 미할당이며 이 상세 delta의 syntax·owner·경로/명령 감사 전에는 실행하지 않는다. Root는 정확히 동결된 local 환경 설정만 수행하고 Coordinator는 실제 Executor invocation/전이·audit를 맡는다.
Owner의 [R8 실패 보존 명령](implementation-recovery.md#r8-attempt3의-blocked-기록-보존)을 현재 hash/role/guard와 대조해 계획 gate `pass`로 수락했다. 정적 결과는 local links82/missing0·Python AST6·R8 PowerShell errors0·고정 hash7/Executor AST/blocked history3 불변, exit `0`이다. Coordinator 관리2문서는 local links175/missing0·diffcheck exit `0`을 확인했다. Root가 동결된 management2/Planning3 정확5문서를 checkpoint한 뒤 R8 actual unchanged Executor가 report1과 controls2를 별도 WIP commit한다. 이는 실제 prep 검증 통과가 아니다. [E8 정상 Ninja 대안](implementation-environment.md#e8-attempt3-후의-정상-backend-대안)은 현재 미실행 요약이며 WIP 보존/clean 이후 별도 Planning이 exact local config/bootstrap·같은 graph의 명령 mapping·status-only/activation을 확정한다. 지금 config/status를 변경하거나 재실행하지 않는다.
E7 attempt3는 [실제 wrapper result](../../.harness/build/mitc4-eigen-evidence/prep/attempt3/executor-result.json)의 native PowerShell/managed exit `2`, `1372.328`초로 종료했다. HEAD `dc6b9b1cf70b0ca1685eb1ac5476aa6f8cd3dab6`와 branch, 모든 비소유 bytes는 불변이다. Dirty는 Implementation report1/control2뿐이며 source/tests/Hook은 변하지 않았다. [Terminal archive](../../.harness/build/mitc4-eigen-evidence/prep/attempt3/terminal-archive.json)는 raw SHA-256 `d106f7ade2d678b6e0b383439b1b9b8d25f5ec32e883aed50c6fb4949a8983f1`, blocked/history3와 이전 history2 equality를 보존한다(exit `0`). Actual Codex exit `0`, 명시 reported-blocked 및 transportFailure null을 별도로 기록하며 transport retry로 재분류하지 않는다. Owner의 attempt1 표기는 전이 요청 이력으로 보존하고 Coordinator 원본은 실제 history3다.
@@ -253,36 +253,7 @@ foreach ($mfeRun in $mfePytestRuns) {
}
```
## E8. Attempt3 후의 정상 backend 대안
E7의 짧은 TEMP/TMP는 actual native build shell에 적용됐지만 FileTracker 접근 거부가
재발했다. 환경 누락으로 해석하지 않는다. 현재 우선 작업은
[R8](implementation-recovery.md#r8-attempt3의-blocked-기록-보존)의 실패 보존이며,
아래는 다음 bounded delta에서 구체화할 정상 backend 대안이다. 설정·configure·build·
Executor 재실행은 이번 Planning에서 수행하지 않았다.
저장소의 [MSVC Ninja preset](../../CMakePresets.json)과
[local config 예시](../../.harness/config.example.json)는 동일 Ninja graph를 manual 검증과
registered Stop이 선택할 수 있는 기존 경로다. MSVC/x64/Debug, 테스트·Hook·유한
7200/7500/14400초 한도와 workspace-write는 유지한다. 기존 config/adapter에 없는
Ninja Multi-Config 선택 기능이나 새 public preset은 만들지 않는다.
Single-config의 실제 archive 출력에는 기존 reference helper가 확인하는
`src/fesa/Debug/fesa_solver.lib`가 필요하다. 표준 CMake cache 변수
`CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG`로 새 ignored build의 해당 디렉터리를 지정하는
대안을 검토했다. Local CMake help는 archive target 속성 초기화 의미를 확인했지만,
이 선택의 actual native configure/build/full VERIFY 성공은 아직 미검증이다.
실제 library 위치/hash/mtime와 기존 cache freshness를 확인해야 하며 파일 복사나 mtime
조작으로 cache guard를 만족시키지 않는다. 기존 VS cache와 attempt evidence는 보존한다.
다음 delta에서 Root 소유의 exact ignored config/환경 setup과 Coordinator 소유의
unchanged Executor invocation을 분리해 확정한다. Prep/main의 기존 고정 build 경로를
새 preset graph에 대응시키는 명령과 registered Stop의 같은 graph 선택까지 명시한 뒤
활성화한다. 현재 E8 요약만으로 이전 명령을 임의 대체하거나 재실행하지 않는다.
기존 named Python/UV offline, 짧은 새 TEMP와 pytest basetemp, process 환경 복원은 유지한다.
이 정상 대안에는 새 DFA 승인을 요청하지 않는다. 이전 one-time DFA 승인은 소진됐으며,
정상 대안이 실제 실패하면 그 evidence로 exact-run의 새 결정을 별도로 다룬다.
Main은 prep 전체 gate와 Coordinator의 사후 감사 전 활성화하지 않는다.
CMake/MSVC/x64/Debug configure/build와 전체 CTest discovery/run은 기존 Step0의 정확한
명령을 같은 inherited TEMP/TMP에서 별도로 실행한다. 실패 시 actual command/exit와 남은
@@ -396,3 +367,260 @@ foreach ($mfeRun in $mfePytestRuns) {
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 경로가
`<new binaryDir>/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 '<Step 원문 regex>' --show-only=json-v1` | `ctest --preset windows-msvc-ninja-debug -R '<같은 원문 regex>' --show-only=json-v1` |
| `ctest --test-dir .harness/build -C Debug -R '<Step 원문 regex>' --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까지 권한을 확대하지 않는다.
@@ -29,6 +29,12 @@ error/history2 WIP 보존 뒤 [E7](implementation-environment.md#e7-짧은-temp
report1/controls2 blocked/history3 WIP 보존이다. [E8](implementation-environment.md#e8-attempt3-후의-정상-backend-대안)의
정상 Ninja 대안은 후속 bounded delta에서 명령을 확정하며 이번에는 설정·status reset·재실행하지 않는다.
R8 report/controls 보존은 실제 두 commit과 clean 확인까지 완료됐다. 현재
[E8](implementation-environment.md#e8-attempt3-후의-정상-backend-대안)은 Root의 ignored 설정 준비와
Coordinator의 별도 정상 Ninja invocation, 기존 Step 명령 대응을 확정한다.
[R9](implementation-recovery.md#r9-e8-활성화-전의-status-only-checkpoint)의 status-only 변경·checkpoint는
후속 할당으로 남는다. 이번 delta는 문서/정적 확인이며 native Ninja 성공은 아직 미검증이다.
[FEATURED_AGENTS](FEATURED_AGENTS.md), [PRD](PRD.md), [ADR](ADR.md)와
[coordination](coordination.md), 승인된 [requirements](requirements.md), [research](research.md),
[formulation](formulation.md), [NR](numerical-review.md), [I/O](io.md) 및 각 상세 r2를 적용한다.
@@ -646,3 +646,73 @@ blocked_reason/blocked_at/started_at/created_at 및 모든 다른 값, top/raw
새 eigen comparison 미실행, 기존 static regression 비교를 구분하도록 현재 광범위한
reference 미사용 문장을 바로잡는다. Planning은 해당 보고서를 수정하지 않는다.
Harness r2 source Correction1회는 사용 완료됐으며 두 번째 source correction은 허용하지 않는다.
## R9. E8 활성화 전의 status-only checkpoint
R8의 실제 두 commit과 clean/blocked/history3 보존은
[실제 결과](../../.harness/build/mitc4-eigen-evidence/prep/attempt3/r8-wip-checkpoint-result.json)에
있다. R8 본문은 당시 명령과 경계로 남긴다. 현재 activation은
[E8](implementation-environment.md#e8-attempt3-후의-정상-backend-대안)의 Root setup →
Coordinator 감사 → 별도 Planning status-only 할당 → 아래 actual Executor checkpoint →
clean → 새 workspace-write native 순서다. 이번 Planning 문서 작업에서는 status를 바꾸지 않는다.
별도 할당을 받은 Planning은 `phases/mitc4-shell-feast-eigen-execution-prep/index.json`의
`steps[0].status` 한 값만 `blocked -> pending`으로 바꾼다. 기존 history3, 모든
timestamp/block 필드, owned_paths와 다른 JSON값/형식, top/raw는 그대로 둔다.
Gate는 HEAD 불변·한 값 외 deep-equal·exact dirty1·보호 hash·diff check다.
이 결과를 감사한 Coordinator만 아래 unchanged `_commit_paths` 명령을 수행한다.
```powershell
$ErrorActionPreference = 'Stop'
$mfePython = Join-Path (Get-Location).Path '.harness/build/mitc4-eigen-evidence/prep/classifier-correction/pytest-venv/Scripts/python.exe'
if (-not (Test-Path -LiteralPath $mfePython -PathType Leaf)) { throw 'Named Python missing' }
@'
import hashlib,json
from pathlib import Path
from scripts import execute
phase="mitc4-shell-feast-eigen-execution-prep"
ex=execute.StepExecutor(phase);root=Path(ex._root)
assert Path.cwd().resolve()==root
assert Path(ex._run_git_checked("rev-parse","--show-toplevel").stdout.strip()).resolve()==root
assert ex._is_isolated_worktree() and ex._codex_sandbox_mode()=="workspace-write"
branch,head=ex._git_execution_identity();assert branch=="refs/heads/feat-"+phase
origin="96efbffa425ff5ce9cd1b7cebe673555273122b9"
ex._run_git_checked("merge-base","--is-ancestor",origin,"HEAD")
docs={"docs/mitc4-shell-feast-eigen/"+n for n in ("FEATURED_AGENTS.md","coordination.md",
"implementation-plan.md","implementation-environment.md","implementation-recovery.md")}
assert set(ex._run_git_checked("diff","--name-only","--no-renames",origin,"HEAD").stdout.splitlines())<=docs
protected={".codex/hooks.json":"e7e5d3c0c4fcd1e33b60680122ea7c42298d5cbde78a7f87d9e0007bf60a0fa4",
"scripts/execute.py":"64f5165fc544b3b17904c633ef3b222de79b52a0960e254c5b5c4eb99e79c2d0",
"tests/test_execute.py":"0eb0c1ca0f25199e00686b7e3ab57672b1390437d09da218a929added0346dd6",
"docs/mitc4-shell-feast-eigen/implementation-prep-evidence.md":"1e4d61997817b84b1df3933c6aa6518f030ca413edcda74393e0a0cf805e6732",
"phases/index.json":"42c9581868cc3f552ea3b42764a291098f648352f31021c7bdd7b4bebcdcf91e",
"phases/"+phase+"/step0-output.json":"d106f7ade2d678b6e0b383439b1b9b8d25f5ec32e883aed50c6fb4949a8983f1"}
for p,h in protected.items(): assert hashlib.sha256((root/p).read_bytes()).hexdigest()==h,p
path="phases/"+phase+"/index.json"
before=json.loads(ex._run_git_checked("show","HEAD:"+path).stdout)
assert before["steps"][0]["status"]=="blocked" and len(before["steps"][0]["attempt_history"])==3
expected=json.loads(json.dumps(before));expected["steps"][0]["status"]="pending"
assert ex._read_phase_index()==expected
assert set(ex._assert_step_scope(()))=={path}
assert not ex._run_git_checked("diff","--cached","--name-only").stdout.strip()
frozen={p:(root/p).read_bytes() for p in [path,*protected]}
assert ex._commit_paths([path],"chore(mitc4-shell-feast-eigen-execution-prep): queue MSVC Ninja environment recovery")
new_branch,new_head=ex._git_execution_identity()
assert new_branch==branch and new_head!=head
assert ex._run_git_checked("diff-tree","--no-commit-id","--name-only","-r",new_head).stdout.splitlines()==[path]
assert all((root/p).read_bytes()==v for p,v in frozen.items())
assert ex._read_phase_index()==expected and not ex._worktree_paths()
ex._preflight_repository()
print(json.dumps({"commit":new_head,"status":"pending","history_count":3,"clean":True}))
'@ | & $mfePython -B -X utf8 -
$mfeStatusExit = $LASTEXITCODE
if ($null -eq $mfeStatusExit) { throw 'Native exit unavailable' }
exit $mfeStatusExit
```
명령은 origin 이후 Root의 관리2/Planning3 선행 문서 checkpoint만 허용하고 source/Hook/
report/top/raw의 현재 hash를 확인한다. Phase control 한 경로만 commit하며
`_commit_step`, 완료/status 자동변경, guard override나 직접 Git commit은 사용하지 않는다.
Native exit를 즉시 전파하고 commit 전후 snapshot 및 clean preflight를 감사한다.
실패하면 bytes/원시 로그/이미 생성된 commit을 보존하고 다음 invocation을 시작하지 않는다.
E8 setup 또는 native 성공을 이 status checkpoint 성공에서 추론하지 않는다.