Files

107 lines
6.9 KiB
Markdown

# 📑 Issue #5 Phase 3 — `run_loop.sh` Thin Wrapper 전환 및 `lib_py.loop` 승격 명세
- **문서 버전**: Rev.1
- **상태**: Phase 3 설계 및 이식 착수 기준선 (Implementation & Regression Specification)
- **대상 파일**:
- `lib_py/loop/runner.py`, `lib_py/loop/__main__.py`, `lib_py/loop/parser.py`
- `.agents/skills/multi-agent-mux-loop/scripts/run_loop.sh`
- `tests/test_issue5_phase3_loop.py`
---
## 1. 개요 및 한 문장 요약
**936줄의 복잡한 Bash 오케스트레이션(`run_loop.sh`)을 단일 제어 구조의 Python 모듈(`lib_py.loop`)로 승격하고, `run_loop.sh`는 CLI 계약과 B-13 Freeze를 보존하는 얇은 래퍼(Thin Wrapper)로 전환한다.**
Phase 2(CAS 전이 엔진, 이중 감지 자동완료 게이트)에서 구축된 상태 및 판정 기반을 실제 루프 제어 흐름에 유기적으로 결합하며, 기존 732개 테스트의 0-Fail 통과와 셸 레거시 롤백(`MAM_LOOP_PY=0`)을 보장합니다.
---
## 2. 모듈 아키텍처 (`lib_py/loop/`)
Phase 1/2a의 형제 패키지 격리 원칙(D1(b), G9: `lib_py.loop`는 `lib_py.delegation` 외의 다른 형제 패키지를 임포트하지 않음)을 엄격히 준수합니다.
```
lib_py/loop/
├── __init__.py # 패키지 선언 및 export
├── __main__.py # python3 -m lib_py.loop 진입점
├── parser.py # 코드 펜스 제외 Strict 판정/태그 파서
├── runner.py # 오케스트레이터 본체 (LoopRunner 클래스)
├── checkpoint.py # 체크포인트 기록 및 복구 (.mam/loop-checkpoint.json)
├── attribution.py # [Phase 2a] 관측 증거 수집
├── watcher.py # [Phase 2a] herdr agent wait 래퍼
├── policy.py # [Phase 2a] 상태 결정 정책
├── shadow.py # [Phase 2a] Would-Complete shadow 실행기
├── store.py # [Phase 2a] 증거 저장소
└── autocomplete.py # [Phase 2b] 자동완료 평가기
```
---
## 3. 핵심 설계 요소
### 3-1. 엄격한 판정 파서 (Strict Parser, `parser.py`)
- **코드 펜스(` ``` `) 무시**:
- 기존 셸 정규식은 리포트 본문 내 코드 블록(예: 마크다운 예시 등)에 적힌 `[VERDICT: PASS]`도 파일 끝에 위치하면 유효한 판정으로 오인하는 결함(`baseline.md` Gap)이 존재했습니다.
- Python 파서는 텍스트를 파싱할 때 마크다운 코드 펜스(` ``` ` 또는 `~~~`) 내부 라인을 제거한 뒤, **가장 마지막 비공백 라인(last non-blank line)**만을 검사합니다.
- **Fail-Closed 불변식**:
- 판정 라인이 없거나, `[VERDICT: NOT PASS]`와 `[VERDICT: PASS]`가 모호하게 충돌하거나, 알 수 없는 태그인 경우 예외 없이 `NOT PASS`로 처리합니다.
- **태그 추출**:
- `[ESCALATE: PLANNER]`: 코드 펜스 외부 어디서든 단독 행으로 존재하면 감지
- `[REBUT: <reviewer>]`: Creator 반론 대상 리뷰어 세션명 추출 (중복 제거 및 실제 거부한 리뷰어로 필터링)
- `[ADJUDICATION: SUSTAINED|OVERRULED]`: 재심 판정 추출 (fail-closed: 명시적 SUSTAINED 외에는 모두 OVERRULED)
- `[ARBITRATION: CREATOR|REVIEWER]`: Planner 중재 판정 추출
### 3-2. `run_loop.sh` Thin Wrapper 및 하위 호환성
- **하위 호환 롤백 플래그**:
- `MAM_LOOP_PY=1` (기본값): Python `lib_py.loop` 실행
- `MAM_LOOP_PY=0`: 기존 인라인 셸 루프 실행 (안전 롤백 경로)
- **B-13 Freeze 및 인자 보존**:
- Phase 4에서 Freeze가 제거되기 전까지, `run_loop.sh`는 기존처럼 기동 시 `/tmp/mam-loop-freeze.XXXXXX`로 트리를 복제하여 실행 격리를 유지합니다.
- `MAM_REAL_ROOT`, `WORKSPACE_ROOT`, `MAM_ENV_FILE` 환경변수 export를 그대로 유지하여 기존 테스트의 문자열 검증을 만족합니다.
- **기존 테스트 텍스트 앵커 보존**:
- `test_o1_rebuttal.py` (`has_tag_line() {`, `extract_tag_values() {`, `find_report() {`)
- `test_b7_diff_untracked.py` (`CHANGES_DIFF=$(mam_collect_changes_diff ...`)
- `test_deploy_freshness.py` (`export MAM_ENV_FILE=`)
- `test_o3_scoped_guard.py` (`mam_release_loop_lock`)
- 위 앵커들은 `run_loop.sh` 내에 셸 헬퍼 또는 주석/shim 블록으로 보존되어 기존 정적 검사 테스트들을 100% 통과시킵니다.
### 3-3. 체크포인트 및 정지 프로토콜 (`checkpoint.py`)
- **원자적 체크포인트 (`.mam/loop-checkpoint.json`)**:
- 루프 회차(`iteration`), 활성 Job ID 목록(`created_jobs`), 현재 계획(`current_plan`), 리뷰 상태(`review_status`), 기준 커밋(`base_commit`), 타임스탬프 기록.
- 임시 파일 쓰기 후 원자적 rename(`replace`)으로 커밋.
- **우아한 정지 (Quiesce on Signal)**:
- SIGINT/SIGTERM 수신 시 즉시 강제 종료하지 않고, 현재 진행 중인 서브프로세스를 정리하고 체크포인트를 기록한 뒤 가드를 해제하고 안전하게 종료(exit 130/143)합니다.
---
## 4. 단계별 세부 구현 및 검증 게이트 (P3-01 ~ P3-03)
### 📌 P3-01: `lib_py/loop/parser.py` 및 오케스트레이션 로직 이식
1. `parser.py` 구현: 코드 펜스 분리 및 엄격한 판정/태그 추출 로직 작성.
2. `runner.py` 구현:
- CLI 인자 파싱 및 검증 (`--creator`, `--task`, `--plan`, `--plan-talk`, `--reviewer`, `--all-reviewer`, `--max-loop`, `--max-rebut`, `--cleanup`, `--verbose`)
- 세션 조회 및 상태 검증 (Planner, Target Agent, Reviewers)
- Phase 1 플래닝 및 토론 (Plan ➔ Critique ➔ Refine)
- Phase 2 구현 디스패치 (Worker)
- Phase 3 리뷰 루프 (병렬 디스패치, Strict 판정 수렴, Escalation 분기, Rebuttal/Adjudication/Arbitration)
- Phase 4 산출물 승격 (Plan 및 Report 원자적 복사/이동) 및 임시 디렉터리 정리
3. `tests/test_issue5_phase3_loop.py` 작성:
- 코드 펜스 내부 허위 판정 무시 검증 (Strict Parser)
- Rebuttal 예산(iteration budget vs run-wide budget) 및 중재 흐름 검증
- 만장일치 PASS 수렴 검증
### 📌 P3-02: `run_loop.sh` Thin Wrapper 전환 및 런타임 호환성
1. `run_loop.sh`에 `MAM_LOOP_PY` 분기 도입:
- `MAM_LOOP_PY=1`일 때 Python `lib_py.loop`로 위임
- 기존 CLI 파싱, `--help` exit 1 유지, B-13 freeze 격리 유지
- 기존 테스트 텍스트 앵커 보존
2. CWD, 공백 경로, 시그널 트랩, 인터프리터 앵커링 검증:
- Freeze 사본 내에서 실행 시 `_delegate_py_bin`이 `WORKSPACE_ROOT` 기준 인터프리터를 정확히 해석하는지 검증 (O-4 인계 해결)
### 📌 P3-03: 전면 회귀 검증 및 체크포인트 핸드오프
1. 전체 732개 테스트 회귀 검증:
- `test_loop_cli.py`, `test_o1_rebuttal.py`, `test_tier4_e2e.py` (Scenario 5 E2E 루프 포함) 전체 0-Fail 통과
2. 체크포인트 기록 및 시그널 인터럽트 시뮬레이션 검증.
3. 롤백 드릴: `MAM_LOOP_PY=0`으로 기존 셸 루프 전환 시 정상 작동 확인.