docs(readme): review fixes (38a64423 / c5a8813c / 7d29a620) and README.ko.md in step

- install.sh: what it actually checks; it writes a starter .mam.env with
  MQTT_BROKER=localhost (broker.hivemq.com is only the unset fallback);
  install_mam.sh is a separate installer.
- Security: tokens exist only when given or when the broker has TLS or a
  username (PoC: no signature check); the remote dispatch carries the token.
- Server isolation: create defaults to a workspace-named server; the shim
  bootstraps only a named server and never when MAM_NO_AUTOSTART=1
  (status/monitor); restore-off is the normal path, with a warning fallback.
- Loop: the selected reviewers must all pass; no reviewer option means a
  creator self-review.
- Interpreter order with the PATH python3 fallback; exit 5 also covers
  target_not_found; two layers with their own registries; test isolation
  stated as sandboxes plus after-run guards; quick start uses named sessions.
- README.ko.md now mirrors README.md.

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:14:31 +09:00
1 parent 20b1014717
commit 423abc7844
2 files changed
+215 -190

No files matched your search

+24 -22
View File
@@ -13,7 +13,7 @@ Long agent runs break in predictable ways: a session dies with its terminal, two
1. **Isolated, resumable agent sessions.** Each agent runs in its own herdr pane, usually on a herdr server dedicated to the workspace. Sessions are recorded in `.mam/agent-sessions.yaml` (backed by SQLite) with their conversation ids, so a stopped agent resumes the same conversation later.
2. **Jobs decided by events, not by the screen.** A delegated job is a registry record plus an MQTT event stream (`started`, `progress`, `completed`, `error`). The agent must acknowledge the prompt within a deadline and heartbeat while it works. A job is closed only by a protocol event or a timeout, never by reading the terminal.
3. **One job per session at a time.** Before injecting a prompt, the dispatcher waits by the registry for the session's earlier jobs (onboarding included) to end. Pane placement is serialised per herdr server, so concurrent `create` calls do not take the same pane.
4. **Reviewed loops with pinned evidence.** `multi-agent-mux-loop` sends a change to every registered reviewer and requires a unanimous `PASS`. With `--worktree`/`--base`, each review round is bound to a snapshot of the source. If the source changes during the round, its approvals are discarded and the round is reviewed again.
4. **Reviewed loops with pinned evidence.** `multi-agent-mux-loop` sends a change to the reviewers you select and requires every one of them to `PASS`. You can name reviewers with `--reviewer` or take every running reviewer with `--all-reviewer`; without either, the creator reviews its own work. With `--worktree`/`--base`, each review round is bound to a snapshot of the source. If the source changes during the round, its approvals are discarded and the round is reviewed again.
---
@@ -31,14 +31,14 @@ or, from a local clone:
bash deploy/install.sh
```
The installer is idempotent. It does the following:
- checks the dependencies (herdr, `python3` with PyYAML and sqlite3, rsync, uuidgen);
- copies `.agents/` and the templates;
`install.sh` is idempotent. It does the following:
- checks that herdr and Python 3.9+ are installed, and that the system `python3` has PyYAML;
- copies `.agents/` and `.mam.env.example` into the workspace;
- creates `.venv` and installs `paho-mqtt` and PyYAML into it;
- writes `.mam.env` from `.mam.env.example`;
- writes a starter `.mam.env` with `MQTT_BROKER=localhost`. An existing `.mam.env` is kept, and a legacy `.env` is renamed to `.mam.env`;
- adds `.venv`, `.mam/` and `.mam.env` to `.gitignore`.
Configure the broker in `.mam.env`. The default is the public `broker.hivemq.com`, which is fine for a trial but not for real work. See [MESSAGING.md](MESSAGING.md) for a private broker. `deploy/update.sh` and `deploy/remove.sh` update and uninstall.
Point `MQTT_BROKER` in `.mam.env` at a broker you run (see [MESSAGING.md](MESSAGING.md) for a private broker). If `MQTT_BROKER` is not set at all, the code falls back to the public `broker.hivemq.com`. That is fine for a trial, but not for real work. `deploy/generate-env.sh` recreates `.mam.env` from `.mam.env.example`. `deploy/update.sh` and `deploy/remove.sh` update and uninstall. `deploy/install_mam.sh` is a separate installer that copies from a local clone into another directory.
---
@@ -54,14 +54,14 @@ Every skill lives under `.agents/skills/` with a `SKILL.md` that documents its o
| **`multi-agent-mux-status`** | Read-only snapshot of every session: registry status, herdr liveness, pane command and cwd, resume id, drift. |
| **`multi-agent-mux-monitor`** | Long-running reconciler (`reconcile.sh --subscribe`). It reacts to job events, falls back to polling when the broker is down, and fixes registry drift. For example, it marks dead sessions `terminated` and registers live sessions the registry does not know. |
| **`multi-agent-mux-delegate-job`** | Delegates a job to a session (`herdr:<name>`) or to a runner on another host (`remote:<name>`) and waits for its result. See [Delegation contract](#-delegation-contract). |
| **`multi-agent-mux-loop`** | Plan, implement, review: an optional planner and a creator, then one or all reviewers until a unanimous `PASS` or `--max-loop`. It also supports `--review-only` for work finished outside the loop. Passing reports are promoted to `.agents/reports/<session>/`. |
| **`multi-agent-mux-loop`** | Plan, implement, review: an optional planner and a creator, then the selected reviewers (`--reviewer A,B`, or `--all-reviewer` for every running reviewer except the creator) until all of them `PASS` or `--max-loop` is reached. With neither option the creator reviews its own work. `--review-only` reviews work finished outside the loop. Passing reports are promoted to `.agents/reports/<session>/`. |
| **`multi-agent-mux-orc-onboard`** | Registers the orchestrator's own session id, so session discovery never mistakes it for a sub-agent. |
---
## 📐 Architecture
MAM has two layers that share one registry:
MAM has two layers, each with its own registry:
1. **Sessions (herdr)**: `lib.sh` and the create/stop/resume/status/monitor scripts run the agents and keep `.mam/agent-sessions.yaml` (+ `.mam/agent-sessions.db`) authoritative.
2. **Jobs (delegation)**: `lib_py/delegation/` registers a job in `.mam/jobs/<id>.json`, injects the brief, and follows the job's events over MQTT. Every event is also appended to the job's audit log `.mam/delegate_job_logs/<id>/`.
@@ -87,15 +87,15 @@ MAM has two layers that share one registry:
### 🔒 Herdr server isolation
- **Dedicated server per workspace (opt-in).** `create --herdr-session <name>` (or `HERDR_SESSION_NAME`) runs the agents on their own herdr server and socket, separate from your default herdr. The server name is recorded on the session row, and every later command routes to it.
- **The shim.** Sourcing `lib.sh` writes `<workspace>/.mam/shim/herdr` and puts it first on `PATH`. The shim provides the tmux-style commands the scripts use (`new-session`, `has-session`, …) on top of herdr's agent API. It routes each call with `--session <server>`, and it starts the server headless if the server is not running.
- **No surprise relaunches.** A server MAM starts uses your herdr config with `resume_agents_on_restore = false`. A herdr restart therefore does not relaunch saved agents without their permission flags.
- **A dedicated server per workspace.** By default `create` runs the agents on a herdr server named after the workspace (its slug), with its own socket, separate from your default herdr. `--herdr-session <name>` or `HERDR_SESSION_NAME` picks another name. The server name is recorded on the session row, and every later command routes to it.
- **The shim.** Sourcing `lib.sh` writes `<workspace>/.mam/shim/herdr` and puts it first on `PATH`. The shim provides the tmux-style commands the scripts use (`new-session`, `has-session`, …) on top of herdr's agent API. For a named server it adds `--session <server>` to each call, and it starts that server headless if it is not running. It does not start one when `MAM_NO_AUTOSTART=1`, which `status` and `monitor` set, so looking never starts a server. Calls for the `default` server go to your ambient herdr unchanged.
- **No surprise relaunches.** A server MAM starts normally uses your herdr config plus `resume_agents_on_restore = false`. A herdr restart therefore does not relaunch saved agents without their permission flags. If that config cannot be built, the bootstrap prints a warning and the server starts with restore on.
- **One pane claim at a time.** Pane placement holds a per-server lock (`lib_py/pane_lock.py`, `flock` on macOS and Linux). Concurrent `create` calls in one folder each get their own pane.
### 🛡️ Registry writes and concurrency
- **Serialised writes.** Every change to `agent-sessions.yaml` goes through `lib.sh::atomic_dump_yaml`. It runs under an exclusive SQLite transaction (`BEGIN IMMEDIATE`) on `.mam/agent-sessions.db` and is validated before the YAML is rewritten atomically. Job records use their own registry lock.
- **One interpreter.** The scripts run their Python in the workspace `.venv` (`AGENT_PYTHON_BIN`, else the active or nearest `.venv`).
- **Python interpreter.** Registry writes and the delegation helpers pick their Python in this order: `AGENT_PYTHON_BIN`, the active virtualenv, the nearest `.venv` above the skills, then `python3` on `PATH`. Some shell paths, such as the shim and parts of `create`, call `python3` from `PATH` directly.
- **Network filesystems.** If `.mam/` is on NFS/CIFS/SSHFS, `lib.sh` warns, and SQLite switches its journal from `WAL` to `DELETE`.
- **One loop per checkout.** A loop lock refuses a second `run_loop.sh` in the same control plane.
@@ -117,7 +117,7 @@ The full specification is in [MESSAGING.md §2.5](MESSAGING.md).
| `1` | failure, or no `started` within T |
| `2` | no event for K×N (`deadline_timeout`) or budget spent (`wall_clock_timeout`) |
| `3` | broker unavailable, and no terminal status on disk |
| `5` | session busy, or the record was taken over while waiting (never delivered) |
| `5` | not delivered (`cancelled`): the session was busy, the target was not found, or the record was taken over while waiting |
---
@@ -157,9 +157,10 @@ sequenceDiagram
## 🔐 Security
- **Signed events**: every job gets its own token (`auth_token`). Each event and each retained state message carries an HMAC-SHA256 signature made with it, and the subscriber drops anything that fails verification. The token itself never goes over the wire.
- **Signed events**: a job gets its own token (`auth_token`) when you pass one, or automatically when the broker uses TLS or a username. Each event and each retained state message then carries an HMAC-SHA256 signature made with it, and the subscriber drops anything that fails verification. Events and state messages carry only the signature, not the token. On a broker with neither TLS nor a username (the PoC setup), a job has no token and signatures are not checked.
- **Remote dispatch carries the token**: the `remote:<name>` dispatch message includes the job's token (signed with `MAM_DISPATCH_SECRET`, not encrypted). Use it only on an access-controlled private broker.
- **Replay and ordering**: each event carries an increasing `seq`. The subscriber accepts only sequence numbers higher than any it has seen and records gaps as `seq_gap`. Timestamps are informational only.
- **Credentials**: broker credentials live only in `.mam.env` (never in a job record). Remote dispatch is signed with `MAM_DISPATCH_SECRET`.
- **Credentials**: broker credentials live only in `.mam.env`, never in a job record.
---
@@ -171,10 +172,9 @@ sequenceDiagram
- The suite has about 1,900 tests, and a full run takes over an hour.
- It runs its own in-process MQTT broker, so it never needs `.mam.env`. Don't export `.mam.env` for tests.
- Tests run in sandboxes:
- they never write to the checkout's `.mam/`, your agent homes (`~/.claude/projects`, `~/.codex`, `~/.gemini`, …) or your herdr config;
- a test that does not use the mock herdr starts its own throwaway herdr server;
- session-level guards fail the run if a test leaves files behind in the real control plane or in an agent home.
- Tests run in sandboxes, with a temporary HOME, registry and audit-log directory, and a mock herdr:
- the tests that drive a real herdr start their own throwaway herdr server;
- after the run, session-level guards check the real control plane and your agent homes (`~/.claude/projects`, `~/.codex`, `~/.gemini`, …) and fail the run if a test left entries there.
- Some tests are platform-specific. A few need Python 3.11+ (`tomllib`), Linux (`/proc`) or the `nats-docker` submodule; elsewhere they are skipped.
---
@@ -219,16 +219,18 @@ bash deploy/install.sh
# 2. Start a creator and a reviewer on a dedicated herdr server
bash .agents/skills/multi-agent-mux-create/scripts/create_session.sh \
--workspace "$PWD" --agent claude --role developer --herdr-session my-project --onboard
--workspace "$PWD" --agent claude --role developer --session creator-claude-01 \
--herdr-session my-project --onboard
bash .agents/skills/multi-agent-mux-create/scripts/create_session.sh \
--workspace "$PWD" --agent codex --role reviewer --herdr-session my-project --onboard
--workspace "$PWD" --agent codex --role reviewer --session reviewer-codex-01 \
--herdr-session my-project --onboard
# 3. Check the sessions
bash .agents/skills/multi-agent-mux-status/scripts/status.sh
# 4. Run a task through the loop
bash .agents/skills/multi-agent-mux-loop/scripts/run_loop.sh \
--creator <creator-session> --all-reviewer --task "Fix the typo in docs/guide.md"
--creator creator-claude-01 --all-reviewer --task "Fix the typo in docs/guide.md"
```
---