release(v4.8.1): bump framework and eight skills to 4.8.1 in lockstep; archive PR #43 reviews (two rounds)

Issue #26: one .mam.env parser for the wrapper and the Python tools,
decimal integer knobs, tests on a local MQTT broker. Merge-workspace
review: round 1 (@b58edac) claude agy PASS, codex NOT PASS (R1-R4), grok
no verdict (its late report, archived as report-c9ed5b14.md, found R1 too);
round 2 (@0eec795) 4/4 PASS. Reports and round-2 identity sidecars go to
.agents/reports/<session>/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
This commit is contained in:
GodopuandClaude Opus 5.5 committed 2026-10-02 00:23:22 +09:00
1 parent 0eec795cd1
commit 2e90c809d3
28 files changed
+922 -26

No files matched your search

+28 -11
View File
@@ -6,8 +6,8 @@
## 📌 현재 버전 개요 (Current Release)
- **프레임워크 버전**: `v4.8.0`
- **최신 릴리스 일시**: 2026-09-26 (KST)
- **프레임워크 버전**: `v4.8.1`
- **최신 릴리스 일시**: 2026-10-02 (KST)
- **기준 브랜치**: `main`
- **핵심 아키텍처**:
- **Terminal 상태 단방향 불변성 (`engine.py`, Issue #6 Phase 1)**: `completed`, `error`, `cancelled` 터미널 상태 진입 후 후속 이벤트나 업데이트에 의한 덮어쓰기를 엄격히 차단(Terminal Immutability). `registry.py close` 서브커맨드 및 fail-closed 조기 종료 도입.
@@ -17,29 +17,46 @@
- **프로토콜 기반 생존·전달 계약 (Issue #18)**: heartbeat 의무(N, 자동 타이머) · 무응답 판정(K×N) · 전달 확인(T 내 `started`) · retained `<prefix>/state` · 원격 전송(`remote:<name>`). TUI 스크래핑은 주입·다이얼로그·진단에만 남는다.
- **워크트리 운영 모델 2단계 (Issue #21 항목 4·5·7)**: 워크트리 준비·해체 헬퍼(변경 전 판정, untracked 포함, 검증된 단일 `--force`), 리뷰 identity(라운드별 스냅샷·stale 재리뷰·승격 직전 재확인·`identity.json`), 수용 사례 A1–A8.
- **잡 예산·라벨·멈춤 알림 (Issue #33·#30)**: 위임 잡 예산은 `--job-timeout`/`MAM_JOB_TIMEOUT_S`, 벽시계 초과는 `wall_clock_timeout`(무응답 `deadline_timeout` 과 구분), `lib_py/stall_watch.py` 가 `blocked`/`idle` 을 `progress stalled:*` 로 알리기만 한다(종결 근거는 #18 의 프로토콜 이벤트뿐).
- **설정 파일 로더 하나 (Issue #26)**: `.mam.env` 는 `lib_py/delegation/envfile.py` 한 곳이 읽는다(셸 해석 없음, 환경변수 우선, 읽을 수 없는 파일은 오류). bash 산술에 들어가는 정수 설정값은 `mam_int` 로 10진수.
- **4-Way 버전 락스텝**: `lib.sh`(`MAM_VERSION`) ↔ `lib_py/loop/eager.py`(`FRAMEWORK_VERSION`) ↔ `VERSIONS.md` ↔ 8개 `SKILL.md`.
---
## 🧭 스킬 패키지 버전 매트릭스 (Skills Version Matrix)
모든 8개 스킬은 YAML frontmatter 메타데이터(`author`, `version`, `platforms`, `environments`) 표준화를 통해 `v4.8.0`로 동기화되어 배포됩니다.
모든 8개 스킬은 YAML frontmatter 메타데이터(`author`, `version`, `platforms`, `environments`) 표준화를 통해 `v4.8.1`로 동기화되어 배포됩니다.
| 스킬명 | 버전 | 역할 및 주요 책임 | 상태 |
| :--- | :---: | :--- | :---: |
| **`multi-agent-mux-create`** | `4.8.0` | 에이전트 세션 신규 생성 및 Herdr 컨테이너 격리 스폰 | ✅ 배포 |
| **`multi-agent-mux-stop`** | `4.8.0` | 대화 UUID 원자적 캡처 및 세션 안전 종료 (Graceful Stop) | ✅ 배포 |
| **`multi-agent-mux-resume`** | `4.8.0` | 온디스크 대화 컨텍스트 기반 Tier-1 초고속 세션 복원 | ✅ 배포 |
| **`multi-agent-mux-status`** | `4.8.0` | 실시간 Herdr 세션 및 레지스트리 드리프트 스냅샷 조회 | ✅ 배포 |
| **`multi-agent-mux-monitor`** | `4.8.0` | YAML ↔ 런타임 상태 간 자율 조정자 (Reconciler Loop) | ✅ 배포 |
| **`multi-agent-mux-delegate-job`** | `4.8.0` | MQTT 이벤트 채널 기반 비동기 단위 작업 위임 | ✅ 배포 |
| **`multi-agent-mux-loop`** | `4.8.0` | Planner-Creator-Reviewer 3자 자율 계획·실행·피어리뷰 루프 | ✅ 배포 |
| **`multi-agent-mux-orc-onboard`** | `4.8.0` | 오케스트레이터 UUID 격리 등록 및 서브 세션 오염 방지 | ✅ 배포 |
| **`multi-agent-mux-create`** | `4.8.1` | 에이전트 세션 신규 생성 및 Herdr 컨테이너 격리 스폰 | ✅ 배포 |
| **`multi-agent-mux-stop`** | `4.8.1` | 대화 UUID 원자적 캡처 및 세션 안전 종료 (Graceful Stop) | ✅ 배포 |
| **`multi-agent-mux-resume`** | `4.8.1` | 온디스크 대화 컨텍스트 기반 Tier-1 초고속 세션 복원 | ✅ 배포 |
| **`multi-agent-mux-status`** | `4.8.1` | 실시간 Herdr 세션 및 레지스트리 드리프트 스냅샷 조회 | ✅ 배포 |
| **`multi-agent-mux-monitor`** | `4.8.1` | YAML ↔ 런타임 상태 간 자율 조정자 (Reconciler Loop) | ✅ 배포 |
| **`multi-agent-mux-delegate-job`** | `4.8.1` | MQTT 이벤트 채널 기반 비동기 단위 작업 위임 | ✅ 배포 |
| **`multi-agent-mux-loop`** | `4.8.1` | Planner-Creator-Reviewer 3자 자율 계획·실행·피어리뷰 루프 | ✅ 배포 |
| **`multi-agent-mux-orc-onboard`** | `4.8.1` | 오케스트레이터 UUID 격리 등록 및 서브 세션 오염 방지 | ✅ 배포 |
---
## 📋 버전별 상세 변경 내역 (Changelog)
### 🚀 `v4.8.1` — Issue #26 `.mam.env` 를 Python 파서 하나로 읽고, 정수 설정값을 10진수로, 테스트를 로컬 MQTT 브로커로 (2026-10-02, PR #43)
> **패치 (PATCH Release)**: 같은 `.mam.env` 를 delegate-job 래퍼는 bash `source` 로, Python 도구는 `KEY=VALUE` 로 읽어서, 한쪽에서 정상인 줄(`KEY= value`)이 다른 쪽에서 래퍼를 즉시 종료시키고 값 속 `$(...)` 는 실행되던 문제(Issue #26)를 고친다. 0 으로 시작하는 정수 설정값이 bash 에서 8진수로 읽히던 문제와, 공개 MQTT 브로커에 기대던 테스트도 함께 정리했다.
#### 🌟 주요 개선 사항
1. **파서는 하나 (`lib_py/delegation/envfile.py`, 래퍼, `mqtt_common.py`)**: 주석·빈 줄 무시, 키와 값의 앞뒤 공백 제거, 감싸는 따옴표 한 쌍 제거, 셸 해석 없음. 키는 `[A-Za-z_][A-Za-z0-9_]*`. 형식이 어긋난 줄, `export` 접두어, NUL 이 든 줄, bash 자체 변수(`IFS`, `PS4`, `RANDOM`, `BASH_*` 등)는 값 없이 줄 번호로 경고하고 건너뛴다. 래퍼는 `source` 대신 파서가 만든 셸 인용 `export` 문을 eval 한다. 이미 있는 환경변수가 파일보다 우선한다(전에는 래퍼만 파일이 덮어썼다). 존재하지만 읽을 수 없는 파일은 오류다: 래퍼는 rc 1, Python 진입점은 `EnvFileError` 로 멈춘다.
2. **정수 설정값은 10진수 (`lib.sh` `mam_int`/`mam_int_knob`, `runner.py` `_positive_int`)**: `MAM_JOB_TIMEOUT_S=0700` 이 래퍼에서 448 초가 되던 문제. 한 규칙(ASCII 공백·숫자만, 10진수, 유효 9 자리 이하, 값별 최솟값)을 로케일과 무관하게 적용한다. 잘못된 환경변수는 경고 후 기본값, 잘못되거나 빈 값으로 명시한 플래그는 rc 1.
3. **테스트가 외부 브로커에 기대지 않는다 (`tests/_local_mqtt.py`)**: 공개 `broker.hivemq.com` 왕복에 기대던 테스트 22 개를 테스트 안의 로컬 MQTT 3.1.1 브로커로 옮겼다. "브로커에 닿지 않음" 건너뛰기는 실패가 됐고, 정적 검사가 공개 브로커 주소의 재유입을 막는다.
4. **문서**: `.mam.env.example` 머리말에 형식 규칙과 우선순위.
#### ✅ 품질 검증
- **신규 테스트**: `tests/test_issue26_envfile.py`(두 실제 로더의 같은 입력·같은 결과, 예약 변수, 읽기 실패·NUL, 래퍼에서 명령 미실행), `tests/test_issue26_ints.py`(래퍼·lib.sh·러너의 정수 규칙 표, 두 로케일), `tests/test_local_mqtt.py`(로컬 브로커의 3.1.1 적합성과 실제 publish_event → job_subscriber 경로).
- **리뷰 (병합 워크스페이스)**: 1회차(@b58edac) claude·agy PASS, codex NOT PASS(R1 읽을 수 없는 파일인데 래퍼가 rc 0 으로 기본값 진행, R2 로케일에 따라 bash·Python 의 정수 해석이 다름, R3 빈 값으로 명시한 정수 플래그가 검증을 우회, R4 NUL 이 든 값을 두 로더가 다르게 처리), grok 은 컨텍스트 압축 중 응답 시간 초과로 판정 없음(늦게 낸 리포트도 R1 과 같은 지적). 0eec795 에서 네 건과 claude 비차단 R1·R2(문서·메시지)를 고치고 회귀 테스트 8 건(모두 수정 전 코드에서 실패)을 추가. 2회차(@0eec795, grok 은 PR 전체) **4/4 PASS**. 네 리뷰어 모두 "읽을 수 없는 파일이면 Python 진입점도 멈춘다"에 동의. 리포트와 identity 사이드카는 `.agents/reports/<session>/`.
- **전체 스위트 (병합 워크스페이스, 브로커 환경변수 없이)**: 0eec795 전체 1315 passed / 1 failed / 3 skipped(60 분, MQTT 환경변수 없이). 실패 1건은 `test_issue21_acceptance.py::test_a8` 로 이 PR 과 무관한 날짜 의존 테스트 버그(main 에서도 같음, 아래 후속). 1회차 head b58edac 전체도 1302 passed / 같은 1건 실패. 공개 브로커 때문에 실패하거나 건너뛴 테스트 없음. PR 본문의 "purge 12건 기준 실패"는 이 호스트에서 재현되지 않음.
- **후속**: Python 진입점의 `EnvFileError` 를 트레이스백 대신 `ERROR:` 한 줄로(claude S1); 파일 첫 줄의 BOM 이 "잘못된 키"로 건너뛰어짐(grok); 한 파일 안 중복 키는 첫 값이 이김 — 문서화(grok); `MESSAGING.md` 의 "없는 `MAM_ENV_FILE` 은 오류" 설명이 실제(조용히 건너뜀)와 다름(grok); `MAM_WAIT_GRACE_S`·`MAM_CHILD_WAIT_S`·`MAM_JOB_TREE_MAX` 를 `_positive_int` 로(grok); `[ -ge ]` 전용 노브의 비숫자 값(claude R3); `mam_int` 와 플래그 검증을 #17 항목 4 이전 목록에(claude R5); `test_issue21_acceptance.py::test_a8` 가 매달 1~9 일에 실패 — 테스트가 마커에 쓰는 `ps -o lstart` 의 두 칸 공백(`Oct 1`)을 제품 코드처럼 한 칸으로 줄이지 않는다(제품 동작은 정상).
### 🚀 `v4.8.0` — Issue #33 위임 잡 예산 조절과 벽시계 라벨 분리, Issue #30 멈춘 에이전트 알림(알림 전용) (2026-09-26, PR #41)
> **마이너 마일스톤 (MINOR Release)**: 위임 잡의 벽시계 예산(기본 3600 초)을 조절할 수 없고 벽시계 초과와 무응답이 같은 `deadline_timeout` 으로 기록되던 문제(Issue #33)와, 살아 있지만 멈춘 에이전트(권한 확인 창에 막힘, 종결 이벤트 없이 턴 종료)를 잡 제한 시간이 지나야만 알 수 있던 문제(Issue #30)를 한 브랜치로 고쳤다. 새 모듈 `lib_py/stall_watch.py`, 루프 옵션 `--job-timeout`, 새 종결 사유 `wall_clock_timeout`, 구독자 종료 코드 4 가 추가되어 MINOR 로 올린다. 예산 **연장**은 범위에서 빼고 #39(에이전트가 프로토콜 이벤트로 요청)로 분리했다.