Skip to content

Event-wide searchable Audit page; Marshaling keeps a compact strip#352

Merged
ryan-johnson2 merged 1 commit into
develfrom
event-audit-page
Jul 3, 2026
Merged

Event-wide searchable Audit page; Marshaling keeps a compact strip#352
ryan-johnson2 merged 1 commit into
develfrom
event-audit-page

Conversation

@ryan-johnson2

Copy link
Copy Markdown
Contributor

The user-approved split of the audit trail's two jobs (review vs action source):

  • New "Audit" workspace tab — every ruling across the event, newest-first: kind badge, resolved callsign, friendly heat name, cleaned summary, trailing log ref. Filters for pilot / heat / kind + free-text; the pilot and heat on every row are clickable filter chips. Read-only (visible to read-only sessions) — the defensible-results review surface.
  • Server: GET /events/{id}/audit merges the existing per-heat audit fold over each heat's window (identical attribution to the Marshaling view — including the current-run rule), tagged with the heat, newest-first. New EventAuditEntry binding + eventAudit client helper.
  • Marshaling slims down: the full trail is gone; the Reverse-ruling/Resolve-protest pickers stay; a compact "Recent rulings" strip (latest 3) links "View full audit →" to the Audit tab pre-filtered to the marshaled heat.
  • Results cross-link: round-standings rows jump to Audit filtered to that pilot — the "why is my result what it is?" flow.
  • Shared rendering extracted to lib/auditRender.ts so the strip, the pickers, and the page can't drift.

Gates: 16 Rust suites (3 new fold tests incl. restart-run exclusion), 536 console tests (new EventAudit suite; strip + cross-link tests), contract 91 incl. a new audit.contract.ts against a real Director, both check passes, clippy/fmt/lint clean. Verified live: the route + page render the real test event's marshaling history (screenshot-checked).

🤖 Generated with Claude Code

…pact strip

Marshaling is the "do the work" page — the full per-heat audit trail moves to
a new first-class, event-wide Audit review surface ("defensible results").

Server:
- New open read GET /events/{event_id}/audit serving Vec<EventAuditEntry>
  (the per-heat AuditEntry fields flattened + a heat tag), newest first.
  Built by running the EXISTING per-heat audit fold (marshaling_log over
  heat_window_offsets) per scheduled heat, so the Audit page can never
  disagree with Marshaling's per-heat view — including the window rules:
  a late ruling heat-tagged to a finished heat lands under THAT heat, and
  a Restarted heat's pre-restart rulings are absent (current-run window).
- Unit tests: cross-heat tagging + newest-first merge, restart exclusion,
  unknown-event 404. ts-rs binding exported (bindings/EventAuditEntry.ts).

Console:
- New workspace tab "audit" (route.ts, App.svelte, Alt+7, magnifier icon)
  rendering screens/EventAudit.svelte: newest-first rows with kind badge
  (DQ / Time penalty / Points / Lap added / ... derived per entry), resolved
  pilot callsign + friendly heat name as clickable filter chips, the #337
  re-composed summary (raw "(ref N)" stripped), and the log ref trailing.
  Client-side filters: pilot / heat / kind / free text. Role-agnostic pure
  read; #340 error-state + retry (no silent []).
- Shared lib/auditRender.ts: the #337 helpers extracted from Marshaling
  (badge/label/time/ref-strip/competitor-chase/line composition) so the
  Audit page and Marshaling render every entry identically.
- lib/auditFilter.svelte.ts: the one-shot cross-screen prefilter seam —
  openAudit(setTab, {heat?, pilot?}); EventAudit consumes+clears on mount.
- Marshaling: full trail replaced by a "Recent rulings" strip (latest 3,
  same shared rendering) + "View full audit →" jumping pre-filtered to the
  marshaled heat. The heat-scoped audit read stays — the Reverse-ruling /
  Resolve-protest pickers and the open-protest Finalize gate derive from it.
- Results: each ROUND-standings row gains a per-pilot "audit" affordance
  jumping to the Audit page pre-filtered to that pilot.
- protocol-client: eventAudit(baseUrl, eventId) mirroring roundStandings;
  session.eventAudit() with test seam.

Tests: EventAudit page suite (order, names, chips, filters, prefilter,
error+retry, read-only); Marshaling strip tests (latest-3, prefiltered
jump) with picker tests untouched; Results audit-link test; new contract
suite (contract/audit.contract.ts) driving a real Director through
schedule -> run -> finalize -> penalty + void, asserting heat tags and
newest-first order over the wire.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ryan-johnson2 ryan-johnson2 merged commit 7c7a0db into devel Jul 3, 2026
3 checks passed
@ryan-johnson2 ryan-johnson2 deleted the event-audit-page branch July 3, 2026 19:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant