930 lines
63 KiB
Markdown
930 lines
63 KiB
Markdown
# 구현 환경·실행시간·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 경로가
|
|
`<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까지 권한을 확대하지 않는다.
|
|
|
|
## E9. Attempt4 후의 직렬 Ninja 검증
|
|
|
|
[R10](implementation-recovery.md#r10-attempt4의-errorhistory4-보존)이 우선이다.
|
|
[설치 모듈·생성 경로 관찰](../../.harness/build/mitc4-eigen-evidence/prep/attempt4/root-gtest-discovery-path-observation.json)
|
|
SHA256 `9d383f04a347df95b742403ceca4732b331ddf4ec96437993f0ceffaa060bf59`에서
|
|
세 POST_BUILD discovery가 누락된 TEST_TARGET 때문에 같은 JSON을 REMOVE/run/READ한다.
|
|
이는 병렬 공유 파일 경쟁을 뒷받침하며 최초 interleaving을 재현한 것은 아니다.
|
|
정상 환경 변수 `CMAKE_BUILD_PARALLEL_LEVEL=1`로 같은 Ninja build의 discovery를 직렬화한다.
|
|
CMake 설치 모듈, generated discovery, source/test/Hook/config와 timeout은 수정하지 않는다.
|
|
|
|
**Activation 미확정:** Root의 config-only [현재 resolver 관찰](../../.harness/build/mitc4-eigen-evidence/prep/attempt4/root-hook-config-resolution.json)은
|
|
canonical Stop1800 해석을 확인했다(server exit0, SHA256
|
|
`5deb9a701388605a14868198276993af3884f0cc76c48928831968b272f46de4`).
|
|
실제 native raw의 source event는 없으며 현재 resolver 결과와 외부 pwsh 약1802초 관찰을 구분한다.
|
|
남은 쟁점은 정상 override 지원·적용 방법이다. 이를 Coordinator가 검토하기 전 status reset/다음
|
|
실행을 할당하지 않는다. Canonical Hook 쓰기나 DFA·추가 timeout을 승인으로 추정하지 않는다.
|
|
아래는 이 조건 해소 후의 실행 계약이며 현재 실행 준비 완료 또는 실제 성공이 아니다.
|
|
|
|
부모 Coordinator invocation은 E8.2 block 전체를 사용하되
|
|
`$env:FEM_HARNESS_CODEX_SANDBOX = 'workspace-write'` 바로 다음에 다음 한 줄을 추가한다.
|
|
|
|
```powershell
|
|
$env:CMAKE_BUILD_PARALLEL_LEVEL = '1'
|
|
```
|
|
|
|
나머지 named Python/UVoffline/cache, dependency4, 새 짧은 TEMP/TMP와 E7 pytest basetemp,
|
|
Root에서 실제 성공한 installed x64 DevShell, 유한14400 module invocation과 finally의
|
|
전체 process 환경 복원은 그대로다. 따라서 registered Stop에도 같은 병렬도1과 graph가
|
|
상속된다. Actual configured outer Stop7500/shared·command7200 계약은 유지하지만 실제
|
|
설정 출처·종료 evidence를 확인해야 하며 새 cap을 만들지 않는다.
|
|
원래 invocation line은 그대로다.
|
|
|
|
```powershell
|
|
& $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' }
|
|
```
|
|
|
|
Native child tool shell에서는 E8.2 manual composition의 DevShell script 호출 한 줄을
|
|
아래 **상속 환경 검사**로 대체한다. 나머지 dependency/Python/짧은 TEMP·병렬도1 설정과
|
|
finally는 그대로 적용한다. 실행 정책 변경이나 우회 인수를 사용하지 않는다.
|
|
부모가 제공한 x64 환경이 없으면 검증 명령을 시작하지 않고 blocked-environment로 반환한다.
|
|
|
|
```powershell
|
|
if ($env:VSCMD_ARG_TGT_ARCH -notin @('x64','amd64') -or
|
|
[string]::IsNullOrWhiteSpace($env:VSINSTALLDIR) -or
|
|
[string]::IsNullOrWhiteSpace($env:INCLUDE) -or
|
|
[string]::IsNullOrWhiteSpace($env:LIB)) { throw 'Inherited MSVC x64 environment missing' }
|
|
$mfeCl = (Get-Command cl.exe -ErrorAction Stop).Source
|
|
$mfeNinjaExe = (Get-Command ninja.exe -ErrorAction Stop).Source
|
|
if ($mfeCl -notmatch '[\\/]Hostx64[\\/]x64[\\/]cl.exe$') { throw 'Unexpected compiler architecture' }
|
|
Write-Output ("Inherited compiler={0}; Ninja={1}" -f $mfeCl, $mfeNinjaExe)
|
|
$env:CMAKE_BUILD_PARALLEL_LEVEL = '1'
|
|
```
|
|
|
|
새 prep의 첫 manual build는 아래 **한 번의 clean-first full build**다. 새 Ninja graph의
|
|
기존 성공 후 no-op build를 경쟁 해소 evidence로 보고하지 않도록, 실제 세 executable
|
|
link와 POST_BUILD discovery를 같은 직렬 build에서 다시 실행한다. CMake의 기존
|
|
clean-first만 사용하며 기존 VS cache나 reference/evidence를 삭제하지 않는다.
|
|
Registered Stop과 후속 통상 build는 E8의 일반 build 명령에 병렬도1을 상속한다.
|
|
|
|
```powershell
|
|
cmake --preset windows-msvc-ninja-debug "-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG=$mfeArchive"
|
|
$mfeVerifyExit = $LASTEXITCODE
|
|
if ($null -eq $mfeVerifyExit) { throw 'Configure exit unavailable' }
|
|
if ($mfeVerifyExit -ne 0) { exit $mfeVerifyExit }
|
|
cmake --build --preset windows-msvc-ninja-debug --clean-first --verbose
|
|
$mfeVerifyExit = $LASTEXITCODE
|
|
if ($null -eq $mfeVerifyExit) { throw 'Build exit unavailable' }
|
|
if ($mfeVerifyExit -ne 0) { exit $mfeVerifyExit }
|
|
ctest --preset windows-msvc-ninja-debug --show-only=json-v1
|
|
$mfeVerifyExit = $LASTEXITCODE
|
|
if ($null -eq $mfeVerifyExit) { throw 'Discovery exit unavailable' }
|
|
if ($mfeVerifyExit -ne 0) { exit $mfeVerifyExit }
|
|
ctest --preset windows-msvc-ninja-debug --output-on-failure
|
|
$mfeVerifyExit = $LASTEXITCODE
|
|
if ($null -eq $mfeVerifyExit) { throw 'CTest exit unavailable' }
|
|
if ($mfeVerifyExit -ne 0) { exit $mfeVerifyExit }
|
|
```
|
|
|
|
Verbose log에는 `fesa_unit_tests_576e7e9d_discovery.cmake`,
|
|
`fesa_integration_tests_d537bc73_discovery.cmake`,
|
|
`fesa_reference_tests_ac7cf2f0_discovery.cmake`의 실제 세 호출과 성공을 보존한다.
|
|
세 `*_tests.cmake`의 새 mtime/hash·등록 identity와 full discovery JSON을 대조한다.
|
|
현재 prep inventory는 unit289/integration34/reference39, 총362다. 명령이 실제 각 target의
|
|
올바른 tests를 등록했는지 확인하며 합계나 leftover JSON의 존재만으로 통과하지 않는다.
|
|
Generated suffix가 바뀌면 actual build graph의 각 target 매핑을 기록하고 임의 파일을 만들지 않는다.
|
|
|
|
새 `src/fesa/Debug/fesa_solver.lib`와 세 executable의 hash/mtime를 기록한다.
|
|
이 새 binary에 대한 required manual full CTest의 fresh reference solve, 입력 복사/hash와
|
|
결과 생성 시각을 확인하고 그 뒤 registered same-binary full의 정상 cache 재사용과 구분한다.
|
|
Manual fresh solve를 cached-only 자동 실행으로 대체하지 않는다. 각 raw log를 덮어쓰기 전에
|
|
새 attempt evidence로 보존한다. No-op 관찰·단독 진단·합산 duration은 full gate가 아니다.
|
|
|
|
E7의 classifier37/focused136/full pytest 대상과 모든 assertion은 유지한다. 새 invocation에서
|
|
각 필수 검증을 수행하되 현재 code에서 한 번 통과한 focused136을 근거 없이 반복하지 않는다.
|
|
과거 attempt4의 focused136 실제 세 반복이 모두 exit0이었다는 사실도 보존한다.
|
|
이미 GREEN인 source를 RED로 되돌리지 않으며 두 번째 source Correction을 시작하지 않는다.
|
|
기존 전체 Python, native configure/build/discovery/CTest와 실제 registered Stop 성공이 모두
|
|
필수다. Full pytest/CTest의 미실행 상태를 다음 owner가 실제 evidence로 해소한다.
|
|
|
|
Implementation owner는 보고서의 역사적 reference 미사용 문장을 정정해 full CTest의 기존
|
|
static reference 읽기·비교, 원본 직접 수정 없음과 새 eigen 비교 미실행을 구분한다.
|
|
과거 manual failure와 registered pwsh1/Python0/CTest0도 각각 보존한다.
|
|
Result payload는 manual 결과와 아직 미관찰인 Stop을 구분하며 Coordinator가 실제 종료 후
|
|
검토한다. Active Executor 동안 Root/Coordinator는 non-owned edits/commits를 멈춘다.
|
|
Main은 prep 전체 gate 뒤 별도 workspace-write invocation만 허용하며 E9의 병렬도1을
|
|
같이 사용한다. 새로운 동일 실패는 원시 evidence와 기존 retry key로 반환한다.
|
|
|
|
## E10. 부모 환경과 독립적인 workspace user preset
|
|
|
|
[Root Stop 실패](../../.harness/build/mitc4-eigen-evidence/prep/attempt4/root-stop-after-decision-docs/observation.json)는
|
|
parent env4 미설정과 public preset의 cache4 빈 값 overwrite/configure1을 보존한다.
|
|
현재 실패 cache hash는 `125a4dbd163c5a0a6d94bd03d3186790c41e6a0d8e0ed7b9c72f18fdf619d66e`다.
|
|
이는 MFE-OQ-004 승인 답변이 아니다. Canonical Hook·재신뢰는 계속 미승인이고 새 native/
|
|
status reset도 미할당이다. 아래는 별도 Root 실행을 위한 문서 계획이며 현재 setup은 미실행이다.
|
|
|
|
[Toolchain](../../scripts/msvc_harness/toolchain.py)은 executable 경로만 찾으며
|
|
[Stop](../../scripts/hooks/stop_validation.py)은 parent env를 복사한다. 따라서 root
|
|
`CMakeUserPresets.json`의 `mfe-workspace-msvc-ninja-debug`가 public preset을 상속하고
|
|
dependency4 literal cache와 최소 MSVC INCLUDE/LIB/tool PATH를 제공하도록 한다.
|
|
Installed CMake4.4 `Help/manual/cmake-presets.7.rst`의 user/common 자동 include,
|
|
`$penv{PATH}`, build/test `inheritConfigureEnvironment`를 사용한다. Public preset,
|
|
Harness API/config schema와 source/test/Hook은 바꾸지 않는다.
|
|
|
|
Build/test는 configure 환경을 상속한다. 같은 Ninja binaryDir·MSVC Hostx64/x64·Debug,
|
|
실제 Debug archive 경로와 직렬 병렬도1을 유지한다. Root의 정상 DevShell에서 INCLUDE/LIB,
|
|
cl/rc/mt/Ninja directory만 capture하고 전체 env·비밀값은 preset에 저장하지 않는다.
|
|
Parent process는 finally에서 복원한다. 이후 arbitrary Root process에도 CMake child가
|
|
자체 preset 환경을 적용하므로 parent env4/DevShell 지속성을 전제로 삼지 않는다.
|
|
|
|
Preset TEMP/TMP는 setup에서 만든 새80자 이하 ignored 디렉터리를 **설정 수명 동안**
|
|
사용한다. CMake child에서는 이 값이 E7/E9의 매회 parent TEMP를 대체한다. 기존 model/test의
|
|
고유 child directory 생성은 유지하고 동시 build/test가 없는지 Root가 setup 전에 실제 확인한다.
|
|
Python/pytest는 기존 per-invocation 새 짧은 TEMP와 basetemp를 유지한다. 기존 디렉터리/
|
|
evidence 삭제, 권한·실행 정책 변경이나 Hook 우회는 없다.
|
|
|
|
### E10.1. Root의 exact setup과 configure-only 확인
|
|
|
|
순서는 Planning3 동결 → Root docs checkpoint → 아래 setup → 실제 observation/최소 문서
|
|
갱신과 Root exact commit이다. 현재 UserPresets는 미존재·미ignore다. Root가 별도 소유하는
|
|
tracked 변경은 [.gitignore](../../.gitignore)의 `/CMakeUserPresets.json` 한 줄뿐이다.
|
|
그 줄을 Root가 검토·commit하며 public preset과 Implementation owned9/phase 범위는 유지한다.
|
|
UserPresets/local config/TEMP/backup/Ninja configure output은 ignored로 둔다.
|
|
|
|
```powershell
|
|
$ErrorActionPreference = 'Stop'
|
|
$mfeRoot=(Get-Location).Path
|
|
$mfePython=Join-Path $mfeRoot '.harness/build/mitc4-eigen-evidence/prep/classifier-correction/pytest-venv/Scripts/python.exe'
|
|
$mfeCmake=(Get-Command cmake.exe -ErrorAction Stop).Source
|
|
$mfePreset='mfe-workspace-msvc-ninja-debug'
|
|
$mfeGitRoot=git rev-parse --show-toplevel
|
|
if ($LASTEXITCODE -ne 0 -or [IO.Path]::GetFullPath($mfeGitRoot) -ne [IO.Path]::GetFullPath($mfeRoot)) { throw 'Repository mismatch' }
|
|
$mfeDirty=git status --porcelain
|
|
if ($LASTEXITCODE -ne 0 -or $mfeDirty) { throw 'Root docs checkpoint and clean required' }
|
|
if (Test-Path -LiteralPath 'CMakeUserPresets.json') { throw 'Preserve existing UserPresets' }
|
|
$mfeInputs=@{
|
|
'.gitignore'='b81d422ee0185f16714e3218369689b808701e5e398a6f687a22784da2290842'
|
|
'.harness/config.json'='3ebdfa80124f1eb96909b2738d6f2a96fecd55cce61150a9cd7ef27d7c5fd892'
|
|
'.harness/build-ninja-msvc-debug/CMakeCache.txt'='125a4dbd163c5a0a6d94bd03d3186790c41e6a0d8e0ed7b9c72f18fdf619d66e'
|
|
}
|
|
foreach ($mfePath in $mfeInputs.Keys) {
|
|
if ((Get-FileHash -LiteralPath $mfePath).Hash.ToLower() -ne $mfeInputs[$mfePath]) { throw "Changed input: $mfePath" }
|
|
}
|
|
$mfeBackup=Join-Path $mfeRoot ('.harness/build/mfe-preset-'+[guid]::NewGuid().ToString('N').Substring(0,8))
|
|
$mfeTemp=Join-Path $mfeRoot ('.harness/build/t-'+[guid]::NewGuid().ToString('N').Substring(0,8))
|
|
if ($mfeTemp.Length -gt 80 -or (Test-Path -LiteralPath $mfeTemp) -or (Test-Path -LiteralPath $mfeBackup)) { throw 'Fresh short paths required' }
|
|
$null=New-Item -ItemType Directory -Path $mfeBackup
|
|
$null=New-Item -ItemType Directory -Path $mfeTemp
|
|
Copy-Item -LiteralPath '.gitignore' -Destination (Join-Path $mfeBackup 'gitignore.before')
|
|
Copy-Item -LiteralPath '.harness/config.json' -Destination (Join-Path $mfeBackup 'config.before.json')
|
|
Copy-Item -LiteralPath '.harness/build-ninja-msvc-debug/CMakeCache.txt' -Destination (Join-Path $mfeBackup 'CMakeCache.before.txt')
|
|
$mfeUtf8=[Text.UTF8Encoding]::new($false)
|
|
[IO.File]::WriteAllText((Join-Path $mfeBackup 'before.json'),(@{hashes=$mfeInputs; userPresetsExisted=$false; temp=$mfeTemp}|ConvertTo-Json -Depth 6),$mfeUtf8)
|
|
$mfeProtected=@('CMakePresets.json','.codex/hooks.json','scripts/execute.py','tests/test_execute.py','phases/index.json','phases/mitc4-shell-feast-eigen-execution-prep/index.json','phases/mitc4-shell-feast-eigen-execution-prep/step0-output.json','.harness/build/CMakeCache.txt')
|
|
$mfeHashes=@{}
|
|
foreach ($mfePath in $mfeProtected) { $mfeHashes[$mfePath]=(Get-FileHash -LiteralPath $mfePath).Hash }
|
|
$mfeBeforeEnv=[Environment]::GetEnvironmentVariables('Process')
|
|
try {
|
|
$mfeVs='C:/Program Files/Microsoft Visual Studio/18/Community'
|
|
& (Join-Path $mfeVs 'Common7/Tools/Launch-VsDevShell.ps1') -VsInstallationPath $mfeVs -Arch amd64 -HostArch amd64 -SkipAutomaticLocation -NoLogo
|
|
$mfeCl=(Get-Command cl.exe -ErrorAction Stop).Source
|
|
$mfeRc=(Get-Command rc.exe -ErrorAction Stop).Source
|
|
$mfeMt=(Get-Command mt.exe -ErrorAction Stop).Source
|
|
$mfeNinja=Join-Path $mfeVs 'Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja/ninja.exe'
|
|
if ($env:VSCMD_ARG_TGT_ARCH -notin @('x64','amd64') -or $mfeCl -notmatch '[\\/]Hostx64[\\/]x64[\\/]cl\.exe$') { throw 'MSVC x64 required' }
|
|
if (-not(Test-Path -LiteralPath $mfeNinja) -or [string]::IsNullOrWhiteSpace($env:INCLUDE) -or [string]::IsNullOrWhiteSpace($env:LIB)) { throw 'Toolchain incomplete' }
|
|
$mfeDirs=@((Split-Path $mfeCl),(Split-Path $mfeNinja),(Split-Path $mfeRc),(Split-Path $mfeMt))|Select-Object -Unique
|
|
$mfeEnv=@{INCLUDE=$env:INCLUDE; LIB=$env:LIB; PATH=($mfeDirs -join ';')+';$penv{PATH}'; TEMP=$mfeTemp.Replace('\','/'); TMP=$mfeTemp.Replace('\','/'); CMAKE_BUILD_PARALLEL_LEVEL='1'}
|
|
$mfeCache=@{
|
|
FESA_GTEST_SOURCE_DIR='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'
|
|
CMAKE_CXX_COMPILER=$mfeCl.Replace('\','/')
|
|
CMAKE_MAKE_PROGRAM=$mfeNinja.Replace('\','/')
|
|
CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG=('$'+'{sourceDir}/.harness/build-ninja-msvc-debug/src/fesa/Debug')
|
|
}
|
|
$mfeUser=@{
|
|
version=3
|
|
configurePresets=@(@{name=$mfePreset; inherits='windows-msvc-ninja-debug'; cacheVariables=$mfeCache; environment=$mfeEnv})
|
|
buildPresets=@(@{name=$mfePreset; inherits='windows-msvc-ninja-debug'; configurePreset=$mfePreset; inheritConfigureEnvironment=$true})
|
|
testPresets=@(@{name=$mfePreset; inherits='windows-msvc-ninja-debug'; configurePreset=$mfePreset; inheritConfigureEnvironment=$true})
|
|
}
|
|
}
|
|
finally {
|
|
foreach ($mfeName in @([Environment]::GetEnvironmentVariables('Process').Keys)) {
|
|
if (-not $mfeBeforeEnv.Contains($mfeName)) { [Environment]::SetEnvironmentVariable($mfeName,$null,'Process') }
|
|
}
|
|
foreach ($mfeName in $mfeBeforeEnv.Keys) { [Environment]::SetEnvironmentVariable($mfeName,$mfeBeforeEnv[$mfeName],'Process') }
|
|
}
|
|
$mfeOriginalIgnore=[IO.File]::ReadAllBytes((Join-Path $mfeRoot '.gitignore'))
|
|
if ($mfeOriginalIgnore[-1] -ne 10) { throw 'Unexpected ignore EOF' }
|
|
$mfeSuffix=$mfeUtf8.GetBytes('/CMakeUserPresets.json'+[Environment]::NewLine)
|
|
[IO.File]::WriteAllBytes((Join-Path $mfeRoot '.gitignore'),[byte[]]($mfeOriginalIgnore+$mfeSuffix))
|
|
git check-ignore --quiet CMakeUserPresets.json
|
|
if ($LASTEXITCODE -ne 0) { throw 'UserPresets must be ignored' }
|
|
[IO.File]::WriteAllText((Join-Path $mfeRoot 'CMakeUserPresets.json'),($mfeUser|ConvertTo-Json -Depth 10)+[Environment]::NewLine,$mfeUtf8)
|
|
$mfeConfig=Get-Content -LiteralPath '.harness/config.json' -Raw|ConvertFrom-Json
|
|
$mfeConfig.cmake.configurePreset=$mfePreset
|
|
$mfeConfig.cmake.buildPreset=$mfePreset
|
|
$mfeConfig.cmake.testPreset=$mfePreset
|
|
[IO.File]::WriteAllText((Join-Path $mfeRoot '.harness/config.json'),($mfeConfig|ConvertTo-Json -Depth 10)+[Environment]::NewLine,$mfeUtf8)
|
|
foreach ($mfeName in @('FESA_GTEST_SOURCE_DIR','MKL_DIR','TBB_DIR','HDF5_DIR')) {
|
|
if (-not [string]::IsNullOrEmpty([Environment]::GetEnvironmentVariable($mfeName,'Process'))) { throw 'Separate env4-unset configure verification required' }
|
|
}
|
|
$mfeExit=$null
|
|
try {
|
|
& $mfeCmake --list-presets=all
|
|
$mfeExit=$LASTEXITCODE
|
|
if ($null -eq $mfeExit) { throw 'Preset validation exit unavailable' }
|
|
if ($mfeExit -ne 0) { exit $mfeExit }
|
|
& $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==c.cmake.build_preset==c.cmake.test_preset=='mfe-workspace-msvc-ninja-debug'; assert c.cmake.binary_dir==Path.cwd()/'.harness/build-ninja-msvc-debug'; print('Local config valid')"
|
|
$mfeExit=$LASTEXITCODE
|
|
if ($null -eq $mfeExit) { throw 'Config validation exit unavailable' }
|
|
if ($mfeExit -ne 0) { exit $mfeExit }
|
|
& $mfeCmake --preset mfe-workspace-msvc-ninja-debug
|
|
$mfeExit=$LASTEXITCODE
|
|
if ($null -eq $mfeExit) { throw 'Configure exit unavailable' }
|
|
}
|
|
finally {
|
|
$mfeAfter=@{}
|
|
foreach ($mfePath in @('.gitignore','CMakeUserPresets.json','.harness/config.json','.harness/build-ninja-msvc-debug/CMakeCache.txt')) {
|
|
$mfeAfter[$mfePath]=(Get-FileHash -LiteralPath $mfePath).Hash.ToLower()
|
|
}
|
|
[IO.File]::WriteAllText((Join-Path $mfeBackup 'after.json'),(@{hashes=$mfeAfter; lastNativeExit=$mfeExit}|ConvertTo-Json -Depth 6),$mfeUtf8)
|
|
foreach ($mfePath in $mfeProtected) {
|
|
if ((Get-FileHash -LiteralPath $mfePath).Hash -ne $mfeHashes[$mfePath]) { throw "Non-owned change: $mfePath" }
|
|
}
|
|
}
|
|
$mfeFinalDirty=git status --porcelain
|
|
if ($LASTEXITCODE -ne 0 -or @($mfeFinalDirty).Count -ne 1 -or $mfeFinalDirty -ne ' M .gitignore') { throw 'Unexpected tracked changes' }
|
|
git diff --check -- .gitignore
|
|
if ($LASTEXITCODE -ne 0) { throw 'Ignore whitespace check failed' }
|
|
Write-Output ("Setup evidence: {0}; configure exit {1}" -f $mfeBackup,$mfeExit)
|
|
exit $mfeExit
|
|
```
|
|
|
|
Original3파일 bytes/hash와 UserPresets 부재를 mutation 전에 backup하고, 실제 CMake
|
|
`--list-presets=all` schema/inheritance 해석 및 `load_config` 뒤 **env4 unset 상태의
|
|
configure만** 수행한다. Root는 after cache의 dependency4, Ninja/Debug, compiler 경로·
|
|
pointer size8, archive 경로와 새 user/config/cache hash를 기록한다. Actual adapter plan의
|
|
configure/build/discovery/test 네 명령도 같은 local preset으로 대조한다.
|
|
Library/build/CTest 성공은 configure evidence가 아니다. HEAD/phase history4/source/
|
|
reference/old VS cache 불변, tracked diff가 ignore1줄뿐인지 감사한 뒤 Root가 exact commit한다.
|
|
자동 Root outer Stop이 발생하면 실제 결과를 따로 관찰하며 manual Hook으로 대체하지 않는다.
|
|
|
|
### E10.2. 기존 명령의 명시 대체와 수명
|
|
|
|
Setup 성공을 별도 감사한 뒤 E8/E9 및 모든 prep/main 명령의 preset 인수를 아래로 대체한다.
|
|
Configure의 archive는 user cache가 고정하므로 예전 추가 `-D`가 필요 없다.
|
|
|
|
| 목적 | 정확한 새 명령 |
|
|
| --- | --- |
|
|
| Configure | `cmake --preset mfe-workspace-msvc-ninja-debug` |
|
|
| E9 최초 실제 직렬 재검증 build | `cmake --build --preset mfe-workspace-msvc-ninja-debug --clean-first --verbose` |
|
|
| 일반 full/registered build | `cmake --build --preset mfe-workspace-msvc-ninja-debug` |
|
|
| Main focused target build | `cmake --build --preset mfe-workspace-msvc-ninja-debug --target fesa_tests` |
|
|
| Discovery | `ctest --preset mfe-workspace-msvc-ninja-debug --show-only=json-v1` |
|
|
| Full CTest | `ctest --preset mfe-workspace-msvc-ninja-debug --output-on-failure` |
|
|
|
|
Focused CTest는 원 Step의 `-R` 문자열을 그대로 유지하고 preset 인수만 위 이름으로 바꾼다.
|
|
E9 세 discovery의 실제 실행/등록 identity·새 binary hash/mtime·fresh manual solve 및
|
|
registered same-binary full 구분, 전체 Python/CTest, 수치/reference 계약은 유지한다.
|
|
CMake 검증에 한해 E8/E9의 외부 shell DevShell 재호출·cl/Ninja 사전 검색 조건을 user preset과
|
|
actual compiler/cache evidence로 대체한다. Python/UV recipe와 finite14400/7500/7200
|
|
계약, workspace-write 및 모든 Hook/retry/ownership guard는 그대로다.
|
|
실제 canonical outer1800·재신뢰 문제는 이 local setup으로 해결됐다고 주장하지 않는다.
|
|
|
|
[Preset contract test](../../tests/test_harness_preset_contract.py)는 tracked public preset/
|
|
config.example과 tmp_path에 복사한 example을 검사하며 실제 local config/UserPresets를
|
|
읽지 않는다. Public/example 불변과 기존 ignore 항목 보존 시 이 선택과 모순되지 않는다.
|
|
테스트 소스/대상/assertions는 수정하지 않았고 이 Planning에서 테스트를 실행하지 않았다.
|
|
|
|
Rollback은 active 실행이 없고 after hash와 현재 파일이 동일한 경우에 Root가 수행한다.
|
|
`.gitignore`와 local config는 backup bytes로 복원하고, 원래 없었던 정확한
|
|
`CMakeUserPresets.json`만 `Remove-Item -LiteralPath`로 비재귀 제거한다.
|
|
필요 시 `CMakeCache.before.txt`를 원래 exact cache 경로에 복사하되 **기존 실패 cache
|
|
복원**임을 기록한다. Generated outputs/TEMP/evidence는 삭제하지 않고 graph 유효성이나
|
|
검증 성공을 주장하지 않는다. 이미 ignore1줄을 commit했다면 Root의 exact inverse commit을
|
|
사용하고 history reset은 하지 않는다. 타 owner 변경이 있으면 덮어쓰지 않고 반환한다.
|
|
설정은 해당 workspace에 유지하며 feature 종료·설치 경로 변경 때 Root가 수명을 검토한다.
|