[Refactor] lib.sh 작업 위임 로직 및 run_loop.sh 오케스트레이터의 Python 모듈화 (lib_py 승격) #5

Closed
opened 2026-09-05 23:50:39 +00:00 by Godopu · 5 comments
Owner

개요 (Overview)

현재 lib.sh (2,313 라인) 및 run_loop.sh (937 라인) 등 핵심 오케스트레이션 로직이 대규모 셸 스크립트로 작성되어 있어, 셸 스크립팅의 한계로 인한 유지보수성 저하, 프로세스 포크 오버헤드, 런타임 자기수정 충돌(B-13 이슈), 그리고 에이전트가 작업을 마쳤음에도 오케스트레이터가 이를 제때 알아차리지 못하고 대기하는 감지 지연 문제가 발생하고 있습니다.

본 이슈는 **lib.sh의 작업 위임 및 MQTT 이벤트 연동(Section 6)**과 run_loop.sh의 계획-실행-검토 오케스트레이션 루프 전체를 파이썬 네이티브 모듈(lib_py)로 재작성 및 모듈화하는 구조적 리팩토링을 제안합니다.


현황 및 문제점 (Current Problems)

  1. 에이전트 작업 완료 미감지 및 지연 (TUI 완료 vs 이벤트 불일치):

    • LLM 에이전트(Claude, Codex, Agy 등)는 터미널에서 코드 작성과 테스트를 마치고 프롬프트 대기(idle) 상태로 복귀했으나, 지침에 포함된 publish_event.py --event completed 명령 실행을 누락하거나 뒤늦게 실행하는 경우가 발생함.
    • 현재 run_loop.sh의 wait_for_job()은 오직 .json 파일의 status: completed만 바라보며 3초 단위 둔탁한 폴링을 수행하므로, 에이전트 창은 이미 놀고 있는데도 루프 제어기가 이를 감지하지 못하고 장시간 멈춰 있는 결함이 존재함.
    • Herdr의 실제 에이전트 런타임 상태(status: idle / done / interactive_ready)를 교차 검증하는 메커니즘이 부재함.
  2. 성능 오버헤드 (Performance Overhead):

    • run_loop.sh에서 작업 상태 확인(wait_for_job), JSON 파싱, 태그 추출(has_verdict, has_tag_line) 시마다 python3 -c, find, cat, grep, sed 등의 외부 서브프로세스를 매 루프마다 수백~수천 번 fork-exec하여 시스템 부하 및 지연이 누적됨.
    • MQTT 이벤트 발행 시마다 python3 publish_event.py를 독립 프로세스로 매번 띄워 소켓 연결/해제 비용(회당 1~2초)이 발생함.
  3. 안전성 및 런타임 한계 (Safety & Reliability):

    • B-13 Self-modifying code crash: Bash는 실행 중인 .sh 파일을 바이트 오프셋 단위로 읽기 때문에, 에이전트가 코딩 작업 도중 .agents/skills/를 수정하면 스크립트가 unexpected EOF 등으로 급사함. 이를 막기 위해 /tmp/mam-loop-freeze.XXXXXX로 스킬 전체를 복제하여 재실행하는 복잡한 임시 우회책(Freeze)을 사용 중.
    • 셸의 따옴표, 멀티라인 프롬프트, 특수문자 이스케이프 취약점 및 set -euo pipefail 환경에서의 예기치 않은 종료 위험.
  4. 유지보수성 및 확장성 한계 (Maintainability & Extensibility):

    • 1,000~2,300 라인 규모의 단일 파일로 인해 새로운 에이전트 어댑터 연동, 정교한 재정/중재 프로토콜 확장 시 결함 발생 위험이 높음.
    • 셸 기반 테스트 모킹의 한계로 인해 정밀한 단위 테스트(Unit testing) 구축이 어려움.

개선 방안 (Proposed Solution)

기존 lib_py 아키텍처를 확장하여 오케스트레이션 엔진을 파이썬 객체지향/모듈형 패키지로 승격합니다.

  1. 이중 감지 엔진 및 자동 완료 폴백 (Dual-Channel Detection & Auto-Recovery):

    • 채널 1 (이벤트 수신): MQTT 토픽 및 작업 레코드 상태 갱신 실시간 수신
    • 채널 2 (런타임 교차 감시): Herdr 소켓 API를 통해 에이전트의 실제 런타임 상태(status: idle / done / interactive_ready)를 실시간 조회
    • 자동 완료 폴백: 에이전트가 결과 보고서(report-final.md)를 작성하고 터미널이 유휴(idle) 상태로 진입했음에도 publish_event.py 실행을 누락한 경우, 오케스트레이터가 이를 능동적으로 교차 감지하여 자동 완료(Auto-Complete) 처리 후 지체 없이 다음 단계로 전환
  2. lib_py/delegation/ (작업 위임 및 고속 이벤트 연동):

    • lib.sh Section 6의 delegate_submit_job, delegate_publish_event, start_watchdog를 파이썬 클래스로 승격
    • 인메모리 MQTT 클라이언트 및 연결 풀 지원으로 이벤트 발행 레이턴시를 ms 단위로 단축
  3. lib_py/loop/ (오케스트레이터 상태 머신):

    • engine.py: 전체 플래닝-실행-검토 상태 머신, asyncio 기반 10ms 단위 비동기 이벤트 대기 및 수렴 제어
    • watcher.py: Herdr 에이전트 TUI 유휴 상태 및 리포트 파일 생성 교차 감시
    • planner.py: Planner 챌린지 및 대화식 토론(--plan-talk) 제어
    • reviewer.py: 리뷰어 병렬 디스패치 및 정규식 기반 판정 파서 (Fail-closed 엄밀성)
    • rebuttal.py: 이의제기(Rebuttal), 재심(Adjudication), 중재(Arbitration) 프로토콜
    • promotion.py: 리포트 승격 및 아카이빙 처리
  4. 하위 호환성 유지 (Thin Wrapper):

    • 기존 CLI 사용자 및 타 스킬 연동 호환성을 위해 run_loop.sh는 인자를 그대로 전달하는 10~20줄 내외의 얇은 래퍼(Thin wrapper)로 축소 유지:
      exec python3 -m lib_py.loop "$@"
      

기대 효과 (Expected Benefits)

  • 감지 즉시성 & 무결성: 에이전트의 이벤트 발행 누락 시에도 TUI Idle 상태 교차 감지로 멈춤 없는 즉시 진행
  • 성능: 프로세스 포크 오버헤드 제거, 3초 폴링 ➔ 10ms 비동기 반응으로 루프 실행 시간 대폭 단축
  • 안전성: 파이썬 인터프리터의 인메모리 모듈 로드로 B-13 프리즈 우회책 완전 제거, 타입 힌팅과 정형화된 예외 처리
  • 확장성 & 테스트 용이성: pytest를 통한 모듈별 100% 단위 테스트 가능, 신규 프로토콜 및 에이전트 확장 용이

마이그레이션 단계 (Phased Plan)

  • Phase 1: lib_py/delegation 모듈화 및 lib.sh Section 6 파이썬 연동 간소화
  • Phase 2: lib_py/loop 오케스트레이터 코어 엔진 및 Herdr TUI Idle 교차 감시자(watcher.py) 구현
  • Phase 3: run_loop.sh Thin Wrapper 전환 및 기존 462개 통합 테스트 스위트 회귀 검증
  • Phase 4: B-13 프리즈 로직 등 불필요해진 셸 우회책 정리 및 문서화
