docs(readme): round-2 review fixes (00aa4a4c / 09bf3e77)

- exit 5: a busy or missing target cancels the job; a superseded attempt
  leaves the record to its new owner, unchanged
- install.sh copies a legacy .env to .mam.env and keeps the original
- restore-off fallback: without tomllib the file keeps only that key
  (restore off, other settings lost, warning); restore on only when no
  file can be written
- PoC: no token only when none is passed; tests: every test gets a temp
  registry and log dir, most also the sandbox HOME and mock herdr

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-13 11:32:01 +09:00
1 parent 423abc7844
commit ae2813773c
2 files changed
+10 -10

No files matched your search

+5 -5
View File
@@ -35,7 +35,7 @@ bash deploy/install.sh
- herdr 와 Python 3.9+ 가 설치돼 있는지, 시스템 `python3` 에 PyYAML 이 있는지 확인합니다.
- `.agents/` 와 `.mam.env.example` 을 워크스페이스에 복사합니다.
- `.venv` 를 만들고 `paho-mqtt`·PyYAML 을 설치합니다.
- `MQTT_BROKER=localhost` 로 된 초기 `.mam.env` 를 씁니다. 이미 있는 `.mam.env` 는 그대로 두고, 예전 `.env` 는 `.mam.env` 로 이름을 바꿉니다.
- `MQTT_BROKER=localhost` 로 된 초기 `.mam.env` 를 씁니다. 이미 있는 `.mam.env` 는 그대로 둡니다. 예전 `.env` 만 있으면 그것을 `.mam.env` 로 복사하고 원본은 남깁니다.
- `.venv`, `.mam/`, `.mam.env` 를 `.gitignore` 에 추가합니다.
`.mam.env` 의 `MQTT_BROKER` 를 직접 운영하는 브로커로 바꾸십시오(사설 브로커는 [MESSAGING.md](MESSAGING.md) 참고). `MQTT_BROKER` 가 아예 설정되지 않으면 코드는 공개 브로커 `broker.hivemq.com` 을 씁니다. 시험용으로는 괜찮지만 실제 작업용은 아닙니다. `deploy/generate-env.sh` 는 `.mam.env.example` 로 `.mam.env` 를 다시 만듭니다. 업데이트와 제거는 `deploy/update.sh`, `deploy/remove.sh` 입니다. `deploy/install_mam.sh` 는 로컬 클론에서 다른 디렉터리로 복사해 설치하는 별도 설치기입니다.
@@ -89,7 +89,7 @@ MAM 은 각자 레지스트리를 가진 두 계층으로 이루어집니다.
- **워크스페이스 전용 서버.** `create` 는 기본으로 워크스페이스 이름(slug)을 딴 herdr 서버에서 에이전트를 돌립니다. 이 서버는 기본 herdr 와 분리된 자기 소켓을 씁니다. `--herdr-session <name>` 또는 `HERDR_SESSION_NAME` 으로 다른 이름을 고를 수 있습니다. 서버 이름은 세션 행에 기록되고, 이후 모든 명령이 그 서버로 갑니다.
- **shim.** `lib.sh` 를 source 하면 `<workspace>/.mam/shim/herdr` 를 쓰고 `PATH` 맨 앞에 둡니다. shim 은 스크립트가 쓰는 tmux 식 명령(`new-session`, `has-session` …)을 herdr 의 에이전트 API 위에 제공합니다. 이름 있는 서버면 호출마다 `--session <server>` 를 붙이고, 그 서버가 돌고 있지 않으면 헤드리스로 시작합니다. 단 `MAM_NO_AUTOSTART=1` 이면 시작하지 않습니다. `status` 와 `monitor` 가 이 값을 설정하므로, 조회만으로 서버가 뜨는 일은 없습니다. `default` 서버 호출은 바꾸지 않고 사용자의 herdr 로 그대로 갑니다.
- **예상치 못한 재실행 없음.** MAM 이 시작한 서버는 보통 사용자의 herdr 설정에 `resume_agents_on_restore = false` 를 더해 씁니다. 그래서 herdr 가 재시작돼도 저장된 에이전트를 권한 플래그 없이 다시 띄우지 않습니다. 이 설정을 만들 수 없으면 부트스트랩이 경고를 남기고, 서버는 restore 가 켜진 채 시작합니다.
- **예상치 못한 재실행 없음.** MAM 이 시작한 서버는 보통 사용자의 herdr 설정에 `resume_agents_on_restore = false` 를 더해 씁니다. 그래서 herdr 가 재시작돼도 저장된 에이전트를 권한 플래그 없이 다시 띄우지 않습니다. `tomllib` 이 없는 Python(macOS 기본 3.9 등)에서는 이 파일에 그 키만 들어가므로, restore 는 꺼지지만 사용자의 다른 herdr 설정은 반영되지 않습니다. 이때 부트스트랩이 경고합니다. 설정 파일을 아예 쓰지 못한 경우에만 서버가 restore 가 켜진 채 시작하며, 이때도 경고를 남깁니다.
- **pane 배치는 한 번에 하나.** pane 배치는 서버별 잠금(`lib_py/pane_lock.py`, macOS·Linux 에서 `flock`)을 잡고 합니다. 한 폴더에서 동시에 실행한 `create` 도 각자 자기 pane 을 받습니다.
### 🛡️ 레지스트리 쓰기와 동시성
@@ -117,7 +117,7 @@ MAM 은 각자 레지스트리를 가진 두 계층으로 이루어집니다.
| `1` | 실패, 또는 T 안에 `started` 없음 |
| `2` | K×N 동안 이벤트 없음(`deadline_timeout`) 또는 예산 소진(`wall_clock_timeout`) |
| `3` | 브로커를 쓸 수 없고, 디스크에도 종결 상태가 없음 |
| `5` | 전달 안 됨(`cancelled`): 세션이 바쁨, 대상을 찾지 못함, 또는 기다리는 동안 레코드를 다른 쪽이 가져감 |
| `5` | 이번 시도는 프롬프트를 전달하지 않음: 세션이 바쁘거나 대상을 찾지 못함(잡은 `cancelled`), 또는 기다리는 동안 다른 시도가 레코드를 가져감(레코드는 새 소유자에게 그대로 둠) |
---
@@ -157,7 +157,7 @@ sequenceDiagram
## 🔐 보안
- **서명된 이벤트**: 토큰을 직접 넘기거나 브로커가 TLS 또는 사용자 이름을 쓰면, 잡은 고유 토큰(`auth_token`)을 받습니다. 그때 모든 이벤트와 retained 상태 메시지에 그 토큰으로 만든 HMAC-SHA256 서명이 붙고, 구독자는 검증에 실패한 메시지를 버립니다. 이벤트와 상태 메시지에는 토큰이 아니라 서명만 실립니다. TLS 도 사용자 이름도 없는 브로커(PoC 구성)에서는 잡에 토큰이 없어 서명을 검사하지 않습니다.
- **서명된 이벤트**: 토큰을 직접 넘기거나 브로커가 TLS 또는 사용자 이름을 쓰면, 잡은 고유 토큰(`auth_token`)을 받습니다. 그때 모든 이벤트와 retained 상태 메시지에 그 토큰으로 만든 HMAC-SHA256 서명이 붙고, 구독자는 검증에 실패한 메시지를 버립니다. 이벤트와 상태 메시지에는 토큰이 아니라 서명만 실립니다. 토큰을 넘기지 않았고 브로커에 TLS 도 사용자 이름도 없으면(PoC 구성), 잡에 토큰이 없어 서명을 검사하지 않습니다.
- **원격 디스패치에는 토큰이 실린다**: `remote:<name>` 디스패치 메시지에는 잡의 토큰이 들어갑니다(`MAM_DISPATCH_SECRET` 으로 서명될 뿐 암호화되지는 않음). 접근이 통제된 사설 브로커에서만 쓰십시오.
- **재전송과 순서**: 이벤트마다 증가하는 `seq` 가 붙습니다. 구독자는 지금까지 본 것보다 큰 번호만 받고, 빈 번호는 `seq_gap` 으로 기록합니다. 타임스탬프는 참고용입니다.
- **자격 증명**: 브로커 자격 증명은 `.mam.env` 에만 있고, 잡 레코드에는 없습니다.
@@ -172,7 +172,7 @@ sequenceDiagram
- 테스트는 약 1,900 개이고, 전체 실행에 한 시간 넘게 걸립니다.
- 프로세스 안에서 자체 MQTT 브로커를 띄우므로 `.mam.env` 가 필요 없습니다. 테스트용으로 `.mam.env` 를 export 하지 마십시오.
- 테스트는 임시 HOME·레지스트리·감사 로그 디렉터리와 mock herdr 를 쓰는 샌드박스에서 돕니다.
- 모든 테스트는 임시 잡 레지스트리와 감사 로그 디렉터리를 씁니다. 대부분의 테스트는 임시 HOME 과 mock herdr 를 설정하는 샌드박스 픽스처도 씁니다.
- 실제 herdr 를 다루는 테스트는 일회용 herdr 서버를 직접 띄웁니다.
- 실행이 끝나면 세션 단위 가드가 실제 제어 평면과 사용자의 에이전트 홈(`~/.claude/projects`, `~/.codex`, `~/.gemini` …)을 확인하고, 테스트가 남긴 항목이 있으면 실행을 실패시킵니다.
- 일부 테스트는 플랫폼에 따라 다릅니다. Python 3.11+(`tomllib`), Linux(`/proc`), `nats-docker` 서브모듈이 필요한 테스트는 그 밖의 환경에서 건너뜁니다.