From dca3498237f411e3f47529036addeab1ce3209d2 Mon Sep 17 00:00:00 2001 From: codex Date: Tue, 25 Aug 2026 17:44:39 +0200 Subject: [PATCH] chore: commit work in progress before registrar reconciliation Authorised as part of the CUST-WP-0068 identity cleanup. The registrar requires a clean worktree, and these changes were already present in the checkout. Refs CUST-WP-0068 Assistant: claude-code Assistant-Model: opus Assistant-Process: 2583210@bnt-lap001 Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006 --- SCOPE.md | 6 +- WORK-RECORDS.md | 5 + spec/worker-coordination-service-v0.1.md | 443 ++++++++++++++++++ ...ION-WP-0003-worker-coordination-service.md | 103 ++++ 4 files changed, 555 insertions(+), 2 deletions(-) create mode 100644 spec/worker-coordination-service-v0.1.md create mode 100644 workplans/COORDINATION-WP-0003-worker-coordination-service.md diff --git a/SCOPE.md b/SCOPE.md index 815d445..aa06558 100644 --- a/SCOPE.md +++ b/SCOPE.md @@ -19,6 +19,8 @@ coordination-engine captures coordination models, specs, and registry entries fo ## In Scope - Coordination specs, history, and registry indexes +- Headless coordination runtime, including cross-repository worker coordination + (observation, leases, wake-up, checkpoints, safety gates, and receipts) - State Hub workplans and agent instructions - Capability registration when coordination patterns stabilize @@ -26,6 +28,6 @@ coordination-engine captures coordination models, specs, and registry entries fo ## Out of Scope -- Runtime orchestration engine implementation (future repos) +- Replacing the systems coordinated through adapters (issue trackers, chat, + workflow, notification, delivery, or evidence systems) - Replacing issue trackers or chat systems - diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index 94c6535..2da3abd 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -10,7 +10,12 @@ | --- | --- | --- | --- | --- | | workplan | COORDINATION-WP-0001 | finished | — | workplans/COORDINATION-WP-0001-statehub-bootstrap.md | | workplan | COORDINATION-WP-0002 | finished | — | workplans/COORDINATION-WP-0002-coordination-model-spec.md | +| workplan | COORDINATION-WP-0003 | ready | — | workplans/COORDINATION-WP-0003-worker-coordination-service.md | | task | COORDINATION-WP-0001-T01 | done | — | workplans/COORDINATION-WP-0001-statehub-bootstrap.md | | task | COORDINATION-WP-0001-T02 | done | — | workplans/COORDINATION-WP-0001-statehub-bootstrap.md | | task | COORDINATION-WP-0001-T03 | done | — | workplans/COORDINATION-WP-0001-statehub-bootstrap.md | | task | COORDINATION-WP-0002-T01 | done | — | workplans/COORDINATION-WP-0002-coordination-model-spec.md | +| task | COORDINATION-WP-0003-T01 | done | — | workplans/COORDINATION-WP-0003-worker-coordination-service.md | +| task | COORDINATION-WP-0003-T02 | wait | — | workplans/COORDINATION-WP-0003-worker-coordination-service.md | +| task | COORDINATION-WP-0003-T03 | wait | — | workplans/COORDINATION-WP-0003-worker-coordination-service.md | +| task | COORDINATION-WP-0003-T04 | wait | — | workplans/COORDINATION-WP-0003-worker-coordination-service.md | diff --git a/spec/worker-coordination-service-v0.1.md b/spec/worker-coordination-service-v0.1.md new file mode 100644 index 0000000..fe8474e --- /dev/null +++ b/spec/worker-coordination-service-v0.1.md @@ -0,0 +1,443 @@ +# Worker Coordination Service v0.1 + +**Status:** Proposed contract +**Owner:** coordination-engine (contract and runtime); State Hub and +`tmux-amq` are external local adapters. +**Request:** net-kingdom, “automatic worker wake-up and dependency coordination” + +## 1. Problem and outcome + +Several repository terminals run independent worker agents. Today an operator +must repeatedly inspect each repository, relay results, and issue prompts that +are effectively a scheduler. The service defined here turns State Hub changes +into safe, deduplicated wake-ups while keeping repository agents responsible for +publishing workplan/task/message state. + +The desired loop is: + +```text +State Hub change + -> observe and normalize + -> determine actionable task/message + -> acquire idempotent lease + -> wake owning repo session + -> agent resumes, checkpoints, and updates State Hub + -> dependent work becomes actionable and is evaluated again +``` + +The service does not execute repository code, invent task state, or replace +State Hub as the source of truth. It does own the observation, lease, policy, +checkpoint, and wake orchestration runtime. + +## 2. Inputs and normalized trigger + +The observer MUST support polling initially and MAY support a State Hub event +subscription later. It watches: + +* workplan status and task status/dependencies; +* unread coordination messages and message read/ack state; +* `needs_human` and intervention notes; +* progress/checkpoint receipts. + +Each source change is normalized to a trigger with an idempotency key: + +```yaml +WorkerTrigger: + id: string + source: workplan | task | message | checkpoint + source_id: string + source_revision: string + target_repo: string + target_agent: string? + reason: task_actionable | dependency_satisfied | inbox_message | retry_due | checkpoint_resume + observed_at: timestamp +``` + +The idempotency key is `(source, source_id, source_revision, target_repo)`. +Repeated observations MUST collapse to one pending trigger. + +## 3. Actionability and safety gates + +A trigger is actionable only when its task/workplan is active or ready, its +dependencies are satisfied (or the message explicitly requests action), and no +terminal safety gate applies. The service MUST stop and leave a durable receipt +when any of these are true: + +* `needs_human` is set or an intervention note requests review; +* credentials, secrets, access tokens, or private key material are needed; +* destructive, production, live, financial, or externally visible action is + proposed without an approved policy/authority; +* a policy decision, scope expansion, or ambiguous ownership requires a human; +* the target session cannot be authenticated or its repository identity does not + match the trigger. + +Safety-gated work is never silently retried or rerouted to another agent. +Retry behavior is configuration-driven: ordinary triggers use bounded +exponential backoff, while safety-gated retries default to zero and may only be +enabled by an explicit policy. No retry setting may bypass the safety gate. + +## 4. Lease and deduplication protocol + +When connected, coordination-engine atomically claims a short-lived coordination +lease before waking an agent. Independently, `tmux-amq` maintains its own local +queue lease so messages remain deliverable while coordination-engine is offline. +The two leases are correlated but neither is the other's storage dependency: + +Coordination-engine stores coordination leases, deduplication keys, and receipts +in a local SQLite database. State Hub receives sanitized projections when it is +available; it is not required for local queue delivery or lease recovery. + +```yaml +WorkerLease: + trigger_id: string + lease_id: string + owner: coordination-engine + target_repo: string + target_agent: string? + state: offered | acknowledged | running | checkpointed | completed | retry_wait | stopped + attempt: integer + acquired_at: timestamp + expires_at: timestamp + last_checkpoint_at: timestamp? + coordination_endpoint_id: string? + local_lease_id: string? +``` + +Only one non-expired coordination lease may exist for a trigger. A wake request is retried +with the same `lease_id`; the receiver MUST treat duplicate requests as no-ops. +The agent acknowledges the lease before work begins, renews it while active, +and releases it with a checkpoint or terminal result. Expiry moves the lease to +`retry_wait` with bounded exponential backoff and an attempt limit. Exhaustion +produces a stopped receipt for operator review. + +## 5. Session wake contract + +The runtime integrates with `tmux-amq`, a separate local repository that owns +tmux session lifecycle, durable queueing, local leases, and PTY injection. +`tmux-amq` MUST remain functional when coordination-engine is unavailable. +Only repositories registered in gita may be addressed. A session may be started +with, for example, +`tamq --cmd "codex" net-kingdom railiance-platform`; the bridge opens one +terminal per repository and runs the command. Messages addressed as +`@repo: text` are queued/injected into that repository's terminal as +`#sender-repo: text`. Coordination-engine calls the bridge through a local, +authenticated adapter; it does not manipulate tmux directly. + +Each tmux-amq endpoint is identified as `tmux-amq-`, where `` is the +tmux server PID. Within one endpoint, a repository slug maps to exactly one +tmux window; duplicate windows for the same repo are rejected or reconciled +before attach. Different endpoint PIDs may independently host the same repo. + +Outbound messages typed directly by an agent are detected through a tamq +tmux-control-mode client. The client intercepts input lines beginning with +`@:` and submits a structured local message using the +authenticated source window/repository. It does not wrap or replace the agent +process. Control-mode parsing MUST preserve ordinary input unchanged and must +not treat message-like text inside an unrelated multiline command as a message +unless the configured parser recognizes a complete address line. + +If tmux control-mode interception is unavailable, tamq leaves ordinary terminal +use unchanged, marks interception unavailable in status/receipts, and does not +fall back to pane scraping or unverified injection. Operators may explicitly +use `tamq send @repo: message` as a degraded path. + +tmux-amq MUST retain a local message history sufficient to inspect delivery +state and export it to a messages file. It MUST also support replaying a +messages file into a selected endpoint. Replay creates a new batch identifier, +passes each entry through normal gita-target validation, policy checks, and +deduplication, and records the original message ID as provenance. Replay MUST +not bypass safety gates or silently overwrite an existing message. + +History files use newline-delimited JSON (JSONL): one complete message envelope +per line, including message ID, sender/target, body, timestamps, state, and +replay provenance. JSONL exports are appendable and replayable as streams. + +The repository is `tmux-amq`, but its executable is `tamq` (Tmux Agentic Message +Queueing). It MUST provide conventional Unix CLI behavior, including +`--help`/`-h`, `--version`/`-V`, non-zero exit status on errors, diagnostics on +stderr, and machine-readable output options where commands produce records. + +Default filesystem locations follow XDG conventions: + +```text +config: ${XDG_CONFIG_HOME:-$HOME/.config}/tamq/config.toml +state: ${XDG_STATE_HOME:-$HOME/.local/state}/tamq/tamq.sqlite3 +socket: ${XDG_RUNTIME_DIR:-/tmp}/tamq.sock +``` + +`TAMQ_CONFIG`, `TAMQ_STATE_DIR`, `TAMQ_SOCKET`, and `TAMQ_POLICY_PROFILE` may +override these defaults. The CLI MUST provide tab completion through +`tamq completion bash|zsh|fish` and expose completion for subcommands, +options, and known gita repository targets. + +Version 0.1 supports direct addressing only. Unknown or unregistered targets +are rejected; there is no broadcast or wildcard routing. If a target session is +absent, `tmux-amq` opens it and starts the configured command. The sender label +in the injected form is derived from the authenticated source repository, not +from message text. + +Delivery acknowledgment is configurable and defaults to `injected`, meaning the +message is considered delivered once tmux-amq successfully writes it to the +target PTY. An optional `acknowledged` mode retains the message until the target +agent explicitly confirms receipt; retries use the same message ID. This +facility carries coordination messages, not task/workplan state. Substantive +work, dependencies, and completion remain represented by State Hub facilities. + +Message bodies are human-readable UTF-8 plain text, limited to 8 KiB and +preserving multiline content. The transport envelope carries structured IDs, +sender/target slugs, timestamps, and policy metadata. Binary payloads and +oversized bodies are rejected. Message text is never interpreted as task or +workplan state. + +On attach, `tmux-amq` connects to a coordination-engine Unix domain socket and +performs a handshake, receiving a unique +`coordination_endpoint_id`. That identifier namespaces all messages and leases +originating from the connected endpoint, so local IDs can safely be reused +across different machines or sessions without cross-endpoint collision. +Coordination-engine MUST treat `(coordination_endpoint_id, local_message_id)` +as the message identity and preserve the endpoint ID in receipts. + +The socket protocol MUST use structured messages and authenticate the peer by +filesystem ownership/permissions. The default deployment runs both processes +under the same approved local user, uses socket mode `0600`, and validates Unix +peer credentials; bearer tokens in command lines are not required. The initial +handshake includes the gita +registered repository slugs, tmux session name, and agent command; the response +contains the endpoint ID and negotiated lease/receipt capabilities. No TCP +listener is required for the local integration. + +coordination-engine MUST refresh the local gita registry before accepting an +attach or addressing a target. It accepts only exact registered repository +slugs, requires the attached session to report the matching slug/path, and +never auto-clones or auto-registers a repository. + +The adapter interface is: + +```yaml +WakeRequest: + lease_id: string + target_repo: string # must be gita-registered and an active tmux-amq target + target_agent: string? + trigger: WorkerTrigger + checkpoint: Checkpoint? + prompt: string + +WakeAck: + lease_id: string + session_id: string + accepted_at: timestamp + capability: resumed | started | unavailable +``` + +The prompt is generated from the trigger and the standard continuation policy; +it MUST contain no secret values. The target agent remains the authority for +editing files, calling tools, and updating State Hub. + +## 6. Checkpoints and standard continuation policy + +Agents SHOULD publish a checkpoint before yielding or stopping: + +```yaml +Checkpoint: + lease_id: string + task_id: string? + summary: string + files_changed: [string] + next_action: string? + blocked_reason: human | secret | destructive | policy | dependency | unavailable | null + recorded_at: timestamp +``` + +When a lease is resumed, the service supplies the latest checkpoint and asks +the agent to continue. The following policy templates are recognized, in order: + +1. inspect open work and implement the highest-priority actionable item; +2. if no work is open, reconcile `SCOPE.md` with `INTENT.md`, record gaps under + `history/`, and create/register a workplan for the most relevant gap; +3. review pending work, refine it where needed, and implement the next safe item; +4. if no safe work remains, close the session and write a perspective entry to + the configured `hall-of-helix` destination. + +Templates are suggestions, not permission to bypass safety gates or invent +scope. A repository may override them through its agent instructions. + +### 6.1 Policy profiles + +Automatic behavior is selected through named policy profiles rather than code +changes. The default profile is conservative: + +```yaml +policy: + profile: default + profiles: + default: + allow: [statehub_read, repo_inspect, repo_edit, local_checks, + state_updates, coordination_messages, tmux_wake, transient_retry] + require_human: [secrets, destructive, live_external, scope_change, + ambiguous_ownership, external_publish, financial, legal] + safety_gated_max_attempts: 0 +``` + +Profiles MUST be selected by configuration, validated at startup, and included +by name/version in every lease and receipt. A profile cannot grant access to +credentials that are unavailable through the configured credential-routing +system, and every profile remains subject to authentication and repository +boundary checks. + +## 7. Receipts and observability + +Every trigger, lease transition, wake attempt, checkpoint, stop, retry, and +completion MUST emit a sanitized progress/audit receipt containing identifiers, +status, reason, timestamps, and retry metadata. Receipts MUST exclude prompt +secrets, credentials, payload contents, and unrestricted terminal output. + +The service SHOULD publish receipts through State Hub progress/events and retain +enough correlation data to explain why a dependent task was (or was not) woken. + +## 8. Ownership boundary + +Repositories publish workplan/task/message state and consume wake requests. They +MUST NOT add independent polling daemons for this feature. Coordination-engine +owns the service process, observation, lease/deduplication, retry policy, and +wake dispatch. State Hub owns durable task/message state. Terminal/session +control is a pluggable adapter owned by coordination-engine and deployed with +the runtime; its underlying bridge remains an external dependency. + +## 9. Operator decisions required before implementation + +The following choices cannot be inferred safely from repository documents: + +1. Which terminal/session bridge is authorized to wake or resume workers? +2. What local SQLite retention and backup policy should be used for leases and + receipts? +3. Default polling interval, lease duration, renewal interval, and retry limit? +4. Which actions are pre-approved policies versus always human-gated? +5. What service identity and authentication path may write State Hub and invoke + the wake adapter? +6. Which Unix socket path and filesystem ownership should the local deployment + use? + +### 9.1 Runtime configuration + +The following values MUST be configurable without code changes: + +```yaml +coordination: + statehub_poll_interval_seconds: 15 + wake_ack_timeout_seconds: 30 + lease_renew_interval_seconds: 10 + retry_backoff_seconds: [5, 15, 60, 300] + max_attempts: 4 + safety_gated_max_attempts: 0 + delivery_ack_mode: injected # injected | acknowledged +``` + +Deployments may choose different values, including up to nine attempts. The +service MUST validate `max_attempts` and `safety_gated_max_attempts` in the +range 0..9 and record the effective configuration version in receipts. + +State Hub observation uses the configured polling interval (15 seconds by +default), backs off exponentially while unavailable, and resumes promptly when +connectivity returns. Local tmux-amq messaging is never blocked by State Hub +outages; receipt projections are queued for asynchronous publication. + +The State Hub endpoint is configurable through `STATEHUB_API_BASE` or +`statehub.api_base`, defaulting to `http://127.0.0.1:8000`. Credentials MUST be +resolved through the approved credential-routing mechanism and never stored in +tamq configuration, SQLite, JSONL exports, tmux commands, or receipts. Missing +credentials leave local messaging operational while State Hub projections stay +pending. + +`tamq status` exposes live endpoint/session, queue, lease, and State Hub +connectivity information. `tamq history` exposes full local delivery history; +State Hub receives sanitized receipts and correlation IDs only. Message bodies +remain local unless explicitly exported to JSONL. + +History is never deleted automatically. When invoked without explicit filters, +`tamq purge` uses dynamic defaults equivalent to `--before 365d` and +`--max-size 100MB`; purge requires confirmation and may be preceded by JSONL +export. On startup, if history exceeds 100 MB, tamq prints an advisory such as: +`Size of history is NNN MB since YYMMDD, exceeding 100MB. Consider using 'tamq purge'.` + +`tamq purge` performs a dry-run summary by default, reporting the matching +message count, date range, and estimated bytes. Interactive execution requires +explicit confirmation; non-interactive execution requires `--yes`. Combined +filters are allowed, and each purge emits a receipt containing filters and +counts without message bodies. + +`tamq start` creates or reuses the tmux server/windows and starts the local +service; `tamq serve` runs the Unix-socket service in the foreground; `tamq stop` +stops the service without killing worker terminals or deleting queues. The +initial repo-opening command MUST ensure the service is alive and start it +automatically when absent. Startup is idempotent and lock-protected so two +concurrent repo opens cannot create duplicate services. `--detach` is required +to daemonize; foreground operation is the default for diagnostics. + +If automatic startup fails, tamq reports the error on stderr, returns non-zero, +does not register an endpoint or claim delivery, and leaves existing sessions +and SQLite data untouched. `--no-service` may explicitly open terminals without +messaging, with a visible warning. + +## 10. Logging and diagnostics + +Foreground `tamq serve` logs to stderr. Detached operation logs to +`${XDG_STATE_HOME:-$HOME/.local/state}/tamq/tamq.log`. The default level is +`info`; `--quiet` suppresses non-errors, `--verbose` enables debug diagnostics, +and `--json` requests structured output where applicable. Message bodies, +credentials, tokens, and unrestricted PTY output are omitted by default. + +`--orwell` is an explicitly unsafe, non-production diagnostic mode that logs +otherwise-omitted diagnostic fields, including message bodies and credential +material when available. It MUST be supplied per invocation, emit a prominent +warning, write only to a local mode-`0600` sink, never project to State Hub, and +be rejected by the default production policy profile. Operators are responsible +for purging Orwell logs after diagnosis. + +This practice is proposed for canonization as the InfoTechCanon PracticePattern +`practice-pattern/orwell-logging-diagnostics` (`OrwellLoggingDiagnostics`). The +canonical owner is info-tech-canon; tamq is a concrete known use, not the owner +of the general practice. + +The first runtime implementation uses Python 3.11+ and should prefer standard +library components (`sqlite3`, `asyncio`, Unix sockets, and CLI primitives) so +local installation remains small and reliable. + +The project is packaged through a root `pyproject.toml` with a `tamq` console +entry point. It must support `uv tool install .`, editable development installs, +and package-derived `tamq --version` output. + +Verification uses layered tests: pytest unit tests for state/config/protocol +logic; Unix-socket integration tests with fake tmux-amq peers; fake State Hub +and gita registry tests; CLI behavior tests; and opt-in live smoke tests only +when explicitly configured. Tests must not require credentials or mutate live +systems. + +The Unix-socket protocol is versioned independently from package versions, +starting at `0.1`. Attach handshakes negotiate protocol version and capabilities; +incompatible major versions are rejected, compatible minor versions may +interoperate, and the negotiated values are retained in endpoint/receipt data. + +SQLite stores an explicit schema version. Startup applies forward migrations in +transactions, creates a timestamped backup before altering message/lease +tables, and refuses to run against a newer schema. Message history is never +silently dropped; `tamq db-version` reports the current schema. + +SQLite uses WAL mode, foreign-key enforcement, and a configurable busy timeout +(5 seconds by default). Queue and lease transitions are transactional, with a +single coordination-engine writer path and concurrent readers. Transient busy +errors may retry without creating duplicate messages. + +On `SIGTERM` or `SIGINT`, the service stops accepting socket requests and new +leases, finishes the current transaction, marks the endpoint disconnected, +closes the socket, preserves queues/leases for recovery, emits a sanitized +shutdown receipt, and exits within a configurable grace period (10 seconds by +default). + +Default CI gates are `uv run pytest`, `git diff --check`, +`python -m compileall src`, `tamq --help`, and `tamq --version`; package +install/build and live smoke checks are separate opt-in jobs. + +Health is local-only: `tamq status` is human-readable, `tamq status --json` is +machine-readable, and `tamq ping` performs a lightweight Unix-socket liveness +check. Status separates process/socket, SQLite, gita registry, State Hub, queue, +and lease health; no TCP health port is exposed. diff --git a/workplans/COORDINATION-WP-0003-worker-coordination-service.md b/workplans/COORDINATION-WP-0003-worker-coordination-service.md new file mode 100644 index 0000000..7f45c9e --- /dev/null +++ b/workplans/COORDINATION-WP-0003-worker-coordination-service.md @@ -0,0 +1,103 @@ +--- +id: COORDINATION-WP-0003 +type: workplan +title: "Worker coordination service contract" +domain: communication +repo: coordination-engine +status: ready +owner: codex +topic_slug: communication +created: "2026-08-23" +updated: "2026-08-23" +--- + +# Worker coordination service contract + +Define and implement the cross-repository worker wake-up and +dependency-coordination capability requested by net-kingdom. Coordination-engine +owns the protocol and runtime. State Hub and the separate `tmux-amq` local tmux +message queue are adapters. Only gita-registered repos are valid worker targets. + +## Publish the v0.1 contract + +```task +id: COORDINATION-WP-0003-T01 +status: done +priority: high +``` + +Authored `spec/worker-coordination-service-v0.1.md`, covering State Hub +observation, actionability gates, leases, deduplication, wake requests, +checkpoints, retries, safety stops, receipts, and operator decisions. + +## Agree adapter and deployment decisions + +```task +id: COORDINATION-WP-0003-T02 +status: wait +priority: high +``` + +The local transport is a Unix domain socket. Coordination-engine uses local +SQLite for coordination leases, deduplication, and receipts, projecting +sanitized state to State Hub. Net-kingdom/operator must choose the socket +path (same-user mode `0600` by default), `tmux-amq` handshake fields, SQLite +retention/backup policy, timers/retry defaults, the configured policy profile, +and strict gita registry validation. Policy profiles define the allowed and +human-gated action classes. v0.1 uses direct-only routing; broadcast is deferred. +Delivery acknowledgment is configurable and defaults to `injected`; this layer +does not duplicate State Hub task/workplan state. +Message bodies are UTF-8 plain text with an 8 KiB limit and structured metadata +kept in the transport envelope. +Endpoint identity is `tmux-amq-`; each endpoint has at most one +tmux window per gita repository. +tmux-amq must support local history inspection, export to a messages file, and +safe replay of that file through normal routing and policy checks. +History is retained by default; explicit `tamq purge` uses `--before 365d` and +`--max-size 100MB` defaults, with a startup advisory when history exceeds 100MB. +The service uses `tamq start`/`serve`/`stop`; first repo opening auto-starts an +absent service with an idempotent lock-protected check. +Logging defaults to safe stderr/file output; `--orwell` is an explicit, +non-production, local-only mode for otherwise-omitted sensitive diagnostics. + +## Establish OrwellLoggingDiagnostics practice pattern + +```task +id: COORDINATION-WP-0003-T04 +status: wait +priority: medium +``` + +Requested candidate canon artifact `practice-pattern/orwell-logging-diagnostics` +from info-tech-canon, with tamq as the first known use. Await canonical owner +review and registration. + +The first runtime implementation is Python 3.11+ with standard-library-first +dependencies. +Package through root `pyproject.toml` with a `tamq` console entry point and uv +install/editable-install support. +Verification uses pytest unit, fake-peer integration, CLI, and opt-in live +smoke tests without production credentials. +Default CI gates: `uv run pytest`, `git diff --check`, compileall, and tamq +help/version checks; package and live smoke checks remain opt-in. +The executable name is `tamq`, with Unix-standard `--help`/`-h` and +`--version`/`-V` flags. +Use XDG config/state/runtime paths with environment overrides and provide +`tamq completion bash|zsh|fish` for tab expansion. +`tmux-amq` independently owns its durable queue and local delivery leases. +Lease/retry timing and attempt counts are configuration parameters; the retry +ceiling is 9, while safety-gated retries default to 0 and require explicit +policy. Runtime ownership is coordination-engine; +tmux/session ownership is `tmux-amq`. + +## Implement the coordination runtime + +```task +id: COORDINATION-WP-0003-T03 +status: wait +priority: high +``` + +Deferred while `tmux-amq` is bootstrapped as the standalone local queue and +tmux control-mode endpoint. Coordination-engine integration will follow the +stable tamq Unix-socket protocol.