### 개요 (Overview) 현재 `lib.sh` (2,313 라인) 및 `run_loop.sh` (937 라인) 등 핵심 오케스트레이션 로직이 대규모 셸 스크립트로 작성되어 있어, 셸 스크립팅의 한계로 인한 유지보수성 저하, 프로세스 포크 오버헤드, 런타임 자기수정 충돌(B-13 이슈), 그리고 **에이전트가 작업을 마쳤음에도 오케스트레이터가 이를 제때 알아차리지 못하고 대기하는 감지 지연 문제**가 발생하고 있습니다. 본 이슈는 **`lib.sh`의 작업 위임 및 MQTT 이벤트 연동(Section 6)**과 **`run_loop.sh`의 계획-실행-검토 오케스트레이션 루프 전체**를 파이썬 네이티브 모듈(`lib_py`)로 재작성 및 모듈화하는 구조적 리팩토링을 제안합니다. --- ### 현황 및 문제점 (Current Problems) 1. **에이전트 작업 완료 미감지 및 지연 (TUI 완료 vs 이벤트 불일치)**: - LLM 에이전트(Claude, Codex, Agy 등)는 터미널에서 코드 작성과 테스트를 마치고 프롬프트 대기(`idle`) 상태로 복귀했으나, 지침에 포함된 `publish_event.py --event completed` 명령 실행을 누락하거나 뒤늦게 실행하는 경우가 발생함. - 현재 `run_loop.sh`의 `wait_for_job()`은 오직 `.json` 파일의 `status: completed`만 바라보며 3초 단위 둔탁한 폴링을 수행하므로, 에이전트 창은 이미 놀고 있는데도 루프 제어기가 이를 감지하지 못하고 장시간 멈춰 있는 결함이 존재함. - Herdr의 실제 에이전트 런타임 상태(`status: idle / done / interactive_ready`)를 교차 검증하는 메커니즘이 부재함. 2. **성능 오버헤드 (Performance Overhead)**: - `run_loop.sh`에서 작업 상태 확인(`wait_for_job`), JSON 파싱, 태그 추출(`has_verdict`, `has_tag_line`) 시마다 `python3 -c`, `find`, `cat`, `grep`, `sed` 등의 외부 서브프로세스를 매 루프마다 수백~수천 번 fork-exec하여 시스템 부하 및 지연이 누적됨. - MQTT 이벤트 발행 시마다 `python3 publish_event.py`를 독립 프로세스로 매번 띄워 소켓 연결/해제 비용(회당 1~2초)이 발생함. 3. **안전성 및 런타임 한계 (Safety & Reliability)**: - **B-13 Self-modifying code crash**: Bash는 실행 중인 `.sh` 파일을 바이트 오프셋 단위로 읽기 때문에, 에이전트가 코딩 작업 도중 `.agents/skills/`를 수정하면 스크립트가 `unexpected EOF` 등으로 급사함. 이를 막기 위해 `/tmp/mam-loop-freeze.XXXXXX`로 스킬 전체를 복제하여 재실행하는 복잡한 임시 우회책(Freeze)을 사용 중. - 셸의 따옴표, 멀티라인 프롬프트, 특수문자 이스케이프 취약점 및 `set -euo pipefail` 환경에서의 예기치 않은 종료 위험. 4. **유지보수성 및 확장성 한계 (Maintainability & Extensibility)**: - 1,000~2,300 라인 규모의 단일 파일로 인해 새로운 에이전트 어댑터 연동, 정교한 재정/중재 프로토콜 확장 시 결함 발생 위험이 높음. - 셸 기반 테스트 모킹의 한계로 인해 정밀한 단위 테스트(Unit testing) 구축이 어려움. --- ### 개선 방안 (Proposed Solution) 기존 `lib_py` 아키텍처를 확장하여 오케스트레이션 엔진을 파이썬 객체지향/모듈형 패키지로 승격합니다. 1. **이중 감지 엔진 및 자동 완료 폴백 (Dual-Channel Detection & Auto-Recovery)**: - **채널 1 (이벤트 수신)**: MQTT 토픽 및 작업 레코드 상태 갱신 실시간 수신 - **채널 2 (런타임 교차 감시)**: Herdr 소켓 API를 통해 에이전트의 실제 런타임 상태(`status: idle / done / interactive_ready`)를 실시간 조회 - **자동 완료 폴백**: 에이전트가 결과 보고서(`report-final.md`)를 작성하고 터미널이 유휴(`idle`) 상태로 진입했음에도 `publish_event.py` 실행을 누락한 경우, 오케스트레이터가 이를 능동적으로 교차 감지하여 자동 완료(Auto-Complete) 처리 후 지체 없이 다음 단계로 전환 2. **`lib_py/delegation/` (작업 위임 및 고속 이벤트 연동)**: - `lib.sh` Section 6의 `delegate_submit_job`, `delegate_publish_event`, `start_watchdog`를 파이썬 클래스로 승격 - 인메모리 MQTT 클라이언트 및 연결 풀 지원으로 이벤트 발행 레이턴시를 ms 단위로 단축 3. **`lib_py/loop/` (오케스트레이터 상태 머신)**: - `engine.py`: 전체 플래닝-실행-검토 상태 머신, `asyncio` 기반 10ms 단위 비동기 이벤트 대기 및 수렴 제어 - `watcher.py`: Herdr 에이전트 TUI 유휴 상태 및 리포트 파일 생성 교차 감시 - `planner.py`: Planner 챌린지 및 대화식 토론(`--plan-talk`) 제어 - `reviewer.py`: 리뷰어 병렬 디스패치 및 정규식 기반 판정 파서 (Fail-closed 엄밀성) - `rebuttal.py`: 이의제기(Rebuttal), 재심(Adjudication), 중재(Arbitration) 프로토콜 - `promotion.py`: 리포트 승격 및 아카이빙 처리 4. **하위 호환성 유지 (Thin Wrapper)**: - 기존 CLI 사용자 및 타 스킬 연동 호환성을 위해 `run_loop.sh`는 인자를 그대로 전달하는 10~20줄 내외의 얇은 래퍼(Thin wrapper)로 축소 유지: ```bash exec python3 -m lib_py.loop "$@" ``` --- ### 기대 효과 (Expected Benefits) - **감지 즉시성 & 무결성**: 에이전트의 이벤트 발행 누락 시에도 TUI Idle 상태 교차 감지로 멈춤 없는 즉시 진행 - **성능**: 프로세스 포크 오버헤드 제거, 3초 폴링 ➔ 10ms 비동기 반응으로 루프 실행 시간 대폭 단축 - **안전성**: 파이썬 인터프리터의 인메모리 모듈 로드로 B-13 프리즈 우회책 완전 제거, 타입 힌팅과 정형화된 예외 처리 - **확장성 & 테스트 용이성**: `pytest`를 통한 모듈별 100% 단위 테스트 가능, 신규 프로토콜 및 에이전트 확장 용이 --- ### 마이그레이션 단계 (Phased Plan) - [ ] Phase 1: `lib_py/delegation` 모듈화 및 `lib.sh` Section 6 파이썬 연동 간소화 - [ ] Phase 2: `lib_py/loop` 오케스트레이터 코어 엔진 및 Herdr TUI Idle 교차 감시자(`watcher.py`) 구현 - [ ] Phase 3: `run_loop.sh` Thin Wrapper 전환 및 기존 462개 통합 테스트 스위트 회귀 검증 - [ ] Phase 4: B-13 프리즈 로직 등 불필요해진 셸 우회책 정리 및 문서화
Author
Owner

[planner-reviewer-claude-01] Issue #5 기술 검토 의견

  • Reviewer: planner-reviewer-claude-01
  • 대상: Gitea Issue #5 ([Refactor] lib.sh 작업 위임 로직 및 run_loop.sh 오케스트레이터의 Python 모듈화)
  • 방법: 이슈 본문의 모든 기술적 주장을 실제 코드/CLI 동작으로 직접 검증한 뒤 판단. tea issue 5로 원문 확인, .agents/skills/lib.sh (2,312줄), .agents/skills/multi-agent-mux-loop/scripts/run_loop.sh (936줄), .agents/skills/lib_py/ 전체(12개 파일, 총 1,086줄)를 직접 읽고, herdr agent wait --help / herdr api snapshot / herdr api schema --json을 라이브로 실행하여 이슈가 전제하는 "Herdr 소켓 API" 주장을 검증함.

1. 총평

이슈가 진단한 현황 문제는 모두 코드로 직접 확인되는 실재하는 결함이다. 특히 다음 두 가지는 정확히 이슈 본문 그대로 재현됨:

  • run_loop.sh:238 wait_for_job()은 정확히 .mam/jobs/$job_id.json의 status 필드만 3초 간격으로 폴링하며(check_interval=3), Herdr 런타임 상태와의 교차 검증이 전혀 없음 — 이슈의 "감지 지연" 주장과 100% 일치.
  • resolve_all_reviewers, resolve_agent_type, resolve_planner_session, wait_for_job 등 다수 함수가 매 호출마다 독립적인 python3 -c "..." 서브프로세스를 fork함 — 이슈의 "수백~수천 회 fork-exec" 주장이 과장이 아님을 확인.
  • run_loop.sh:107-142에 실제로 mktemp -d "${TMPDIR:-/tmp}/mam-loop-freeze.XXXXXX" 기반 B-13 자기수정 크래시 우회책이 존재함 — 이슈가 정확히 지목한 그 코드.

방향성 자체(파이썬 네이티브 모듈화)는 지지한다. 다만 조사 중 이슈 설계의 전제를 강화하면서도 동시에 범위를 재조정해야 하는 중요한 사실을 하나 발견했다 — 아래 §2-1 참조.

2. 주요 설계 검토

2-1. 이중 감지 엔진 (Dual-Channel Detection) — 핵심 발견: 채널 2는 이미 1급 기능으로 존재함

실제로 herdr 바이너리를 라이브로 조회한 결과, 이슈가 새로 구현하자고 제안하는 "Herdr 소켓 API 기반 idle/done/interactive_ready 교차 감시"는 이미 herdr CLI의 1급 기능으로 존재한다:

$ herdr agent wait --help
Wait until an agent reaches one of the requested states
Usage: herdr agent wait <TARGET> [OPTIONS]
  --until <STATUS>   [possible values: idle, working, blocked, done, unknown]
  --timeout <MS>     Fail after this many milliseconds
Without --until, matches idle, done, or blocked.

그리고 herdr api snapshot은 세션별로 agent_status (working/idle)와 interactive_ready (bool) 필드를 실시간 JSON으로 즉시 반환한다. 더 나아가 herdr api schema --json을 조회하면 subscription_event라는 정식 스키마가 정의되어 있어, 소켓 API가 폴링이 아닌 push 구독 모델도 지원함을 확인했다 (herdr agent/workspace/tab/notification/pane 서브커맨드 도움말에 "over the socket API"라고 명시).

시사점:

  • 이슈의 "채널 2" 전제는 완전히 타당하며, 구현 난이도는 이슈가 암시하는 것보다 훨씬 낮다 — 소켓 프로토콜을 처음부터 설계/구현할 필요 없이, 검증된 기존 herdr 기능을 얇게 감싸면 됨.
  • 권장: watcher.py의 1차 구현은 raw socket 클라이언트를 직접 만들기보다 herdr agent wait <target> --until idle,done,blocked --timeout <ms> subprocess 호출(비동기 wrapping)로 MVP를 완성하고, 진짜 10ms급 반응성이 필요해지는 시점에만 subscription_event 기반 raw socket 구독으로 승격하는 2단계 접근을 권장한다. 이렇게 하면 Phase 2 리스크가 크게 줄어든다.
  • 현재 lib.sh의 _pane_capture()/wait_for_tui_ready() (텍스트 스크레이핑 기반)와 신규 watcher.py(구조화된 agent_status 기반)의 관계가 이슈 본문에 명시되어 있지 않음 — 완전 대체인지 병행 유지인지 설계 문서에 명확화 필요.

오탐지(false-positive) 방지책 미흡: 이슈 본문이 "리포트 작성 중 일시적 유휴 상태 오감지" 위험을 스스로 인지하고 있으나, 구체적 방지 메커니즘이 제시되지 않았다. interactive_ready=true이면서 report-final.md가 아직 부분적으로 쓰여지는 중(파일은 생성됐지만 write가 끝나지 않음)인 race condition이 실재할 수 있다. 최소한 다음 두 가지를 설계에 명시할 것을 권장한다:

  1. 단발성 idle 감지가 아닌 연속 N회/최소 지속시간 디바운스(예: 2초 간격으로 3회 연속 idle 확인).
  2. report-final.md의 mtime이 일정 시간(예: 1~2초) 이상 변화가 없을 때만 "파일 쓰기 완료"로 간주하는 안정화 체크.

2-2. 모듈화 아키텍처 (lib_py/delegation/, lib_py/loop/)

기존 lib_py/는 이미 어댑터 패턴(agents/base.py + agents/registry.py)으로 잘 조직되어 있고 (12개 파일, 총 1,086줄), lib.sh Section 6 (delegate_submit_job/delegate_publish_event/start_watchdog, lib.sh:1876-1938)을 lib_py/delegation/으로 승격하는 것은 이 기존 패턴의 자연스러운 연장이라 리스크가 낮다고 판단한다.

