tmux-amq/workplans/TAMQ-WP-0014-readable-duplex-messaging-and-limits.md
tegwick 17b6bd7ae7
Some checks failed
tamq-ci / test (push) Failing after 6s
feat: add reliable trigger and worker message blocks
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a03397-4d51-7fd1-8ff2-946eb22ea2bc
2026-08-25 23:22:39 +02:00

14 KiB

id type title domain repo status owner topic_slug planning_priority planning_order created updated state_hub_workstream_id
TAMQ-WP-0014 workplan Readable duplex messaging, runtime commands, and line limits communication tmux-amq finished codex coulomb-social P0 19 2026-08-25 2026-08-25 3b675117-dd26-553f-adea-d0505df3cadd

Readable duplex messaging, runtime commands, and line limits

Follow-up: TAMQ-WP-0015 supersedes this workplan's single-line worker output contract with blank-line-terminated worker message blocks and repeats From: framing on every delivered physical line.

Replace the shell-oriented @/# protocol with a readable To:/From: protocol that can originate in either operator input or worker output, add an operator-only runtime command lane, separate input placement from submission, and impose session-lifetime per-window message/input/output line budgets.

This is a breaking local-alpha protocol change. It deliberately removes the old address aliases and changes pushy so that submission requires the new trigger mode.

Required protocol contract

The normalized line keywords are case-insensitive and recognized only at the start of logical content. A terminal program's conservative worker-output gutter may precede worker content:

Observed source Line Effect
Operator input in alpha To:beta: Hello! Queue one message with operator provenance.
Worker output in alpha To:beta: Hello! Queue one message with worker provenance.
Delivery of operator message n/a Render/inject From:alpha/o: Hello!.
Delivery of worker message n/a Render/inject From:alpha: Hello!.
Operator input Cmd: mode=trigger Apply an allowlisted runtime setting and report the result locally.
Worker output Cmd: mode=trigger Ordinary worker output; it must not mutate tamq.

Recipient names use exact gita-registered repository slugs, with the repository between the first and second colon and a non-empty message body after it. Leading separator whitespace is removed from the body. From: is delivery framing only and is never routable. Durable message identity remains metadata rather than visible protocol text.

The mode contract becomes:

Mode Target behavior
inbox Store durably without changing the target terminal.
output Display the From: line as terminal output above stable input.
pushy Place the From: line in the target's input buffer without submitting it.
trigger Perform pushy placement and then submit exactly once, as one Enter.

output remains the default. pushy and trigger remain explicit, experimental choices because tamq cannot infer the foreground program or the state of its input buffer.

Running-limit contract

The service owns one atomic ledger for every repository window in a managed tmux session. A tap or broker restart must not reset the ledger; a newly created managed-session generation starts a new ledger. The three independent counters overlap intentionally:

  • messages: accepted outbound To: lines from either origin in this window; inbound delivery and rejected attempts do not increment it.
  • input: complete logical lines submitted by the operator in this window, including an operator To: or Cmd: line.
  • output: complete normalized logical lines emitted by the worker in this window, including a worker To: line.

Tamq-generated From:tamq: notices, routed From: deliveries, terminal protocol replies, and display redraw fragments do not increment input or output counts and cannot feed back into routing. Input and output counts continue to advance while messaging is blocked; only an explicit reset or a new session generation clears them.

Defaults are maxmsg = 8, maxin = 1024, and maxout = 32768. They are positive integer configuration keys and startup options --maxmsg, --maxin, and --maxout; startup options override configuration. Admission checks the source window before durable enqueue. Equality blocks: when any relevant count is already greater than or equal to its limit, no message is created. If more than one limit is exceeded, report the first in deterministic order: messages, input, output.

Every blocked attempt produces exactly one local, stable-row notice in the source terminal:

From:tamq: Messaging blocked! Running linecount XXX limited by MMM lines of messages/input/output in this terminal. Use 'Cmd: reset-limits' to unblock.

