Files
FESADev/phases/mitc4-shell-feast-eigen-execution-prep/step0.md
T
2026-10-04 03:32:59 +09:00

20 KiB

Step 0: 유한 실행시간 조정과 정상 검증 경로 보존

과거 실행 기록: 아래 지시·소유 경로는 당시 계획이며 현재 실행 입력이 아니다. 원문은 Git 858e87b에서 확인한다. 문서 링크는 통합된 기록으로 연결하며 새 작업은 현재 문서 안내와 기능 PRD를 따른다.

현재 실행 계약(r2): 모든 configure/build/CTest는 mfe-workspace-msvc-ninja-debug를 사용한다. MSVC x64 Debug, 동일 Ninja graph의 manual/registered 검증과 CMAKE_BUILD_PARALLEL_LEVEL=1을 유지한다. 과거 .harness/build VS 명령과 public preset 명령은 이 Step의 실행 명령을 대체하지 않는다. Targets/regex/필수 test identity·owned_paths·수치 계약은 그대로다. E10.2/E11을 적용한다. 긴 도구 호출은 결과 전체를 전달한다. session_id가 있으면 write_stdin으로 종료까지 이어받고, functions가 running cell을 반환했을 때만 해당 cell_id로 functions.wait를 사용한다. r.output만 비었다고 같은 명령을 다시 실행하지 않는다. 통과한 focused 검증은 새 변경/실패 없이 반복하지 않는다. Executor가 이미 만든 top/current control dirty 상태는 보호 snapshot이며 구현 소유권 위반으로 단정하지 않는다. 선택 Step의 result fields만 반환하고 timestamps/history/다른 metadata는 변경하지 않는다. 현재 prep는 이미 GREEN인 runtime/classifier의 재검증이다. 아래 초기 RED/GREEN 절차는 보존된 증거와 대조하며 RED를 만들기 위해 source를 되돌리지 않는다. 새 source Correction 없이 현재 manual full 검증을 완료한다.

  • Feature ID: mitc4-shell-feast-eigen
  • Plan owner: implementation-planning-agent
  • Execution owner: implementation-agent
  • Input contract revision: r2
  • Phase: mitc4-shell-feast-eigen-execution-prep
  • Requirement: FEM-REQ-MITC4-EIGEN-023/025; MFE-C27, IO-T11
  • 이 Step은 운영준비이고 solver physics/C++ 기능 변경이 아니다.

필수 입력

Feature 폴더 docs/mitc4-shell-feast-eigen/와 다음 management/approved bundle을 읽는다.

추가 필수: 현재 Executor, 등록 hooks (당시 경로: ../../.codex/hooks.json, 현재 checkout에 없음), Stop (당시 경로: ../../scripts/hooks/stop_validation.py, 현재 checkout에 없음), CommandSpec, process, config, CMake adapter, HARNESS, WORKFLOW, 환경·activation 상세. 현재 config schema에는 timeout option이 없다. 이번에 새 config field를 만들지 않는다.

재개 시 복구 계획과 실제 classifier 재현 (당시 경로: ../../.harness/build/mitc4-eigen-evidence/prep/attempt1/classifier-observation.json, 현재 checkout에 없음)을 추가 입력으로 읽는다. 아래 classifier delta는 기존 owned scripts/execute.py/tests/test_execute.py에 한정된 TDD 작업이다. 현재 blocked history와 실제 Hook 쓰기 거부는 그대로 보존한다. 현재 WIP 보존 뒤 별도 Correction Agent가 classifier 소스/테스트와 corrections.md를 먼저 완성한다. 그 실제 결과·별도 checkpoint 감사·수정 classifier를 읽는 새 process activation이 완료되기 전 이 prep를 재실행하지 않는다. 재개 Implementation은 선행 RED/GREEN evidence를 읽고 아래 회귀를 다시 실행하며, 이미 통과한 assertion을 새 RED라고 주장하지 않는다.

Owned paths

[
  "scripts/execute.py",
  ".codex/hooks.json",
  "scripts/hooks/stop_validation.py",
  "scripts/msvc_harness/models.py",
  "scripts/msvc_harness/process.py",
  "tests/test_execute.py",
  "tests/test_harness_timeouts.py",
  "docs/HARNESS_WORKFLOW.md",
  "docs/mitc4-shell-feast-eigen/implementation-prep-evidence.md"
]

타 owner 변경을 보존한다. docs/HARNESS_WORKFLOW.md는 실제 deadline 값의 설명 문단만 수정하고 workflow/approval/Git/Hook 계약을 바꾸지 않는다.

