feat: complete reliable coordination adapter
Some checks failed
tamq-ci / test (push) Failing after 5s

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a03397-4d51-7fd1-8ff2-946eb22ea2bc
This commit is contained in:
tegwick 2026-08-26 08:11:09 +02:00
parent 25113f463e
commit 6d2ccc7760
30 changed files with 2553 additions and 144 deletions

112
README.md
View file

@ -4,8 +4,8 @@ Tmux Agentic Message Queueing (`tamq`) provides repository-aware tmux sessions
and a local, durable message queue. It does not assume who or what uses a pane.
The local alpha provides tmux endpoint lifecycle, local SQLite history and
leases, readable `To:` routing, JSONL export/replay, and a Unix-socket protocol
for a later coordination-engine adapter.
leases, readable `To:` routing, JSONL export/replay, bounded delivery state, and
a versioned Unix-socket coordination-engine adapter.
Agents and operators should start with the concise
[TAMQ messaging introduction](TamqMessagingIntroduction.md).
@ -182,6 +182,34 @@ the durable id needed by `ack`:
From:flex-auth/o: please review the auth boundary
```
### Reviewing the communication protocol
TAMQ automatically appends structured protocol events to the local database.
The ledger includes addressed-message acceptance, operator/worker provenance,
worker block boundaries and termination reasons, allowlisted command outcomes,
line-limit blocks, endpoint lifecycle, and delivery attempts or failures. It
does not capture unrelated pane output or ordinary shell input.
Create a review artifact with:
```bash
tamq capture --output tamq-protocol.md
tamq capture --repo audit-core --output audit-core-protocol.md
tamq capture --message-id m-... --format jsonl
tamq capture --event delivery.failed
```
Markdown is the human-oriented default and starts with aggregate counts useful
for spotting protocol friction. JSONL is intended for scripts. The default is
the newest 500 matching events; `--limit` changes that bound. Repository filters
match either side of an exchange. A message body is included only on its
acceptance event, not repeated for every delivery event. Captures are durable
communication evidence, so never put credentials or secrets in TAMQ messages.
When upgrading an already-running alpha, recreate the managed session once so
its long-lived pane observers use the capture-aware build; existing durable
message lifecycle is backfilled, but old observers cannot reconstruct block or
command events retroactively.
To explicitly consume pending messages through a command, use an inbox filter:
```bash
@ -195,12 +223,26 @@ it and all later messages pending. Filters never run in the background and
cannot be combined with `--all` or `--json`.
Outside a managed window, use `tamq inbox --repo audit-core` and optionally
`--json`. Output-displayed messages remain durable and pending until
acknowledged. Neither `output` nor `inbox` mode injects terminal keystrokes.
Pushy places input without Enter. Trigger waits for terminal paste detection to
settle and then adds exactly one Enter. A short endpoint-startup grace protects
the first input delivery while the foreground program initializes. Both input
modes record accepted placement as `injected`, not recipient acknowledgement.
`--json`. Neither `output` nor `inbox` mode injects terminal keystrokes. Pushy
places input without Enter. Trigger waits for terminal paste detection to settle
and then adds exactly one Enter. A short endpoint-startup grace protects the
first input delivery while the foreground program initializes.
The policy profile controls completion. The default `injected` policy completes
after a successful terminal write. `acknowledged` keeps the message in
`awaiting_ack`, visible in the inbox, and redelivers the same ID after the ack
deadline. Delivery failures and expired leases use bounded backoff; exhaustion
becomes `failed`. Inspect the attempt count and reason, then explicitly reset a
terminal message if retry is safe:
```bash
tamq inspect m-...
tamq retry m-...
```
Acknowledged-mode redelivery can create duplicate terminal presentation. A late
ack wins even after exhaustion. Neither state proves that an agent completed the
requested work.
Every session window has independent, session-lifetime running counters for
accepted outbound messages, operator input lines, and normalized worker output
@ -296,17 +338,16 @@ later phase.
This keeps tmux-specific topology concerns separate from reusable terminal I/O
observation and message identity.
Normal endpoints use terminal-output delivery: each message is written once to
the target pane's PTY output and stays pending in the durable inbox until
acknowledged. `--mode inbox` selects inbox-only manual mode. Neither becomes
pane input. Experimental `--mode pushy` places a sanitized `From:` block
Normal endpoints use terminal-output delivery. `--mode inbox` selects
inbox-only manual mode. Neither becomes pane input. Experimental `--mode pushy`
places a sanitized `From:` block
without Enter; `--mode trigger` performs the same placement, lets paste
detection settle, and submits once.
The PTY observer records explicit operator/worker provenance and suppresses
echoed operator lines before they can route again.
The older pane-delivery experiment remains available only with the explicit
`tamq start --tap --command ...` opt-in. Both input paths remain subject to the
retry and acknowledgement limitations tracked by `TAMQ-WP-0003`.
`tamq start --tap --command ...` opt-in. Both input paths use the same bounded
retry and acknowledgement state machine.
The visible endpoint label is `tmux-amq-<PID>`; each boot also receives an
instance nonce so PID reuse cannot collide with prior leases or receipts.
@ -324,6 +365,9 @@ purge_before = "365d"
purge_max_size = "100MB"
history_max_size = "100MB"
delivery_poll_interval = "0.5"
delivery_lease_seconds = "30"
delivery_retry_backoff_seconds = "5,15,60,300"
delivery_ack_timeout_seconds = "30"
maxmsg = 8
maxin = 1024
maxout = 32768
@ -331,15 +375,43 @@ maxout = 32768
[policy.profiles.diagnostics]
safety_gated_max_attempts = 2
delivery_ack_mode = "acknowledged"
delivery_max_attempts = 4
```
Policy profiles accept a safety-gated retry cap of at most nine attempts, but
the alpha delivery path does not enforce attempt counting yet. Explicit
acknowledgement exists, while `delivery_ack_mode` enforcement and bounded retry
state are tracked in `TAMQ-WP-0003`. Use `--policy-profile` to select a profile;
`--orwell` enables explicitly unsafe local diagnostics.
Policy profiles accept one to nine delivery attempts. Lease expiry and write
failure consume an attempt; retry delay uses the configured sequence and then
repeats its last value. `delivery_ack_mode` is either `injected` or
`acknowledged`. Use `--policy-profile` to select a profile; `--orwell` enables
explicitly unsafe local diagnostics.
The Unix socket service supports structured `ping`, `register`, `send`,
`history`, `ack`, `endpoints`, and `disconnect` operations. Endpoint
`message`, `history`, `ack`, `retry`, `endpoints`, and `disconnect` operations. Endpoint
registrations and messages are persisted in the same local SQLite database;
delivery remains delegated to the control-mode adapter.
## Coordination-engine adapter
`tamq.client.CoordinationEngineAdapter` is a transport-only async adapter. It
does not import tmux/control-mode code and opens a fresh authenticated
Unix-socket connection per operation. A wake resolves exactly one live endpoint,
validates the gita target, and uses the coordination lease ID as its idempotency
key:
```python
from tamq.client import CoordinationEngineAdapter, WakeRequest
receipt = await CoordinationEngineAdapter().wake(
WakeRequest(
lease_id="lease-123",
trigger_id="task-456:r7",
target_repo="audit-core",
prompt="Resume the actionable task and publish a checkpoint.",
)
)
```
Repeating that wake returns the same message ID. Reusing its lease ID for a
different payload is rejected. Receipt recovery, explicit acknowledgement, and
terminal retry use `receipt`, `acknowledge`, and `retry_failed`. The normative
state and ownership contract is
[`spec/coordination-engine-adapter-v0.1.md`](spec/coordination-engine-adapter-v0.1.md).