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
This commit is contained in:
Eric Wagoner
2026-09-22 09:56:49 -04:00
co-authored by Claude Fable 5.1
parent c4a555f8df
commit 66b5c06f17
21 changed files with 245 additions and 239 deletions
+1 -7
View File
@@ -8,7 +8,7 @@
// Make the old checkout with `git worktree add <dir> <commit>`. Each seed
// is played once per rotation of the table so seat order cancels out.
import { applyCommand, automatonFallback, createGame, viewFor } from "../packages/engine/src/index.ts";
import { actingSeat, applyCommand, automatonFallback, createGame, viewFor } from "../packages/engine/src/index.ts";
import { pathToFileURL } from "node:url";
import { resolve } from "node:path";
@@ -25,12 +25,6 @@ const brains = {
old: old.automatonCommand,
};
function actingSeat(state) {
return state.wardPending?.ownerId ?? state.pushPending?.pusheeId ?? state.slowDeathPending?.playerId
?? state.pendingDiscard ?? state.chaosPending?.queue[0] ?? state.stack?.waitingOn
?? state.outOfTurnWindow?.playerId ?? state.players[state.turn.activeIndex].id;
}
function playOut(seed, order) {
const ids = order.map((b, i) => `${b}${i + 1}`);
const brainOf = Object.fromEntries(ids.map((id, i) => [id, brains[order[i]]]));
+3 -2
View File
@@ -26,8 +26,9 @@ 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']
event = {'event_id': uuid.uuid4().hex, 'timestamp': datetime.datetime.now(datetime.UTC).isoformat(), 'level': 'error', 'platform': 'other',
'message': {'formatted': f'Desk replies on report {rid} ({status}): {text[:100]}'}, 'fingerprint': ['report-reply', rid, datetime.datetime.now(datetime.UTC).isoformat()],
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}'})
+4 -4
View File
@@ -14,9 +14,9 @@ CHANNEL="${1:-#wizwar-notifications}"
API="https://us.sentry.io/api/0/organizations/$ORG"
AUTH="Authorization: Bearer $SENTRY_TOKEN"
# What the API wants, learned the hard way: the Slack action needs the
# channel's ID as well as its name, the project's detector is found by
# project id, and the binding is a PUT of the workflow with detectorIds.
# The Slack action takes the channel's ID as well as its name; the
# project's error detector is looked up by project id; a workflow is bound
# to its detectors by PUT after creation.
SLACK_ID="${SENTRY_SLACK_INTEGRATION:-345334}"
CHANNEL_ID="${SLACK_CHANNEL_ID:?SLACK_CHANNEL_ID=C... is required (the Slack ID of the channel)}"
PROJECT_ID="${SENTRY_PROJECT_ID:-4512011462049793}"
@@ -68,6 +68,6 @@ if [ "$CODE" != "201" ]; then
fi
WORKFLOW_ID=$(printf '%s' "$BODY" | python3 -c 'import json,sys; print(json.load(sys.stdin).get("id",""))')
echo "created workflow $WORKFLOW_ID"
# A fresh workflow may come back without its detectors; bind them by PUT.
# Binding to the detector is done by PUT, the whole workflow resent.
curl -s -o /dev/null -w "bound to detector $DETECTOR_ID: %{http_code}\n" -X PUT "$API/workflows/$WORKFLOW_ID/" -H "$AUTH" -H "Content-Type: application/json" -d "$PAYLOAD"
echo "done: https://$ORG.sentry.io/monitors/alerts/$WORKFLOW_ID/"