RED

먼저 tests/test_harness_timeouts.py를 작성한다. 실제 hook를 수동 실행하지 않고 기존 Python tests 방식으로 clock/subprocess/adapter를 주입한다.

  1. StepExecutor._invoke_codex가 기본14400초를 전달함과 실제 TimeoutExpired가 terminal result 없을 때만 최대2번 재시도되는 것을 검사한다. 기존 tests/test_execute.py의1800 message 기대값은 승인 default14400으로 갱신하되 explicit injected1800 exception의 actual timeout message는 그대로 구분한다.

  2. stop_validation.run_validations에서 새 shared deadline7200이 discovery/toolchain/execute_plan까지 같은 deadline으로 전달되는지 검사한다. Hook entry/reentry/doc-only 정책은 기존 tests로 보존한다.

  3. CommandSpec default7200 및 execute_plan 자체 default7200을 검사한다. Fake elapsed2000 뒤 다음 command cap이 remaining5200이고 explicit cap5이면5를 유지하는지, deadline 만료·nonzero subprocess가 계속 failure인지 확인한다. 실제 대기는 하지 않는다.

  4. 등록 Stop timeout7500이 shared7200보다 크며 command/matcher/PreToolUse timeout30이 그대로인지 검사한다. Executor14400>registered7500 관계와 finite positive 값을 확인한다.

  5. One-time module invocation은 딱 StepExecutor.CODEX_TIMEOUT_SECONDS만 유한14400으로 지정하고 unchanged execute.main()을 호출한다는 계약을 mock entry로 검사한다. Sandbox modes/default, MAX_TRANSPORT_ATTEMPTS, ownership/preflight/branch/commit/terminal result는 기존 tests를 유지한다.

  6. tests/test_execute.py에서 실제 _codex_environment_failure와 _classify_attempt, 기존 step_runtime을 사용하는 회귀를 먼저 추가한다. 필수 이름은 test_environment_classifier_ignores_successful_source_echo, test_environment_classifier_retains_runtime_helper_failure, test_successful_source_echo_preserves_terminal_and_retry다. 첫 test는 archive의 source excerpt와 실제 JSONL item.completed/command_execution/exit_code=0의 marker 포함 aggregated_output을 주입해 None을 기대한다. 성공 command가 실제 helper 오류 문장까지 source로 출력한 경우도 포함한다. 현재 broad substring은 environment로 오판하므로 RED다. 두 번째는 기존 실제 stderr helper diagnostic을 exit0/1에서 계속 검출하고, 성공 source echo와 진짜 stderr failure가 함께 있을 때도 차단함을 확인한다. 마지막은 성공 echo만 있는 completed/exit0의 완료, 명시 error/blocked의 원래 reason·history 보존, pending/exit0의 missing-result 오류, 실제 wrapper timeout만 최대2회 재시도되는 기존 분기를 검증한다. 이 positive regression들은 최초부터 pass할 수 있으므로 새 RED로 주장하지 않는다.

$mfePython = Join-Path (Get-Location).Path '.harness/build/mitc4-eigen-evidence/prep/classifier-correction/pytest-venv/Scripts/python.exe'
$mfePytestCache = Join-Path (Get-Location).Path '.harness/build/mitc4-eigen-evidence/prep/classifier-correction/pytest-cache'
$mfePytestBase = Join-Path (Get-Location).Path ('.harness/build/p-' + [guid]::NewGuid().ToString('N').Substring(0,8))
if ($mfePytestBase.Length -gt 80 -or (Test-Path -LiteralPath $mfePytestBase)) { throw 'Fresh short pytest basetemp required' }
& $mfePython -B -X utf8 -m pytest -v -rs -o "cache_dir=$mfePytestCache" "--basetemp=$mfePytestBase" tests/test_execute.py -k 'environment_classifier or successful_source_echo'

Case3개의 collection inventory/parameter 전개와 actual failure를 기록한다. 무관 import/setup 오류는 classifier RED가 아니다. 마지막 attempt1의 test-only .value 수정은 별도 미검증이므로 기존 focused 명령으로 실제 재확인하고 원 보고서도 Implementation owner가 수정한다.