XXX, MMM, and the final dimension word are replaced with the applicable counter, limit, and messages, input, or output. Cmd: reset-limits atomically resets all three counters for the current source window only.

Resolve PTY attribution and line semantics

id: TAMQ-WP-0014-T01
status: done
priority: critical
state_hub_task_id: "66ac5b8c-6435-5d62-8b3c-4516bddae75f"

Capture real shell and coding-agent PTY traffic and define one terminal-neutral normalization boundary for logical input and output lines. Demonstrate that a worker-rendered To: row can be observed once through ANSI redraws, while an operator To: line echoed or repainted by the worker cannot be misclassified as a second worker message. Correlate exact recent operator-line fingerprints, deduplicate stable output row transitions, and fail closed when provenance is ambiguous. Preserve raw byte forwarding, geometry, mouse behavior, cursor state, and alternate-screen behavior.

This is the feasibility gate for the workplan. Generic PTYs do not inherently label output as program-authored versus echoed input; do not replace that missing signal with coding-agent-specific assumptions. Record the accepted line/echo boundary and fixtures before routing worker output.

Replace routing grammar and persist provenance

id: TAMQ-WP-0014-T02
status: done
priority: critical
state_hub_task_id: "95cf3b20-8b23-5155-8b6d-3431baf36486"

After T01, implement one parser and event model for operator-input and worker-output To: lines. Validate exact recipients, store an explicit operator_input or worker_output provenance value with every durable message, and render the corresponding From:sender/o: or From:sender: line. Make From: non-routable at tap and broker boundaries. Remove @, @repo:, bare-@ composer, latest-counterparty shorthand, #repo:, and their generated shims rather than retaining hidden aliases.

Cover punctuation, UTF-8, whitespace, malformed/missing recipients, unknown repos, multiline normalization, exact origin attribution, output redraw deduplication, echo suppression, and feedback-chain containment.

Separate pushy placement from trigger submission

id: TAMQ-WP-0014-T03
status: done
priority: high
state_hub_task_id: "3ae47806-9808-5b38-b0cd-1f63536ebce9"

Redefine pushy as literal input-buffer placement without Enter and add trigger as the same sanitized placement followed by exactly one Enter. Retain inbox and stable terminal output behavior. Carry provenance framing unchanged through every mode, expose the selected mode through CLI/status and endpoint registration, and add a new service capability so startup replaces a stale broker that implements the old pushy-submit or legacy framing contract.

Prove with real tmux targets that pushy never submits, trigger submits once, neither mode repeats after accepted delivery, and no mode turns delivered From: text into another outbound message.

Add the operator-only runtime command lane

id: TAMQ-WP-0014-T04
status: done
priority: high
state_hub_task_id: "67c3aa0d-ad5e-5fcd-bd7a-fe4bdcdebbcb"

Recognize Cmd: only from operator input. Start with an allowlist of mode=inbox|output|pushy|trigger, maxmsg=N, maxin=N, maxout=N, and reset-limits; reject malformed, unknown, negative, or out-of-range settings without changing state. Apply settings atomically to the current managed session endpoint, persist them across tap/broker restart, and emit a local From:tamq: confirmation or error excluded from routing and counters. Worker output beginning Cmd: must remain inert.

Preserve terminal neutrality explicitly: the current transparent PTY path cannot recognize a complete line and then retroactively remove bytes already forwarded to the foreground program. Before implementation, choose and test one of these honest contracts: observed Cmd: lines also remain visible to the worker, or a separately activated operator control input path buffers and renders them without forwarding. Do not silently swallow arbitrary typing, delay normal input, or implement an agent-specific erasure trick.

Enforce atomic per-window line budgets

id: TAMQ-WP-0014-T05
status: done
priority: critical
state_hub_task_id: "5101a264-5fde-5e94-b924-bdaa114d18fd"

