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:
1 parent
a4b7b45e13
commit
508ca99d71
18 files changed
+179
-30
No files matched your search
@@ -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
|
||||
```
|
||||
@@ -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`) 실증 완료.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in new issue
Block a user