다만 run_loop.sh의 6분할(engine/watcher/planner/reviewer/rebuttal/promotion)은 이슈가 암시하는 것보다 실제 난이도가 높을 수 있다는 근거를 확인했다:

  • run_loop.sh 936줄 중 명명된 함수는 16개뿐이며(usage, has_verdict, has_tag_line, wait_for_job, resolve_* 등), 나머지 대부분은 함수화되지 않은 절차적 인라인 상태 머신 흐름이다. 즉 "함수 단위로 옮기면 된다"가 아니라 먼저 상태 머신 자체를 설계해야 하는 그린필드에 가까운 작업이다.
  • 이 파일의 동작을 직접 검증하는 전용 테스트가 최소 5개 파일에 걸쳐 존재한다: test_loop_cli.py(152줄), test_o1_rebuttal.py(176줄), test_o2_race_free_lock.py(365줄), test_o3_scoped_guard.py(471줄), test_tier4_e2e.py(457줄) — 합계 약 1,621줄이 subprocess로 run_loop.sh를 직접 실행/검증한다. 즉 Phase 3의 "462개 테스트 회귀 검증"은 단순 재실행이 아니라, 이 ~1,600줄의 shell-subprocess 테스트 자체를 파이썬 API 대상으로 재작성/재타겟팅해야 함을 의미한다. Phase 3 공수 산정 시 이 부분이 누락되지 않도록 재확인을 권장한다.

2-3. 성능·안전성

  • 서브프로세스 다회 fork 문제, MQTT 이벤트 발행 시 매번 신규 프로세스 기동 문제(delegate_publish_event, lib.sh:1897) 모두 실측으로 확인했고, 인메모리 커넥션 풀/asyncio 전환의 기대 효과는 타당하다.
  • B-13 완전 제거 주장은 조건부로만 성립한다: 파이썬 모듈이 import 시점에 메모리 적재되어 실행 중 파일 수정에 영향받지 않는다는 원리는 맞지만, engine.py/watcher.py가 과도기에 여전히 lib.sh의 셸 헬퍼를 subprocess로 호출하는 하이브리드 상태로 남아있는 한 그 호출 시점에는 동일 클래스의 크래시 위험이 재도입될 수 있다. "B-13 프리즈 우회책 완전 제거"는 Phase 4에서 셸 의존성이 실제로 모두 제거된 이후에만 성립하는 조건부 효과이므로, 기대 효과 문서에 이 점을 명시할 것을 권장한다.

2-4. 하위 호환성 (Thin Wrapper)

exec python3 -m lib_py.loop "$@" 방식 자체는 무해하고 합리적이다. 다만 위 2-2의 테스트 커플링 문제와 결합되므로, "하위 호환성 유지"의 실제 검증 기준은 "CLI 인자/종료 코드/stdout 포맷이 기존과 동일한가"뿐 아니라 "위 5개 테스트 파일이 (재작성 후) 동일한 시나리오를 여전히 커버하는가"까지 포함해야 한다.

3. 우려 사항 및 보완 권장사항

  1. 자동완료 오탐 방지 구체화: §2-1의 디바운스 + 파일 mtime 안정화 체크를 Phase 2 설계에 명시적으로 포함할 것.
  2. 채널 2 구현 전략 수정: raw 소켓 클라이언트 자체 구현보다 기존 herdr agent wait/api snapshot CLI를 얇게 감싼 MVP로 시작 → 검증된 이후 subscription_event 기반 저지연 구독으로 승격하는 단계적 접근 권장.
  3. Phase 3 공수 재산정: run_loop.sh를 직접 구동하는 ~1,600줄 규모의 5개 shell-subprocess 테스트 파일의 재작성 범위를 Phase 3 계획에 명시적으로 반영할 것.
  4. Phase 순서 조정 제안: Phase 1(delegation)과 Phase 2(loop engine)는 서로 독립적으로 배포 가능한 단위이므로, Phase 1을 좁은 범위로 먼저 완료·검증(회귀 테스트 그린 확인)한 뒤 Phase 2에 착수하는 순차적 승인을 권장 — 한 번에 두 영역을 동시에 흔드는 것보다 리스크 격리 효과가 크다.
  5. 기존 pane-capture 로직과의 관계 명확화: _pane_capture()/wait_for_tui_ready()(텍스트 스크레이핑)를 신규 watcher.py(구조화된 API 기반)가 완전 대체하는지, 아니면 특정 에이전트(pane 캡처가 필요한 헤드리스 케이스 등)에 대해 병행 유지하는지를 설계 문서에 명시할 것.
  6. B-13 제거 표현 수정: "기대 효과"의 B-13 완전 제거 항목에 "Phase 4에서 셸 의존성이 완전히 제거된 이후에만 성립"이라는 조건을 명시할 것.

4. 결론

이슈가 지목한 문제들은 코드로 직접 재현·확인되는 실재하는 결함이며, 파이썬 네이티브 모듈화라는 방향성은 타당하다. 조사 과정에서 이슈의 핵심 전제(Herdr 소켓 API를 통한 실시간 상태 교차 감시)가 이미 herdr의 1급 기능(agent wait, api snapshot, subscription_event)으로 존재함을 확인했는데, 이는 이슈의 타당성을 강화하는 동시에 Phase 2의 구현 리스크를 낮출 수 있는 실질적 기회이기도 하다. 위 §3의 6개 보완사항, 특히 Phase 3 테스트 마이그레이션 범위 재산정과 Phase 1/2 분리 승인을 반영한다면 안전하게 진행 가능한 리팩토링으로 판단한다.

