docs: preserve prep failure and short-temp recovery plan

This commit is contained in:
KOKO\Mimi
2026-09-06 15:32:03 +09:00
parent d64cd1403a
commit 2f7103ac37
5 changed files with 287 additions and 9 deletions
@@ -397,3 +397,153 @@ Prep full gate·등록 Stop 실제 exit·Coordinator 사후 감사 전 main acti
Executor AST 불변, local links/EOF/whitespace와 blocked archive 동일성을 대상으로 했다.
정확 결과와 갱신3문서 hash는 handoff에 기록한다. Source/tests/Hook/phase/status/Git과
Correction 본문은 이번 Planning 작업에서 수정하지 않았다.
## R7. Attempt2 실패 보존과 정상 workspace-write 재개
R2/R6/R3와 E6은 과거 실행·승인 이력으로 보존한다. 이번 actual attempt2는 종료됐으며
[terminal archive](../../.harness/build/mitc4-eigen-evidence/prep/attempt2/terminal-archive.json)에
native PowerShell1/Codex0, Step error/history2와 이전 history1이 남아 있다.
Hook RED3pass/1fail→GREEN4pass, focused136pass(기존 classifier37 포함),
configure/build/discovery0 뒤 manual CTest와 registered CTest는 각각 exit8,
361/362pass였다. Stop wrapper/Python0은 검증 성공이 아니다. Full pytest는 미실행이다.
[동일 binary의 경로 길이 비교](../../.harness/build/mitc4-eigen-evidence/prep/attempt2/path-length-probe-e15c1747/observation.json)는
TEMP152/result251/lock261에서 해당 test exit1, TEMP70/관찰 lock179에서 exit0을 기록한다.
Binary SHA-256 `d52ed2538be8f66e076f25ae44f073aea8486c5f543fbc7c179b7a5610dc3209`는 같고
source/shared CTest log/reference 변경은 없다. 이 결과는 정상 환경 설정의 근거이며
solver defect 또는 직접 관찰하지 않은 GetLastError를 주장하지 않는다.
### 실패 상태의 WIP checkpoint
Root는 frozen management4문서와 Planning3문서의 실제 변경 경로만 먼저 checkpoint한다.
Hook/report/phase controls는 그 문서 commit에 섞지 않는다. Root ack 뒤 Coordinator가 아래
unchanged Executor 호출을 할당한다. Origin은 `d64cd1403ac41fb1397dfb088361ce18ad1d59bd`,
dirty는 Hook+report2 및 controls2뿐이어야 한다. 두 commit은 WIP/실패 기록이며 성공 전환이 아니다.
모든 bytes/history/raw/error는 유지한다. 중간 실패 시 원래 HEAD/index/worktree를 보존하며
자동 재시도나 rollback을 하지 않는다. `_commit_step`/runtime override는 사용하지 않는다.
```powershell
$ErrorActionPreference = 'Stop'
$mfePython = Join-Path (Get-Location).Path '.harness/build/mitc4-eigen-evidence/prep/classifier-correction/pytest-venv/Scripts/python.exe'
if (-not (Test-Path -LiteralPath $mfePython -PathType Leaf)) { throw 'Named Python missing' }
@'
import ast,hashlib,json
from pathlib import Path
from scripts import execute
phase="mitc4-shell-feast-eigen-execution-prep"
origin="d64cd1403ac41fb1397dfb088361ce18ad1d59bd"
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"
assert ex._implementation_agent_settings()==("gpt-5.6-terra","xhigh")
branch,head=ex._git_execution_identity()
assert branch=="refs/heads/feat-"+phase
ex._run_git_checked("merge-base","--is-ancestor",origin,"HEAD")
docs={"docs/mitc4-shell-feast-eigen/"+n for n in ("FEATURED_AGENTS.md","PRD.md","ADR.md",
"coordination.md","implementation-plan.md","implementation-environment.md","implementation-recovery.md")}
assert set(ex._run_git_checked("diff","--name-only","--no-renames",origin,"HEAD").stdout.splitlines())<=docs
assert not ex._run_git_checked("diff","--cached","--name-only").stdout.strip()
expected={".codex/hooks.json":"e7e5d3c0c4fcd1e33b60680122ea7c42298d5cbde78a7f87d9e0007bf60a0fa4",
"docs/mitc4-shell-feast-eigen/implementation-prep-evidence.md":"90d104423af2971837a38eb632c8a4aa54b8acf6f6cd96b5a193dbd4ba4e083f",
"phases/index.json":"c2d98e5bcb96bb781f687e696083076a3f5bea2d095f4c7264bb4a6415b6cc38",
"phases/"+phase+"/index.json":"7990530b4d259850f614ae68036c551b3c11539c90673512c6515d3f87ad1ebe",
"phases/"+phase+"/step0-output.json":"8852e0ddae9ef94d885e8b4ae4b8a3b2e3a9d9161a3801bc7e56ea157e9411f4",
"scripts/execute.py":"64f5165fc544b3b17904c633ef3b222de79b52a0960e254c5b5c4eb99e79c2d0",
"tests/test_execute.py":"0eb0c1ca0f25199e00686b7e3ab57672b1390437d09da218a929added0346dd6"}
for p,h in expected.items():assert hashlib.sha256((root/p).read_bytes()).hexdigest()==h,p
assert ast.dump(ast.parse((root/"scripts/execute.py").read_text(encoding="utf-8")))==ast.dump(ast.parse(ex._run_git_checked("show",origin+":scripts/execute.py").stdout))
old_hook=json.loads(ex._run_git_checked("show",origin+":.codex/hooks.json").stdout)
old_hook["hooks"]["Stop"][0]["hooks"][0]["timeout"]=7500
assert json.loads((root/".codex/hooks.json").read_bytes())==old_hook
idx=ex._read_phase_index();top=ex._read_top_index()
assert idx["steps"][0]["status"]=="error" and len(idx["steps"][0]["attempt_history"])==2
assert next(p for p in top["phases"] if p["dir"]==phase)["status"]=="error"
owned=ex._step_owned_paths(idx["steps"][0])
code=[".codex/hooks.json","docs/mitc4-shell-feast-eigen/implementation-prep-evidence.md"]
control=["phases/index.json","phases/"+phase+"/index.json"]
assert set(ex._assert_step_scope(owned))==set(code+control)
frozen={p:(root/p).read_bytes() for p in list(owned)+list(expected)+["phases/"+phase+"/step0.md","phases/mitc4-shell-feast-eigen/index.json"]}
for paths,message in (
(code,"chore(mitc4-shell-feast-eigen-execution-prep): WIP Hook update with verification failure"),
(control,"chore(mitc4-shell-feast-eigen-execution-prep): preserve attempt 2 error metadata")):
assert all((root/p).read_bytes()==v for p,v in frozen.items())
assert ex._git_execution_identity()==(branch,head)
assert ex._commit_paths(paths,message,owned_paths=owned)
new_branch,new_head=ex._git_execution_identity()
assert new_branch==branch and new_head!=head
actual=ex._run_git_checked("diff-tree","--no-commit-id","--name-only","--no-renames","-r",new_head).stdout.splitlines()
assert set(actual)==set(paths)
assert all((root/p).read_bytes()==v for p,v in frozen.items())
assert ex._read_phase_index()==idx and ex._read_top_index()==top
print(json.dumps({"commit":new_head,"paths":actual,"status":"error","history_count":2}))
head=new_head
assert not ex._worktree_paths()
ex._preflight_repository()
print(json.dumps({"head":head,"branch":branch,"clean":True}))
'@ | & $mfePython -B -X utf8 -
$mfeWipExit = $LASTEXITCODE
if ($null -eq $mfeWipExit) { throw 'Native exit unavailable' }
exit $mfeWipExit
```
### 별도 할당 뒤 status-only checkpoint
위 terminal WIP 보존이 실제 완료되기 전에는 status를 바꾸지 않는다.
그 후 Coordinator의 별도 할당을 받은 Planning만 prep index의 현재 Step0.status를
`error -> pending` 한 값으로 바꾼다. error_message/failed_at/started_at/created_at/
attempt_history2/owned_paths와 다른 fields/top/raw는 그대로 둔다. 현재 Planning dispatch는
이 status edit를 허용하지 않는다. 반환 감사 뒤 Coordinator가 다음 Executor control
checkpoint를 할당하고 clean을 확인한다. 일반 환경 복구이므로 새 사용자 승인은 필요하지 않다.
```powershell
$ErrorActionPreference = 'Stop'
$mfePython = Join-Path (Get-Location).Path '.harness/build/mitc4-eigen-evidence/prep/classifier-correction/pytest-venv/Scripts/python.exe'
if (-not (Test-Path -LiteralPath $mfePython -PathType Leaf)) { throw 'Named Python missing' }
@'
import json
from pathlib import Path
from scripts import execute
phase="mitc4-shell-feast-eigen-execution-prep"
ex=execute.StepExecutor(phase);root=Path(ex._root)
assert Path.cwd().resolve()==root
assert Path(ex._run_git_checked("rev-parse","--show-toplevel").stdout.strip()).resolve()==root
assert ex._is_isolated_worktree() and ex._codex_sandbox_mode()=="workspace-write"
branch,head=ex._git_execution_identity();assert branch=="refs/heads/feat-"+phase
path="phases/"+phase+"/index.json"
before=json.loads(ex._run_git_checked("show","HEAD:"+path).stdout)
assert before["steps"][0]["status"]=="error" and len(before["steps"][0]["attempt_history"])==2
expected=json.loads(json.dumps(before));expected["steps"][0]["status"]="pending"
assert ex._read_phase_index()==expected
assert set(ex._assert_step_scope(()))=={path}
assert not ex._run_git_checked("diff","--cached","--name-only").stdout.strip()
frozen={p:(root/p).read_bytes() for p in (path,"phases/index.json","phases/"+phase+"/step0-output.json")}
assert ex._commit_paths([path],"chore(mitc4-shell-feast-eigen-execution-prep): queue short-temp environment recovery")
new_branch,new_head=ex._git_execution_identity()
assert new_branch==branch and new_head!=head
assert ex._run_git_checked("diff-tree","--no-commit-id","--name-only","-r",new_head).stdout.splitlines()==[path]
assert all((root/p).read_bytes()==v for p,v in frozen.items())
assert ex._read_phase_index()==expected and not ex._worktree_paths()
ex._preflight_repository()
print(json.dumps({"commit":new_head,"status":"pending","history_count":2,"clean":True}))
'@ | & $mfePython -B -X utf8 -
$mfeStatusExit = $LASTEXITCODE
if ($null -eq $mfeStatusExit) { throw 'Native exit unavailable' }
exit $mfeStatusExit
```
이어 [E7의 짧은 TEMP와 정상 sandbox](implementation-environment.md#e7-짧은-temp를-사용하는-정상-재개)로
prep를 재개한다. 이전 E6의 one-time DFA 승인은 사용 완료됐고 Hook7500은 안전하게
보존되므로 이번에는 DFA flag나 danger-full-access 환경을 사용하지 않는다.
Main도 full prep gate/Coordinator 사후 감사 뒤 같은 짧은 환경과 workspace-write로 실행한다.
Source classifier의 harness r2 Correction allowance는 이미 사용됐으며 두 번째 source
Correction은 허용하지 않는다. 같은 테스트·전체 VERIFY·Hook·retry/ownership guard를 유지한다.
재개 Implementation은 기존 RED/GREEN을 읽고 focused/full을 실제 재검증한다. Full CTest는
기존 정적 reference를 읽고 비교하므로 보고서의 'reference를 읽거나 비교하지 않았다' 문장은
owner가 바로잡아야 한다. 원본 reference의 직접 수정 없음, 새 eigen reference 비교 없음과
기존 static regression 비교 수행을 구분하고 당시 실패·미실행 기록도 보존한다.
Planning은 implementation-prep-evidence.md를 수정하지 않는다.
이 R7의 commit/status edit/재실행은 아직 미실행이다. 정적 검사 결과와 갱신3문서 hash는
handoff에 기록하며 실제 실행 exit·commit path/bytes·clean 확인은 Coordinator가 감사한다.