docs: preserve Ninja failure and bound environment recovery
This commit is contained in:
@@ -716,3 +716,168 @@ report/top/raw의 현재 hash를 확인한다. Phase control 한 경로만 commi
|
||||
Native exit를 즉시 전파하고 commit 전후 snapshot 및 clean preflight를 감사한다.
|
||||
실패하면 bytes/원시 로그/이미 생성된 commit을 보존하고 다음 invocation을 시작하지 않는다.
|
||||
E8 setup 또는 native 성공을 이 status checkpoint 성공에서 추론하지 않는다.
|
||||
|
||||
## R10. Attempt4의 error/history4 보존
|
||||
|
||||
[Executor 결과](../../.harness/build/mitc4-eigen-evidence/prep/attempt4/executor-result.json)와
|
||||
[terminal archive](../../.harness/build/mitc4-eigen-evidence/prep/attempt4/terminal-archive.json)는
|
||||
native PowerShell1, Codex0, transportFailure null과 report1/controls2만의 변경을 기록한다.
|
||||
현재 Step0/top은 error/history4다. Classifier37/focused136은 통과했지만 required manual
|
||||
build는 GoogleTest JSON parsing에서 실패했고 manual CTest/full pytest는 미실행이다.
|
||||
후속 단독 discovery와 등록 CTest 성공으로 최초 실패를 대체하지 않는다.
|
||||
|
||||
[프로세스 관찰](../../.harness/build/mitc4-eigen-evidence/prep/attempt4/root-process-observations.json)의
|
||||
registered Ninja build/CTest0·362pass 및 Python 두 개0과 외부 pwsh1은 별개의 실제 결과다.
|
||||
Whole Stop0으로 합치지 않는다. [원시 선택 이벤트](../../.harness/build/mitc4-eigen-evidence/prep/attempt4/raw-audit-selected-events.json)의
|
||||
item67 direct discovery0은 뒤의 빈 log 조회 때문에 전체 shell1이고 item68은 memo/hash0이다.
|
||||
176-byte log는 후속 관찰 메모이며 해당 direct 실행 stdout 원본으로 치환하지 않는다.
|
||||
|
||||
Root가 frozen 관리/Planning 문서만 exact checkpoint한 뒤 Coordinator가 아래 unchanged
|
||||
Executor method invocation으로 report1 WIP와 controls2 error 보존을 분리 commit한다.
|
||||
사용자 요청 [Root 설명문서](msvc-build-access-error.md)의 기존 commit도 origin 이후
|
||||
허용 문서에 포함하며 현재 bytes/hash를 보존한다. Source/Hook/config/cache 변경,
|
||||
`_commit_step`, 상태 성공·reset, guard override와 직접 Git commit은 없다.
|
||||
|
||||
```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="23c4ebe526260d584247804d8cbe2f7aa8cc60ac"
|
||||
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","msvc-build-access-error.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":"fc88f1c943f7f25d7eeece87dbbd967a6007b14b0adce342ced9aa78f4cd20b2",
|
||||
"phases/index.json":"33d911587305cc96148a3e60f9ca32f9ec114ce75e49118391bcc1ef3a6692c3",
|
||||
"phases/"+phase+"/index.json":"3f4ce6178172819f3e1ab4310db61bc318348aeea822b806d4dcca676b53a60f",
|
||||
"phases/"+phase+"/step0-output.json":"c74f18d0b681f6ab7480b825de4458188fb6b204147ab84b08582820039cab61",
|
||||
"scripts/execute.py":"64f5165fc544b3b17904c633ef3b222de79b52a0960e254c5b5c4eb99e79c2d0",
|
||||
"tests/test_execute.py":"0eb0c1ca0f25199e00686b7e3ab57672b1390437d09da218a929added0346dd6"}
|
||||
expected.update({
|
||||
"docs/mitc4-shell-feast-eigen/msvc-build-access-error.md":"0722dff075e706977d55eb1ac2514d4318b1341adab30a51fc82c744315f1c9f",
|
||||
".harness/config.json":"3ebdfa80124f1eb96909b2738d6f2a96fecd55cce61150a9cd7ef27d7c5fd892",
|
||||
".harness/build-ninja-msvc-debug/CMakeCache.txt":"bf024961a7469672d1fd4f9e8b6606fc1ccaac3fa40dea25709ec4c00ddd5d0e",
|
||||
".harness/build/CMakeCache.txt":"d880104fdc3f1411119ce787c0ddb9a63db23de3f571ba2fedce1c56cb91085b"})
|
||||
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)
|
||||
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"])==4
|
||||
assert next(p for p in top["phases"] if p["dir"]==phase)["status"]=="error"
|
||||
owned=ex._step_owned_paths(idx["steps"][0]);assert len(owned)==9
|
||||
code=["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 prep report with discovery build failure"),
|
||||
(control,"chore(mitc4-shell-feast-eigen-execution-prep): preserve attempt 4 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":4}))
|
||||
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
|
||||
```
|
||||
|
||||
검사 실패 시 이미 생성된 commit, 남은 dirty 파일과 원시 기록을 보존하고 반환한다.
|
||||
이 명령 성공은 실패의 안전한 보존일 뿐 prep gate 통과가 아니다.
|
||||
R11 status edit와 E9 실행은 별도 할당 전 미실행이다. 현재 resolver의 canonical Stop1800
|
||||
해석은 확인됐지만 정상 override 지원·적용 방법이 미확정이므로 현재는 보존만 진행한다.
|
||||
기존 exact owned9와 r2 source Correction1회 소진을 유지한다.
|
||||
|
||||
## R11. R10 뒤의 별도 status-only 복구
|
||||
|
||||
R10 실제 두 commit/clean 감사와 [E9 환경 진입 조건](implementation-environment.md#e9-attempt4-후의-직렬-ninja-검증)이
|
||||
해소된 뒤 Coordinator가 별도 할당할 때만 Planning이 Step0의 `status` 한 값을
|
||||
`error -> pending`으로 바꾼다. 나머지 모든 JSON/bytes, error_message/failed_at/started_at,
|
||||
created_at, history4, owned_paths, top/raw는 보존한다. 이번 문서 작업에서는 바꾸지 않는다.
|
||||
그 한 값 diff/HEAD/staging/hash 감사를 받은 Coordinator만 아래 control checkpoint를 실행한다.
|
||||
|
||||
```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 hashlib,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
|
||||
origin="23c4ebe526260d584247804d8cbe2f7aa8cc60ac"
|
||||
ex._run_git_checked("merge-base","--is-ancestor",origin,"HEAD")
|
||||
report="docs/mitc4-shell-feast-eigen/implementation-prep-evidence.md"
|
||||
controls={"phases/index.json","phases/"+phase+"/index.json"}
|
||||
docs={"docs/mitc4-shell-feast-eigen/"+n for n in ("FEATURED_AGENTS.md","PRD.md","ADR.md",
|
||||
"coordination.md","msvc-build-access-error.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|controls|{report}
|
||||
for paths,probe in ((controls,"phases/"+phase+"/index.json"),({report},report)):
|
||||
commit=ex._run_git_checked("log","-1","--format=%H","--",probe).stdout.strip()
|
||||
actual=set(ex._run_git_checked("diff-tree","--no-commit-id","--name-only","--no-renames","-r",commit).stdout.splitlines())
|
||||
assert actual==paths
|
||||
protected={".codex/hooks.json":"e7e5d3c0c4fcd1e33b60680122ea7c42298d5cbde78a7f87d9e0007bf60a0fa4",
|
||||
"scripts/execute.py":"64f5165fc544b3b17904c633ef3b222de79b52a0960e254c5b5c4eb99e79c2d0",
|
||||
"tests/test_execute.py":"0eb0c1ca0f25199e00686b7e3ab57672b1390437d09da218a929added0346dd6",
|
||||
report:"fc88f1c943f7f25d7eeece87dbbd967a6007b14b0adce342ced9aa78f4cd20b2",
|
||||
"phases/index.json":"33d911587305cc96148a3e60f9ca32f9ec114ce75e49118391bcc1ef3a6692c3",
|
||||
"phases/"+phase+"/step0-output.json":"c74f18d0b681f6ab7480b825de4458188fb6b204147ab84b08582820039cab61",
|
||||
".harness/config.json":"3ebdfa80124f1eb96909b2738d6f2a96fecd55cce61150a9cd7ef27d7c5fd892",
|
||||
".harness/build-ninja-msvc-debug/CMakeCache.txt":"bf024961a7469672d1fd4f9e8b6606fc1ccaac3fa40dea25709ec4c00ddd5d0e",
|
||||
".harness/build/CMakeCache.txt":"d880104fdc3f1411119ce787c0ddb9a63db23de3f571ba2fedce1c56cb91085b"}
|
||||
for p,h in protected.items():assert hashlib.sha256((root/p).read_bytes()).hexdigest()==h,p
|
||||
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"])==4
|
||||
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,*protected]}
|
||||
assert ex._commit_paths([path],"chore(mitc4-shell-feast-eigen-execution-prep): queue serial Ninja 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":4,"clean":True}))
|
||||
'@ | & $mfePython -B -X utf8 -
|
||||
$mfeStatusExit = $LASTEXITCODE
|
||||
if ($null -eq $mfeStatusExit) { throw 'Native exit unavailable' }
|
||||
exit $mfeStatusExit
|
||||
```
|
||||
|
||||
R10 report1/controls2 commit 경로와 HEAD의 error/history4를 검사하므로 미보존 상태에서
|
||||
pending 재실행을 시작하지 않는다. 실제 source/Hook/config 및 기존 cache는 그대로다.
|
||||
각 native exit와 clean을 확인하고, 다음 E9 invocation은 Coordinator가 새 process로
|
||||
별도 할당한다. 실패를 재분류해 새 Correction budget을 만들거나 자동 재시도하지 않는다.
|
||||
|
||||
Reference in New Issue
Block a user