400 lines
26 KiB
Markdown
400 lines
26 KiB
Markdown
# 차단된 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에 기록한다.
|
|
|
|
## R6. 실제 Correction source2의 보존과 남은 실행 조건
|
|
|
|
R2는 실제 WIP commit `6e00dba1`과 blocked metadata commit
|
|
`5dfbea7e543b64fdefcea292de43237adb790a72`을 만든 **과거 명령**이다.
|
|
이후 classifier가 바뀌었으므로 그 timeout-only AST guard를 다시 쓰거나 완화하지 않는다.
|
|
[Correction 보고서](corrections.md)와 [검증 summary](../../.harness/build/mitc4-eigen-evidence/prep/classifier-correction/20260906025404Z-continuation3-verification-summary.json)는
|
|
실제 RED21fail/16pass 뒤 GREEN37pass, 전체 pytest152pass/1fail을 기록한다.
|
|
Manual configure0/build1의 FileTracker TEMP 접근 거부 뒤 manual CTest는 미실행이다.
|
|
[실제 native 결과](../../.harness/build/mitc4-eigen-evidence/prep/classifier-correction/native-continuation-3-result.json)는
|
|
native/wrapper0,1914.797초이며, [등록 process exits](../../.harness/build/mitc4-eigen-evidence/prep/classifier-correction/native-continuation-3-registered-exits.json)의
|
|
Stop2개/CTest exit0 및362pass는 별도 자동 검증이다. 이를 manual full 성공으로 합치지 않는다.
|
|
|
|
Classifier key의 Correction1회는 사용됐고 추가 source correction은 허용하지 않는다.
|
|
재개 Implementation은 확보된 RED/GREEN을 읽고 현재 source의 focused/full을 재검증한다.
|
|
GREEN source를 다시 망가뜨려 RED를 만들지 않는다. 과거 timeout RED와 마지막 enum fix의
|
|
당시 미검증 기록은 보존하며, enum fix가 이번 focused/full에서 통과했다는 새 evidence를 구분한다.
|
|
Protected Hook1800!=7500과 manual build 환경 문제는 아직 해소되지 않았다.
|
|
|
|
Root는 frozen management `FEATURED_AGENTS.md/ADR.md/coordination.md`, Planning의
|
|
`implementation-plan.md/implementation-environment.md/implementation-recovery.md`,
|
|
독립 Correction의 `corrections.md` **정확7문서만** 먼저 checkpoint한다.
|
|
Correction 보고서는 prep owned_paths 밖이므로 이 선행 문서 commit으로 clean하게 만든다.
|
|
Root ack 뒤에만 Coordinator가 아래 실제 unchanged Executor method 호출을 할당한다.
|
|
Dirty 경로는 source2만 허용하며 phase/top/raw/Hook/status/history와 report는 불변이다.
|
|
아래 AST normalization은 검사에만 사용하고 실행 module/method를 교체하지 않는다.
|
|
|
|
```powershell
|
|
$ErrorActionPreference = 'Stop'
|
|
$mfeCheckpointPython = Join-Path (Get-Location).Path '.harness/build/mitc4-eigen-evidence/prep/classifier-correction/pytest-venv/Scripts/python.exe'
|
|
if (-not (Test-Path -LiteralPath $mfeCheckpointPython -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 = "5dfbea7e543b64fdefcea292de43237adb790a72"
|
|
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, before_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/" + p for p in (
|
|
"FEATURED_AGENTS.md", "ADR.md", "coordination.md", "implementation-plan.md",
|
|
"implementation-environment.md", "implementation-recovery.md", "corrections.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()
|
|
sources = {"scripts/execute.py": "64f5165fc544b3b17904c633ef3b222de79b52a0960e254c5b5c4eb99e79c2d0",
|
|
"tests/test_execute.py": "0eb0c1ca0f25199e00686b7e3ab57672b1390437d09da218a929added0346dd6"}
|
|
fixed = {".codex/hooks.json": "0ab23dad4643f45238f4a60402083e32d8801f5c41fd6ba12b68ef6a9fc5fc28",
|
|
"phases/index.json": "2e4dfef44cd76b7ae447d0e2186a8a949ec29627df9c573646162b92348f1edb",
|
|
"phases/" + phase + "/index.json": "e23269a5518a8dbffbbf2e4706431d7f8af67e43706dcc9086aa6c8991d24262",
|
|
"phases/" + phase + "/step0-output.json": "0d5c0fe0aeba5604c5289764e7aad1834902548ca02158f8feac03484b195941",
|
|
"docs/mitc4-shell-feast-eigen/corrections.md": "d4ea3fb18accc2b2316eb439f56f5106d8ae6640fe79452cef6cb341b1933ee4"}
|
|
def check_hashes():
|
|
for path, expected in {**sources, **fixed}.items():
|
|
assert hashlib.sha256((root / path).read_bytes()).hexdigest() == expected, path
|
|
check_hashes()
|
|
old_tree = ast.parse(ex._run_git_checked("show", origin + ":scripts/execute.py").stdout)
|
|
new_tree = ast.parse((root / "scripts/execute.py").read_text(encoding="utf-8"))
|
|
old_cls = next(n for n in old_tree.body if isinstance(n, ast.ClassDef) and n.name == "StepExecutor")
|
|
new_cls = next(n for n in new_tree.body if isinstance(n, ast.ClassDef) and n.name == "StepExecutor")
|
|
old_methods = {n.name: n for n in old_cls.body if isinstance(n, ast.FunctionDef)}
|
|
new_methods = {n.name: n for n in new_cls.body if isinstance(n, ast.FunctionDef)}
|
|
assert set(new_methods) - set(old_methods) == {"_stdout_has_helper_failure"}
|
|
assert not set(old_methods) - set(new_methods)
|
|
assert {n for n in old_methods if ast.dump(old_methods[n]) != ast.dump(new_methods[n])} == {"_codex_environment_failure"}
|
|
new_cls.body = [old_methods["_codex_environment_failure"] if isinstance(n, ast.FunctionDef)
|
|
and n.name == "_codex_environment_failure" else n for n in new_cls.body
|
|
if not (isinstance(n, ast.FunctionDef) and n.name == "_stdout_has_helper_failure")]
|
|
assert ast.dump(new_tree) == ast.dump(old_tree)
|
|
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])
|
|
assert set(sources) <= set(owned)
|
|
assert set(ex._assert_step_scope(owned)) == set(sources)
|
|
snapshot = {p: (root / p).read_bytes() for p in
|
|
list(owned) + list(fixed) + ["phases/" + phase + "/step0.md",
|
|
"phases/mitc4-shell-feast-eigen/index.json"]}
|
|
assert ex._commit_paths(list(sources),
|
|
"chore(mitc4-shell-feast-eigen-execution-prep): WIP classifier correction with full verification blocked",
|
|
owned_paths=owned)
|
|
after_branch, after_head = ex._git_execution_identity()
|
|
assert after_branch == branch and after_head != before_head
|
|
actual = ex._run_git_checked("diff-tree", "--no-commit-id", "--name-only",
|
|
"--no-renames", "-r", after_head).stdout.splitlines()
|
|
assert set(actual) == set(sources)
|
|
assert all((root / p).read_bytes() == value for p, value in snapshot.items())
|
|
check_hashes()
|
|
assert ex._read_phase_index() == idx and ex._read_top_index() == top
|
|
assert not ex._worktree_paths()
|
|
ex._preflight_repository()
|
|
print(json.dumps({"commit": after_head, "paths": sorted(actual), "clean": True,
|
|
"status": "blocked", "history_count": 1, "branch": branch}))
|
|
'@ | & $mfeCheckpointPython -B -X utf8 -
|
|
$mfeCorrectionCommitExit = $LASTEXITCODE
|
|
if ($null -eq $mfeCorrectionCommitExit) { throw 'Native exit unavailable' }
|
|
exit $mfeCorrectionCommitExit
|
|
```
|
|
|
|
이 명령은 아직 미실행이다. Native exit와 commit path/hash/clean 결과를 실제 관찰한 뒤
|
|
Coordinator가 감사한다. 실패하면 현재 bytes/index/HEAD를 보존하고 자동 재시도하지 않는다.
|
|
새 source commit은 WIP와 전체 검증의 제한을 명시하며 `_commit_step`/completed를 호출하지 않는다.
|
|
|
|
성공 뒤에도 R3의 별도 status-only 할당과 해당 실행 직전 exact DFA 사용자 승인이 필요하다.
|
|
DFA는 아직 승인되지 않았다. 후속 native process에는 [E6의 실제 환경 recipe](implementation-environment.md#e6-correction-후의-pythonpytest와-process-temp)를 적용하고,
|
|
그 환경에서 R4와 동일한 phase/finite14400/approval flag를 사용한다. 새 process는 corrected
|
|
classifier를 로드한다. Protected Hook 권한과 TEMP/TMP 운영 설정의 근거를 혼동하지 않는다.
|
|
Prep full gate·등록 Stop 실제 exit·Coordinator 사후 감사 전 main activation은 금지다.
|
|
|
|
정적 검증은 command AST/PowerShell syntax, source2/report hash, 변경 method2와 나머지
|
|
Executor AST 불변, local links/EOF/whitespace와 blocked archive 동일성을 대상으로 했다.
|
|
정확 결과와 갱신3문서 hash는 handoff에 기록한다. Source/tests/Hook/phase/status/Git과
|
|
Correction 본문은 이번 Planning 작업에서 수정하지 않았다.
|