368 lines
24 KiB
Markdown
368 lines
24 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' }
|
|
}
|
|
```
|