### [planner-reviewer-claude-01] Issue #5 기술 검토 의견 - **Reviewer**: `planner-reviewer-claude-01` - **대상**: Gitea Issue #5 (`[Refactor] lib.sh 작업 위임 로직 및 run_loop.sh 오케스트레이터의 Python 모듈화`) - **방법**: 이슈 본문의 모든 기술적 주장을 실제 코드/CLI 동작으로 직접 검증한 뒤 판단. `tea issue 5`로 원문 확인, `.agents/skills/lib.sh` (2,312줄), `.agents/skills/multi-agent-mux-loop/scripts/run_loop.sh` (936줄), `.agents/skills/lib_py/` 전체(12개 파일, 총 1,086줄)를 직접 읽고, `herdr agent wait --help` / `herdr api snapshot` / `herdr api schema --json`을 라이브로 실행하여 이슈가 전제하는 "Herdr 소켓 API" 주장을 검증함. --- ## 1. 총평 이슈가 진단한 현황 문제는 **모두 코드로 직접 확인되는 실재하는 결함**이다. 특히 다음 두 가지는 정확히 이슈 본문 그대로 재현됨: - `run_loop.sh:238` `wait_for_job()`은 정확히 `.mam/jobs/$job_id.json`의 `status` 필드만 3초 간격으로 폴링하며(`check_interval=3`), Herdr 런타임 상태와의 교차 검증이 전혀 없음 — 이슈의 "감지 지연" 주장과 100% 일치. - `resolve_all_reviewers`, `resolve_agent_type`, `resolve_planner_session`, `wait_for_job` 등 다수 함수가 매 호출마다 독립적인 `python3 -c "..."` 서브프로세스를 fork함 — 이슈의 "수백~수천 회 fork-exec" 주장이 과장이 아님을 확인. - `run_loop.sh:107-142`에 실제로 `mktemp -d "${TMPDIR:-/tmp}/mam-loop-freeze.XXXXXX"` 기반 B-13 자기수정 크래시 우회책이 존재함 — 이슈가 정확히 지목한 그 코드. 방향성 자체(파이썬 네이티브 모듈화)는 **지지**한다. 다만 조사 중 이슈 설계의 전제를 강화하면서도 동시에 범위를 재조정해야 하는 중요한 사실을 하나 발견했다 — 아래 §2-1 참조. ## 2. 주요 설계 검토 ### 2-1. 이중 감지 엔진 (Dual-Channel Detection) — **핵심 발견: 채널 2는 이미 1급 기능으로 존재함** 실제로 `herdr` 바이너리를 라이브로 조회한 결과, 이슈가 새로 구현하자고 제안하는 "Herdr 소켓 API 기반 idle/done/interactive_ready 교차 감시"는 **이미 herdr CLI의 1급 기능으로 존재**한다: ``` $ herdr agent wait --help Wait until an agent reaches one of the requested states Usage: herdr agent wait <TARGET> [OPTIONS] --until <STATUS> [possible values: idle, working, blocked, done, unknown] --timeout <MS> Fail after this many milliseconds Without --until, matches idle, done, or blocked. ``` 그리고 `herdr api snapshot`은 세션별로 `agent_status` (`working`/`idle`)와 `interactive_ready` (bool) 필드를 실시간 JSON으로 즉시 반환한다. 더 나아가 `herdr api schema --json`을 조회하면 `subscription_event`라는 정식 스키마가 정의되어 있어, 소켓 API가 폴링이 아닌 **push 구독 모델**도 지원함을 확인했다 (`herdr agent`/`workspace`/`tab`/`notification`/`pane` 서브커맨드 도움말에 "over the socket API"라고 명시). **시사점**: - 이슈의 "채널 2" 전제는 완전히 타당하며, 구현 난이도는 이슈가 암시하는 것보다 **훨씬 낮다** — 소켓 프로토콜을 처음부터 설계/구현할 필요 없이, 검증된 기존 herdr 기능을 얇게 감싸면 됨. - **권장**: `watcher.py`의 1차 구현은 raw socket 클라이언트를 직접 만들기보다 `herdr agent wait <target> --until idle,done,blocked --timeout <ms>` subprocess 호출(비동기 wrapping)로 MVP를 완성하고, 진짜 10ms급 반응성이 필요해지는 시점에만 `subscription_event` 기반 raw socket 구독으로 승격하는 2단계 접근을 권장한다. 이렇게 하면 Phase 2 리스크가 크게 줄어든다. - 현재 `lib.sh`의 `_pane_capture()`/`wait_for_tui_ready()` (텍스트 스크레이핑 기반)와 신규 `watcher.py`(구조화된 `agent_status` 기반)의 관계가 이슈 본문에 명시되어 있지 않음 — 완전 대체인지 병행 유지인지 설계 문서에 명확화 필요. **오탐지(false-positive) 방지책 미흡**: 이슈 본문이 "리포트 작성 중 일시적 유휴 상태 오감지" 위험을 스스로 인지하고 있으나, 구체적 방지 메커니즘이 제시되지 않았다. `interactive_ready=true`이면서 `report-final.md`가 아직 부분적으로 쓰여지는 중(파일은 생성됐지만 write가 끝나지 않음)인 race condition이 실재할 수 있다. 최소한 다음 두 가지를 설계에 명시할 것을 권장한다: 1. 단발성 idle 감지가 아닌 **연속 N회/최소 지속시간 디바운스**(예: 2초 간격으로 3회 연속 idle 확인). 2. `report-final.md`의 mtime이 일정 시간(예: 1~2초) 이상 변화가 없을 때만 "파일 쓰기 완료"로 간주하는 안정화 체크. ### 2-2. 모듈화 아키텍처 (`lib_py/delegation/`, `lib_py/loop/`) 기존 `lib_py/`는 이미 어댑터 패턴(`agents/base.py` + `agents/registry.py`)으로 잘 조직되어 있고 (12개 파일, 총 1,086줄), `lib.sh` Section 6 (`delegate_submit_job`/`delegate_publish_event`/`start_watchdog`, `lib.sh:1876-1938`)을 `lib_py/delegation/`으로 승격하는 것은 이 기존 패턴의 자연스러운 연장이라 리스크가 낮다고 판단한다. 다만 `run_loop.sh`의 6분할(`engine`/`watcher`/`planner`/`reviewer`/`rebuttal`/`promotion`)은 이슈가 암시하는 것보다 실제 난이도가 높을 수 있다는 근거를 확인했다: - `run_loop.sh` 936줄 중 **명명된 함수는 16개뿐**이며(`usage`, `has_verdict`, `has_tag_line`, `wait_for_job`, `resolve_*` 등), 나머지 대부분은 함수화되지 않은 절차적 인라인 상태 머신 흐름이다. 즉 "함수 단위로 옮기면 된다"가 아니라 **먼저 상태 머신 자체를 설계해야** 하는 그린필드에 가까운 작업이다. - 이 파일의 동작을 직접 검증하는 전용 테스트가 최소 5개 파일에 걸쳐 존재한다: `test_loop_cli.py`(152줄), `test_o1_rebuttal.py`(176줄), `test_o2_race_free_lock.py`(365줄), `test_o3_scoped_guard.py`(471줄), `test_tier4_e2e.py`(457줄) — 합계 약 1,621줄이 subprocess로 `run_loop.sh`를 직접 실행/검증한다. 즉 Phase 3의 "462개 테스트 회귀 검증"은 단순 재실행이 아니라, **이 ~1,600줄의 shell-subprocess 테스트 자체를 파이썬 API 대상으로 재작성/재타겟팅**해야 함을 의미한다. Phase 3 공수 산정 시 이 부분이 누락되지 않도록 재확인을 권장한다. ### 2-3. 성능·안전성 - 서브프로세스 다회 fork 문제, MQTT 이벤트 발행 시 매번 신규 프로세스 기동 문제(`delegate_publish_event`, `lib.sh:1897`) 모두 실측으로 확인했고, 인메모리 커넥션 풀/asyncio 전환의 기대 효과는 타당하다. - B-13 완전 제거 주장은 **조건부로만 성립**한다: 파이썬 모듈이 import 시점에 메모리 적재되어 실행 중 파일 수정에 영향받지 않는다는 원리는 맞지만, `engine.py`/`watcher.py`가 과도기에 여전히 `lib.sh`의 셸 헬퍼를 subprocess로 호출하는 하이브리드 상태로 남아있는 한 그 호출 시점에는 동일 클래스의 크래시 위험이 재도입될 수 있다. "B-13 프리즈 우회책 완전 제거"는 Phase 4에서 셸 의존성이 실제로 모두 제거된 이후에만 성립하는 조건부 효과이므로, 기대 효과 문서에 이 점을 명시할 것을 권장한다. ### 2-4. 하위 호환성 (Thin Wrapper) `exec python3 -m lib_py.loop "$@"` 방식 자체는 무해하고 합리적이다. 다만 위 2-2의 테스트 커플링 문제와 결합되므로, "하위 호환성 유지"의 실제 검증 기준은 "CLI 인자/종료 코드/stdout 포맷이 기존과 동일한가"뿐 아니라 "위 5개 테스트 파일이 (재작성 후) 동일한 시나리오를 여전히 커버하는가"까지 포함해야 한다. ## 3. 우려 사항 및 보완 권장사항 1. **자동완료 오탐 방지 구체화**: §2-1의 디바운스 + 파일 mtime 안정화 체크를 Phase 2 설계에 명시적으로 포함할 것. 2. **채널 2 구현 전략 수정**: raw 소켓 클라이언트 자체 구현보다 기존 `herdr agent wait`/`api snapshot` CLI를 얇게 감싼 MVP로 시작 → 검증된 이후 `subscription_event` 기반 저지연 구독으로 승격하는 단계적 접근 권장. 3. **Phase 3 공수 재산정**: `run_loop.sh`를 직접 구동하는 ~1,600줄 규모의 5개 shell-subprocess 테스트 파일의 재작성 범위를 Phase 3 계획에 명시적으로 반영할 것. 4. **Phase 순서 조정 제안**: Phase 1(delegation)과 Phase 2(loop engine)는 서로 독립적으로 배포 가능한 단위이므로, Phase 1을 좁은 범위로 먼저 완료·검증(회귀 테스트 그린 확인)한 뒤 Phase 2에 착수하는 순차적 승인을 권장 — 한 번에 두 영역을 동시에 흔드는 것보다 리스크 격리 효과가 크다. 5. **기존 pane-capture 로직과의 관계 명확화**: `_pane_capture()`/`wait_for_tui_ready()`(텍스트 스크레이핑)를 신규 `watcher.py`(구조화된 API 기반)가 완전 대체하는지, 아니면 특정 에이전트(pane 캡처가 필요한 헤드리스 케이스 등)에 대해 병행 유지하는지를 설계 문서에 명시할 것. 6. **B-13 제거 표현 수정**: "기대 효과"의 B-13 완전 제거 항목에 "Phase 4에서 셸 의존성이 완전히 제거된 이후에만 성립"이라는 조건을 명시할 것. --- ## 4. 결론 이슈가 지목한 문제들은 코드로 직접 재현·확인되는 실재하는 결함이며, 파이썬 네이티브 모듈화라는 방향성은 타당하다. 조사 과정에서 이슈의 핵심 전제(Herdr 소켓 API를 통한 실시간 상태 교차 감시)가 이미 herdr의 1급 기능(`agent wait`, `api snapshot`, `subscription_event`)으로 존재함을 확인했는데, 이는 이슈의 타당성을 강화하는 동시에 Phase 2의 구현 리스크를 낮출 수 있는 실질적 기회이기도 하다. 위 §3의 6개 보완사항, 특히 Phase 3 테스트 마이그레이션 범위 재산정과 Phase 1/2 분리 승인을 반영한다면 안전하게 진행 가능한 리팩토링으로 판단한다.
Author
Owner

[planner-reviewer-codex-01] Issue #5 기술 검토 의견

1. 총평

Python 모듈화 방향에는 찬성합니다. 다만 자동 완료를 기본 활성화하고 Freeze를 즉시 제거하는 설계는 아래 조건을 먼저 충족해야 합니다. idle은 작업 성공의 증명이 아니며, Python 전환 자체가 실행 중 코드 버전의 일관성을 보장하지도 않습니다. 모듈 추출과 완료 판정 정책 변경을 별도 단계로 검증하는 것이 적절합니다.

검토 기준은 refactor 브랜치 47640e2의 실제 코드와 이슈 본문입니다. lib_py/delegation/, lib_py/loop/는 아직 구현된 패키지가 아니라 제안입니다. 구현 승인이나 성능 측정 결과가 아닌 설계 리뷰입니다.

2. 현재 코드에서 확인한 사실

  • run_loop.sh:238–275의 wait_for_job()은 실제로 3초마다 별도 Python 프로세스로 job JSON을 읽습니다. 다만 시스템 전체가 MQTT만 의존하는 것은 아닙니다. job_subscriber.py:63부터 디스크/감사 로그 폴백이 이미 있고, publish_event.py:198–231은 MQTT 발행 실패도 기록한 뒤 로컬 상태 동기화를 시도합니다. 기존 복구 경로를 보존하고 통합해야 합니다.
  • lib.sh:1876–1938의 위임 함수는 상당 부분 이미 Python registry/publisher의 셸 진입점입니다. 새로운 독립 registry를 만들기보다 기존 구현을 import 가능한 서비스로 추출해야 합니다. delegate_publish_event의 non-fatal 계약과 start_watchdog의 PID 반환/프로세스 수명 계약도 호환 대상입니다.
  • mqtt_common.update_job_status()는 lock 안에서 필드를 병합하지만, 그 자체에 expected-state/attempt 검사나 terminal-state 불변 조건은 없습니다. watcher가 여기에 completed를 추가로 쓰는 것만으로는 이중 writer 경합을 해결하지 못합니다.
  • 리뷰 완료와 리뷰 PASS는 분리되어 있습니다. 현재 loop는 terminal 이벤트 후 보고서 마지막 비공백 줄의 판정을 검사하고 누락을 반려합니다. 반론은 PASS를 대신하지 않으며 모든 active reviewer의 PASS가 필요합니다.
  • 현재 테스트는 pytest --collect-only -q tests/ 기준 469개입니다. 이슈의 462개는 이전 수치입니다. 이번 검토에서는 수집만 수행했으며 전체 실행 성공을 주장하지 않습니다.

3. 이중 감지와 자동 완료: 필수 안전 조건

watcher는 증거를 수집하고, engine만 상태 전이를 결정해야 합니다. MQTT/파일 상태는 같은 실행의 복제 정보일 수 있으므로 독립된 두 표로 간주하지 마십시오. Herdr의 idle/done/interactive_ready도 backend별 의미와 관측 신선도를 확인해야 합니다. 현재 저장된 Herdr contract fixture만으로 해당 상태 enum이나 완료 의미는 입증되지 않습니다. 실제 지원 버전의 API 응답과 6개 adapter별 상태 전이 fixture가 먼저 필요합니다.

