docs(issue-6): establish phase 1-5 implementation plan and task checklist (Rev.2)
This commit is contained in:
1 parent
f98b9582c7
commit
7b761be7b8
6 files changed
+827
No files matched your search
@@ -0,0 +1,104 @@
|
||||
# 📑 Issue #6 Task Checklist & Verification Evidence
|
||||
|
||||
- **Document Version**: Rev.2 (Planner `planner-reviewer-claude-01`, job `f4873d82` — Creator 이의제기 3건 반영)
|
||||
- **Issue**: [Gitea Issue #6](https://git.godopu.com/tmpl/multi-agent-mux/issues/6)
|
||||
- **Plan**: `docs/contracts/issue-6/implementation_plan.md` (Rev.2)
|
||||
- **Baseline**: `f98b958` (v4.4.0), 750 passed
|
||||
- **Status**: Phase 1 대기
|
||||
|
||||
> 각 항목은 완료 시 `[x]`로 바꾸고 바로 아래 `*증거*:` 줄에 커밋 해시·테스트 ID·실측 수치를 기록한다(Issue #5 관례). 신규 회귀 테스트는 **수정 전 코드에서 실패함을 역검증**한 뒤 통과 증거를 남긴다.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: 레지스트리 CAS 표준 연동 및 delegate-job Fail-Closed
|
||||
|
||||
- [ ] **P1-01** `registry.py close --job <id> --request {deadline_timeout,cancelled} [--detail] [--expect-dispatch-token]` 서브커맨드 추가 (`engine.transition(..., request, source="delegate_wrapper")`). rc: 커밋/멱등/terminal 거부 0, 레코드 없음 1, 토큰 불일치 4.
|
||||
- *증거*:
|
||||
- [ ] **P1-02** 래퍼에 `reap_subscriber`, `_disk_status`, `_map_sub_rc`(기존 `:340-354` 리터럴 보존), `_rc_for`, `finalize_unfinished` 헬퍼 추가. phase `preflight|idle_wait`는 `cancelled`/`session_busy`(rc 5), 그 외는 `deadline_timeout`. `MAM_DELEGATE_FAIL_CLOSED=0` 롤백 분기 포함.
|
||||
- *증거*:
|
||||
- [ ] **P1-03** direct 경로 `:227` `|| true` 제거 → `sub_rc` 매핑 → `finalize_unfinished` → 종료 코드 0/1/2/3/5. 마지막 stdout 줄(감사 경로) 유지.
|
||||
- *증거*:
|
||||
- [ ] **P1-04** loop/discuss 워커(`:359`)·리뷰어(`:375`) `break` 직전 `finalize_unfinished` 호출. **loop 경로에서 `publish_event --event error` 발행 금지**(O-1).
|
||||
- *증거*:
|
||||
- [ ] **P1-05** `run_agent` 실패 분기 명시화(`if ! run_agent`): `reap_subscriber` + `finalize_unfinished … inject` + `exit 1`. trap(`:523`)에 `--registry-dir "$REGISTRY_DIR"` 추가.
|
||||
- *증거*:
|
||||
- [ ] **P1-06** rc=3 처리: 남은 데드라인 동안 3s 간격 디스크 재관측, terminal 발견 시 채택, 아니면 `deadline_timeout`(rc=3).
|
||||
- *증거*:
|
||||
- [ ] **P1-07** dry-run direct에서 구독자 미기동 (현재 `:166` 기동 후 `:224` `return 0`).
|
||||
- *증거*:
|
||||
- [ ] **P1-08** 결정적 재현 4종(T1-1, T1-2, T1-4, T1-7)이 수정 전 실패·수정 후 통과. `test_wrapper_exit_code_mapping_literals_are_frozen` 통과.
|
||||
- *증거*:
|
||||
- [ ] **P1-09** 롤백 드릴: `MAM_DELEGATE_FAIL_CLOSED=0`에서 T1-8 재현(rc=0, `pending`).
|
||||
- *증거*:
|
||||
- [ ] **P1-10** (Rev.2 Tertiary) `attempt_id` 규약: `registry.py update --attempt-id`, `engine._decide` redispatch가 `attempt_id` 공급 시 이를 전진 조건으로 사용(미공급 시 기존 iteration 규칙), `redispatch`/`claim` 커밋 시 레코드 기록, `publish_event --finalize-report` 기본 attempt_id가 `record.attempt_id` 우선.
|
||||
- *증거*:
|
||||
- [ ] **P1-11** 래퍼 loop 경로: phase 디스패치마다 `attempt` 증가 후 `update … --attempt-id "$attempt"`. T1-10(수정 전 rc=4 역검증)/T1-11/T1-12, F-A 3종 무변경 통과.
|
||||
- *증거*:
|
||||
- [ ] **P1-12** T1-13 `close --request cancelled` 전이 규칙 고정.
|
||||
- *증거*:
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: 사전 TUI 유휴 핸드셰이크 및 제출 검증 보강
|
||||
|
||||
- [ ] **P2-01** `lib_py/loop/watcher.py`에 `main()`/`__main__` 추가: `wait <target> --session S --until … --timeout-ms N`, JSON 1줄 stdout, rc matched 0 / timeout 2 / agent_not_found 3 / transport_error 4. `build_argv(..., session=None)`가 `default`가 아닌 세션이면 `herdr --session S agent wait …`로 구성(Rev.2 Primary-A). `lib_py.delegation`→`lib_py.loop` 임포트 0건 유지(`test_delegation_package_imports_no_sibling_lib_py_modules`).
|
||||
- *증거*:
|
||||
- [ ] **P2-02** `lib.sh: wait_for_agent_idle`: `SKS_IDLE_HANDSHAKE`, 사전 `_sks_herdr agent get`(`unknown`→3, `blocked`→2, `idle|done`→0), `working`→`"$(_delegate_py_bin)" -m lib_py.loop.watcher wait <t> --session "$HERDR_SESSION_NAME" --until idle --until done --until blocked --timeout-ms ${SKS_IDLE_TIMEOUT_MS:-120000}`, timeout은 `SKS_IDLE_RETRIES`(2)×`SKS_IDLE_RETRY_BACKOFF_S`(10) 재시도 후 rc 1. bare `python` 금지. `interactive_ready` 미사용.
|
||||
- *증거*:
|
||||
- [ ] **P2-03** 래퍼 `run_agent`를 `preflight_agent` + `inject_agent`로 분리. 순서: register → preflight → idle wait → `_disp_tok` 읽기 → 구독자 기동 → inject → wait → finalize. direct·loop 양 경로 적용. 프리플라이트/idle 실패 시 `finalize_unfinished … preflight|idle_wait`(→ `cancelled`/`session_busy`) + `exit 5`.
|
||||
- *증거*:
|
||||
- [ ] **P2-04** `send_keys_safe` 제출 검증: pre_submit에 존재한 busy 토큰 배제(`:2330-2332`).
|
||||
- *증거*:
|
||||
- [ ] **P2-05** `send_keys_safe` 네이티브 경로 `agent prompt --wait --until working --timeout 5000` (`SKS_PROMPT_WAIT=1` 기본). stalled/timeout → 재제출 없이 `agent get` 1회 확인, `agent_blocked` → rc 2, 불명 → rc 4.
|
||||
- *증거*:
|
||||
- [ ] **P2-06** 폴백(`unknown`) 경로 busy 토큰 게이트(`SKS_BUSY_TIMEOUT` 기본 120s).
|
||||
- *증거*:
|
||||
- [ ] **P2-07** T2-1~T2-11 통과, `test_h16`/`test_b8`/`test_c1_*`/`test_herdr_shim_contract` 무변경 통과. 롤백 드릴 `SKS_IDLE_HANDSHAKE=0`.
|
||||
- *증거*:
|
||||
- [ ] **P2-08** (Rev.2 Primary) T2-10 `--session` argv 단정, T2-11 bare `python` 정적 린트 0건.
|
||||
- *증거*:
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: 오케스트레이터 러너 Fail-Fast 연결
|
||||
|
||||
- [ ] **P3-01** `runner.delegate_job`: rc≠0에서도 `registered job:` 파싱 → `created_jobs`·checkpoint 기록 → id 반환. 미매치 시만 `None`.
|
||||
- *증거*:
|
||||
- [ ] **P3-02** `run_loop.sh` `delegate_job_safe`/`:373` 파싱 동등성(`MAM_LOOP_PY=0`).
|
||||
- *증거*:
|
||||
- [ ] **P3-03** T3-1(`wait_for_job` ≤ 2s False), T3-2(checkpoint 기록), `test_issue5_phase3_loop.py` 무변경 통과.
|
||||
- *증거*:
|
||||
- [ ] **P3-04** (Rev.2 Secondary) `delegate_job` rc=5 → `MAM_SESSION_BUSY_RETRY_S`(30) 대기 후 1회 재위임. T3-3.
|
||||
- *증거*:
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: 단위/계약 회귀 스위트 및 문서
|
||||
|
||||
- [ ] **P4-01** `tests/conftest.py` mock_herdr 확장: `agent get/list`에 `agent_status`(기본 `idle`), `agent wait`(`status_sequence` 소비, timeout 시 stderr JSON rc 1), `agent prompt --wait`(`prompt_wait_result`), 전역 `--session <name>` 인자 수용·호출 기록. 기존 테스트 무변경 통과.
|
||||
- *증거*:
|
||||
- [ ] **P4-02** `tests/test_issue6_fail_closed.py` T1-1~T1-13, T3-1~T3-3 작성 및 역검증.
|
||||
- *증거*:
|
||||
- [ ] **P4-03** `tests/test_issue6_turn_handshake.py` T2-1~T2-11 작성 및 역검증.
|
||||
- *증거*:
|
||||
- [ ] **P4-04** 문서: `multi-agent-mux-delegate-job/SKILL.md` 종료 코드 표, `MESSAGING.md` §5.1 구독자 타임아웃→레지스트리 반영, `BOOTSTRAP.md`/`BOOTSTRAP.ko.md` "completed 발행 후 도구 호출 없이 턴 종료" 1문장. `test_deploy_freshness.py`(`MQTT_*` 10종)·`test_o1_rebuttal.py` 통과.
|
||||
- *증거*:
|
||||
- [ ] **P4-05** 전체 스위트 0-Fail (750 + 신규 ≥ 20), `git diff --check` 클린, 수집 수·통과 수·소요 시간 기록.
|
||||
- *증거*:
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: 실기동 E2E, 정리, 릴리스
|
||||
|
||||
- [ ] **P5-01** 4개 백엔드(Claude/Grok/Codex/OpenCode) 연속 위임 E2E(**direct 모드**; loop 모드 종단은 O-1 이슈 완료 후): `completed`→다음 잡 `started` 타임라인, idle 대기 시간, 주입 실패·중복 0건. `docs/contracts/issue-6/phase5-e2e.md` 작성.
|
||||
- *증거*:
|
||||
- [ ] **P5-02** 타임아웃 주입 E2E(`--idle-timeout 30`, 프롬프트 무시): 래퍼 rc=2, `error`, `wait_for_job` ≤ 2s.
|
||||
- *증거*:
|
||||
- [ ] **P5-03** 잔존 레코드 `93a44347`, `2961b822`, `ee242671` `registry.py close --request deadline_timeout … --detail "Issue #6 backfill"`로 폐쇄.
|
||||
- *증거*:
|
||||
- [ ] **P5-04** `IMPROVEMENTS.md` §5 `Issue-6-FailClosed-TurnHandshake` 블록 추가(§6 표·헤더 키 목록·건수 동기화). 별도 이슈 등록: O-1 리테인 재수락(**loop/discuss 모드 사용 전 필수**로 표기), 레지스트리 오염.
|
||||
- *증거*:
|
||||
- [ ] **P5-05** `v4.4.1` 4-way 락스텝(`lib.sh:32`, `eager.py:16`, `VERSIONS.md` 개요·매트릭스·Changelog, 8개 `SKILL.md`), `test_version_consistency.py` 통과.
|
||||
- *증거*:
|
||||
- [ ] **P5-06** 리뷰어 교차 검토 `[VERDICT: PASS]` 후 `main` 병합.
|
||||
- *증거*:
|
||||
Reference in new issue
Block a user