tmux-amq/spec/coordination-engine-adapter-v0.1.md
tegwick 6d2ccc7760
Some checks failed
tamq-ci / test (push) Failing after 5s
feat: complete reliable coordination adapter
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a03397-4d51-7fd1-8ff2-946eb22ea2bc
2026-08-26 08:11:09 +02:00

5.5 KiB
Raw Permalink Blame History

Coordination-engine ↔ TAMQ adapter contract v0.1

Status: implemented local-alpha contract. TAMQ owns this transport contract; coordination-engine owns trigger policy, coordination leases, checkpoints, and workflow state.

Boundary and authentication

The adapter connects to TAMQ's configured Unix-domain socket. The socket is mode 0600, and TAMQ accepts only the same Unix user through SO_PEERCRED when the platform exposes it. There is no TCP listener or command-line bearer token. The client opens a new connection for every operation, so restarting TAMQ needs no reconnect handshake or client-side session state.

The client first sends ping with protocol 0.1. Major versions must match and the service must advertise bounded_delivery_ack_v1 and idempotent_send_v1. Unknown minor capabilities are ignored. An incompatible major version or a missing required capability stops the wake before message admission.

Wake mapping

CoordinationEngineAdapter.wake(WakeRequest) resolves exactly one live endpoint whose registered repository list includes target_repo. Zero matches returns unavailable. Multiple matches require an explicit endpoint ID; TAMQ never chooses an arbitrary worker session.

The wake becomes a send request:

{
  "op": "send",
  "protocol": "0.1",
  "client_id": "coordination-engine",
  "idempotency_key": "<coordination lease id>",
  "correlation_id": "<trigger id>",
  "sender_repo": "coordination-engine",
  "target_repo": "<exact gita slug>",
  "endpoint_id": "<resolved TAMQ endpoint instance>",
  "provenance": "coordination_engine",
  "metadata": {"lease_id": "...", "trigger_id": "..."},
  "body": "<human-readable wake prompt>"
}

Targets and non-local senders are validated against the current gita registry. Bodies are UTF-8 text up to 8 KiB; metadata is a JSON object up to 4 KiB. TAMQ transports the prompt but does not interpret it as task state or grant authority.

(client_id, idempotency_key) is unique. Repeating an identical request returns the original message ID with deduplicated: true. Reusing the key with a different sender, target, endpoint, or body is an error. The durable identity used by coordination-engine is therefore the pair of TAMQ endpoint instance and local message ID, correlated to its own lease and trigger IDs.

Message and delivery states

State Meaning Coordination interpretation
pending Accepted and eligible now or after next_attempt_at Transport owns retry timing.
awaiting_ack Written successfully under explicit-ack policy Recipient comprehension is still unproven.
injected Written successfully under injected policy Transport delivery is complete, not task completion.
acknowledged Explicit acknowledgement received Strongest TAMQ receipt; still not workflow completion.
failed Delivery or acknowledgement attempts exhausted Terminal until an operator/client explicitly retries or a late ack arrives.

Every delivery lease acquisition increments the persistent attempt_count. Failure releases the lease and sets last_failure_reason plus a bounded next_attempt_at. Lease expiry is itself a failed attempt. Retry delays default to 5, 15, 60, and 300 seconds and use the last value thereafter. The selected endpoint policy supplies delivery_max_attempts in the range 19.

With delivery_ack_mode=injected, a successful terminal write completes the message immediately. With acknowledged, success enters awaiting_ack; the default 30-second deadline then redelivers the same message ID. Duplicate visual or input delivery is therefore possible and recipients must correlate by message ID when the operation is not naturally idempotent. Exhausting the cap while waiting produces failed with reason ack_timeout. A late explicit ack wins even after terminal failure and cancels any outstanding retry. retry resets only a failed message's attempts and returns it to pending.

Operations and failure semantics

  • endpoints: discover live repository attachment and disambiguate a wake.
  • send: admit an idempotent durable message.
  • message: retrieve one receipt including state, attempts, deadlines, and correlation metadata.
  • history: recover receipts after either process restarts.
  • ack: record explicit or late acknowledgement and cancel pending delivery.
  • retry: operator/policy-authorized reset of terminal delivery failure.

Endpoint disappearance before admission is unavailable and creates no message. Disappearance after admission leaves the message durable. Repeating the identical wake after a replacement endpoint appears rebinds that same message ID, but only when its previous endpoint is no longer live; TAMQ will not move a message between two live sessions implicitly. A process crash after claiming a message is recovered through lease expiry and bounded backoff.

JSONL replay uses the original message ID (or a deterministic content digest) as a tamq-replay idempotency key. Repeating the same replay reports it as deduplicated rather than creating another message. Replay still uses normal gita validation and never changes coordination-engine workflow state.

Ownership

TAMQ owns local queue rows, endpoint registration, delivery leases, retry and ack state, terminal interaction, and protocol capture. Coordination-engine owns trigger deduplication, coordination leases, actionability and safety policy, checkpoints, State Hub projection, and the decision to issue a wake or request an explicit retry. Neither system treats terminal injection as proof that an agent completed work.