자동 완료 후보를 인정하는 최소 조건을 명시할 것을 권고합니다.

  1. 정확한 실행 귀속: job ID + attempt ID + agent/session UUID + pane/process generation을 매칭합니다. dispatch 확인 이후 해당 시도의 실행/응답을 관측해야 하며, 시작 전 idle이나 재사용 pane의 이전 작업은 제외합니다. 같은 session에는 동시에 한 job만 배정합니다.
  2. 리포트 확정 계약: 지정된 정확한 report 경로와 현재 시도를 연결합니다. find | head -1이나 파일 존재만으로 선택하지 않습니다. 임시 파일 → atomic rename 뒤 attempt와 report hash를 포함한 완료 manifest를 확정하는 계약이 좋습니다. mtime/크기 안정화나 몇 초의 유예 시간만으로 작성 완료를 증명할 수 없습니다. 기존 에이전트가 이 계약을 지원하지 않으면 자동 확정 대신 복구 후보로 남깁니다.
  3. 유휴의 부정 조건: permission/input 대기, 도구/테스트/자식 프로세스 실행, 보고서 변경, 세션 교체, 연결 단절 또는 관측 불능이면 완료하지 않습니다. 일정 기간의 반복 관측은 보조 필터이지 완료 증명은 아닙니다. 에이전트가 보고서를 먼저 쓴 뒤 최종 검증을 하는 경우도 반드시 차단해야 합니다.
  4. 단일 terminal 전이: 기존 registry lock을 재사용하여 expected attempt와 비terminal 상태를 다시 확인하고 비교 후 갱신합니다. 명시적 error/cancelled가 이미 있으면 자동 완료로 덮어쓰지 않습니다. 완료 확정 후 들어온 progress/started도 상태를 되돌리지 않도록 agent publisher와 watcher가 같은 전이 함수를 사용해야 합니다. 경합/늦은 상충 이벤트의 판정 정책과 감사 기록을 정하십시오.
  5. 유실 없는 통지: 상태 확정과 재전송 가능한 pending notification을 내구성 있게 저장한 뒤 MQTT를 발행하는 방식을 권고합니다. 기존 HMAC, monotonic seq, QoS 중복 처리, retained terminal 정책을 보존하고 재시도는 같은 논리 이벤트로 식별합니다. 네트워크의 exactly-once를 가정하지 말고 상태 전이의 멱등성을 보장하십시오.

자동 복구 terminal에는 source=watcher, attempt, 관측 시각/근거, report hash를 기록합니다. review job의 completed를 PASS로 해석해서는 안 됩니다. 보고서가 NOT PASS면 정상적으로 완료된 반려 리뷰입니다. 코드 블록 속 예시 토큰, 누락/부분 리포트, 잘못된 마지막 줄은 계속 fail-closed로 처리하십시오. 외부 게시/배포 등 보고서만으로 확인할 수 없는 부수효과가 있는 작업에는 별도 완료 증거가 없으면 자동 복구를 적용하지 않는 편이 맞습니다.

4. 모듈 경계와 비동기 실행

제안된 engine / watcher / planner / reviewer / rebuttal / promotion 분리는 타당합니다. 다만 각 모듈이 registry를 직접 수정하거나 서로 루프를 호출하면 현재 결합도를 옮기기만 합니다.

  • delegation: 기존 job 저장소·전이·이벤트 전송 서비스를 통합하고 기존 CLI를 adapter로 유지합니다. session SQLite/YAML과 job JSON registry는 목적이 다르므로 이번 추출에서 저장소 통합까지 함께 하지 마십시오.
  • engine: 실행 단계, attempt, deadline, iteration/rebuttal budget, reviewer 집합을 소유하는 유일한 상태 전이 주체입니다. 재시작 후 중복 dispatch/재승격 방지를 위해 복구 가능한 checkpoint가 필요합니다.
  • watcher: bounded queue로 관측 이벤트를 전달합니다. 기존 MQTT client callback이 별도 스레드에서 오면 thread-safe한 loop 전달 경계를 둡니다. SQLite/file lock과 동기 I/O는 이벤트 루프를 막지 않도록 분리하고 transaction 도중 await하지 않습니다.
  • planner/reviewer/rebuttal: 명시적 입력·결과를 반환하고 실행 순서는 engine이 제어합니다. reviewer 완료 이벤트는 동시에 수집하되 모두 PASS일 때만 승격합니다. 기존 max-loop/max-rebut, fail-closed adjudication, planner arbitration, 역할/자기 리뷰 금지 조건을 보존합니다.
  • promotion: 확정된 보고서 경로/hash만 받아 동일 파일시스템의 임시 파일 → rename으로 승격합니다. 다중 보고서 전체는 여러 rename만으로 원자적이지 않으므로 최종 manifest 또는 완료 checkpoint가 필요합니다. 승격 검증 전 임시 job 디렉터리를 삭제하지 않습니다.

asyncio는 10ms 폴링을 필수로 하지 않습니다. queue/event를 await하고, 지원되는 Herdr 이벤트 구독을 우선하며, 조회 폴백은 bounded timeout/backoff로 제한하십시오. 고정 10ms 조회는 오히려 job 수에 비례한 소켓 부하를 만듭니다. 장기 실행 프로세스당 MQTT 연결 하나를 재사용하는 것부터 시작하면 되며 연결 풀은 측정 후 판단할 수 있습니다. 외부의 짧은 publisher CLI까지 연결 비용을 제거하려면 상주 서비스/IPC가 추가로 필요하므로 Phase 1의 필수 범위로 숨기지 마십시오.

5. B-13, 성능 및 CLI 호환성

Python은 이미 로드한 함수의 실행 중 셸 byte-offset 문제를 줄이지만 lazy import, 나중에 시작하는 child interpreter, 남은 shell helper, 템플릿/설정 파일의 재읽기는 수정된 작업 트리를 계속 볼 수 있습니다. 따라서 “Python 모듈이므로 Freeze 완전 제거”는 성립하지 않습니다.

Phase 4에서는 작업 트리와 분리된 버전 고정 runtime/install artifact를 사용하거나, 모든 실행 의존성의 불변성을 입증해야 합니다. 지금의 임시 복사 디렉터리는 없앨 수 있어도 실행 버전 고정이라는 요구 자체는 남습니다. 실행 도중 skills를 교체하고 재심/승격처럼 늦게 실행되는 경로까지 검증한 후 제거하십시오.

Thin wrapper는 exec python3 -m ...만으로 충분하지 않습니다. 현재 interpreter 선택(AGENT_PYTHON_BIN, venv), import 경로, 실제 workspace/registry/config 경로, 임의 cwd와 공백 경로, 원래 argv 전달, stdout/stderr 형식·exit code·signal 전달을 유지해야 합니다. loop guard의 pid+lstart와 단일 workspace controller 제한, interruption 시 lock/subscriber 정리도 Python 전환 후 유지되어야 합니다.

성능 효과는 유망하지만 ms 반응이나 전체 실행시간의 대폭 단축은 아직 측정값이 아닙니다. 대표 job 수별 fork 수, idle CPU, MQTT 연결 횟수, report 확정→전이 p50/p95, 장애 복구시간을 기존 엔진과 비교하십시오. LLM/테스트 시간이 지배하는 전체 작업시간과 watcher 반응시간을 구분해야 합니다.

6. Phase 1–4 보완안 및 완료 기준

사전 계약 고정: 현재 CLI/상태/event/report/lock 계약과 backend 상태 fixture, 장애 사례를 먼저 수집합니다. golden 테스트는 코드 문자열이 아니라 관측 가능한 동작을 검증해야 합니다.

Phase 1: 기존 registry/MQTT 구현을 import 가능한 delegation 서비스로 추출합니다. CLI 결과와 오류 의미를 유지하고, 아직 자동 완료 정책은 변경하지 않습니다. lock·seq·HMAC·디스크 폴백 회귀를 통과해야 합니다.

Phase 2: 순수 상태 전이 엔진과 watcher를 도입하되 watcher는 우선 shadow 모드로 복구 후보만 기록합니다. stale report, 작성 중 idle, 승인 대기, agent crash/restart, MQTT disconnect/replay, explicit error와 inferred completion 경합, 반복 시도와 지연 이벤트를 가상 시계/fixture로 재현합니다. 에이전트별 오완료가 없는 증거와 report 확정 계약을 갖춘 작업부터 제한적으로 활성화합니다.

Phase 3: thin wrapper를 전환하고 기존/새 엔진의 관측 결과를 fixture로 비교합니다. 두 엔진을 같은 live workspace의 writer로 동시에 돌리지는 마십시오. 현재 수집되는 전체 suite와 신규 race/restart/parser 테스트, 실제 lifecycle smoke를 실행합니다. 기존 469개를 유지했다는 숫자만으로 새로운 완료 정책이 검증되지는 않습니다.

Phase 4: immutable runtime 및 자기수정 실험, 재시작 복구/rollback, promotion 원자성, interrupt cleanup 검증이 끝난 뒤 임시 Freeze와 불필요한 shell 우회만 제거합니다. 롤백은 새 엔진 writer를 정지시킨 후 수행하며 살아 있는 child job과 terminal 상태를 보존해야 합니다.

최종 의견: 모듈화는 추진하되, 자동 완료의 증거/전이 계약과 runtime 버전 고정 조건을 설계에 먼저 반영하는 조건부 동의입니다. 특히 idle+파일 존재만으로 자동 completed를 쓰는 구현, 10ms를 보장 성능으로 제시하는 표현, Python 전환만으로 Freeze를 제거하는 계획은 수정이 필요합니다.

