# 📑 Issue #5 Task Checklist & Verification Evidence - **Document Version**: Rev.7 (Phase 2a 실행 완료 — P2A-01~P2A-04 증거 기록) - **Issue**: [Gitea Issue #5](https://git.godopu.com/tmpl/multi-agent-mux/issues/5) - **Status**: Phase 0 Complete / **Phase 1 Complete (v4.3.0)** / **Phase 2a Complete (shadow-only)** / Phase 2b–4 Staged --- ## Phase 0: 사전 계약 기준선 및 Fixture 수집 (이번 실행 범위) - [x] **P0-01** 기준 commit, dirty diff, Herdr/Python 버전, pytest collection 수 기록. - *증거*: Commit `47640e2`, Herdr `0.8.2`, Python `3.9.6`, Pytest `469 tests collected initially` ➔ `510 tests collected with Phase 0 suite` (+41 contract & mutation tests). - [x] **P0-02** `docs/contracts/issue-5/baseline.md` 작성: 공개 CLI/default/invalid input/stdout-stderr/exit/interpreter/path/signal 계약과 소스·기존 테스트 매핑. - *증거*: `docs/contracts/issue-5/baseline.md` §2 (`--all-reviewer` 우선순위 및 L192–196 소스 매핑 반영). - [x] **P0-03** event schema/HMAC/seq/retain/audit/디스크 fallback 및 publisher 실패 후 로컬 commit 동작 기록. - *증거*: `docs/contracts/issue-5/baseline.md` §3 (감사 로그 경로 `.mam/delegate_job_logs//` 정확히 반영). - [x] **P0-04** event와 registry status 분리; permission clearance·cancelled subscriber 차이·pick_pending 등 writer inventory/gap 기록. - *증거*: `docs/contracts/issue-5/baseline.md` §3, `job_subscriber.py:46, 80` vs `publish_event.py:49` 간극 명시. - [x] **P0-05** report strictness/promotion/cleanup 및 job/session/loop lock 획득·해제/ownership 계약 기록. - *증거*: `docs/contracts/issue-5/baseline.md` §4, §5. - [x] **P0-06** `docs/contracts/issue-5/state-transitions.md` 작성: 4중 귀속, dispatch anchor, target CAS 표와 duplicate/conflict/deadline 정책. - *증거*: `docs/contracts/issue-5/state-transitions.md` §2, §3. - [x] **P0-07** writing/stable_candidate/finalized 및 manifest/hash/부수효과 확정 계약 기록; debounce만으로 completed 금지. - *증거*: `docs/contracts/issue-5/state-transitions.md` §4. - [x] **P0-08** Herdr native wait version/help/spec 및 단일 결과 capture 수집. timeout/unknown target/transport failure와 unknown 상태를 분리하고 외부 collector의 before/after 참조를 검증. - *증거*: `tests/fixtures/issue_5/herdr/wait-contract.json`, `docs/contracts/issue-5/herdr-runtime.md` §1 (timeout stderr 채널 반영). - [x] **P0-09** claude native 상태/call-outcome 행렬·실측 provenance·미관측 gap 기록. - *증거*: `tests/fixtures/issue_5/herdr/claude/idle.json`, `herdr/manifest.json`. - [x] **P0-10** agy native 상태/call-outcome 행렬·실측 provenance·미관측 gap 기록. - *증거*: `tests/fixtures/issue_5/herdr/agy/working.json`, `tests/fixtures/issue_5/herdr/agy/wait_timeout.json`, `herdr/manifest.json`. - [x] **P0-11** hermes native 상태/call-outcome 행렬·실측 provenance·미관측 gap 기록. - *증거*: `herdr/manifest.json` (미가동 세션 gap으로 정직하게 기록). - [x] **P0-12** grok native 상태/call-outcome 행렬·실측 provenance·미관측 gap 기록. - *증거*: `tests/fixtures/issue_5/herdr/grok/idle.json`, `herdr/manifest.json`. - [x] **P0-13** opencode native 상태/call-outcome 행렬·실측 provenance·미관측 gap 기록. - *증거*: `herdr/manifest.json` (미가동 세션 gap으로 정직하게 기록). - [x] **P0-14** codex native 상태/call-outcome 행렬·실측 provenance·미관측 gap 기록. - *증거*: `tests/fixtures/issue_5/herdr/codex/done.json`, `herdr/manifest.json`. - [x] **P0-15** `herdr/manifest.json`과 `watcher/manifest.json` 분리. native observed 캡처만 저장; watcher timeline source별 observed/simulated, 전체 mixed 여부, identity association과 redaction 검증. - *증거*: `tests/fixtures/issue_5/herdr/manifest.json`, `tests/fixtures/issue_5/watcher/manifest.json`. - [x] **P0-16** 두 계층 schema/reference/coverage 테스트 추가: native payload에 job/attempt/report phase 주입 거부, 오류와 상태 분리, simulated를 observed로 표기 거부. 운영 session 쓰기 금지. - *증거*: `tests/test_issue5_phase0_contracts.py`. - *Rev.5 보강 (Codex [P1] 대응)*: `source_kind` 명시적 분기(`SUPPORTED_SOURCE_KINDS`), 관측 증거 스키마 미구현 kind(event/filesystem/harness)의 `observed` 표기 fail-closed 거부, Herdr 항목의 필수 필드·전 필드 대응·세션 UUID/pane/backend 정체성 대응, `capture_ref` 증거 루트 격리, 1캡처=1관측, 매니페스트↔파일 정합성 검증. 계약 명세는 `herdr-runtime.md` §3-1. - [x] **P0-16a** watcher 복합 시나리오 7종 작성: initial idle, tool active, report pause, finalized candidate, blocked, disconnect, generation restart. source별 증거/가상 시계/expected policy를 구분. - *증거*: `tests/fixtures/issue_5/watcher/*.json` (7개 시나리오 완료). - [x] **P0-16b** `herdr-runtime.md`에 native API·단일 wait·외부 collector·file/event/dispatch source 경계를 명시. - *증거*: `docs/contracts/issue-5/herdr-runtime.md`. - [x] **P0-17** Phase 1–4 `implementation_plan.md`/`task.md` 작성, live-helper version/공통 CAS/notification 복구 결정 기록. - *증거*: `docs/contracts/issue-5/implementation_plan.md`, `docs/contracts/issue-5/task.md`. - [x] **P0-18** 관련 CLI/lock/rebuttal/adapter 테스트와 전체 suite 실행; 수집·실행·통과·실패 숫자 분리. - *증거 (Rev.3 당시)*: 전체 484개 수집, 선행 전체 실행 481개 통과(0 failed, 0 skipped, 786.18s), 15개 계약/변이 테스트 전체 통과, 집중 코어 회귀 155개 통과(60.48s). - *증거 (Rev.5, job `fb7fadd4`)*: 전체 suite 실행 **499 passed, 0 failed, 0 skipped (848.90s)** — 커밋 `19d798b` 기준선(계약 테스트 30개 포함)에서 실행. Rev.5 보강 후 계약 테스트 파일 단독 재실행 **41 passed** (`+11`), 수집 총계 **510** (`--collect-only`). Rev.5 변경은 `tests/test_issue5_phase0_contracts.py` 및 `docs/`에 국한되어 나머지 469개 테스트에 영향 없음. - [x] **P0-19** 문서 링크/JSON/git diff --check/production 코드 무변경 확인. - *증거*: `git diff --check` 클린, 공백 린트 완료, 프로덕션 `.sh`/`.py` 무변경 (오직 `docs/`, `tests/` 변경). - [x] **P0-20** 결과 보고: Phase 0 산출물 완료 여부, backend별 native live gap·mixed/simulated scenario 현황, 남은 gate를 별도 명시하고 peer review 요청. - *증거*: `.mam/jobs/61f2fa87/agy-reports/report-final.md` (Rev.3 최초 보고), `.mam/jobs/f29cb24e/claude-code-reports/report-final.md` (Codex [P1]·Claude [Finding 2] 정정, 커밋 `19d798b`), `.mam/jobs/fb7fadd4/claude-reports/report-final.md` (Rev.5 자체 재리뷰 및 보강). --- ## Phase 1: `lib_py/delegation/` 구축 (완료, v4.3.0) - [x] **P1-00** 이동 전 특성화 테스트 선행. 위임 셸 헬퍼 3종의 기존 직접 커버리지는 0건이었다. - *증거*: `tests/test_issue5_phase1_delegation.py` C-01~C-09 (`MAM_DELEGATION_PY` 0/1 양쪽 parametrize), CLI 계약 스냅샷, 자동완료 3표면 불변 가드. 커밋 `265a1f6`. - [x] **P1-01** delegation 스크립트 4종을 `lib_py/delegation/`으로 `git mv` 하고 `scripts/*.py`는 패키지 바인딩 shim으로 보존. 저장소 통합 없음, non-fatal 계약 보존. - *증거*: 커밋 `fb3498e`. PV-1 정체성+출처, PV-4 10개 시나리오(A/A_pe/B/B2/C1/C1_pe/C2/C2_pe/D/E) + K1/K3/K6 서브프로세스 매트릭스, PV-5 shim 바이트 동일성, AST 기반 형제 임포트 금지 검사, `--help` 이동 전 캡처와 무차이. - *설계 근거*: `creator-claude-01`의 이의제기(job `c0b9c987`)로 `sys.path.insert(0)` 방식이 pytest에서 `lib_py.agents`까지 샌드박스 사본으로 가로채는 것이 실증되어, 패키지 단위 bind-once로 확정. - [x] **P1-02** `DelegationService`/`cli.py`/`daemon.py` 구현 및 `lib.sh` 헬퍼 교체. daemon PID·중복·수명 계약 일치. - *증거*: 커밋 `78cb9ec`. C-01~C-09가 레거시·파이썬 두 본체에서 통과, daemon 부모 종료 후 생존 및 `pgrep` 중복 검출, cli가 레거시 실패 문구를 정확히 재현, 발행 실패 시맨틱(status 동기화·seq 소비·`published: false`)이 shim 경로와 cli 경로에서 동일. - [x] **P1-03** 장수 MQTT 연결 프로토타입 및 벤치마크. HMAC/seq/retain/디스크 폴백 회귀 유지, 자동완료 비활성 유지. - *증거*: 커밋 `a4b7b45` + 자체 리뷰 수정 `f5286a0`(job `5e3c7660`에서 발견한 `PersistentPublisher` CONNACK 상태 공유 결함 수정 및 회귀 3종 추가). `publish_event.main`을 `prepare_event`/`record_outcome`/`main`으로 분리(동작 불변, G-1~G-4 통과). 가짜 전송에서 OneShot N connect vs Persistent 1 connect, 두 전송의 레지스트리·감사 레코드 필드 단위 동일, PUBACK 미확인 시 재시도 후 `published=false`, 브로커 상이 시 거부. 네트워크 접촉 0. - [x] **P1-04** 벤치마크 실측 및 문서 동기화, 롤백 드릴. - *증거*: `docs/contracts/issue-5/phase1-benchmark.md`. 가짜 전송 p50 54.813ms → 0.002ms(연결 50회 → 1회), 실브로커 p50 1892.728ms → 275.992ms(정보성). `MAM_DELEGATION_PY=0` 롤백 드릴 및 K2(freeze 사본 + 라이브 `PYTHONPATH`) 실증 완료. --- ## Phase 2a: `lib_py/loop/` 코어 & Shadow Watcher (완료, shadow-only) - [x] **P2A-00** 이동 전 writer 특성화 선행 (X-01~X-04, `MAM_ENGINE_CAS` 0/1 parametrize). - *증거*: 커밋 `9389d7e`. X-02가 계획서의 초기 가정을 정정한다 — `pick_pending`은 락 안에서 `pending`을 필터하므로 **이미 올바른 CAS**이며, 문제는 정확성이 아니라 **중복**이다. - [x] **P2A-01** 단일 전이 경계 구현 및 writer 2종 라우팅. - *증거*: 커밋 `2532e78`. `engine.transition`이 유일한 상태 writer. `state-transitions.md` §3 표 전 항목(claim/비terminal/explicit terminal/멱등 재수신/상충 거부+감사/stale attempt/deadline) 테스트. `MAM_ENGINE_CAS=0` 레거시 본체 보존. - *계획 대비 구조 정정*: 계획서는 `engine.py`를 `lib_py/loop/`에 두었으나, 그러면 `lib_py.delegation`이 **형제 패키지를 임포트**하게 되어 freeze 하에서 트리가 섞인다(Phase 1이 명문화한 규칙). Phase 1의 기존 가드 테스트가 이를 즉시 검출했고, 엔진을 레지스트리 writer들이 있는 `lib_py/delegation/`으로 옮겼다. - *락 규율*: 락은 판정 + 레코드 1회 쓰기만 덮고, 감사 mirror는 큐잉 후 락 해제 뒤 flush한다. 순서는 `transition_seq`로 복원한다. 락 보유 중 `subprocess`/`socket`/`sleep` 호출 0건을 테스트로 감시한다. - [x] **P2A-02** watcher·귀속·dispatch 증거·재연결 백오프. - *증거*: 커밋 `b49af56`. `--timeout`은 **밀리초**(파라미터명 `timeout_ms`), `--until` 항상 명시(생략 시 `working` 누락), exit 1은 **stderr**에서 파싱. 백오프 1→2→4→8→16s 상한, 실패 시 캐시 스냅샷 폐기. 귀속 증거는 **레지스트리가 아닌 shadow 전용 저장소**(`.mam/shadow/`)에 둔다 — 레코드에 3개 필드가 전부 없고 Phase 1이 스키마를 동결했기 때문. - [x] **P2A-03** shadow-only가 terminal을 쓰지 않음을 검증. - *증거*: 커밋 `964abc6`. `ShadowRunner`는 engine 참조를 **갖지 않는다**(구조적 차단, AST 단정). 측정: 전체 시나리오 실행 전후 **레지스트리 디렉터리 전 파일 SHA-256 동일**. - [x] **P2A-05** 교차 리뷰(`68abd0ff` Claude / `cae12436` Codex) 지적 5건 전건 수용·수정. - *증거*: 커밋 `56d08ef`. F-A(래퍼 loop/discuss 전이 2건 누락 → 운영자 권한 요청 `redispatch`/`finalize` 신설 + CLI 거부 시 non-zero), F-B(감사 mirror 순서 회귀 → `transition_seq` 비교), R1(관측 식별자 미대조 → `collect_observed_identity` 전량 대조 + 매니페스트 attempt 검증), R2(`expected_attempt`가 레코드에 없으면 무시 → fail-closed), R3(raw `status` 필드 우회 → 요청만이 status를 설정). 신규 회귀 11종 전부 수정 전 코드에서 실패함을 역검증. - [x] **P2A-04** race/attempt 재사용/부분 report/도구 실행/blocked/unknown/재시작 시나리오. - *증거*: 신규 5종(`race_double_dispatch`, `attempt_reuse`, `partial_report`, `unknown_status`, `restart_midflight`)을 Phase 0 스키마로 작성해 **Phase 0의 `validate_watcher_scenario`를 통과**시켰고, 기존 7종과 합쳐 **12종 전부 `expected_policy.decision`과 일치**함을 단정한다. --- ## Phase 2b: 이중 감지 자동완료 활성화 (후속) - [ ] **P2B-01** report finalization/manifest/hash 및 외부 부수효과 evidence protocol 구현. - [ ] **P2B-02** terminal+pending notification commit/재전송·재시작·늦은 conflict 처리 검증. - [ ] **P2B-03** 검증된 backend/job에만 default-off flag로 활성화; unsupported explicit event 경로 보존. --- ## Phase 3: `run_loop.sh` Thin Wrapper 전환 및 전면 회귀 (후속) - [ ] **P3-01** planner/reviewer/rebuttal/promotion 및 strict 판정/예산/중재/합의 테스트. - [ ] **P3-02** thin wrapper 인자·interpreter·cwd·signal·guard·child cleanup 호환 검증. - *인계 (교차 리뷰 `25609c81` O-4)*: freeze 사본의 `lib.sh`에서 `_delegate_py_bin`은 `AGENT_PYTHON_BIN`/`VIRTUAL_ENV`가 없으면 **자기 위치에서 상향 탐색**하는데, freeze 디렉터리 아래에는 `.venv`가 없어 paho가 없는 시스템 `python3`로 떨어진다. Phase 1에서는 freeze `lib.sh`의 위임 헬퍼를 호출하는 프로덕션 경로가 없어 무해하나, **Phase 3에서 루프 프로세스가 freeze `lib.sh`의 헬퍼를 직접 호출하기 시작하면** 인터프리터 해석을 `WORKSPACE_ROOT`(또는 `MAM_REAL_ROOT`) 기준으로 앵커링해야 한다. - [ ] **P3-03** 전체 suite+신규 race/restart/lifecycle, writer 단일성, rollback checkpoint 인계 검증. --- ## Phase 4: 불변 런타임 검증 및 Freeze 제거 (후속) - [ ] **P4-01** eager import+child/helper/template 실행 버전 정책 구현/검증. - [ ] **P4-02** 실행 중 코드 교체와 늦은 재심/승격/rollback 스트레스 검증. - [ ] **P4-03** gate 통과 후에만 Freeze 제거 및 운영 문서 갱신.