--- id: TAMQ-WP-0014 type: workplan title: "Readable duplex messaging, runtime commands, and line limits" domain: communication repo: tmux-amq status: finished owner: codex topic_slug: coulomb-social planning_priority: P0 planning_order: 19 created: "2026-08-25" updated: "2026-08-25" state_hub_workstream_id: "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: ```text 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 ```task 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 ```task 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 ```task 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 ```task 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 ```task 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 ```task 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 ```task 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`.