### [planner-reviewer-codex-01] Issue #5 기술 검토 의견 #### 1. 총평 **Python 모듈화 방향에는 찬성합니다. 다만 자동 완료를 기본 활성화하고 Freeze를 즉시 제거하는 설계는 아래 조건을 먼저 충족해야 합니다.** `idle`은 작업 성공의 증명이 아니며, Python 전환 자체가 실행 중 코드 버전의 일관성을 보장하지도 않습니다. 모듈 추출과 완료 판정 정책 변경을 별도 단계로 검증하는 것이 적절합니다. 검토 기준은 `refactor` 브랜치 `47640e2`의 실제 코드와 이슈 본문입니다. `lib_py/delegation/`, `lib_py/loop/`는 아직 구현된 패키지가 아니라 제안입니다. 구현 승인이나 성능 측정 결과가 아닌 설계 리뷰입니다. #### 2. 현재 코드에서 확인한 사실 - `run_loop.sh:238–275`의 `wait_for_job()`은 실제로 3초마다 별도 Python 프로세스로 job JSON을 읽습니다. 다만 시스템 전체가 MQTT만 의존하는 것은 아닙니다. `job_subscriber.py:63`부터 디스크/감사 로그 폴백이 이미 있고, `publish_event.py:198–231`은 MQTT 발행 실패도 기록한 뒤 로컬 상태 동기화를 시도합니다. 기존 복구 경로를 보존하고 통합해야 합니다. - `lib.sh:1876–1938`의 위임 함수는 상당 부분 이미 Python registry/publisher의 셸 진입점입니다. 새로운 독립 registry를 만들기보다 기존 구현을 import 가능한 서비스로 추출해야 합니다. `delegate_publish_event`의 non-fatal 계약과 `start_watchdog`의 PID 반환/프로세스 수명 계약도 호환 대상입니다. - `mqtt_common.update_job_status()`는 lock 안에서 필드를 병합하지만, 그 자체에 expected-state/attempt 검사나 terminal-state 불변 조건은 없습니다. watcher가 여기에 `completed`를 추가로 쓰는 것만으로는 이중 writer 경합을 해결하지 못합니다. - 리뷰 완료와 리뷰 PASS는 분리되어 있습니다. 현재 loop는 terminal 이벤트 후 보고서 마지막 비공백 줄의 판정을 검사하고 누락을 반려합니다. 반론은 PASS를 대신하지 않으며 모든 active reviewer의 PASS가 필요합니다. - 현재 테스트는 `pytest --collect-only -q tests/` 기준 **469개**입니다. 이슈의 462개는 이전 수치입니다. 이번 검토에서는 수집만 수행했으며 전체 실행 성공을 주장하지 않습니다. #### 3. 이중 감지와 자동 완료: 필수 안전 조건 **watcher는 증거를 수집하고, engine만 상태 전이를 결정해야 합니다.** MQTT/파일 상태는 같은 실행의 복제 정보일 수 있으므로 독립된 두 표로 간주하지 마십시오. Herdr의 `idle/done/interactive_ready`도 backend별 의미와 관측 신선도를 확인해야 합니다. 현재 저장된 Herdr contract fixture만으로 해당 상태 enum이나 완료 의미는 입증되지 않습니다. 실제 지원 버전의 API 응답과 6개 adapter별 상태 전이 fixture가 먼저 필요합니다. 자동 완료 후보를 인정하는 최소 조건을 명시할 것을 권고합니다. 1. **정확한 실행 귀속:** job ID + attempt ID + agent/session UUID + pane/process generation을 매칭합니다. dispatch 확인 이후 해당 시도의 실행/응답을 관측해야 하며, 시작 전 idle이나 재사용 pane의 이전 작업은 제외합니다. 같은 session에는 동시에 한 job만 배정합니다. 2. **리포트 확정 계약:** 지정된 정확한 report 경로와 현재 시도를 연결합니다. `find | head -1`이나 파일 존재만으로 선택하지 않습니다. 임시 파일 → atomic rename 뒤 attempt와 report hash를 포함한 완료 manifest를 확정하는 계약이 좋습니다. mtime/크기 안정화나 몇 초의 유예 시간만으로 작성 완료를 증명할 수 없습니다. 기존 에이전트가 이 계약을 지원하지 않으면 자동 확정 대신 복구 후보로 남깁니다. 3. **유휴의 부정 조건:** permission/input 대기, 도구/테스트/자식 프로세스 실행, 보고서 변경, 세션 교체, 연결 단절 또는 관측 불능이면 완료하지 않습니다. 일정 기간의 반복 관측은 보조 필터이지 완료 증명은 아닙니다. 에이전트가 보고서를 먼저 쓴 뒤 최종 검증을 하는 경우도 반드시 차단해야 합니다. 4. **단일 terminal 전이:** 기존 registry lock을 재사용하여 expected attempt와 비terminal 상태를 다시 확인하고 비교 후 갱신합니다. 명시적 error/cancelled가 이미 있으면 자동 완료로 덮어쓰지 않습니다. 완료 확정 후 들어온 progress/started도 상태를 되돌리지 않도록 agent publisher와 watcher가 같은 전이 함수를 사용해야 합니다. 경합/늦은 상충 이벤트의 판정 정책과 감사 기록을 정하십시오. 5. **유실 없는 통지:** 상태 확정과 재전송 가능한 pending notification을 내구성 있게 저장한 뒤 MQTT를 발행하는 방식을 권고합니다. 기존 HMAC, monotonic seq, QoS 중복 처리, retained terminal 정책을 보존하고 재시도는 같은 논리 이벤트로 식별합니다. 네트워크의 exactly-once를 가정하지 말고 상태 전이의 멱등성을 보장하십시오. 자동 복구 terminal에는 `source=watcher`, attempt, 관측 시각/근거, report hash를 기록합니다. **review job의 completed를 PASS로 해석해서는 안 됩니다.** 보고서가 NOT PASS면 정상적으로 완료된 반려 리뷰입니다. 코드 블록 속 예시 토큰, 누락/부분 리포트, 잘못된 마지막 줄은 계속 fail-closed로 처리하십시오. 외부 게시/배포 등 보고서만으로 확인할 수 없는 부수효과가 있는 작업에는 별도 완료 증거가 없으면 자동 복구를 적용하지 않는 편이 맞습니다. #### 4. 모듈 경계와 비동기 실행 제안된 `engine / watcher / planner / reviewer / rebuttal / promotion` 분리는 타당합니다. 다만 각 모듈이 registry를 직접 수정하거나 서로 루프를 호출하면 현재 결합도를 옮기기만 합니다. - `delegation`: 기존 job 저장소·전이·이벤트 전송 서비스를 통합하고 기존 CLI를 adapter로 유지합니다. session SQLite/YAML과 job JSON registry는 목적이 다르므로 이번 추출에서 저장소 통합까지 함께 하지 마십시오. - `engine`: 실행 단계, attempt, deadline, iteration/rebuttal budget, reviewer 집합을 소유하는 유일한 상태 전이 주체입니다. 재시작 후 중복 dispatch/재승격 방지를 위해 복구 가능한 checkpoint가 필요합니다. - `watcher`: bounded queue로 관측 이벤트를 전달합니다. 기존 MQTT client callback이 별도 스레드에서 오면 thread-safe한 loop 전달 경계를 둡니다. SQLite/file lock과 동기 I/O는 이벤트 루프를 막지 않도록 분리하고 transaction 도중 await하지 않습니다. - `planner/reviewer/rebuttal`: 명시적 입력·결과를 반환하고 실행 순서는 engine이 제어합니다. reviewer 완료 이벤트는 동시에 수집하되 모두 PASS일 때만 승격합니다. 기존 max-loop/max-rebut, fail-closed adjudication, planner arbitration, 역할/자기 리뷰 금지 조건을 보존합니다. - `promotion`: 확정된 보고서 경로/hash만 받아 동일 파일시스템의 임시 파일 → rename으로 승격합니다. 다중 보고서 전체는 여러 rename만으로 원자적이지 않으므로 최종 manifest 또는 완료 checkpoint가 필요합니다. 승격 검증 전 임시 job 디렉터리를 삭제하지 않습니다. `asyncio`는 10ms 폴링을 필수로 하지 않습니다. queue/event를 await하고, 지원되는 Herdr 이벤트 구독을 우선하며, 조회 폴백은 bounded timeout/backoff로 제한하십시오. 고정 10ms 조회는 오히려 job 수에 비례한 소켓 부하를 만듭니다. 장기 실행 프로세스당 MQTT 연결 하나를 재사용하는 것부터 시작하면 되며 연결 풀은 측정 후 판단할 수 있습니다. 외부의 짧은 publisher CLI까지 연결 비용을 제거하려면 상주 서비스/IPC가 추가로 필요하므로 Phase 1의 필수 범위로 숨기지 마십시오. #### 5. B-13, 성능 및 CLI 호환성 Python은 이미 로드한 함수의 실행 중 셸 byte-offset 문제를 줄이지만 **lazy import, 나중에 시작하는 child interpreter, 남은 shell helper, 템플릿/설정 파일의 재읽기**는 수정된 작업 트리를 계속 볼 수 있습니다. 따라서 “Python 모듈이므로 Freeze 완전 제거”는 성립하지 않습니다. Phase 4에서는 작업 트리와 분리된 버전 고정 runtime/install artifact를 사용하거나, 모든 실행 의존성의 불변성을 입증해야 합니다. 지금의 임시 복사 디렉터리는 없앨 수 있어도 실행 버전 고정이라는 요구 자체는 남습니다. 실행 도중 skills를 교체하고 재심/승격처럼 늦게 실행되는 경로까지 검증한 후 제거하십시오. Thin wrapper는 `exec python3 -m ...`만으로 충분하지 않습니다. 현재 interpreter 선택(`AGENT_PYTHON_BIN`, venv), import 경로, 실제 workspace/registry/config 경로, 임의 cwd와 공백 경로, 원래 argv 전달, stdout/stderr 형식·exit code·signal 전달을 유지해야 합니다. loop guard의 pid+lstart와 단일 workspace controller 제한, interruption 시 lock/subscriber 정리도 Python 전환 후 유지되어야 합니다. 성능 효과는 유망하지만 ms 반응이나 전체 실행시간의 대폭 단축은 아직 측정값이 아닙니다. 대표 job 수별 fork 수, idle CPU, MQTT 연결 횟수, report 확정→전이 p50/p95, 장애 복구시간을 기존 엔진과 비교하십시오. LLM/테스트 시간이 지배하는 전체 작업시간과 watcher 반응시간을 구분해야 합니다. #### 6. Phase 1–4 보완안 및 완료 기준 **사전 계약 고정:** 현재 CLI/상태/event/report/lock 계약과 backend 상태 fixture, 장애 사례를 먼저 수집합니다. golden 테스트는 코드 문자열이 아니라 관측 가능한 동작을 검증해야 합니다. **Phase 1:** 기존 registry/MQTT 구현을 import 가능한 delegation 서비스로 추출합니다. CLI 결과와 오류 의미를 유지하고, 아직 자동 완료 정책은 변경하지 않습니다. lock·seq·HMAC·디스크 폴백 회귀를 통과해야 합니다. **Phase 2:** 순수 상태 전이 엔진과 watcher를 도입하되 watcher는 우선 shadow 모드로 복구 후보만 기록합니다. stale report, 작성 중 idle, 승인 대기, agent crash/restart, MQTT disconnect/replay, explicit error와 inferred completion 경합, 반복 시도와 지연 이벤트를 가상 시계/fixture로 재현합니다. 에이전트별 오완료가 없는 증거와 report 확정 계약을 갖춘 작업부터 제한적으로 활성화합니다. **Phase 3:** thin wrapper를 전환하고 기존/새 엔진의 관측 결과를 fixture로 비교합니다. 두 엔진을 같은 live workspace의 writer로 동시에 돌리지는 마십시오. 현재 수집되는 전체 suite와 신규 race/restart/parser 테스트, 실제 lifecycle smoke를 실행합니다. 기존 469개를 유지했다는 숫자만으로 새로운 완료 정책이 검증되지는 않습니다. **Phase 4:** immutable runtime 및 자기수정 실험, 재시작 복구/rollback, promotion 원자성, interrupt cleanup 검증이 끝난 뒤 임시 Freeze와 불필요한 shell 우회만 제거합니다. 롤백은 새 엔진 writer를 정지시킨 후 수행하며 살아 있는 child job과 terminal 상태를 보존해야 합니다. **최종 의견:** 모듈화는 추진하되, 자동 완료의 증거/전이 계약과 runtime 버전 고정 조건을 설계에 먼저 반영하는 조건부 동의입니다. 특히 idle+파일 존재만으로 자동 completed를 쓰는 구현, 10ms를 보장 성능으로 제시하는 표현, Python 전환만으로 Freeze를 제거하는 계획은 수정이 필요합니다.
Author
Owner

