CLAUDE.md ยท diff

git:20261019.e927c6e to git:20261021.f523a6c

10 added, 2 removed. Audit A to A.

# CLAUDE.md
This is the repository instruction file for agents. `AGENTS.md` is a symlink
to this file so harnesses that select either name load the same guidance.
## Project Overview
Agent Message Queue (AMQ) is a daemon-free, file-based message bus for local
coding agents. Maildir-style `tmp -> new -> cur` delivery gives crash-safe
messages without a database or server. AMQ owns messaging, threads, routing,
receipts, handoff state, and operational diagnosis. Orchestrators continue to
own worktrees, dependency scheduling, task decomposition, and PR landing.
## Release Contract
- Release Please maintains the release PR from conventional squash commits on
`main`. Do not create release branches, tags, or GitHub releases manually.
- A push to `main` updates the AvivSinai marketplace for `amq-cli` and
`amq-spec`.
- Keep one version across `CHANGELOG.md`, `.release-please-manifest.json`, and
skill/plugin metadata. After the release PR merges, `release.yml` validates
that commit, creates the tag, and publishes GitHub and Homebrew artifacts.
- `make build` and GoReleaser embed the same bare semver (for example `0.63.0`,
not `v0.63.0`); the Makefile strips one leading `v` from `VERSION`.
- PR titles use `type(scope): description`. Squash merge makes the title the
conventional commit on `main`. Use `BEGIN_COMMIT_OVERRIDE` in the PR body,
or edit the release PR, when release notes need multiple entries. Each entry
is one conventional header of at most 72 characters, separated by a blank
line.
- `verify-brew-release.yml` runs when `release.yml` actually publishes a
release, and on demand, to confirm the published release installs from the
real `avivsinai/tap/amq` formula. It ignores non-release merges (where
`release.yml` completes but its own `release` job stays skipped) and
drafts or prereleases. It retries the tap refresh and install for up to 6
attempts to absorb tap propagation lag, then requires `amq --version` to
match the released tag and runs an init/send/drain round trip against a
throwaway queue root to prove the installed binary works end to end. It
never writes to the tap.
## Operational Constraints
- Handles are lowercase, match `[a-z0-9_-]+`, and do not start with `-`.
- Use the CLI for mailbox operations. Never edit queue files directly.
- Cleanup is explicit through `amq cleanup`; do not add automatic deletion.
- AMQ remains daemon-free. Supervisors can run `wake` or `monitor`, but AMQ
does not own their lifecycle.
## Build and Development Commands
```bash
- make build # go build amq, amq-keepalive, amq-bridge, amq-acp, amq-remote
+ make build # go build amq, amq-keepalive, amq-bridge, amq-acp, amq-remote, amq-owner-sign
make test # go test ./...
make fmt # gofmt -w
make vet # go vet
make lint # golangci-lint
make check # static gates the pre-push hook runs (fmt, vet, lint, docs, skills)
make ci # check plus the full test suite and smoke checks (CI runs this)
make check-skills # validate canonical and symlinked skill content
```
Formatting and lint use the toolchain pinned in `go.mod` and the golangci-lint
version in the Makefile; other versions are refused.
Go 1.26+ is required. `golangci-lint` is optional for local development and
required by `make lint` and `make ci`.
## Architecture
```text
cmd/amq/ CLI entry point
cmd/amq-keepalive/ macOS wake supervisor companion
cmd/amq-bridge/ Cross-host courier companion (apply-file + HTTPS, not Core)
cmd/amq-acp/ Preview ACP v2 stdio companion (not Core)
cmd/amq-remote/ Remote-session companion (not Core)
+ cmd/amq-owner-sign/ Owner signer for a strict relay share; the key stays in its process
internal/cli/ Command handlers and routing policy
internal/fsq/ Maildir delivery, atomic operations, and scans
internal/format/ JSON frontmatter plus Markdown message serialization
internal/config/ Queue and project configuration
internal/receipt/ Consumer-local drained and DLQ receipts
internal/integration Shared adapter support for Symphony and Kanban
internal/launch/ Plans, adapters, trust, leases, bindings, and resume state
internal/keepalive/ Companion registry, adapters, hooks, and supervision
internal/bridge/ Envelope, auth, and crash-idempotent local apply
internal/acp/ ACP v2 sessions, steering, and prompt delivery
internal/remote/ Endpoint, adapters, and request store for amq-remote
internal/sessionguard Shared fail-closed session decision table
internal/swarm/ Claude Code Agent Teams interoperability
internal/thread/ Cross-mailbox thread collection
internal/presence/ Agent presence metadata
```
Mailbox layout:
```text
<root>/agents/<agent>/inbox/{tmp,new,cur}/
<root>/agents/<agent>/outbox/sent/
<root>/agents/<agent>/receipts/
<root>/agents/<agent>/dlq/{tmp,new,cur}/
<root>/bridge/{host-id,identity,trusted/<host>,outbox,drop,receipts}/
```
## Core Concepts
**Atomic delivery**: Writers create and sync a file under `tmp`, then rename it
atomically into `new`. Readers scan only `new` and `cur`.
**Message format**: JSON frontmatter is followed by `---` and a Markdown body.
The header contains schema, ID, sender, recipients, thread, subject, creation
time, refs, priority, kind, labels, context, and optional reply-routing fields.
P2P thread names use `p2p/<lower_handle>__<higher_handle>`.
**Receipts**: Consumers write `drained` or `dlq` receipts under their own
mailbox. Use `receipts list`, `receipts wait`, or `send --wait-for` to inspect
delivery without treating a wake notification as consumption proof.
**Sessions**: Named sessions are child queue roots. A participating shell is
pinned by `AM_ROOT`, `AM_BASE_ROOT`, and `AM_SESSION`; AMQ-managed identity
tokens authenticate roots. Participating commands fail closed on a mismatch.
Use `--session` or `--project` for routing, not a foreign raw `--root`. See
[Session routing and safety](docs/session-routing.md).
**Wake state**: Wake ownership, injector targets, lifecycle serialization,
readiness, and repair continuity have separate commit domains. Never infer one
from another or weaken an uncertain state. See [Wake operations](docs/wake-operations.md),
[wake state invariants](docs/wake-state-invariants.md), and the
[doorbell acknowledgement policy](docs/wake-doorbell-acknowledgement.md).
**Managed launch recovery**: A mode-0600 journal closes the create-before-binding
crash window. A matching binding is authoritative; otherwise the backend must
prove absent or adoptable state. Uncertain or partial state is action-required
and preserved. See [Managed launch recovery](docs/launch-recovery.md).
**Extension metadata**: Higher layers own data below
`<AM_ROOT>/extensions/<layer>/` or
`<AM_ROOT>/agents/<handle>/extensions/<layer>/`. AMQ does not execute extension
code and cleanup does not remove extension data. See
[the layer extension ADR](docs/adr-layer-extensions.md).
Two-host fleets, alias routing, and the v1 kill-list are
[the two-host fleets ADR](docs/adr-two-host-fleets.md). Companion `amq-bridge`
wire format is [the bridge protocol ADR](docs/adr-bridge-protocol.md); the
proven hop is `apply-file`, and HTTPS needs an operator-provided rendezvous.
Wake capability (no silent downgrade) is
[the wake capability-vector ADR](docs/adr-wake-capability-vector.md). Remote
control of a running harness session is
[the remote-control ADR](docs/adr-remote-control.md), with installed seams in
[the compatibility manifest](docs/remote-compat.md). Operator commands are
[the amq-remote companion](cmd/amq-remote/README.md). Preview
ACP v2 is [the amq-acp companion](cmd/amq-acp/README.md).
## Configuration
- Configuration lives in four scopes: agent (`<root>/agents/<me>/`), root
(`<root>/meta/`), project (`.amqrc`, `.amq/launch.json`), and user
(`~/.amq/`). New per-user files go under `~/.amq` through `internal/amqhome`;
no feature joins its own home path.
- Rule: a long-running process must hot-reload its configuration. A change
applies without a restart, a refused edit keeps the last good value, and
identity bound into locks, targets, or resume state (`--me`, `--root`,
`--inject-*`) is restart-only. Do not add configuration that a running
process reads only at startup. Which processes reload what is in
[Configuration](docs/configuration.md#hot-reload).
See [Configuration](docs/configuration.md).
## CLI Commands
Use the [generated CLI reference](docs/cli.md) or `amq <command> --help` for
exact flags. This table defines the owning workflow for each surface.
| Area | Commands | Contract |
| --- | --- | --- |
| Onboarding | `setup`, `launch` | Configure once, then reconcile and print or run the declared launch plan. The [README Getting started](README.md#getting-started) is canonical. |
| Sessions | `session create`, `session list`, `session resume` | Create explicitly, inspect available sessions, or resume stored conversations. |
| Shell context | `env`, `who`, `shell-setup`, `completion` | Set or inspect a complete context and configure shell integration. |
| Messaging | `send`, `reply`, `list`, `read`, `drain`, `thread`, `trace` | Deliver, ingest, inspect, and follow conversations. Prefer `drain --include-body` for handoffs. |
| Delivery proof | `receipts list`, `receipts wait` | Inspect consumer-local `drained` and `dlq` outcomes. |
| Live waits | `watch`, `monitor` | Wait for arrivals; `monitor` also drains and emits receipts. |
| Routing | `route explain`, `presence set`, `presence list` | Explain a route and publish or inspect advisory presence. |
| Health | `doctor`, `cleanup`, `upgrade` | Diagnose, perform explicit safe cleanup (including exact stuck launch journals and one empty agent mailbox), or update the binary. |
| Wake | `wake`, `wake check`, `wake config`, `wake repair`, `wake recover-owner`, `wake retire` | Notify, inspect capability, change live settings, and make identity-safe lifecycle changes. |
| DLQ | `dlq list`, `dlq read`, `dlq retry`, `dlq purge` | Inspect and explicitly recover or purge corrupt messages. |
| Low-level provisioning | `init`, `coop init`, `coop exec` | Create raw queues or enter an agent process. See [COOP.md](COOP.md). |
| Swarm bridge | `swarm list`, `join`, `leave`, `tasks`, `claim`, `complete`, `fail`, `block`, `bridge` | Interoperate with Claude Code Agent Teams. |
| Integrations | `integration symphony`, `integration kanban` | Convert external lifecycle events into AMQ messages. See [the adapter contract](docs/adapter-contract.md). |
Exit codes are `0` success, `1` general error, `2` usage, `3` not found, `4`
timeout, `5` context mismatch, and `6` action required. JSON output does not
change exit codes. `--json-schema` requires `--json`.
`send` and `reply` resolve `--body` from a literal, `@file`, or stdin. Empty or
whitespace-only input is a usage error unless `--allow-empty` is explicit.
## Message Kinds
| Kind | Reply kind | Default priority | Purpose |
| --- | --- | --- | --- |
| `review_request` | `review_response` | normal | Request review. |
| `review_response` | - | normal | Return review findings. |
| `question` | `answer` | normal | Ask for a decision or fact. |
| `answer` | - | normal | Answer a question. |
| `decision` | - | normal | Record a decision. |
| `brainstorm` | - | normal | Explore options. |
| `status` | - | low | Report progress or state. |
| `todo` | - | normal | Assign work. |
When work starts, reply with `kind=status` and an ETA. Review responses remain
`normal` by default. Use `--priority urgent` on `send` or `reply` for a
time-critical verdict or unblocking request that must bypass an optional wake
hold. Urgent priority alone does not trigger an interrupt notice; that also
requires the configured interrupt label.
## Dead Letter Queue
`read`, `drain`, and `monitor` move messages with invalid serialization or
headers to DLQ and emit a `dlq` receipt. The envelope records the parse error,
retry count, and retry state. A successful retry keeps a terminal audit in
`dlq/cur` until explicit purge.
`delivered` is terminal and idempotent. `pending` or legacy `indeterminate`
without a visible inbox destination refuses retry, including with `--force`.
The flag bypasses only the retry-count limit. Bulk JSON separates new retries,
already-delivered records, and skipped records.
## Doctor and Wake Operations
`doctor` checks installation, root selection, permissions, configuration, and
skill setup. `--ops` adds queue depth, sibling backlogs, DLQ age, presence,
wake health, worktree diagnostics, and integration hints.
Mailbox and wake repair preserve existing messages and fail closed on unsafe
paths, symlinks, conflicting session pins, or concurrent replacement. Doctor
can inspect an explicit mismatched root, but mutation requires the
authenticated pinned base or explicit `--root --ignore-session-pin`.
Before wake mutation, run `amq wake check --me <agent> --json`. Only
`restart_capability=agent_safe` permits agent-side action. Repair, owner
recovery, and retirement revalidate exact identity and have distinct scopes.
See [Wake operations](docs/wake-operations.md) for the full contract.
## Coordination Workflows
During active work, run `amq drain --include-body` between phases. Use
`send --wait-for drained` when delivery proof matters. Use `watch` only when no
wake is live for you; a live wake already delivers a doorbell, and a blocking
wait would hold your turn while the doorbell queues behind it. Reply to the
initiator, preserve the existing thread, send status at start and phase
boundaries, and finish with changes and verification.
The [co-op guide](COOP.md) owns peer roles, phased flow, wake use, supervisor
recipes, and troubleshooting. The `amq-cli` skill owns agent-facing command
mechanics. The `amq-spec` skill owns research-discuss-draft-review workflows
and the human approval gate. Swarm mode is a bridge to Claude Code Agent Teams;
AMQ messages to a teammate still require the team leader to relay them.
## Testing
Run the tests of the packages you changed, narrowest first. The pre-push hook
runs `make check`; CI runs the full `make ci` suite. Useful focused commands
include:
```bash
go test ./internal/fsq -run TestMaildir
go test ./internal/cli -run '<relevant test>'
go test ./internal/sessionguard
make check-skills
```
Opt-in live proofs (`AMQ_CMUX_LIVE`, `AMQ_GHOSTTY_LIVE`, `AMQ_CLAUDE_LIVE`,
`AMQ_CODEX_LIVE`, `AMQ_TMUX_LIVE`) skip unless the env is `1`. They are not
part of `make ci`. Commands are in
[Contributing: live proofs](CONTRIBUTING.md#live-proofs-opt-in).
SessionStart hook-script tests in `internal/keepalive/hookinstall` run the real
Bash script and skip unless `AMQ_HOOK_SCRIPT_TESTS=1`. Linux and macOS CI run
them with `-p 1` in a separate serial step, outside the parallel package suite.
Two kinds of test exist. One small happy-path test per user-visible behavior
ships in the same PR as the behavior. A regression test for a defect observed
in the field, in CI, or by pre-merge review ships in the same PR as the fix and
reproduces that failure and nothing more; its comment names the bead, review
finding, or CI run it came from.
Both are deterministic and fast (under 5 seconds, no child process, no
network) unless the observed defect lives at exactly that boundary and cannot
be reproduced without it. Do not add speculative negative cases, mutation
demonstrations, guard tests about tests, or tests for existing behavior with
no observed defect. A slow or flaky test is deleted or rewritten to this bar,
not tuned.
Before you add a test, name the contract it protects, the regression that
makes it fail, and why existing coverage misses it. Each contract has one
keeper at its strongest boundary: add a row to that table, not a near
duplicate. A test that needs an export, flag, env var, or wrapper that no
production caller uses belongs at the real boundary instead. A regression
test must fail on the pre-fix code; check that privately before it ships.
## Security
- Queue directories use mode 0700 and files use mode 0600.
- Handle and message ID validation prevents path traversal.
- Unknown handles warn by default; `--strict` changes warnings to errors.
- With `--strict`, unreadable or corrupt configuration is also an error.
- External injectors execute local code. Their executable and ordered fixed
arguments form the saved identity; message-derived payloads are sanitized.
- Preserve uncertain ownership or filesystem state. Never add a force path
that guesses at process, target, generation, or owner identity.
## Commit Conventions
- Install the repository hooks with `./scripts/install-hooks.sh`.
- Use conventional, descriptive commits such as
`fix(wake): preserve replacement generation`.
- Run the focused tests before committing and follow every pushed CI run to
completion.
- Do not commit placeholders, weaken a validator, regenerate goldens to hide a
defect, or split code from the test that ships with it.
+ - PR titles, PR bodies, and commit messages state the user-visible change and
+ the reason. A bead id or review finding may appear once, at the end, as a
+ reference. Do not add review-round labels or narrate rulings. Test names
+ describe behavior, not bead ids.
+ - Production code comments state invariants, not provenance: no bead ids,
+ review rounds, or reviewer names. Test comments follow the Testing rule.
## Documentation Policy
- - Keep `README.md` as the canonical install and onboarding path.
+ - Keep `README.md` as the canonical onboarding path and `INSTALL.md` as the
+ one home for install, companion, and platform facts.
- Keep `COOP.md` as the full co-op and supervisor operations guide.
- Keep `CLAUDE.md` as a concise project index and engineering contract.
- Keep `docs/` evergreen: architecture, protocol contracts, and operational
references only. Plans and frozen specs belong in issues, PRs, or the AMQ
spec workflow.
- Describe current behavior in present tense. Put one-sentence known
limitations beside an issue link instead of adding historical narration.
## Skill Development
Canonical skills live in `skills/amq-cli/` and `skills/amq-spec/`.
`.claude/skills/`, `.agents/skills/`, and `.grok/skills/` are symlinks to those
directories so local runs use repository changes. Project skills take
precedence over user installations.
Edit only the canonical directory, bump skill metadata when publishing, run
`make check-skills`, and test the project-local skill. Do not create divergent
copies. See the [README skill install](README.md#2-install-skill) for
installed-skill commands.