$mfePython = Join-Path (Get-Location).Path '.harness/build/mitc4-eigen-evidence/prep/classifier-correction/pytest-venv/Scripts/python.exe'
$mfePytestCache = Join-Path (Get-Location).Path '.harness/build/mitc4-eigen-evidence/prep/classifier-correction/pytest-cache'
$mfePytestBase = Join-Path (Get-Location).Path ('.harness/build/p-' + [guid]::NewGuid().ToString('N').Substring(0,8))
if ($mfePytestBase.Length -gt 80 -or (Test-Path -LiteralPath $mfePytestBase)) { throw 'Fresh short pytest basetemp required' }
& $mfePython -B -X utf8 -m pytest -v -rs -o "cache_dir=$mfePytestCache" "--basetemp=$mfePytestBase" tests/test_harness_timeouts.py

Actual nonzero exit와 기존1800 기본값 때문에 실패한 assertions를 기록한다. Import/setup/인증 오류는 RED가 아니다.

Minimal GREEN

변경은 아래 다섯 runtime 설정의 literal default와 필요한 설명, 이어지는 재현된 classifier 결함의 최소 수정에 한정한다.

파일 / symbol 기존 새 값
scripts/execute.py / StepExecutor.CODEX_TIMEOUT_SECONDS 1800 14400
.codex/hooks.json / Stop command timeout 1800 7500
scripts/hooks/stop_validation.py / TOTAL_TIMEOUT_SECONDS 1800 7200
scripts/msvc_harness/models.py / CommandSpec.timeout_seconds 1800 7200
scripts/msvc_harness/process.py / execute_plan total_timeout_seconds default 1800 7200

Classifier GREEN은 _codex_environment_failure의 helper marker 판별만 좁힌다. 성공한 source/tool 출력의 임의 substring을 runtime diagnostic으로 사용하지 않는다. Stderr의 실제 helper diagnostic과 관찰된 명시 runtime failure 형식을 보존하고, JSONL 성공 command의 command/aggregated_output 같은 source payload는 제외한다. Plain Source excerpt: 문장도 진짜 runtime error 형식이 아니므로 무시한다. 모든 exit0을 정상으로 간주하거나 stderr 검사를 제거하지 않는다. 필요한 작은 private 판별 함수는 같은 scripts/execute.py 안에 둔다. 기존 auth/CLI nonzero 진단, explicit terminal·history, retry 분기와 횟수는 바꾸지 않는다.

min(command cap, shared remaining) 알고리즘은 그대로 둔다. 이 classifier delta 외의 함수· sandbox·transport/Coordinator retry·Hook scope/active flags·ownership/Git/API를 변경하지 않는다. docs/HARNESS_WORKFLOW.md의 이전1800 설명은 위 유한 deadline/새 process activation을 정확히 반영한다. Config field/환경변수/새 public CLI timeout option은 만들지 않는다.

Focused VERIFY

$mfePython = Join-Path (Get-Location).Path '.harness/build/mitc4-eigen-evidence/prep/classifier-correction/pytest-venv/Scripts/python.exe'
$mfePytestCache = Join-Path (Get-Location).Path '.harness/build/mitc4-eigen-evidence/prep/classifier-correction/pytest-cache'
$mfePytestBase = Join-Path (Get-Location).Path ('.harness/build/p-' + [guid]::NewGuid().ToString('N').Substring(0,8))
if ($mfePytestBase.Length -gt 80 -or (Test-Path -LiteralPath $mfePytestBase)) { throw 'Fresh short pytest basetemp required' }
& $mfePython -B -X utf8 -m pytest -v -rs -o "cache_dir=$mfePytestCache" "--basetemp=$mfePytestBase" 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

Exit0, failures0, 현재 sandbox/terminal/ownership regressions 보존을 확인한다. PreToolUse/Stop unit tests는 mock 테스트이고 실제 등록 Stop 통과 evidence가 아니다.

위 신규 classifier test3개의 실제 collection 이름과 parameter case 존재도 확인한다. 등록된 기존 suite만 실행되었다고 새로운 behavior가 검증됐다고 보고하지 않는다.

이미 GREEN인 timeout/classifier source는 기존 Correction evidence와 보존된 RED/GREEN을 읽고 재검증한다. RED를 다시 만들려고 source를 되돌리지 않는다. 현재 classifier37/timeout4/focused136과 전체 pytest를 실제 확인한다.

Full VERIFY

