From 8d955c86a171c9c3d5121f328d512f9a16698af1 Mon Sep 17 00:00:00 2001 From: mosaic-coder Date: Sat, 25 Jul 2026 16:03:51 -0500 Subject: [PATCH] feat(framework): accept digest message class in agent-send.sh (W1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The triage class validator in agent-send.sh rejected `digest`, the canonical machine-wake / coalescible message class defined by the converged wake/heartbeat design (CONVERGED-DESIGN ยง2.3 sol C1). Add `digest` to the accepted class set (case-statement validator + the documented consumer grammar regex), alongside the existing terminal-log/actionable/human/reaction classes. Red-first: extended agent-send.test.sh with --class digest / -C digest assertions plus a grammar-regex case for class=digest. At origin/main these 3 new assertions FAIL (PASS=15 FAIL=3); with the validator fix applied, all 18 assertions PASS (PASS=18 FAIL=0). All pre-existing assertions were unaffected throughout. Part of #892 --- .../mosaic/framework/tools/tmux/agent-send.sh | 7 ++++--- .../framework/tools/tmux/agent-send.test.sh | 21 +++++++++++++++++-- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/packages/mosaic/framework/tools/tmux/agent-send.sh b/packages/mosaic/framework/tools/tmux/agent-send.sh index 9809bf70..9da54052 100755 --- a/packages/mosaic/framework/tools/tmux/agent-send.sh +++ b/packages/mosaic/framework/tools/tmux/agent-send.sh @@ -46,6 +46,7 @@ # actionable carries a decision/blocker/gate โ€” deliver # human from a human operator โ€” deliver # reaction an emoji/ack reaction +# digest machine-wake, coalescible; batched wake/heartbeat signal # Long form: --class CLASS (or --class=CLASS). When SET, the # preamble carries a ` class=` token INSIDE the bracket: # [ -> class=terminal-log] @@ -58,7 +59,7 @@ # -h help # # PREAMBLE GRAMMAR (for consumers / daemons mirroring this producer) -# ^\[(\S+) -> (\S+?)(?: class=(terminal-log|actionable|human|reaction))?\] (.*)$ +# ^\[(\S+) -> (\S+?)(?: class=(terminal-log|actionable|human|reaction|digest))?\] (.*)$ # group 1 = src label group 2 = dst host:session # group 3 = class (absent => actionable) group 4 = message body # @@ -109,8 +110,8 @@ done CLASS_TOKEN="" if [ -n "$CLASS" ]; then case "$CLASS" in - terminal-log|actionable|human|reaction) CLASS_TOKEN=" class=${CLASS}" ;; - *) echo "ERROR: invalid --class '$CLASS' (allowed: terminal-log, actionable, human, reaction)" >&2; exit 3 ;; + terminal-log|actionable|human|reaction|digest) CLASS_TOKEN=" class=${CLASS}" ;; + *) echo "ERROR: invalid --class '$CLASS' (allowed: terminal-log, actionable, human, reaction, digest)" >&2; exit 3 ;; esac fi diff --git a/packages/mosaic/framework/tools/tmux/agent-send.test.sh b/packages/mosaic/framework/tools/tmux/agent-send.test.sh index bc94e5f4..87a1ed90 100755 --- a/packages/mosaic/framework/tools/tmux/agent-send.test.sh +++ b/packages/mosaic/framework/tools/tmux/agent-send.test.sh @@ -17,6 +17,9 @@ # 8. MOSAIC_AGENT_NAME is authoritative for sender identity. # 9. sender fallback queries local tmux, never the destination -L socket. # 10. an undeterminable sender is stamped as "?". +# 11. --class digest is accepted (machine-wake, coalescible canon class). +# 12. -C digest short form parses identically. +# 13. the documented consumer regex parses producer output for class=digest. set -uo pipefail HERE=$(cd -- "$(dirname -- "$0")" && pwd) @@ -65,7 +68,7 @@ run_auto() { } # Documented consumer grammar โ€” the daemon will mirror exactly this. -GRAMMAR='^\[(\S+) -> (\S+) class=(terminal-log|actionable|human|reaction)\] (.*)$' +GRAMMAR='^\[(\S+) -> (\S+) class=(terminal-log|actionable|human|reaction|digest)\] (.*)$' GRAMMAR_NOCLASS='^\[(\S+) -> (\S+)\] (.*)$' # 1. REGRESSION BAR: classic preamble, byte-for-byte. @@ -108,8 +111,22 @@ else [ "$?" = 3 ] && ok "--class with no value => exit 3" || no "--class with no value => exit 3" "wrong rc" fi +# 11. --class digest (space form) is accepted. +got=$(run -s mos --class digest -m "wake payload") +want='[a:src -> dsthost:mos class=digest] wake payload' +if [ "$got" = "$want" ]; then ok "--class digest emits token" +else no "--class digest emits token" "got=[$got] want=[$want]" +fi + +# 12. -C digest short form. +got=$(run -s mos -C digest -m "coalesced wake") +want='[a:src -> dsthost:mos class=digest] coalesced wake' +if [ "$got" = "$want" ]; then ok "-C digest (short form)" +else no "-C digest (short form)" "got=[$got] want=[$want]" +fi + # 7. consumer grammar parses every class + classic line. -for c in terminal-log actionable human reaction; do +for c in terminal-log actionable human reaction digest; do line=$(run -s mos --class "$c" -m "body $c") [[ "$line" =~ $GRAMMAR ]] && [ "${BASH_REMATCH[3]}" = "$c" ] && [ "${BASH_REMATCH[4]}" = "body $c" ] \ && ok "grammar parses class=$c" || no "grammar parses class=$c" "line=[$line]"