docs(issue-5): phase 1 benchmark results, contract mapping, task checklist

Records the measured numbers and syncs every document that names the
delegation script paths, then bumps the framework to 4.3.0 in the three-way
lockstep (lib.sh, VERSIONS.md current + matrix, eight SKILL.md frontmatters).

phase1-benchmark.md carries both arms. The deterministic fake transport is what
CI asserts on: 50 publishes cost 50 connections one-shot and 1 persistent, p50
54.813ms -> 0.002ms. The real broker run is informational, since the PoC
default is a public broker: p50 1892.728ms -> 275.992ms, about 85% off.

It also corrects the plan's own estimate rather than repeating it. D8 predicted
the new shell path would drop from 3 forks to 2; the implementation is still 3,
because keeping the `_delegate_script publish_event.py` lookup is the only
thing that produces the "missing script tree does nothing" non-fatal contract
that C-02 pins. Saving that fork would change the contract, so it is deferred
to phase 4 rather than taken quietly.

SKILL.md gains the context table saying which tree wins where, so an operator
reading it knows a frozen loop runs frozen delegation code. The script paths in
every document remain correct and every quoted command still works verbatim.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UrDNJkHmm18uu7n7JwV5Qd
This commit is contained in:
GodopuandClaude Opus 5 committed 2026-09-06 15:48:38 +09:00
1 parent a4b7b45e13
commit 508ca99d71
18 files changed
+179 -30

No files matched your search

+1 -1
View File
@@ -29,7 +29,7 @@ export WORKSPACE_ROOT
# Framework semantic version. Single runtime source of truth; kept in lockstep
# with VERSIONS.md and the 8 SKILL.md frontmatters by tests/test_version_consistency.py.
# NOTE: unlike other MAM_* variables this one is intentionally NOT env-overridable.
MAM_VERSION="4.2.0"
MAM_VERSION="4.3.0"
export MAM_VERSION
AGENT_SESSIONS_YAML="${AGENT_SESSIONS_YAML:-$WORKSPACE_ROOT/.mam/agent-sessions.yaml}"
@@ -1,7 +1,7 @@
---
name: multi-agent-mux-create
description: "Create a new agent session (claude, antigravity/agy) in a dedicated herdr session for context-preserving long-running work. Always creates a herdr session — never backgrounds with nohup/disown. Writes the new session to .mam/agent-sessions.yaml. Use when you want to start a fresh agent (no prior UUID) for a new project workspace."
version: 4.2.0
version: 4.3.0
author: godopu
license: MIT
platforms: [linux, macos]
@@ -7,5 +7,6 @@
- 브로커 PoC→운영 전환: [`mqtt-broker-setup.md`](./mqtt-broker-setup.md)
- 레지스트리 포맷/동시성: [`registry.md`](./registry.md)
- 참조 구현: [`multi-agent-mux-delegate-job`](./multi-agent-mux-delegate-job) (bash wrapper), [`scripts/publish_event.py`](./scripts/publish_event.py), [`scripts/job_subscriber.py`](./scripts/job_subscriber.py), [`scripts/registry.py`](./scripts/registry.py), [`scripts/mqtt_common.py`](./scripts/mqtt_common.py)
- **v4.3.0 이후**: 위 `scripts/*.py`는 호환 shim이며 실제 구현은 `.agents/skills/lib_py/delegation/`에 있다 (issue #5 phase 1). 스크립트 경로와 CLI 계약은 그대로이며, `lib.sh` 헬퍼는 `python -m lib_py.delegation.cli`를 호출한다.
- 영구 감사 로그: `.mam/delegate_job_logs/<job_id>/` (`meta.json`·`events.ndjson`·`status.json`)
— `multi-agent-mux-delegate-job logs <id>` 또는 `multi-agent-mux-delegate-job logs --list`로 조회 (SKILL.md "Audit Logs" 참조)
@@ -1,7 +1,7 @@
---
name: multi-agent-mux-delegate-job
description: "Delegate a unit of work to any autonomous agent (claude-code, hermes, agy, grok-build, codex, or a human) and observe it asynchronously over an MQTT event channel. Supported roles include orchestrator, worker, and reviewer."
version: 4.2.0
version: 4.3.0
author: godopu
license: MIT
platforms: [linux, macos, windows]
@@ -70,6 +70,31 @@ For detailed state machine diagrams and configurations, see [DELEGATION_TYPES.md
---
## Where the Implementation Lives (v4.3.0)
The implementation moved to the `lib_py.delegation` package in issue #5 phase 1.
`scripts/{mqtt_common,registry,publish_event,job_subscriber}.py` remain as
compatibility shims and **their paths are unchanged** -- every command in this
document still works verbatim. Each shim binds the `lib_py.delegation` package
to the tree next to itself, once per process, without touching `sys.path`, so
`import mqtt_common` yields the same module object as
`lib_py.delegation.mqtt_common`.
Which tree wins, by execution context:
| Context | Resolved by | Tree that wins |
|---|---|---|
| Loop process and its children (frozen `lib.sh` sourced) | `PYTHONPATH` | the frozen snapshot |
| Agent session running a **frozen** script path while `PYTHONPATH` still points live | the shim, from its own location | the frozen snapshot (B-13 preserved) |
| Live helpers (create/stop/resume/reconcile) | `PYTHONPATH` or the shim (same tree) | the live tree |
| Standalone, no `PYTHONPATH` | the shim's fallback append | the shim's own tree |
`lib.sh` calls the package through `python -m lib_py.delegation.cli`. Setting
`MAM_DELEGATION_PY=0` switches the shell helpers back to their preserved legacy
bodies with no redeploy.
---
## The Event Protocol Contract
Every agent participating in the delegation contract must follow the same lifecycle publishing protocol using `publish_event.py`:
@@ -112,3 +112,7 @@ On `broker.hivemq.com` anyone can publish/subscribe the same topic. Therefore:
subscriber **before** the agent (ordering dependency), or rely on retained
terminal events in production.
- Real operational decisions belong to the own-broker stage with auth + ACL.
---
> **구현 위치 각주 (v4.3.0)**: 본 문서가 인용하는 `scripts/*.py` 경로는 유효하며 계약도 불변이다. 실제 구현은 issue #5 phase 1에서 `.agents/skills/lib_py/delegation/`으로 이동했고, `scripts/*.py`는 그 패키지를 자기 옆 트리에 바인딩하는 호환 shim이다.
@@ -183,3 +183,7 @@ $PY scripts/registry.py logs <job_id> --tail 20 # last 20 events
$PY scripts/registry.py logs <job_id> --json # raw JSON lines
$PY scripts/registry.py logs --list # every job, live status
```
---
> **구현 위치 각주 (v4.3.0)**: 본 문서가 인용하는 `scripts/*.py` 경로는 유효하며 계약도 불변이다. 실제 구현은 issue #5 phase 1에서 `.agents/skills/lib_py/delegation/`으로 이동했고, `scripts/*.py`는 그 패키지를 자기 옆 트리에 바인딩하는 호환 shim이다.
+1 -1
View File
@@ -1,7 +1,7 @@
---
name: multi-agent-mux-loop
description: "Run an autonomous planning-execution-review loop using multiple agents (Planner, Creator, Reviewers) in the workspace. Automatically orchestrates plan discussion, code changes, and peer reviews until a unanimous PASS is achieved or the maximum iteration limit is reached."
version: 4.2.0
version: 4.3.0
author: godopu
license: MIT
platforms: [linux, macos]
@@ -1,7 +1,7 @@
---
name: multi-agent-mux-monitor
description: "Run a long-lived reconciler that watches .mam/agent-sessions.yaml against the actual herdr/agent runtime state and reconciles them. Use when you want live visibility into which agent sessions are running, which are dead, which have stale YAML entries, and which have new session ids that haven't been recorded yet. Runs as a persistent loop (`reconcile.sh --subscribe`) that keeps going until it times out, idles out, or is interrupted."
version: 4.2.0
version: 4.3.0
author: godopu
license: MIT
platforms: [linux, macos]
@@ -1,7 +1,7 @@
---
name: multi-agent-mux-orc-onboard
description: "Register current or specified orchestrator session UUID into agent-sessions.yaml orchestrator_uuids list to prevent sub-agent discovery capture."
version: 4.2.0
version: 4.3.0
author: godopu
license: MIT
platforms: [linux, macos]
@@ -1,7 +1,7 @@
---
name: multi-agent-mux-resume
description: "Resume an existing agent (claude, antigravity/agy) conversation by UUID into a herdr session. Reads .mam/agent-sessions.yaml for the saved session/conversation id, spawns (or reuses) a herdr session of the matching name, and runs `claude -r <id>` or `agy --conversation <id>` inside. Use when you want to reattach to a previous session's context, or revive a session whose herdr died but the agent's conversation is still on disk."
version: 4.2.0
version: 4.3.0
author: godopu
license: MIT
platforms: [linux, macos]
@@ -1,7 +1,7 @@
---
name: multi-agent-mux-status
description: "Read-only instant snapshot of all agent herdr sessions — name, YAML status, herdr alive, pane cmd/cwd, resume UUID on disk, and any drift. No mutation. Reuses reconcile.sh --dry-run for the diff logic. Use when you want to know 'what's running RIGHT NOW' without spinning up the monitor loop."
version: 4.2.0
version: 4.3.0
author: godopu
license: MIT
platforms: [linux, macos]
+1 -1
View File
@@ -1,7 +1,7 @@
---
name: multi-agent-mux-stop
description: "Stop an agent herdr session (claude, antigravity/agy) and update .mam/agent-sessions.yaml. Default stops gracefully and marks status=stopped with conversation preserved for resume. Does NOT delete on-disk conversation artifacts (jsonl/db) — those are preserved unless --purge-conversation is passed. Use when ending a work session, switching to a different one, or cleaning up before a fresh start."
version: 4.2.0
version: 4.3.0
author: godopu
license: MIT
platforms: [linux, macos]
+31 -13
View File
@@ -6,35 +6,53 @@
## 📌 현재 버전 개요 (Current Release)
- **프레임워크 버전**: `v4.2.0`
- **최신 릴리스 일시**: 2026-09-05 (KST)
- **기준 브랜치**: `support-codex`
- **프레임워크 버전**: `v4.3.0`
- **최신 릴리스 일시**: 2026-09-06 (KST)
- **기준 브랜치**: `refactor`
- **핵심 아키텍처**:
- **Codex First-Class Agent Integration**: OpenAI Codex CLI(`codex`)를 6번째 1급 에이전트 백엔드로 전면 통합 (`claude`, `agy`, `hermes`, `grok`, `opencode`, `codex`)
- **Class A Codex Lifecycle & State DB Resolution**: 동적 `state_*.sqlite` SQLite 인덱스 및 date-nested rollout jsonl 폴백 지원, `--dangerously-bypass-approvals-and-sandbox` 비대화형 실행 연동
- **Runtime Framework Version Constant (`MAM_VERSION`) & 3-Way Lockstep**: `lib.sh` 내 `MAM_VERSION="4.2.0"` 런타임 진실 공급원 및 8개 스킬 3자 동기화 가드 유지
- **`lib_py.delegation` 패키지 추출 (Issue #5 Phase 1)**: 위임 스크립트 4종을 파이썬 패키지로 승격하고, 기존 `scripts/*.py` 경로는 패키지를 자기 옆 트리에 프로세스당 1회 바인딩하는 호환 shim으로 유지
- **Runtime Framework Version Constant (`MAM_VERSION`) & 3-Way Lockstep**: `lib.sh` 내 `MAM_VERSION="4.3.0"` 런타임 진실 공급원 및 8개 스킬 3자 동기화 가드 유지
---
## 🧭 스킬 패키지 버전 매트릭스 (Skills Version Matrix)
모든 8개 스킬은 YAML frontmatter 메타데이터(`author`, `version`, `platforms`, `environments`) 표준화를 통해 `v4.2.0`으로 동기화되어 배포됩니다.
모든 8개 스킬은 YAML frontmatter 메타데이터(`author`, `version`, `platforms`, `environments`) 표준화를 통해 `v4.3.0`으로 동기화되어 배포됩니다.
| 스킬명 | 버전 | 역할 및 주요 책임 | 상태 |
| :--- | :---: | :--- | :---: |
| **`multi-agent-mux-create`** | `4.2.0` | 에이전트 세션 신규 생성 및 Herdr 컨테이너 격리 스폰 | ✅ 배포 |
| **`multi-agent-mux-stop`** | `4.2.0` | 대화 UUID 원자적 캡처 및 세션 안전 종료 (Graceful Stop) | ✅ 배포 |
| **`multi-agent-mux-resume`** | `4.2.0` | 온디스크 대화 컨텍스트 기반 Tier-1 초고속 세션 복원 | ✅ 배포 |
| **`multi-agent-mux-status`** | `4.2.0` | 실시간 Herdr 세션 및 레지스트리 드리프트 스냅샷 조회 | ✅ 배포 |
| **`multi-agent-mux-monitor`** | `4.2.0` | YAML ↔ 런타임 상태 간 자율 조정자 (Reconciler Loop) | ✅ 배포 |
| **`multi-agent-mux-delegate-job`** | `4.2.0` | MQTT 이벤트 채널 기반 비동기 단위 작업 위임 | ✅ 배포 |
| **`multi-agent-mux-loop`** | `4.2.0` | Planner-Creator-Reviewer 3자 자율 계획·실행·피어리뷰 루프 | ✅ 배포 |
| **`multi-agent-mux-orc-onboard`** | `4.2.0` | 오케스트레이터 UUID 격리 등록 및 서브 세션 오염 방지 | ✅ 배포 |
| **`multi-agent-mux-create`** | `4.3.0` | 에이전트 세션 신규 생성 및 Herdr 컨테이너 격리 스폰 | ✅ 배포 |
| **`multi-agent-mux-stop`** | `4.3.0` | 대화 UUID 원자적 캡처 및 세션 안전 종료 (Graceful Stop) | ✅ 배포 |
| **`multi-agent-mux-resume`** | `4.3.0` | 온디스크 대화 컨텍스트 기반 Tier-1 초고속 세션 복원 | ✅ 배포 |
| **`multi-agent-mux-status`** | `4.3.0` | 실시간 Herdr 세션 및 레지스트리 드리프트 스냅샷 조회 | ✅ 배포 |
| **`multi-agent-mux-monitor`** | `4.3.0` | YAML ↔ 런타임 상태 간 자율 조정자 (Reconciler Loop) | ✅ 배포 |
| **`multi-agent-mux-delegate-job`** | `4.3.0` | MQTT 이벤트 채널 기반 비동기 단위 작업 위임 | ✅ 배포 |
| **`multi-agent-mux-loop`** | `4.3.0` | Planner-Creator-Reviewer 3자 자율 계획·실행·피어리뷰 루프 | ✅ 배포 |
| **`multi-agent-mux-orc-onboard`** | `4.3.0` | 오케스트레이터 UUID 격리 등록 및 서브 세션 오염 방지 | ✅ 배포 |
---
## 📋 버전별 상세 변경 내역 (Changelog)
### 🚀 `v4.3.0` — `lib_py.delegation` 패키지 추출 및 장수 MQTT 연결 프로토타입 (2026-09-06)
> **주요 마일스톤 (MINOR Release)**: Issue #5 Phase 1. `lib.sh`의 위임 헬퍼 3종과 `multi-agent-mux-delegate-job/scripts/*.py` 4종을 `lib_py/delegation/` 파이썬 패키지로 추출. 스크립트 경로는 와이어 계약이므로 호환 shim으로 보존하며, 프로덕션 동작·이벤트 스키마·자동완료 정책은 한 줄도 바뀌지 않는다.
#### 🌟 신규 기능 및 아키텍처 확장
* **패키지 바인딩 shim (D2)**: `scripts/{mqtt_common,registry,publish_event,job_subscriber}.py`는 `lib_py.delegation` **패키지**를 자기 옆 트리에 프로세스당 1회 바인딩하고 `sys.path`를 건드리지 않는다. `import mqtt_common`은 `lib_py.delegation.mqtt_common`과 동일한 모듈 객체가 된다.
- `sys.path.insert(0, ...)` 방식은 pytest에서 최초로 임포트된 샌드박스 사본이 `lib_py.agents`/`layout`/`state`까지 세션 전체에 걸쳐 가로채므로 채택하지 않았다.
- 모듈 단위 파일 적재 방식은 형제를 임포트하는 모듈이 다른 트리의 의존성을 끌어와 freeze(B-13) 보호를 부분 상실하므로 채택하지 않았다.
* **`DelegationService` / `cli.py` / `daemon.py`**: 셸 헬퍼 3종의 본체를 `python -m lib_py.delegation.cli`로 교체. `start_watchdog`은 `ensure_subscriber_daemon`의 별칭으로 유지.
* **`PersistentPublisher` 프로토타입 (`publisher.py`) 및 벤치마크 하니스 (`bench.py`)**: 장수 연결은 Phase 2a 엔진용이며 프로덕션 경로(CLI·셸)는 계속 1회성 연결을 사용한다.
* **`ensure_env_loaded()` (D6)**: `.mam.env` 로딩을 임포트 시점에서 프로세스 진입점으로 이동. 라이브러리 임포트가 `os.environ`을 변경하지 않는다.
#### 🔒 롤백 및 안전장치
* **`MAM_DELEGATION_PY=0`**: 셸 헬퍼가 보존된 레거시 인라인 본체(`_*_legacy`)로 즉시 분기. 재배포·revert 불필요. 레거시 본체 제거는 Phase 4.
* **특성화 테스트 선행 (P1-00)**: 이전까지 위임 셸 헬퍼 3종을 직접 검증하는 테스트가 0건이었으므로, 이동 **전에** 골든 테스트를 먼저 추가하고 두 경로(`MAM_DELEGATION_PY` 0/1) 모두에서 통과시켰다.
### 🚀 `v4.2.0` — OpenAI Codex First-Class Agent Backend Integration (2026-09-05)
> **주요 마일스톤 (MINOR Release)**: OpenAI Codex CLI(`codex`)를 6번째 정식 1급 에이전트 백엔드로 통합. 46개 전체 아키텍처 결합 지점(Shell 라이프사이클, Python 어댑터, 레지스트리, 상태 머신, 동기화 루프, 테스트 스위트, 문서) 전면 연동 완료.
+1
View File
@@ -101,6 +101,7 @@ check_assets_present() {
".agents/skills/lib.sh"
".agents/skills/multi-agent-mux-create/scripts/create_session.sh"
".agents/skills/multi-agent-mux-delegate-job/scripts/registry.py"
".agents/skills/lib_py/delegation/__init__.py"
".agents/skills/multi-agent-mux-status/scripts/status.sh"
".agents/skills/multi-agent-mux-loop/scripts/run_loop.sh"
".agents/hooks.json"
+1 -1
View File
@@ -137,5 +137,5 @@ stateDiagram-v2
| 오케스트레이터 CLI | `run_loop.sh` | `tests/test_loop_cli.py` | 9개 테스트 통과 |
| 루프 가드 락 | `loop_lock.sh` | `tests/test_o2_race_free_lock.py` | 22개 테스트 통과 |
| 반론 상한선 | `run_loop.sh` | `tests/test_o1_rebuttal.py` | 10개 테스트 통과 |
| 위임 헬퍼 | `lib.sh` | `tests/test_tier1_unit.py` | 단위 테스트 통과 |
| 위임 헬퍼 | `lib.sh` + `lib_py/delegation/` | `tests/test_issue5_phase1_delegation.py` | Phase 1 추출 완료 (v4.3.0); shim 경로·CLI 계약 불변 |
| 작업 레지스트리 | `registry.py`, `mqtt_common.py` | `tests/test_tier2_component.py` | fcntl 기반 락킹 |
@@ -22,7 +22,7 @@
| 단계 | 작업 목표 | 세부 구현 내용 | 필수 완료 게이트 (Gate Criteria) | 롤백 절차 (Rollback Path) |
|---|---|---|---|---|
| **Phase 0**<br>*(현재)* | **사전 계약 고정 및 Fixture 수집** | • CLI, 이벤트, 리포트, 락 계약 기준선 문서화<br>• Herdr 0.8.2 네이티브 캡처 및 복합 Watcher 시나리오 2계층 분리<br>• 6개 백엔드 실측 증거 행렬 수집 | • 510개 전체 테스트 수집 및 회귀 0-Fail (100% 통과)<br>• Fixture 스키마 및 증거 경계 검증 통과<br>• 프로덕션 코드 무변경 diff 검증 | 미추적 산출물 즉시 삭제 (`rm -rf docs/contracts/issue-5 tests/fixtures/issue_5 tests/test_issue5_phase0_contracts.py`) |
| **Phase 1** | **`lib_py/delegation/` 추출** | • `lib.sh` L1833 이하 위임 헬퍼를 파이썬 서비스 클래스로 추출<br>• `start_watchdog`을 내부 명칭 `ensure_subscriber_daemon`으로 명명(기존 함수 별칭 보존)<br>• 장수 프로세스 단일 MQTT 연결 재사용 프로토타입 | • CLI/non-fatal/HMAC/seq/디스크 폴백 회귀 100% 통과<br>• 데몬 수명 및 PID 계약 일치 확인<br>• **자동완료 정책 변경 없음** | `lib.sh` 위임 헬퍼 호출을 이전 인라인/셸 방식으로 즉시 복원 |
| **Phase 1**<br>*(완료 v4.3.0)* | **`lib_py/delegation/` 추출** | • `lib.sh` L1833 이하 위임 헬퍼를 파이썬 서비스 클래스로 추출<br>• `start_watchdog`을 내부 명칭 `ensure_subscriber_daemon`으로 명명(기존 함수 별칭 보존)<br>• 장수 프로세스 단일 MQTT 연결 재사용 프로토타입 | • CLI/non-fatal/HMAC/seq/디스크 폴백 회귀 100% 통과<br>• 데몬 수명 및 PID 계약 일치 확인<br>• **자동완료 정책 변경 없음** | `MAM_DELEGATION_PY=0`으로 보존된 레거시 인라인 본체(`_*_legacy`)로 즉시 분기 (재배포·revert 불필요; 레거시 본체 제거는 Phase 4) |
| **Phase 2a** | **`lib_py/loop/` 코어 & Shadow Watcher** | • `engine.py` (단일 전이 주체), `watcher.py` (`herdr agent wait` 래핑) 구현<br>• 모든 Writer에 대한 단일 CAS 트랜잭션 경계 구현<br>• 자동완료를 수행하지 않고 "Would-Complete" 로깅만 수행하는 Shadow 모드 가동 | • 락 내 비동기/I/O 배제 검증<br>• 소켓 단절/스냅샷 재연결 백오프 검증<br>• Shadow 모드가 레지스트리 상태를 쓰지 않음을 검증 | 1) Shadow 모니터 프로세스 종료 및 인메모리 큐 폐기<br>2) CAS 서비스는 하위 호환 모드로 유지하거나 `MAM_ENGINE_CAS=0` 플래그로 비활성화하여 레거시 무조건 필드 병합(`update_job_status`)으로 복귀<br>3) 기존 셸 루프 상태 및 레코드 불변 유지 |
| **Phase 2b** | **이중 감지 자동완료 활성화 (Flag-Gated)** | • 4중 실행 귀속 + 리포트 확정 계약 + 단일 CAS 전이 게이트 연동<br>• Pending Notification 지연 알림 및 크래시 복구 구현<br>• 검증된 백엔드/작업에 한해 opt-in 플래그로 활성화 (기본값 OFF) | • 부수효과 작업 예외 및 무판정 fail-closed 테스트 완료<br>• 경쟁/재시작 시나리오 통과<br>• 플래그 OFF 시 기존 explicit event 경로 100% 보존 | 환경변수/플래그 `MAM_AUTO_COMPLETE=0` 설정; 이미 확정된 terminal 레코드는 보존하고 신규 자동완료만 중단 |
| **Phase 3** | **`run_loop.sh` Thin Wrapper 전환 및 전면 회귀** | • `run_loop.sh`를 인자 전달 래퍼(`exec python3 -m lib_py.loop "$@"`)로 전환<br>• 플래너/리뷰어/반론/승격 오케스트레이션 로직 완전 이식<br>• 엄격한 판정 파서(Strict Parser) 적용 | • 5개 subprocess 전용 테스트(~1,621줄) 포함 전체 481개+ 테스트 0-Fail<br>• 시그널, 루프 가드, 임의 CWD 및 공백 경로 검증 통과 | **우아한 핸드오프 시퀀스**:<br>1) Quiesce: 실행 중인 Python 루프 프로세스에 종료 신호를 전달하여 신규 디스패치 중단<br>2) Checkpoint: 현재 루프 회차, 활성 Job ID 및 리뷰 상태를 `.mam/loop-checkpoint.json`에 원자적 기록<br>3) Exit: Python 루프 정상 종료 및 가드 해제<br>4) Resume: 백업된 셸 원본 스크립트로 `run_loop.sh` 복원 후 체크포인트 기반 재개 검증 |
@@ -0,0 +1,87 @@
# 📊 Issue #5 Phase 1 — 장수 MQTT 연결 벤치마크 실측
- **문서 버전**: Rev.1
- **측정 일시**: 2026-09-06
- **기준 커밋**: Phase 1 커밋 4 (`feat(issue-5): persistent MQTT publisher prototype and benchmark harness`)
- **하니스**: `python -m lib_py.delegation.bench --n <N> --transport {fake|broker}`
- **근거 대상**: `implementation_plan.md` §5 "MQTT 연결 재사용 p50 단축" 항목
---
## 1. 측정 환경
| 항목 | 값 |
|---|---|
| Python | 3.9.6 (`.venv`) |
| paho-mqtt | 2.1.0 |
| 플랫폼 | darwin-arm64 |
| 로컬 브로커 | **없음** (`mosquitto`, `nats-server`, `docker` 모두 미설치) |
| 실브로커 | `broker.hivemq.com:1883` (PoC 기본 공용 브로커, TLS 없음) |
> ⚠️ 로컬 브로커가 없으므로 실브로커 수치는 공용 인터넷 브로커에 대한 **1회 측정치**이며, 네트워크 상태에 좌우된다. **게이트 조건이 아니다.** 게이트가 걸린 것은 아래 §2의 결정적 지표뿐이다.
---
## 2. 결정적 지표 — 가짜 전송 (CI 단정 대상)
합성 연결 지연 50 ms, N = 50.
| 지표 | OneShot | Persistent |
|---|---:|---:|
| 발행 수 | 50 | 50 |
| **연결 수립 횟수** | **50** | **1** |
| 실패 | 0 | 0 |
| 발행당 지연 p50 | 54.813 ms | **0.002 ms** |
| 발행당 지연 p95 | 55.049 ms | 0.003 ms |
| 발행당 지연 max | 55.075 ms | 51.110 ms (최초 연결) |
`tests/test_issue5_phase1_delegation.py::test_bench_fake_transport_schema_and_counts`가 "OneShot = N, Persistent = 1" 및 p50 감소를 단정한다. 네트워크 접촉 0.
---
## 3. 정보성 지표 — 실브로커 (게이트 아님)
`broker.hivemq.com:1883`, N = 5.
| 지표 | OneShot | Persistent |
|---|---:|---:|
| 연결 수립 횟수 | 5 | 1 |
| 실패 | 0 | 0 |
| 발행당 지연 p50 | 1892.728 ms | **275.992 ms** |
| 발행당 지연 p95 | 1942.762 ms | 875.412 ms |
| 발행당 지연 max | 1942.762 ms | 875.412 ms (최초 연결) |
p50 기준 약 **85% 단축**. 연결 수립이 발행 지연의 지배적 요소임을 보여준다.
### 3-1. 이 프로토타입의 실측 동기
Rev.1 계획 job의 `started` 이벤트는 payload timestamp 05:58:49Z에서 모니터 수신 05:59:01.487Z까지 **약 12.5초**가 걸렸고, 원인은 `CONNECT_ACK_TIMEOUT=10` 1회 실패 후 재연결이었다. 본 job(`ddcaf930`)의 `started` 발행에서도 같은 CONNACK 경고가 재현됐다. 1회성 연결은 이 비용을 매 이벤트마다 다시 지불한다.
---
## 4. 프로세스 포크 수 (셸 경로, 분석값)
`delegate_publish_event` 1회당:
| 구현 | fork |
|---|---:|
| 레거시 (`_delegate_publish_event_legacy`) | 3 (`$(_delegate_py_bin)`, `$(_delegate_script)`, python) |
| 신규 (`-m lib_py.delegation.cli`) | 3 (`$(_delegate_py_bin)`, `$(_delegate_script)`, python) |
> 계획서 D8은 신규 경로가 2 fork일 것으로 예상했으나, **실제 구현은 3 fork로 동일하다.** `_delegate_script publish_event.py` 호출을 유지했기 때문이며, 이는 의도적이다: 그 호출이 "스크립트 트리가 없으면 아무 것도 하지 않는다"는 비치명 계약(C-02)을 만들어내는 유일한 지점이다. 이를 제거하면 fork 1회를 아끼는 대신 계약이 바뀐다. fork 절감은 Phase 4에서 계약과 함께 재검토한다.
---
## 5. 프로덕션 적용 범위
**Phase 1에서 장수 연결은 프로덕션 경로에 쓰이지 않는다.** CLI와 셸 헬퍼는 발행 1회 후 프로세스가 종료되므로 재사용 이득이 없고, 두 경로 모두 `OneShotPublisher`를 계속 쓴다. 첫 소비자는 Phase 2a의 장수 엔진이다.
## 6. 재현 명령
```bash
export PYTHONPATH="$PWD/.agents/skills"
.venv/bin/python -m lib_py.delegation.bench --n 50 --transport fake --connect-latency-ms 50
# 실브로커(임시 레지스트리 필요)
.venv/bin/python -m lib_py.delegation.cli submit --prompt bench --registry-dir .mam/jobs
.venv/bin/python -m lib_py.delegation.bench --n 5 --transport broker --job <id> --registry-dir .mam/jobs
```
+15 -6
View File
@@ -1,8 +1,8 @@
# 📑 Issue #5 Task Checklist & Verification Evidence
- **Document Version**: Rev.5 (Evidence Dispatch Hardening — P0-16/P0-18/P0-20 증거 갱신)
- **Document Version**: Rev.6 (Phase 1 실행 완료 — P1-01~P1-03 증거 기록)
- **Issue**: [Gitea Issue #5](https://git.godopu.com/tmpl/multi-agent-mux/issues/5)
- **Status**: Phase 0 Complete / Phase 1–4 Staged
- **Status**: Phase 0 Complete / **Phase 1 Complete (v4.3.0)** / Phase 2–4 Staged
---
@@ -57,10 +57,19 @@
---
## Phase 1: `lib_py/delegation/` 구축 (후속 승인된 작업)
- [ ] **P1-01** 기존 delegation import 서비스/CLI adapter 추출; 저장소 통합 없이 nonfatal·daemon PID 계약 보존.
- [ ] **P1-02** 장수 프로세스 단일 MQTT 연결 재사용과 benchmark; legacy publisher 호환 테스트.
- [ ] **P1-03** HMAC/seq/retain/disk fallback 회귀와 rollback 확인. 자동완료 비활성 유지.
## 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`. `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`) 실증 완료.
---