# 차단된 prep의 보존과 조건부 재개 계획 - Feature ID: `mitc4-shell-feast-eigen` - Owner: `implementation-planning-agent` - Input contract revision: `r2` - 기본 보고서: [implementation-plan](implementation-plan.md) - 범위: 문서와 정적 검토만 완료한다. 아래 Git mutation/status edit/재실행은 아직 실행하지 않는다. ## R1. 실제 상태와 변경 없는 경계 필수 입력은 Feature 폴더와 [FEATURED_AGENTS](FEATURED_AGENTS.md), [PRD](PRD.md), [ADR](ADR.md), [현재 Coordinator 감사](coordination.md#execution-prep-attempt-1-실제-결과), 기존 [환경](implementation-environment.md), [interfaces](implementation-interfaces.md), [verification](implementation-verification.md) 및 그 upstream r2 links다. [AGENTS](../../AGENTS.md), [agent 계약](../SOLVER_AGENT_DESIGN.md), [문서 관리](../FEATURE_DOCUMENTATION.md), [harness](../../.agents/skills/harness/SKILL.md), [fem-implementation-tdd](../../.codex/skills/fem-implementation-tdd/SKILL.md)를 적용한다. Prep attempt1은 종료되었고 Step0/top은 blocked, history1이다. [원 보고서](implementation-prep-evidence.md)의 미검증 test 수정/실패 횟수 서술은 후속 Implementation owner가 실제 raw 순서에 맞춰 갱신한다. Planning은 본문을 수정하지 않는다. [보존된 raw](../../.harness/build/mitc4-eigen-evidence/prep/attempt1/step0-output.json)와 [observation](../../.harness/build/mitc4-eigen-evidence/prep/attempt1/observation.json)을 사용한다. Raw SHA-256은 `0d5c0fe0aeba5604c5289764e7aad1834902548ca02158f8feac03484b195941`이다. 마지막 focused run은2pass/2fail, 이후 test-only 수정은 미실행이다. Registered CTest의 362pass 기록은 manual full VERIFY/별도 process exit를 대신하지 않는다. [현재 Executor](../../scripts/execute.py)의 constructor는 경로/schema를 읽고 field를 설정한다. `_stop_step`은 blocked/history/top을 저장한 뒤 종료하며 커밋하지 않는다. `_commit_paths`는 자체 `_assert_step_scope`, trusted path 검증, exact staged 경로 검사와 commit 직전 재검사를 수행한다. 내부 index reset은 검사된 dirty 경로의 staging만 정리하며 worktree bytes는 보존한다. 아래 명령은 이 method를 변경 없이 호출한다. `run/_commit_step/_finalize/_stop_step`, status reset, Hook writes 또는 guard overrides는 없다. 일반 실행용 clean preflight는 dirty WIP 보존 전에 성립하지 않으므로 이 전용 checkpoint는 constructor/identity/scope/commit 경로를 사용하고 마지막 clean 상태에서 정상 preflight를 확인한다. 이는 새로운 recovery CLI가 아니다. ## R2. Root checkpoint 이후의 정확한 WIP 보존 명령 1. 모든 실행이 종료된 상태에서 Coordinator가 이 계획을 감사한다. Root는 management4문서와 이 변경3문서, classifier delta를 반영한 prep step0.md의 정확한8경로만 먼저 checkpoint한다. Partial runtime/tests/report와 phase index/top의 controls는 stage하거나 커밋하지 않는다. Root checkpoint 후 staging은 비어 있어야 한다. 2. Branch `feat-mitc4-shell-feast-eigen-execution-prep`, linked root, origin `d533b615410751fe023dc73ac2be994f05d37d30`의 descendant, origin 이후 commit path가 해당8계획/관리 파일 이내임을 아래 명령이 검증한다. 현재 partial implementation8경로와 control2경로가 정확히 남아야 한다. `.codex/hooks.json`은 이 WIP commit의 변경 대상이 아니다. 3. Coordinator가 실행을 할당하면 **실제 Executor method**가 두 개의 local commit을 만든다. Root/Coordinator는 실행 동안 추가 편집·커밋을 멈춘다. 성공 명칭이나 completed를 쓰지 않는다. 첫 commit 후 두 번째가 실패할 수 있으며 두 commit은 하나의 transaction이 아니다. 실패 시 현재 HEAD/index/worktree/log를 그대로 감사하고 자동 재시도나 rollback을 하지 않는다. Workspace root의 별도 managed PowerShell process에서 아래 전체 block을 실행하도록 계획한다. Python native exit를 즉시 저장하여 동일 shell exit로 전파한다. CommandNotFound는 terminating error이며 나중 명령의 exit0으로 덮이지 않는다. 이 block은 **현재 planning turn에서 미실행**이다. ```powershell $ErrorActionPreference = 'Stop' Get-Command python -ErrorAction Stop | Out-Null @' import ast, hashlib, json, os from pathlib import Path from scripts import execute phase = "mitc4-shell-feast-eigen-execution-prep" origin = "d533b615410751fe023dc73ac2be994f05d37d30" 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() assert ex._codex_sandbox_mode() == "workspace-write" assert ex._implementation_agent_settings() == ("gpt-5.6-terra", "xhigh") branch, before_head = ex._git_execution_identity() assert branch == "refs/heads/feat-" + phase ex._run_git_checked("merge-base", "--is-ancestor", origin, "HEAD") doc_names = ("FEATURED_AGENTS.md", "PRD.md", "ADR.md", "coordination.md", "implementation-plan.md", "implementation-environment.md", "implementation-recovery.md") doc_paths = {"docs/mitc4-shell-feast-eigen/" + n for n in doc_names} doc_paths.add("phases/" + phase + "/step0.md") committed = ex._run_git_checked("diff", "--name-only", "--no-renames", origin, "HEAD").stdout.splitlines() assert set(committed) <= doc_paths assert not ex._run_git_checked("diff", "--cached", "--name-only").stdout.strip() current_source = (root / "scripts/execute.py").read_text(encoding="utf-8") original_source = ex._run_git_checked("show", origin + ":scripts/execute.py").stdout assert ast.dump(ast.parse(current_source.replace("CODEX_TIMEOUT_SECONDS = 14400", "CODEX_TIMEOUT_SECONDS = 1800"))) == ast.dump(ast.parse(original_source)) idx = ex._read_phase_index() top = ex._read_top_index() assert len(idx["steps"]) == 1 and idx["steps"][0]["status"] == "blocked" assert len(idx["steps"][0]["attempt_history"]) == 1 assert next(p for p in top["phases"] if p["dir"] == phase)["status"] == "blocked" owned = ex._step_owned_paths(idx["steps"][0]) expected_owned = ("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") assert owned == expected_owned control = ["phases/index.json", "phases/" + phase + "/index.json"] code = [p for p in owned if p != ".codex/hooks.json"] assert set(ex._assert_step_scope(owned)) == set(code + control) raw_path = "phases/" + phase + "/step0-output.json" raw = (root / raw_path).read_bytes() assert hashlib.sha256(raw).hexdigest() == "0d5c0fe0aeba5604c5289764e7aad1834902548ca02158f8feac03484b195941" frozen_paths = list(owned) + control + ["phases/" + phase + "/step0.md", raw_path] frozen = {p: (root / p).read_bytes() for p in frozen_paths} def verify_frozen(): assert all((root / p).read_bytes() == data for p, data in frozen.items()) assert ex._read_phase_index() == idx and ex._read_top_index() == top assert ex._git_execution_identity()[0] == branch verify_frozen() previous = before_head for paths, message in ( (code, "chore(mitc4-shell-feast-eigen-execution-prep): WIP blocked partial deadline preparation"), (control, "chore(mitc4-shell-feast-eigen-execution-prep): preserve blocked attempt 1 metadata"), ): verify_frozen() assert ex._commit_paths(paths, message, owned_paths=owned) current = ex._git_execution_identity()[1] assert current != previous actual = ex._run_git_checked("diff-tree", "--no-commit-id", "--name-only", "--no-renames", "-r", current).stdout.splitlines() assert set(actual) == set(paths), (current, actual) verify_frozen() print(json.dumps({"commit": current, "paths": sorted(actual), "status": "blocked"})) previous = current assert not ex._worktree_paths() ex._preflight_repository() verify_frozen() print(json.dumps({"clean": True, "branch": branch, "head": previous, "raw_sha256": hashlib.sha256(raw).hexdigest(), "phase_status": "blocked", "history_count": 1})) '@ | python -B - $mfeCheckpointExit = $LASTEXITCODE if ($mfeCheckpointExit -ne 0) { exit $mfeCheckpointExit } exit $mfeCheckpointExit ``` 상태/history/timestamps/다른 step/top/step markdown/raw/owned file bytes는 전후 동일해야 한다. 출력 commit SHA와 actual path set, clean/branch/root 및 실제 process exit를 Coordinator가 관리문서에 감사한다. 이 두 commit은 blocked WIP 보존이며 구현/검증 통과가 아니다. Raw archive는 ignored 상태로 유지하고 Git에 추가하지 않는다. ## R3. 승인 후에만 가능한 status-only checkpoint 현재 exact DFA run의 명시적 사용자 승인은 없다. WIP checkpoint에는 별도 사용자 질문이 필요하지 않지만 DFA는 [harness elevated rule](../../.agents/skills/harness/SKILL.md#elevated-and-remote-execution)에 따라 동일 native 명령 실패 evidence, clean linked worktree, **해당 실행 직전 명시적 사용자 승인**, approval flag가 모두 필요하다. 과거 일반 구현 승인이나 이 문서 작성은 그 승인이 아니다. 그 승인이 실제로 도착한 경우에만 다음 순서를 같은 bounded 복구 준비로 진행한다. 1. Coordinator가 승인된 exact command와 recovery dispatch를 management에 기록하고 Root가 그 문서만 checkpoint하여 clean을 유지한다. 원시 attempt1 archive는 그대로 보존한다. 2. Coordinator의 별도 명시 할당을 받은 Planning만 `phases/mitc4-shell-feast-eigen-execution-prep/index.json`의 **현재 Step0 status 한 값** `blocked -> pending`을 바꾼다. `blocked_reason/blocked_at/started_at/created_at/ attempt_history`, owned paths, 다른 Step/top은 그대로 둔다. 현재 dispatch는 이 편집을 허용하지 않는다. 3. Coordinator가 할당한 실제 Executor method는 아래 control-only checkpoint를 수행한다. Staged HEAD의 blocked JSON과 working pending JSON의 차이가 status 한 값뿐인지 검증한다. Top은 계속 blocked다. 기존 `_check_blockers`는 phase의 첫 미완료 Step을 판별하므로 pending을 실행할 수 있으며 top을 미리 성공/초기화할 필요가 없다. 4. Clean checkpoint 확인 뒤 별도 변경 없이 R4의 승인된 invocation을 시작한다. 필요한 준비 사이에 실행 범위나 환경이 달라지면 재개하지 않고 Coordinator에 반환한다. ```powershell $ErrorActionPreference = 'Stop' Get-Command python -ErrorAction Stop | Out-Null @' import 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, before_head = ex._git_execution_identity() assert branch == "refs/heads/feat-" + phase path = "phases/" + phase + "/index.json" before = json.loads(ex._run_git_checked("show", "HEAD:" + path).stdout) after = ex._read_phase_index() expected = json.loads(json.dumps(before)) assert len(expected["steps"]) == 1 and expected["steps"][0]["status"] == "blocked" expected["steps"][0]["status"] = "pending" assert after == expected assert set(ex._assert_step_scope(())) == {path} assert not ex._run_git_checked("diff", "--cached", "--name-only").stdout.strip() top_before = ex._read_control_bytes(ex._top_index_file) raw_path = root / "phases" / phase / "step0-output.json" raw_before = raw_path.read_bytes() phase_before = ex._read_control_bytes(ex._index_file) assert ex._commit_paths([path], "chore(mitc4-shell-feast-eigen-execution-prep): queue approved recovery preserving attempt history") current = ex._git_execution_identity() assert current[0] == branch and current[1] != before_head assert ex._run_git_checked("diff-tree", "--no-commit-id", "--name-only", "-r", current[1]).stdout.splitlines() == [path] assert ex._read_control_bytes(ex._index_file) == phase_before assert ex._read_control_bytes(ex._top_index_file) == top_before assert raw_path.read_bytes() == raw_before assert ex._read_phase_index() == after and not ex._worktree_paths() ex._preflight_repository() print(json.dumps({"commit": current[1], "clean": True, "step_status": "pending", "history_preserved": True})) '@ | python -B - $mfeStatusExit = $LASTEXITCODE if ($mfeStatusExit -ne 0) { exit $mfeStatusExit } exit $mfeStatusExit ``` 이 단계도 `_commit_step`이나 완료 처리를 부르지 않는다. 이후 실행에서 추가 attempt 기록과 terminal outcome/timestamp 정리는 Executor 소유다. Planning/Root가 과거 failure를 지우지 않는다. ## R4. 조건부 exact DFA invocation과 후속 검증 Prep에 실제 classifier 결함의 TDD delta가 추가되었다. 상세 RED/GREEN/신규 test3개 및 전체 VERIFY는 [prep Step0](../../phases/mitc4-shell-feast-eigen-execution-prep/step0.md)에 있다. [순수함수 재현](../../.harness/build/mitc4-eigen-evidence/prep/attempt1/classifier-observation.json)은 성공한 source read stdout의 marker7회가 오판 원인이었음을 보여 준다. 실제 protected Hook 쓰기 거부/명시 blocked는 별개의 실제 failure로 보존한다. Root/Coordinator가 확정한 순서는 이번 계획 종료 → 정확 문서 checkpoint → R2의 unchanged Executor WIP 두 commit → 별도 Correction Agent dispatch다. Correction 소유는 scripts/execute.py, tests/test_execute.py와 `docs/mitc4-shell-feast-eigen/corrections.md`이며 Hook/index/status/Git은 변경하지 않는다. Correction은 Step0에 정의한 최소 RED/GREEN·focused/full acceptance를 수행한다. Checkpoint/recovery bootstrap이 classifier를 monkeypatch하거나 진단을 지우지 않는다. 이미 시작된 Executor는 source 수정 뒤에도 예전 classifier를 유지하므로 Correction은 다음 실제 prep invocation보다 먼저 완료되어야 한다. 실제 Correction 결과가 반환된 뒤 Coordinator는 Planning을 별도 재개하여 source/report의 정확 checkpoint 계획을 감사한다. 현재 문서는 미래 Correction 성공/hash/commit이나 그 checkpoint를 미리 승인하지 않는다. 해당 검증·checkpoint와 새 process가 수정 classifier를 읽는 activation 확인이 끝나기 전 R3/R4 재개를 실행하지 않는다. 현재 timeout-only AST guard는 최초 WIP 보존에 그대로 유지한다. 수정된 classifier를 현재 Executor에 reload/override하거나 old classifier의 terminal을 성공으로 바꾸지 않는다. R3과 사용자 승인까지 실제 완료된 경우에만, workspace root의 새 managed PowerShell process에서 아래 실행을 허용한다. E3의 실제 `main()`과 단일 유한14400 timeout assignment를 유지하며 flag와 process-local sandbox 값만 승인 범위에 맞춘다. 이전 환경 값은 `finally`에서 복원하고 native exit를 즉시 저장한다. transport/ownership/Hook/verification guard는 변경하지 않는다. ```powershell $ErrorActionPreference = 'Stop' Get-Command python -ErrorAction Stop | Out-Null $mfePriorSandbox = [Environment]::GetEnvironmentVariable('FEM_HARNESS_CODEX_SANDBOX', 'Process') if ($null -ne $mfePriorSandbox -and $mfePriorSandbox -ne 'workspace-write') { throw 'Unexpected pre-existing sandbox environment' } $mfeNativeExit = $null try { $env:FEM_HARNESS_CODEX_SANDBOX = 'danger-full-access' python -B -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 was not captured' } } finally { [Environment]::SetEnvironmentVariable('FEM_HARNESS_CODEX_SANDBOX', $mfePriorSandbox, 'Process') } exit $mfeNativeExit ``` Implementation은 선행 Correction의 실제 RED/GREEN evidence를 읽고 같은 classifier regression, 남은 Hook 변경, 미검증 test 수정의 focused 재검증, 전체 pytest와 MSVC/x64/Debug CMake/CTest, actual registered Stop을 모두 수행한다. 기존 보고서의 실제 2개 실패와 미검증 수정도 owner가 바로잡는다. 실패 이력을 새 RED 성공이나 correction으로 바꾸지 않는다. Native Exit/Stop 사후 감사까지 prep gate가 완료되기 전 main activation은 금지다. Push/tag/publish/release 또는 다른 sandbox/guard 변경 권한은 없다. ## R5. 계획 정적 검증 Command AST/PowerShell syntax와 현 상태의 read-only 검사를 수행했다. Python `ast.parse`로 WIP/status checkpoint code2개를 검증했고 PowerShell `Parser::ParseInput`으로 실행 block3개의 syntax errors0을 확인했다(각 exit0). 현재 execute.py는 origin 대비 timeout 상수 외 AST가 같아 checkpoint에 사용되는 guard가 변경되지 않았음을 확인했다. Phase/top/raw는 보존 archive와 동일하며 상태 blocked/history1이다. 문서 EOF/trailing whitespace·local links와 `git diff --check`도 확인했다. Commit/status edit/DFA/CMake/CTest/pytest는 미실행이다. 최종 scope/link count·hash는 handoff에 기록한다.