$env:CMAKE_BUILD_PARALLEL_LEVEL = '1'
cmake --preset mfe-workspace-msvc-ninja-debug
if ($LASTEXITCODE -ne 0) { throw 'configure failed' }
cmake --build --preset mfe-workspace-msvc-ninja-debug --clean-first --verbose
if ($LASTEXITCODE -ne 0) { throw 'build failed' }
ctest --preset mfe-workspace-msvc-ninja-debug --show-only=json-v1
if ($LASTEXITCODE -ne 0) { throw 'discovery failed' }
ctest --preset mfe-workspace-msvc-ninja-debug --output-on-failure
if ($LASTEXITCODE -ne 0) { throw 'full CTest failed' }
$mfePython = Join-Path (Get-Location).Path '.harness/build/mitc4-eigen-evidence/prep/classifier-correction/pytest-venv/Scripts/python.exe'
$mfePytestCache = Join-Path (Get-Location).Path '.harness/build/mitc4-eigen-evidence/prep/classifier-correction/pytest-cache'
$mfePytestBase = Join-Path (Get-Location).Path ('.harness/build/p-' + [guid]::NewGuid().ToString('N').Substring(0,8))
if ($mfePytestBase.Length -gt 80 -or (Test-Path -LiteralPath $mfePytestBase)) { throw 'Fresh short pytest basetemp required' }
& $mfePython -B -X utf8 -m pytest -v -rs -o "cache_dir=$mfePytestCache" "--basetemp=$mfePytestBase"
if ($LASTEXITCODE -ne 0) { throw 'full pytest failed' }

이 clean-first/verbose는 새 Ninja graph의 실제 세 executable link/POST_BUILD discovery를 직렬로 실행한다. fesa_unit_tests_576e7e9d_discovery.cmake, fesa_integration_tests_d537bc73_discovery.cmake, fesa_reference_tests_ac7cf2f0_discovery.cmake의 실제 호출과 대응 executable/등록 identity를 raw에 남긴다. unit289/integration34/reference39의 실제 호출·등록 identity와 전체362 discovery를 확인하고, 새 Debug library/executable hash·mtime 및 fresh manual solve를 남긴다. No-op build/기존 자동 결과만으로 manual 성공을 주장하지 않는다.

C++는 수정하지 않는다. 기존 same-binary cache를 쓰는 helper와 항상 fresh solver를 호출하는 nonlinear helper를 구별한다. 모든 full CTest를 실제 실행하고 완결 count/exit/duration을 기록한다. Cached outputs를 이번 eigen 신규 검증이라고 부르지 않는다. 등록 Stop도 정상 수행하며 full VERIFY를 생략/분할 성공으로 대체하지 않는다.

현재 prep Executor와 Codex는 E11의 local preset/유한14400과 실제 승인·신뢰된 등록 Stop7500/shared7200을 사용한다. 실제 등록 Stop 초과/실패 시 정상 terminal evidence와 원시 로그를 보존해 Coordinator에 반환한다. Hook 직접 실행, 재진입 flag/state 조작, 거짓 Markdown-only skip으로 우회하지 않는다.

보고서는 현재 attempt의 actual manual과 registered 결과, 과거 wording을 구분한다. 기존 full CTest는 static reference를 읽고 비교한다. 원본 직접 수정 없음과 새 eigen comparison 미실행을 그 사실과 구분하며 당시 실패/미실행 기록을 보존한다.

Evidence / result

docs/mitc4-shell-feast-eigen/implementation-prep-evidence.md에 feature/owner/r2, 각 RED/GREEN command/exit/duration, 전체 pytest/CTest counts, cap before/after, 실제 code diff 범위, current loaded wrapper14400과 실제 등록 Stop7500/shared7200, 그 시점에 관찰된 Stop/Codex exit 또는 아직 확인 대기인 항목을 기록한다. Raw logs는 ignored .harness/build/mitc4-eigen-evidence/prep/다. CTest log는 즉시 복사 보존한다.

보고서 작성 시점에는 마지막 registered Stop/Codex exit가 아직 발생하지 않을 수 있다. Implementation은 실제 완료된 manual 검증과 미관찰 Stop을 구분하고 미래 성공을 선기록하지 않는다. completed payload는 그 자체로 Stop 성공 증거가 아니다. Executor 종료 뒤 Coordinator가 raw output·등록 Hook evidence·actual exit를 management 문서에서 사후 감사한다. Specialist 보고서 본문은 Coordinator가 대신 수정하지 않는다.

이 Step의 manual AC가 통과하면 현재 phase index Step0의 completed/summary만 기록한다. 실패는 error/error_message 또는 blocked/blocked_reason이며 attempt_history/timestamps/다른Step/top index는 건드리지 않는다. 최종 phase commit/branch/checkpoint는 Executor가 수행한다. 마지막 응답은 common envelope다. Main invocation은 prep Executor의 실제 종료·completed·registered Stop 성공·actual Codex exit0·code/control commit·clean 및 Coordinator 사후 감사 완료 후 Coordinator가 새 process로 시작한다.