Session routing and safety
August 19, 2026 ยท View on GitHub
AMQ keeps each named session in its own queue root. A participating shell is
pinned by AM_ROOT, AM_BASE_ROOT, and AM_SESSION; identity-aware shells
also carry AMQ-managed root identity tokens. For a named session,
AM_BASE_ROOT is the authorized parent. For a sessionless context, it is the
exact root and AM_SESSION is empty. Do not set the identity tokens manually.
Root selection
Root precedence is explicit --root, AM_ROOT, project .amqrc,
AMQ_GLOBAL_ROOT, then eligible implicit fallbacks. Within a Git checkout,
only repo-local implicit state is eligible. An unreadable or invalid project
.amqrc blocks lower-precedence fallback; an explicit --root or AM_ROOT
can override it intentionally.
A direct --root selects a queue. It is not a federation route. send refuses
an explicit root in a different base tree when the caller has an active
session and supplies no --project, --session, or --from-session. Use
--project or --session for replyable routing because these options add the
sender-origin metadata that reply needs. Bare-root scripts without session
evidence keep direct-root behavior and can create an unreplyable message.
Session guard
read, drain, monitor, watch, and DLQ commands compare their target with
the active pin before reading or moving mailbox state. watch and monitor
repeat this check while they wait. send and reply apply the same guard to
their local source. A mismatch exits with code 5. Target routing does not
authorize a mismatched source.
An implicit participating command also refuses when its pin conflicts with an initialized queue in the current project. A live identity-bound sessionless pin is the narrow exception: when both identity tokens authenticate its exact root, that explicit context outranks ambient project discovery. Named, legacy, incomplete, stale, and mismatched pins still refuse.
Use a named --session or --project route when possible. For intentional
raw-root access, --ignore-session-pin requires a non-empty explicit --root.
Explicitly empty root or session values are usage errors. --base-root gives
doctor configuration authority only; it does not bypass the guard.
list and doctor --root remain read-only inspection paths on a mismatch and
report a warning. Doctor repairs are allowed for the authenticated pinned base
root or with an explicit --root plus --ignore-session-pin. Other mismatch
repairs are skipped and reported as structured doctor errors while the doctor
process continues with exit 0.
doctor --fix-mailboxes creates only missing required directories for the
configured roster and reserved user handle. It reports discovered mailboxes
outside that roster but never repairs them. It does not edit, move, overwrite,
or delete message files; unsafe types, symlinks, unreadable paths, and
concurrent layout changes fail closed. --base-root must name the target or
its direct parent.
Message publication uses a unique attempt file in inbox/tmp and a
no-replace tmp -> new commit. An existing same-name new file is never
overwritten: identical bytes are an idempotent success, while different bytes
preserve both copies and return a collision. Claiming new -> cur also refuses
to replace a retained same-name message.
send --from-session is deliberately double-explicit and resolves its source
from the supplied raw base; callers must verify that base. See
issue #104.
Environment replacement
Every shell-mode amq env result replaces AM_ROOT, AM_ME, AM_BASE_ROOT,
and AM_SESSION as one context. Sessionless output pins the exact root and
emits an empty session. An ambient root that conflicts with an existing pin is
rejected unless a non-empty --root or --session explicitly repins it.
amq env --session routes from a valid pinned base before it checks project
configuration.
Creation and backlog discovery
Create named sessions explicitly with amq session create <name>. coop exec
uses the declared default session, or collab when no default is declared.
Its missing-session bootstrap is deprecated except for zero-configuration
collab; scripts must use session create or init --root. Bare repositories
cannot host implicit bootstrap, and coop exec --no-init keeps the refusal.
An empty drain or list --new performs a shallow sibling-session scan and
prints exact inspection commands. doctor --ops reports the same state as
sibling_backlog. When the active session differs from the base queue,
doctor --ops can also report base_backlog; JSON output includes the target,
session, agent, pending count, and exact inspection command.
Git worktree diagnostics remain in doctor --ops, not the send path. Relative
and auto-detected roots belong to one worktree; deliberate sharing requires an
absolute .amqrc root or AMQ_GLOBAL_ROOT.