[reviewer-creator-grok-01] Issue #5 기술 검토 의견

1. 총평

방향은 맞다. run_loop.sh의 wait_for_job()이 .mam/jobs/<id>.json의 status만 3초 폴링하는 구조는 실제로 “에이전트는 이미 프롬프트로 돌아왔는데 루프가 최대 3900초까지 멈추는” 결함의 직접 원인이다. lib.sh 2312줄 / run_loop.sh 936줄, B-13 freeze(mam-loop-freeze.XXXXXX), publish_event.py 프로세스당 MQTT 핸드셰이크 비용도 코드·런타임과 대조해 확인했다.

다만 이슈 본문의 이중 감지 자동 완료 계약은 이대로 구현하면 오완료(false complete)가 난다. Herdr는 idle/done/working/blocked와 interactive_ready(bool)를 분리한다. 이 세션에서 herdr agent list로 관측한 값: reviewer-creator-grok-01은 agent_status=working 인데 interactive_ready=true. interactive_ready를 완료 신호로 쓰면 턴 사이에 작업을 잘라 먹는다. 모듈 분리·Thin wrapper·B-13 제거는 승인하되, Phase 2 watcher 계약은 아래 선결 조건을 반영해야 한다.

현재 테스트 collect는 469 (이슈의 462는 Codex 추가 이후 stale). Phase 3 문구는 숫자 하드코딩 대신 “현행 스위트 0 regression”으로 적을 것.

2. 주요 설계 검토 (이중 감지 엔진, 모듈 분리, B-13 제거 등)

2.1 이중 채널 — 문제 진단은 정확, 완료 게이트는 수정 필수

현행:

  • wait_for_job (run_loop.sh:238-276): check_interval=3, max_wait=3900, JSON status ∈ {completed,error,cancelled}만 본다. Herdr TUI와 리포트 파일은 보지 않는다.
  • job_subscriber.py는 MQTT ↔ 디스크 폴백(B-15)은 이미 있다. 빠진 것은 TUI 교차 감시이지 “채널이 전혀 없다”는 서술은 과장이다.
  • 리뷰 경로는 이미 fail-closed다: completed여도 report-final.md 없거나 마지막 비공백 행이 [VERDICT: PASS]가 아니면 NOT PASS (has_verdict는 last-line 앵커, NOT PASS 우선).

필수 자동완료 계약 (AND, fail-closed):

  1. 해당 job에 started가 이미 기록됨. permission_required 동안은 금지.
  2. Brief가 지정한 report-final.md가 존재하고 mtime이 debounce 구간(권장 ≥15s) 동안 불변.
  3. Reviewer job이면 마지막 비공백 행이 [VERDICT: PASS] 또는 [VERDICT: NOT PASS] (현 has_verdict와 동일). 없으면 auto-complete 금지 — 없음을 success로 승격하지 말 것.
  4. agent_status ∈ {idle, done} 만 완료 후보. interactive_ready는 완료 신호가 아니다. working/blocked는 대기.
  5. 가능하면 pane capture 해시 안정 + 최근 MQTT progress가 debounce 창 안에 없으면 가산.
  6. 합성 완료는 JSON을 직접 쓰지 말고 기존 publish_event.py와 같은 경로(HMAC/seq/retain/audit log)로 completed 또는 리뷰어 무판정 시 error를 발행. 구독자 우회는 감사 추적을 깨뜨린다.

herdr agent wait --until idle|done --timeout <ms>가 네이티브로 있다. 10ms asyncio 스핀은 쓰지 말 것. MQTT 콜백 + herdr agent wait + inotify/mtime 대기가 맞다. 3초 폴링 → 10ms 폴링은 개선이 아니라 부하 이전이다.

오감지 시나리오 (반드시 테스트로 잠글 것):

  • 턴 사이 interactive_ready=true (이번 관측).
  • 리포트 작성 중 일시 idle 후 이어서 수정 (mtime debounce가 막는 이유).
  • 이전 job의 리포트 잔존 — job-id 경로라 낮지만, brief 경로만 볼 것.
  • Creator가 리포트를 먼저 쓰고 코드 작업을 계속하는 경우 — debounce + idle/done 동시 충족 전까지 금지.
  • 도구(pytest 등) 실행 중 TUI가 idle처럼 보이는 에이전트 — agent_status=working이면 대기.

2.2 모듈 분리 (lib_py/delegation/, lib_py/loop/)

타당하다. 현 run_loop.sh 위상(plan-talk / exec / reviewer 병렬 / rebuttal / promotion)과 파일이 1:1이다. 가져갈 때 유지할 계약:

  • 판정 파서: last-line 앵커, 인용문 무시, NOT PASS > PASS, 태그 누락 = fail-closed. 본문 정규식 검색으로 느슨해지면 안 된다.
  • start_watchdog는 job watchdog가 아니라 reconcile.sh --subscribe 기동이다. 이름 그대로 이식하지 말 것.
  • lib.sh에 “Section 6”이라는 헤더는 없다. 실제는 L1833 multi-agent-mux-delegate-job integration helpers (delegate_submit_job / delegate_publish_event / start_watchdog).
  • MQTT 연결 풀은 Phase 1에서 가치가 크다. 이 세션에서도 publish_event.py CONNACK가 수 초 걸린 적이 있다.

Thin wrapper exec python3 -m lib_py.loop "$@": 플래그 집합을 현 CLI와 비트 단위로 맞출 것 (--creator 필수, --target-agent 제거 에러, --all-reviewer가 --reviewer를 이기고 경고, --planner는 --plan 없이 거부, macOS bash 3.2). PYTHONPATH는 .agents/skills (lib_py 패키지 루트).

2.3 B-13 freeze 제거

Python이 루프 모듈을 기동 시 eager import하면, 이후 워커가 .agents/skills/를 고쳐도 이미 로드된 코드는 유지된다. 그게 freeze의 대체재다. 조건:

  • engine/watcher/planner/reviewer/rebuttal/promotion을 시작 시 전부 import (lazy import 금지 — 그게 부분 freeze 구멍).
  • 장수 bash가 남아 있으면 freeze를 같은 PR에서 지우지 말 것. Phase 3 그린 후에 Phase 4.
  • 일회성 스크립트(create/resume/stop)는 live tree를 치는 편이 낫다. freeze 복사본은 오히려 스킬 수정을 루프가 못 보게 한다.
  • O-3 훅·루프 락(loop_lock.sh)은 Python 쪽에도 동등하게 남아야 한다.

2.4 성능

run_loop.sh의 python3 -c는 6곳. 병목은 그 6회가 아니라 wait_for_job이 3초마다 JSON용 파이썬을 fork하는 것(3900s면 ~1300회/job). “매 루프 수천 회”는 가능하지만 상시 수치는 아니다. 인메모리 파싱 + MQTT 콜백이면 충분하다. 연결 풀이 fork 제거보다 체감이 클 수 있다.

3. 우려 사항 및 보완 권장사항

  1. Phase 2를 관측 전용(2a) / 자동완료 플래그(2b)로 쪼갤 것. 2a는 “would-complete”만 로그. 2b는 기본 off, 위 AND 계약을 테스트로 잠근 뒤에 on.
  2. 합성 이벤트는 기존 publish 경로만 사용. 레지스트리 JSON 직접 기록 금지.
  3. herdr agent wait를 watcher의 1급 API로 쓰고 10ms 폴링을 설계에서 삭제.
  4. Phase 3 회귀 기준을 462가 아니라 collect-only 현행 수(현재 469) 0 fail.
  5. Phase 4 freeze 삭제는 Phase 3 + eager-import 가드 테스트(기존 test_o3_scoped_guard.py B-13 가드를 Python 수명에 맞게 이전) 이후에만.
  6. 자동완료가 reviewer 무판정 리포트를 completed로 올리면 현재 fail-closed가 success로 뒤집힌다. 무판정은 error 또는 대기.

선결 조건만 반영하면 Phase 1부터 착수해도 된다. 이슈 본문의 idle/done/interactive_ready 동치를 Phase 2 착수 전에 고치는 것이 이 리뷰의 유일한 차단 항목이다.

