- Introduce finalize_unfinished in multi-agent-mux-delegate-job for fail-closed atomic transitions - Enforce CAS dispatch_token and attempt_id pinning across engine, CLI, and lifecycle scripts - Integrate Herdr wait_for_agent_idle turn handshake to prevent prompt loss and race conditions - Resolve bash 3.2 set -u empty array expansion compatibility in lib.sh - Preserve Issue #5 R2 contract in CAS transition engine (engine.py, publish_event.py, service.py) - Add comprehensive regression suites (test_issue6_fail_closed.py, test_issue6_turn_handshake.py) - Bump lockstep framework and skills to v4.4.1 across lib.sh, eager.py, VERSIONS.md, 8 SKILL.md - Synchronize documentation (IMPROVEMENTS.md, MESSAGING.md, state-transitions.md, task.md, phase5-e2e.md) - Unanimous PASS achieved across 4 reviewer team leaders (Claude, Codex, OpenCode, Grok) Closes #6
63 lines
5.5 KiB
Markdown
63 lines
5.5 KiB
Markdown
### [planner-reviewer-claude-01] Issue #6 구현 결과물 9차 최종 만장일치 재검토 의견
|
||
|
||
- Job `51b67d19` / Reviewer / 검토 대상: 워킹트리(`git diff 7b761be`, 40 파일 +1366/−292). 8차 검토(`08e87682`) 이후 변경: `engine.py`·`publish_event.py`·`service.py`(09:26 KST), `cli.py`·`stop_session.sh`·`create_session.sh`·`test_issue6_fail_closed.py`(09:27), `lib.sh`·`state-transitions.md`·`MESSAGING.md`(09:28).
|
||
- 검토 방법: 8차 지적 B1·B2와 Codex P2 조치를 코드로 확인하고, 1~8차 하니스를 같은 조건으로 재실행했다(`[실측]`). 브리프의 8개 모듈과 전체 스위트는 §3.
|
||
|
||
---
|
||
|
||
## 1. 8차 지적 사항 조치 확인
|
||
|
||
| # | 항목 | 반영 | 실측/근거 |
|
||
|---|---|---|---|
|
||
| 1 | **[B1]** bash 3.2 빈 배열 확장 | ✅ | `lib.sh:1913,2007` 두 헬퍼 모두 `${extra[@]+"${extra[@]}"}`. 미보호 `"${extra[@]}"`·`"${*args[@]}"` 잔존 0건(`lib.sh`·`stop_session.sh`·`create_session.sh`). `[실측]` `/bin/bash 3.2 set -euo pipefail`에서 `delegate_publish_event` 인자 없이/토큰 포함/레거시 본체(`MAM_DELEGATION_PY=0`) 3회 모두 rc 0, 이벤트 3건 기록 |
|
||
| 2 | **[B2]** 토큰 필수 규칙 축소 | ✅ | 엔진·CLI·서비스 3층 모두 "토큰과 `expected_attempt`가 둘 다 없을 때"로 한정(`engine.py:191-195`, `publish_event.py:307-311`, `service.py:70-74`). `[실측]` `attempt_id=7` 레코드에 `expected_attempt=7`·토큰 없음 → **커밋**(R2 계약 복원); attempt 2·둘 다 없음 → 거절 |
|
||
| 3 | **[Codex P2]** 라이프사이클 토큰 고정 | ✅ | `stop_session.sh`·`create_session.sh`가 잡 레코드에서 `dispatch_token`/`attempt_id`를 고정해 4·5번째 인자로 전달, `cli.py publish`가 두 옵션을 포워딩, `lib.sh`가 `MAM_JOBS_DIR`→`--registry-dir` 전달. T1-25(attempt 2 `cancelled` 전이, attempt 3 재위임 후 stale 취소 rc 4) 통과 |
|
||
| 4 | **[N1]** 계약 문서 | ✅ | `state-transitions.md:55,57`(권한 축에 `delegate_wrapper`, 시도 정체성 규칙), `MESSAGING.md` §5.1("`attempt_id > 1` 잡의 terminal 요청은 토큰 또는 `expected_attempt` 필수") |
|
||
|
||
---
|
||
|
||
## 2. 핵심 결함 완결성 최종 평가 `[실측]`
|
||
|
||
| 시나리오 | 결과 |
|
||
|---|---|
|
||
| attempt-1 direct, 토큰 없는 레거시 `completed` | 디스크 폴백으로 rc 0 `completed` (하위 호환) |
|
||
| loop 2-phase 종단(`/bin/bash 3.2`, 워커 tok1 → 리뷰어 tok2 `PASS`, `--validate`) | rc 0, `completed`, `attempt_id=2`, 훅 실행 1회 |
|
||
| direct R1-a(`working`, 8s 후 토큰 포함 `completed`) | rc 0, `completed` |
|
||
| 8차 하니스(attempt-2 토큰 없는 terminal 거절, `close` on completed 거절, R1-b 벽시계, stale 디스크 레코드 거부) | 해당 코드 무변경 구간(래퍼·구독자) → 8차 결과 유효 |
|
||
|
||
결함 ①·②, R1, bash 3.2(루프·헬퍼), 시도별 토큰 바인딩, 디스크 폴백 검증, 토큰 없는 종료 차단(R2 계약 보존)까지 모두 실측으로 완결되었고 각 동작에 실행되는 회귀 테스트가 있다.
|
||
|
||
---
|
||
|
||
## 3. 테스트 결과
|
||
|
||
| 실행 | 결과 |
|
||
|---|---|
|
||
| 브리프 8개 모듈 (전체 스위트와 **병행** 실행) | 3 failed / 208 passed — 실패 3건 모두 `subprocess.TimeoutExpired`(T1-7 30s, T1-15 25s, T1-16 45s 하니스 타임아웃) |
|
||
| 위 3건 격리 재실행 | **3 passed (49.8s)**; 전체 스위트의 T1-1도 발행 후 격리 재실행 → **1 passed in 10.96s** |
|
||
| 전체 스위트 (본 검토자, 재실행·하니스와 **병행**) | **1 failed / 792 passed (1628s)** — 실패 1건은 T1-1 `TimeoutExpired`(동일 부류) |
|
||
| Creator 보고(단독 실행) | 793 passed / 0 failed (1478.7s) — 7차의 791/0과 정합 |
|
||
| `bash -n` 4파일, `git diff --check`, 4-way 락스텝 4.4.1, IMPROVEMENTS 32=32 | 통과 |
|
||
|
||
판정: 실패는 전부 Issue #6 테스트의 **하니스 `timeout=`이 동시 부하에서 래퍼 실행 시간(mock herdr 파이썬 기동 ×N + 벽시계 예산)을 못 따라간 것**이며, 코드 결함이나 결정적 실패는 없다(격리·단독 실행 전부 통과). 7차 PASS 때와 같은 성격이다.
|
||
|
||
---
|
||
|
||
## 4. 비차단 지적 (머지 시 정리 권장)
|
||
|
||
| ID | 내용 |
|
||
|---|---|
|
||
| N1 | `test_issue6_fail_closed.py` T1-1/T1-7/T1-15/T1-16의 `_run_wrapper(timeout=…)`을 래퍼 `--timeout`의 3배 이상(≥90s)으로 상향하고, T1-15·T1-16의 고정 `sleep`을 T1-14/T1-20처럼 구독자 로그 관측 기반으로 전환. 부하 하 CI 안정성 |
|
||
| N2 | `phase5-e2e.md` 행 1 `e59778a0`(구현 이전 잡)·§5 "783 collected/0-Fail", `task.md` P4-05 수치 미갱신(실측 793 수집). 7~9차의 loop 2-phase 종단 결과를 Phase 5 증거로 옮길 것 |
|
||
| N3 | `test_bug4_send_keys_safe_gating_order` 2500자 창 여유 23자; 오케스트레이터 브리프의 완료 명령 템플릿 토큰 누락(attempt 1에서는 폴백 동작) |
|
||
| N4 | 이전 라운드 잔여(러너 첫 rc=5 잡 id, T1-1/T1-2 `events.log` 경로, T2-8 순서, `MAM_ENGINE_CAS=0` `close`, `MQTT_HOST` 문서) — 동작 영향 없음 |
|
||
| N5 | 범위 밖 인계: 레지스트리 pytest 누출, 동시 스위트 실행이 남기는 샌드박스 고아 프로세스 |
|
||
|
||
---
|
||
|
||
## 5. 최종 판정
|
||
|
||
8차의 두 결정적 회귀(bash 3.2 세션 생성 롤백, R2 계약 파괴)는 실측으로 해소되었고, Codex P2의 라이프사이클 토큰 고정과 계약 문서까지 반영되었다. 코드 동작은 1~9차 하니스 전부에서 일치하며, 결정적 실패는 없다. 남은 것은 부하 하에서만 드러나는 테스트 하니스 타임아웃(N1)과 문서 수치(N2)로, 머지 커밋에서 정리하면 된다.
|
||
|
||
[VERDICT: PASS]
|