Files
wizwar6e/deploy/feedback-reply.sh
T
Eric WagonerandClaude Fable 5.1 66b5c06f17 Credibility pass: one teleport step, one bell, one step type, and the comments that argued are gone
Since 6e49fc9. Engine: the teleport BFS in the view and the engine's
wallIgnoringDistance share teleportStep; the counter trail is weighed
between steps instead of on six arms; the bush attack takes its
adjacency from SIDES like the wall does; a dead redirected clause, a
one-member set, an identity ternary, and a stray try/catch are gone;
two tests now assert what their names promise. Server: KEEPER and
MAX_SEATS live in rooms.ts, the three Sentry bells ring through one
helper, the unread reply field is dropped, actingSeat comes from the
engine, and the protocol header names every message. Web: ReplayStep
is one type, cardName one helper, the say box and the reference section
one snippet each, the keeper's name arrives from the server rather than
the source, and the lifesaver ruling that ruled nothing is out.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
2026-09-22 09:56:49 -04:00

38 lines
2.4 KiB
Bash
Executable File

#!/bin/bash
# Answer a player's feedback report; the reply appears under it in their
# lobby ledger. Legacy reports without an id answer to their timestamp.
# deploy/feedback-reply.sh <host> <reportId> <resolved|by-design|open> <text...>
set -euo pipefail
HOST="${1:?usage: feedback-reply.sh <host> <reportId> <status> <text...>}"
REPORT_ID="${2:?usage: feedback-reply.sh <host> <reportId> <status> <text...>}"
STATUS="${3:?usage: feedback-reply.sh <host> <reportId> <status> <text...>}"
shift 3
TEXT="$*"
case "$STATUS" in resolved|by-design|open) ;; *) echo "status must be resolved, by-design, or open" >&2; exit 1;; esac
LINE=$(REPORT_ID="$REPORT_ID" STATUS="$STATUS" TEXT="$TEXT" node -e '
console.log(JSON.stringify({
reportId: process.env.REPORT_ID,
at: new Date().toISOString(),
status: process.env.STATUS,
text: process.env.TEXT,
}));')
printf '%s\n' "$LINE" | ssh "root@$HOST" 'cat >> /var/lib/wizwar/feedback.jsonl && tail -1 /var/lib/wizwar/feedback.jsonl'
# The desk's bell rings for the reply too, so Eric sees the exchange move:
# an event straight to Sentry from the droplet, with the DSN the service holds.
ssh "root@$HOST" "REPORT_ID='$REPORT_ID' STATUS='$STATUS' TEXT=\"\$(cat)\" python3 - <<'PY'
import json, os, re, uuid, urllib.request, datetime
svc = open('/etc/systemd/system/wizwar.service').read()
m = re.search(r'SENTRY_DSN=https://([0-9a-f]+)@([^/]+)/(\\d+)', svc)
if not m: raise SystemExit(0)
key, host, project = m.groups()
text = os.environ['TEXT']; rid = os.environ['REPORT_ID']; status = os.environ['STATUS']
now = datetime.datetime.now(datetime.UTC).isoformat()
event = {'event_id': uuid.uuid4().hex, 'timestamp': now, 'level': 'error', 'platform': 'other',
'message': {'formatted': f'Desk replies on report {rid} ({status}): {text[:100]}'}, 'fingerprint': ['report-reply', rid, now],
'tags': {'report': rid, 'status': status}, 'extra': {'text': text}}
body = json.dumps({'event_id': event['event_id'], 'sent_at': event['timestamp']}) + '\\n' + json.dumps({'type': 'event'}) + '\\n' + json.dumps(event)
req = urllib.request.Request(f'https://{host}/api/{project}/envelope/', data=body.encode(), headers={'Content-Type': 'application/x-sentry-envelope', 'X-Sentry-Auth': f'Sentry sentry_version=7, sentry_client=wizwar-desk/1, sentry_key={key}'})
try: urllib.request.urlopen(req, timeout=10); print('bell rung')
except Exception as e: print('bell failed:', e)
PY" <<< "$TEXT"