- Replace import-time LOGS_DIR cwd binding with dynamic get_logs_dir() function - Implement PEP 562 __getattr__ and __dir__ for transparent LOGS_DIR backward compatibility - Update audit-log callers in mqtt_common.py and registry.py to use dynamic resolution - Add 5 regression guards in tests/test_tier1_unit.py (276/276 PASS) - Update IMPROVEMENTS.md, VERSIONS.md, registry.md, and include plan and peer review reports
331 lines
43 KiB
Markdown
331 lines
43 KiB
Markdown
# 🛠️ Multi-Agent Mux 종합 개선 및 미해결 과제 백로그 (`IMPROVEMENTS.md`)
|
||
|
||
- **최종 갱신일**: 2026-08-17 (B-9 감사 로그 루트 지연 평가 완료, B-13/Stage 2 완료, B-10 완료, B-5 종결, C-6 완료, 전체 276/276 회귀 통과 반영)
|
||
- **통합 관리 대상**: 기존 `CODEBASE_REVIEW_REPORT.md` + `OPTIMIZATION.md`
|
||
- **총 추적 미해결 과제**: **1건** (아키텍처 1건, 엣지케이스 0건, 오케스트레이션 0건, 레거시 잔재 0건)
|
||
- **완료된 과제**: **24건** (A-1, A-3, A-4, A-5, B-1, B-3, B-4, B-5, B-7, B-8, B-9, B-10, B-13, C-1, C-2, C-3b, C-6, O-1, O-2, O-3, O-4-OrcOnboard, Herdr-0.8.0-Compat-SanitizeHash, P2-1-DelegateJobSafe-TrapFix, P2-2-C3a-C4-LegacyCleanup)
|
||
|
||
---
|
||
|
||
## 📌 개요
|
||
|
||
본 문서는 Multi-Agent Mux (MAM) 프레임워크의 **코드베이스 아키텍처 결함, 런타임 엣지케이스, 레거시 잔재** 및 **`/multi-agent-mux-loop` 오케스트레이션 최적화 과제**를 단일 백로그로 통합 추적하기 위한 종합 관리 문서입니다.
|
||
|
||
---
|
||
|
||
## 1. 🔴 아키텍처 결함 (Architecture Flaws — 1건)
|
||
|
||
### **A-2: 공개 브로커 + HMAC 인증 Off + 와일드카드 전파**
|
||
- **현상**: `mqtt_common.py`의 기본 브로커가 공개 서버(`broker.hivemq.com`)이고, 잡 생성 시 `auth_token` 이 **한 번도 발급되지 않아**(실측 26/26 잡이 `auth_token=None`) `verify_hmac` 의 `if not auth_token: return True` 경로가 항상 타집니다. 발행자는 워크스페이스 지문 토픽을 채택하지 않고 전역 `python/mqtt/jobs/<job_id>/events` 로 발행하며, `reconcile.sh:237` 이 같은 전역 토픽을 구독합니다. (HMAC 구현 자체는 정상입니다 — 토큰이 없어 검증이 공허해지는 것이 원인입니다.)
|
||
- **파급 효과**: 외부에서 유입되는 malicious `error` 이벤트 수신 시 `reconcile.sh`가 라이브 에이전트 pane을 `kill-session`으로 강제 파괴하는 치명적 보안/안정성 위험이 존재합니다.
|
||
|
||
### **A-4 (✅ 완료 — P3-1): 에이전트 지식 산재 — `BaseAgentAdapter` 어댑터 계층 도입 (Rev.2)**
|
||
|
||
> 결함 조치가 아니라 **구조 개선 제안**입니다. 상세 설계·실측 근거는 `.mam/jobs/44062a63/claude-reports/report-final.md` 및 `744ac67a` 를 참조하십시오.
|
||
|
||
- **현상**: "claude 의 transcript 는 어디 있나", "cline 재개 argv 는 무엇인가" 같은 **에이전트에 대한 사실**이 스크립트 8개 · **34개 팬아웃 지점**에 흩어져 있습니다. (8줄 윈도 안에 4개 에이전트 중 3개 이상이 등장하는 지점 기준: `create_session.sh` 8, `reconcile.sh` 7, `stop_session.sh` 6, `lib.sh` 4, `resolve_session_id.sh` 3, `resume_session.sh`/`update_yaml_resumed.sh`/`run_loop.sh` 각 2)
|
||
- **사본 현황**: `agent → *_id_own` 키 맵 **4벌**, `~/.claude/projects` 17참조, `antigravity-cli/conversations` 11참조, `.hermes/state.db` 6참조, `.cline/data/sessions` 5참조.
|
||
- **파급 효과**: 같은 질문에 **서로 다른 답**이 공존합니다. 세션명→에이전트 추론이 `reconcile.sh::row_agent`(pane.cmd → cmd_full → 이름 접미사)와 `run_loop.sh:236-243`(세그먼트 매칭 + 실패 시 `claude` 기본값) 두 벌로 존재하며 후자는 오판 가능합니다. b4a1d094 에서 드러난 "격리 분기 inert" 결함도 아티팩트 경로 규칙이 두 벌이었던 데서 비롯됐습니다.
|
||
|
||
#### 설계 요지 (Rev.2 갱신)
|
||
- **`.agents/skills/mam_agents/`** 패키지(약 484줄): `base.py`(ABC + `SpawnSpec` + `DiscoveryContext`), `registry.py`(정적 레지스트리), `__main__.py`(셸 브리지), `adapters/{claude,agy,hermes,cline}.py`.
|
||
- **인터페이스**: `own_key` / `supports_assigned_id` / `ready_tokens` 속성 + `auth_ok(run)` · `spawn_spec()` · `resume_spec(binary, uuid, materialized)` · `artifact_path(uuid, ctx)` · `verify_artifact(uuid, ctx)` · `discover(ctx)`.
|
||
- **`DiscoveryContext` & `discover()` 템플릿 메서드**: `cwd`(물리 절대경로), `ws_key`, `home`, `claude_dir`, `iso_root`, `epoch`, `claimed` 필드를 객체 하나로 캡슐화. `_raw_candidates(ctx)` 추상 메서드로 어댑터별 물리 탐색만 서술하고 `claimed`/`epoch` 필터는 기반 클래스 템플릿이 100% 보장.
|
||
- `auth_ok` 는 서브프로세스 실행자를 **주입**받아 CLI 미설치 환경에서도 단위 테스트가 가능합니다(hermes 는 현재 미설치).
|
||
- `resume_spec` 의 `materialized` 파라미터가 b4a1d094 규칙(`claude -r <미실현 uuid>` 실패 → `--session-id`)을 흡수합니다.
|
||
- `ready_tokens` 속성을 어댑터로 내보내 `wait_for_tui_ready` 의 25줄 inline shell `case` 블록을 단 1줄의 `grep -E -q "$MAM_READY_TOKENS"` 로 축소.
|
||
- **레지스트리 패턴**: **정적 dict 채택.** `entry_points` 는 MAM 이 `pip install` 되지 않고 `rsync`/`cp` 로 배포되므로 부적합, 디렉터리 스캔은 "0개 발견"과 "에이전트 미설치"가 구분되지 않아 부적합.
|
||
- **bash↔python 브리지**: `python -m mam_agents facts <agent>` 가 `shlex.quote` 된 `KEY=value` 를 출력. **스크립트당 1회 `eval`** 이 계약입니다(실측 22.8 ms/호출 vs bash `case` 2.3 ms — 분기마다 호출하면 안 됨).
|
||
|
||
#### 실현 가능성 및 부트스트랩 (Rev.2 실측)
|
||
- 파이썬 진입점 **3종 전부**에서 import 확인: `env_python`, `atomic_dump_yaml`(flock 쓰기 경로), venv 없는 **맨 `/usr/bin/python3`**.
|
||
- **`lib.sh` source 시점 1회 `export PYTHONPATH`**: `lib.sh` 로드 시 `_mam_export_pythonpath` 가 `mam_skills_dir` 을 `PYTHONPATH` 에 자동 얹어 `run_loop.sh` 등 셸 상의 모든 `python3 -c` 호출이 한 번에 호환됨.
|
||
- herdr shim 내부 `python3 -c` **9곳 전부 에이전트 지식 0** → shim 경계가 이미 올바른 위치에 있습니다.
|
||
- **제약(규칙화 필요)**: 어댑터는 **표준 라이브러리만** 사용해야 합니다. 서드파티 의존성이 들어오면 venv 없는 경로가 깨집니다.
|
||
|
||
#### 선행 필수 체크리스트 (누락 시 조용히 업그레이드가 막힘)
|
||
1. **`deploy/remove.sh:83-91` `fallback_assets` 에 `".agents/skills/mam_agents"` 등록.**
|
||
미등록 시 `tests/test_deploy_freshness.py::test_d2` 가 실패하며(프로토타입에서 실제 발생), 언인스톨 후 잔존 자산이 워크스페이스를 **영구히 구버전에 고정**시킵니다(`install.sh` 는 비-스킬 자산을 "없을 때만" 복사).
|
||
2. `deploy/install.sh` 무결성 자산 목록 등록.
|
||
3. `deploy/gitea-ci.yml:69-77` 의 `flake8` / `py_compile` 경로 추가 — 현재 CI 파이썬 잡은 `multi-agent-mux-delegate-job/scripts/` 만 검사하므로 신규 패키지는 린트 사각지대입니다.
|
||
|
||
#### 단계적 이행 (각 단계는 셸 사본 제거를 같은 커밋에 포함)
|
||
| 단계 | 내용 |
|
||
|---|---|
|
||
| M0 | 패키지 골격 + `lib.sh` source 시점 `PYTHONPATH` export + 배포/CI 등록 |
|
||
| M1 | `own_key` / `agent_of_row` 이관 — **프로토타입 검증 완료: 팬아웃 34 → 29** |
|
||
| M2 | `artifact_path` + `verify_artifact` (`verify_session_uuid` 4분기, `DiscoveryContext` 적용, 격리 경로 일원화) |
|
||
| M3 | `spawn_spec` / `resume_spec` / `auth_ok` (create·resume argv 및 프리플라이트) |
|
||
| M4 | `discover()` (raw candidates + base class template filter) — hermes DB 스키마 실측 선행 |
|
||
| M5 | `stop_session.sh` purge 경로 및 exit key |
|
||
| M6 | `ready_tokens` 어댑터 이관 (`wait_for_tui_ready` 25줄 case 제거) |
|
||
| M7 | claude ready tokens 에서 `projects` 제거 및 자체 검증 분리 커밋 |
|
||
|
||
- **정직한 상한**: 34 → **약 10**. 남는 약 10곳은 셸 상주 TUI·프로세스 제어(`send_keys_safe` 의 agy/claude/cline 분기, `handle_startup_dialogs`, spawn 래퍼 분기, `pgrep -P` 자식 pid 게이트)로 이 추상화의 대상이 아닙니다.
|
||
- **중단 기준**: M2 이후에도 팬아웃이 29 → 20 이하로 떨어지지 않으면 중단하고 잔여 단계를 재검토합니다.
|
||
- **검증 상태**: Rev.2 프로토타입 기준 전체 회귀 **162 passed (회귀 0)**, 변이 6/6 검출, 배포 스위트 25/25, `py_compile` 통과.
|
||
|
||
---
|
||
|
||
## 2. 🟠 엣지 케이스 및 런타임 버그 (Edge-case Bugs — 0건 — 전원 완료)
|
||
|
||
---
|
||
|
||
## 3. 🟡 오케스트레이션 최적화 과제 (Orchestration Optimizations — 0건 — 전원 완료)
|
||
|
||
---
|
||
|
||
## 4. ⚪ 레거시 잔재 및 죽은 코드 (Legacy Remnants — 0건 — 전원 완료)
|
||
|
||
---
|
||
|
||
## 5. 🎉 완료된 과제 (Completed Tasks — 24건)
|
||
|
||
### **B-9 (P4-1): `LOGS_DIR` import 시점 cwd 고정 해소** — ✅ 완료
|
||
- `mqtt_common.LOGS_DIR` 이 모듈 import 시점의 `os.getcwd()` 로 절대화되어, 이후 프로세스가 `chdir` 하면 감사 로그가 옛 경로에 계속 쌓이던 문제를 해소했습니다(실측 재현). 경로 해석을 호출 시점으로 미루는 `get_logs_dir()` 를 도입하고 모듈 전역 대입을 제거했습니다.
|
||
- **하위 호환**: PEP 562 모듈 `__getattr__` 로 `mqtt_common.LOGS_DIR` 속성 접근을 그대로 유지하되 동적으로 평가합니다. 저장소 내 `from mqtt_common import LOGS_DIR` 사용은 0건임을 전수 확인했으므로 호환 표면이 100% 덮입니다.
|
||
- **가시성 & 탐색성**: PEP 562 `__dir__` 을 함께 정의해 `dir(mqtt_common)` 및 탭 완성에서 `LOGS_DIR` 이 계속 보이도록 했습니다(`hasattr` 은 `__getattr__` 만으로도 동작하므로 별개입니다).
|
||
- **부수 개선**: `DELEGATE_JOB_LOGS_DIR` 환경변수가 이제 실행 중 변경까지 반영됩니다(종전에는 import 이후 변경이 무시되었습니다).
|
||
- 같은 파일의 `DEFAULT_REGISTRY_DIR` 은 상대 문자열로 남아 있어 애초에 이 결함이 없었습니다 — B-9 의 본질은 "함수가 아니라 **절대화 시점**"이었습니다.
|
||
- 회귀 가드 5종을 신설했습니다. 감사 로그 계층은 best-effort `except Exception` 으로 예외를 삼키므로, 잘못된 수정은 **무음 로그 소실 + 전 테스트 통과**로 나타납니다(실측). 이에 가드 하나는 문자열이 아니라 **실제 파일 생성**을 단언하도록 설계했습니다.
|
||
|
||
### **B-13 (Stage 2): 셀프 호스팅 루프 런타임 프리즈 스냅샷** — ✅ 완료
|
||
- 루프 기동 시 `.agents/skills/` 를 `$TMPDIR` 의 임시 디렉터리에 1회 동결하고 그 스냅샷에서 재실행(`exec`)하도록 하여, 턴 도중 Worker 가 프레임워크 스킬을 편집해도 진행 중인 루프가 영향을 받지 않게 했습니다. 상태·저장소 경로는 `MAM_REAL_ROOT`/`WORKSPACE_ROOT` 로 실제 루트를 계속 가리키므로 레지스트리·락·diff 수집 동작은 종전과 동일합니다.
|
||
- **계층 B 신규 대응**: bash 가 실행 중인 스크립트를 바이트 오프셋 기준으로 계속 읽는다는 사실을 실측 확인하여(정상 교체본에도 `unexpected EOF` 발생), 래퍼뿐 아니라 `run_loop.sh` 본체까지 동결 대상에 포함했습니다.
|
||
- **B-6 과의 구분**: B-6 이 제거한 것은 *위임 매 호출마다 스킬 트리 내부에* 만들던 `.tmp` 사본이고, 본 조치는 *기동 시 1회 트리 외부에* 만드는 스냅샷입니다. 스킬 트리에는 아무것도 쓰지 않으며 기존 가드 `test_z9_no_tmp_copy_left_in_skill_tree` 가 그대로 통과합니다.
|
||
- **결함 교정 (P1/C1/C2)**: 인자 파서의 `$@` 소진에 대비해 최상단에서 `MAM_LOOP_ARGV` 배열 포획, `export MAM_LOOP_FREEZE_OWNED="1"` 로 정리 게이트 누수 차단, `log_*` 정의 전 구간 `echo` 직접 사용으로 폴백 시의 구문 오류 크래시를 원천 방지했습니다.
|
||
- 정리 로직은 새 트랩을 추가하지 않고 기존 `_mam_release_guard` 를 확장했습니다 — `trap … EXIT` 중복 설치는 기존 핸들러를 조용히 대체하며(실측), 이는 B-12 와 동일한 계열의 사고입니다.
|
||
- 회귀 가드 5종(`test_b13_reexec_preserves_original_argv`, `test_b13_freeze_survives_broken_wrapper`, `test_b13_freeze_dir_is_outside_the_skill_tree`, `test_b13_release_guard_cleans_up_and_releases_lock`, `test_b13_no_freeze_switch_disables_reexec`)을 신설하고 뮤테이션 M0~M6 으로 방어력을 검증했습니다.
|
||
|
||
### **B-10 (P3-2): `agent_identities` tier-3 신원 캐시 완전 제거 (Option A)** — ✅ 완료
|
||
- 저장소 전체에 `agent_identities` 쓰기 코드가 0건임을 재확인하고(라이브 `.db` 최상위 키에도 부재), 구조적으로 히트 불가였던 읽기 경로 3곳을 제거했습니다 — `workspace_uuid.py` tier-3 폴백(28줄), `reconcile.sh` drift D 진단(35줄), `stop_session.sh` purge 시 캐시 소거(6줄), 관련 주석 3곳. UUID 해결은 tier-1(per-row own id) → tier-2(어댑터 `discover()`) 2단계로 단순화되었습니다.
|
||
- **PyYAML 의존 — 실행 경로 기준으로 해소**: `verify_session.py::mam_orchestrator_uuids` 가 `yaml` 을 함수 진입 즉시 import 하고 있어(`:10`), tier-3 을 지워도 UUID 해결 경로는 PyYAML 을 요구했습니다. `state.py` 의 기존 선례대로 YAML 폴백 분기 안으로 이동시켜 교정했습니다.
|
||
- **정정**: 원 항목이 서술했던 "`lib.sh` 의 PyYAML 하드 의존" 은 `load_state_json` 이 `state.py` 로 이관되며 **이미 해소된 상태**였습니다. 한편 `atomic_yaml.py` 는 모듈 존재 이유상 앞으로도 최상단에서 import 하므로 **저장소 차원의 PyYAML 요구와 설치 게이트는 유지**됩니다.
|
||
- 회귀 가드 3종(`test_b10_no_agent_identities_reader_in_production`, `test_b10_workspace_uuid_has_no_yaml_import`, `test_b10_find_workspace_uuid_runs_without_pyyaml`)을 신설하고 뮤테이션 5종(M1·M2·M3a·M3b·M4)으로 방어력을 검증했습니다.
|
||
|
||
### **B-5: macOS NFS 감지 `df -P` 폴백 검증 및 종결** — ✅ 완료 (종결)
|
||
- `_check_is_nfs`(`lib.sh:1181-1192`)에서 macOS/BSD 환경 시 GNU 전용 `df --output=target` 실패(`rc=64`)에 대비한 `df -P "$f" | tail -1 | awk '{print $6}'` POSIX 폴백이 정상 동작함을 실측 및 단위 테스트(`test_stop_check_is_nfs_local`)로 검증 완료하여 종결 처리했습니다.
|
||
|
||
### **C-6 (P2-3): `stop_session.sh` 레거시 주석 및 구버전 사용법 정리** — ✅ 완료
|
||
- 헤더 주석이 광고하던 `--mode soft|hard` / `--capture-id` / `--graceful` 3종은 파서가 `exit 2` 로 거부하는 폐지 플래그였습니다. 헤더 29줄을 현재 CLI 에 맞게 교체하고, `usage()` 에 누락돼 있던 옵션 설명과 `--agent` 접미사 추론 동작을 보강했으며, Option B 이후 무의미해진 "워크스페이스에 격리된" 표현과 내부 주석 3곳의 플래그 표기를 정리했습니다.
|
||
- `MESSAGING.md` 상태 표가 제거된 플래그로 `stopped`/`terminated` 를 정의하던 것을 교정하고, 생산자가 사라진 `archived` 를 레거시 값으로 명기했습니다.
|
||
- 도움말과 파서의 일치를 강제하는 회귀 가드 `test_comp_stop_usage_matches_parser` 를 신설하고 뮤테이션 3종(M1~M3)으로 방어력을 검증했습니다 — C-6 은 문서 과제라 기존 테스트가 전혀 잡지 못하던 영역입니다.
|
||
|
||
### **P3-1 (A-4 Phase 2 / Option B / C-3b / M2~M7): 에이전트 지식 계층 어댑터 일원화 및 isolation.root 완전 폐기** — ✅ 완료
|
||
- 에이전트별 아티팩트 경로, 검증 로직, 재개/시작 스펙, 토큰, 종료 키, 인증(`auth_ok`), 자동 발견(`discover`)을 `BaseAgentAdapter` 및 4개 구체 어댑터(`claude`, `agy`, `hermes`, `cline`)로 이관하고, CLI facts bridge(`shlex.quote`) 및 서브커맨드(`spawn-spec`, `resume-spec`, `exit-key`)를 구축했습니다.
|
||
- Universal Global Config 전환 후에도 남아있던 `isolation.root` 4개 소비자(`lib.sh`, `verify_session.py`, `workspace_uuid.py`, `stop_session.sh`, `atomic_yaml.py`)를 완전 폐기(Option B)했습니다.
|
||
- 전용 계약 테스트 스위트 `tests/test_a4_adapter_contract.py` (9/9 PASS) 및 전체 회귀 테스트 **259/259 PASS (100%)** 를 달성했습니다.
|
||
|
||
### **P2-2 (C-3a / C-4): 격리 빈 스텁 4종·공허한 테스트 4건·미사용 심볼 3종 제거** — ✅ 완료
|
||
- `.agents/skills/lib.sh` 의 백워드 호환 빈 스텁 `provision_isolation` / `isolation_lever` / `isolation_env_prefix` / `isolation_cmd_args` 4종(프로덕션 호출자 0건)을 제거하고, 주석 블록에 C-3b(`isolation.root` 행 필드) 경계를 명시해 후속 정리 시 오삭제를 차단했습니다.
|
||
- 위 스텁의 빈 출력만 재확인하던 공허한 테스트 4건(`tests/test_tier1_unit.py` 3, `tests/test_tier2_component.py` 1)을 제거하고, 그 자리에 `--isolate`/`--no-isolate` 레거시 no-op 플래그의 인자 파서 계약을 고정하는 `test_create_session_legacy_isolate_flags_noop` 1건을 신설했습니다. 신규 테스트는 분기 삭제·한쪽만 삭제·조용한 no-op 화·usage 문서 줄 삭제 4종 변이를 모두 검출함을 변이 검사로 입증했습니다. `test_tier1_unit.py:31` 섹션 헤더도 `(5 Test Cases)` 로 동기화했습니다.
|
||
- 참조 0회 미사용 심볼 3종을 제거했습니다: `_REAL_HERDR_PATH`(`lib.sh:126-127`, 대입+export만 — `_resolve_real_herdr_path` 의 stdout/rc 반환 채널은 불변임을 실측 확인), `TERMINAL_STATUSES`(`registry.py:38`, `__all__` 미포함으로 임포트 계약 불변), `ISOLATE`(`create_session.sh:57`, `set -u` 하 숨은 확장 불가능).
|
||
- `_HERDR_SHIM_DIR_PATTERN` / `_HERDR_SKILLS_BIN_PATTERN`(`lib.sh:83-84` → `:105` 사용 중), `VALID_STATUSES`(`registry.py:150-151` 사용 중), `--isolate`/`--no-isolate` 레거시 호환 분기, C-3b 소비자 4곳은 계획대로 미접촉입니다.
|
||
- 전체 회귀 **256/256 PASS (100%)** 로 입증했습니다 (259 → 256, 순감 3 = 제거 4 − 신설 1).
|
||
|
||
### **P2-1 (B-6 / B-12): `delegate_job_safe` 임시 사본 제거 및 서브셸 루프 락 조기 해제 차단 조치** — ✅ 완료
|
||
- `.agents/skills/multi-agent-mux-loop/scripts/run_loop.sh` 내 `delegate_job_safe` 가 `.agents/skills/...` 경로 내에 `.tmp` 사본을 생성하던 방식을 제거하고 원본 래퍼 스크립트를 인플레이스로 직접 실행(`bash "$orig_script" "$@"`)하도록 개선하여 버전 관리 트리 오염 및 rsync 배포 유출(B-6)을 완전히 해소했습니다.
|
||
- 명령 치환(`$(delegate_job_safe ...)`) 서브셸 내에 설치되던 `trap _mam_release_guard EXIT` 로 인해 첫 번째 위임 잡 종료 시점에 `.mam/loop-guard-active` 마커가 삭제되어 O-3 Scoped Guard 및 O-2 락이 무력화되던 인접 P0 결함(**B-12 / D1**)을 로컬 트랩 제거를 통해 근본 해결했습니다.
|
||
- 래퍼 스크립트 실행 실패 시 도달 불가능하던 에러 진단을 `delegate_job_safe` 내부에서 직접 표준오류로 출력(`log_error "delegate_job_safe failed (exit $rc)..."`)하도록 진단 로깅을 보강했습니다.
|
||
- `tests/test_o3_scoped_guard.py` 내 Z-9 테스트를 4개 세부 행위 기반 테스트(`test_z9_loop_lock_survives_delegation`, `test_z9_probe_detects_the_defect`, `test_z9_no_tmp_copy_left_in_skill_tree`, `test_z9_exit_code_and_diagnostics_propagation`)로 교체 검증했습니다.
|
||
|
||
### **multi-agent-mux-orc-onboard: 오케스트레이터 온보딩 스킬 및 `orchestrator_uuids` 배제 게이트 조치** — ✅ 완료
|
||
- `.agents/skills/multi-agent-mux-orc-onboard/` 스킬 및 `.agents/skills/multi-agent-mux-orc-onboard/scripts/orc_onboard.sh` 헬퍼 모듈을 생성하여, 메인 오케스트레이터가 프로젝트 맥락 파악 시 자신의 대화 UUID를 포착해 `.mam/agent-sessions.yaml` 및 SQLite DB 내 `orchestrator_uuids` 리스트로 원자적 기록하는 구조를 구축했습니다.
|
||
- `.agents/skills/lib.sh` 내 `find_workspace_uuid` 및 `verify_session_uuid` 함수를 갱신하여 `orchestrator_uuids` 리스트에 포함된 오케스트레이터 대화 ID를 서브 에이전트(`canary-projects-multi-agent-mux-creator-agy`)의 `find_workspace_uuid` 및 `capture_conversation_id` 탐색 대상에서 100% 스킵(Skip)하는 배제 게이트를 수립하여 오케스트레이터 대화 DB 오염 및 SQLite DB 락 결함을 원천 해결했습니다.
|
||
- 전용 회귀 테스트 스위트 `tests/test_orc_onboard.py` (40/40 PASS)를 작성하여 입증했습니다.
|
||
|
||
### **P0-2 (O-2): 동일 워크스페이스 내 중복 루프 기동 방지 원자적 락 및 마커 소유권 대조 삭제 조치** — ✅ 완료
|
||
- [`.agents/skills/multi-agent-mux-loop/scripts/loop_lock.sh`](file:///Users/godopu16/PuKi/laa/canary_projects/multi-agent-mux/.agents/skills/multi-agent-mux-loop/scripts/loop_lock.sh) 헬퍼 모듈을 작성하여, `set -C` (noclobber) 기반 원자적 락 생성 및 마커 임시 쓰기+Atomic Rename 구조를 구축했습니다.
|
||
- 마커 상의 `pid` + `lstart`(프로세스 시작시각) 신원 대조 검증을 수행하여, 동일 워크스페이스 내 중복 루프 기동 시 이를 감지하고 안전하게 기동을 차단합니다.
|
||
- 종료 트랩(`_mam_release_guard`) 시 마커 파일 상의 `pid` 및 `lstart` 가 자기 자신과 100% 일치할 때만 마커를 삭제하도록 소유권 대조 삭제를 수립하여, 타 루프 인스턴스의 마커를 실수로 제거하여 O-3 가드레일을 무력화시키는 결함을 원천 차단했습니다.
|
||
- 전용 회귀 테스트 스위트 `tests/test_o2_race_free_lock.py` (22/22 PASS) 및 전체 회귀 테스트 스위트 (46/46 PASS)를 작성하여 입증했습니다.
|
||
|
||
### **P0-1 (B-7): `run_loop.sh` 루프 기동 외곽 diff 누락 및 신규 미추적 파일 캡처 결함 조치** — ✅ 완료
|
||
- `.agents/skills/multi-agent-mux-loop/scripts/diff_collect.sh` 헬퍼 모듈을 작성하여, `run_loop.sh` 가 어느 CWD 에서 기동되더라도 항상 `$REPO_ROOT` 기반으로 안전하게 이동하여 `git diff` 를 수행하도록 CWD 독립성을 확립했습니다.
|
||
- Git 인덱스를 오염시키는 `git add -N` 대신, `git ls-files -o --exclude-standard -z` 와 `git diff --no-index --binary /dev/null "$f"` 구문을 조합하여 에이전트가 **새로 생성한 신규 미추적 파일(Untracked Files)까지 100% diff에 안전하게 병합**시키는 기법을 구현했습니다.
|
||
- diff 가 500줄 또는 30KB 를 초과할 경우 `--stat` 요약으로 전환하되, **리뷰어 프롬프트에 `[WARNING: Truncated]` 경고 태그를 명시적으로 노출**하여 감춰진 PASS 판정을 원천 차단했습니다.
|
||
- 멀티에이전트 자율 오케스트레이션 루프(`run_loop.sh --plan --all-reviewer`)를 통해 Planner(`claude`), Creator(`agy`), Reviewer(`cline`) 3자에 의해 구현 및 교차 검증 후 **`[VERDICT: PASS]` (만장일치 통과)** 되었습니다.
|
||
- 전용 회귀 테스트 스위트 `tests/test_b7_diff_untracked.py` (20/20 PASS)를 작성하여 입증했습니다.
|
||
|
||
### **Rev.2 (b4a1d094): 생성 시 세션 ID 자동 할당 및 Reconciler 고정/경로 정규화 프로토콜** — ✅ 완료
|
||
- 신규 `claude` 세션 생성 시 `mam_gen_uuid`로 UUID를 즉시 생성하여 `--session-id <uuid>`로 전달하고, `session_id_source: assigned`, `session_id_verified: false`로 등록하는 원자적 고정 구조를 구축했습니다.
|
||
- 첫 사용자 메시지 전달 시 디스크 트랜스크립트 `.jsonl` 생성을 모니터 루프(`reconcile.sh` drift C0)가 감지하고 `session_id_verified: true`, `last_visible_status: pinned`로 고정시킵니다.
|
||
- 미할당 다수 후보 발견 시 무작위 고정을 금지하고 `C-ambiguous` 상태를 명확히 보고하도록 강화했습니다.
|
||
- 심볼릭 링크/트레일링 슬래시/상대경로 계산 시 `mam_abs_workspace` 및 `mam_workspace_key` (`cd -P && pwd -P` / `os.path.realpath`) 경로 정규화를 전수 적용하여 100% 키 일치성을 확립했습니다.
|
||
- 전용 단위/통합 테스트 스위트 `tests/test_uuid_target.py` (13/13 PASS) 및 전체 회귀 테스트 스위트를 검증 완료했습니다.
|
||
|
||
### **B-4: 시프트 `ls`의 `created` 동적 POSIX 타임스탬프 복원 및 재개 가드 정상화** — ✅ 완료
|
||
- `.agents/skills/lib.sh` 554번 라인의 `999999` 하드코딩 출력을 제거하고, real herdr 또는 `.mam/agent-sessions.yaml` 에 기록된 세션 생성 시각(`created`/`created_at`/`created_epoch`) 및 동적 POSIX 타임스탬프(`int(time.time())`)를 리턴하도록 정제했습니다.
|
||
- `reconcile.sh` drift-B 감지 시 epoch 0 및 `1970-01-01` 오기록 결함을 차단하여 `find_workspace_uuid` 재개 가드가 정상 작동하도록 해결했습니다.
|
||
- 멀티에이전트 자율 오케스트레이션 루프(`run_loop.sh --plan --all-reviewer`)를 통해 Planner(`claude`), Creator(`agy`), Reviewer(`cline`) 3자에 의해 구현 및 교차 검증 후 **`[VERDICT: PASS]` (만장일치 통과)** 되었습니다.
|
||
- 전용 회귀 테스트 스위트 `tests/test_b4_session_created.py` (21/21 PASS)를 작성하여 입증했습니다.
|
||
|
||
### **O-2: 동일 워크스페이스 내 중복 루프 기동 방지 락 (Race-Free Mutex & Ownership)** — ✅ 완료
|
||
- `loop_lock.sh` 독립 락 모듈(`mam_acquire_loop_lock` / `mam_release_loop_lock`)을 생성하고 하드링크(`ln`) 기반 원자적 패키징 쓰기를 구현하여 빈/파티셜 마커 노출 및 Livelock 을 원천 차단했습니다.
|
||
- `pid` + `lstart`(프로세스 시작 시각) 기반 신원 검증 로직을 적용하여 PID Rollover 오판을 차단하고, stale 락 회수 시 마커 규약과 동일한 `steal_lock` (`$marker.steal`) 신원 인수 디스패처를 구축하여 고아 디렉터리로 인한 영구 워크스페이스 데드락 결함을 근본 해결했습니다.
|
||
- 이전 Rev.1 레거시 `.steal` 디렉터리 자동 정리 업그레이드 경로 및 소유권 검증 기반 원자적 해제(`mam_release_loop_lock`)를 통합하여 이차 루프 종료 시 소유권 없는 마커 파기를 차단하고 O-3 위임 가드를 완벽 보호했습니다.
|
||
- 전용 테스트 스위트 `tests/test_o2_race_free_lock.py` (22/22 PASS) 및 전체 회귀 테스트 스위트 (204/204 PASS)를 작성하여 입증했습니다.
|
||
|
||
### **O-3: 조건부 오케스트레이션 위임 가드 (Invocation-Aware Scoped Guard)** — ✅ 완료
|
||
- Normal Mode(직접 소스 수정)와 Loop Active Mode(`/multi-agent-mux-loop` 인보크 시 `run_loop.sh` 자율 위임)의 역할 경계를 명확히 구분하는 스킬 인터셉터 가드레일(`.agents/hooks.json` & `.agents/hooks/loop_delegation_guard.sh`)을 구축했습니다.
|
||
- step-type 파생명 매처(`file_change|edit_notebook|write_blob`)를 적용하여 가드 무발화 결함을 방지했습니다.
|
||
- `pid` + `lstart`(프로세스 시작시각) 신원 대조 검증을 통해 PID Rollover 및 `PermissionError` 시 발생할 수 있는 Livelock 영구 차단 오판을 완벽히 해결했습니다.
|
||
- `run_loop.sh` 마커 기록 및 `delegate_job_safe` 트랩 복원(`_mam_release_guard`)을 완료했습니다.
|
||
- `AGENTS.md`, `MULTI_AGENT_RULES.md` (.ko.md), `SKILL.md` 문서를 전수 대칭 갱신했습니다.
|
||
- 전용 단위/회귀 테스트 스위트 `tests/test_o3_scoped_guard.py` (22/22 PASS)를 수립하여 입증했습니다.
|
||
|
||
### **A-1: 워크스페이스 세션 격리 & drift-B 오등록 방지** — ✅ 완료
|
||
- `derive_workspace_slug` 헬퍼 함수를 추가하여 워크스페이스 경로 기반 단일 소켓 슬러그(`mam-<parent>-<work>`) 도출 체계를 구축했습니다.
|
||
- `reconcile.sh` drift-B 자동 등록 시 foreign cwd 차단 게이트를 구축하여 세션 오등록을 방지했습니다.
|
||
|
||
### **A-3: 시프트 버퍼 동시 주입 오염 & 자동 GC 체계 구축** — ✅ 완료
|
||
- `lib.sh` 내 `send_keys_safe` 시프트 버퍼 명령의 임시 파일명을 `sks_${sess}_${job_id}_$$_${RANDOM}_$(date +%s%N)` 식 호출 단위 독립 토큰으로 변환하여 다중 에이전트 동시 주입 시 대화 교차 오염 및 무음 유실(T5)을 원천 차단했습니다.
|
||
- `set-buffer` 시 원자적 임시 쓰기(`.$buf.$$.tmp`) 및 rename(`mv -f`) 구조를 구현하여 파티셜 레코드 관측을 방지했습니다.
|
||
- 인터럽트/예외 종료 시 남는 stale 버퍼 파일을 자동으로 정리하는 60분 내장 GC(`find -mmin +60 -delete`)를 내장했습니다.
|
||
- 전용 회귀 테스트 스위트 `tests/test_a3_buffer_isolation.py` (12/12 PASS)를 작성하여 입증했습니다.
|
||
|
||
### **C-2: 미사용 `.cache/` 상태 디렉터리 생성 및 데드 코드 정돈** — ✅ 완료
|
||
- `reconcile.sh`에서 아무 데이터도 저장하지 않던 미사용 `.cache/multi-agent-mux-monitor` 디렉터리 생성(`mkdir -p`) 구문 및 `STATE_DIR` 환경변수를 제거했습니다.
|
||
- 레거시 환경변수 `AGENT_SESSIONS_STATE_DIR` 설정 시 무음 생성을 방지하고 stderr에 가이드 경고만 안내하도록 정돈했습니다.
|
||
- `deploy/remove.sh` 언인스톨러에서 미사용 `.cache/` 디렉터리가 비어있는 경우 안전하게 제거(`rmdir .cache`)하도록 개선했습니다.
|
||
- 전용 단위/회귀 테스트 스위트 `tests/test_c2_no_stale_cache_dir.py` (5/5 PASS)를 작성하여 입증했습니다.
|
||
|
||
### **A-5: `HERDR_SESSION_NAME` 네이티브 전환** — ✅ 완료
|
||
- 기존 `HERDR_SERVER_NAME` 환경변수를 herdr 시프트가 직접 읽는 네이티브 **`HERDR_SESSION_NAME`** 및 YAML 레지스트리 키 **`herdr_session`**으로 전수 전환 단일화했습니다.
|
||
|
||
### **B-1: `find_workspace_uuid` tier-3 신원 캐시 해석 오류 해결** — ✅ 완료
|
||
- `lib.sh` tier-3 신원 캐시 조회 시 미정의 변수(`db_path`, `yaml_path`) 및 `yaml` import 누락으로 무조건 `NameError` 예외가 발생하던 결함을 해결했습니다.
|
||
- DB를 1차 권위 경로로, `$YAML_PATH`를 폴백으로 정제하고 전용 회귀 테스트 `tests/test_b1_tier3_identity.py` (8/8 PASS)를 작성하여 입증했습니다.
|
||
|
||
### **B-3: `command -v herdr` 프리플라이트 무력화** — ✅ 완료
|
||
- `lib.sh`에 `_canonical_file()`, `_is_shim_path()`, `_resolve_real_herdr_path()`, `has_real_herdr()` 헬퍼를 작성하여 `herdr()` bash 함수 오판과 `.mam/shim/herdr` 래퍼 매칭(파일 수준 심링크 포함)을 완전 차단했습니다.
|
||
- `create_session.sh`, `multi-agent-mux-delegate-job`, `create/SKILL.md`, `status/SKILL.md` 프리플라이트를 `has_real_herdr`로 전수 교체했습니다.
|
||
- 회귀 테스트 `tests/test_b3_herdr_preflight.py` (11/11 PASS)를 작성하여 입증했습니다.
|
||
|
||
### **C-1: Kanban 문서 29회 언급 vs 실제 구현 0건** — ✅ 완료
|
||
- SKILL.md 3종(monitor 22 / status 5 / create 2)과 README 2종의 Kanban 서술을 전면 제거했습니다.
|
||
- `multi-agent-mux-monitor` 의 실행 메커니즘 서술을 실제 구현인 `reconcile.sh --subscribe` (MQTT push + 브로커 다운 시 폴링 폴백) 기준으로 재작성했습니다.
|
||
- 존재하지 않는 스킬 참조 2건(`kanban-worker`, `kanban-orchestrator`)을 실존 스킬로 교체했습니다.
|
||
- `hermes kanban create` CLI 플래그 잔재 10종(`--goal-max-turns`, `--assignee`, `--comment-card` 등)을 파생형 검증 게이트(G-C)로 차단했습니다.
|
||
- 제품 표면(`.agents/skills/`, `README*.md`) Kanban 참조 **0건** 확인.
|
||
|
||
### **O-1: 타당하지 않은 리뷰 피드백 거부/반론 프로토콜 미지원 (Rebuttal Protocol)** — ✅ 완료
|
||
- `run_loop.sh`에 `--max-rebut N` (기본값 1) 옵션 및 Rebuttal/Re-adjudication/Arbitration 3단계 프로토콜을 구현했습니다.
|
||
- Creator가 지적 항목 거부 시 `[REBUT: <reviewer>]` 태그를 남겨 해당 리뷰어 대상 재심(`[ADJUDICATION: SUSTAINED/OVERRULED]`)을 가동하며, 교착 시 Planner 재정(`[ARBITRATION: CREATOR/REVIEWER]`) 또는 Fail-Closed 결정을 수행합니다.
|
||
- bash 3.2 macOS 규격 빈 배열 확장 안전성(`${ARR[@]+"${ARR[@]}"}`) 및 per-iteration budget reset / total budget cap 결함을 완벽히 보완하고 회귀 테스트 `tests/test_o1_rebuttal.py` (10/10 PASS)로 입증했습니다.
|
||
- `MULTI_AGENT_RULES.md`, `.ko.md`, `multi-agent-mux-loop/SKILL.md` 문서 연동을 완료했습니다.
|
||
|
||
### **Herdr-0.8.0-Compat-SanitizeHash: 세션명 32자 SHA-1 해시 접미사 절단 기반 유일성 보장 및 Mock Herdr 0.8.0 에러 정렬 (Commit `14b9de1`)** — ✅ 완료
|
||
- `.agents/skills/lib_py/agents/sanitize.py` 및 `.agents/skills/lib.sh` 내 `_sanitize_herdr_agent_name()`의 기존 단순 절단 방식(`s[:16]-s[-15:]`)으로 인해 동일 부모 경로 하위의 형제 워크스페이스들이 동일한 세션명으로 축약되던 결함을 **8자리 SHA-1 해시 접미사(`s[:23]-sha1[:8]`)** 결합 방식으로 100% 해소했습니다.
|
||
- 빈 문자열(`"agent"`), 숫자/특수문자 시작(`"x-"` 접두사), 32자 경계 및 33자 이상 절단 등 11개 엣지 케이스에서 **Bash 심 ↔ Python 모듈 간 100% 바이트 단위 동등성(Parity)**을 확립했습니다.
|
||
- `tests/conftest.py` Mock Herdr 에러 출력을 실제 Herdr 0.8.0 바이너리 출력 규격(`unknown option:`, `missing required`, `invalid_agent_name`)과 완전 일치하도록 정렬하고, `lib.sh` Early Abort 가드 정규식(`missing required`, `invalid_agent_name`, `^error:`)을 보강하여 불필요한 3회 재시도 루프 지연을 원천 차단했습니다.
|
||
- `lib.sh`의 `has-session` 분기 내 잔존하던 구형 휴리스틱을 제거하고, `tests/conftest.py` 내의 7곳 구형 절단 사본을 `_match_agent` 헬퍼 함수로 일원화했습니다.
|
||
- 전용 단위 테스트 `tests/test_sanitize_and_mock_errors.py` (3/3 PASS) 및 전체 회귀 테스트 스위트 (**256/256 PASS, 0 Failures / 0 Errors**)를 검증 완료했습니다.
|
||
- 멀티에이전트 자율 오케스트레이션 루프(`run_loop.sh --all-reviewer`)를 통해 Creator(`agy`, Job: `94bceedd`) 및 Reviewer(`cline`, Job: `14187d43`) 교차 검증 만장일치 **`[VERDICT: PASS]`** 를 달성했습니다.
|
||
|
||
---
|
||
|
||
## 6. 🧭 우선순위 실행 로드맵 (Prioritized Execution Roadmap)
|
||
|
||
> 평가 근거·항목별 실측 결과는 `.mam/jobs/ecef05a3/claude-reports/report-final.md` 참조.
|
||
> **순위를 매기기 전에 12건을 전부 현재 코드에 대조했으며, 그중 4건(A-2·B-5·C-3·C-4)의 기존 서술이 현재 코드와 달라 본문을 정정했습니다.**
|
||
|
||
### 6.1 정렬 원칙
|
||
|
||
① 외부에서 트리거 가능한 위험 → ② 검증 신호를 **거짓으로** 만드는 결함 → ③ 다른 항목을 싸게 만드는 구조 작업 → ④ 국소 결함 → ⑤ 정리.
|
||
|
||
**조용한 실패에 가중치를 둡니다.** 시끄러운 실패는 사람이 보지만, 조용한 실패는 "통과"로 기록되고 그 위에 다음 작업이 쌓입니다.
|
||
|
||
### 6.2 실행 순서
|
||
|
||
> **사용자 지침 반영**: **A-2 (공개 브로커 & HMAC)** 과제는 차후 자체 전용 MQTT 브로커 서버를 구축할 예정이므로 사용자 지침에 따라 **우선순위를 최하위(P5)로 조정**하였습니다.
|
||
|
||
| 순위 | 항목 | 근거 | 비용 | 선행 |
|
||
|---|---|---|---|---|
|
||
| **P0-1** | **B-7** | 저장소 밖 기동 시 리뷰어가 문자열 `"No git diff available"` 로 `[VERDICT: PASS]` 를 냄. 신규(미추적) 파일은 리뷰 대상 밖. **(✅ 완료 — tests/test_b7_diff_untracked.py 20/20 PASS)** | 소 (1파일) | — |
|
||
| **P0-2** | **O-2** | 마커를 조건 없이 덮어쓰고 종료 트랩이 **타 인스턴스의 마커까지 삭제** → 완료 처리된 **O-3 가드가 조용히 무력화**됨 **(✅ 완료 — tests/test_o2_race_free_lock.py 22/22 PASS)** | 소~중 (1파일) | — |
|
||
| **P1-1** | **A-4 M0~M1** | `PYTHONPATH` 부트스트랩·배포/CI 등록·`own_key` 이관. B-8/B-10/C-3b 로직을 싸게 만듦 **(✅ 완료 — tests/test_a4_adapter_contract.py 3/3 PASS)** | 중 | B-7 |
|
||
| **P1-2** | **B-8** | agy 주입 시 `return 0` 우회 제거 및 제출 검증 루프 이관 **(✅ 완료 — tests/test_b8_send_keys_verification.py 1/1 PASS)** | 소 | A-4 M0 |
|
||
| **P2-1** | **B-6 / B-12** | 스킬 트리 내 임시 사본 및 서브셸 EXIT 트랩으로 인한 루프 락 조기 해제 차단 **(✅ 완료 — tests/test_o3_scoped_guard.py 27/27 PASS, commit b490713)** | 소 | — |
|
||
| **P2-2** | **C-3a + C-4** | 빈 스텁 4종 + 공허한 테스트 4건 + 죽은 심볼 3종 제거 및 `--isolate` no-op 회귀 가드 신설 **(✅ 완료 — tests/test_tier1_unit.py + test_tier2_component.py 256/256 PASS)** | 소 | — |
|
||
| **P2-3** | **C-6** | `stop_session.sh` 헤더/도움말/주석/MESSAGING.md 정리 및 회귀 가드 신설 **(✅ 완료 — tests/test_tier2_component.py 가드 신설, 전체 263/263 PASS)** | 극소 | — |
|
||
| **P3-1** | **A-4 M2~M7** | 어댑터 본이관 및 CLI facts 브리지/서브커맨드 구축 **(✅ 완료 — tests/test_a4_adapter_contract.py 9/9 PASS, 전체 259/259 PASS)** | 대 | P1-1 |
|
||
| **P3-2** | **B-10** | tier-3 신원 캐시 완전 제거 및 UUID 경로 PyYAML 탈의존 (Option A) **(✅ 완료 — tests/test_tier1_unit.py 가드 3건 신설, 전체 266/266 PASS)** | 중 | A-4 M2 |
|
||
| **P3-3** | **C-3b** | `isolation.root` 4개 소비자 완전 폐기 (Option B 채택) **(✅ 완료 — 전체 259/259 PASS)** | 소 | A-4 M2 |
|
||
| **B-13** | **Stage 2** | 셀프 호스팅 루프 런타임 프리즈 스냅샷 및 이중 루트 격리 **(✅ 완료 — tests/test_o3_scoped_guard.py 5건 가드 신설, 전체 271/271 PASS)** | 중 | — |
|
||
| **P4-1** | **B-9** | 감사 로그 루트 지연 평가 및 `__getattr__`/`__dir__` 동적 별칭 **(✅ 완료 — tests/test_tier1_unit.py 5건 가드 신설, 전체 276/276 PASS)** | 극소 | — |
|
||
| **P5-1** | **A-2** | 공개 브로커 및 HMAC 검증 보완 (📌 *사용자 지침: 차후 전용 MQTT 브로커 서빙 환경 구축 시점에 진행*) | 중 (3파일) | 전용 브로커 |
|
||
| **종결** | **B-5** | `df -P` 폴백 정상 동작 실측 및 단위 테스트 검증 완료 **(✅ 완료/종결 — tests/test_tier1_unit.py test_stop_check_is_nfs_local)** | — | — |
|
||
|
||
**A-2 과제의 후순위 배치 사유**: 사용자 지침에 따라 차후 자체 전용 MQTT 브로커 서빙 환경 구축 시점에 맞춰 진행하기 위해 **최하위(P5-1)**로 배치하였습니다.
|
||
|
||
**정리(C 계열)를 P2 에 두는 이유**: (a) C-3a 는 죽은 코드를 고정하던 테스트를 함께 제거해 C-3a 를 실행 가능하게 만들고, (b) C-4 는 **잘못 실행하면 버그를 만듭니다**. 방치할수록 누군가 "쉬운 정리"로 집어 들 확률이 올라갑니다.
|
||
|
||
### 6.3 병렬 실행 — 파일 소유권 슬롯 (Rev.2 교체)
|
||
|
||
> Rev.1 은 "주제별 트랙"으로 병렬화를 서술했고 **그 분해는 4곳에서 틀렸습니다**(챌린지 `7d604ee7` 계기로 파일 단위 재대조). 병렬 단위는 **주제가 아니라 파일**입니다.
|
||
|
||
**항목별 처방이 건드리는 파일**
|
||
|
||
| 파일 | 건드리는 항목 |
|
||
|---|---|
|
||
| `run_loop.sh` | **B-6, B-7, O-2** |
|
||
| `lib.sh` | **A-4, B-8, B-10, C-3a, C-4** |
|
||
| `reconcile.sh` | **A-2, A-4, B-10** |
|
||
| `mqtt_common.py` | **A-2, B-9** |
|
||
| `stop_session.sh` | **B-10, C-6** |
|
||
| `registry.py` | **A-2, C-4** |
|
||
| `create_session.sh` | **A-4, C-4** |
|
||
|
||
**슬롯 배치 — 슬롯 안은 직렬, 슬롯 간은 병렬**
|
||
|
||
| 슬롯 | 순서 |
|
||
|---|---|
|
||
| **`run_loop.sh`** | `B-7` → `O-2` → `B-6` |
|
||
| **`lib.sh`** | `C-3a`+`C-4` → `B-8` |
|
||
| **MQTT 계열** (`mqtt_common.py`·`registry.py`·`publish_event.py`·`job_subscriber.py`·`reconcile.sh`) | `A-2` → `B-9` |
|
||
| **`stop_session.sh`** | `C-6` |
|
||
| **단독 실행** (슬롯 경계를 넘음) | `A-4`, `B-10` |
|
||
|
||
- `A-4`(`lib.sh`+`reconcile.sh`+`create_session.sh`+`resume_session.sh`)와 `B-10`(`lib.sh`+`reconcile.sh`+`stop_session.sh`)은 **어떤 슬롯 조합과도 겹치므로 단독 실행**합니다.
|
||
- `A-4` 는 신규 파일을 대량 추가하므로 **B-7 이 먼저 닫혀 있어야 리뷰가 성립**합니다.
|
||
- **Rev.1 오류 정정 4건**: `B-6`(트랙 C→`run_loop.sh` 슬롯), `C-3a`·`C-4`(트랙 C→`lib.sh` 슬롯), `B-9`(독립→MQTT 슬롯), `C-6`(독립→`stop_session.sh` 슬롯).
|
||
- 참고: `reconcile.sh` 는 `MAM_LOOP_MARKER`·`send_keys_safe` 를 **참조 0건**이므로 `O-2`·`B-8` 과는 경합하지 않습니다(자체 `.mam/monitor.lock` 보유).
|
||
|
||
### 6.4 B-7 처방 (Rev.2 신설 — 진단만 있고 처방이 없었음)
|
||
|
||
`cd "$REPO_ROOT"` 만으로는 **미추적 신규 파일이 여전히 100% 누락**됩니다. `git diff` 는 정의상 추적 파일만 봅니다.
|
||
|
||
```bash
|
||
CHANGES_DIFF=$(
|
||
cd "$REPO_ROOT" || exit 1
|
||
git diff "$BASE_COMMIT"
|
||
# 미추적 신규 파일을 인덱스 변경 없이 덧붙인다.
|
||
# --exclude-standard 가 .gitignore / .git/info/exclude 를 그대로 존중한다.
|
||
git ls-files -o --exclude-standard -z | while IFS= read -r -d '' f; do
|
||
git diff --no-index --binary /dev/null "$f" 2>/dev/null || true
|
||
done
|
||
)
|
||
```
|
||
|
||
**`git add -N .` 은 채택하지 않습니다.** 미추적 파일을 diff 에 넣는 목적은 달성하지만(실측 확인) **인덱스에 `A` 항목을 남기며**, 그 상태에서 Creator 가 `git commit -am` 을 실행하면 **추가한 적 없는 파일이 내용째 커밋됩니다**(실측 확인). `run_loop.sh` 는 Creator 가 같은 저장소에서 작업하는 동안 반복 실행되므로 실제 위험입니다. 위 대안은 동일 결과를 내면서 인덱스를 건드리지 않습니다.
|
||
|
||
**크기 상한도 함께 필요합니다.** 현재 `CHANGES_DIFF`(537·539행)는 **아무 제한 없이** 547행 리뷰 프롬프트에 보간되고 `send_keys_safe` paste-buffer 로 주입됩니다. 미추적 파일을 포함시키면 커지기만 하므로 상한을 두고, 초과 시 `--stat` 요약으로 대체하되 **잘렸다는 사실을 리뷰어에게 반드시 노출**해야 합니다(조용히 자르면 "빈 diff PASS" 가 "부분 diff PASS" 로 바뀔 뿐입니다). 구체적 임계값은 구현자가 샌드박스 세션에서 paste-buffer 실패 지점을 측정해 확정할 것.
|
||
|
||
### 6.5 ⚠️ 실행 전 반드시 확인할 정정 사항
|
||
|
||
|
||
1. **C-3 (✅ 완료)**:
|
||
- **C-3a (✅ 완료)**: `provision_isolation` / `isolation_lever` / `isolation_env_prefix` / `isolation_cmd_args` 4종 빈 스텁 및 이를 고정하던 공허한 테스트 4건을 제거하고 `--isolate`/`--no-isolate` no-op 회귀 가드로 대체했습니다.
|
||
- **C-3b (✅ 완료 — P3-1 / Option B)**: `isolation.root` 4개 소비자(`lib.sh` `verify_session_uuid` 의 `iso_root` 분기, `mam_session_iso_root`, `find_workspace_uuid` 격리 분기, `stop_session.sh:277` purge 가드 및 `atomic_yaml.py:30-33` 유효성 검사)를 완전히 폐기하고 Universal Global Config 및 어댑터 기반 단일 경로로 이관했습니다.
|
||
2. **C-4 (✅ 완료)**:
|
||
- `_HERDR_SHIM_DIR_PATTERN` — **사용 중입니다** (`lib.sh:83` 정의, `lib.sh:105` 사용). 목록대로 지우면 shim 경로 판정이 깨집니다.
|
||
- `local_herdr` — 참조 0건, **이미 제거됨**.
|
||
- 실제 대상 `_REAL_HERDR_PATH`, `TERMINAL_STATUSES`, `ISOLATE` 3종이 안전하게 제거되었습니다(`provision_isolation` 은 C-3a 에서 처리).
|
||
3. **A-2 의 원인 표현 정정** — `verify_hmac` 구현 자체는 정상입니다(토큰이 있으면 `hmac.compare_digest` 로 검증). 원인은 **토큰이 아무 데서도 발급되지 않아 검증이 공허해지는 것** + 발행자가 워크스페이스 지문 토픽을 채택하지 않은 것입니다. 수정은 ① 발행자 토픽 교체 ② `reconcile.sh:237` 레거시 전역 구독 제거 ③ `verify_hmac` fail-closed + 토큰 발급 순입니다.
|
||
4. **B-5 잔여분** — 폴백으로 감지는 정상화됐으나 `mount | grep -E "$mountpoint.*(nfs|...)"` 가 마운트포인트를 **이스케이프 없이 ERE 에 보간**합니다(경로의 `.` 이 임의 문자로 해석). 이것만 신규 항목(B-11)으로 분리 권고.
|
||
|
||
### 6.6 결론
|
||
|
||
`IMPROVEMENTS.md` 는 남은 백로그 항목(아키텍처 2건, 엣지케이스 6건, 오케스트레이션 1건, 레거시 잔재 3건 — 총 12건)을 위 우선순위에 따라 일원화된 보완 로드맵으로 관리합니다.
|