Add the session-generation/window ledger, configured defaults, startup flags, runtime updates, and reset command. Count normalized input and output events at their single authoritative observation points. Perform counter inspection, message admission, and accepted-message increment in one transaction so simultaneous operator and worker sends cannot cross a limit. A blocked attempt must create no durable message, lease, delivery, or injected input and must produce exactly the specified source-terminal notice without incrementing any tamq-generated-output count.

Cover equality and over-limit boundaries, all three dimensions, deterministic precedence, overlapping input/message and output/message accounting, per-window isolation, current-window reset, runtime limit changes below a current count, broker/tap restart, managed-session replacement, concurrent sends, and notice feedback suppression.

Migrate the alpha contract and documentation

id: TAMQ-WP-0014-T06
status: done
priority: high
state_hub_task_id: "5b630cab-e431-5f8f-83b0-cc1bd56c262c"

Update root/start help, completion, config examples, README, SCOPE, protocol documentation, and diagnostics for To:/From:/Cmd:, origin suffixes, four modes, counters, reset behavior, and the intentional removal of @/# aliases. Remove obsolete generated shims during managed-session reconciliation and cleanup without touching user-owned commands. Identify this as an alpha breaking change and make mixed-version startup fail or upgrade rather than quietly accepting incompatible traffic.

Keep limits distinct from TAMQ-WP-0003: these counters bound new message generation, while WP0003 still owns bounded delivery retry attempts and acknowledgement policy. Hold TAMQ-WP-0002 adapter implementation against the new protocol until this workplan's local contract is proven.

Prove the installed end-to-end workflow

id: TAMQ-WP-0014-T07
status: done
priority: critical
state_hub_task_id: "bae85317-60d0-5e12-8ffd-d08a70f9d9e7"

Run unit, pseudo-terminal, real-tmux, upgrade, and installed-package tests with two repository windows and real worker-style alternate-screen output. Prove operator and worker sends in both directions, exact /o attribution, inert worker Cmd:, allowed operator commands, pushy placement, trigger submission, stable-row output, every limit and reset path, service restart continuity, and cleanup. Include a controlled installed make install smoke without modifying unrelated panes or durable history, and leave runaway-safe cleanup available.

Do not mark the workplan finished while T01 attribution is only simulated or while a worker output replay can duplicate an operator message.

Completion evidence

  • The readable, case-insensitive To: parser is shared by attributed operator input and normalized worker output. Conservative full-screen worker-output gutters are removed before worker parsing, while operator prompt gutters stay inert. Durable provenance renders exactly as From:sender/o: or From:sender:; From: and worker-output Cmd: lines are inert. Legacy @/# routing, reply/composer code, and generated v1 shims were removed from the active contract.
  • A real tmux PTY fixture echoed an operator To: line and then emitted a distinct worker To: line. Exactly two records resulted, with operator and worker provenance respectively; the echo was suppressed. ANSI normalization, redraw deduplication, resize, raw mouse input, and byte forwarding are covered.
  • pushy now places one sanitized From: line without Enter. trigger places the same line and submits exactly once. Startup requires readable framing, trigger, and line-limit capabilities, and managed sessions without the new tap marker fail with an explicit recreate instruction.
  • Cmd: supports the allowlisted modes, three positive per-window limits, and current-window reset-limits. It is operator-only. The selected transparent contract leaves the command visible to the foreground program; shell absorbers prevent ordinary-shell command-not-found noise.
  • SQLite schema v4 holds atomic counters keyed by session generation and repo. Tests prove equality blocking, deterministic precedence, overlapping accounting, per-window isolation, persistence across reopen, fresh session generations, atomic concurrent admission, reset, and the exact local block notice. tamq status exposes the ledger.
  • make check: 133 tests passed, including real tmux and the isolated installed package workflow. make install refreshed tmux-amq==0.1.0. Installed tamq cleanup dry-run verified the live broker identity, preserved all 26 durable records, and reported legacy owned shims and stale sockets without mutation.
  • Retry and acknowledgement residuals remain owned by TAMQ-WP-0003; coordination-engine interoperability remains owned by TAMQ-WP-0002.