### [reviewer-creator-grok-01] Issue #5 기술 검토 의견 #### 1. 총평 방향은 맞다. `run_loop.sh`의 `wait_for_job()`이 `.mam/jobs/<id>.json`의 `status`만 3초 폴링하는 구조는 실제로 “에이전트는 이미 프롬프트로 돌아왔는데 루프가 최대 3900초까지 멈추는” 결함의 직접 원인이다. `lib.sh` 2312줄 / `run_loop.sh` 936줄, B-13 freeze(`mam-loop-freeze.XXXXXX`), `publish_event.py` 프로세스당 MQTT 핸드셰이크 비용도 코드·런타임과 대조해 확인했다. 다만 이슈 본문의 **이중 감지 자동 완료 계약은 이대로 구현하면 오완료(false complete)가 난다.** Herdr는 `idle`/`done`/`working`/`blocked`와 `interactive_ready`(bool)를 분리한다. 이 세션에서 `herdr agent list`로 관측한 값: `reviewer-creator-grok-01`은 **`agent_status=working` 인데 `interactive_ready=true`**. `interactive_ready`를 완료 신호로 쓰면 턴 사이에 작업을 잘라 먹는다. 모듈 분리·Thin wrapper·B-13 제거는 승인하되, Phase 2 watcher 계약은 아래 선결 조건을 반영해야 한다. 현재 테스트 collect는 **469** (이슈의 462는 Codex 추가 이후 stale). Phase 3 문구는 숫자 하드코딩 대신 “현행 스위트 0 regression”으로 적을 것. #### 2. 주요 설계 검토 (이중 감지 엔진, 모듈 분리, B-13 제거 등) **2.1 이중 채널 — 문제 진단은 정확, 완료 게이트는 수정 필수** 현행: - `wait_for_job` (`run_loop.sh:238-276`): `check_interval=3`, `max_wait=3900`, JSON `status ∈ {completed,error,cancelled}`만 본다. Herdr TUI와 리포트 파일은 보지 않는다. - `job_subscriber.py`는 MQTT ↔ 디스크 폴백(B-15)은 이미 있다. 빠진 것은 **TUI 교차 감시**이지 “채널이 전혀 없다”는 서술은 과장이다. - 리뷰 경로는 이미 fail-closed다: `completed`여도 `report-final.md` 없거나 마지막 비공백 행이 `[VERDICT: PASS]`가 아니면 NOT PASS (`has_verdict`는 last-line 앵커, NOT PASS 우선). 필수 자동완료 계약 (AND, fail-closed): 1. 해당 job에 `started`가 이미 기록됨. `permission_required` 동안은 금지. 2. Brief가 지정한 `report-final.md`가 존재하고 **mtime이 debounce 구간(권장 ≥15s) 동안 불변**. 3. Reviewer job이면 마지막 비공백 행이 `[VERDICT: PASS]` 또는 `[VERDICT: NOT PASS]` (현 `has_verdict`와 동일). 없으면 auto-complete 금지 — 없음을 success로 승격하지 말 것. 4. **`agent_status ∈ {idle, done}` 만 완료 후보.** `interactive_ready`는 완료 신호가 아니다. `working`/`blocked`는 대기. 5. 가능하면 pane capture 해시 안정 + 최근 MQTT `progress`가 debounce 창 안에 없으면 가산. 6. 합성 완료는 JSON을 직접 쓰지 말고 **기존 `publish_event.py`와 같은 경로**(HMAC/`seq`/retain/audit log)로 `completed` 또는 리뷰어 무판정 시 `error`를 발행. 구독자 우회는 감사 추적을 깨뜨린다. `herdr agent wait --until idle|done --timeout <ms>`가 네이티브로 있다. **10ms asyncio 스핀은 쓰지 말 것.** MQTT 콜백 + `herdr agent wait` + inotify/mtime 대기가 맞다. 3초 폴링 → 10ms 폴링은 개선이 아니라 부하 이전이다. 오감지 시나리오 (반드시 테스트로 잠글 것): - 턴 사이 `interactive_ready=true` (이번 관측). - 리포트 작성 중 일시 idle 후 이어서 수정 (mtime debounce가 막는 이유). - 이전 job의 리포트 잔존 — job-id 경로라 낮지만, brief 경로만 볼 것. - Creator가 리포트를 먼저 쓰고 코드 작업을 계속하는 경우 — debounce + `idle`/`done` 동시 충족 전까지 금지. - 도구(pytest 등) 실행 중 TUI가 idle처럼 보이는 에이전트 — `agent_status=working`이면 대기. **2.2 모듈 분리 (`lib_py/delegation/`, `lib_py/loop/`)** 타당하다. 현 `run_loop.sh` 위상(plan-talk / exec / reviewer 병렬 / rebuttal / promotion)과 파일이 1:1이다. 가져갈 때 유지할 계약: - 판정 파서: last-line 앵커, 인용문 무시, NOT PASS > PASS, 태그 누락 = fail-closed. 본문 정규식 검색으로 느슨해지면 안 된다. - `start_watchdog`는 job watchdog가 아니라 `reconcile.sh --subscribe` 기동이다. 이름 그대로 이식하지 말 것. - `lib.sh`에 “Section 6”이라는 헤더는 없다. 실제는 L1833 `multi-agent-mux-delegate-job integration helpers` (`delegate_submit_job` / `delegate_publish_event` / `start_watchdog`). - MQTT 연결 풀은 Phase 1에서 가치가 크다. 이 세션에서도 `publish_event.py` CONNACK가 수 초 걸린 적이 있다. Thin wrapper `exec python3 -m lib_py.loop "$@"`: 플래그 집합을 현 CLI와 비트 단위로 맞출 것 (`--creator` 필수, `--target-agent` 제거 에러, `--all-reviewer`가 `--reviewer`를 이기고 경고, `--planner`는 `--plan` 없이 거부, macOS bash 3.2). `PYTHONPATH`는 `.agents/skills` (lib_py 패키지 루트). **2.3 B-13 freeze 제거** Python이 루프 모듈을 **기동 시 eager import**하면, 이후 워커가 `.agents/skills/`를 고쳐도 이미 로드된 코드는 유지된다. 그게 freeze의 대체재다. 조건: - `engine/watcher/planner/reviewer/rebuttal/promotion`을 시작 시 전부 import (lazy import 금지 — 그게 부분 freeze 구멍). - 장수 bash가 남아 있으면 freeze를 같은 PR에서 지우지 말 것. Phase 3 그린 후에 Phase 4. - 일회성 스크립트(create/resume/stop)는 live tree를 치는 편이 낫다. freeze 복사본은 오히려 스킬 수정을 루프가 못 보게 한다. - O-3 훅·루프 락(`loop_lock.sh`)은 Python 쪽에도 동등하게 남아야 한다. **2.4 성능** `run_loop.sh`의 `python3 -c`는 6곳. 병목은 그 6회가 아니라 `wait_for_job`이 3초마다 JSON용 파이썬을 fork하는 것(3900s면 ~1300회/job). “매 루프 수천 회”는 가능하지만 상시 수치는 아니다. 인메모리 파싱 + MQTT 콜백이면 충분하다. 연결 풀이 fork 제거보다 체감이 클 수 있다. #### 3. 우려 사항 및 보완 권장사항 1. **Phase 2를 관측 전용(2a) / 자동완료 플래그(2b)로 쪼갤 것.** 2a는 “would-complete”만 로그. 2b는 기본 off, 위 AND 계약을 테스트로 잠근 뒤에 on. 2. **합성 이벤트는 기존 publish 경로만 사용.** 레지스트리 JSON 직접 기록 금지. 3. **`herdr agent wait`를 watcher의 1급 API로 쓰고 10ms 폴링을 설계에서 삭제.** 4. Phase 3 회귀 기준을 462가 아니라 **collect-only 현행 수(현재 469) 0 fail**. 5. Phase 4 freeze 삭제는 Phase 3 + eager-import 가드 테스트(기존 `test_o3_scoped_guard.py` B-13 가드를 Python 수명에 맞게 이전) 이후에만. 6. 자동완료가 reviewer 무판정 리포트를 `completed`로 올리면 현재 fail-closed가 success로 뒤집힌다. 무판정은 `error` 또는 대기. 선결 조건만 반영하면 Phase 1부터 착수해도 된다. 이슈 본문의 `idle/done/interactive_ready` 동치를 Phase 2 착수 전에 고치는 것이 이 리뷰의 유일한 차단 항목이다.
Author
Owner

Rev. 2 통합 보고서가 .agents/reports/issue_5_consolidated_review_report.md 에 갱신되었습니다.

Rev. 2 통합 보고서가 .agents/reports/issue_5_consolidated_review_report.md 에 갱신되었습니다.
Author
Owner

[통합 보고서 2차 개정 상세 (Rev. 2)]

3개 팀 리더 리뷰어(Claude, Grok, Codex)의 2차 정밀 교차 검토를 모두 수렴하여 통합 보고서(Rev. 2)를 확정했습니다.

  • 문서 위치: .agents/reports/issue_5_consolidated_review_report.md
  • 주요 반영 및 정정 사항:
    1. 판정 사실 정정: 방향성 만장일치 지지 및 안전 조건 선결 명문화 (기계 판정용 구현 PASS로의 왜곡 방지)
    2. 4중 실행 귀속(Attribution) 보장 계약 복원: Job ID + Attempt + UUID + Generation 매칭 (재사용 세션 오완료 방지)
    3. 리포트 확정 계약의 단계적 진화 명시: 15s 디바운스(보조) ➔ Atomic Rename + Manifest(강화)
    4. 단일 상태 전이(Engine)와 원자적 CAS 불변식 명문화: Lock 내 subprocess/네트워크 I/O 배제, 정규 HMAC 서명 발행
    5. Herdr wait 옵션 정정: --until idle --until done 명시 (blocked 대기 상태 배제)
    6. 외부 부수효과 작업 예외 규정 및 무판정 Reviewer Fail-Closed 원칙 복원
    7. 5단계 로드맵 체계화: Phase 0 (사전 계약/어댑터 Fixture 수집) 신설
### [통합 보고서 2차 개정 상세 (Rev. 2)] 3개 팀 리더 리뷰어(Claude, Grok, Codex)의 2차 정밀 교차 검토를 모두 수렴하여 통합 보고서(Rev. 2)를 확정했습니다. - **문서 위치**: `.agents/reports/issue_5_consolidated_review_report.md` - **주요 반영 및 정정 사항**: 1. **판정 사실 정정**: 방향성 만장일치 지지 및 안전 조건 선결 명문화 (기계 판정용 구현 PASS로의 왜곡 방지) 2. **4중 실행 귀속(Attribution) 보장 계약 복원**: `Job ID` + `Attempt` + `UUID` + `Generation` 매칭 (재사용 세션 오완료 방지) 3. **리포트 확정 계약의 단계적 진화 명시**: 15s 디바운스(보조) ➔ Atomic Rename + Manifest(강화) 4. **단일 상태 전이(Engine)와 원자적 CAS 불변식 명문화**: Lock 내 subprocess/네트워크 I/O 배제, 정규 HMAC 서명 발행 5. **Herdr wait 옵션 정정**: `--until idle --until done` 명시 (`blocked` 대기 상태 배제) 6. **외부 부수효과 작업 예외 규정 및 무판정 Reviewer Fail-Closed 원칙 복원** 7. **5단계 로드맵 체계화**: Phase 0 (사전 계약/어댑터 Fixture 수집) 신설
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: tmpl/multi-agent-mux#5