5.0 KiB
5.0 KiB
Phase-5 Anti-Silent / Group UX
Goal
Reduce user-facing silent outcomes in group/private chat flows while avoiding spam.
Invariants
I1: no silent user-facing failure forpublic_activeagents (SILENT/early-return -> short ACK).I2: one-message rule per webhook in group chats.I3: debounce by(chat_id, agent_id, reason)with cooldown.I4: evidence in gateway event (anti_silent_action,anti_silent_template,chat_type).
Deploy
cd /opt/microdao-daarion
docker compose -f docker-compose.node1.yml up -d --no-deps --build --force-recreate gateway
Seed / Precheck
export GATEWAY_WEBHOOK_URL='http://127.0.0.1:9300/agromatrix/telegram/webhook'
export PG_CONTAINER='dagi-postgres'
pre_rows_gateway=$(docker exec "$PG_CONTAINER" psql -U daarion -d daarion_memory -tAc \
"SELECT count(*) FROM agent_experience_events WHERE source='gateway' AND ts > now()-interval '10 minutes';")
pre_rows_join=$(docker exec "$PG_CONTAINER" psql -U daarion -d daarion_memory -tAc \
"SELECT count(*) FROM (
SELECT g.request_id
FROM agent_experience_events g
JOIN agent_experience_events r ON r.request_id=g.request_id
WHERE g.source='gateway' AND r.source='router' AND g.ts > now()-interval '10 minutes'
) x;")
pre_js=$(curl -sS http://127.0.0.1:8222/jsz?streams=true | python3 -c '
import json,sys
j=json.load(sys.stdin)
d=(j.get("account_details") or [{}])[0].get("stream_detail") or []
print(next((s.get("state",{}).get("messages",0) for s in d if s.get("name")=="EXPERIENCE"),0))
')
echo "pre_rows_gateway=$pre_rows_gateway"
echo "pre_rows_join=$pre_rows_join"
echo "pre_js=$pre_js"
Fixed Payload Replay
Payloads:
docs/ops/payloads/phase5_payload_group_unsupported_no_message.jsondocs/ops/payloads/phase5_payload_group_source_lock.jsondocs/ops/payloads/phase5_payload_private_photo_unsupported.json
# 1) group unsupported_no_message
curl -sS -X POST "$GATEWAY_WEBHOOK_URL" \
-H 'content-type: application/json' \
-d @docs/ops/payloads/phase5_payload_group_unsupported_no_message.json
# 2) group source_lock pair (same update_id)
curl -sS -X POST "$GATEWAY_WEBHOOK_URL" \
-H 'content-type: application/json' \
-d @docs/ops/payloads/phase5_payload_group_source_lock.json
curl -sS -X POST "$GATEWAY_WEBHOOK_URL" \
-H 'content-type: application/json' \
-d @docs/ops/payloads/phase5_payload_group_source_lock.json
# 3) private photo unsupported (photo follow-up without image context)
curl -sS -X POST "$GATEWAY_WEBHOOK_URL" \
-H 'content-type: application/json' \
-d @docs/ops/payloads/phase5_payload_private_photo_unsupported.json
Assertions
A) Strict row delta
post_rows_gateway=$(docker exec "$PG_CONTAINER" psql -U daarion -d daarion_memory -tAc \
"SELECT count(*) FROM agent_experience_events WHERE source='gateway' AND ts > now()-interval '10 minutes';")
delta_rows=$((post_rows_gateway-pre_rows_gateway))
echo "delta_rows=$delta_rows"
# expected: delta_rows == 4
B) Anti-silent evidence in DB
docker exec "$PG_CONTAINER" psql -U daarion -d daarion_memory -P pager=off -c "
SELECT request_id,
raw->>'chat_type' as chat_type,
raw->'policy'->>'sowa_decision' as sowa,
raw->'policy'->>'reason' as reason,
raw->>'anti_silent_action' as anti_silent_action,
raw->>'anti_silent_template' as anti_silent_template,
raw->'result'->>'http_status' as http_status,
ts
FROM agent_experience_events
WHERE source='gateway' AND agent_id='agromatrix' AND ts > now()-interval '10 minutes'
ORDER BY ts DESC LIMIT 25;
"
# expected:
# - reason=unsupported_no_message with sowa=UNKNOWN (group path)
# - reason=source_lock_duplicate_update with anti_silent_action in (ACK_EMITTED, ACK_SUPPRESSED_COOLDOWN)
# - reason=photo_followup_without_image_context with anti_silent_action=ACK_EMITTED
C) Metrics
curl -sS http://127.0.0.1:9300/metrics | grep -E \
'gateway_anti_silent_total|gateway_ack_sent_total|gateway_experience_emitted_total|gateway_early_return_total'
# expected:
# - gateway_anti_silent_total{action="ACK_EMITTED",reason="...",chat_type="group|private"} increments
# - source-lock repeated request may produce ACK_SUPPRESSED_COOLDOWN depending on timing
D) Join sanity (normal path still healthy)
post_rows_join=$(docker exec "$PG_CONTAINER" psql -U daarion -d daarion_memory -tAc \
"SELECT count(*) FROM (
SELECT g.request_id
FROM agent_experience_events g
JOIN agent_experience_events r ON r.request_id=g.request_id
WHERE g.source='gateway' AND r.source='router' AND g.ts > now()-interval '10 minutes'
) x;")
echo "post_rows_join=$post_rows_join"
# expected: non-zero with normal traffic
PASS Criteria
delta_rows == 4for fixed replay batch.- Deterministic reason codes present (
unsupported_no_message,source_lock_duplicate_update,photo_followup_without_image_context). anti_silent_actionis present for anti-silent branches (ACK_EMITTEDorACK_SUPPRESSED_COOLDOWN).- No evidence of double-event for one webhook request.