chore: AA character agents implementation complete

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-28 19:51:49 -06:00
parent 7d8e93932b
commit 3779978768
73 changed files with 2991 additions and 911 deletions

1
AA-transcripts Submodule

Submodule AA-transcripts added at 67b05da4e2

1
CourtRecord Submodule

Submodule CourtRecord added at 91570ccd07

290
IDEA.md
View File

@@ -1,290 +0,0 @@
# JuryRigged ⚖️🎭
*Roleplay comedy + audience verdict game show format*
## One-liner
AI lawyers argue absurd cases, AI witnesses improv testimony, and the audience serves as jury—delivering a verdict and voting on a ridiculous sentence. A judge AI issues the final ruling with dramatic (and silly) flair.
---
## Core Concept
A structured, turn-based “courtroom show” designed for streaming: instantly legible to new viewers, naturally clip-friendly, and tolerant of platform latency.
**Hook:** everyone sticks around for the **verdict moment** (and the sentencing poll right after).
---
## Roles
### AI agents
- **Judge**: controls pacing, sustains tone, delivers summary + final ruling/sentence
- **Prosecutor**: argues “guilty / liable” (or equivalent), cross-examines
- **Defense**: argues “not guilty / not liable,” cross-examines
- **Witnesses (13)**: improvised testimony (characterful, constrained, punchy)
### System host (automated)
- **Bailiff / timekeeper**: phase timers, announcements, stingers, poll triggers, scene transitions
### Viewers (jury)
- Vote on **verdict**
- Vote on **sentence** (from curated options)
---
## Round Flow & Automation
1. **Case prompt selected**
2. **Opening statements (timed)**
3. **Witness examination (turn-based Q/A)**
4. **Optional “evidence card” reveal**
5. **Closing arguments**
6. **Jury verdict vote**
7. **Jury sentence vote** (curated outcomes)
8. **Judge final ruling + comedic wrap-up**
**Automation emphasis**
- Hard phase boundaries + strict turn enforcement
- Timers per segment + caps per response
- Auto-summaries to prevent runaway monologues and keep newcomers oriented
---
## Voting / Decision System
### Verdict poll
- Criminal style: **Guilty / Not Guilty**
- Civil style: **Liable / Not Liable**
### Sentencing poll (pre-enumerated outcomes)
Examples:
- Community service
- Banished to the shadow realm
- Forced to write apology haikus
- Mandatory “ethics training” hosted by a raccoon
- Probation with an ankle monitor that only plays ukulele covers
---
## UI/UX (Overlay + On-screen Systems)
- Courtroom overlay: **bench + counsel tables**
- **Active-speaker indicator**
- **Evidence cards carousel**
- **Objection counter** (recurring bit + pacing feedback)
- **Jury vote bars** (verdict + sentence)
- **Live captions / transcript**
- “Case file” sidebar:
- Charges / claims
- Constraints (tone policy, no-go topics)
- Current phase timer
---
## Integrations / APIs
- **Polls + TTS** (announcer moments, verdict, recap)
- Overlay framework: **NodeCG** or **StreamElements**
- Optional: **OBS WebSocket** for automatic scene changes
- Optional: soundboard stingers triggered automatically:
- “Order in the court!”
- “Sustained!”
- “Overruled!”
- “Mistrial!”
---
## Latency Tolerance
Designed to be naturally robust with stream delay:
- Turn-based segments
- 2040s vote windows
- Phase timers make pacing predictable even when chat is laggy
---
## Safety & Moderation Policy
**Clean Courtroom Policy**
- Curated case prompts (pre-approved)
- Curated sentence options (pre-approved)
- Guardrails for witnesses (no slurs, no graphic content, no harassment targets)
---
## Failure Modes & Mitigation
### Offensive content risk
- Use curated prompts + strict policy filters
- Immediate “Judge redirects” + bailiff stinger (“Order!”) + swap witness
### Runaway monologues
- Hard time/token caps
- Auto-summarization (judge recap) on schedule:
- **Judge summary every 2 questions**
- **Witness answers capped** (time + token)
### Repetitive humor / fatigue
- Prompt bank rotation + style constraints per episode
- Rotate “case genres”:
- Absurd civil suit
- Cosmic crime
- Workplace tribunal
- Fantasy court
### Chaotic pacing
- Strict turn enforcement + phase timers
- Bailiff announces transitions and locks phases
---
## Complexity
**Medium**
- Multi-agent turn-taking + overlays + timers
- Lower secrecy/state complexity than deduction games
- Minimal persistent state requirements (good for reliability)
---
## Predicted Audience Retention: High
### Why it works
- Comedy + structure = drop-in comprehension within ~20 seconds
- “Verdict moment” is a clear retention hook (people stay for vote + sentence)
- Hard phase boundaries create natural pacing and predictability
### Retention risks
- Humor fatigue (“objection!” beats get stale)
- Witness segments can drag if witnesses ramble
### Fixes
- Rotate case genres
- Hard caps + periodic judge summaries
- Add recurring bits:
- Objection Counter
- Contempt Meter
- Evidence Wheel
---
## Monetization (Clean, Non-Gross)
### Strong, non-extractive levers
- **Verdict vote multipliers (cosmetic only)**
Subs/bits unlock courtroom effects:
- gavel slam SFX
- confetti
- “Order in court” stinger
*(Not pay-to-win outcomes.)*
- **Patreon perk**
Patrons submit case prompts into a curated queue
(still moderated/approved)
- **Sponsor fit**
Brands like “game show energy” adjacency:
- structured segments
- predictable moments
- clip-friendly reveals and verdicts
---
## Product Strategy: What to Ship First 🛠️
### Architecture Decision Record
See [docs/ADR-001-juryrigged-architecture.md](docs/ADR-001-juryrigged-architecture.md) for runtime boundaries, module ownership, phase-state contracts, and API/SSE/persistence contracts.
### Phase 1 — JuryRigged = “Orchestration/Overlay Engine Test”
Proves:
- turn-taking
- polling
- TTS cues
- scene switching
- safety filters
- overlays
- transcript capture
Produces clips immediately.
### Phase 2 — Co-op Cipher Break (stateful progress UI)
Proves:
- timers
- progress bar
- decision history
- hint escalation
### Phase 3 — Writers Room (persistence + recap pipeline)
Proves:
- story bible
- canon registry
- branch pruning
### Phase 4 — Ghost in the Chat (season finale format)
Uses everything:
- plus secrecy + evidence logic
**Thesis:** build a reliable game show OS first, then layer ambition on top.
---
## Extra Levers (High Impact)
- **Onboarding/catch-up panel** (1530s): “Heres the case so far…”
- **Round length discipline**: retention loves predictable cadence
- **Soft participation**: lurkers can vote without typing commands
- **Clip triggers**: guarantee 12 clip moments per round
(verdict, evidence reveal, twist lock)
- **Failure theatrics**: “mistrial” / “narrator emergency recap” turns bugs into content
---
## Cost Model (Runtime Expense Knobs) 💸
### Primary drivers
- **LLM tokens per minute**
- multi-agent formats multiply tokens quickly
- **Summaries**
- expensive but necessary; do once per phase
- **TTS minutes**
- keep TTS for “announcer moments,” verdicts, recaps (not constant narration)
- **Image generation**
- biggest cost spike if frequent
- use event-based: episode cover, key evidence art, final verdict tableau
- **State persistence + logging**
- cheap in dollars, expensive in correctness (bugs kill trust)
### Relative runtime cost (low → high)
JuryRigged (medium) < Cipher (medium) < Writers Room (medium-high) ≈ Ghost (medium-high)
---

View File

@@ -10,7 +10,7 @@ SHELL := /usr/bin/env bash
NPM ?= npm
DOCKER_COMPOSE ?= docker compose
.PHONY: help install dev dev-dashboard lint build build-dashboard test test-spec ci smoke-staging start migrate migrate-dist docker-up docker-down docker-restart clean status
.PHONY: help install dev dev-dashboard run lint build build-dashboard test test-spec ci smoke-staging start migrate migrate-dist docker-up docker-down docker-restart clean status
help: ## Show available commands
@awk 'BEGIN {FS = ":.*##"; printf "\nJuryRigged Make targets:\n\n"} /^[a-zA-Z0-9_.-]+:.*##/ { printf " %-18s %s\n", $$1, $$2 } END { printf "\n" }' $(MAKEFILE_LIST)
@@ -24,6 +24,13 @@ dev: ## Start local dev server with watch mode
dev-dashboard: ## Start operator dashboard dev server with Vite
$(NPM) run dev:dashboard
run: ## Start API + dashboard together (Ctrl+C stops both)
@bash -c 'set -euo pipefail; \
$(NPM) run dev & API_PID=$$!; \
$(NPM) run dev:dashboard & DASH_PID=$$!; \
trap "kill $$API_PID $$DASH_PID 2>/dev/null || true" INT TERM EXIT; \
wait $$API_PID $$DASH_PID'
lint: ## Run TypeScript type-check (no emit)
$(NPM) run lint

Binary file not shown.

BIN
aa-sprites/HDedgeworth.zip Normal file

Binary file not shown.

BIN
aa-sprites/HDfranziska.zip Normal file

Binary file not shown.

BIN
aa-sprites/HDgodot.zip Normal file

Binary file not shown.

BIN
aa-sprites/HDgrossberg.zip Normal file

Binary file not shown.

Binary file not shown.

BIN
aa-sprites/HDgumshoe.zip Normal file

Binary file not shown.

BIN
aa-sprites/HDjudge.zip Normal file

Binary file not shown.

BIN
aa-sprites/HDlarry.zip Normal file

Binary file not shown.

BIN
aa-sprites/HDlarryGuard.zip Normal file

Binary file not shown.

BIN
aa-sprites/HDlarryPaint.zip Normal file

Binary file not shown.

BIN
aa-sprites/HDlotta.zip Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
aa-sprites/HDmanfred.zip Normal file

Binary file not shown.

BIN
aa-sprites/HDmaya.zip Normal file

Binary file not shown.

Binary file not shown.

BIN
aa-sprites/HDmia.zip Normal file

Binary file not shown.

BIN
aa-sprites/HDmiamaya.zip Normal file

Binary file not shown.

BIN
aa-sprites/HDpayne.zip Normal file

Binary file not shown.

Binary file not shown.

BIN
aa-sprites/HDpearl.zip Normal file

Binary file not shown.

BIN
aa-sprites/HDphoenix.zip Normal file

Binary file not shown.

BIN
aa-sprites/HDyedgeworth.zip Normal file

Binary file not shown.

BIN
aa-sprites/HDymia.zip Normal file

Binary file not shown.

BIN
aa-sprites/HDyphoenix.zip Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
aa-sprites/sfx-gk.zip Normal file

Binary file not shown.

BIN
aa-sprites/sfx-tat.zip Normal file

Binary file not shown.

BIN
aa-sprites/sfx_20AJ.zip Normal file

Binary file not shown.

Binary file not shown.

BIN
aa-sprites/sfx_20jfa.zip Normal file

Binary file not shown.

BIN
aa-sprites/sfx_20pwaa.zip Normal file

Binary file not shown.

View File

@@ -1,108 +0,0 @@
{
"scope": [
"src/**/*.ts",
"dashboard/src/**/*.{ts,tsx}",
"public/**/*.js",
"public/renderer/**/*.js"
],
"generatedAt": "2025-01-28",
"summary": {
"high": 7,
"medium": 14,
"low": 6,
"total": 27
},
"issues": [
{
"id": "CC-001",
"summary": "public app stream handling now uses dispatch-map handlers"
},
{
"id": "CC-004",
"summary": "prompt rotation pipeline duplication removed via shared helpers"
},
{
"id": "CC-006",
"summary": "vote-spam stale cleanup duplication removed"
},
{
"id": "CC-008",
"summary": "phase entry boilerplate consolidated with beginPhase helper"
},
{
"id": "CC-009",
"summary": "session mutation error mapping centralized"
},
{
"id": "CC-010",
"summary": "phase timing literals replaced with named constants"
},
{
"id": "CC-012",
"summary": "dashboard SSE reconnect delay constant extracted"
},
{
"id": "CC-013",
"summary": "tx:any removed; transaction cast centralized via helper"
},
{
"id": "CC-014",
"summary": "ambiguous dashboard response variable renamed"
},
{
"id": "CC-015",
"summary": "component timing literals extracted to constants"
},
{
"id": "CC-016",
"summary": "coding conventions document added and linked from README"
}
],
"issues": [
{
"id": "CC-001R",
"type": "Function Issues",
"principle": "Small Functions + SRP",
"location": "src/server.ts",
"severity": "Medium",
"issue": "createServerApp still coordinates env parsing, guard lifecycle, composition, and recovery flow in one startup function.",
"suggestion": "Extract createRuntimeConfig(...) and resumeInterruptedSessions(...), keeping createServerApp primarily as wiring glue."
},
{
"id": "CC-007R",
"type": "Function Issues",
"principle": "Small Functions + SRP",
"location": "src/court/phases/session-flow.ts",
"severity": "Medium",
"issue": "runWitnessExamPhase still combines witness-loop orchestration with recap generation/persistence/TTS side effects.",
"suggestion": "Extract runWitnessCycle(...) and emitRecapIfDue(...) helpers to isolate responsibilities."
},
{
"id": "CC-011R",
"type": "Config Drift Risk",
"principle": "Avoid Hardcoding Drift",
"location": "src/court/catchup.ts, public/app.js",
"severity": "Medium",
"issue": "Catch-up max char cap is independently defined in backend and public runtimes.",
"suggestion": "Promote to one shared config source consumed by both runtime surfaces."
},
{
"id": "CC-005R",
"type": "Over-Engineering",
"principle": "YAGNI",
"location": "src/court/prompt-bank.ts",
"severity": "Low",
"issue": "selectNextPrompt remains unused in workspace and now primarily exists for compatibility.",
"suggestion": "Remove in a planned cleanup release after external usage confirmation."
},
{
"id": "CC-013R",
"type": "Typing Ergonomics",
"principle": "Consistency",
"location": "src/store/session-store.ts",
"severity": "Low",
"issue": "One transaction type cast remains inside the centralized helper due postgres callback/type-call-signature mismatch.",
"suggestion": "Keep centralized unless upstream typings or wrapper abstraction allows full removal without type regressions."
}
]
}

View File

@@ -1,252 +0,0 @@
# Clean Code Review — JuryRigged (Full Repo)
**Date**: 2025-01-28
**Scope**: All source files (`src/`, `dashboard/`, `public/`, config)
**Reviewer**: Automated (Clean Code dimensions)
**Conventions ref**: `docs/coding-conventions.md`
---
## Summary
| Severity | Count |
|----------|-------|
| High | 7 |
| Medium | 14 |
| Low | 6 |
The codebase is well-structured overall: domain types are centralized, event flows are clearly separated, error handling at API boundaries is solid, and the coding conventions are largely followed. The main areas for improvement are **duplicated utility helpers in the dashboard**, **magic numbers in the renderer layer**, and a handful of **long functions** that would benefit from extraction.
---
## High Severity
### [Duplication]: `asRecord` / `asString` / `asNumber` duplicated across dashboard files
- **Principle**: DRY
- **Location**: `dashboard/src/App.tsx:10-22`, `dashboard/src/session-snapshot.ts:23-43`
- **Severity**: High
- **Issue**: Identical payload-narrowing helpers (`asRecord`, `asString`, `asNumber`, `asStringArray`) are copy-pasted in two files. Any behavioral change must be applied in both places.
- **Suggestion**: Extract into `dashboard/src/utils/payload-guards.ts` and import from both files.
### [Function Size]: `createDialogueStateMachine()` — ~230 lines
- **Principle**: Small Functions + SRP
- **Location**: `public/renderer/dialogue.js:40-270`
- **Severity**: High
- **Issue**: Single closure function managing typewriter state, punctuation timing, blip sounds, skip logic, and line advancement. Hard to test or modify individual behaviors.
- **Suggestion**: Extract `advanceLine()`, `computePunctuationDelay()`, and `handleSkip()` as standalone functions that the state machine delegates to.
### [Function Size]: `initCharacters()` — ~270 lines
- **Principle**: Small Functions + SRP
- **Location**: `public/renderer/characters.js:15-285`
- **Severity**: High
- **Issue**: Monolithic function creating all character slots, placeholder sprites, tint logic, and pose/face overlay handlers in one closure. Difficult to reason about individual slot behavior.
- **Suggestion**: Extract `createCharacterSlot()` to build one slot, then loop in `initCharacters()`. Extract `setPoseSprite` / `setFaceOverlay` as named helpers.
### [Function Size]: `instrumentCourtSessionStore()` — 87 lines
- **Principle**: Small Functions + SRP
- **Location**: `src/metrics.ts:202-289`
- **Severity**: High
- **Issue**: Factory returning a wrapper object where every method follows the same try/catch → record-error → rethrow pattern. The repetition obscures the actual instrumentation intent.
- **Suggestion**: Extract a generic `wrapWithMetrics(methodName, fn)` helper and use it for each method, reducing the function to a mapping.
### [Magic Numbers]: Renderer hex colors and proportional coordinates
- **Principle**: Avoid Hardcoding
- **Location**: `public/renderer/layers/background.js`, `characters.js`, `ui.js`, `effects.js`, `evidence.js`
- **Severity**: High
- **Issue**: 80+ unlabeled hex color values (`0xa08040`, `0x3b2f1e`, `0xff4444`, etc.) and proportional position constants (`0.5`, `0.12`, `0.85`, etc.) scattered throughout all renderer layer files. No palette or layout constants file exists.
- **Suggestion**: Create `public/renderer/theme.js` exporting named color constants (e.g., `ROLE_COLOR_JUDGE`, `BG_COURTROOM_DARK`) and layout proportions (e.g., `JUDGE_BENCH_Y`, `WITNESS_SLOT_X`).
### [Missing Backoff]: `useSSE` reconnect uses fixed 3 s interval
- **Principle**: Structural Clarity / Runtime Safety
- **Location**: `dashboard/src/hooks/useSSE.ts:46-50`
- **Severity**: High
- **Issue**: On SSE disconnect, the hook retries every 3 000 ms forever with no exponential backoff and no retry cap. Under sustained server downtime this can flood the server with connection attempts.
- **Suggestion**: Implement exponential backoff (e.g., 3 s → 6 s → 12 s, capped at 30 s) and a max-retry limit after which `error` state is set permanently.
### [Potential Resource Leak]: `effects.js` shake timer
- **Principle**: Runtime Safety
- **Location**: `public/renderer/effects.js``shake()` function
- **Severity**: High
- **Issue**: Calling `shake()` while a previous shake animation is still running starts a new `setInterval` without clearing the old one, leaking interval handles.
- **Suggestion**: Guard `shake()` entry by checking/clearing any active `shakeTimer` before creating a new interval.
---
## Medium Severity
### [Duplication]: `selectNextPrompt` / `selectNextSafePrompt` — 80 % identical
- **Principle**: DRY
- **Location**: `src/court/prompt-bank.ts:187-240`
- **Severity**: Medium
- **Issue**: Both functions differ only in a `.filter(p => p.active)` predicate. The rotation, hashing, and fallback logic is duplicated.
- **Suggestion**: Merge into a single function accepting an optional `filter` predicate; `selectNextSafePrompt` becomes `selectNextPrompt(history, { filter: p => p.active })`.
### [Duplication]: Typewriter logic duplicated between `public/app.js` and `dialogue.js`
- **Principle**: DRY
- **Location**: `public/app.js` (`startDialogueTypewriter`) and `public/renderer/dialogue.js`
- **Severity**: Medium
- **Issue**: Both files implement character-by-character text reveal with punctuation pauses and skip support. The `app.js` version is the legacy overlay; `dialogue.js` is the PixiJS version. Maintaining two diverges over time.
- **Suggestion**: Extract shared typewriter config (chars-per-second, punctuation delays) into `public/renderer/typewriter-config.js`. Long-term: remove `app.js` typewriter once PixiJS renderer is primary.
### [Magic Numbers]: `speaker-selection.ts` weighting constants
- **Principle**: Avoid Hardcoding
- **Location**: `src/court/speaker-selection.ts:26,41`
- **Severity**: Medium
- **Issue**: `Math.random() * 0.4 - 0.2` (jitter range) and `0.5` (recency penalty multiplier) are unlabeled.
- **Suggestion**: Extract as `const JITTER_RANGE = 0.4` / `const RECENCY_PENALTY = 0.5` with brief comment on tuning rationale.
### [Magic Numbers]: Token budget defaults
- **Principle**: Avoid Hardcoding
- **Location**: `src/court/token-budget.ts:22-29`
- **Severity**: Medium
- **Issue**: Role-specific token limits `260, 220, 160, 120` and `costPer1kTokensUsd: 0.002` are inline in the defaults object with no explanation of how values were chosen.
- **Suggestion**: Add a brief comment block above `DEFAULT_ROLE_TOKEN_BUDGETS` explaining the sizing rationale.
### [Magic Numbers]: `catchup.ts` — `DEFAULT_CASE_SO_FAR_MAX_CHARS = 220`, `turns.slice(-3)`
- **Principle**: Avoid Hardcoding
- **Location**: `src/court/catchup.ts:8,35`
- **Severity**: Medium
- **Issue**: `220` character limit and `-3` recent turns count are unlabeled. The `220` should document why this threshold.
- **Suggestion**: Rename `DEFAULT_CASE_SO_FAR_MAX_CHARS` → keep, add comment. Add `const RECENT_TURNS_COUNT = 3` for the slice.
### [Magic Numbers]: `dialogue.js` punctuation pause map
- **Principle**: Avoid Hardcoding
- **Location**: `public/renderer/dialogue.js:~10-20`
- **Severity**: Medium
- **Issue**: `180, 200, 200, 90, 110, 100, 260, 140` ms pause values for punctuation characters are inline with no comment.
- **Suggestion**: Group into a named `PUNCTUATION_PAUSES` constant object with a brief comment.
### [Naming]: `bestOf()` — non-intent-revealing
- **Principle**: Meaningful Names
- **Location**: `src/court/phases/session-flow.ts:79`
- **Severity**: Medium
- **Issue**: `bestOf` doesn't convey "most voted option". Reads like a comparison utility.
- **Suggestion**: Rename to `mostVotedChoice()` or `winningVoteOption()`.
### [Naming]: `input` parameter used generically in multiple functions
- **Principle**: Meaningful Names
- **Location**: `src/court/personas.ts:42`, `src/court/prompt-bank.ts:170,194,218`
- **Severity**: Medium
- **Issue**: Multiple functions use `input` as the sole parameter name for different shaped objects. In files with multiple such functions it reduces scanability.
- **Suggestion**: Use `promptConfig`, `rotationInput`, `selectionInput` respectively.
### [Naming]: `stitched` in `catchup.ts`
- **Principle**: Meaningful Names
- **Location**: `src/court/catchup.ts:36`
- **Severity**: Medium
- **Issue**: Variable name doesn't reveal intent.
- **Suggestion**: Rename to `recentTurnsSummary` or `turnExcerpt`.
### [Function Size]: `initCamera()` — ~120-line closure
- **Principle**: Small Functions + SRP
- **Location**: `public/renderer/camera.js`
- **Severity**: Medium
- **Issue**: Manages transition state, easing math, and animation frame loop in one closure.
- **Suggestion**: Extract `easeLerp()` and `animateTransition()` as standalone functions.
### [Function Size]: ModerationQueue `useEffect` — ~40 lines with nested loops
- **Principle**: Small Functions + SRP
- **Location**: `dashboard/src/components/ModerationQueue.tsx`
- **Severity**: Medium
- **Issue**: Event processing, deduplication, and queue mutation combined in a single effect callback.
- **Suggestion**: Extract `buildFlaggedItemsFromEvents(newEvents, existingIds): FlaggedItem[]` as a pure function.
### [Structural Clarity]: SessionMonitor inconsistent sessionId truncation
- **Principle**: Consistency
- **Location**: `dashboard/src/components/SessionMonitor.tsx` (`.slice(0, 16)`) vs `dashboard/src/App.tsx` (`.slice(0, 8)`)
- **Severity**: Medium
- **Issue**: Session ID display length differs between components without explanation.
- **Suggestion**: Extract `const SESSION_ID_DISPLAY_LENGTH` and use consistently.
### [Duplication]: `parsePositiveInt` / `parsePositiveFloat` in `token-budget.ts`
- **Principle**: DRY
- **Location**: `src/court/token-budget.ts:39-55`
- **Severity**: Medium
- **Issue**: 90 % identical functions differing only in `parseInt` vs `parseFloat`. Both also duplicate `parsePositiveInt` in `server.ts`.
- **Suggestion**: Merge into a shared utility or deduplicate via a generic `parsePositiveNumber`.
---
## Low Severity
### [Naming]: Renderer abbreviations (`camX`, `camY`, `camZoom`)
- **Principle**: Meaningful Names
- **Location**: `public/renderer/camera.js`
- **Severity**: Low
- **Issue**: Abbreviated coordinates. Acceptable in animation code but less self-documenting.
- **Suggestion**: Keep — standard convention in renderer/game code.
### [YAGNI]: `OBSWebSocketAdapter` is entirely TODO stubs
- **Principle**: YAGNI
- **Location**: `src/broadcast/obs-adapter.ts`
- **Severity**: Low
- **Issue**: Every method logs a stub message and does nothing. Kept as a placeholder.
- **Suggestion**: Acceptable if planned for near-term implementation. Consider marking with a `// TODO(phase-N)` header.
### [Naming]: `MockTTSAdapter` exported from production code
- **Principle**: Consistency
- **Location**: `src/tts/adapter.ts`
- **Severity**: Low
- **Issue**: Test-only adapter lives alongside production code without clear separation.
- **Suggestion**: Either prefix with `_` or move to `src/tts/__mocks__/adapter.ts`.
### [Structural Clarity]: `logger.ts` uses `Object.create()` for child loggers
- **Principle**: Readability First
- **Location**: `src/logger.ts:73-88`
- **Severity**: Low
- **Issue**: Prototype-based composition is unusual in TypeScript; class composition would be clearer.
- **Suggestion**: Acceptable if intentional. Add a brief comment explaining the design choice.
### [Convention]: `console.log` / `console.error` used in dashboard instead of structured logging
- **Principle**: Project Conventions
- **Location**: `dashboard/src/hooks/useSSE.ts:32,35`, dashboard components
- **Severity**: Low
- **Issue**: Dashboard uses raw `console.*` while backend uses structured logger. Acceptable for browser code.
- **Suggestion**: No action needed unless a browser-side logging wrapper is desired.
### [Convention]: `eslint-disable-next-line no-console` appears 10+ times in backend
- **Principle**: Project Conventions
- **Location**: `src/server.ts`, `src/court/orchestrator.ts`, `src/broadcast/adapter.ts`
- **Severity**: Low
- **Issue**: The structured `logger` exists but many places still use `console.*` with inline lint suppressions.
- **Suggestion**: Migrate remaining `console.warn` / `console.error` calls to the structured logger.
---
## What's Working Well
- **Types**: Centralized in `src/types.ts` with narrow union types for phases, roles, events. Dashboard mirrors via its own `types.ts`.
- **Event taxonomy**: Every court event has a typed payload interface in `src/events.ts`.
- **Error handling at API boundaries**: `sendError()`, `mapSessionMutationError()`, and custom error classes (`CourtValidationError`, `CourtNotFoundError`) provide clear error responses.
- **Moderation pipeline**: Input validation → content filter → spam guard → structured event emission.
- **Phase orchestration**: Clean separation into `phases/session-flow.ts` with named constants for durations and pauses.
- **Metrics instrumentation**: Prometheus counters/histograms properly wrap store operations.
- **Test coverage**: Behavior-focused tests for all major modules.
- **Configuration**: Environment-driven with sensible defaults and `parsePositiveInt` safety.
- **Coding conventions**: Documented and largely followed across the project.

View File

@@ -7,6 +7,8 @@ services:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-change_this_now}
POSTGRES_DB: juryrigged
ports:
- '127.0.0.1:55432:5432'
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:

192
package-lock.json generated
View File

@@ -11,13 +11,17 @@
"dotenv": "^17.2.3",
"express": "^4.21.2",
"express-rate-limit": "^8.2.1",
"howler": "^2.2.4",
"pixi.js": "^8.0.0",
"postgres": "^3.4.5",
"prom-client": "^15.1.3",
"react": "^18.3.1",
"react-dom": "^18.3.1"
"react-dom": "^18.3.1",
"tmi.js": "^1.8.5"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/howler": "^2.2.11",
"@types/node": "^22.13.9",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
@@ -914,6 +918,12 @@
"node": ">=8.0.0"
}
},
"node_modules/@pixi/colord": {
"version": "2.9.6",
"resolved": "https://registry.npmjs.org/@pixi/colord/-/colord-2.9.6.tgz",
"integrity": "sha512-nezytU2pw587fQstUu1AsJZDVEynjskwOL+kibwcdxsMBFqPsFFNA7xl0ii/gXuDi6M0xj3mfRJj8pBSc2jCfA==",
"license": "MIT"
},
"node_modules/@rolldown/pluginutils": {
"version": "1.0.0-beta.27",
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz",
@@ -1337,6 +1347,12 @@
"@types/node": "*"
}
},
"node_modules/@types/earcut": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/earcut/-/earcut-3.0.0.tgz",
"integrity": "sha512-k/9fOUGO39yd2sCjrbAJvGDEQvRwRnQIZlBz43roGwUZo5SHAmyVvSFyaVVZkicRVCaDXPKlbxrUcBuJoSWunQ==",
"license": "MIT"
},
"node_modules/@types/estree": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
@@ -1370,6 +1386,13 @@
"@types/send": "*"
}
},
"node_modules/@types/howler": {
"version": "2.2.12",
"resolved": "https://registry.npmjs.org/@types/howler/-/howler-2.2.12.tgz",
"integrity": "sha512-hy769UICzOSdK0Kn1FBk4gN+lswcj1EKRkmiDtMkUGvFfYJzgaDXmVXkSShS2m89ERAatGIPnTUlp2HhfkVo5g==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/http-errors": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
@@ -1490,6 +1513,21 @@
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
}
},
"node_modules/@webgpu/types": {
"version": "0.1.69",
"resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.69.tgz",
"integrity": "sha512-RPmm6kgRbI8e98zSD3RVACvnuktIja5+yLgDAkTmxLr90BEwdTXRQWNLF3ETTTyH/8mKhznZuN5AveXYFEsMGQ==",
"license": "BSD-3-Clause"
},
"node_modules/@xmldom/xmldom": {
"version": "0.8.11",
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz",
"integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
@@ -1925,6 +1963,12 @@
"node": ">= 0.4"
}
},
"node_modules/earcut": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/earcut/-/earcut-3.0.2.tgz",
"integrity": "sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==",
"license": "ISC"
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -2044,6 +2088,12 @@
"node": ">= 0.6"
}
},
"node_modules/eventemitter3": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz",
"integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==",
"license": "MIT"
},
"node_modules/express": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz",
@@ -2295,6 +2345,15 @@
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
}
},
"node_modules/gifuct-js": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/gifuct-js/-/gifuct-js-2.1.2.tgz",
"integrity": "sha512-rI2asw77u0mGgwhV3qA+OEgYqaDn5UNqgs+Bx0FGwSpuqfYn+Ir6RQY5ENNQ8SbIiG/m5gVa7CD5RriO4f4Lsg==",
"license": "MIT",
"dependencies": {
"js-binary-schema-parser": "^2.0.3"
}
},
"node_modules/glob-parent": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
@@ -2344,6 +2403,12 @@
"node": ">= 0.4"
}
},
"node_modules/howler": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/howler/-/howler-2.2.4.tgz",
"integrity": "sha512-iARIBPgcQrwtEr+tALF+rapJ8qSc+Set2GJQl7xT1MQzWaVkFebdJhR3alVlSiUf5U7nAANKuj3aWpwerocD5w==",
"license": "MIT"
},
"node_modules/http-errors": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
@@ -2462,6 +2527,12 @@
"node": ">=0.12.0"
}
},
"node_modules/ismobilejs": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ismobilejs/-/ismobilejs-1.1.1.tgz",
"integrity": "sha512-VaFW53yt8QO61k2WJui0dHf4SlL8lxBofUuUmwBo0ljPk0Drz2TiuDW4jo3wDcv41qy/SxrJ+VAzJ/qYqsmzRw==",
"license": "MIT"
},
"node_modules/jiti": {
"version": "1.21.7",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
@@ -2472,6 +2543,12 @@
"jiti": "bin/jiti.js"
}
},
"node_modules/js-binary-schema-parser": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/js-binary-schema-parser/-/js-binary-schema-parser-2.0.3.tgz",
"integrity": "sha512-xezGJmOb4lk/M1ZZLTR/jaBHQ4gG/lqQnJqdIv4721DMggsa1bDVlHXNeHYogaIEHD9vCRv0fcL4hMA+Coarkg==",
"license": "MIT"
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -2685,6 +2762,26 @@
"node": ">= 0.6"
}
},
"node_modules/node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"license": "MIT",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/node-releases": {
"version": "2.0.27",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
@@ -2746,6 +2843,12 @@
"node": ">= 0.8"
}
},
"node_modules/parse-svg-path": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz",
"integrity": "sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ==",
"license": "MIT"
},
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -2808,6 +2911,28 @@
"node": ">= 6"
}
},
"node_modules/pixi.js": {
"version": "8.16.0",
"resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-8.16.0.tgz",
"integrity": "sha512-gu2xw3sZGAn3cWBtk0HqTQT+v19YAfiaYXwUGgWoJl5NKz4cEZJUgWrwkmdfDszGyYBAGqOvJNbd2M9+vzLLMg==",
"license": "MIT",
"dependencies": {
"@pixi/colord": "^2.9.6",
"@types/earcut": "^3.0.0",
"@webgpu/types": "^0.1.69",
"@xmldom/xmldom": "^0.8.11",
"earcut": "^3.0.2",
"eventemitter3": "^5.0.1",
"gifuct-js": "^2.1.2",
"ismobilejs": "^1.1.1",
"parse-svg-path": "^0.1.2",
"tiny-lru": "^11.4.7"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/pixijs"
}
},
"node_modules/postcss": {
"version": "8.5.6",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
@@ -3532,6 +3657,15 @@
"node": ">=0.8"
}
},
"node_modules/tiny-lru": {
"version": "11.4.7",
"resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-11.4.7.tgz",
"integrity": "sha512-w/Te7uMUVeH0CR8vZIjr+XiN41V+30lkDdK+NRIDCUYKKuL9VcmaUEmaPISuwGhLlrTGh5yu18lENtR9axSxYw==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=12"
}
},
"node_modules/tinyglobby": {
"version": "0.2.15",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
@@ -3580,6 +3714,19 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/tmi.js": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/tmi.js/-/tmi.js-1.8.5.tgz",
"integrity": "sha512-A9qrydfe1e0VWM9MViVhhxVgvLpnk7pFShVUWePsSTtoi+A1X+Zjdoa7OJd7/YsgHXGj3GkNEvnWop/1WwZuew==",
"license": "MIT",
"dependencies": {
"node-fetch": "^2.6.1",
"ws": "^8.2.0"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -3602,6 +3749,12 @@
"node": ">=0.6"
}
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
"license": "MIT"
},
"node_modules/ts-interface-checker": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
@@ -4318,6 +4471,43 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
"license": "BSD-2-Clause"
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"license": "MIT",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/ws": {
"version": "8.19.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
"integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",

View File

@@ -23,13 +23,17 @@
"dotenv": "^17.2.3",
"express": "^4.21.2",
"express-rate-limit": "^8.2.1",
"howler": "^2.2.4",
"pixi.js": "^8.0.0",
"prom-client": "^15.1.3",
"postgres": "^3.4.5",
"react": "^18.3.1",
"react-dom": "^18.3.1"
"react-dom": "^18.3.1",
"tmi.js": "^1.8.5"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/howler": "^2.2.11",
"@types/node": "^22.13.9",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",

View File

@@ -1,66 +0,0 @@
{
"scope": "working-tree vs 467d7d9 (HEAD/main)",
"verdict": "Ready with fixes",
"tests": { "pass": 158, "fail": 0, "skipped": 2 },
"triage": {
"docsOnly": false,
"reactNextPerfReview": false,
"uiGuidelinesAudit": true
},
"issues": {
"critical": [
{
"id": "C1",
"title": "/press and /present endpoints have no rate limiting",
"location": "src/server.ts:703-731",
"impact": "Unauthenticated flood of render_directive events via rapid /press calls"
},
{
"id": "C2",
"title": "Twitch !objection emits count: -1 sentinel; nothing increments it",
"location": "src/twitch/adapter.ts:149-153",
"impact": "SSE listeners receive count=-1, corrupting overlay and dashboard UI state"
}
],
"important": [
{
"id": "I1",
"title": "/api/metrics endpoint not documented; operator runbook contradicts",
"location": "docs/operator-runbook.md:213"
},
{
"id": "I2",
"title": "TWITCH_EVENTSUB_SECRET in .env.example is unused in code",
"location": ".env.example:42"
},
{
"id": "I3",
"title": "event-taxonomy.md render_directive payload shows flat pose/face vs actual map",
"location": "docs/event-taxonomy.md"
},
{
"id": "I4",
"title": "Dashboard App.tsx duplicates session-snapshot event mapping logic",
"location": "dashboard/src/App.tsx:10-160"
}
],
"minor": [
{
"id": "M1",
"title": "inferRenderDirective only matches keywords with trailing !",
"location": "src/court/orchestrator.ts:100-115"
},
{
"id": "M2",
"title": "public/app.js growing large (~970 lines)",
"location": "public/app.js"
},
{
"id": "M3",
"title": "record:sse script flags not in docs/api.md",
"location": "README.md"
}
]
},
"untested_new_modules": ["src/metrics.ts", "src/twitch/adapter.ts"]
}

View File

@@ -1,124 +0,0 @@
# Quality Review — Phase 7 Uncommitted Changes
## Summary
- **Verdict: Ready with fixes** (2 critical, 4 important)
- **Scope:** Working tree vs HEAD (`467d7d9`) — 20 modified files + ~12 new untracked files
- **Tests:** 158 pass / 0 fail / 2 skipped
## Triage
- Docs-only: **no**
- React/Next perf review: **no** (dashboard is Vite + React 18, no Next.js)
- UI guidelines audit: **yes**`dashboard/src/App.tsx` and `public/app.js` / `public/index.html` have significant UI changes
- Reason:
- `.tsx` files changed (`dashboard/src/App.tsx`)
- Client JS overlay code heavily extended (`public/app.js`, `public/index.html`)
- Core server, orchestrator, types, events, and new modules added (metrics, replay, twitch)
---
## Strengths
1. **Well-structured event system extension** — Phase 7 event types (`render_directive`, `witness_statement`, `case_file_generated`) follow existing conventions: typed payloads, runtime assertion in `assertEventPayload`, and matching test coverage.
2. **Comprehensive documentation**`docs/event-taxonomy.md`, `docs/api.md`, `docs/broadcast-integration.md`, and `README.md` are all updated with the new endpoints, event types, and Twitch integration docs.
3. **Prometheus metrics module**`src/metrics.ts` is clean, uses a dedicated registry, instruments all store operations via a proxy wrapper (`instrumentCourtSessionStore`), and exposes SSE/vote telemetry.
4. **Replay/recording system** — NDJSON record + replay is well-separated in `src/replay/session-replay.ts` with a clean manager class, test coverage, and both CLI flag and env-var entry points.
5. **Graceful degradation** — Twitch adapter, replay, and metrics all degrade to no-op when unconfigured; LLM client now falls back to mock on empty response instead of returning empty strings.
6. **Docker security hardened** — compose binds to `127.0.0.1` only and adds `TRUST_PROXY` support with proper parsing (bool / int / CIDR list).
---
## Issues
### Critical (Must Fix)
#### C1. `/press` and `/present` endpoints have no rate limiting
- **Location:** [src/server.ts](src/server.ts#L703-L731)
- **What:** The new `POST /api/court/sessions/:id/press` and `POST /api/court/sessions/:id/present` handlers are registered without any rate limiter. The existing vote endpoint has `VoteSpamGuard`; these audience-interaction endpoints have none.
- **Why it matters:** These are public-facing, unauthenticated endpoints. An attacker can flood `render_directive` events via rapid `/press` calls, overwhelming SSE clients and the overlay renderer. The docs themselves note "Per-loop audience action rate limits are enforced at the API layer" (broadcast-integration.md) — but this is not actually implemented.
- **Minimal fix:** Apply `express-rate-limit` (or extend `VoteSpamGuard`) to both endpoints. A sensible default: 10 req/IP/10s.
#### C2. Twitch `!objection` emits `count: -1` sentinel, but nothing increments it
- **Location:** [src/twitch/adapter.ts](src/twitch/adapter.ts#L149-L153)
- **What:** `wireTwitchToSession` emits `objection_count_changed` with `count: -1` and a comment "sentinel — orchestrator should increment". But the orchestrator only increments `objectionCount` inside `handleModerationRedirect` (moderation path). No code reads the `-1` sentinel from an SSE event and increments the counter.
- **Why it matters:** Every Twitch `!objection` command will broadcast `count: -1` to all SSE listeners. The overlay and dashboard will display `-1` as the objection count, corrupting the UI state. This is a data integrity issue.
- **Minimal fix:** Either (a) read the current `objectionCount` from the session inside `wireTwitchToSession` and emit `currentCount + 1`, or (b) have the store handle the increment internally when it receives this event.
---
### Important (Should Fix)
#### I1. `/api/metrics` endpoint not documented; operator runbook says it doesn't exist
- **Location:** [docs/operator-runbook.md](docs/operator-runbook.md#L213), README "API at a Glance" section
- **What:** `docs/operator-runbook.md` line 213 states: "There is no built-in metrics endpoint." But the uncommitted code adds `GET /api/metrics` serving Prometheus-format metrics. The README's API listing also omits `/api/metrics`.
- **Why it matters:** Operators won't discover the metrics endpoint; the runbook actively misleads.
- **Minimal fix:** Update `docs/operator-runbook.md` to reference `/api/metrics` and add it to the README's API listing and `docs/api.md`.
#### I2. `TWITCH_EVENTSUB_SECRET` in `.env.example` is unused
- **Location:** `.env.example` line 42
- **What:** `.env.example` declares `TWITCH_EVENTSUB_SECRET=` but no code reads this variable. The Twitch adapter only uses `TWITCH_CHANNEL`, `TWITCH_BOT_TOKEN`, and `TWITCH_CLIENT_ID`.
- **Why it matters:** Misleads operators into thinking EventSub is configured. If a secret is generated and placed here, it creates a false sense of security for a feature that doesn't exist yet.
- **Minimal fix:** Remove the line or comment it with `# (future — not yet used)`.
#### I3. `docs/event-taxonomy.md` payload schema mismatch for `render_directive`
- **Location:** [docs/event-taxonomy.md](docs/event-taxonomy.md) (render_directive payload section)
- **What:** The doc schema shows `directive.pose` (singular string) and `directive.face` (singular string), but the TypeScript type `RenderDirective` in `src/types.ts` uses `poses?: Partial<Record<CourtRole, CharacterPose>>` (plural, map) and `faces?: Partial<Record<CourtRole, CharacterFace>>` (plural, map). The orchestrator's `inferRenderDirective` emits `poses: { [role]: 'point' }`, not a flat `pose: 'point'`.
- **Why it matters:** Frontend consumers implementing against the docs will expect a flat string but receive an object map, causing rendering bugs.
- **Minimal fix:** Update the event taxonomy doc to show the actual `poses`/`faces` map shape.
#### I4. Dashboard `applyEventToSnapshot` duplicates session-snapshot logic
- **Location:** [dashboard/src/App.tsx](dashboard/src/App.tsx#L10-L160) (the entire `applyEventToSnapshot` function)
- **What:** The 160-line `applyEventToSnapshot` function in `App.tsx` re-implements event-to-snapshot mapping that already exists in `dashboard/src/session-snapshot.ts` (`mapSessionToSnapshot`). The two implementations handle overlapping event types (`phase_changed`, `turn`, `judge_recap_emitted`, `vote_updated`) with slightly different parsing logic.
- **Why it matters:** Two sources of truth for the same transformation. If one is updated, the other goes stale. The `App.tsx` version uses its own `asRecord`/`asString`/`asNumber` helpers rather than sharing the snapshot mapper.
- **Minimal fix:** Extend `mapSessionToSnapshot` (or add an `applyEventDelta` function in `session-snapshot.ts`) and import it into `App.tsx`.
---
### Minor (Nice to Have)
#### M1. `inferRenderDirective` keyword matching is case-sensitive after `.toUpperCase()`
- **Location:** [src/court/orchestrator.ts](src/court/orchestrator.ts#L100-L115)
- **What:** The function calls `dialogue.toUpperCase()` then checks for `'OBJECTION!'`, `'HOLD IT!'`, `'TAKE THAT!'`. This works, but only matches exact substrings with the exclamation mark. Dialogue like `"Objection, your honor"` (no `!`) won't trigger the effect.
- **Why it matters:** Low severity — the effect miss is cosmetic, but users may expect the Ace Attorney effect on any `objection` keyword.
- **Minimal fix:** Consider also matching without the trailing `!`.
#### M2. `public/app.js` growing large
- **Location:** [public/app.js](public/app.js) (~970 lines after diff)
- **What:** The file is accumulating responsibilities: SSE connection, fixture replay, dialogue typewriter, renderer bootstrap, keyboard shortcuts, vote UI, caption controls. No module splitting beyond the renderer.
- **Why it matters:** Harder to maintain as more overlay features land. Not blocking, but worth noting.
#### M3. `record:sse` script not documented in `docs/api.md`
- **Location:** README mentions it; `docs/api.md` does not.
- **What:** The `npm run record:sse` command and its flags (`--session`, `--base`, `--out`, `--max-events`, `--duration-ms`) are documented in README but absent from the API reference doc.
- **Why it matters:** Minor discovery issue for developers who check `docs/api.md` first.
---
## UI Guidelines (terse audit of changed UI files)
- [dashboard/src/App.tsx](dashboard/src/App.tsx#L262): `setInterval` with 5s polling — no `AbortController` or visibility-based pause; wastes battery on background tabs.
- [public/app.js](public/app.js): `document.addEventListener('keydown', ...)` does preventDefault on Enter/Escape globally — may conflict with form fields in future overlays. Current `isEditableElementFocused` guard is adequate for now.
- [public/index.html](public/index.html): New `#pixiStage` container introduced — no `aria-hidden="true"` attribute on the decorative canvas; screen readers may try to parse it.
---
## Verification Evidence
| Check | Result |
| ------------------------- | ------------------------------------------------------- |
| `npm test` | 158 pass, 0 fail, 2 skipped |
| TypeScript compilation | Implicit via test run (tsx) |
| New event payloads tested | Yes — 6 new tests for Phase 7 events |
| Replay module tested | Yes — `session-replay.test.ts`, `server-replay.test.ts` |
| Metrics module | Not tested (no `src/metrics.test.ts`) |
| Twitch adapter | Not tested (no `src/twitch/adapter.test.ts`) |

View File

@@ -0,0 +1,82 @@
{"id":"c31fe93b-1638-4877-886f-45f6bd782b10","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"session_created","at":"2026-02-28T23:39:37.219Z","payload":{"sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1"}}
{"id":"1a6c7371-fc1b-4206-a78c-f088d121efd9","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"session_started","at":"2026-02-28T23:39:37.229Z","payload":{"sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","startedAt":"2026-02-28T23:39:37.227Z"}}
{"id":"1f800ff4-fbf6-4957-a507-9c04ae553d8c","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"case_file_generated","at":"2026-02-28T23:39:37.229Z","payload":{"caseFile":{"title":"Operator-created session","genre":"absurd_civil","caseType":"civil","synopsis":"Operator-created session","charges":["Damages as alleged"],"witnesses":[],"evidence":[],"sentenceOptions":["Community service in the meme archives","Banished to the shadow realm","Mandatory apology haikus","Ethics training hosted by a raccoon","Ukulele ankle-monitor probation"]},"sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","generatedAt":"2026-02-28T23:39:37.229Z"}}
{"id":"7319625b-b626-4a12-b1db-3e34c64fcbf8","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"phase_changed","at":"2026-02-28T23:39:37.236Z","payload":{"phase":"case_prompt","phaseStartedAt":"2026-02-28T23:39:37.232Z","phaseDurationMs":8000}}
{"id":"4a1211e1-aed1-4a70-90ad-ce2f292fc434","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"broadcast_hook_triggered","at":"2026-02-28T23:39:37.237Z","payload":{"phase":"case_prompt","hookType":"phase_stinger","triggeredAt":"2026-02-28T23:39:37.237Z"}}
{"id":"f317cc61-9194-4bb1-84d1-b3948feefbe3","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"turn","at":"2026-02-28T23:39:37.239Z","payload":{"turn":{"id":"9e72bd86-2bc7-4a00-9c70-4335c7e56931","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","turnNumber":0,"speaker":"mux","role":"bailiff","phase":"case_prompt","dialogue":"All rise. The JuryRigged court is now in session. Case: Operator-created session","createdAt":"2026-02-28T23:39:37.237Z"}}}
{"id":"9b4804b1-0d24-42a6-b0e2-dcd4c3d37ed0","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"phase_changed","at":"2026-02-28T23:39:38.444Z","payload":{"phase":"openings","phaseStartedAt":"2026-02-28T23:39:38.440Z","phaseDurationMs":30000}}
{"id":"b05172db-4636-4b3d-9961-184288b4ad9e","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"turn","at":"2026-02-28T23:39:38.447Z","payload":{"turn":{"id":"cabec07a-463c-43a5-a40c-3d80b545d239","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","turnNumber":1,"speaker":"subrosa","role":"prosecutor","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-02-28T23:39:38.445Z"}}}
{"id":"ad1529bd-4f6e-498c-93d6-671b77a4d041","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"render_directive","at":"2026-02-28T23:39:38.447Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"cabec07a-463c-43a5-a40c-3d80b545d239","phase":"openings","emittedAt":"2026-02-28T23:39:38.447Z"}}
{"id":"9d63bf8b-6947-4bea-b024-5660e2cf71f3","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"token_budget_applied","at":"2026-02-28T23:39:38.447Z","payload":{"turnId":"cabec07a-463c-43a5-a40c-3d80b545d239","speaker":"subrosa","role":"prosecutor","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"60beadcb-b815-4460-a0b3-635e445b5977","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"session_token_estimate","at":"2026-02-28T23:39:38.448Z","payload":{"turnId":"cabec07a-463c-43a5-a40c-3d80b545d239","role":"prosecutor","phase":"openings","estimatedPromptTokens":138,"estimatedCompletionTokens":22,"cumulativeEstimatedTokens":160,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00032}}
{"id":"727fcfd6-dbea-43fc-8aab-63a1769016fc","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"turn","at":"2026-02-28T23:39:39.353Z","payload":{"turn":{"id":"c9331cf6-8bcf-4849-93d0-a6b4da3b54f9","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","turnNumber":2,"speaker":"chora","role":"defense","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-02-28T23:39:39.349Z"}}}
{"id":"a94659b2-0f94-4063-b8b8-9e8390f42272","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"render_directive","at":"2026-02-28T23:39:39.354Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"c9331cf6-8bcf-4849-93d0-a6b4da3b54f9","phase":"openings","emittedAt":"2026-02-28T23:39:39.354Z"}}
{"id":"56d74a8d-813e-44e8-891b-9b8a3a7e4e03","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"token_budget_applied","at":"2026-02-28T23:39:39.354Z","payload":{"turnId":"c9331cf6-8bcf-4849-93d0-a6b4da3b54f9","speaker":"chora","role":"defense","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"fe689e5a-88f4-41c2-b266-d6c2f0acd1b7","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"session_token_estimate","at":"2026-02-28T23:39:39.354Z","payload":{"turnId":"c9331cf6-8bcf-4849-93d0-a6b4da3b54f9","role":"defense","phase":"openings","estimatedPromptTokens":290,"estimatedCompletionTokens":44,"cumulativeEstimatedTokens":334,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.000668}}
{"id":"ef24af90-7e17-4dab-98f5-e7edd2ce20e5","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"phase_changed","at":"2026-02-28T23:39:39.357Z","payload":{"phase":"witness_exam","phaseStartedAt":"2026-02-28T23:39:39.356Z","phaseDurationMs":40000}}
{"id":"3387898a-dc82-44b5-a04c-e53be60d63bd","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"turn","at":"2026-02-28T23:39:39.962Z","payload":{"turn":{"id":"c26bc207-2844-4946-bd45-2c96d46e384a","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","turnNumber":3,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:39:39.958Z"}}}
{"id":"169cee13-4102-415d-9e7d-b43e2bef0945","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"render_directive","at":"2026-02-28T23:39:39.962Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"c26bc207-2844-4946-bd45-2c96d46e384a","phase":"witness_exam","emittedAt":"2026-02-28T23:39:39.962Z"}}
{"id":"51374e84-0eec-405a-b90e-aae643939cd9","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"token_budget_applied","at":"2026-02-28T23:39:39.962Z","payload":{"turnId":"c26bc207-2844-4946-bd45-2c96d46e384a","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"6a74354b-c65b-4c54-b251-f07141bb9e3e","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"session_token_estimate","at":"2026-02-28T23:39:39.962Z","payload":{"turnId":"c26bc207-2844-4946-bd45-2c96d46e384a","role":"judge","phase":"witness_exam","estimatedPromptTokens":471,"estimatedCompletionTokens":64,"cumulativeEstimatedTokens":535,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00107}}
{"id":"fd37933e-8816-4ee2-883b-65caf2a428c1","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"turn","at":"2026-02-28T23:39:40.566Z","payload":{"turn":{"id":"7c6451e9-a2cb-489c-ba95-77afd6c2bb7c","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","turnNumber":4,"speaker":"thaum","role":"witness_1","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:39:40.564Z"}}}
{"id":"7c906b11-2280-41f7-ac50-7725c5ca2038","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"render_directive","at":"2026-02-28T23:39:40.567Z","payload":{"directive":{"camera":"witness","poses":{"witness_1":"talk"}},"turnId":"7c6451e9-a2cb-489c-ba95-77afd6c2bb7c","phase":"witness_exam","emittedAt":"2026-02-28T23:39:40.567Z"}}
{"id":"17d38b75-3db5-4f31-af16-f804ad1ab00c","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"witness_statement","at":"2026-02-28T23:39:40.567Z","payload":{"statement":{"witnessRole":"witness_1","agentId":"thaum","statementText":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","issuedAt":"2026-02-28T23:39:40.567Z"},"phase":"witness_exam","emittedAt":"2026-02-28T23:39:40.567Z"}}
{"id":"8c55d2c0-890d-4076-85b8-07d28524567e","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"token_budget_applied","at":"2026-02-28T23:39:40.567Z","payload":{"turnId":"7c6451e9-a2cb-489c-ba95-77afd6c2bb7c","speaker":"thaum","role":"witness_1","phase":"witness_exam","requestedMaxTokens":90,"appliedMaxTokens":90,"roleMaxTokens":160,"source":"requested"}}
{"id":"899f226b-ad63-4ab8-a6e8-be587de6c3a5","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"session_token_estimate","at":"2026-02-28T23:39:40.567Z","payload":{"turnId":"7c6451e9-a2cb-489c-ba95-77afd6c2bb7c","role":"witness_1","phase":"witness_exam","estimatedPromptTokens":672,"estimatedCompletionTokens":84,"cumulativeEstimatedTokens":756,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001512}}
{"id":"fbd327b4-c218-42d2-922f-c83c4b266709","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"turn","at":"2026-02-28T23:39:41.171Z","payload":{"turn":{"id":"49c87575-06bf-43f4-b84e-5c48367e5841","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","turnNumber":5,"speaker":"subrosa","role":"prosecutor","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:39:41.168Z"}}}
{"id":"473150b5-90df-4e4b-beb5-bdd8a0e7eaaf","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"render_directive","at":"2026-02-28T23:39:41.172Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"49c87575-06bf-43f4-b84e-5c48367e5841","phase":"witness_exam","emittedAt":"2026-02-28T23:39:41.172Z"}}
{"id":"c5e45c5d-fc16-4e21-ba9a-db6becf1bed0","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"token_budget_applied","at":"2026-02-28T23:39:41.172Z","payload":{"turnId":"49c87575-06bf-43f4-b84e-5c48367e5841","speaker":"subrosa","role":"prosecutor","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"42fa9c9c-8b3d-4a8e-a010-200c7e9a8e6b","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"session_token_estimate","at":"2026-02-28T23:39:41.172Z","payload":{"turnId":"49c87575-06bf-43f4-b84e-5c48367e5841","role":"prosecutor","phase":"witness_exam","estimatedPromptTokens":893,"estimatedCompletionTokens":104,"cumulativeEstimatedTokens":997,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001994}}
{"id":"fc8b5ad3-3935-459d-832c-25ea65c9ad41","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"turn","at":"2026-02-28T23:39:41.776Z","payload":{"turn":{"id":"961f3030-87ba-4d41-82e4-e6247a20a495","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","turnNumber":6,"speaker":"chora","role":"defense","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:39:41.773Z"}}}
{"id":"6b1017f6-d7a0-46e7-8fbc-16e4993aafd9","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"render_directive","at":"2026-02-28T23:39:41.776Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"961f3030-87ba-4d41-82e4-e6247a20a495","phase":"witness_exam","emittedAt":"2026-02-28T23:39:41.776Z"}}
{"id":"474c3560-d2cf-47d7-9ff3-456d7d85d810","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"token_budget_applied","at":"2026-02-28T23:39:41.777Z","payload":{"turnId":"961f3030-87ba-4d41-82e4-e6247a20a495","speaker":"chora","role":"defense","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"51871727-d6a7-4d0d-ad40-550a127f5b68","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"session_token_estimate","at":"2026-02-28T23:39:41.777Z","payload":{"turnId":"961f3030-87ba-4d41-82e4-e6247a20a495","role":"defense","phase":"witness_exam","estimatedPromptTokens":1137,"estimatedCompletionTokens":124,"cumulativeEstimatedTokens":1261,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.002522}}
{"id":"eaf017b6-c346-4aba-b8b2-e1476591c0f6","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"turn","at":"2026-02-28T23:39:42.580Z","payload":{"turn":{"id":"00a287ee-248f-4c4a-9e9a-a5e26954a498","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","turnNumber":7,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:39:42.578Z"}}}
{"id":"e98ac7a6-ff76-497c-b088-7fa2f7132ff9","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"render_directive","at":"2026-02-28T23:39:42.580Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"00a287ee-248f-4c4a-9e9a-a5e26954a498","phase":"witness_exam","emittedAt":"2026-02-28T23:39:42.580Z"}}
{"id":"0d2901ef-b677-468c-9629-e2dcfc297494","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"token_budget_applied","at":"2026-02-28T23:39:42.580Z","payload":{"turnId":"00a287ee-248f-4c4a-9e9a-a5e26954a498","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"497d1f3b-00ca-4c68-b1f1-05dc23b42b33","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"session_token_estimate","at":"2026-02-28T23:39:42.580Z","payload":{"turnId":"00a287ee-248f-4c4a-9e9a-a5e26954a498","role":"judge","phase":"witness_exam","estimatedPromptTokens":1406,"estimatedCompletionTokens":144,"cumulativeEstimatedTokens":1550,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.0031}}
{"id":"15124955-4d5a-4215-abe2-a9054a334ec7","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"turn","at":"2026-02-28T23:39:43.184Z","payload":{"turn":{"id":"d0741b03-26d4-4b07-942e-0e45d76ef648","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","turnNumber":8,"speaker":"praxis","role":"witness_2","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:39:43.181Z"}}}
{"id":"a73eaebf-0ab0-4dce-9840-37cfaa0cf6db","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"render_directive","at":"2026-02-28T23:39:43.184Z","payload":{"directive":{"camera":"witness","poses":{"witness_2":"talk"}},"turnId":"d0741b03-26d4-4b07-942e-0e45d76ef648","phase":"witness_exam","emittedAt":"2026-02-28T23:39:43.184Z"}}
{"id":"24113243-6905-4ec5-a84e-f0218afae41b","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"witness_statement","at":"2026-02-28T23:39:43.184Z","payload":{"statement":{"witnessRole":"witness_2","agentId":"praxis","statementText":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","issuedAt":"2026-02-28T23:39:43.184Z"},"phase":"witness_exam","emittedAt":"2026-02-28T23:39:43.184Z"}}
{"id":"aceb2fdc-c115-4d7f-bcca-8746b7b2559b","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"token_budget_applied","at":"2026-02-28T23:39:43.184Z","payload":{"turnId":"d0741b03-26d4-4b07-942e-0e45d76ef648","speaker":"praxis","role":"witness_2","phase":"witness_exam","requestedMaxTokens":90,"appliedMaxTokens":90,"roleMaxTokens":160,"source":"requested"}}
{"id":"a56aaca5-444b-4c23-aee7-5e77a6a6ad9e","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"session_token_estimate","at":"2026-02-28T23:39:43.184Z","payload":{"turnId":"d0741b03-26d4-4b07-942e-0e45d76ef648","role":"witness_2","phase":"witness_exam","estimatedPromptTokens":1695,"estimatedCompletionTokens":164,"cumulativeEstimatedTokens":1859,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.003718}}
{"id":"4a7ae140-677e-47d9-bfb2-29b6fb8deb73","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"turn","at":"2026-02-28T23:39:43.788Z","payload":{"turn":{"id":"5131972a-3999-4ebf-a9c9-b97f48951990","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","turnNumber":9,"speaker":"subrosa","role":"prosecutor","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:39:43.785Z"}}}
{"id":"8a9655d3-6491-4a57-b52e-332ce78cf24d","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"render_directive","at":"2026-02-28T23:39:43.788Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"5131972a-3999-4ebf-a9c9-b97f48951990","phase":"witness_exam","emittedAt":"2026-02-28T23:39:43.788Z"}}
{"id":"a51ca69f-c814-4e8e-9a7e-6428fac84802","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"token_budget_applied","at":"2026-02-28T23:39:43.789Z","payload":{"turnId":"5131972a-3999-4ebf-a9c9-b97f48951990","speaker":"subrosa","role":"prosecutor","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"8a5cb7a9-fea1-4b21-ad96-3da241acfada","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"session_token_estimate","at":"2026-02-28T23:39:43.789Z","payload":{"turnId":"5131972a-3999-4ebf-a9c9-b97f48951990","role":"prosecutor","phase":"witness_exam","estimatedPromptTokens":2004,"estimatedCompletionTokens":184,"cumulativeEstimatedTokens":2188,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.004376}}
{"id":"37123f65-f8af-4876-ad02-3db7add6bfd1","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"turn","at":"2026-02-28T23:39:44.393Z","payload":{"turn":{"id":"75235196-9c39-4e59-8d99-08265f1a0c1c","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","turnNumber":10,"speaker":"chora","role":"defense","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:39:44.390Z"}}}
{"id":"e1fc0ad1-832a-40ff-90bb-e06e9ad94960","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"render_directive","at":"2026-02-28T23:39:44.393Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"75235196-9c39-4e59-8d99-08265f1a0c1c","phase":"witness_exam","emittedAt":"2026-02-28T23:39:44.393Z"}}
{"id":"90a4c68e-f861-48a1-b5a9-b44fcfe4f9f5","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"token_budget_applied","at":"2026-02-28T23:39:44.393Z","payload":{"turnId":"75235196-9c39-4e59-8d99-08265f1a0c1c","speaker":"chora","role":"defense","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"46afdf11-b879-471b-b572-4248b2bcd411","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"session_token_estimate","at":"2026-02-28T23:39:44.393Z","payload":{"turnId":"75235196-9c39-4e59-8d99-08265f1a0c1c","role":"defense","phase":"witness_exam","estimatedPromptTokens":2312,"estimatedCompletionTokens":204,"cumulativeEstimatedTokens":2516,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.005032}}
{"id":"b4f7462f-6a2e-4f98-a3b1-a6f751f57895","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"turn","at":"2026-02-28T23:39:44.998Z","payload":{"turn":{"id":"8e633c92-f709-4dca-921b-6d129c5d9322","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","turnNumber":11,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"Recap: Order in the court. I acknowledge the point and move us to the next absurdly important matter.","createdAt":"2026-02-28T23:39:44.995Z"}}}
{"id":"2e995be7-c1ea-4604-9a84-9b65b5d257d6","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"render_directive","at":"2026-02-28T23:39:44.999Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"8e633c92-f709-4dca-921b-6d129c5d9322","phase":"witness_exam","emittedAt":"2026-02-28T23:39:44.999Z"}}
{"id":"2eb05827-3a8f-4d1d-913d-682aa4751839","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"token_budget_applied","at":"2026-02-28T23:39:44.999Z","payload":{"turnId":"8e633c92-f709-4dca-921b-6d129c5d9322","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"7b15b666-a985-4cfc-9f68-6f77b4defe10","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"session_token_estimate","at":"2026-02-28T23:39:44.999Z","payload":{"turnId":"8e633c92-f709-4dca-921b-6d129c5d9322","role":"judge","phase":"witness_exam","estimatedPromptTokens":2625,"estimatedCompletionTokens":222,"cumulativeEstimatedTokens":2847,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.005694}}
{"id":"77fd234f-7fc7-4e99-bc72-3553ad84fec0","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"judge_recap_emitted","at":"2026-02-28T23:39:45.001Z","payload":{"turnId":"8e633c92-f709-4dca-921b-6d129c5d9322","phase":"witness_exam","cycleNumber":2}}
{"id":"3c67b5f5-1de0-4c32-a5be-aef46c190555","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"phase_changed","at":"2026-02-28T23:39:45.807Z","payload":{"phase":"closings","phaseStartedAt":"2026-02-28T23:39:45.803Z","phaseDurationMs":30000}}
{"id":"4476297c-557f-4543-afe8-9f430a901d6a","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"turn","at":"2026-02-28T23:39:45.809Z","payload":{"turn":{"id":"29ce02b9-77a0-488c-85c7-a3c939d36c84","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","turnNumber":12,"speaker":"subrosa","role":"prosecutor","phase":"closings","dialogue":"At the end of the day, this is either a crime or a spectacular misunderstanding involving glitter and plausible deniability.","createdAt":"2026-02-28T23:39:45.807Z"}}}
{"id":"da69b7dd-f01a-44af-8a2b-92207d7a5945","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"render_directive","at":"2026-02-28T23:39:45.809Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"29ce02b9-77a0-488c-85c7-a3c939d36c84","phase":"closings","emittedAt":"2026-02-28T23:39:45.809Z"}}
{"id":"7a64797e-bdfb-4e21-ab9d-22c8295bdc95","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"token_budget_applied","at":"2026-02-28T23:39:45.809Z","payload":{"turnId":"29ce02b9-77a0-488c-85c7-a3c939d36c84","speaker":"subrosa","role":"prosecutor","phase":"closings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"a4a35520-9ab1-4817-864e-b863a16ed0e3","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"session_token_estimate","at":"2026-02-28T23:39:45.809Z","payload":{"turnId":"29ce02b9-77a0-488c-85c7-a3c939d36c84","role":"prosecutor","phase":"closings","estimatedPromptTokens":2931,"estimatedCompletionTokens":242,"cumulativeEstimatedTokens":3173,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.006346}}
{"id":"15a005d2-caca-4ffe-85cb-46d39fc905b2","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"turn","at":"2026-02-28T23:39:46.611Z","payload":{"turn":{"id":"b52b3b3f-9cec-4f8c-ab25-d91c65098d43","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","turnNumber":13,"speaker":"chora","role":"defense","phase":"closings","dialogue":"At the end of the day, this is either a crime or a spectacular misunderstanding involving glitter and plausible deniability.","createdAt":"2026-02-28T23:39:46.610Z"}}}
{"id":"c52d0b98-5002-4f1c-9b7b-25ec613c13ce","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"render_directive","at":"2026-02-28T23:39:46.611Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"b52b3b3f-9cec-4f8c-ab25-d91c65098d43","phase":"closings","emittedAt":"2026-02-28T23:39:46.611Z"}}
{"id":"bf8e0129-3084-49c1-85ef-6cf223e357a9","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"token_budget_applied","at":"2026-02-28T23:39:46.611Z","payload":{"turnId":"b52b3b3f-9cec-4f8c-ab25-d91c65098d43","speaker":"chora","role":"defense","phase":"closings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"790a840d-a7dc-4dc8-aa9f-676265601020","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"session_token_estimate","at":"2026-02-28T23:39:46.611Z","payload":{"turnId":"b52b3b3f-9cec-4f8c-ab25-d91c65098d43","role":"defense","phase":"closings","estimatedPromptTokens":3232,"estimatedCompletionTokens":262,"cumulativeEstimatedTokens":3494,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.006988}}
{"id":"3dfb3f1a-ea75-413c-8cad-98c41b1a9146","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"phase_changed","at":"2026-02-28T23:39:46.615Z","payload":{"phase":"verdict_vote","phaseStartedAt":"2026-02-28T23:39:46.613Z","phaseDurationMs":20000}}
{"id":"0b289ece-1126-428b-ada6-105a289e0d2d","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"analytics_event","at":"2026-02-28T23:39:46.615Z","payload":{"name":"poll_started","pollType":"verdict","phase":"verdict_vote"}}
{"id":"a96e8843-ff84-4e82-a7eb-64d036fa2ad2","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"broadcast_hook_triggered","at":"2026-02-28T23:39:46.616Z","payload":{"phase":"verdict_vote","hookType":"scene_switch","triggeredAt":"2026-02-28T23:39:46.616Z"}}
{"id":"a03fbb9f-d728-4da5-ac11-b856a2e423fb","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"turn","at":"2026-02-28T23:39:46.618Z","payload":{"turn":{"id":"49cafd53-7648-4c49-84f8-232fed2dd8a6","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","turnNumber":14,"speaker":"mux","role":"bailiff","phase":"verdict_vote","dialogue":"Jury poll is open: liable / not_liable. Cast your votes now.","createdAt":"2026-02-28T23:39:46.616Z"}}}
{"id":"f9eb726c-4420-4ce6-9fee-cca8758dbdae","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"phase_changed","at":"2026-02-28T23:40:06.625Z","payload":{"phase":"sentence_vote","phaseStartedAt":"2026-02-28T23:40:06.620Z","phaseDurationMs":20000}}
{"id":"1a164ab0-ccf3-46ae-8550-e5fbe22a21f4","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"vote_closed","at":"2026-02-28T23:40:06.625Z","payload":{"pollType":"verdict","closedAt":"2026-02-28T23:40:06.620Z","votes":{},"nextPhase":"sentence_vote"}}
{"id":"dd4483cc-b604-4979-9402-01f83ac81a21","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"analytics_event","at":"2026-02-28T23:40:06.625Z","payload":{"name":"poll_closed","pollType":"verdict","phase":"sentence_vote"}}
{"id":"c4128c11-b9ec-4cc9-a243-f0de1f13c8f9","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"analytics_event","at":"2026-02-28T23:40:06.625Z","payload":{"name":"poll_started","pollType":"sentence","phase":"sentence_vote"}}
{"id":"74b5d1f4-a291-484f-b7eb-72cccf04c1da","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"broadcast_hook_triggered","at":"2026-02-28T23:40:06.625Z","payload":{"phase":"sentence_vote","hookType":"scene_switch","triggeredAt":"2026-02-28T23:40:06.625Z"}}
{"id":"3d6f7c10-9f31-4a2f-a001-0f2134510f7d","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"turn","at":"2026-02-28T23:40:06.628Z","payload":{"turn":{"id":"b2396a70-a1d7-4440-876a-f9adb37c0a9d","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","turnNumber":15,"speaker":"mux","role":"bailiff","phase":"sentence_vote","dialogue":"Sentence poll is now open. Options: Community service in the meme archives | Banished to the shadow realm | Mandatory apology haikus | Ethics training hosted by a raccoon | Ukulele ankle-monitor probation","createdAt":"2026-02-28T23:40:06.626Z"}}}
{"id":"3661fbda-3e07-413a-8c63-859b5f806d79","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"phase_changed","at":"2026-02-28T23:40:26.634Z","payload":{"phase":"final_ruling","phaseStartedAt":"2026-02-28T23:40:26.629Z","phaseDurationMs":20000}}
{"id":"94cd6c70-170b-4b86-9d38-bcf73824ce2c","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"vote_closed","at":"2026-02-28T23:40:26.634Z","payload":{"pollType":"sentence","closedAt":"2026-02-28T23:40:26.629Z","votes":{},"nextPhase":"final_ruling"}}
{"id":"843c8b88-5004-4621-be69-f037c8dca744","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"analytics_event","at":"2026-02-28T23:40:26.634Z","payload":{"name":"poll_closed","pollType":"sentence","phase":"final_ruling"}}
{"id":"faf26c2a-6ced-4566-9c3a-a6e9f42669e8","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"turn","at":"2026-02-28T23:40:26.642Z","payload":{"turn":{"id":"b5c137a4-64e6-447a-a092-ffffe38c8f0d","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","turnNumber":16,"speaker":"primus","role":"judge","phase":"final_ruling","dialogue":"On the charge of chaos in the first degree, this court finds the defendant dramatically guilty—with style points.","createdAt":"2026-02-28T23:40:26.639Z"}}}
{"id":"625fd155-d3b4-45a4-b8c3-a8d137165d15","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"render_directive","at":"2026-02-28T23:40:26.642Z","payload":{"directive":{"camera":"verdict","poses":{"judge":"talk"}},"turnId":"b5c137a4-64e6-447a-a092-ffffe38c8f0d","phase":"final_ruling","emittedAt":"2026-02-28T23:40:26.642Z"}}
{"id":"656279a6-dc14-4046-8557-b7f838ae48e6","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"token_budget_applied","at":"2026-02-28T23:40:26.642Z","payload":{"turnId":"b5c137a4-64e6-447a-a092-ffffe38c8f0d","speaker":"primus","role":"judge","phase":"final_ruling","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"4bc55695-3713-4eec-80ce-771051a7ae7e","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"session_token_estimate","at":"2026-02-28T23:40:26.642Z","payload":{"turnId":"b5c137a4-64e6-447a-a092-ffffe38c8f0d","role":"judge","phase":"final_ruling","estimatedPromptTokens":3551,"estimatedCompletionTokens":280,"cumulativeEstimatedTokens":3831,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.007662}}
{"id":"81993b2a-0173-4608-844e-605353dd80f4","sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","type":"session_completed","at":"2026-02-28T23:40:26.649Z","payload":{"sessionId":"05192586-b4e6-4bc9-8172-b2dce2bf57f1","completedAt":"2026-02-28T23:40:26.642Z"}}

View File

@@ -0,0 +1,82 @@
{"id":"9d8095d2-2dd0-4fe2-8881-7f00192bd9a1","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"session_created","at":"2026-02-28T23:42:43.413Z","payload":{"sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d"}}
{"id":"c95996c3-2203-4bb0-aa54-23834e410bd9","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"session_started","at":"2026-02-28T23:42:43.415Z","payload":{"sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","startedAt":"2026-02-28T23:42:43.414Z"}}
{"id":"95513044-2bff-4f74-8c09-0101ae3429ee","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"case_file_generated","at":"2026-02-28T23:42:43.415Z","payload":{"caseFile":{"title":"is the defendant guilty of freely farting on an airplane?","genre":"cosmic_crime","caseType":"criminal","synopsis":"is the defendant guilty of freely farting on an airplane?","charges":["As stated in case prompt"],"witnesses":[],"evidence":[],"sentenceOptions":["Community service in the meme archives","Banished to the shadow realm","Mandatory apology haikus","Ethics training hosted by a raccoon","Ukulele ankle-monitor probation"]},"sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","generatedAt":"2026-02-28T23:42:43.415Z"}}
{"id":"ffc7ce9f-b63d-4380-a112-7dd7ae32a91b","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"phase_changed","at":"2026-02-28T23:42:43.417Z","payload":{"phase":"case_prompt","phaseStartedAt":"2026-02-28T23:42:43.415Z","phaseDurationMs":8000}}
{"id":"1ee0438a-4aa2-45e8-b457-4f7e8ca6f0d0","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"broadcast_hook_triggered","at":"2026-02-28T23:42:43.417Z","payload":{"phase":"case_prompt","hookType":"phase_stinger","triggeredAt":"2026-02-28T23:42:43.417Z"}}
{"id":"136d0fe2-4fc4-49f8-98c7-27b0dcdf17fd","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"turn","at":"2026-02-28T23:42:43.421Z","payload":{"turn":{"id":"0cdc5f2d-9425-4e83-8ef4-c6b7a4e667c7","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","turnNumber":0,"speaker":"mux","role":"bailiff","phase":"case_prompt","dialogue":"All rise. The JuryRigged court is now in session. Case: is the defendant guilty of freely farting on an airplane?","createdAt":"2026-02-28T23:42:43.420Z"}}}
{"id":"a8ad96b9-ac93-4340-9c5c-49092dc02676","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"phase_changed","at":"2026-02-28T23:42:44.625Z","payload":{"phase":"openings","phaseStartedAt":"2026-02-28T23:42:44.621Z","phaseDurationMs":30000}}
{"id":"cdaacd1e-9a7b-48ee-9b80-ea364c5908c4","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"turn","at":"2026-02-28T23:42:44.628Z","payload":{"turn":{"id":"2deef3a0-7ffe-44a1-ad83-6463cabab468","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","turnNumber":1,"speaker":"subrosa","role":"prosecutor","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-02-28T23:42:44.626Z"}}}
{"id":"380cc4e2-d271-426e-8206-d3f18e7331ca","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"render_directive","at":"2026-02-28T23:42:44.628Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"2deef3a0-7ffe-44a1-ad83-6463cabab468","phase":"openings","emittedAt":"2026-02-28T23:42:44.628Z"}}
{"id":"2eb12917-62e9-484a-9b05-fb0f52d48eea","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"token_budget_applied","at":"2026-02-28T23:42:44.628Z","payload":{"turnId":"2deef3a0-7ffe-44a1-ad83-6463cabab468","speaker":"subrosa","role":"prosecutor","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"a414ff16-a154-4cb6-b7d5-4f3fe231fefe","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"session_token_estimate","at":"2026-02-28T23:42:44.628Z","payload":{"turnId":"2deef3a0-7ffe-44a1-ad83-6463cabab468","role":"prosecutor","phase":"openings","estimatedPromptTokens":143,"estimatedCompletionTokens":22,"cumulativeEstimatedTokens":165,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00033}}
{"id":"d8dcaeb1-b473-42f2-a6d1-c282462c71c4","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"turn","at":"2026-02-28T23:42:45.530Z","payload":{"turn":{"id":"bb9806e6-c1fb-4f3e-9970-f77530e2288e","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","turnNumber":2,"speaker":"chora","role":"defense","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-02-28T23:42:45.528Z"}}}
{"id":"b98ea29a-5e48-45d0-b9f2-2b8a3abac52e","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"render_directive","at":"2026-02-28T23:42:45.530Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"bb9806e6-c1fb-4f3e-9970-f77530e2288e","phase":"openings","emittedAt":"2026-02-28T23:42:45.530Z"}}
{"id":"3b233e39-4da8-4604-a91e-55d0b69b4424","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"token_budget_applied","at":"2026-02-28T23:42:45.530Z","payload":{"turnId":"bb9806e6-c1fb-4f3e-9970-f77530e2288e","speaker":"chora","role":"defense","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"88e0ab3b-fc3f-4965-b375-a021af27880c","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"session_token_estimate","at":"2026-02-28T23:42:45.530Z","payload":{"turnId":"bb9806e6-c1fb-4f3e-9970-f77530e2288e","role":"defense","phase":"openings","estimatedPromptTokens":307,"estimatedCompletionTokens":44,"cumulativeEstimatedTokens":351,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.000702}}
{"id":"a2183e46-2baf-46fa-b4c3-ce259d4205d3","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"phase_changed","at":"2026-02-28T23:42:45.536Z","payload":{"phase":"witness_exam","phaseStartedAt":"2026-02-28T23:42:45.533Z","phaseDurationMs":40000}}
{"id":"b7a47502-64cf-4449-ab87-3b6f0b1e76f6","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"turn","at":"2026-02-28T23:42:46.140Z","payload":{"turn":{"id":"2982a90b-5dec-4032-8442-7885f104bf53","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","turnNumber":3,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:42:46.136Z"}}}
{"id":"2ba1c0c0-3b23-4372-8ddc-4e67d82088dc","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"render_directive","at":"2026-02-28T23:42:46.140Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"2982a90b-5dec-4032-8442-7885f104bf53","phase":"witness_exam","emittedAt":"2026-02-28T23:42:46.140Z"}}
{"id":"48959c32-cdcd-4c77-aa06-da7f3a0aa54e","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"token_budget_applied","at":"2026-02-28T23:42:46.140Z","payload":{"turnId":"2982a90b-5dec-4032-8442-7885f104bf53","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"6bf1474d-3a61-49d1-b615-5936df9b4f22","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"session_token_estimate","at":"2026-02-28T23:42:46.140Z","payload":{"turnId":"2982a90b-5dec-4032-8442-7885f104bf53","role":"judge","phase":"witness_exam","estimatedPromptTokens":491,"estimatedCompletionTokens":64,"cumulativeEstimatedTokens":555,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00111}}
{"id":"def9302b-579d-4f64-b841-f21a0ec90eb1","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"turn","at":"2026-02-28T23:42:46.744Z","payload":{"turn":{"id":"212962d1-54d0-411c-9e2d-432d6461871b","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","turnNumber":4,"speaker":"thaum","role":"witness_1","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:42:46.740Z"}}}
{"id":"80256226-fec1-42a9-b474-14693370d9e4","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"render_directive","at":"2026-02-28T23:42:46.745Z","payload":{"directive":{"camera":"witness","poses":{"witness_1":"talk"}},"turnId":"212962d1-54d0-411c-9e2d-432d6461871b","phase":"witness_exam","emittedAt":"2026-02-28T23:42:46.745Z"}}
{"id":"1fc030ae-731e-4af5-901e-6a57189976f1","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"witness_statement","at":"2026-02-28T23:42:46.745Z","payload":{"statement":{"witnessRole":"witness_1","agentId":"thaum","statementText":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","issuedAt":"2026-02-28T23:42:46.745Z"},"phase":"witness_exam","emittedAt":"2026-02-28T23:42:46.745Z"}}
{"id":"4cae0dea-89fe-4355-b82a-4e02058cf550","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"token_budget_applied","at":"2026-02-28T23:42:46.745Z","payload":{"turnId":"212962d1-54d0-411c-9e2d-432d6461871b","speaker":"thaum","role":"witness_1","phase":"witness_exam","requestedMaxTokens":90,"appliedMaxTokens":90,"roleMaxTokens":160,"source":"requested"}}
{"id":"35446a35-f272-4fd0-86bf-38d951ef4945","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"session_token_estimate","at":"2026-02-28T23:42:46.745Z","payload":{"turnId":"212962d1-54d0-411c-9e2d-432d6461871b","role":"witness_1","phase":"witness_exam","estimatedPromptTokens":700,"estimatedCompletionTokens":84,"cumulativeEstimatedTokens":784,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001568}}
{"id":"ae977cb6-2cec-4651-9373-c21180114ea8","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"turn","at":"2026-02-28T23:42:47.347Z","payload":{"turn":{"id":"7a60cf3a-0f0f-4c79-9618-bb2a38b355c1","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","turnNumber":5,"speaker":"subrosa","role":"prosecutor","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:42:47.345Z"}}}
{"id":"6a64644b-7811-4e8b-9be3-101c08fe64e5","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"render_directive","at":"2026-02-28T23:42:47.347Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"7a60cf3a-0f0f-4c79-9618-bb2a38b355c1","phase":"witness_exam","emittedAt":"2026-02-28T23:42:47.347Z"}}
{"id":"3003c155-c6c1-4231-82c0-058874a98fe8","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"token_budget_applied","at":"2026-02-28T23:42:47.347Z","payload":{"turnId":"7a60cf3a-0f0f-4c79-9618-bb2a38b355c1","speaker":"subrosa","role":"prosecutor","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"44a007c9-c4cc-4448-b687-79e65a698414","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"session_token_estimate","at":"2026-02-28T23:42:47.347Z","payload":{"turnId":"7a60cf3a-0f0f-4c79-9618-bb2a38b355c1","role":"prosecutor","phase":"witness_exam","estimatedPromptTokens":926,"estimatedCompletionTokens":104,"cumulativeEstimatedTokens":1030,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00206}}
{"id":"f9d81cf0-0c95-4fe8-afc3-0251cfa1afc8","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"turn","at":"2026-02-28T23:42:47.951Z","payload":{"turn":{"id":"9a0b7f8d-4405-4c13-ab46-0dc08d1efd45","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","turnNumber":6,"speaker":"chora","role":"defense","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:42:47.947Z"}}}
{"id":"ebc13754-5223-4060-b11c-bfa1edd7f60e","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"render_directive","at":"2026-02-28T23:42:47.951Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"9a0b7f8d-4405-4c13-ab46-0dc08d1efd45","phase":"witness_exam","emittedAt":"2026-02-28T23:42:47.951Z"}}
{"id":"a5de3157-345b-4a89-b69a-33744474b5c5","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"token_budget_applied","at":"2026-02-28T23:42:47.951Z","payload":{"turnId":"9a0b7f8d-4405-4c13-ab46-0dc08d1efd45","speaker":"chora","role":"defense","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"c3fffed5-cd5b-467e-88ac-3f3e4d71cd62","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"session_token_estimate","at":"2026-02-28T23:42:47.951Z","payload":{"turnId":"9a0b7f8d-4405-4c13-ab46-0dc08d1efd45","role":"defense","phase":"witness_exam","estimatedPromptTokens":1182,"estimatedCompletionTokens":124,"cumulativeEstimatedTokens":1306,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.002612}}
{"id":"84fc2384-959b-40b1-8915-cefc2964303a","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"turn","at":"2026-02-28T23:42:48.755Z","payload":{"turn":{"id":"2b0672c0-2b6b-4a05-9755-3ec10394e601","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","turnNumber":7,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:42:48.751Z"}}}
{"id":"af89ef8d-7758-4a07-b61e-f1ead332741e","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"render_directive","at":"2026-02-28T23:42:48.755Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"2b0672c0-2b6b-4a05-9755-3ec10394e601","phase":"witness_exam","emittedAt":"2026-02-28T23:42:48.755Z"}}
{"id":"a9a8d3e3-f0d1-45fe-b6c2-c6be6d178643","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"token_budget_applied","at":"2026-02-28T23:42:48.755Z","payload":{"turnId":"2b0672c0-2b6b-4a05-9755-3ec10394e601","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"24893982-c1ef-4daa-9ac3-81f6de57f16a","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"session_token_estimate","at":"2026-02-28T23:42:48.755Z","payload":{"turnId":"2b0672c0-2b6b-4a05-9755-3ec10394e601","role":"judge","phase":"witness_exam","estimatedPromptTokens":1454,"estimatedCompletionTokens":144,"cumulativeEstimatedTokens":1598,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.003196}}
{"id":"8d2927f1-af39-46cc-af7b-52514a49cb92","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"turn","at":"2026-02-28T23:42:49.360Z","payload":{"turn":{"id":"2fcd0cef-b588-43ed-973c-7a79d5b27350","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","turnNumber":8,"speaker":"praxis","role":"witness_2","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:42:49.356Z"}}}
{"id":"db398f00-fee8-4758-8435-7c3b4f0c604f","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"render_directive","at":"2026-02-28T23:42:49.360Z","payload":{"directive":{"camera":"witness","poses":{"witness_2":"talk"}},"turnId":"2fcd0cef-b588-43ed-973c-7a79d5b27350","phase":"witness_exam","emittedAt":"2026-02-28T23:42:49.360Z"}}
{"id":"6b187631-b8bf-4b22-9475-d2a0ab4aba98","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"witness_statement","at":"2026-02-28T23:42:49.360Z","payload":{"statement":{"witnessRole":"witness_2","agentId":"praxis","statementText":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","issuedAt":"2026-02-28T23:42:49.360Z"},"phase":"witness_exam","emittedAt":"2026-02-28T23:42:49.360Z"}}
{"id":"8a405a48-cbbd-405d-8011-d1d62400e9e1","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"token_budget_applied","at":"2026-02-28T23:42:49.360Z","payload":{"turnId":"2fcd0cef-b588-43ed-973c-7a79d5b27350","speaker":"praxis","role":"witness_2","phase":"witness_exam","requestedMaxTokens":90,"appliedMaxTokens":90,"roleMaxTokens":160,"source":"requested"}}
{"id":"c10885b9-9d77-41fa-89eb-92267fd54a23","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"session_token_estimate","at":"2026-02-28T23:42:49.360Z","payload":{"turnId":"2fcd0cef-b588-43ed-973c-7a79d5b27350","role":"witness_2","phase":"witness_exam","estimatedPromptTokens":1751,"estimatedCompletionTokens":164,"cumulativeEstimatedTokens":1915,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00383}}
{"id":"e98b9fc8-e931-4773-8603-8771b1f996e5","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"turn","at":"2026-02-28T23:42:49.965Z","payload":{"turn":{"id":"ebb81610-010a-4b1e-9902-3e392c22dc27","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","turnNumber":9,"speaker":"subrosa","role":"prosecutor","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:42:49.961Z"}}}
{"id":"a268d693-320b-430f-97b2-72cae6da539b","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"render_directive","at":"2026-02-28T23:42:49.965Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"ebb81610-010a-4b1e-9902-3e392c22dc27","phase":"witness_exam","emittedAt":"2026-02-28T23:42:49.965Z"}}
{"id":"863e2474-2704-4221-aef2-7b50ff24efbf","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"token_budget_applied","at":"2026-02-28T23:42:49.965Z","payload":{"turnId":"ebb81610-010a-4b1e-9902-3e392c22dc27","speaker":"subrosa","role":"prosecutor","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"fff7e947-f544-41d0-819a-cdedd49eb129","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"session_token_estimate","at":"2026-02-28T23:42:49.965Z","payload":{"turnId":"ebb81610-010a-4b1e-9902-3e392c22dc27","role":"prosecutor","phase":"witness_exam","estimatedPromptTokens":2065,"estimatedCompletionTokens":184,"cumulativeEstimatedTokens":2249,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.004498}}
{"id":"88f58b87-539d-403b-a7b7-69f2204d4ad4","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"turn","at":"2026-02-28T23:42:50.567Z","payload":{"turn":{"id":"94415285-c8f2-4d2e-b511-a5b36ddf27cc","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","turnNumber":10,"speaker":"chora","role":"defense","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:42:50.566Z"}}}
{"id":"eea46c18-33e8-4886-9598-07e01aac7378","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"render_directive","at":"2026-02-28T23:42:50.567Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"94415285-c8f2-4d2e-b511-a5b36ddf27cc","phase":"witness_exam","emittedAt":"2026-02-28T23:42:50.567Z"}}
{"id":"1a85f948-ab1d-4eac-9633-54bc6b2bf961","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"token_budget_applied","at":"2026-02-28T23:42:50.567Z","payload":{"turnId":"94415285-c8f2-4d2e-b511-a5b36ddf27cc","speaker":"chora","role":"defense","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"c2e74159-2e3d-4cfd-9ecc-5767ade8318f","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"session_token_estimate","at":"2026-02-28T23:42:50.567Z","payload":{"turnId":"94415285-c8f2-4d2e-b511-a5b36ddf27cc","role":"defense","phase":"witness_exam","estimatedPromptTokens":2385,"estimatedCompletionTokens":204,"cumulativeEstimatedTokens":2589,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.005178}}
{"id":"f4b0377d-9c4a-4470-846e-5459cf3b9001","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"turn","at":"2026-02-28T23:42:51.173Z","payload":{"turn":{"id":"baf26068-dbf4-4abf-8122-22166e03edbe","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","turnNumber":11,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"Recap: Order in the court. I acknowledge the point and move us to the next absurdly important matter.","createdAt":"2026-02-28T23:42:51.169Z"}}}
{"id":"3139ac0e-c37d-4feb-af47-7df3e679d5b7","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"render_directive","at":"2026-02-28T23:42:51.173Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"baf26068-dbf4-4abf-8122-22166e03edbe","phase":"witness_exam","emittedAt":"2026-02-28T23:42:51.173Z"}}
{"id":"f526e800-2457-41a1-a7f1-09b496c0ec1c","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"token_budget_applied","at":"2026-02-28T23:42:51.173Z","payload":{"turnId":"baf26068-dbf4-4abf-8122-22166e03edbe","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"319e7f15-b3d8-4d87-a310-c4c5797769b6","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"session_token_estimate","at":"2026-02-28T23:42:51.173Z","payload":{"turnId":"baf26068-dbf4-4abf-8122-22166e03edbe","role":"judge","phase":"witness_exam","estimatedPromptTokens":2701,"estimatedCompletionTokens":222,"cumulativeEstimatedTokens":2923,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.005846}}
{"id":"80be7e6b-1cdd-4945-b6cd-7b16299be4f9","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"judge_recap_emitted","at":"2026-02-28T23:42:51.176Z","payload":{"turnId":"baf26068-dbf4-4abf-8122-22166e03edbe","phase":"witness_exam","cycleNumber":2}}
{"id":"193bcfc3-988f-493d-af0e-28e705f4fdd0","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"phase_changed","at":"2026-02-28T23:42:51.981Z","payload":{"phase":"closings","phaseStartedAt":"2026-02-28T23:42:51.978Z","phaseDurationMs":30000}}
{"id":"3c4194d4-842c-4c72-8c1c-55945c3df99d","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"turn","at":"2026-02-28T23:42:51.983Z","payload":{"turn":{"id":"54ca0a5c-57b2-4a38-a1a0-acab6c6232e3","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","turnNumber":12,"speaker":"subrosa","role":"prosecutor","phase":"closings","dialogue":"At the end of the day, this is either a crime or a spectacular misunderstanding involving glitter and plausible deniability.","createdAt":"2026-02-28T23:42:51.982Z"}}}
{"id":"0e4e0d46-2d50-497e-ab8d-a48248dd5816","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"render_directive","at":"2026-02-28T23:42:51.983Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"54ca0a5c-57b2-4a38-a1a0-acab6c6232e3","phase":"closings","emittedAt":"2026-02-28T23:42:51.983Z"}}
{"id":"3a9c5d4a-184c-4bca-96b2-7c1ae9628292","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"token_budget_applied","at":"2026-02-28T23:42:51.983Z","payload":{"turnId":"54ca0a5c-57b2-4a38-a1a0-acab6c6232e3","speaker":"subrosa","role":"prosecutor","phase":"closings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"9fc5cc0e-0a14-4507-9955-d58b09e87f31","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"session_token_estimate","at":"2026-02-28T23:42:51.983Z","payload":{"turnId":"54ca0a5c-57b2-4a38-a1a0-acab6c6232e3","role":"prosecutor","phase":"closings","estimatedPromptTokens":3012,"estimatedCompletionTokens":242,"cumulativeEstimatedTokens":3254,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.006508}}
{"id":"1683bead-34be-479c-a736-23cc8d1809e4","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"turn","at":"2026-02-28T23:42:52.789Z","payload":{"turn":{"id":"8171c855-1c10-4898-8d9e-ebece9427102","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","turnNumber":13,"speaker":"chora","role":"defense","phase":"closings","dialogue":"At the end of the day, this is either a crime or a spectacular misunderstanding involving glitter and plausible deniability.","createdAt":"2026-02-28T23:42:52.785Z"}}}
{"id":"a0ab53c2-e5a2-4bc9-9d63-19dbd956eb3a","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"render_directive","at":"2026-02-28T23:42:52.789Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"8171c855-1c10-4898-8d9e-ebece9427102","phase":"closings","emittedAt":"2026-02-28T23:42:52.789Z"}}
{"id":"76cc23c2-383c-4d74-b8a9-c109ae4a7990","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"token_budget_applied","at":"2026-02-28T23:42:52.789Z","payload":{"turnId":"8171c855-1c10-4898-8d9e-ebece9427102","speaker":"chora","role":"defense","phase":"closings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"72ad09e2-5d93-4110-833c-a698858613eb","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"session_token_estimate","at":"2026-02-28T23:42:52.789Z","payload":{"turnId":"8171c855-1c10-4898-8d9e-ebece9427102","role":"defense","phase":"closings","estimatedPromptTokens":3325,"estimatedCompletionTokens":262,"cumulativeEstimatedTokens":3587,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.007174}}
{"id":"7b8db1d9-8f47-4512-8f99-bafeff3d1f84","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"phase_changed","at":"2026-02-28T23:42:52.793Z","payload":{"phase":"verdict_vote","phaseStartedAt":"2026-02-28T23:42:52.791Z","phaseDurationMs":20000}}
{"id":"60dfeb9a-f4ad-4a1d-a81e-b8c48ec73691","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"analytics_event","at":"2026-02-28T23:42:52.793Z","payload":{"name":"poll_started","pollType":"verdict","phase":"verdict_vote"}}
{"id":"0cdd4682-3d21-4848-9d40-bd3232e06335","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"broadcast_hook_triggered","at":"2026-02-28T23:42:52.793Z","payload":{"phase":"verdict_vote","hookType":"scene_switch","triggeredAt":"2026-02-28T23:42:52.793Z"}}
{"id":"e451107b-79dd-4520-b051-372f83562940","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"turn","at":"2026-02-28T23:42:52.796Z","payload":{"turn":{"id":"1dafd359-2969-4a70-aff4-8ae1dec3526d","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","turnNumber":14,"speaker":"mux","role":"bailiff","phase":"verdict_vote","dialogue":"Jury poll is open: guilty / not_guilty. Cast your votes now.","createdAt":"2026-02-28T23:42:52.793Z"}}}
{"id":"88cb7704-c5cb-43d8-be09-c7b12fa033d2","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"phase_changed","at":"2026-02-28T23:43:12.799Z","payload":{"phase":"sentence_vote","phaseStartedAt":"2026-02-28T23:43:12.797Z","phaseDurationMs":20000}}
{"id":"0bc4d069-cb51-484f-aa7d-8eb9fa55ff4d","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"vote_closed","at":"2026-02-28T23:43:12.799Z","payload":{"pollType":"verdict","closedAt":"2026-02-28T23:43:12.797Z","votes":{},"nextPhase":"sentence_vote"}}
{"id":"8b9d4613-d307-456b-94cf-171d7394255e","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"analytics_event","at":"2026-02-28T23:43:12.799Z","payload":{"name":"poll_closed","pollType":"verdict","phase":"sentence_vote"}}
{"id":"b0da48d2-201c-47b0-acff-106ea9df1e64","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"analytics_event","at":"2026-02-28T23:43:12.799Z","payload":{"name":"poll_started","pollType":"sentence","phase":"sentence_vote"}}
{"id":"08de2105-0792-4f97-bad6-a0da44093e30","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"broadcast_hook_triggered","at":"2026-02-28T23:43:12.799Z","payload":{"phase":"sentence_vote","hookType":"scene_switch","triggeredAt":"2026-02-28T23:43:12.799Z"}}
{"id":"5fc4a054-081a-4985-8f7c-110223acaf19","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"turn","at":"2026-02-28T23:43:12.801Z","payload":{"turn":{"id":"7be2e8da-baac-4c76-a92a-83c501267ba3","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","turnNumber":15,"speaker":"mux","role":"bailiff","phase":"sentence_vote","dialogue":"Sentence poll is now open. Options: Community service in the meme archives | Banished to the shadow realm | Mandatory apology haikus | Ethics training hosted by a raccoon | Ukulele ankle-monitor probation","createdAt":"2026-02-28T23:43:12.800Z"}}}
{"id":"0823ee53-06c5-4b98-bfb5-eaa39c16fca1","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"phase_changed","at":"2026-02-28T23:43:32.808Z","payload":{"phase":"final_ruling","phaseStartedAt":"2026-02-28T23:43:32.803Z","phaseDurationMs":20000}}
{"id":"da41d925-db02-4495-bd8a-1fb327e2c619","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"vote_closed","at":"2026-02-28T23:43:32.809Z","payload":{"pollType":"sentence","closedAt":"2026-02-28T23:43:32.803Z","votes":{},"nextPhase":"final_ruling"}}
{"id":"e3c5016d-87bb-48ec-9dcf-b898267ce207","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"analytics_event","at":"2026-02-28T23:43:32.809Z","payload":{"name":"poll_closed","pollType":"sentence","phase":"final_ruling"}}
{"id":"c18be41e-ec87-4a99-ab66-142503f889d6","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"turn","at":"2026-02-28T23:43:32.816Z","payload":{"turn":{"id":"91ec8a41-e3bc-4800-908d-253414bbae3f","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","turnNumber":16,"speaker":"primus","role":"judge","phase":"final_ruling","dialogue":"On the charge of chaos in the first degree, this court finds the defendant dramatically guilty—with style points.","createdAt":"2026-02-28T23:43:32.813Z"}}}
{"id":"7b16a266-cfd4-40fa-b559-3880d8dbfd4f","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"render_directive","at":"2026-02-28T23:43:32.816Z","payload":{"directive":{"camera":"verdict","poses":{"judge":"talk"}},"turnId":"91ec8a41-e3bc-4800-908d-253414bbae3f","phase":"final_ruling","emittedAt":"2026-02-28T23:43:32.816Z"}}
{"id":"3de01495-1332-47a7-9adb-f5333f141b22","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"token_budget_applied","at":"2026-02-28T23:43:32.816Z","payload":{"turnId":"91ec8a41-e3bc-4800-908d-253414bbae3f","speaker":"primus","role":"judge","phase":"final_ruling","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"46f4451e-fc7d-4b6e-9f95-b6519952b967","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"session_token_estimate","at":"2026-02-28T23:43:32.816Z","payload":{"turnId":"91ec8a41-e3bc-4800-908d-253414bbae3f","role":"judge","phase":"final_ruling","estimatedPromptTokens":3647,"estimatedCompletionTokens":280,"cumulativeEstimatedTokens":3927,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.007854}}
{"id":"0b115801-b892-41c5-8e0f-694d6155fee7","sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","type":"session_completed","at":"2026-02-28T23:43:32.823Z","payload":{"sessionId":"07adf71f-ded3-472e-8c1a-e4d1ff70815d","completedAt":"2026-02-28T23:43:32.816Z"}}

View File

@@ -0,0 +1,36 @@
{"id":"8001247d-5a5b-4fe7-9c7a-1caa035318ab","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"session_created","at":"2026-02-28T23:36:04.152Z","payload":{"sessionId":"38206317-0796-439c-822b-32aa3df18b95"}}
{"id":"65eef678-4561-4d80-ba96-9b1a4f700d4d","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"session_started","at":"2026-02-28T23:36:04.155Z","payload":{"sessionId":"38206317-0796-439c-822b-32aa3df18b95","startedAt":"2026-02-28T23:36:04.153Z"}}
{"id":"4926b34f-f554-4ab3-a0bd-72ffac49633b","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"case_file_generated","at":"2026-02-28T23:36:04.155Z","payload":{"caseFile":{"title":"DB persistence check session","genre":"workplace_tribunal","caseType":"civil","synopsis":"DB persistence check session","charges":["Damages as alleged"],"witnesses":[],"evidence":[],"sentenceOptions":["Community service in the meme archives","Banished to the shadow realm","Mandatory apology haikus","Ethics training hosted by a raccoon","Ukulele ankle-monitor probation"]},"sessionId":"38206317-0796-439c-822b-32aa3df18b95","generatedAt":"2026-02-28T23:36:04.155Z"}}
{"id":"04a7eeac-9adc-480a-8e22-30e64a9441fb","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"phase_changed","at":"2026-02-28T23:36:04.166Z","payload":{"phase":"case_prompt","phaseStartedAt":"2026-02-28T23:36:04.163Z","phaseDurationMs":8000}}
{"id":"c1e78d05-c2f0-4a63-aca6-9a648f1595c2","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"broadcast_hook_triggered","at":"2026-02-28T23:36:04.167Z","payload":{"phase":"case_prompt","hookType":"phase_stinger","triggeredAt":"2026-02-28T23:36:04.167Z"}}
{"id":"4aa2aa9a-a1e2-4eb3-9ef8-16d9bd4ef2d5","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"turn","at":"2026-02-28T23:36:04.169Z","payload":{"turn":{"id":"b9ef855e-2e48-4f30-9c18-67a0fc7cc4a6","sessionId":"38206317-0796-439c-822b-32aa3df18b95","turnNumber":0,"speaker":"mux","role":"bailiff","phase":"case_prompt","dialogue":"All rise. The JuryRigged court is now in session. Case: DB persistence check session","createdAt":"2026-02-28T23:36:04.167Z"}}}
{"id":"ce1234b2-ec04-46ba-8604-2afaa783fc2a","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"phase_changed","at":"2026-02-28T23:36:05.375Z","payload":{"phase":"openings","phaseStartedAt":"2026-02-28T23:36:05.371Z","phaseDurationMs":30000}}
{"id":"0705c46b-61f9-4423-bcaf-7b4a77b65f99","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"turn","at":"2026-02-28T23:36:05.378Z","payload":{"turn":{"id":"7eb10d34-2d08-46b4-aeaf-2fa1fd7a527a","sessionId":"38206317-0796-439c-822b-32aa3df18b95","turnNumber":1,"speaker":"subrosa","role":"prosecutor","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-02-28T23:36:05.376Z"}}}
{"id":"1bddae68-cfd9-4c9c-9b6d-1b7f004c173b","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"render_directive","at":"2026-02-28T23:36:05.379Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"7eb10d34-2d08-46b4-aeaf-2fa1fd7a527a","phase":"openings","emittedAt":"2026-02-28T23:36:05.379Z"}}
{"id":"a4cd9be8-400f-4343-a4ec-26a070e48b85","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"token_budget_applied","at":"2026-02-28T23:36:05.379Z","payload":{"turnId":"7eb10d34-2d08-46b4-aeaf-2fa1fd7a527a","speaker":"subrosa","role":"prosecutor","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"adf0a983-f6de-4f61-b23b-d6b8d1f6b1fd","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"session_token_estimate","at":"2026-02-28T23:36:05.379Z","payload":{"turnId":"7eb10d34-2d08-46b4-aeaf-2fa1fd7a527a","role":"prosecutor","phase":"openings","estimatedPromptTokens":135,"estimatedCompletionTokens":22,"cumulativeEstimatedTokens":157,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.000314}}
{"id":"23974011-0778-4bbb-869f-5aa4bb78b40d","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"turn","at":"2026-02-28T23:36:06.284Z","payload":{"turn":{"id":"87ad3e4f-bad5-4653-97ca-70e62581164a","sessionId":"38206317-0796-439c-822b-32aa3df18b95","turnNumber":2,"speaker":"chora","role":"defense","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-02-28T23:36:06.280Z"}}}
{"id":"284ef127-d8be-4f67-9f26-b31db58687eb","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"render_directive","at":"2026-02-28T23:36:06.284Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"87ad3e4f-bad5-4653-97ca-70e62581164a","phase":"openings","emittedAt":"2026-02-28T23:36:06.284Z"}}
{"id":"3fc9c152-9ba7-4065-9e2b-4983cb1fae49","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"token_budget_applied","at":"2026-02-28T23:36:06.284Z","payload":{"turnId":"87ad3e4f-bad5-4653-97ca-70e62581164a","speaker":"chora","role":"defense","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"ea4fd6a1-2fdc-43a3-ac5a-2246a363bd5b","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"session_token_estimate","at":"2026-02-28T23:36:06.284Z","payload":{"turnId":"87ad3e4f-bad5-4653-97ca-70e62581164a","role":"defense","phase":"openings","estimatedPromptTokens":287,"estimatedCompletionTokens":44,"cumulativeEstimatedTokens":331,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.000662}}
{"id":"f3ec808d-03fe-40a5-b048-46598ee4fa4e","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"phase_changed","at":"2026-02-28T23:36:06.288Z","payload":{"phase":"witness_exam","phaseStartedAt":"2026-02-28T23:36:06.286Z","phaseDurationMs":40000}}
{"id":"d9962438-fa9f-478b-b4b0-94f41b501605","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"turn","at":"2026-02-28T23:36:06.893Z","payload":{"turn":{"id":"064dd996-631c-48aa-981f-2f56bc0785a8","sessionId":"38206317-0796-439c-822b-32aa3df18b95","turnNumber":3,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:36:06.890Z"}}}
{"id":"c83671d4-b80a-4629-9630-cfcaba51ee39","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"render_directive","at":"2026-02-28T23:36:06.893Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"064dd996-631c-48aa-981f-2f56bc0785a8","phase":"witness_exam","emittedAt":"2026-02-28T23:36:06.893Z"}}
{"id":"e08e08ff-c67c-47f6-b385-af83cd90ed27","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"token_budget_applied","at":"2026-02-28T23:36:06.893Z","payload":{"turnId":"064dd996-631c-48aa-981f-2f56bc0785a8","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"64b9d130-5ee0-4962-bb8d-aab88db0476f","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"session_token_estimate","at":"2026-02-28T23:36:06.893Z","payload":{"turnId":"064dd996-631c-48aa-981f-2f56bc0785a8","role":"judge","phase":"witness_exam","estimatedPromptTokens":467,"estimatedCompletionTokens":64,"cumulativeEstimatedTokens":531,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001062}}
{"id":"081ec06a-eee8-4c3a-aa00-a67258e32069","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"turn","at":"2026-02-28T23:36:07.496Z","payload":{"turn":{"id":"5d59252d-456e-41ca-84fe-b3f37d80c8da","sessionId":"38206317-0796-439c-822b-32aa3df18b95","turnNumber":4,"speaker":"thaum","role":"witness_1","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:36:07.494Z"}}}
{"id":"e8377cc6-1f60-4fe8-8e02-b4c480550974","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"render_directive","at":"2026-02-28T23:36:07.496Z","payload":{"directive":{"camera":"witness","poses":{"witness_1":"talk"}},"turnId":"5d59252d-456e-41ca-84fe-b3f37d80c8da","phase":"witness_exam","emittedAt":"2026-02-28T23:36:07.496Z"}}
{"id":"b04710e6-ded2-4fa2-9b3a-93612ffacbe7","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"witness_statement","at":"2026-02-28T23:36:07.496Z","payload":{"statement":{"witnessRole":"witness_1","agentId":"thaum","statementText":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","issuedAt":"2026-02-28T23:36:07.496Z"},"phase":"witness_exam","emittedAt":"2026-02-28T23:36:07.496Z"}}
{"id":"e3b02e03-38b9-45ea-b331-dc85b3c7059f","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"token_budget_applied","at":"2026-02-28T23:36:07.496Z","payload":{"turnId":"5d59252d-456e-41ca-84fe-b3f37d80c8da","speaker":"thaum","role":"witness_1","phase":"witness_exam","requestedMaxTokens":90,"appliedMaxTokens":90,"roleMaxTokens":160,"source":"requested"}}
{"id":"1b56a6a4-a7cc-4b08-b2d1-a1e52321179e","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"session_token_estimate","at":"2026-02-28T23:36:07.496Z","payload":{"turnId":"5d59252d-456e-41ca-84fe-b3f37d80c8da","role":"witness_1","phase":"witness_exam","estimatedPromptTokens":670,"estimatedCompletionTokens":84,"cumulativeEstimatedTokens":754,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001508}}
{"id":"325bf84d-f291-4676-821a-f1905d019ad5","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"turn","at":"2026-02-28T23:36:08.101Z","payload":{"turn":{"id":"83da2c15-163c-4e2f-87db-e725c2ae6026","sessionId":"38206317-0796-439c-822b-32aa3df18b95","turnNumber":5,"speaker":"subrosa","role":"prosecutor","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:36:08.097Z"}}}
{"id":"0800667e-a29b-4395-90e5-2aa7d60810fd","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"render_directive","at":"2026-02-28T23:36:08.101Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"83da2c15-163c-4e2f-87db-e725c2ae6026","phase":"witness_exam","emittedAt":"2026-02-28T23:36:08.101Z"}}
{"id":"a61d62fd-1ca4-4ac8-8e70-c68217c79a20","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"token_budget_applied","at":"2026-02-28T23:36:08.101Z","payload":{"turnId":"83da2c15-163c-4e2f-87db-e725c2ae6026","speaker":"subrosa","role":"prosecutor","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"748b09d7-837f-4714-b9ff-8368a859a570","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"session_token_estimate","at":"2026-02-28T23:36:08.101Z","payload":{"turnId":"83da2c15-163c-4e2f-87db-e725c2ae6026","role":"prosecutor","phase":"witness_exam","estimatedPromptTokens":888,"estimatedCompletionTokens":104,"cumulativeEstimatedTokens":992,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001984}}
{"id":"aa40f534-c9e4-442a-bab8-a228bd3f4996","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"turn","at":"2026-02-28T23:36:08.705Z","payload":{"turn":{"id":"6db6d557-3278-442d-944a-adfcf8b9d92a","sessionId":"38206317-0796-439c-822b-32aa3df18b95","turnNumber":6,"speaker":"chora","role":"defense","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:36:08.702Z"}}}
{"id":"bedeeffd-44f8-42da-8ccf-acbf382b75de","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"render_directive","at":"2026-02-28T23:36:08.706Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"6db6d557-3278-442d-944a-adfcf8b9d92a","phase":"witness_exam","emittedAt":"2026-02-28T23:36:08.706Z"}}
{"id":"35144bbd-332a-4037-9f09-f0123b5dd127","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"token_budget_applied","at":"2026-02-28T23:36:08.706Z","payload":{"turnId":"6db6d557-3278-442d-944a-adfcf8b9d92a","speaker":"chora","role":"defense","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"aa8d99bf-9dd0-4329-a740-45d5ca4ac73a","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"session_token_estimate","at":"2026-02-28T23:36:08.706Z","payload":{"turnId":"6db6d557-3278-442d-944a-adfcf8b9d92a","role":"defense","phase":"witness_exam","estimatedPromptTokens":1132,"estimatedCompletionTokens":124,"cumulativeEstimatedTokens":1256,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.002512}}
{"id":"3f1e7073-e61c-4e6c-a3d9-9695580c8e5f","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"session_started","at":"2026-02-28T23:36:15.934Z","payload":{"sessionId":"38206317-0796-439c-822b-32aa3df18b95","startedAt":"2026-02-28T23:36:04.153Z"}}
{"id":"1f839910-e9fd-4888-ae60-ffc2b6e4280a","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"case_file_generated","at":"2026-02-28T23:36:15.934Z","payload":{"caseFile":{"title":"DB persistence check session","genre":"workplace_tribunal","caseType":"civil","synopsis":"DB persistence check session","charges":["Damages as alleged"],"witnesses":[],"evidence":[],"sentenceOptions":["Community service in the meme archives","Banished to the shadow realm","Mandatory apology haikus","Ethics training hosted by a raccoon","Ukulele ankle-monitor probation"]},"sessionId":"38206317-0796-439c-822b-32aa3df18b95","generatedAt":"2026-02-28T23:36:15.934Z"}}
{"id":"7817ec67-64ef-4dc1-8b54-b29f28393c9d","sessionId":"38206317-0796-439c-822b-32aa3df18b95","type":"session_failed","at":"2026-02-28T23:36:15.943Z","payload":{"sessionId":"38206317-0796-439c-822b-32aa3df18b95","reason":"Invalid phase transition: witness_exam -> case_prompt","completedAt":"2026-02-28T23:36:15.940Z"}}

View File

@@ -0,0 +1,82 @@
{"id":"b3d0fc7d-eace-4abd-ac91-2cefd058f634","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"session_created","at":"2026-02-28T23:47:38.800Z","payload":{"sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7"}}
{"id":"81eb74d4-c185-4e09-86cb-83274856ae47","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"session_started","at":"2026-02-28T23:47:38.803Z","payload":{"sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","startedAt":"2026-02-28T23:47:38.801Z"}}
{"id":"256fae22-25c1-46b2-9061-7f6dedad2c91","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"case_file_generated","at":"2026-02-28T23:47:38.803Z","payload":{"caseFile":{"title":"is the defendant guilty of freely farting on an airplane?","genre":"fantasy_court","caseType":"criminal","synopsis":"is the defendant guilty of freely farting on an airplane?","charges":["As stated in case prompt"],"witnesses":[],"evidence":[],"sentenceOptions":["Community service in the meme archives","Banished to the shadow realm","Mandatory apology haikus","Ethics training hosted by a raccoon","Ukulele ankle-monitor probation"]},"sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","generatedAt":"2026-02-28T23:47:38.803Z"}}
{"id":"cfb3a47f-c5dc-492b-bca8-78ed04248833","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"phase_changed","at":"2026-02-28T23:47:38.805Z","payload":{"phase":"case_prompt","phaseStartedAt":"2026-02-28T23:47:38.803Z","phaseDurationMs":8000}}
{"id":"41240f78-2b7f-4037-97f2-fff1f54585c7","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"broadcast_hook_triggered","at":"2026-02-28T23:47:38.805Z","payload":{"phase":"case_prompt","hookType":"phase_stinger","triggeredAt":"2026-02-28T23:47:38.805Z"}}
{"id":"e88e66b1-fdb6-471b-8241-d70671db4d63","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"turn","at":"2026-02-28T23:47:38.809Z","payload":{"turn":{"id":"b369629d-8585-44ce-a0dd-4378ca01c096","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","turnNumber":0,"speaker":"mux","role":"bailiff","phase":"case_prompt","dialogue":"All rise. The JuryRigged court is now in session. Case: is the defendant guilty of freely farting on an airplane?","createdAt":"2026-02-28T23:47:38.807Z"}}}
{"id":"2ee40dd1-14ea-4dc9-9df1-e02f7ee4662f","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"phase_changed","at":"2026-02-28T23:47:40.013Z","payload":{"phase":"openings","phaseStartedAt":"2026-02-28T23:47:40.009Z","phaseDurationMs":30000}}
{"id":"0377f764-bb87-4400-89a3-ae1d8d7e7895","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"turn","at":"2026-02-28T23:47:40.015Z","payload":{"turn":{"id":"af8bec85-89e7-46e2-acef-148a274ba2c3","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","turnNumber":1,"speaker":"subrosa","role":"prosecutor","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-02-28T23:47:40.014Z"}}}
{"id":"6cd22f6a-483a-405a-9244-16c6921099b6","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"render_directive","at":"2026-02-28T23:47:40.016Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"af8bec85-89e7-46e2-acef-148a274ba2c3","phase":"openings","emittedAt":"2026-02-28T23:47:40.016Z"}}
{"id":"268448ef-74b0-4c7a-a60b-33c4d4d3bd8d","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"token_budget_applied","at":"2026-02-28T23:47:40.016Z","payload":{"turnId":"af8bec85-89e7-46e2-acef-148a274ba2c3","speaker":"subrosa","role":"prosecutor","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"6e56503d-9234-4487-9260-4295870107f1","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"session_token_estimate","at":"2026-02-28T23:47:40.016Z","payload":{"turnId":"af8bec85-89e7-46e2-acef-148a274ba2c3","role":"prosecutor","phase":"openings","estimatedPromptTokens":144,"estimatedCompletionTokens":22,"cumulativeEstimatedTokens":166,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.000332}}
{"id":"91f4bea0-a4ac-4097-854c-9ac0a5190380","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"turn","at":"2026-02-28T23:47:40.920Z","payload":{"turn":{"id":"fad49735-8f19-4d00-b425-6ecbcbef4ff0","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","turnNumber":2,"speaker":"chora","role":"defense","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-02-28T23:47:40.917Z"}}}
{"id":"ea6e6d97-67fc-4296-b5fa-821609d009ee","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"render_directive","at":"2026-02-28T23:47:40.920Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"fad49735-8f19-4d00-b425-6ecbcbef4ff0","phase":"openings","emittedAt":"2026-02-28T23:47:40.920Z"}}
{"id":"4c16dad6-ec72-406f-b6bf-8713de8cee7c","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"token_budget_applied","at":"2026-02-28T23:47:40.920Z","payload":{"turnId":"fad49735-8f19-4d00-b425-6ecbcbef4ff0","speaker":"chora","role":"defense","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"7d0d6376-0ad9-4a1f-954b-d5f19091c511","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"session_token_estimate","at":"2026-02-28T23:47:40.920Z","payload":{"turnId":"fad49735-8f19-4d00-b425-6ecbcbef4ff0","role":"defense","phase":"openings","estimatedPromptTokens":306,"estimatedCompletionTokens":44,"cumulativeEstimatedTokens":350,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.0007}}
{"id":"a883b825-6e0c-4017-9c30-02d7ff2a60fc","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"phase_changed","at":"2026-02-28T23:47:40.924Z","payload":{"phase":"witness_exam","phaseStartedAt":"2026-02-28T23:47:40.922Z","phaseDurationMs":40000}}
{"id":"c15051b7-727c-479e-9749-53903b389349","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"turn","at":"2026-02-28T23:47:41.526Z","payload":{"turn":{"id":"4b4795a9-419e-4459-aa1d-71bb6d27d2e2","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","turnNumber":3,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:47:41.524Z"}}}
{"id":"cb50bfdf-2dde-4c96-805b-91af851b9396","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"render_directive","at":"2026-02-28T23:47:41.526Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"4b4795a9-419e-4459-aa1d-71bb6d27d2e2","phase":"witness_exam","emittedAt":"2026-02-28T23:47:41.526Z"}}
{"id":"98db96da-a28a-4cef-bd99-8e8a7439c2b1","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"token_budget_applied","at":"2026-02-28T23:47:41.526Z","payload":{"turnId":"4b4795a9-419e-4459-aa1d-71bb6d27d2e2","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"b184290f-81b4-4012-ac44-8db9ae4fbfd9","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"session_token_estimate","at":"2026-02-28T23:47:41.526Z","payload":{"turnId":"4b4795a9-419e-4459-aa1d-71bb6d27d2e2","role":"judge","phase":"witness_exam","estimatedPromptTokens":495,"estimatedCompletionTokens":64,"cumulativeEstimatedTokens":559,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001118}}
{"id":"4413d110-e4e6-43ed-8260-0eaf66e63633","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"turn","at":"2026-02-28T23:47:42.130Z","payload":{"turn":{"id":"fccfaffb-a593-46ae-806b-9d600c677d96","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","turnNumber":4,"speaker":"thaum","role":"witness_1","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:47:42.126Z"}}}
{"id":"201b9347-d2b0-45b4-8cdf-0b9cda72e519","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"render_directive","at":"2026-02-28T23:47:42.130Z","payload":{"directive":{"camera":"witness","poses":{"witness_1":"talk"}},"turnId":"fccfaffb-a593-46ae-806b-9d600c677d96","phase":"witness_exam","emittedAt":"2026-02-28T23:47:42.130Z"}}
{"id":"dca55a8e-31c9-4c31-aa6e-a1defb0e1f6b","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"witness_statement","at":"2026-02-28T23:47:42.130Z","payload":{"statement":{"witnessRole":"witness_1","agentId":"thaum","statementText":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","issuedAt":"2026-02-28T23:47:42.130Z"},"phase":"witness_exam","emittedAt":"2026-02-28T23:47:42.130Z"}}
{"id":"a6506c36-dac6-43ab-9bf7-bb0fc2e1e6ad","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"token_budget_applied","at":"2026-02-28T23:47:42.130Z","payload":{"turnId":"fccfaffb-a593-46ae-806b-9d600c677d96","speaker":"thaum","role":"witness_1","phase":"witness_exam","requestedMaxTokens":90,"appliedMaxTokens":90,"roleMaxTokens":160,"source":"requested"}}
{"id":"5e67f033-7c06-4a3c-bf65-b3602b8e529d","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"session_token_estimate","at":"2026-02-28T23:47:42.130Z","payload":{"turnId":"fccfaffb-a593-46ae-806b-9d600c677d96","role":"witness_1","phase":"witness_exam","estimatedPromptTokens":704,"estimatedCompletionTokens":84,"cumulativeEstimatedTokens":788,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001576}}
{"id":"b50dd566-705f-4cbe-8daf-5a8a409b7cce","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"turn","at":"2026-02-28T23:47:42.735Z","payload":{"turn":{"id":"44fabbba-4616-4999-8cda-15e8b9965670","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","turnNumber":5,"speaker":"subrosa","role":"prosecutor","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:47:42.731Z"}}}
{"id":"dafaf92b-953a-497b-abea-fd1edcd34970","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"render_directive","at":"2026-02-28T23:47:42.735Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"44fabbba-4616-4999-8cda-15e8b9965670","phase":"witness_exam","emittedAt":"2026-02-28T23:47:42.735Z"}}
{"id":"57ccab05-c805-4e30-b3ed-951a919ce279","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"token_budget_applied","at":"2026-02-28T23:47:42.735Z","payload":{"turnId":"44fabbba-4616-4999-8cda-15e8b9965670","speaker":"subrosa","role":"prosecutor","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"f2ef73ef-2cb4-4f51-b4f9-c3e25c365aec","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"session_token_estimate","at":"2026-02-28T23:47:42.735Z","payload":{"turnId":"44fabbba-4616-4999-8cda-15e8b9965670","role":"prosecutor","phase":"witness_exam","estimatedPromptTokens":931,"estimatedCompletionTokens":104,"cumulativeEstimatedTokens":1035,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00207}}
{"id":"f3c8b8c7-31cc-41b3-b145-00768f6873da","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"turn","at":"2026-02-28T23:47:43.339Z","payload":{"turn":{"id":"2e05bb69-6685-47b8-a65c-ff2067b7c639","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","turnNumber":6,"speaker":"chora","role":"defense","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:47:43.335Z"}}}
{"id":"09e5fbca-730f-4d23-b2a7-987a7826b1f1","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"render_directive","at":"2026-02-28T23:47:43.339Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"2e05bb69-6685-47b8-a65c-ff2067b7c639","phase":"witness_exam","emittedAt":"2026-02-28T23:47:43.339Z"}}
{"id":"c127e549-547b-4d91-b429-c82aa24e8dbc","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"token_budget_applied","at":"2026-02-28T23:47:43.339Z","payload":{"turnId":"2e05bb69-6685-47b8-a65c-ff2067b7c639","speaker":"chora","role":"defense","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"66a02be0-4115-45c5-a7b3-9e5b429c65ac","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"session_token_estimate","at":"2026-02-28T23:47:43.339Z","payload":{"turnId":"2e05bb69-6685-47b8-a65c-ff2067b7c639","role":"defense","phase":"witness_exam","estimatedPromptTokens":1185,"estimatedCompletionTokens":124,"cumulativeEstimatedTokens":1309,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.002618}}
{"id":"4b6985a7-7e4e-4c1f-a6bf-0d76751d2662","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"turn","at":"2026-02-28T23:47:44.143Z","payload":{"turn":{"id":"513b393f-120f-4ba9-9316-34b194712202","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","turnNumber":7,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:47:44.139Z"}}}
{"id":"d632172a-9bce-4c06-b3c4-66f4211549a7","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"render_directive","at":"2026-02-28T23:47:44.143Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"513b393f-120f-4ba9-9316-34b194712202","phase":"witness_exam","emittedAt":"2026-02-28T23:47:44.143Z"}}
{"id":"9a89f2b1-9181-4887-8f22-75f9a2b629ac","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"token_budget_applied","at":"2026-02-28T23:47:44.143Z","payload":{"turnId":"513b393f-120f-4ba9-9316-34b194712202","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"dd3bbdfc-b94f-427f-ad56-ed24ea9eb34b","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"session_token_estimate","at":"2026-02-28T23:47:44.143Z","payload":{"turnId":"513b393f-120f-4ba9-9316-34b194712202","role":"judge","phase":"witness_exam","estimatedPromptTokens":1462,"estimatedCompletionTokens":144,"cumulativeEstimatedTokens":1606,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.003212}}
{"id":"bf009b49-f7b6-4044-a2c2-f0e1b52fa4a6","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"turn","at":"2026-02-28T23:47:44.747Z","payload":{"turn":{"id":"19d1515d-d3b8-4cd4-9d19-7bfd2d88af36","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","turnNumber":8,"speaker":"praxis","role":"witness_2","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:47:44.743Z"}}}
{"id":"c628b7ca-fb7a-42c4-877e-627d34d03d2e","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"render_directive","at":"2026-02-28T23:47:44.747Z","payload":{"directive":{"camera":"witness","poses":{"witness_2":"talk"}},"turnId":"19d1515d-d3b8-4cd4-9d19-7bfd2d88af36","phase":"witness_exam","emittedAt":"2026-02-28T23:47:44.747Z"}}
{"id":"864d3a4e-0cc4-4fa8-85a1-0583006ebcef","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"witness_statement","at":"2026-02-28T23:47:44.747Z","payload":{"statement":{"witnessRole":"witness_2","agentId":"praxis","statementText":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","issuedAt":"2026-02-28T23:47:44.747Z"},"phase":"witness_exam","emittedAt":"2026-02-28T23:47:44.747Z"}}
{"id":"05cca0d7-daf1-497b-80c4-0c85310fab52","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"token_budget_applied","at":"2026-02-28T23:47:44.747Z","payload":{"turnId":"19d1515d-d3b8-4cd4-9d19-7bfd2d88af36","speaker":"praxis","role":"witness_2","phase":"witness_exam","requestedMaxTokens":90,"appliedMaxTokens":90,"roleMaxTokens":160,"source":"requested"}}
{"id":"2988d3cf-2efc-45d4-9bbf-e58df3501c7d","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"session_token_estimate","at":"2026-02-28T23:47:44.747Z","payload":{"turnId":"19d1515d-d3b8-4cd4-9d19-7bfd2d88af36","role":"witness_2","phase":"witness_exam","estimatedPromptTokens":1759,"estimatedCompletionTokens":164,"cumulativeEstimatedTokens":1923,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.003846}}
{"id":"e2ea4626-3e31-4214-9c52-8c00e23f47eb","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"turn","at":"2026-02-28T23:47:45.351Z","payload":{"turn":{"id":"f1eb711d-b685-4c61-9099-aeee968bbf12","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","turnNumber":9,"speaker":"subrosa","role":"prosecutor","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:47:45.347Z"}}}
{"id":"dd1ad4a0-6207-4760-a51b-28448055c855","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"render_directive","at":"2026-02-28T23:47:45.351Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"f1eb711d-b685-4c61-9099-aeee968bbf12","phase":"witness_exam","emittedAt":"2026-02-28T23:47:45.351Z"}}
{"id":"6931746d-b740-4398-83f7-ecabd7ea24fd","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"token_budget_applied","at":"2026-02-28T23:47:45.351Z","payload":{"turnId":"f1eb711d-b685-4c61-9099-aeee968bbf12","speaker":"subrosa","role":"prosecutor","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"e4490044-8c84-44aa-bb85-12d4c6000e1f","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"session_token_estimate","at":"2026-02-28T23:47:45.351Z","payload":{"turnId":"f1eb711d-b685-4c61-9099-aeee968bbf12","role":"prosecutor","phase":"witness_exam","estimatedPromptTokens":2074,"estimatedCompletionTokens":184,"cumulativeEstimatedTokens":2258,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.004516}}
{"id":"a4209cd3-2ed8-4946-9699-0b39ca814f58","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"turn","at":"2026-02-28T23:47:45.955Z","payload":{"turn":{"id":"97e97682-a28d-4dda-9b25-338eff5f1a71","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","turnNumber":10,"speaker":"chora","role":"defense","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:47:45.951Z"}}}
{"id":"7e3d67b2-733a-4547-86f3-6cfd5f2967ec","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"render_directive","at":"2026-02-28T23:47:45.955Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"97e97682-a28d-4dda-9b25-338eff5f1a71","phase":"witness_exam","emittedAt":"2026-02-28T23:47:45.955Z"}}
{"id":"3f5d84dc-fa8b-4c97-9cde-1613d176f7f7","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"token_budget_applied","at":"2026-02-28T23:47:45.955Z","payload":{"turnId":"97e97682-a28d-4dda-9b25-338eff5f1a71","speaker":"chora","role":"defense","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"7d7499c1-de1d-4fe8-ac71-7b8a47b50e4d","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"session_token_estimate","at":"2026-02-28T23:47:45.955Z","payload":{"turnId":"97e97682-a28d-4dda-9b25-338eff5f1a71","role":"defense","phase":"witness_exam","estimatedPromptTokens":2392,"estimatedCompletionTokens":204,"cumulativeEstimatedTokens":2596,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.005192}}
{"id":"3757ed81-8dea-42df-bdb9-ee28b0bf53b4","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"turn","at":"2026-02-28T23:47:46.557Z","payload":{"turn":{"id":"d1b7b270-5005-4936-b7f7-473a0f6f75e6","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","turnNumber":11,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"Recap: Order in the court. I acknowledge the point and move us to the next absurdly important matter.","createdAt":"2026-02-28T23:47:46.555Z"}}}
{"id":"c72cbe96-9135-4088-a4c8-4835a5df0f2f","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"render_directive","at":"2026-02-28T23:47:46.557Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"d1b7b270-5005-4936-b7f7-473a0f6f75e6","phase":"witness_exam","emittedAt":"2026-02-28T23:47:46.557Z"}}
{"id":"bcbb69e1-7b2d-4dc9-b0d6-6e686f512f14","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"token_budget_applied","at":"2026-02-28T23:47:46.557Z","payload":{"turnId":"d1b7b270-5005-4936-b7f7-473a0f6f75e6","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"9947820c-dbfb-4cf4-9a4d-4b88a3d6b451","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"session_token_estimate","at":"2026-02-28T23:47:46.557Z","payload":{"turnId":"d1b7b270-5005-4936-b7f7-473a0f6f75e6","role":"judge","phase":"witness_exam","estimatedPromptTokens":2713,"estimatedCompletionTokens":222,"cumulativeEstimatedTokens":2935,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00587}}
{"id":"4390b839-e921-45c9-b5ca-9def83c019b0","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"judge_recap_emitted","at":"2026-02-28T23:47:46.560Z","payload":{"turnId":"d1b7b270-5005-4936-b7f7-473a0f6f75e6","phase":"witness_exam","cycleNumber":2}}
{"id":"4ca17ea3-de53-4d5c-bbfa-b38e88f42a7b","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"phase_changed","at":"2026-02-28T23:47:47.366Z","payload":{"phase":"closings","phaseStartedAt":"2026-02-28T23:47:47.362Z","phaseDurationMs":30000}}
{"id":"db66cf0d-6ea9-4cd0-a14b-923d23eff3df","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"turn","at":"2026-02-28T23:47:47.368Z","payload":{"turn":{"id":"3bbb3245-56c1-454f-83c9-8fcf3f52b48f","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","turnNumber":12,"speaker":"subrosa","role":"prosecutor","phase":"closings","dialogue":"At the end of the day, this is either a crime or a spectacular misunderstanding involving glitter and plausible deniability.","createdAt":"2026-02-28T23:47:47.367Z"}}}
{"id":"5c996891-6838-4e3b-8cf8-20234a6443e4","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"render_directive","at":"2026-02-28T23:47:47.368Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"3bbb3245-56c1-454f-83c9-8fcf3f52b48f","phase":"closings","emittedAt":"2026-02-28T23:47:47.368Z"}}
{"id":"0a18cd32-750d-4333-a521-7642d5f425a4","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"token_budget_applied","at":"2026-02-28T23:47:47.368Z","payload":{"turnId":"3bbb3245-56c1-454f-83c9-8fcf3f52b48f","speaker":"subrosa","role":"prosecutor","phase":"closings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"1acd6067-4064-41d5-90d5-5c580037a34c","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"session_token_estimate","at":"2026-02-28T23:47:47.368Z","payload":{"turnId":"3bbb3245-56c1-454f-83c9-8fcf3f52b48f","role":"prosecutor","phase":"closings","estimatedPromptTokens":3025,"estimatedCompletionTokens":242,"cumulativeEstimatedTokens":3267,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.006534}}
{"id":"ccacf4d2-f74b-44ba-98a6-abb74d48477b","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"turn","at":"2026-02-28T23:47:48.174Z","payload":{"turn":{"id":"84de4f8c-9bd0-478c-90b7-1cbdaa068aa8","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","turnNumber":13,"speaker":"chora","role":"defense","phase":"closings","dialogue":"At the end of the day, this is either a crime or a spectacular misunderstanding involving glitter and plausible deniability.","createdAt":"2026-02-28T23:47:48.169Z"}}}
{"id":"386ea62b-76e0-4718-892f-61848fd3fc21","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"render_directive","at":"2026-02-28T23:47:48.174Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"84de4f8c-9bd0-478c-90b7-1cbdaa068aa8","phase":"closings","emittedAt":"2026-02-28T23:47:48.174Z"}}
{"id":"735c3aa8-2299-49c9-86b7-b9c7991ca09b","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"token_budget_applied","at":"2026-02-28T23:47:48.174Z","payload":{"turnId":"84de4f8c-9bd0-478c-90b7-1cbdaa068aa8","speaker":"chora","role":"defense","phase":"closings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"213ce5b5-5cc5-4e70-9fef-a52faa0b9f1c","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"session_token_estimate","at":"2026-02-28T23:47:48.174Z","payload":{"turnId":"84de4f8c-9bd0-478c-90b7-1cbdaa068aa8","role":"defense","phase":"closings","estimatedPromptTokens":3336,"estimatedCompletionTokens":262,"cumulativeEstimatedTokens":3598,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.007196}}
{"id":"633fd928-6719-4951-ae23-0d181e3e413c","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"phase_changed","at":"2026-02-28T23:47:48.177Z","payload":{"phase":"verdict_vote","phaseStartedAt":"2026-02-28T23:47:48.176Z","phaseDurationMs":20000}}
{"id":"39c16df7-a5b6-4192-961b-c8353b9aa55f","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"analytics_event","at":"2026-02-28T23:47:48.177Z","payload":{"name":"poll_started","pollType":"verdict","phase":"verdict_vote"}}
{"id":"88e5c5f5-8c92-4c08-b7d7-4ce4313abed6","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"broadcast_hook_triggered","at":"2026-02-28T23:47:48.177Z","payload":{"phase":"verdict_vote","hookType":"scene_switch","triggeredAt":"2026-02-28T23:47:48.177Z"}}
{"id":"5d00dc39-d933-436e-bcf2-07c5995b50a3","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"turn","at":"2026-02-28T23:47:48.180Z","payload":{"turn":{"id":"45daa96f-cc6e-4aca-9b9f-770ab7882f51","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","turnNumber":14,"speaker":"mux","role":"bailiff","phase":"verdict_vote","dialogue":"Jury poll is open: guilty / not_guilty. Cast your votes now.","createdAt":"2026-02-28T23:47:48.178Z"}}}
{"id":"3255a5ff-f7f3-4901-be93-d1ddd3d6a780","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"phase_changed","at":"2026-02-28T23:48:08.186Z","payload":{"phase":"sentence_vote","phaseStartedAt":"2026-02-28T23:48:08.181Z","phaseDurationMs":20000}}
{"id":"b2beb3a6-74f5-4e63-8394-3e1ce5917856","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"vote_closed","at":"2026-02-28T23:48:08.186Z","payload":{"pollType":"verdict","closedAt":"2026-02-28T23:48:08.181Z","votes":{},"nextPhase":"sentence_vote"}}
{"id":"9a19ae65-016e-4c12-b4f4-d233a454a047","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"analytics_event","at":"2026-02-28T23:48:08.186Z","payload":{"name":"poll_closed","pollType":"verdict","phase":"sentence_vote"}}
{"id":"35b58d89-4855-432b-98f4-bf4ddd9e9f1a","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"analytics_event","at":"2026-02-28T23:48:08.186Z","payload":{"name":"poll_started","pollType":"sentence","phase":"sentence_vote"}}
{"id":"b7f559ee-5714-430c-b4d4-72c8a2c79faa","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"broadcast_hook_triggered","at":"2026-02-28T23:48:08.186Z","payload":{"phase":"sentence_vote","hookType":"scene_switch","triggeredAt":"2026-02-28T23:48:08.186Z"}}
{"id":"68879e54-fa2f-4157-91a0-fdcf535b4993","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"turn","at":"2026-02-28T23:48:08.189Z","payload":{"turn":{"id":"535cd828-42ae-4fca-b261-04056ad3560d","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","turnNumber":15,"speaker":"mux","role":"bailiff","phase":"sentence_vote","dialogue":"Sentence poll is now open. Options: Community service in the meme archives | Banished to the shadow realm | Mandatory apology haikus | Ethics training hosted by a raccoon | Ukulele ankle-monitor probation","createdAt":"2026-02-28T23:48:08.187Z"}}}
{"id":"b2301f0d-99db-4c0d-9043-39f6e94d8191","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"phase_changed","at":"2026-02-28T23:48:28.193Z","payload":{"phase":"final_ruling","phaseStartedAt":"2026-02-28T23:48:28.189Z","phaseDurationMs":20000}}
{"id":"75114e29-9df0-4afe-a606-da2c0fe557d2","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"vote_closed","at":"2026-02-28T23:48:28.193Z","payload":{"pollType":"sentence","closedAt":"2026-02-28T23:48:28.189Z","votes":{},"nextPhase":"final_ruling"}}
{"id":"e9ebbc50-5313-4945-81fc-3d9972a64cba","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"analytics_event","at":"2026-02-28T23:48:28.193Z","payload":{"name":"poll_closed","pollType":"sentence","phase":"final_ruling"}}
{"id":"fd6c96b0-2509-43b8-b333-ea00642d21f3","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"turn","at":"2026-02-28T23:48:28.198Z","payload":{"turn":{"id":"71a99338-e462-40c3-82ad-0b28d1aaec93","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","turnNumber":16,"speaker":"primus","role":"judge","phase":"final_ruling","dialogue":"On the charge of chaos in the first degree, this court finds the defendant dramatically guilty—with style points.","createdAt":"2026-02-28T23:48:28.197Z"}}}
{"id":"e45828f1-5760-46f8-acff-e80822a9ac6e","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"render_directive","at":"2026-02-28T23:48:28.198Z","payload":{"directive":{"camera":"verdict","poses":{"judge":"talk"}},"turnId":"71a99338-e462-40c3-82ad-0b28d1aaec93","phase":"final_ruling","emittedAt":"2026-02-28T23:48:28.198Z"}}
{"id":"e8b06da9-58fc-4934-a187-f084492f3b95","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"token_budget_applied","at":"2026-02-28T23:48:28.198Z","payload":{"turnId":"71a99338-e462-40c3-82ad-0b28d1aaec93","speaker":"primus","role":"judge","phase":"final_ruling","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"abf5dd30-638b-46ad-83be-17f13c5110b6","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"session_token_estimate","at":"2026-02-28T23:48:28.198Z","payload":{"turnId":"71a99338-e462-40c3-82ad-0b28d1aaec93","role":"judge","phase":"final_ruling","estimatedPromptTokens":3663,"estimatedCompletionTokens":280,"cumulativeEstimatedTokens":3943,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.007886}}
{"id":"e0d522b1-3d34-4974-8c14-879999f45cf4","sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","type":"session_completed","at":"2026-02-28T23:48:28.201Z","payload":{"sessionId":"43cde4a4-d952-4b2d-a544-a5c7a5939fe7","completedAt":"2026-02-28T23:48:28.198Z"}}

View File

@@ -0,0 +1,82 @@
{"id":"fa8cd2cc-1f21-4204-936c-2935247e6749","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"session_created","at":"2026-02-28T23:56:19.697Z","payload":{"sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b"}}
{"id":"623a8004-0cab-4365-bafe-245634508301","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"session_started","at":"2026-02-28T23:56:19.700Z","payload":{"sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","startedAt":"2026-02-28T23:56:19.698Z"}}
{"id":"a6ba851e-cdc6-4e7d-bea5-adab4b290e97","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"case_file_generated","at":"2026-02-28T23:56:19.700Z","payload":{"caseFile":{"title":"is the defendant guilty of freely farting on an airplane?","genre":"cosmic_crime","caseType":"criminal","synopsis":"is the defendant guilty of freely farting on an airplane?","charges":["As stated in case prompt"],"witnesses":[],"evidence":[],"sentenceOptions":["Community service in the meme archives","Banished to the shadow realm","Mandatory apology haikus","Ethics training hosted by a raccoon","Ukulele ankle-monitor probation"]},"sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","generatedAt":"2026-02-28T23:56:19.700Z"}}
{"id":"d6f802df-4c2e-418c-9340-4f96a10e6e0b","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"phase_changed","at":"2026-02-28T23:56:19.705Z","payload":{"phase":"case_prompt","phaseStartedAt":"2026-02-28T23:56:19.703Z","phaseDurationMs":8000}}
{"id":"3ea7d3e1-55ac-4a7c-a5e6-e3f06ebcf3b1","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"broadcast_hook_triggered","at":"2026-02-28T23:56:19.706Z","payload":{"phase":"case_prompt","hookType":"phase_stinger","triggeredAt":"2026-02-28T23:56:19.706Z"}}
{"id":"972d9278-fc66-4f97-a587-c2ee85155124","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"turn","at":"2026-02-28T23:56:19.708Z","payload":{"turn":{"id":"1a84f99b-07b2-4ff2-bd3d-6fa6239d6f68","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","turnNumber":0,"speaker":"mux","role":"bailiff","phase":"case_prompt","dialogue":"All rise. The JuryRigged court is now in session. Case: is the defendant guilty of freely farting on an airplane?","createdAt":"2026-02-28T23:56:19.706Z"}}}
{"id":"7088ec26-40d5-4711-b507-a03959264b1d","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"phase_changed","at":"2026-02-28T23:56:20.913Z","payload":{"phase":"openings","phaseStartedAt":"2026-02-28T23:56:20.909Z","phaseDurationMs":30000}}
{"id":"e093c9ba-a614-4606-9d77-45d5cd849456","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"turn","at":"2026-02-28T23:56:21.050Z","payload":{"turn":{"id":"b2bab399-ec2a-4f5d-aa98-4996bd43cedd","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","turnNumber":1,"speaker":"subrosa","role":"prosecutor","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-02-28T23:56:21.048Z"}}}
{"id":"66173a65-f247-4874-a169-844c34b219fa","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"render_directive","at":"2026-02-28T23:56:21.050Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"b2bab399-ec2a-4f5d-aa98-4996bd43cedd","phase":"openings","emittedAt":"2026-02-28T23:56:21.050Z"}}
{"id":"6a110fb5-95f7-4f6a-a885-2a8ec0e6d657","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"token_budget_applied","at":"2026-02-28T23:56:21.050Z","payload":{"turnId":"b2bab399-ec2a-4f5d-aa98-4996bd43cedd","speaker":"subrosa","role":"prosecutor","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"1e726064-cb06-4752-8d1c-6ac651c8e37d","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"session_token_estimate","at":"2026-02-28T23:56:21.050Z","payload":{"turnId":"b2bab399-ec2a-4f5d-aa98-4996bd43cedd","role":"prosecutor","phase":"openings","estimatedPromptTokens":143,"estimatedCompletionTokens":22,"cumulativeEstimatedTokens":165,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00033}}
{"id":"35a149a8-c71c-4986-b06f-421b5093369d","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"turn","at":"2026-02-28T23:56:21.985Z","payload":{"turn":{"id":"b84e725c-7a1b-4e20-b46d-9c25ac09cab9","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","turnNumber":2,"speaker":"chora","role":"defense","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-02-28T23:56:21.983Z"}}}
{"id":"6c4ea770-d9a9-46dd-b638-41934e0a84a6","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"render_directive","at":"2026-02-28T23:56:21.986Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"b84e725c-7a1b-4e20-b46d-9c25ac09cab9","phase":"openings","emittedAt":"2026-02-28T23:56:21.986Z"}}
{"id":"f47939dd-6af3-4e95-b207-87d538756e44","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"token_budget_applied","at":"2026-02-28T23:56:21.986Z","payload":{"turnId":"b84e725c-7a1b-4e20-b46d-9c25ac09cab9","speaker":"chora","role":"defense","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"3c489c44-bfd8-436b-b0fb-389ca2fb8143","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"session_token_estimate","at":"2026-02-28T23:56:21.986Z","payload":{"turnId":"b84e725c-7a1b-4e20-b46d-9c25ac09cab9","role":"defense","phase":"openings","estimatedPromptTokens":307,"estimatedCompletionTokens":44,"cumulativeEstimatedTokens":351,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.000702}}
{"id":"52d447c1-249a-4a88-acdc-67941cffb908","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"phase_changed","at":"2026-02-28T23:56:21.990Z","payload":{"phase":"witness_exam","phaseStartedAt":"2026-02-28T23:56:21.988Z","phaseDurationMs":40000}}
{"id":"f2388045-097d-4e06-9099-a3ccabd01ac9","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"turn","at":"2026-02-28T23:56:22.623Z","payload":{"turn":{"id":"38c68b0d-dee9-4c01-8f72-08dfcafe4adb","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","turnNumber":3,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:56:22.619Z"}}}
{"id":"6cb4d5c4-b399-4e9c-8f94-89655c43518d","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"render_directive","at":"2026-02-28T23:56:22.623Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"38c68b0d-dee9-4c01-8f72-08dfcafe4adb","phase":"witness_exam","emittedAt":"2026-02-28T23:56:22.623Z"}}
{"id":"c54c0b1e-afe5-480e-bc01-35309a4e5d26","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"token_budget_applied","at":"2026-02-28T23:56:22.623Z","payload":{"turnId":"38c68b0d-dee9-4c01-8f72-08dfcafe4adb","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"7711c533-f547-4c6c-8d63-50f8b49312bc","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"session_token_estimate","at":"2026-02-28T23:56:22.623Z","payload":{"turnId":"38c68b0d-dee9-4c01-8f72-08dfcafe4adb","role":"judge","phase":"witness_exam","estimatedPromptTokens":491,"estimatedCompletionTokens":64,"cumulativeEstimatedTokens":555,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00111}}
{"id":"609b3846-e195-4fbf-9fb0-be4a6d3771da","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"turn","at":"2026-02-28T23:56:23.248Z","payload":{"turn":{"id":"4be11570-a450-49a4-81a6-97b0bc482ed0","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","turnNumber":4,"speaker":"thaum","role":"witness_1","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:56:23.244Z"}}}
{"id":"fedb9a7a-74a5-49e5-b907-4fb33a7745a2","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"render_directive","at":"2026-02-28T23:56:23.248Z","payload":{"directive":{"camera":"witness","poses":{"witness_1":"talk"}},"turnId":"4be11570-a450-49a4-81a6-97b0bc482ed0","phase":"witness_exam","emittedAt":"2026-02-28T23:56:23.248Z"}}
{"id":"e8c767b9-0e9e-4a7d-a20f-f1139e1e470b","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"witness_statement","at":"2026-02-28T23:56:23.248Z","payload":{"statement":{"witnessRole":"witness_1","agentId":"thaum","statementText":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","issuedAt":"2026-02-28T23:56:23.248Z"},"phase":"witness_exam","emittedAt":"2026-02-28T23:56:23.248Z"}}
{"id":"f1efacc4-60d1-4741-a63f-1cc80ef2f874","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"token_budget_applied","at":"2026-02-28T23:56:23.248Z","payload":{"turnId":"4be11570-a450-49a4-81a6-97b0bc482ed0","speaker":"thaum","role":"witness_1","phase":"witness_exam","requestedMaxTokens":90,"appliedMaxTokens":90,"roleMaxTokens":160,"source":"requested"}}
{"id":"5a9ae728-dd84-48eb-b1d6-0c3bfada9667","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"session_token_estimate","at":"2026-02-28T23:56:23.248Z","payload":{"turnId":"4be11570-a450-49a4-81a6-97b0bc482ed0","role":"witness_1","phase":"witness_exam","estimatedPromptTokens":700,"estimatedCompletionTokens":84,"cumulativeEstimatedTokens":784,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001568}}
{"id":"637e7457-b4da-4a5a-8ab7-4f0137e223d4","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"turn","at":"2026-02-28T23:56:23.879Z","payload":{"turn":{"id":"9c2ad987-9fb7-41b2-b1ff-282874c2f655","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","turnNumber":5,"speaker":"subrosa","role":"prosecutor","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:56:23.875Z"}}}
{"id":"f7814afa-795e-474d-a923-358340b23cfa","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"render_directive","at":"2026-02-28T23:56:23.879Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"9c2ad987-9fb7-41b2-b1ff-282874c2f655","phase":"witness_exam","emittedAt":"2026-02-28T23:56:23.879Z"}}
{"id":"0f8a5832-1b80-4652-b091-87b7ce21f176","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"token_budget_applied","at":"2026-02-28T23:56:23.879Z","payload":{"turnId":"9c2ad987-9fb7-41b2-b1ff-282874c2f655","speaker":"subrosa","role":"prosecutor","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"5494e45a-b4b8-494b-b70e-9b22a2ac37ad","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"session_token_estimate","at":"2026-02-28T23:56:23.879Z","payload":{"turnId":"9c2ad987-9fb7-41b2-b1ff-282874c2f655","role":"prosecutor","phase":"witness_exam","estimatedPromptTokens":926,"estimatedCompletionTokens":104,"cumulativeEstimatedTokens":1030,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00206}}
{"id":"1d6aef2d-32be-4c19-838f-8b5a1d1e1ba7","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"turn","at":"2026-02-28T23:56:24.512Z","payload":{"turn":{"id":"84f89d68-4342-4590-ab6c-679e18b5b19d","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","turnNumber":6,"speaker":"chora","role":"defense","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:56:24.509Z"}}}
{"id":"dfc92e91-0fe2-4d51-be5e-634664c5645d","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"render_directive","at":"2026-02-28T23:56:24.512Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"84f89d68-4342-4590-ab6c-679e18b5b19d","phase":"witness_exam","emittedAt":"2026-02-28T23:56:24.512Z"}}
{"id":"b4512b6c-3d83-4a59-b805-9c86c19eb257","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"token_budget_applied","at":"2026-02-28T23:56:24.512Z","payload":{"turnId":"84f89d68-4342-4590-ab6c-679e18b5b19d","speaker":"chora","role":"defense","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"c73aaa3f-1ff7-48db-9ac9-bd77db9e02e5","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"session_token_estimate","at":"2026-02-28T23:56:24.512Z","payload":{"turnId":"84f89d68-4342-4590-ab6c-679e18b5b19d","role":"defense","phase":"witness_exam","estimatedPromptTokens":1182,"estimatedCompletionTokens":124,"cumulativeEstimatedTokens":1306,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.002612}}
{"id":"5b98cc44-3ce2-43d5-b2b1-bf6c968720cf","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"turn","at":"2026-02-28T23:56:25.351Z","payload":{"turn":{"id":"6080c314-e40c-4a71-97a1-aa6a363d3033","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","turnNumber":7,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:56:25.348Z"}}}
{"id":"50381078-60d8-4cf8-a23f-599c231d3315","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"render_directive","at":"2026-02-28T23:56:25.351Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"6080c314-e40c-4a71-97a1-aa6a363d3033","phase":"witness_exam","emittedAt":"2026-02-28T23:56:25.351Z"}}
{"id":"e787ddf2-f0fc-49e5-852b-6414438613e5","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"token_budget_applied","at":"2026-02-28T23:56:25.351Z","payload":{"turnId":"6080c314-e40c-4a71-97a1-aa6a363d3033","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"7a7a74dd-69dc-47d7-bd45-9960a2a781b1","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"session_token_estimate","at":"2026-02-28T23:56:25.351Z","payload":{"turnId":"6080c314-e40c-4a71-97a1-aa6a363d3033","role":"judge","phase":"witness_exam","estimatedPromptTokens":1454,"estimatedCompletionTokens":144,"cumulativeEstimatedTokens":1598,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.003196}}
{"id":"02f09811-9893-4125-a2dd-c9d2a962a337","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"turn","at":"2026-02-28T23:56:25.979Z","payload":{"turn":{"id":"cbebcddd-4ab2-41fa-8a4d-438184c1ea2b","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","turnNumber":8,"speaker":"praxis","role":"witness_2","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:56:25.976Z"}}}
{"id":"5465cebc-25b2-4cce-aa6e-6c12dc601fb5","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"render_directive","at":"2026-02-28T23:56:25.979Z","payload":{"directive":{"camera":"witness","poses":{"witness_2":"talk"}},"turnId":"cbebcddd-4ab2-41fa-8a4d-438184c1ea2b","phase":"witness_exam","emittedAt":"2026-02-28T23:56:25.979Z"}}
{"id":"89f4f155-adc7-42ad-afd7-1c38b7fd26b3","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"witness_statement","at":"2026-02-28T23:56:25.979Z","payload":{"statement":{"witnessRole":"witness_2","agentId":"praxis","statementText":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","issuedAt":"2026-02-28T23:56:25.979Z"},"phase":"witness_exam","emittedAt":"2026-02-28T23:56:25.979Z"}}
{"id":"0113cbab-5eca-4e58-85e5-108c60318e42","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"token_budget_applied","at":"2026-02-28T23:56:25.979Z","payload":{"turnId":"cbebcddd-4ab2-41fa-8a4d-438184c1ea2b","speaker":"praxis","role":"witness_2","phase":"witness_exam","requestedMaxTokens":90,"appliedMaxTokens":90,"roleMaxTokens":160,"source":"requested"}}
{"id":"eefc9afc-e6cf-4671-8d78-856fa5b22e9d","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"session_token_estimate","at":"2026-02-28T23:56:25.979Z","payload":{"turnId":"cbebcddd-4ab2-41fa-8a4d-438184c1ea2b","role":"witness_2","phase":"witness_exam","estimatedPromptTokens":1751,"estimatedCompletionTokens":164,"cumulativeEstimatedTokens":1915,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00383}}
{"id":"4c76c626-3c2d-4a91-b716-1da5d57aed42","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"turn","at":"2026-02-28T23:56:26.614Z","payload":{"turn":{"id":"0f6b75ec-9e8f-4b3e-992c-692ddf943b9b","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","turnNumber":9,"speaker":"subrosa","role":"prosecutor","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:56:26.611Z"}}}
{"id":"6547a3a0-5532-453a-b77f-9884c62426cd","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"render_directive","at":"2026-02-28T23:56:26.614Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"0f6b75ec-9e8f-4b3e-992c-692ddf943b9b","phase":"witness_exam","emittedAt":"2026-02-28T23:56:26.614Z"}}
{"id":"c2cf8308-e1c7-4abf-a759-4ea6ca5144db","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"token_budget_applied","at":"2026-02-28T23:56:26.614Z","payload":{"turnId":"0f6b75ec-9e8f-4b3e-992c-692ddf943b9b","speaker":"subrosa","role":"prosecutor","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"0a7342fc-0012-4b17-845b-b0f25cd19b96","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"session_token_estimate","at":"2026-02-28T23:56:26.615Z","payload":{"turnId":"0f6b75ec-9e8f-4b3e-992c-692ddf943b9b","role":"prosecutor","phase":"witness_exam","estimatedPromptTokens":2065,"estimatedCompletionTokens":184,"cumulativeEstimatedTokens":2249,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.004498}}
{"id":"0452b1da-b5ec-4cb9-8350-26a8b0b0d141","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"turn","at":"2026-02-28T23:56:27.249Z","payload":{"turn":{"id":"591acae5-174a-4917-b5a3-3cad0f5314cd","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","turnNumber":10,"speaker":"chora","role":"defense","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:56:27.245Z"}}}
{"id":"da9d8369-02fa-4321-b298-778ef431d5d8","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"render_directive","at":"2026-02-28T23:56:27.249Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"591acae5-174a-4917-b5a3-3cad0f5314cd","phase":"witness_exam","emittedAt":"2026-02-28T23:56:27.249Z"}}
{"id":"f1052e70-4ebb-4f7d-b56c-bbbab0e40a26","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"token_budget_applied","at":"2026-02-28T23:56:27.249Z","payload":{"turnId":"591acae5-174a-4917-b5a3-3cad0f5314cd","speaker":"chora","role":"defense","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"b326257f-61e4-4ab5-9bec-159016e919b8","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"session_token_estimate","at":"2026-02-28T23:56:27.249Z","payload":{"turnId":"591acae5-174a-4917-b5a3-3cad0f5314cd","role":"defense","phase":"witness_exam","estimatedPromptTokens":2385,"estimatedCompletionTokens":204,"cumulativeEstimatedTokens":2589,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.005178}}
{"id":"b96cdee8-7b24-4ff9-9a45-32e71327dd25","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"turn","at":"2026-02-28T23:56:27.875Z","payload":{"turn":{"id":"203ca87b-3b19-4095-ba9b-8037efd70c25","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","turnNumber":11,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"Recap: Order in the court. I acknowledge the point and move us to the next absurdly important matter.","createdAt":"2026-02-28T23:56:27.871Z"}}}
{"id":"57639831-f02b-4e7e-a252-4cac94da709c","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"render_directive","at":"2026-02-28T23:56:27.875Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"203ca87b-3b19-4095-ba9b-8037efd70c25","phase":"witness_exam","emittedAt":"2026-02-28T23:56:27.875Z"}}
{"id":"8b146393-136a-4557-9c8a-b20c0f4c634c","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"token_budget_applied","at":"2026-02-28T23:56:27.875Z","payload":{"turnId":"203ca87b-3b19-4095-ba9b-8037efd70c25","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"f250e392-d30e-4515-a448-3d8754cd8ce3","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"session_token_estimate","at":"2026-02-28T23:56:27.875Z","payload":{"turnId":"203ca87b-3b19-4095-ba9b-8037efd70c25","role":"judge","phase":"witness_exam","estimatedPromptTokens":2701,"estimatedCompletionTokens":222,"cumulativeEstimatedTokens":2923,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.005846}}
{"id":"62a24bc2-aa4e-4533-b611-d6b1c35368c0","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"judge_recap_emitted","at":"2026-02-28T23:56:27.879Z","payload":{"turnId":"203ca87b-3b19-4095-ba9b-8037efd70c25","phase":"witness_exam","cycleNumber":2}}
{"id":"a6eb4472-17a8-4fa5-84e4-ef5a5f862053","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"phase_changed","at":"2026-02-28T23:56:28.684Z","payload":{"phase":"closings","phaseStartedAt":"2026-02-28T23:56:28.680Z","phaseDurationMs":30000}}
{"id":"1e2b85d1-c11c-43d0-afda-c50e196ce8e0","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"turn","at":"2026-02-28T23:56:28.706Z","payload":{"turn":{"id":"06fd0cb1-3a29-431a-a457-d1a24b5ebcec","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","turnNumber":12,"speaker":"subrosa","role":"prosecutor","phase":"closings","dialogue":"At the end of the day, this is either a crime or a spectacular misunderstanding involving glitter and plausible deniability.","createdAt":"2026-02-28T23:56:28.705Z"}}}
{"id":"93ee5cbb-c7ed-429f-878b-8ca70f05b726","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"render_directive","at":"2026-02-28T23:56:28.706Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"06fd0cb1-3a29-431a-a457-d1a24b5ebcec","phase":"closings","emittedAt":"2026-02-28T23:56:28.706Z"}}
{"id":"5a48a325-1ecb-4378-9cbd-ad3003171e56","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"token_budget_applied","at":"2026-02-28T23:56:28.706Z","payload":{"turnId":"06fd0cb1-3a29-431a-a457-d1a24b5ebcec","speaker":"subrosa","role":"prosecutor","phase":"closings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"d017c698-5eca-4acd-b124-df8af9880601","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"session_token_estimate","at":"2026-02-28T23:56:28.706Z","payload":{"turnId":"06fd0cb1-3a29-431a-a457-d1a24b5ebcec","role":"prosecutor","phase":"closings","estimatedPromptTokens":3012,"estimatedCompletionTokens":242,"cumulativeEstimatedTokens":3254,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.006508}}
{"id":"52185708-9016-4e64-8fd1-45d4efe0454d","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"turn","at":"2026-02-28T23:56:29.541Z","payload":{"turn":{"id":"37c2da11-26f5-4c78-bf1a-b730f8eac167","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","turnNumber":13,"speaker":"chora","role":"defense","phase":"closings","dialogue":"At the end of the day, this is either a crime or a spectacular misunderstanding involving glitter and plausible deniability.","createdAt":"2026-02-28T23:56:29.538Z"}}}
{"id":"0e7216b5-b6d5-4eee-b2a0-a3e3ca604585","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"render_directive","at":"2026-02-28T23:56:29.541Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"37c2da11-26f5-4c78-bf1a-b730f8eac167","phase":"closings","emittedAt":"2026-02-28T23:56:29.541Z"}}
{"id":"9ae371be-8f6e-4948-818e-49d296756462","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"token_budget_applied","at":"2026-02-28T23:56:29.541Z","payload":{"turnId":"37c2da11-26f5-4c78-bf1a-b730f8eac167","speaker":"chora","role":"defense","phase":"closings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"3d2358a5-465c-4b02-ba76-528e7c03a5bc","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"session_token_estimate","at":"2026-02-28T23:56:29.541Z","payload":{"turnId":"37c2da11-26f5-4c78-bf1a-b730f8eac167","role":"defense","phase":"closings","estimatedPromptTokens":3325,"estimatedCompletionTokens":262,"cumulativeEstimatedTokens":3587,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.007174}}
{"id":"f82ee8e9-1883-4c71-94fa-ef771b5de14a","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"phase_changed","at":"2026-02-28T23:56:29.545Z","payload":{"phase":"verdict_vote","phaseStartedAt":"2026-02-28T23:56:29.543Z","phaseDurationMs":20000}}
{"id":"ab134d22-2830-4d44-8245-e7dcafa403ca","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"analytics_event","at":"2026-02-28T23:56:29.545Z","payload":{"name":"poll_started","pollType":"verdict","phase":"verdict_vote"}}
{"id":"7e679a8d-5a75-46bb-bfbe-74c7576b7c3b","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"broadcast_hook_triggered","at":"2026-02-28T23:56:29.545Z","payload":{"phase":"verdict_vote","hookType":"scene_switch","triggeredAt":"2026-02-28T23:56:29.545Z"}}
{"id":"98547ebc-6cd0-4e61-a161-4b00214b2e31","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"turn","at":"2026-02-28T23:56:29.548Z","payload":{"turn":{"id":"c2d8cb22-8580-4e8b-83cf-6f8475dd1aa8","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","turnNumber":14,"speaker":"mux","role":"bailiff","phase":"verdict_vote","dialogue":"Jury poll is open: guilty / not_guilty. Cast your votes now.","createdAt":"2026-02-28T23:56:29.546Z"}}}
{"id":"4d0ac6ae-ee3f-4bdc-8e35-6d79914d5694","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"phase_changed","at":"2026-02-28T23:56:49.552Z","payload":{"phase":"sentence_vote","phaseStartedAt":"2026-02-28T23:56:49.550Z","phaseDurationMs":20000}}
{"id":"385c66ab-05aa-476d-9a08-d8f449b92d0b","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"vote_closed","at":"2026-02-28T23:56:49.552Z","payload":{"pollType":"verdict","closedAt":"2026-02-28T23:56:49.550Z","votes":{},"nextPhase":"sentence_vote"}}
{"id":"8d7e50d8-9d83-4392-b37f-12e988465dd5","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"analytics_event","at":"2026-02-28T23:56:49.552Z","payload":{"name":"poll_closed","pollType":"verdict","phase":"sentence_vote"}}
{"id":"93ac58d3-4bde-480d-a1e4-4afc29ef7e1b","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"analytics_event","at":"2026-02-28T23:56:49.552Z","payload":{"name":"poll_started","pollType":"sentence","phase":"sentence_vote"}}
{"id":"2115fd61-24e0-470d-886b-05095420788f","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"broadcast_hook_triggered","at":"2026-02-28T23:56:49.552Z","payload":{"phase":"sentence_vote","hookType":"scene_switch","triggeredAt":"2026-02-28T23:56:49.552Z"}}
{"id":"b87698f4-3572-460e-8740-10b51901f916","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"turn","at":"2026-02-28T23:56:49.556Z","payload":{"turn":{"id":"0467d6cd-d473-4ef9-84e8-71df4a1e7d64","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","turnNumber":15,"speaker":"mux","role":"bailiff","phase":"sentence_vote","dialogue":"Sentence poll is now open. Options: Community service in the meme archives | Banished to the shadow realm | Mandatory apology haikus | Ethics training hosted by a raccoon | Ukulele ankle-monitor probation","createdAt":"2026-02-28T23:56:49.553Z"}}}
{"id":"e3ea9442-e784-4b22-a642-288a72ad9568","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"phase_changed","at":"2026-02-28T23:57:09.559Z","payload":{"phase":"final_ruling","phaseStartedAt":"2026-02-28T23:57:09.557Z","phaseDurationMs":20000}}
{"id":"cc1f534c-4959-480f-b5f0-d0569bb34e40","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"vote_closed","at":"2026-02-28T23:57:09.560Z","payload":{"pollType":"sentence","closedAt":"2026-02-28T23:57:09.557Z","votes":{},"nextPhase":"final_ruling"}}
{"id":"cca50b87-fae0-45bb-b444-928dff2f499e","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"analytics_event","at":"2026-02-28T23:57:09.560Z","payload":{"name":"poll_closed","pollType":"sentence","phase":"final_ruling"}}
{"id":"d6d7f41e-0035-475d-95d2-d0dbe51d506e","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"turn","at":"2026-02-28T23:57:09.697Z","payload":{"turn":{"id":"610a1807-5313-461f-8cea-3a054a1d9dc7","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","turnNumber":16,"speaker":"primus","role":"judge","phase":"final_ruling","dialogue":"On the charge of chaos in the first degree, this court finds the defendant dramatically guilty—with style points.","createdAt":"2026-02-28T23:57:09.693Z"}}}
{"id":"17bd6330-8c0d-47d8-895e-14604271e32b","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"render_directive","at":"2026-02-28T23:57:09.697Z","payload":{"directive":{"camera":"verdict","poses":{"judge":"talk"}},"turnId":"610a1807-5313-461f-8cea-3a054a1d9dc7","phase":"final_ruling","emittedAt":"2026-02-28T23:57:09.697Z"}}
{"id":"0f156e2b-6620-45b8-9bfc-c42fcdef375a","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"token_budget_applied","at":"2026-02-28T23:57:09.697Z","payload":{"turnId":"610a1807-5313-461f-8cea-3a054a1d9dc7","speaker":"primus","role":"judge","phase":"final_ruling","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"b27a8d2c-0481-42f1-ac1a-f8d74dd626a9","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"session_token_estimate","at":"2026-02-28T23:57:09.697Z","payload":{"turnId":"610a1807-5313-461f-8cea-3a054a1d9dc7","role":"judge","phase":"final_ruling","estimatedPromptTokens":3647,"estimatedCompletionTokens":280,"cumulativeEstimatedTokens":3927,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.007854}}
{"id":"954a4822-e654-4c60-a2d3-086c6499aa89","sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","type":"session_completed","at":"2026-02-28T23:57:09.701Z","payload":{"sessionId":"52fc7551-8762-4a55-83e9-5bcebe9b8b0b","completedAt":"2026-02-28T23:57:09.697Z"}}

View File

@@ -0,0 +1,32 @@
{"id":"069c12f8-e0af-49ba-9149-1077cb95a0f6","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"session_created","at":"2026-03-01T00:11:40.488Z","payload":{"sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff"}}
{"id":"4ec1b2d0-ae84-4274-ad66-f9588136f289","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"session_started","at":"2026-03-01T00:11:40.492Z","payload":{"sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","startedAt":"2026-03-01T00:11:40.489Z"}}
{"id":"effb8040-a767-4ee3-8f34-823d6e07213c","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"case_file_generated","at":"2026-03-01T00:11:40.492Z","payload":{"caseFile":{"title":"is the defendant guilty of freely farting on an airplane?","genre":"absurd_civil","caseType":"criminal","synopsis":"is the defendant guilty of freely farting on an airplane?","charges":["As stated in case prompt"],"witnesses":[],"evidence":[],"sentenceOptions":["Community service in the meme archives","Banished to the shadow realm","Mandatory apology haikus","Ethics training hosted by a raccoon","Ukulele ankle-monitor probation"]},"sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","generatedAt":"2026-03-01T00:11:40.492Z"}}
{"id":"aa9cd1a3-bf4d-4116-81f1-d9f1a997e1fb","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"phase_changed","at":"2026-03-01T00:11:40.500Z","payload":{"phase":"case_prompt","phaseStartedAt":"2026-03-01T00:11:40.498Z","phaseDurationMs":8000}}
{"id":"eeb897e7-83ae-4828-8c1f-c5a1266ba0fc","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"broadcast_hook_triggered","at":"2026-03-01T00:11:40.501Z","payload":{"phase":"case_prompt","hookType":"phase_stinger","triggeredAt":"2026-03-01T00:11:40.501Z"}}
{"id":"93c26719-9145-4d80-9aa4-070c6afba20a","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"turn","at":"2026-03-01T00:11:40.503Z","payload":{"turn":{"id":"20b09e96-0881-42b9-a5d6-8d603fe06eee","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","turnNumber":0,"speaker":"mux","role":"bailiff","phase":"case_prompt","dialogue":"All rise. The JuryRigged court is now in session. Case: is the defendant guilty of freely farting on an airplane?","createdAt":"2026-03-01T00:11:40.501Z"}}}
{"id":"efb2c144-fb8f-4878-b652-308089451ba8","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"phase_changed","at":"2026-03-01T00:11:41.707Z","payload":{"phase":"openings","phaseStartedAt":"2026-03-01T00:11:41.705Z","phaseDurationMs":30000}}
{"id":"f3229d2b-b217-4c2b-baba-5ed41aae74d6","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"turn","at":"2026-03-01T00:11:42.126Z","payload":{"turn":{"id":"5edb166d-337d-4ca5-a713-07c8a0be0664","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","turnNumber":1,"speaker":"subrosa","role":"prosecutor","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-03-01T00:11:42.123Z"}}}
{"id":"ae0e9372-a49a-4dda-b911-e6ab0af0e0d7","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"render_directive","at":"2026-03-01T00:11:42.127Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"5edb166d-337d-4ca5-a713-07c8a0be0664","phase":"openings","emittedAt":"2026-03-01T00:11:42.127Z"}}
{"id":"5f8ca5e9-c793-400d-b433-45ff2f59c118","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"token_budget_applied","at":"2026-03-01T00:11:42.127Z","payload":{"turnId":"5edb166d-337d-4ca5-a713-07c8a0be0664","speaker":"subrosa","role":"prosecutor","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"268e2906-b8ba-4236-ae13-1f995d3c0ab2","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"session_token_estimate","at":"2026-03-01T00:11:42.127Z","payload":{"turnId":"5edb166d-337d-4ca5-a713-07c8a0be0664","role":"prosecutor","phase":"openings","estimatedPromptTokens":146,"estimatedCompletionTokens":22,"cumulativeEstimatedTokens":168,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.000336}}
{"id":"ea706c24-c027-4e21-9baf-c2a7c133053a","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"turn","at":"2026-03-01T00:11:43.353Z","payload":{"turn":{"id":"f6f001d8-3825-411e-bcdc-94750e85596a","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","turnNumber":2,"speaker":"chora","role":"defense","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-03-01T00:11:43.350Z"}}}
{"id":"2f46fdc0-0788-430b-873d-fbd9e0de0488","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"render_directive","at":"2026-03-01T00:11:43.353Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"f6f001d8-3825-411e-bcdc-94750e85596a","phase":"openings","emittedAt":"2026-03-01T00:11:43.353Z"}}
{"id":"84018f4b-f09d-4fd3-9186-2f0582bea04d","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"token_budget_applied","at":"2026-03-01T00:11:43.353Z","payload":{"turnId":"f6f001d8-3825-411e-bcdc-94750e85596a","speaker":"chora","role":"defense","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"62a0e514-30be-44b9-b594-6866fd7124da","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"session_token_estimate","at":"2026-03-01T00:11:43.354Z","payload":{"turnId":"f6f001d8-3825-411e-bcdc-94750e85596a","role":"defense","phase":"openings","estimatedPromptTokens":306,"estimatedCompletionTokens":44,"cumulativeEstimatedTokens":350,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.0007}}
{"id":"0134e1ac-456b-4189-92fd-392404b1b47c","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"phase_changed","at":"2026-03-01T00:11:43.356Z","payload":{"phase":"witness_exam","phaseStartedAt":"2026-03-01T00:11:43.354Z","phaseDurationMs":40000}}
{"id":"755e8d8c-83db-46eb-bebd-26d3f42b8db9","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"turn","at":"2026-03-01T00:11:44.218Z","payload":{"turn":{"id":"977bf13c-d678-44c8-802d-2817b617ebe8","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","turnNumber":3,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-03-01T00:11:44.214Z"}}}
{"id":"e73cb61e-0101-4efe-8423-2fbb6713a8b7","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"render_directive","at":"2026-03-01T00:11:44.218Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"977bf13c-d678-44c8-802d-2817b617ebe8","phase":"witness_exam","emittedAt":"2026-03-01T00:11:44.218Z"}}
{"id":"2b90fa41-b970-4262-bc51-a1e64c8b48a9","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"token_budget_applied","at":"2026-03-01T00:11:44.218Z","payload":{"turnId":"977bf13c-d678-44c8-802d-2817b617ebe8","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"2b85e703-047d-4cc6-93e4-f0ec2f27a6b4","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"session_token_estimate","at":"2026-03-01T00:11:44.218Z","payload":{"turnId":"977bf13c-d678-44c8-802d-2817b617ebe8","role":"judge","phase":"witness_exam","estimatedPromptTokens":495,"estimatedCompletionTokens":64,"cumulativeEstimatedTokens":559,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001118}}
{"id":"ef0d6fd5-fc45-4f98-a30a-b7a655002689","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"turn","at":"2026-03-01T00:11:57.726Z","payload":{"turn":{"id":"d9f14d78-4b71-4bed-b6e1-fda8fbef5192","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","turnNumber":4,"speaker":"thaum","role":"witness_1","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-03-01T00:11:57.722Z"}}}
{"id":"58a9a61f-9d85-4975-afc9-dd9d626226f9","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"render_directive","at":"2026-03-01T00:11:57.726Z","payload":{"directive":{"camera":"witness","poses":{"witness_1":"talk"}},"turnId":"d9f14d78-4b71-4bed-b6e1-fda8fbef5192","phase":"witness_exam","emittedAt":"2026-03-01T00:11:57.726Z"}}
{"id":"23d15e6e-29b6-41e9-8f89-2b052afef692","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"witness_statement","at":"2026-03-01T00:11:57.726Z","payload":{"statement":{"witnessRole":"witness_1","agentId":"thaum","statementText":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","issuedAt":"2026-03-01T00:11:57.726Z"},"phase":"witness_exam","emittedAt":"2026-03-01T00:11:57.726Z"}}
{"id":"b6f48d8c-7b04-46e1-963f-46bc0c2205cf","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"token_budget_applied","at":"2026-03-01T00:11:57.726Z","payload":{"turnId":"d9f14d78-4b71-4bed-b6e1-fda8fbef5192","speaker":"thaum","role":"witness_1","phase":"witness_exam","requestedMaxTokens":90,"appliedMaxTokens":90,"roleMaxTokens":160,"source":"requested"}}
{"id":"6e2baf65-fc05-40f5-be90-35c3a69667ed","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"session_token_estimate","at":"2026-03-01T00:11:57.726Z","payload":{"turnId":"d9f14d78-4b71-4bed-b6e1-fda8fbef5192","role":"witness_1","phase":"witness_exam","estimatedPromptTokens":704,"estimatedCompletionTokens":84,"cumulativeEstimatedTokens":788,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001576}}
{"id":"c1871363-38a5-4926-ac88-b364fc7dd9b2","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"turn","at":"2026-03-01T00:12:16.484Z","payload":{"turn":{"id":"7b4ac9a8-2942-4f07-8700-5c53129fa471","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","turnNumber":5,"speaker":"subrosa","role":"prosecutor","phase":"witness_exam","dialogue":"Witness, you were halfasleep in a dim cabin and the aircrafts ventilation","createdAt":"2026-03-01T00:12:16.480Z"}}}
{"id":"85da2968-34b8-4640-9822-da6a0b0b4e7d","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"render_directive","at":"2026-03-01T00:12:16.484Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"7b4ac9a8-2942-4f07-8700-5c53129fa471","phase":"witness_exam","emittedAt":"2026-03-01T00:12:16.484Z"}}
{"id":"50fb9313-cb95-435a-9f01-3f61abcf41be","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"token_budget_applied","at":"2026-03-01T00:12:16.484Z","payload":{"turnId":"7b4ac9a8-2942-4f07-8700-5c53129fa471","speaker":"subrosa","role":"prosecutor","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"77d29947-96f2-460a-b300-f27753c5ba58","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"session_token_estimate","at":"2026-03-01T00:12:16.484Z","payload":{"turnId":"7b4ac9a8-2942-4f07-8700-5c53129fa471","role":"prosecutor","phase":"witness_exam","estimatedPromptTokens":933,"estimatedCompletionTokens":96,"cumulativeEstimatedTokens":1029,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.002058}}
{"id":"3fd20319-80e7-47e5-8758-cc53ed010c00","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"session_started","at":"2026-03-01T00:12:23.892Z","payload":{"sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","startedAt":"2026-03-01T00:11:40.489Z"}}
{"id":"cd248293-59ec-42c6-80e4-c3a2e9a7938a","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"case_file_generated","at":"2026-03-01T00:12:23.893Z","payload":{"caseFile":{"title":"is the defendant guilty of freely farting on an airplane?","genre":"absurd_civil","caseType":"criminal","synopsis":"is the defendant guilty of freely farting on an airplane?","charges":["As stated in case prompt"],"witnesses":[],"evidence":[],"sentenceOptions":["Community service in the meme archives","Banished to the shadow realm","Mandatory apology haikus","Ethics training hosted by a raccoon","Ukulele ankle-monitor probation"]},"sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","generatedAt":"2026-03-01T00:12:23.893Z"}}
{"id":"66261dde-ccca-45b3-bfb7-b93f68346f99","sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","type":"session_failed","at":"2026-03-01T00:12:23.900Z","payload":{"sessionId":"59827ffb-fa49-48a6-8fe5-eb34d712b4ff","reason":"Invalid phase transition: witness_exam -> case_prompt","completedAt":"2026-03-01T00:12:23.897Z"}}

View File

@@ -0,0 +1,77 @@
{"id":"3b36f4dd-8943-4ca4-9cfd-3ca7af4797fa","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"session_created","at":"2026-02-28T23:55:13.669Z","payload":{"sessionId":"6153ef56-2165-416e-b715-ad3e64400739"}}
{"id":"385eb86a-8633-4f4e-8ce1-c91ce82f8ffc","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"session_started","at":"2026-02-28T23:55:13.673Z","payload":{"sessionId":"6153ef56-2165-416e-b715-ad3e64400739","startedAt":"2026-02-28T23:55:13.670Z"}}
{"id":"f3fdba0a-d7d5-4d9f-b4bd-42c6ecc9da12","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"case_file_generated","at":"2026-02-28T23:55:13.673Z","payload":{"caseFile":{"title":"is the defendant guilty of freely farting on an airplane?","genre":"fantasy_court","caseType":"criminal","synopsis":"is the defendant guilty of freely farting on an airplane?","charges":["As stated in case prompt"],"witnesses":[],"evidence":[],"sentenceOptions":["Community service in the meme archives","Banished to the shadow realm","Mandatory apology haikus","Ethics training hosted by a raccoon","Ukulele ankle-monitor probation"]},"sessionId":"6153ef56-2165-416e-b715-ad3e64400739","generatedAt":"2026-02-28T23:55:13.673Z"}}
{"id":"45fda829-7944-4fed-a428-3e70629d072a","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"phase_changed","at":"2026-02-28T23:55:13.676Z","payload":{"phase":"case_prompt","phaseStartedAt":"2026-02-28T23:55:13.674Z","phaseDurationMs":8000}}
{"id":"22de41c4-6996-4820-b2f5-eb05c5fead59","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"broadcast_hook_triggered","at":"2026-02-28T23:55:13.677Z","payload":{"phase":"case_prompt","hookType":"phase_stinger","triggeredAt":"2026-02-28T23:55:13.677Z"}}
{"id":"01aef3c8-4346-4927-be9b-f5809cb88d57","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"turn","at":"2026-02-28T23:55:13.681Z","payload":{"turn":{"id":"51b823d3-014c-4f01-ada1-45fc01d6e31a","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","turnNumber":0,"speaker":"mux","role":"bailiff","phase":"case_prompt","dialogue":"All rise. The JuryRigged court is now in session. Case: is the defendant guilty of freely farting on an airplane?","createdAt":"2026-02-28T23:55:13.679Z"}}}
{"id":"a781ebe4-7263-4de7-9c5a-16d0c1634a16","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"phase_changed","at":"2026-02-28T23:55:14.886Z","payload":{"phase":"openings","phaseStartedAt":"2026-02-28T23:55:14.883Z","phaseDurationMs":30000}}
{"id":"afebbb08-9416-4bab-accd-6ade4bc15466","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"turn","at":"2026-02-28T23:55:15.001Z","payload":{"turn":{"id":"409dbaaf-70bb-4bce-a39b-0d360b343be3","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","turnNumber":1,"speaker":"subrosa","role":"prosecutor","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-02-28T23:55:14.998Z"}}}
{"id":"e06234ae-c01d-43b4-a6e4-1f361bbc5dcb","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"render_directive","at":"2026-02-28T23:55:15.002Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"409dbaaf-70bb-4bce-a39b-0d360b343be3","phase":"openings","emittedAt":"2026-02-28T23:55:15.002Z"}}
{"id":"1f887a20-0530-4e73-a4bf-dc3af6dc3d48","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"token_budget_applied","at":"2026-02-28T23:55:15.002Z","payload":{"turnId":"409dbaaf-70bb-4bce-a39b-0d360b343be3","speaker":"subrosa","role":"prosecutor","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"ca1acecb-2da3-4b5a-b0ea-4bc702a83f17","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"session_token_estimate","at":"2026-02-28T23:55:15.002Z","payload":{"turnId":"409dbaaf-70bb-4bce-a39b-0d360b343be3","role":"prosecutor","phase":"openings","estimatedPromptTokens":144,"estimatedCompletionTokens":22,"cumulativeEstimatedTokens":166,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.000332}}
{"id":"78a1055b-bfb7-434b-bb2d-dd8987627d7a","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"turn","at":"2026-02-28T23:55:15.928Z","payload":{"turn":{"id":"c6ef5d23-8670-4e08-84b6-71386bd26e09","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","turnNumber":2,"speaker":"chora","role":"defense","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-02-28T23:55:15.924Z"}}}
{"id":"e4a86a8c-b4c2-4aeb-ab17-fc2364622dcd","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"render_directive","at":"2026-02-28T23:55:15.929Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"c6ef5d23-8670-4e08-84b6-71386bd26e09","phase":"openings","emittedAt":"2026-02-28T23:55:15.929Z"}}
{"id":"a627d64f-6e85-4ec3-abbd-1178931b0c9e","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"token_budget_applied","at":"2026-02-28T23:55:15.929Z","payload":{"turnId":"c6ef5d23-8670-4e08-84b6-71386bd26e09","speaker":"chora","role":"defense","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"d91d7d34-6a91-4f68-a1fb-81647dd2bf06","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"session_token_estimate","at":"2026-02-28T23:55:15.929Z","payload":{"turnId":"c6ef5d23-8670-4e08-84b6-71386bd26e09","role":"defense","phase":"openings","estimatedPromptTokens":306,"estimatedCompletionTokens":44,"cumulativeEstimatedTokens":350,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.0007}}
{"id":"f8dacf37-7eec-4309-8f96-8c1a2b9aaedb","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"phase_changed","at":"2026-02-28T23:55:15.931Z","payload":{"phase":"witness_exam","phaseStartedAt":"2026-02-28T23:55:15.929Z","phaseDurationMs":40000}}
{"id":"d0acb2bb-5062-487d-bed3-b9929d79e39d","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"turn","at":"2026-02-28T23:55:16.565Z","payload":{"turn":{"id":"dca8be44-c819-4256-8797-a071080a52c6","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","turnNumber":3,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:55:16.562Z"}}}
{"id":"897f1c83-97ab-48c5-8e21-61b84e415b78","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"render_directive","at":"2026-02-28T23:55:16.565Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"dca8be44-c819-4256-8797-a071080a52c6","phase":"witness_exam","emittedAt":"2026-02-28T23:55:16.565Z"}}
{"id":"ed4c361f-e494-43bd-8717-d324fd0000fc","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"token_budget_applied","at":"2026-02-28T23:55:16.565Z","payload":{"turnId":"dca8be44-c819-4256-8797-a071080a52c6","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"6991f4ec-c172-4a47-867a-a511369f4c28","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"session_token_estimate","at":"2026-02-28T23:55:16.565Z","payload":{"turnId":"dca8be44-c819-4256-8797-a071080a52c6","role":"judge","phase":"witness_exam","estimatedPromptTokens":495,"estimatedCompletionTokens":64,"cumulativeEstimatedTokens":559,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001118}}
{"id":"51103515-98d1-4a3a-acb5-2a2cb4f56f26","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"turn","at":"2026-02-28T23:55:17.198Z","payload":{"turn":{"id":"e8f089ad-250c-4cc3-8edf-d78017c13c25","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","turnNumber":4,"speaker":"thaum","role":"witness_1","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:55:17.195Z"}}}
{"id":"916443c8-2137-49be-adb0-a8920148c237","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"render_directive","at":"2026-02-28T23:55:17.198Z","payload":{"directive":{"camera":"witness","poses":{"witness_1":"talk"}},"turnId":"e8f089ad-250c-4cc3-8edf-d78017c13c25","phase":"witness_exam","emittedAt":"2026-02-28T23:55:17.198Z"}}
{"id":"62325d76-0369-4121-9b40-ac07eb4e4e25","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"witness_statement","at":"2026-02-28T23:55:17.199Z","payload":{"statement":{"witnessRole":"witness_1","agentId":"thaum","statementText":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","issuedAt":"2026-02-28T23:55:17.199Z"},"phase":"witness_exam","emittedAt":"2026-02-28T23:55:17.199Z"}}
{"id":"c960d1f7-c9dd-4002-8c3f-644563a2917b","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"token_budget_applied","at":"2026-02-28T23:55:17.199Z","payload":{"turnId":"e8f089ad-250c-4cc3-8edf-d78017c13c25","speaker":"thaum","role":"witness_1","phase":"witness_exam","requestedMaxTokens":90,"appliedMaxTokens":90,"roleMaxTokens":160,"source":"requested"}}
{"id":"f90bbede-28bc-4f3e-8591-836ccc265ae2","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"session_token_estimate","at":"2026-02-28T23:55:17.199Z","payload":{"turnId":"e8f089ad-250c-4cc3-8edf-d78017c13c25","role":"witness_1","phase":"witness_exam","estimatedPromptTokens":704,"estimatedCompletionTokens":84,"cumulativeEstimatedTokens":788,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001576}}
{"id":"999e4ccd-d816-4c67-85ce-194022ea0fd9","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"turn","at":"2026-02-28T23:55:17.823Z","payload":{"turn":{"id":"11913c6c-3b3f-4953-83ef-26ad2e574a84","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","turnNumber":5,"speaker":"subrosa","role":"prosecutor","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:55:17.821Z"}}}
{"id":"85e81896-7b83-4d85-afe5-ae89782a39ea","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"render_directive","at":"2026-02-28T23:55:17.823Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"11913c6c-3b3f-4953-83ef-26ad2e574a84","phase":"witness_exam","emittedAt":"2026-02-28T23:55:17.823Z"}}
{"id":"947834cc-4519-4495-843d-44fcfe20aa38","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"token_budget_applied","at":"2026-02-28T23:55:17.823Z","payload":{"turnId":"11913c6c-3b3f-4953-83ef-26ad2e574a84","speaker":"subrosa","role":"prosecutor","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"f4fe466a-d64d-4f4d-a8df-ecfbdd70fe59","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"session_token_estimate","at":"2026-02-28T23:55:17.823Z","payload":{"turnId":"11913c6c-3b3f-4953-83ef-26ad2e574a84","role":"prosecutor","phase":"witness_exam","estimatedPromptTokens":931,"estimatedCompletionTokens":104,"cumulativeEstimatedTokens":1035,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00207}}
{"id":"12bfda6b-da7d-4910-a380-6be48d2cde98","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"turn","at":"2026-02-28T23:55:18.455Z","payload":{"turn":{"id":"b024fc0b-4504-4d45-836e-81afdb81c987","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","turnNumber":6,"speaker":"chora","role":"defense","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:55:18.451Z"}}}
{"id":"9c90ba5b-aa70-4799-bf81-b936f5c1e7f2","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"render_directive","at":"2026-02-28T23:55:18.455Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"b024fc0b-4504-4d45-836e-81afdb81c987","phase":"witness_exam","emittedAt":"2026-02-28T23:55:18.455Z"}}
{"id":"5530af5b-da21-4faf-a676-03ef5f302d24","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"token_budget_applied","at":"2026-02-28T23:55:18.455Z","payload":{"turnId":"b024fc0b-4504-4d45-836e-81afdb81c987","speaker":"chora","role":"defense","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"bc5d41c7-9bc0-4390-a0f0-84624b7f696e","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"session_token_estimate","at":"2026-02-28T23:55:18.455Z","payload":{"turnId":"b024fc0b-4504-4d45-836e-81afdb81c987","role":"defense","phase":"witness_exam","estimatedPromptTokens":1185,"estimatedCompletionTokens":124,"cumulativeEstimatedTokens":1309,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.002618}}
{"id":"4c6dd4e6-879d-4774-8ef1-e241dd214259","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"turn","at":"2026-02-28T23:55:19.284Z","payload":{"turn":{"id":"27b25aa4-9728-4998-a700-01806a30eea7","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","turnNumber":7,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:55:19.280Z"}}}
{"id":"d12b8778-6a28-4ea9-b4a5-672e4c8e035b","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"render_directive","at":"2026-02-28T23:55:19.284Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"27b25aa4-9728-4998-a700-01806a30eea7","phase":"witness_exam","emittedAt":"2026-02-28T23:55:19.284Z"}}
{"id":"c779c338-1b3e-40e5-9ea5-305d94c7011a","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"token_budget_applied","at":"2026-02-28T23:55:19.284Z","payload":{"turnId":"27b25aa4-9728-4998-a700-01806a30eea7","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"dec8aa63-0ec6-4d00-b51f-d196b9e6b8c2","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"session_token_estimate","at":"2026-02-28T23:55:19.284Z","payload":{"turnId":"27b25aa4-9728-4998-a700-01806a30eea7","role":"judge","phase":"witness_exam","estimatedPromptTokens":1462,"estimatedCompletionTokens":144,"cumulativeEstimatedTokens":1606,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.003212}}
{"id":"ac714a0f-34ec-416a-a810-7a29192074e2","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"turn","at":"2026-02-28T23:55:19.914Z","payload":{"turn":{"id":"3ef156fb-f0a8-40dd-b012-ccaad9784213","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","turnNumber":8,"speaker":"praxis","role":"witness_2","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:55:19.912Z"}}}
{"id":"affe6ff2-0c7c-48ac-a89a-85157007f20f","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"render_directive","at":"2026-02-28T23:55:19.914Z","payload":{"directive":{"camera":"witness","poses":{"witness_2":"talk"}},"turnId":"3ef156fb-f0a8-40dd-b012-ccaad9784213","phase":"witness_exam","emittedAt":"2026-02-28T23:55:19.914Z"}}
{"id":"737013ea-846d-4e6b-b154-775e814d3d43","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"witness_statement","at":"2026-02-28T23:55:19.914Z","payload":{"statement":{"witnessRole":"witness_2","agentId":"praxis","statementText":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","issuedAt":"2026-02-28T23:55:19.914Z"},"phase":"witness_exam","emittedAt":"2026-02-28T23:55:19.914Z"}}
{"id":"0047891e-ca97-49d4-b5c3-c3845c6759bc","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"token_budget_applied","at":"2026-02-28T23:55:19.914Z","payload":{"turnId":"3ef156fb-f0a8-40dd-b012-ccaad9784213","speaker":"praxis","role":"witness_2","phase":"witness_exam","requestedMaxTokens":90,"appliedMaxTokens":90,"roleMaxTokens":160,"source":"requested"}}
{"id":"120e3035-58e5-4501-b6b2-f60ec259a31e","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"session_token_estimate","at":"2026-02-28T23:55:19.914Z","payload":{"turnId":"3ef156fb-f0a8-40dd-b012-ccaad9784213","role":"witness_2","phase":"witness_exam","estimatedPromptTokens":1759,"estimatedCompletionTokens":164,"cumulativeEstimatedTokens":1923,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.003846}}
{"id":"17e55297-82fe-466c-84bf-862deb4c671f","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"turn","at":"2026-02-28T23:55:20.547Z","payload":{"turn":{"id":"7888b5b2-2d14-4e8b-8176-056977d07775","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","turnNumber":9,"speaker":"subrosa","role":"prosecutor","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:55:20.544Z"}}}
{"id":"45994d4e-a518-4456-9299-357bbe1193da","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"render_directive","at":"2026-02-28T23:55:20.547Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"7888b5b2-2d14-4e8b-8176-056977d07775","phase":"witness_exam","emittedAt":"2026-02-28T23:55:20.547Z"}}
{"id":"9b0f7f92-e0f1-4cc3-b447-2c1f005f9a62","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"token_budget_applied","at":"2026-02-28T23:55:20.547Z","payload":{"turnId":"7888b5b2-2d14-4e8b-8176-056977d07775","speaker":"subrosa","role":"prosecutor","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"7421f7a5-5ebe-4d19-8104-8968c75b483b","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"session_token_estimate","at":"2026-02-28T23:55:20.548Z","payload":{"turnId":"7888b5b2-2d14-4e8b-8176-056977d07775","role":"prosecutor","phase":"witness_exam","estimatedPromptTokens":2074,"estimatedCompletionTokens":184,"cumulativeEstimatedTokens":2258,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.004516}}
{"id":"e9f65513-464a-424e-a8ad-6cd0ca010c56","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"turn","at":"2026-02-28T23:55:21.173Z","payload":{"turn":{"id":"d710c6c2-d22b-49c5-afa2-ad44a6e38c16","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","turnNumber":10,"speaker":"chora","role":"defense","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:55:21.169Z"}}}
{"id":"c1cbc026-a345-4f97-83de-9e9e95226875","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"render_directive","at":"2026-02-28T23:55:21.173Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"d710c6c2-d22b-49c5-afa2-ad44a6e38c16","phase":"witness_exam","emittedAt":"2026-02-28T23:55:21.173Z"}}
{"id":"d8e2affa-7a05-4227-b8ff-91c873c9ca60","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"token_budget_applied","at":"2026-02-28T23:55:21.173Z","payload":{"turnId":"d710c6c2-d22b-49c5-afa2-ad44a6e38c16","speaker":"chora","role":"defense","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"7d49e130-b7bf-4128-81e9-de0f00d35e20","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"session_token_estimate","at":"2026-02-28T23:55:21.173Z","payload":{"turnId":"d710c6c2-d22b-49c5-afa2-ad44a6e38c16","role":"defense","phase":"witness_exam","estimatedPromptTokens":2392,"estimatedCompletionTokens":204,"cumulativeEstimatedTokens":2596,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.005192}}
{"id":"51382c83-2c63-44d4-aa32-62b1e274c9cc","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"turn","at":"2026-02-28T23:55:21.800Z","payload":{"turn":{"id":"638bc75a-b0cd-4f19-84c6-c27c76e51c88","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","turnNumber":11,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"Recap: Order in the court. I acknowledge the point and move us to the next absurdly important matter.","createdAt":"2026-02-28T23:55:21.796Z"}}}
{"id":"59aeb7bf-392f-4930-98a4-9877e40fb509","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"render_directive","at":"2026-02-28T23:55:21.800Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"638bc75a-b0cd-4f19-84c6-c27c76e51c88","phase":"witness_exam","emittedAt":"2026-02-28T23:55:21.800Z"}}
{"id":"7d6e7f16-eba3-4f87-b3ae-cf3b6ef62fa7","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"token_budget_applied","at":"2026-02-28T23:55:21.800Z","payload":{"turnId":"638bc75a-b0cd-4f19-84c6-c27c76e51c88","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"31c7f557-993d-41fd-b6b3-639acde9499a","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"session_token_estimate","at":"2026-02-28T23:55:21.800Z","payload":{"turnId":"638bc75a-b0cd-4f19-84c6-c27c76e51c88","role":"judge","phase":"witness_exam","estimatedPromptTokens":2713,"estimatedCompletionTokens":222,"cumulativeEstimatedTokens":2935,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00587}}
{"id":"5f3899b3-1b56-4111-8d20-06291b08cde6","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"judge_recap_emitted","at":"2026-02-28T23:55:21.804Z","payload":{"turnId":"638bc75a-b0cd-4f19-84c6-c27c76e51c88","phase":"witness_exam","cycleNumber":2}}
{"id":"1228ce1c-3f9a-4f8d-842d-695b97af4e80","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"phase_changed","at":"2026-02-28T23:55:22.609Z","payload":{"phase":"closings","phaseStartedAt":"2026-02-28T23:55:22.605Z","phaseDurationMs":30000}}
{"id":"057d8113-3e55-4f63-9c93-d4826b8b81e7","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"turn","at":"2026-02-28T23:55:22.633Z","payload":{"turn":{"id":"46df178e-8920-4c13-bc82-fdfb4981fe1e","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","turnNumber":12,"speaker":"subrosa","role":"prosecutor","phase":"closings","dialogue":"At the end of the day, this is either a crime or a spectacular misunderstanding involving glitter and plausible deniability.","createdAt":"2026-02-28T23:55:22.632Z"}}}
{"id":"51e1d92b-b3c3-4e2f-b2ff-c4391f780286","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"render_directive","at":"2026-02-28T23:55:22.633Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"46df178e-8920-4c13-bc82-fdfb4981fe1e","phase":"closings","emittedAt":"2026-02-28T23:55:22.633Z"}}
{"id":"c169bec2-48d9-4f38-9dd1-3352dd6e6f7d","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"token_budget_applied","at":"2026-02-28T23:55:22.633Z","payload":{"turnId":"46df178e-8920-4c13-bc82-fdfb4981fe1e","speaker":"subrosa","role":"prosecutor","phase":"closings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"797fa063-8e23-46e7-8a7c-266e05f16e75","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"session_token_estimate","at":"2026-02-28T23:55:22.633Z","payload":{"turnId":"46df178e-8920-4c13-bc82-fdfb4981fe1e","role":"prosecutor","phase":"closings","estimatedPromptTokens":3025,"estimatedCompletionTokens":242,"cumulativeEstimatedTokens":3267,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.006534}}
{"id":"bdcdc87a-7eb3-4c88-97e4-432f781e9046","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"turn","at":"2026-02-28T23:55:23.466Z","payload":{"turn":{"id":"4ae1a95a-1dde-4c58-aa0c-8bd8c9688269","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","turnNumber":13,"speaker":"chora","role":"defense","phase":"closings","dialogue":"At the end of the day, this is either a crime or a spectacular misunderstanding involving glitter and plausible deniability.","createdAt":"2026-02-28T23:55:23.464Z"}}}
{"id":"a072cab2-78dd-4103-952b-cd2a367f287c","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"render_directive","at":"2026-02-28T23:55:23.467Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"4ae1a95a-1dde-4c58-aa0c-8bd8c9688269","phase":"closings","emittedAt":"2026-02-28T23:55:23.467Z"}}
{"id":"181be041-45a8-4226-8e33-e0c671a32528","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"token_budget_applied","at":"2026-02-28T23:55:23.467Z","payload":{"turnId":"4ae1a95a-1dde-4c58-aa0c-8bd8c9688269","speaker":"chora","role":"defense","phase":"closings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"c8967650-186d-403d-8103-dec058b1a3df","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"session_token_estimate","at":"2026-02-28T23:55:23.467Z","payload":{"turnId":"4ae1a95a-1dde-4c58-aa0c-8bd8c9688269","role":"defense","phase":"closings","estimatedPromptTokens":3336,"estimatedCompletionTokens":262,"cumulativeEstimatedTokens":3598,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.007196}}
{"id":"f0fdef86-04d9-44bd-baa7-3ac895002099","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"phase_changed","at":"2026-02-28T23:55:23.470Z","payload":{"phase":"verdict_vote","phaseStartedAt":"2026-02-28T23:55:23.468Z","phaseDurationMs":20000}}
{"id":"fab79a1e-a248-425d-b6f2-b0a51099effc","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"analytics_event","at":"2026-02-28T23:55:23.470Z","payload":{"name":"poll_started","pollType":"verdict","phase":"verdict_vote"}}
{"id":"d0d1d793-daeb-4d17-a2e5-26ada07c520d","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"broadcast_hook_triggered","at":"2026-02-28T23:55:23.470Z","payload":{"phase":"verdict_vote","hookType":"scene_switch","triggeredAt":"2026-02-28T23:55:23.470Z"}}
{"id":"a6cb5623-a7ef-4b59-bb59-21510c9e16d1","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"turn","at":"2026-02-28T23:55:23.474Z","payload":{"turn":{"id":"189e6a43-ac2c-4077-b7e4-1fc20d4e6a15","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","turnNumber":14,"speaker":"mux","role":"bailiff","phase":"verdict_vote","dialogue":"Jury poll is open: guilty / not_guilty. Cast your votes now.","createdAt":"2026-02-28T23:55:23.471Z"}}}
{"id":"19138bd6-1f06-4efa-9d4b-e06ea7b434e0","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"phase_changed","at":"2026-02-28T23:55:43.479Z","payload":{"phase":"sentence_vote","phaseStartedAt":"2026-02-28T23:55:43.476Z","phaseDurationMs":20000}}
{"id":"96b13906-44ca-4ea2-bf6c-7f6c4c2fbbd7","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"vote_closed","at":"2026-02-28T23:55:43.479Z","payload":{"pollType":"verdict","closedAt":"2026-02-28T23:55:43.476Z","votes":{},"nextPhase":"sentence_vote"}}
{"id":"2cd2dd78-cdec-447c-86d6-e54ce7168f5d","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"analytics_event","at":"2026-02-28T23:55:43.479Z","payload":{"name":"poll_closed","pollType":"verdict","phase":"sentence_vote"}}
{"id":"b07f0dde-b94b-4416-af24-5b5230b1bf0c","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"analytics_event","at":"2026-02-28T23:55:43.479Z","payload":{"name":"poll_started","pollType":"sentence","phase":"sentence_vote"}}
{"id":"84b6ea69-2bdf-4e21-9269-16186fb90dbd","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"broadcast_hook_triggered","at":"2026-02-28T23:55:43.479Z","payload":{"phase":"sentence_vote","hookType":"scene_switch","triggeredAt":"2026-02-28T23:55:43.479Z"}}
{"id":"fe0dd474-cabb-4f26-b9ec-7e86e2bfe0ae","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"turn","at":"2026-02-28T23:55:43.481Z","payload":{"turn":{"id":"b93ed632-485d-4c11-bce1-661d8ce061f0","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","turnNumber":15,"speaker":"mux","role":"bailiff","phase":"sentence_vote","dialogue":"Sentence poll is now open. Options: Community service in the meme archives | Banished to the shadow realm | Mandatory apology haikus | Ethics training hosted by a raccoon | Ukulele ankle-monitor probation","createdAt":"2026-02-28T23:55:43.480Z"}}}
{"id":"9ebf5526-efef-4149-87ce-affceb4b0298","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"session_started","at":"2026-02-28T23:56:00.405Z","payload":{"sessionId":"6153ef56-2165-416e-b715-ad3e64400739","startedAt":"2026-02-28T23:55:13.670Z"}}
{"id":"512125ae-1c14-4134-bf2b-3863c33c262c","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"case_file_generated","at":"2026-02-28T23:56:00.405Z","payload":{"caseFile":{"title":"is the defendant guilty of freely farting on an airplane?","genre":"fantasy_court","caseType":"criminal","synopsis":"is the defendant guilty of freely farting on an airplane?","charges":["As stated in case prompt"],"witnesses":[],"evidence":[],"sentenceOptions":["Community service in the meme archives","Banished to the shadow realm","Mandatory apology haikus","Ethics training hosted by a raccoon","Ukulele ankle-monitor probation"]},"sessionId":"6153ef56-2165-416e-b715-ad3e64400739","generatedAt":"2026-02-28T23:56:00.405Z"}}
{"id":"f50f157a-8d50-4a6c-af7a-429cce632a94","sessionId":"6153ef56-2165-416e-b715-ad3e64400739","type":"session_failed","at":"2026-02-28T23:56:00.412Z","payload":{"sessionId":"6153ef56-2165-416e-b715-ad3e64400739","reason":"Invalid phase transition: sentence_vote -> case_prompt","completedAt":"2026-02-28T23:56:00.409Z"}}

View File

@@ -0,0 +1,82 @@
{"id":"490db2f1-da3e-411e-a6b8-f36c0c32813d","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"session_created","at":"2026-02-28T23:22:39.576Z","payload":{"sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98"}}
{"id":"862645c3-c2ec-4f23-b03a-70c21272a1e0","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"session_started","at":"2026-02-28T23:22:39.577Z","payload":{"sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","startedAt":"2026-02-28T23:22:39.577Z"}}
{"id":"7f55d437-5288-432d-b89b-8c13f8681639","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"case_file_generated","at":"2026-02-28T23:22:39.578Z","payload":{"caseFile":{"title":"Did the bailiff eat the evidence?","genre":"workplace_tribunal","caseType":"civil","synopsis":"Did the bailiff eat the evidence?","charges":["Damages as alleged"],"witnesses":[],"evidence":[],"sentenceOptions":["Community service in the meme archives","Banished to the shadow realm","Mandatory apology haikus","Ethics training hosted by a raccoon","Ukulele ankle-monitor probation"]},"sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","generatedAt":"2026-02-28T23:22:39.578Z"}}
{"id":"db677996-868b-4cd2-b369-c49f9db650ae","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"phase_changed","at":"2026-02-28T23:22:39.578Z","payload":{"phase":"case_prompt","phaseStartedAt":"2026-02-28T23:22:39.578Z","phaseDurationMs":8000}}
{"id":"f5d9eeb2-35cc-4091-9fd6-677887db725b","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"broadcast_hook_triggered","at":"2026-02-28T23:22:39.578Z","payload":{"phase":"case_prompt","hookType":"phase_stinger","triggeredAt":"2026-02-28T23:22:39.578Z"}}
{"id":"beb21d17-1434-4ce6-a5ac-735ecacea695","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"turn","at":"2026-02-28T23:22:39.578Z","payload":{"turn":{"id":"da3e0fdb-3c59-4474-8205-2871653ca86e","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","turnNumber":0,"speaker":"mux","role":"bailiff","phase":"case_prompt","dialogue":"All rise. The JuryRigged court is now in session. Case: Did the bailiff eat the evidence?","createdAt":"2026-02-28T23:22:39.578Z"}}}
{"id":"166533e4-317b-4d63-872e-62f585c077eb","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"phase_changed","at":"2026-02-28T23:22:40.779Z","payload":{"phase":"openings","phaseStartedAt":"2026-02-28T23:22:40.779Z","phaseDurationMs":30000}}
{"id":"372d3842-fba0-4603-ae13-d0226e6fbf53","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"turn","at":"2026-02-28T23:22:40.780Z","payload":{"turn":{"id":"135d0d76-469b-4aea-a307-9c1db6ad5829","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","turnNumber":1,"speaker":"subrosa","role":"prosecutor","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-02-28T23:22:40.780Z"}}}
{"id":"a4eb45f7-ea8f-4fad-b8f3-40177f19c650","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"render_directive","at":"2026-02-28T23:22:40.780Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"135d0d76-469b-4aea-a307-9c1db6ad5829","phase":"openings","emittedAt":"2026-02-28T23:22:40.780Z"}}
{"id":"b7822830-e98c-4565-bdb8-092648d862d2","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"token_budget_applied","at":"2026-02-28T23:22:40.780Z","payload":{"turnId":"135d0d76-469b-4aea-a307-9c1db6ad5829","speaker":"subrosa","role":"prosecutor","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"e2f2a0f8-df36-4e63-b35c-8f9f293ea0f2","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"session_token_estimate","at":"2026-02-28T23:22:40.780Z","payload":{"turnId":"135d0d76-469b-4aea-a307-9c1db6ad5829","role":"prosecutor","phase":"openings","estimatedPromptTokens":137,"estimatedCompletionTokens":22,"cumulativeEstimatedTokens":159,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.000318}}
{"id":"1cbd18bf-b949-4d6e-b461-5663af3f496b","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"turn","at":"2026-02-28T23:22:41.680Z","payload":{"turn":{"id":"2c92c14a-031a-4bdd-8e92-0650b9919c0c","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","turnNumber":2,"speaker":"chora","role":"defense","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-02-28T23:22:41.680Z"}}}
{"id":"ee065126-555f-4090-b731-3e1294c3377a","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"render_directive","at":"2026-02-28T23:22:41.680Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"2c92c14a-031a-4bdd-8e92-0650b9919c0c","phase":"openings","emittedAt":"2026-02-28T23:22:41.680Z"}}
{"id":"946679c3-3f1f-4599-ab8e-fd3d5b9d4470","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"token_budget_applied","at":"2026-02-28T23:22:41.680Z","payload":{"turnId":"2c92c14a-031a-4bdd-8e92-0650b9919c0c","speaker":"chora","role":"defense","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"bcc10b8f-92f6-4d1d-9c58-9df5eacfd88a","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"session_token_estimate","at":"2026-02-28T23:22:41.680Z","payload":{"turnId":"2c92c14a-031a-4bdd-8e92-0650b9919c0c","role":"defense","phase":"openings","estimatedPromptTokens":291,"estimatedCompletionTokens":44,"cumulativeEstimatedTokens":335,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00067}}
{"id":"c89b64d0-2975-4321-a1e2-142e39f7c7af","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"phase_changed","at":"2026-02-28T23:22:41.680Z","payload":{"phase":"witness_exam","phaseStartedAt":"2026-02-28T23:22:41.680Z","phaseDurationMs":40000}}
{"id":"01cac632-df57-4bb6-a39e-dac0364c6afe","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"turn","at":"2026-02-28T23:22:42.281Z","payload":{"turn":{"id":"94f5fdb9-2f52-4fc7-b999-90f2fa28ad32","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","turnNumber":3,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:22:42.281Z"}}}
{"id":"196dd62a-c9ea-49a5-bccf-855ad2e8cfac","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"render_directive","at":"2026-02-28T23:22:42.281Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"94f5fdb9-2f52-4fc7-b999-90f2fa28ad32","phase":"witness_exam","emittedAt":"2026-02-28T23:22:42.281Z"}}
{"id":"ac24316b-8b52-4bc8-9c61-a7b477dc8ee9","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"token_budget_applied","at":"2026-02-28T23:22:42.281Z","payload":{"turnId":"94f5fdb9-2f52-4fc7-b999-90f2fa28ad32","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"e0c0b0b9-8a95-479a-91ec-5889c5edbc96","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"session_token_estimate","at":"2026-02-28T23:22:42.281Z","payload":{"turnId":"94f5fdb9-2f52-4fc7-b999-90f2fa28ad32","role":"judge","phase":"witness_exam","estimatedPromptTokens":473,"estimatedCompletionTokens":64,"cumulativeEstimatedTokens":537,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001074}}
{"id":"e6bb9dc4-2872-4ea0-a1f7-4cbb455585cc","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"turn","at":"2026-02-28T23:22:42.881Z","payload":{"turn":{"id":"3ae3d2cd-1300-4837-b39c-c3bb20ea0276","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","turnNumber":4,"speaker":"thaum","role":"witness_1","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:22:42.881Z"}}}
{"id":"9db6cc36-9ba2-4df4-b0e0-72e862c2a900","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"render_directive","at":"2026-02-28T23:22:42.881Z","payload":{"directive":{"camera":"witness","poses":{"witness_1":"talk"}},"turnId":"3ae3d2cd-1300-4837-b39c-c3bb20ea0276","phase":"witness_exam","emittedAt":"2026-02-28T23:22:42.881Z"}}
{"id":"d3c79e84-7ab5-43a4-ab17-d4990c45a8cb","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"witness_statement","at":"2026-02-28T23:22:42.882Z","payload":{"statement":{"witnessRole":"witness_1","agentId":"thaum","statementText":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","issuedAt":"2026-02-28T23:22:42.881Z"},"phase":"witness_exam","emittedAt":"2026-02-28T23:22:42.882Z"}}
{"id":"7ddee286-214e-4688-ab0c-7ac70d8ddd2d","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"token_budget_applied","at":"2026-02-28T23:22:42.882Z","payload":{"turnId":"3ae3d2cd-1300-4837-b39c-c3bb20ea0276","speaker":"thaum","role":"witness_1","phase":"witness_exam","requestedMaxTokens":90,"appliedMaxTokens":90,"roleMaxTokens":160,"source":"requested"}}
{"id":"96b3c978-9631-47b8-8767-e896b2136e55","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"session_token_estimate","at":"2026-02-28T23:22:42.882Z","payload":{"turnId":"3ae3d2cd-1300-4837-b39c-c3bb20ea0276","role":"witness_1","phase":"witness_exam","estimatedPromptTokens":678,"estimatedCompletionTokens":84,"cumulativeEstimatedTokens":762,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001524}}
{"id":"69d09562-b743-4858-bfee-a0d9d903a7df","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"turn","at":"2026-02-28T23:22:43.482Z","payload":{"turn":{"id":"b4e9d5f8-4644-49dc-8a07-5bd448766db1","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","turnNumber":5,"speaker":"subrosa","role":"prosecutor","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:22:43.482Z"}}}
{"id":"fc8e4a1e-6b78-4b5e-b5a9-c0e7b167e034","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"render_directive","at":"2026-02-28T23:22:43.482Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"b4e9d5f8-4644-49dc-8a07-5bd448766db1","phase":"witness_exam","emittedAt":"2026-02-28T23:22:43.482Z"}}
{"id":"b11b3b44-d46f-411b-91d5-4ae2eae0deb3","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"token_budget_applied","at":"2026-02-28T23:22:43.482Z","payload":{"turnId":"b4e9d5f8-4644-49dc-8a07-5bd448766db1","speaker":"subrosa","role":"prosecutor","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"c215ceb3-0821-43a0-8e6e-4410e0ca0f62","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"session_token_estimate","at":"2026-02-28T23:22:43.482Z","payload":{"turnId":"b4e9d5f8-4644-49dc-8a07-5bd448766db1","role":"prosecutor","phase":"witness_exam","estimatedPromptTokens":898,"estimatedCompletionTokens":104,"cumulativeEstimatedTokens":1002,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.002004}}
{"id":"364626f4-2499-4b5f-8a53-cd0163432aa0","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"turn","at":"2026-02-28T23:22:44.082Z","payload":{"turn":{"id":"1138ed75-5100-4149-b5b3-f02d6ce7e3e6","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","turnNumber":6,"speaker":"chora","role":"defense","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:22:44.082Z"}}}
{"id":"5c64c365-c4af-4494-b151-5209dcba3e64","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"render_directive","at":"2026-02-28T23:22:44.082Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"1138ed75-5100-4149-b5b3-f02d6ce7e3e6","phase":"witness_exam","emittedAt":"2026-02-28T23:22:44.082Z"}}
{"id":"144c44a2-1e64-4669-9d61-2695c3411a0a","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"token_budget_applied","at":"2026-02-28T23:22:44.082Z","payload":{"turnId":"1138ed75-5100-4149-b5b3-f02d6ce7e3e6","speaker":"chora","role":"defense","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"c0490ca0-52ce-4d79-968a-4a7b40fafac0","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"session_token_estimate","at":"2026-02-28T23:22:44.082Z","payload":{"turnId":"1138ed75-5100-4149-b5b3-f02d6ce7e3e6","role":"defense","phase":"witness_exam","estimatedPromptTokens":1144,"estimatedCompletionTokens":124,"cumulativeEstimatedTokens":1268,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.002536}}
{"id":"88fd0f94-62aa-4525-a6fb-93936d74fdf1","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"turn","at":"2026-02-28T23:22:44.882Z","payload":{"turn":{"id":"5b85148c-46fd-49da-beb2-7f2b75cbc9db","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","turnNumber":7,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:22:44.882Z"}}}
{"id":"090ec1ef-a3eb-46be-addc-b293e8f610d4","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"render_directive","at":"2026-02-28T23:22:44.883Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"5b85148c-46fd-49da-beb2-7f2b75cbc9db","phase":"witness_exam","emittedAt":"2026-02-28T23:22:44.883Z"}}
{"id":"4d5661bc-9a48-40e3-8633-665cc8e74424","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"token_budget_applied","at":"2026-02-28T23:22:44.883Z","payload":{"turnId":"5b85148c-46fd-49da-beb2-7f2b75cbc9db","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"d6914f40-7606-4f88-b6b4-ab7c8fcf02cc","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"session_token_estimate","at":"2026-02-28T23:22:44.883Z","payload":{"turnId":"5b85148c-46fd-49da-beb2-7f2b75cbc9db","role":"judge","phase":"witness_exam","estimatedPromptTokens":1414,"estimatedCompletionTokens":144,"cumulativeEstimatedTokens":1558,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.003116}}
{"id":"0cfecd6f-8721-4f22-9cb5-709eb99732d7","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"turn","at":"2026-02-28T23:22:45.483Z","payload":{"turn":{"id":"077c6ca6-b15a-4e9c-bc76-739ef989e390","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","turnNumber":8,"speaker":"praxis","role":"witness_2","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:22:45.483Z"}}}
{"id":"84f2fd44-e4ab-471d-bf6c-4e9188894fa8","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"render_directive","at":"2026-02-28T23:22:45.483Z","payload":{"directive":{"camera":"witness","poses":{"witness_2":"talk"}},"turnId":"077c6ca6-b15a-4e9c-bc76-739ef989e390","phase":"witness_exam","emittedAt":"2026-02-28T23:22:45.483Z"}}
{"id":"a5639511-2029-4648-a2ee-fd84b75de793","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"witness_statement","at":"2026-02-28T23:22:45.483Z","payload":{"statement":{"witnessRole":"witness_2","agentId":"praxis","statementText":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","issuedAt":"2026-02-28T23:22:45.483Z"},"phase":"witness_exam","emittedAt":"2026-02-28T23:22:45.483Z"}}
{"id":"28d418d3-dd23-46fc-ae3d-b16713848673","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"token_budget_applied","at":"2026-02-28T23:22:45.483Z","payload":{"turnId":"077c6ca6-b15a-4e9c-bc76-739ef989e390","speaker":"praxis","role":"witness_2","phase":"witness_exam","requestedMaxTokens":90,"appliedMaxTokens":90,"roleMaxTokens":160,"source":"requested"}}
{"id":"4cf805a6-2530-4047-98dd-d432e6a00b13","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"session_token_estimate","at":"2026-02-28T23:22:45.483Z","payload":{"turnId":"077c6ca6-b15a-4e9c-bc76-739ef989e390","role":"witness_2","phase":"witness_exam","estimatedPromptTokens":1707,"estimatedCompletionTokens":164,"cumulativeEstimatedTokens":1871,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.003742}}
{"id":"f5df31f0-743c-4c1d-94d0-77e85367c70c","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"turn","at":"2026-02-28T23:22:46.083Z","payload":{"turn":{"id":"ea620d67-bc81-4042-9c0e-bd261654140c","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","turnNumber":9,"speaker":"subrosa","role":"prosecutor","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:22:46.083Z"}}}
{"id":"9c666eed-25e9-464d-9ebf-1c22a5211442","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"render_directive","at":"2026-02-28T23:22:46.083Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"ea620d67-bc81-4042-9c0e-bd261654140c","phase":"witness_exam","emittedAt":"2026-02-28T23:22:46.083Z"}}
{"id":"3a02b8f2-0d5d-4219-8822-3d3cd9fa8669","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"token_budget_applied","at":"2026-02-28T23:22:46.083Z","payload":{"turnId":"ea620d67-bc81-4042-9c0e-bd261654140c","speaker":"subrosa","role":"prosecutor","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"f9623cea-5b9b-4641-9efd-f1f9488f16e6","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"session_token_estimate","at":"2026-02-28T23:22:46.084Z","payload":{"turnId":"ea620d67-bc81-4042-9c0e-bd261654140c","role":"prosecutor","phase":"witness_exam","estimatedPromptTokens":2015,"estimatedCompletionTokens":184,"cumulativeEstimatedTokens":2199,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.004398}}
{"id":"05ed4ff7-53e4-4328-89df-a9c3e1d0226b","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"turn","at":"2026-02-28T23:22:46.684Z","payload":{"turn":{"id":"ee4fba65-6b08-47f8-8472-dd093e258648","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","turnNumber":10,"speaker":"chora","role":"defense","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:22:46.684Z"}}}
{"id":"31b62023-9d86-4f57-a89e-1db825821c84","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"render_directive","at":"2026-02-28T23:22:46.684Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"ee4fba65-6b08-47f8-8472-dd093e258648","phase":"witness_exam","emittedAt":"2026-02-28T23:22:46.684Z"}}
{"id":"0f67d056-6f52-4b85-89e1-e54cf6798ce8","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"token_budget_applied","at":"2026-02-28T23:22:46.684Z","payload":{"turnId":"ee4fba65-6b08-47f8-8472-dd093e258648","speaker":"chora","role":"defense","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"f83a2fa2-62be-4ae6-a4ca-edb33710cf50","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"session_token_estimate","at":"2026-02-28T23:22:46.684Z","payload":{"turnId":"ee4fba65-6b08-47f8-8472-dd093e258648","role":"defense","phase":"witness_exam","estimatedPromptTokens":2325,"estimatedCompletionTokens":204,"cumulativeEstimatedTokens":2529,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.005058}}
{"id":"2661c953-565a-4cba-a015-ac1ad345f849","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"turn","at":"2026-02-28T23:22:47.284Z","payload":{"turn":{"id":"662878be-a5c7-432f-af9f-ae3337017e31","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","turnNumber":11,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"Recap: Order in the court. I acknowledge the point and move us to the next absurdly important matter.","createdAt":"2026-02-28T23:22:47.284Z"}}}
{"id":"f3de8098-eb64-4d53-8697-dcc0968738bc","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"render_directive","at":"2026-02-28T23:22:47.284Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"662878be-a5c7-432f-af9f-ae3337017e31","phase":"witness_exam","emittedAt":"2026-02-28T23:22:47.284Z"}}
{"id":"0153b15f-c320-4384-8db2-6978d4d1ca8f","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"token_budget_applied","at":"2026-02-28T23:22:47.284Z","payload":{"turnId":"662878be-a5c7-432f-af9f-ae3337017e31","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"4ca59758-cfb8-455a-b3f9-5f4b770b179d","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"session_token_estimate","at":"2026-02-28T23:22:47.284Z","payload":{"turnId":"662878be-a5c7-432f-af9f-ae3337017e31","role":"judge","phase":"witness_exam","estimatedPromptTokens":2639,"estimatedCompletionTokens":222,"cumulativeEstimatedTokens":2861,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.005722}}
{"id":"6103c5f2-8ba5-4ee6-9f8e-16430982ab63","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"judge_recap_emitted","at":"2026-02-28T23:22:47.284Z","payload":{"turnId":"662878be-a5c7-432f-af9f-ae3337017e31","phase":"witness_exam","cycleNumber":2}}
{"id":"c28b7277-8d12-45ee-947c-8ed2a24b4c70","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"phase_changed","at":"2026-02-28T23:22:48.085Z","payload":{"phase":"closings","phaseStartedAt":"2026-02-28T23:22:48.085Z","phaseDurationMs":30000}}
{"id":"17cbc3ad-0e19-47cd-b71c-47ec0e3143a1","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"turn","at":"2026-02-28T23:22:48.085Z","payload":{"turn":{"id":"3f0c8bf0-2987-4acf-9a12-7e784e6d0614","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","turnNumber":12,"speaker":"subrosa","role":"prosecutor","phase":"closings","dialogue":"At the end of the day, this is either a crime or a spectacular misunderstanding involving glitter and plausible deniability.","createdAt":"2026-02-28T23:22:48.085Z"}}}
{"id":"f4422249-45fa-4ca2-a113-dc9814d877e6","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"render_directive","at":"2026-02-28T23:22:48.085Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"3f0c8bf0-2987-4acf-9a12-7e784e6d0614","phase":"closings","emittedAt":"2026-02-28T23:22:48.085Z"}}
{"id":"95ab2d71-61be-4f1c-b119-61c2713a8a2c","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"token_budget_applied","at":"2026-02-28T23:22:48.085Z","payload":{"turnId":"3f0c8bf0-2987-4acf-9a12-7e784e6d0614","speaker":"subrosa","role":"prosecutor","phase":"closings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"d83dadd7-fb51-42b9-89c0-2e84031531cd","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"session_token_estimate","at":"2026-02-28T23:22:48.085Z","payload":{"turnId":"3f0c8bf0-2987-4acf-9a12-7e784e6d0614","role":"prosecutor","phase":"closings","estimatedPromptTokens":2944,"estimatedCompletionTokens":242,"cumulativeEstimatedTokens":3186,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.006372}}
{"id":"d998bd03-5202-4bbb-895c-4ff80773c590","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"turn","at":"2026-02-28T23:22:48.885Z","payload":{"turn":{"id":"0b7b79d5-19f6-48a2-9845-d4f07a6fd807","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","turnNumber":13,"speaker":"chora","role":"defense","phase":"closings","dialogue":"At the end of the day, this is either a crime or a spectacular misunderstanding involving glitter and plausible deniability.","createdAt":"2026-02-28T23:22:48.885Z"}}}
{"id":"5bbaf928-1735-4f8a-8e0f-9d637f2e648c","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"render_directive","at":"2026-02-28T23:22:48.885Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"0b7b79d5-19f6-48a2-9845-d4f07a6fd807","phase":"closings","emittedAt":"2026-02-28T23:22:48.885Z"}}
{"id":"8611d536-88cd-4bc3-ab32-b4e3a54263c7","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"token_budget_applied","at":"2026-02-28T23:22:48.885Z","payload":{"turnId":"0b7b79d5-19f6-48a2-9845-d4f07a6fd807","speaker":"chora","role":"defense","phase":"closings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"a6b6130c-02d1-4a3b-a95a-8ae100f91a0c","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"session_token_estimate","at":"2026-02-28T23:22:48.885Z","payload":{"turnId":"0b7b79d5-19f6-48a2-9845-d4f07a6fd807","role":"defense","phase":"closings","estimatedPromptTokens":3247,"estimatedCompletionTokens":262,"cumulativeEstimatedTokens":3509,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.007018}}
{"id":"bac98a73-a7f1-402a-8b88-4db94e65d9e5","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"phase_changed","at":"2026-02-28T23:22:48.885Z","payload":{"phase":"verdict_vote","phaseStartedAt":"2026-02-28T23:22:48.885Z","phaseDurationMs":20000}}
{"id":"67d80287-5b70-4c6b-a119-5751c9c7feb6","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"analytics_event","at":"2026-02-28T23:22:48.885Z","payload":{"name":"poll_started","pollType":"verdict","phase":"verdict_vote"}}
{"id":"37ad6757-04ad-44e8-a925-e6a9774747bd","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"broadcast_hook_triggered","at":"2026-02-28T23:22:48.885Z","payload":{"phase":"verdict_vote","hookType":"scene_switch","triggeredAt":"2026-02-28T23:22:48.885Z"}}
{"id":"bb740633-b391-4af9-9f7e-342fca3aae99","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"turn","at":"2026-02-28T23:22:48.885Z","payload":{"turn":{"id":"10a318fd-0031-4d65-96f3-ad40f3af031c","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","turnNumber":14,"speaker":"mux","role":"bailiff","phase":"verdict_vote","dialogue":"Jury poll is open: liable / not_liable. Cast your votes now.","createdAt":"2026-02-28T23:22:48.885Z"}}}
{"id":"f58c8cbc-2e56-4920-8b93-7629316d5726","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"phase_changed","at":"2026-02-28T23:23:08.885Z","payload":{"phase":"sentence_vote","phaseStartedAt":"2026-02-28T23:23:08.885Z","phaseDurationMs":20000}}
{"id":"dc0be831-9000-43e6-82dd-c4506e6cda84","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"vote_closed","at":"2026-02-28T23:23:08.885Z","payload":{"pollType":"verdict","closedAt":"2026-02-28T23:23:08.885Z","votes":{},"nextPhase":"sentence_vote"}}
{"id":"71e1c431-fa37-44e9-b5e0-5c21c91cc6e3","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"analytics_event","at":"2026-02-28T23:23:08.885Z","payload":{"name":"poll_closed","pollType":"verdict","phase":"sentence_vote"}}
{"id":"adeab7ff-1fc5-4221-9612-affa9e7229a2","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"analytics_event","at":"2026-02-28T23:23:08.885Z","payload":{"name":"poll_started","pollType":"sentence","phase":"sentence_vote"}}
{"id":"ab1e04bf-ced3-412a-960e-9a91a5e05636","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"broadcast_hook_triggered","at":"2026-02-28T23:23:08.885Z","payload":{"phase":"sentence_vote","hookType":"scene_switch","triggeredAt":"2026-02-28T23:23:08.885Z"}}
{"id":"c641f88d-5452-4b83-9cf5-44159429e497","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"turn","at":"2026-02-28T23:23:08.885Z","payload":{"turn":{"id":"ee153410-8857-4872-b361-f91d22f091a0","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","turnNumber":15,"speaker":"mux","role":"bailiff","phase":"sentence_vote","dialogue":"Sentence poll is now open. Options: Community service in the meme archives | Banished to the shadow realm | Mandatory apology haikus | Ethics training hosted by a raccoon | Ukulele ankle-monitor probation","createdAt":"2026-02-28T23:23:08.885Z"}}}
{"id":"792f1c08-4cf0-4480-9efc-80a5c237caa4","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"phase_changed","at":"2026-02-28T23:23:28.886Z","payload":{"phase":"final_ruling","phaseStartedAt":"2026-02-28T23:23:28.886Z","phaseDurationMs":20000}}
{"id":"2b05fc63-29b1-428e-a0f2-8b1a3cc7982d","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"vote_closed","at":"2026-02-28T23:23:28.886Z","payload":{"pollType":"sentence","closedAt":"2026-02-28T23:23:28.886Z","votes":{},"nextPhase":"final_ruling"}}
{"id":"ff8706ff-50f5-425d-807e-3920490ae231","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"analytics_event","at":"2026-02-28T23:23:28.886Z","payload":{"name":"poll_closed","pollType":"sentence","phase":"final_ruling"}}
{"id":"375a87d8-bc30-4351-ba95-7c1de5b6e369","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"turn","at":"2026-02-28T23:23:28.887Z","payload":{"turn":{"id":"d10fce26-a9f3-485c-93f5-0ed7bdcfaaf6","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","turnNumber":16,"speaker":"primus","role":"judge","phase":"final_ruling","dialogue":"On the charge of chaos in the first degree, this court finds the defendant dramatically guilty—with style points.","createdAt":"2026-02-28T23:23:28.887Z"}}}
{"id":"2e539c61-b895-426f-821c-7a92afad98e4","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"render_directive","at":"2026-02-28T23:23:28.888Z","payload":{"directive":{"camera":"verdict","poses":{"judge":"talk"}},"turnId":"d10fce26-a9f3-485c-93f5-0ed7bdcfaaf6","phase":"final_ruling","emittedAt":"2026-02-28T23:23:28.888Z"}}
{"id":"0c34a78d-83ee-4e9b-8a06-858c64791945","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"token_budget_applied","at":"2026-02-28T23:23:28.888Z","payload":{"turnId":"d10fce26-a9f3-485c-93f5-0ed7bdcfaaf6","speaker":"primus","role":"judge","phase":"final_ruling","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"4e2498ec-27de-44be-8e43-4a8a3cb4c89f","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"session_token_estimate","at":"2026-02-28T23:23:28.888Z","payload":{"turnId":"d10fce26-a9f3-485c-93f5-0ed7bdcfaaf6","role":"judge","phase":"final_ruling","estimatedPromptTokens":3567,"estimatedCompletionTokens":280,"cumulativeEstimatedTokens":3847,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.007694}}
{"id":"57182fa9-bb42-4c03-b22b-f08a36314fe4","sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","type":"session_completed","at":"2026-02-28T23:23:28.888Z","payload":{"sessionId":"709ed6f9-e59f-4063-8d09-d52bd1cafc98","completedAt":"2026-02-28T23:23:28.888Z"}}

View File

@@ -0,0 +1,82 @@
{"id":"24268c88-5fa5-4848-a988-acec9d34218b","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"session_created","at":"2026-03-01T00:12:32.453Z","payload":{"sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474"}}
{"id":"64260b19-4960-4143-865d-743bc69d10ae","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"session_started","at":"2026-03-01T00:12:32.457Z","payload":{"sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","startedAt":"2026-03-01T00:12:32.454Z"}}
{"id":"2493f9c4-5ee4-42c8-82fd-d4f272b06db2","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"case_file_generated","at":"2026-03-01T00:12:32.457Z","payload":{"caseFile":{"title":"is the defendant guilty of freely farting on an airplane?","genre":"fantasy_court","caseType":"criminal","synopsis":"is the defendant guilty of freely farting on an airplane?","charges":["As stated in case prompt"],"witnesses":[],"evidence":[],"sentenceOptions":["Community service in the meme archives","Banished to the shadow realm","Mandatory apology haikus","Ethics training hosted by a raccoon","Ukulele ankle-monitor probation"]},"sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","generatedAt":"2026-03-01T00:12:32.457Z"}}
{"id":"33c98f2e-388a-4db1-aa47-9d39e7d7f484","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"phase_changed","at":"2026-03-01T00:12:32.464Z","payload":{"phase":"case_prompt","phaseStartedAt":"2026-03-01T00:12:32.461Z","phaseDurationMs":8000}}
{"id":"78ebcec3-dcb5-42d0-b41c-b6218c775437","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"broadcast_hook_triggered","at":"2026-03-01T00:12:32.464Z","payload":{"phase":"case_prompt","hookType":"phase_stinger","triggeredAt":"2026-03-01T00:12:32.464Z"}}
{"id":"14090c10-592b-4b40-9d3c-170af140dba2","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"turn","at":"2026-03-01T00:12:32.467Z","payload":{"turn":{"id":"b4c699a2-8b1f-484c-a537-8ed6949a642b","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","turnNumber":0,"speaker":"mux","role":"bailiff","phase":"case_prompt","dialogue":"All rise. The JuryRigged court is now in session. Case: is the defendant guilty of freely farting on an airplane?","createdAt":"2026-03-01T00:12:32.465Z"}}}
{"id":"7ba37280-5b8f-4fb0-a298-84a353edaca6","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"phase_changed","at":"2026-03-01T00:12:33.671Z","payload":{"phase":"openings","phaseStartedAt":"2026-03-01T00:12:33.668Z","phaseDurationMs":30000}}
{"id":"76b6e6a7-c2ea-4b30-bac9-7a07e40cfa24","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"turn","at":"2026-03-01T00:12:40.141Z","payload":{"turn":{"id":"7b568b05-de54-4b98-bee0-6f79164294cf","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","turnNumber":1,"speaker":"subrosa","role":"prosecutor","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-03-01T00:12:40.137Z"}}}
{"id":"e035f16a-01d1-4b9d-8de1-7018e3720119","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"render_directive","at":"2026-03-01T00:12:40.142Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"7b568b05-de54-4b98-bee0-6f79164294cf","phase":"openings","emittedAt":"2026-03-01T00:12:40.142Z"}}
{"id":"10e38f5f-74b2-4a77-bd23-6c31fee03d02","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"token_budget_applied","at":"2026-03-01T00:12:40.142Z","payload":{"turnId":"7b568b05-de54-4b98-bee0-6f79164294cf","speaker":"subrosa","role":"prosecutor","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"67fe1076-e8f7-4047-96e0-ad494d07579a","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"session_token_estimate","at":"2026-03-01T00:12:40.142Z","payload":{"turnId":"7b568b05-de54-4b98-bee0-6f79164294cf","role":"prosecutor","phase":"openings","estimatedPromptTokens":144,"estimatedCompletionTokens":22,"cumulativeEstimatedTokens":166,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.000332}}
{"id":"9f9e6ca5-6844-4c6f-80a6-49452319a04a","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"turn","at":"2026-03-01T00:12:43.792Z","payload":{"turn":{"id":"05a4c40d-96cf-453e-84a1-80b168812b3d","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","turnNumber":2,"speaker":"chora","role":"defense","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-03-01T00:12:43.791Z"}}}
{"id":"d0e650cc-8ba0-4b0c-b83f-96a614a1aab3","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"render_directive","at":"2026-03-01T00:12:43.793Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"05a4c40d-96cf-453e-84a1-80b168812b3d","phase":"openings","emittedAt":"2026-03-01T00:12:43.793Z"}}
{"id":"5541fc03-02ba-46fa-9c26-87a859bc8064","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"token_budget_applied","at":"2026-03-01T00:12:43.793Z","payload":{"turnId":"05a4c40d-96cf-453e-84a1-80b168812b3d","speaker":"chora","role":"defense","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"8cacef03-a3fb-421b-b542-00ffdc9cd0aa","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"session_token_estimate","at":"2026-03-01T00:12:43.793Z","payload":{"turnId":"05a4c40d-96cf-453e-84a1-80b168812b3d","role":"defense","phase":"openings","estimatedPromptTokens":306,"estimatedCompletionTokens":44,"cumulativeEstimatedTokens":350,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.0007}}
{"id":"81eafb1f-b4d8-47ec-b1a6-fbd985638919","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"phase_changed","at":"2026-03-01T00:12:43.800Z","payload":{"phase":"witness_exam","phaseStartedAt":"2026-03-01T00:12:43.797Z","phaseDurationMs":40000}}
{"id":"21234ca8-fddc-4720-bbd7-1faca86b092f","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"turn","at":"2026-03-01T00:12:48.201Z","payload":{"turn":{"id":"cbf756f9-f891-4135-9bd5-ed4f7c41cae1","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","turnNumber":3,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-03-01T00:12:48.197Z"}}}
{"id":"1ce745a9-eb51-4acf-b853-4b4ae69fe3df","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"render_directive","at":"2026-03-01T00:12:48.201Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"cbf756f9-f891-4135-9bd5-ed4f7c41cae1","phase":"witness_exam","emittedAt":"2026-03-01T00:12:48.201Z"}}
{"id":"fceaba99-82a3-4c9c-a04d-30d07a1c9639","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"token_budget_applied","at":"2026-03-01T00:12:48.201Z","payload":{"turnId":"cbf756f9-f891-4135-9bd5-ed4f7c41cae1","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"e1edc583-3333-4a66-81c5-74f6b9385ed3","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"session_token_estimate","at":"2026-03-01T00:12:48.201Z","payload":{"turnId":"cbf756f9-f891-4135-9bd5-ed4f7c41cae1","role":"judge","phase":"witness_exam","estimatedPromptTokens":495,"estimatedCompletionTokens":64,"cumulativeEstimatedTokens":559,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001118}}
{"id":"a5e3c6e5-86a8-47ba-b1b4-63617c176f6d","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"turn","at":"2026-03-01T00:12:50.277Z","payload":{"turn":{"id":"b3213308-fbf2-4328-8248-d1ffbf9d06e4","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","turnNumber":4,"speaker":"thaum","role":"witness_1","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-03-01T00:12:50.273Z"}}}
{"id":"ee602463-32dc-4268-9e88-f0653f837d95","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"render_directive","at":"2026-03-01T00:12:50.277Z","payload":{"directive":{"camera":"witness","poses":{"witness_1":"talk"}},"turnId":"b3213308-fbf2-4328-8248-d1ffbf9d06e4","phase":"witness_exam","emittedAt":"2026-03-01T00:12:50.277Z"}}
{"id":"d2bc1168-c5df-4beb-b3a0-b8cac3a51d9f","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"witness_statement","at":"2026-03-01T00:12:50.277Z","payload":{"statement":{"witnessRole":"witness_1","agentId":"thaum","statementText":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","issuedAt":"2026-03-01T00:12:50.277Z"},"phase":"witness_exam","emittedAt":"2026-03-01T00:12:50.277Z"}}
{"id":"8276ab29-b7ab-45db-a022-d848cba96ce3","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"token_budget_applied","at":"2026-03-01T00:12:50.277Z","payload":{"turnId":"b3213308-fbf2-4328-8248-d1ffbf9d06e4","speaker":"thaum","role":"witness_1","phase":"witness_exam","requestedMaxTokens":90,"appliedMaxTokens":90,"roleMaxTokens":160,"source":"requested"}}
{"id":"991df2b1-ff7a-43bf-8f81-33a5df24595a","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"session_token_estimate","at":"2026-03-01T00:12:50.277Z","payload":{"turnId":"b3213308-fbf2-4328-8248-d1ffbf9d06e4","role":"witness_1","phase":"witness_exam","estimatedPromptTokens":704,"estimatedCompletionTokens":84,"cumulativeEstimatedTokens":788,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001576}}
{"id":"8be311a2-891f-4da0-be72-4f94e4e84ca2","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"turn","at":"2026-03-01T00:12:54.740Z","payload":{"turn":{"id":"9cba4b69-2bc3-49e8-9796-aaad19f48000","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","turnNumber":5,"speaker":"subrosa","role":"prosecutor","phase":"witness_exam","dialogue":"Are you testifying as a forensic emotional intent detector, or did you just see someone holding a spoon?","createdAt":"2026-03-01T00:12:54.737Z"}}}
{"id":"7d83b322-4947-4e48-9198-f7be6d91c37c","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"render_directive","at":"2026-03-01T00:12:54.740Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"9cba4b69-2bc3-49e8-9796-aaad19f48000","phase":"witness_exam","emittedAt":"2026-03-01T00:12:54.740Z"}}
{"id":"d68fbd23-f0a1-48c1-b6da-28526e0a02e6","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"token_budget_applied","at":"2026-03-01T00:12:54.740Z","payload":{"turnId":"9cba4b69-2bc3-49e8-9796-aaad19f48000","speaker":"subrosa","role":"prosecutor","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"7e80b1f8-735a-4b34-82e8-45303bd44824","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"session_token_estimate","at":"2026-03-01T00:12:54.740Z","payload":{"turnId":"9cba4b69-2bc3-49e8-9796-aaad19f48000","role":"prosecutor","phase":"witness_exam","estimatedPromptTokens":931,"estimatedCompletionTokens":102,"cumulativeEstimatedTokens":1033,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.002066}}
{"id":"4309071c-7810-475e-9cc8-7d417563f855","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"turn","at":"2026-03-01T00:12:59.572Z","payload":{"turn":{"id":"f3fa2c0e-7718-4330-ad92-94dc6a6c626d","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","turnNumber":6,"speaker":"chora","role":"defense","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-03-01T00:12:59.567Z"}}}
{"id":"a8228def-8bc0-4ac0-8484-9c438e5e0f65","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"render_directive","at":"2026-03-01T00:12:59.572Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"f3fa2c0e-7718-4330-ad92-94dc6a6c626d","phase":"witness_exam","emittedAt":"2026-03-01T00:12:59.572Z"}}
{"id":"44bb5c98-93ef-4ecb-bcdb-dd54ebb04a92","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"token_budget_applied","at":"2026-03-01T00:12:59.572Z","payload":{"turnId":"f3fa2c0e-7718-4330-ad92-94dc6a6c626d","speaker":"chora","role":"defense","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"a67abcfb-9dcd-40d8-8bc1-9b4be5a9583b","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"session_token_estimate","at":"2026-03-01T00:12:59.572Z","payload":{"turnId":"f3fa2c0e-7718-4330-ad92-94dc6a6c626d","role":"defense","phase":"witness_exam","estimatedPromptTokens":1183,"estimatedCompletionTokens":122,"cumulativeEstimatedTokens":1305,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00261}}
{"id":"2816e093-0752-4f66-9458-0b030126d717","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"turn","at":"2026-03-01T00:13:02.620Z","payload":{"turn":{"id":"6acb05fc-1dcc-4d42-8504-6e066373e0cb","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","turnNumber":7,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"W","createdAt":"2026-03-01T00:13:02.616Z"}}}
{"id":"974cae38-b4c0-4529-919c-a8d073210b76","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"render_directive","at":"2026-03-01T00:13:02.620Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"6acb05fc-1dcc-4d42-8504-6e066373e0cb","phase":"witness_exam","emittedAt":"2026-03-01T00:13:02.620Z"}}
{"id":"cb395995-d6ea-4a41-94d8-1ddfc9365a17","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"token_budget_applied","at":"2026-03-01T00:13:02.620Z","payload":{"turnId":"6acb05fc-1dcc-4d42-8504-6e066373e0cb","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"10b922cf-2afa-4554-ac43-5d90b2fa58f5","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"session_token_estimate","at":"2026-03-01T00:13:02.620Z","payload":{"turnId":"6acb05fc-1dcc-4d42-8504-6e066373e0cb","role":"judge","phase":"witness_exam","estimatedPromptTokens":1458,"estimatedCompletionTokens":123,"cumulativeEstimatedTokens":1581,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.003162}}
{"id":"91f3d301-7a74-4cbb-a776-6f3000f9173d","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"turn","at":"2026-03-01T00:13:04.640Z","payload":{"turn":{"id":"1c63753b-5124-454e-be93-ad957f9a7934","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","turnNumber":8,"speaker":"praxis","role":"witness_2","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-03-01T00:13:04.637Z"}}}
{"id":"049401ed-fc52-4590-bfd2-c1af20691ec2","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"render_directive","at":"2026-03-01T00:13:04.641Z","payload":{"directive":{"camera":"witness","poses":{"witness_2":"talk"}},"turnId":"1c63753b-5124-454e-be93-ad957f9a7934","phase":"witness_exam","emittedAt":"2026-03-01T00:13:04.641Z"}}
{"id":"ed538e2d-ec89-45f8-b857-0024202bdd8c","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"witness_statement","at":"2026-03-01T00:13:04.641Z","payload":{"statement":{"witnessRole":"witness_2","agentId":"praxis","statementText":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","issuedAt":"2026-03-01T00:13:04.641Z"},"phase":"witness_exam","emittedAt":"2026-03-01T00:13:04.641Z"}}
{"id":"d46b5017-3a4c-4c4c-9926-d767086acac5","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"token_budget_applied","at":"2026-03-01T00:13:04.641Z","payload":{"turnId":"1c63753b-5124-454e-be93-ad957f9a7934","speaker":"praxis","role":"witness_2","phase":"witness_exam","requestedMaxTokens":90,"appliedMaxTokens":90,"roleMaxTokens":160,"source":"requested"}}
{"id":"fe549f60-25a4-4a36-a6f9-e1d1f1910854","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"session_token_estimate","at":"2026-03-01T00:13:04.641Z","payload":{"turnId":"1c63753b-5124-454e-be93-ad957f9a7934","role":"witness_2","phase":"witness_exam","estimatedPromptTokens":1734,"estimatedCompletionTokens":143,"cumulativeEstimatedTokens":1877,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.003754}}
{"id":"03ee6056-3591-4891-9ca0-6575739c68ed","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"turn","at":"2026-03-01T00:13:07.724Z","payload":{"turn":{"id":"ce9b21b0-a624-4127-b4e3-d8bc95f3b9c1","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","turnNumber":9,"speaker":"subrosa","role":"prosecutor","phase":"witness_exam","dialogue":"Your so-called \"emotional intent detector\" is just you","createdAt":"2026-03-01T00:13:07.721Z"}}}
{"id":"833e6686-0cd0-48f8-bb4e-fb065dbe0531","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"render_directive","at":"2026-03-01T00:13:07.724Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"ce9b21b0-a624-4127-b4e3-d8bc95f3b9c1","phase":"witness_exam","emittedAt":"2026-03-01T00:13:07.724Z"}}
{"id":"1e6e1f5f-8c74-403b-87b1-d3c47a9d0211","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"token_budget_applied","at":"2026-03-01T00:13:07.724Z","payload":{"turnId":"ce9b21b0-a624-4127-b4e3-d8bc95f3b9c1","speaker":"subrosa","role":"prosecutor","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"09577d24-ca3e-426b-a2ba-410fd84b8f96","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"session_token_estimate","at":"2026-03-01T00:13:07.724Z","payload":{"turnId":"ce9b21b0-a624-4127-b4e3-d8bc95f3b9c1","role":"prosecutor","phase":"witness_exam","estimatedPromptTokens":2028,"estimatedCompletionTokens":151,"cumulativeEstimatedTokens":2179,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.004358}}
{"id":"2c32d78c-d6e4-48b9-9519-2c8231c6cb7d","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"turn","at":"2026-03-01T00:13:10.764Z","payload":{"turn":{"id":"1be5d566-0b9d-400d-a93a-f63b4b8f7981","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","turnNumber":10,"speaker":"chora","role":"defense","phase":"witness_exam","dialogue":"Objection, the prosecutor mocks a recognized arcane sensory perception! My witness is a certified Level 3 Empath; her emotional intent readings are admissible under the Mystic Accord of 1327. You're just jealous your mundane eyes can't see","createdAt":"2026-03-01T00:13:10.761Z"}}}
{"id":"43d7aa0b-0f81-4ca6-839f-8ba20cd37309","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"render_directive","at":"2026-03-01T00:13:10.764Z","payload":{"directive":{"camera":"defense","poses":{"defense":"point"},"effect":"objection"},"turnId":"1be5d566-0b9d-400d-a93a-f63b4b8f7981","phase":"witness_exam","emittedAt":"2026-03-01T00:13:10.764Z"}}
{"id":"ae726a3d-d43e-4da1-9e05-0727c9482cce","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"token_budget_applied","at":"2026-03-01T00:13:10.764Z","payload":{"turnId":"1be5d566-0b9d-400d-a93a-f63b4b8f7981","speaker":"chora","role":"defense","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"22901a15-e33a-4700-a8a7-4215a120ee7d","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"session_token_estimate","at":"2026-03-01T00:13:10.764Z","payload":{"turnId":"1be5d566-0b9d-400d-a93a-f63b4b8f7981","role":"defense","phase":"witness_exam","estimatedPromptTokens":2313,"estimatedCompletionTokens":188,"cumulativeEstimatedTokens":2501,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.005002}}
{"id":"fa4cae68-29d2-4c67-9f8e-af6960188fad","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"turn","at":"2026-03-01T00:13:13.270Z","payload":{"turn":{"id":"dd9c75f4-ed2d-41e9-b521-de013401385c","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","turnNumber":11,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"Recap: Order in the court. I acknowledge the point and move us to the next absurdly important matter.","createdAt":"2026-03-01T00:13:13.266Z"}}}
{"id":"064eb30f-adc4-440b-bcca-798333d2bd33","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"render_directive","at":"2026-03-01T00:13:13.270Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"dd9c75f4-ed2d-41e9-b521-de013401385c","phase":"witness_exam","emittedAt":"2026-03-01T00:13:13.270Z"}}
{"id":"41497b2c-9bc1-4c16-b0ea-9aa572653327","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"token_budget_applied","at":"2026-03-01T00:13:13.270Z","payload":{"turnId":"dd9c75f4-ed2d-41e9-b521-de013401385c","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"e93cb504-a1a4-4a1b-be9d-97e26c246dff","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"session_token_estimate","at":"2026-03-01T00:13:13.270Z","payload":{"turnId":"dd9c75f4-ed2d-41e9-b521-de013401385c","role":"judge","phase":"witness_exam","estimatedPromptTokens":2618,"estimatedCompletionTokens":206,"cumulativeEstimatedTokens":2824,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.005648}}
{"id":"25c79475-1107-49e1-80cd-1b5edf3adda8","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"judge_recap_emitted","at":"2026-03-01T00:13:13.274Z","payload":{"turnId":"dd9c75f4-ed2d-41e9-b521-de013401385c","phase":"witness_exam","cycleNumber":2}}
{"id":"15124578-f82e-4861-8262-8e63e732053f","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"phase_changed","at":"2026-03-01T00:13:14.078Z","payload":{"phase":"closings","phaseStartedAt":"2026-03-01T00:13:14.076Z","phaseDurationMs":30000}}
{"id":"e66a51aa-e537-46da-87da-4d39eb123cfb","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"turn","at":"2026-03-01T00:13:18.194Z","payload":{"turn":{"id":"a36a30f6-7943-4772-a261-22eb72cedf88","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","turnNumber":12,"speaker":"subrosa","role":"prosecutor","phase":"closings","dialogue":"At the end of the day, this is either a crime or a spectacular misunderstanding involving glitter and plausible deniability.","createdAt":"2026-03-01T00:13:18.192Z"}}}
{"id":"8793eac4-b2b9-44b6-8669-49c94a2a627f","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"render_directive","at":"2026-03-01T00:13:18.194Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"a36a30f6-7943-4772-a261-22eb72cedf88","phase":"closings","emittedAt":"2026-03-01T00:13:18.194Z"}}
{"id":"d7253b27-6c4f-4f12-abcc-333e966c954d","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"token_budget_applied","at":"2026-03-01T00:13:18.194Z","payload":{"turnId":"a36a30f6-7943-4772-a261-22eb72cedf88","speaker":"subrosa","role":"prosecutor","phase":"closings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"44fc8c50-2a70-419a-8e63-c4db6828c088","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"session_token_estimate","at":"2026-03-01T00:13:18.194Z","payload":{"turnId":"a36a30f6-7943-4772-a261-22eb72cedf88","role":"prosecutor","phase":"closings","estimatedPromptTokens":2914,"estimatedCompletionTokens":226,"cumulativeEstimatedTokens":3140,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00628}}
{"id":"2d028c35-7f97-4f78-9222-94f88e1b1e09","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"turn","at":"2026-03-01T00:13:22.020Z","payload":{"turn":{"id":"8af9b0d4-9a5f-47b6-ad59-5060a44b9f4b","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","turnNumber":13,"speaker":"chora","role":"defense","phase":"closings","dialogue":"At the end of the day, this is either a crime or a spectacular misunderstanding involving glitter and plausible deniability.","createdAt":"2026-03-01T00:13:22.016Z"}}}
{"id":"81bae01b-8d7d-4dcb-8847-00c3cb0afb80","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"render_directive","at":"2026-03-01T00:13:22.020Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"8af9b0d4-9a5f-47b6-ad59-5060a44b9f4b","phase":"closings","emittedAt":"2026-03-01T00:13:22.020Z"}}
{"id":"7a41baf6-2641-4c18-bbcc-50f2c3df43f3","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"token_budget_applied","at":"2026-03-01T00:13:22.020Z","payload":{"turnId":"8af9b0d4-9a5f-47b6-ad59-5060a44b9f4b","speaker":"chora","role":"defense","phase":"closings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"467c144d-71c5-409b-ab25-2ebe70b0039f","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"session_token_estimate","at":"2026-03-01T00:13:22.021Z","payload":{"turnId":"8af9b0d4-9a5f-47b6-ad59-5060a44b9f4b","role":"defense","phase":"closings","estimatedPromptTokens":3209,"estimatedCompletionTokens":246,"cumulativeEstimatedTokens":3455,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00691}}
{"id":"82500da9-9546-481f-a30d-eebae93ed985","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"phase_changed","at":"2026-03-01T00:13:22.026Z","payload":{"phase":"verdict_vote","phaseStartedAt":"2026-03-01T00:13:22.024Z","phaseDurationMs":20000}}
{"id":"adec6114-09ed-4801-ab77-f3f4552ddd7e","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"analytics_event","at":"2026-03-01T00:13:22.026Z","payload":{"name":"poll_started","pollType":"verdict","phase":"verdict_vote"}}
{"id":"6dce593b-6d60-411a-9540-c04e656f7353","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"broadcast_hook_triggered","at":"2026-03-01T00:13:22.027Z","payload":{"phase":"verdict_vote","hookType":"scene_switch","triggeredAt":"2026-03-01T00:13:22.027Z"}}
{"id":"725c5471-3022-4301-bd33-74811a4c0435","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"turn","at":"2026-03-01T00:13:22.031Z","payload":{"turn":{"id":"e44a19e3-ccff-4014-992d-2fdd589eadf8","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","turnNumber":14,"speaker":"mux","role":"bailiff","phase":"verdict_vote","dialogue":"Jury poll is open: guilty / not_guilty. Cast your votes now.","createdAt":"2026-03-01T00:13:22.027Z"}}}
{"id":"70044545-3e84-43f9-b149-57ac270dc73f","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"phase_changed","at":"2026-03-01T00:13:42.037Z","payload":{"phase":"sentence_vote","phaseStartedAt":"2026-03-01T00:13:42.032Z","phaseDurationMs":20000}}
{"id":"88a021d5-7336-45c4-905d-efd0f9d497ab","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"vote_closed","at":"2026-03-01T00:13:42.037Z","payload":{"pollType":"verdict","closedAt":"2026-03-01T00:13:42.032Z","votes":{},"nextPhase":"sentence_vote"}}
{"id":"78725c35-c044-443a-b3e1-a3d9ad45c056","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"analytics_event","at":"2026-03-01T00:13:42.037Z","payload":{"name":"poll_closed","pollType":"verdict","phase":"sentence_vote"}}
{"id":"4742e2ce-7a5c-4c63-931d-08da62970dbb","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"analytics_event","at":"2026-03-01T00:13:42.037Z","payload":{"name":"poll_started","pollType":"sentence","phase":"sentence_vote"}}
{"id":"c556bd21-05eb-4f52-b144-460b2426a966","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"broadcast_hook_triggered","at":"2026-03-01T00:13:42.037Z","payload":{"phase":"sentence_vote","hookType":"scene_switch","triggeredAt":"2026-03-01T00:13:42.037Z"}}
{"id":"d0211eb9-ee5b-458c-99a7-1595076e7685","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"turn","at":"2026-03-01T00:13:42.040Z","payload":{"turn":{"id":"bec1aa1b-74b4-4cc6-b829-df91f977b254","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","turnNumber":15,"speaker":"mux","role":"bailiff","phase":"sentence_vote","dialogue":"Sentence poll is now open. Options: Community service in the meme archives | Banished to the shadow realm | Mandatory apology haikus | Ethics training hosted by a raccoon | Ukulele ankle-monitor probation","createdAt":"2026-03-01T00:13:42.038Z"}}}
{"id":"e633188d-52ac-427b-a571-224ed89c8539","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"phase_changed","at":"2026-03-01T00:14:02.044Z","payload":{"phase":"final_ruling","phaseStartedAt":"2026-03-01T00:14:02.042Z","phaseDurationMs":20000}}
{"id":"7e7a1e15-0cc3-4d53-a5ca-8efd58c0327f","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"vote_closed","at":"2026-03-01T00:14:02.044Z","payload":{"pollType":"sentence","closedAt":"2026-03-01T00:14:02.042Z","votes":{},"nextPhase":"final_ruling"}}
{"id":"063abac0-50c8-43f9-8efc-89e84d45f0e8","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"analytics_event","at":"2026-03-01T00:14:02.044Z","payload":{"name":"poll_closed","pollType":"sentence","phase":"final_ruling"}}
{"id":"29ce2b47-7d6b-4e52-b1ab-b00e4c912b14","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"turn","at":"2026-03-01T00:14:06.462Z","payload":{"turn":{"id":"f7e0845d-8a22-4c7f-be13-969445e3a3ad","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","turnNumber":16,"speaker":"primus","role":"judge","phase":"final_ruling","dialogue":"By the Sacred Scrolls of Scent and the Precedent of the Powdered Wig of 1412, I find the defendant guilty of Unleashing Gases of Mischief in a Confined Sky-Vessel. Your sentence is archival","createdAt":"2026-03-01T00:14:06.458Z"}}}
{"id":"a82e07d6-10b2-4f67-9ac2-d7610b6bdff5","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"render_directive","at":"2026-03-01T00:14:06.462Z","payload":{"directive":{"camera":"verdict","poses":{"judge":"talk"}},"turnId":"f7e0845d-8a22-4c7f-be13-969445e3a3ad","phase":"final_ruling","emittedAt":"2026-03-01T00:14:06.462Z"}}
{"id":"72c5ac99-1ad4-4dca-992b-aa550fc53d0b","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"token_budget_applied","at":"2026-03-01T00:14:06.462Z","payload":{"turnId":"f7e0845d-8a22-4c7f-be13-969445e3a3ad","speaker":"primus","role":"judge","phase":"final_ruling","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"f473c6f4-4d7c-44db-891e-836b1700c6b4","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"session_token_estimate","at":"2026-03-01T00:14:06.462Z","payload":{"turnId":"f7e0845d-8a22-4c7f-be13-969445e3a3ad","role":"judge","phase":"final_ruling","estimatedPromptTokens":3522,"estimatedCompletionTokens":279,"cumulativeEstimatedTokens":3801,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.007602}}
{"id":"dc26cded-fd35-47b5-8979-931804f59fec","sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","type":"session_completed","at":"2026-03-01T00:14:06.466Z","payload":{"sessionId":"71f211ec-5c3c-4d6f-9c5d-9dbb9cb05474","completedAt":"2026-03-01T00:14:06.462Z"}}

View File

@@ -0,0 +1,63 @@
{"id":"dd97eb7c-8637-487c-8e19-2fa5b7842c16","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"session_created","at":"2026-02-28T23:54:05.862Z","payload":{"sessionId":"926ee362-2b41-49da-9294-70d8407d58bb"}}
{"id":"e3cc1c93-7894-4e24-8cbb-861ea469692d","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"session_started","at":"2026-02-28T23:54:05.865Z","payload":{"sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","startedAt":"2026-02-28T23:54:05.863Z"}}
{"id":"70bccfb9-0376-46f0-8cfa-a0e33c544629","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"case_file_generated","at":"2026-02-28T23:54:05.865Z","payload":{"caseFile":{"title":"is the defendant guilty of freely farting on an airplane?","genre":"workplace_tribunal","caseType":"criminal","synopsis":"is the defendant guilty of freely farting on an airplane?","charges":["As stated in case prompt"],"witnesses":[],"evidence":[],"sentenceOptions":["Community service in the meme archives","Banished to the shadow realm","Mandatory apology haikus","Ethics training hosted by a raccoon","Ukulele ankle-monitor probation"]},"sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","generatedAt":"2026-02-28T23:54:05.865Z"}}
{"id":"467cc934-df31-417e-b6af-067678b5bcdf","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"phase_changed","at":"2026-02-28T23:54:05.869Z","payload":{"phase":"case_prompt","phaseStartedAt":"2026-02-28T23:54:05.867Z","phaseDurationMs":8000}}
{"id":"0bf29ed7-8a85-4a67-9ee7-bec0ca3c7c70","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"broadcast_hook_triggered","at":"2026-02-28T23:54:05.869Z","payload":{"phase":"case_prompt","hookType":"phase_stinger","triggeredAt":"2026-02-28T23:54:05.869Z"}}
{"id":"2acc711b-ec1a-4cfb-8aea-63e3e1073757","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"turn","at":"2026-02-28T23:54:05.874Z","payload":{"turn":{"id":"8096c356-d8b7-45c2-8173-25b199af28f5","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","turnNumber":0,"speaker":"mux","role":"bailiff","phase":"case_prompt","dialogue":"All rise. The JuryRigged court is now in session. Case: is the defendant guilty of freely farting on an airplane?","createdAt":"2026-02-28T23:54:05.872Z"}}}
{"id":"da46ac58-500f-4446-9901-bbd62a9eb846","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"phase_changed","at":"2026-02-28T23:54:07.079Z","payload":{"phase":"openings","phaseStartedAt":"2026-02-28T23:54:07.075Z","phaseDurationMs":30000}}
{"id":"830d4ed4-5611-46ab-8895-8b595502fd2b","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"turn","at":"2026-02-28T23:54:11.239Z","payload":{"turn":{"id":"3352897b-fbc3-4670-b9f5-62643539e3b1","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","turnNumber":1,"speaker":"subrosa","role":"prosecutor","phase":"openings","dialogue":"Ladies and gentlemen, this","createdAt":"2026-02-28T23:54:11.235Z"}}}
{"id":"bf2b296a-db9d-4d7e-a64b-8f5ac8a88202","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"render_directive","at":"2026-02-28T23:54:11.239Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"3352897b-fbc3-4670-b9f5-62643539e3b1","phase":"openings","emittedAt":"2026-02-28T23:54:11.239Z"}}
{"id":"55c5ab05-8f0b-4193-b835-87115d7845db","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"token_budget_applied","at":"2026-02-28T23:54:11.239Z","payload":{"turnId":"3352897b-fbc3-4670-b9f5-62643539e3b1","speaker":"subrosa","role":"prosecutor","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"502f3747-bed4-483b-96be-598e9b5a223f","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"session_token_estimate","at":"2026-02-28T23:54:11.239Z","payload":{"turnId":"3352897b-fbc3-4670-b9f5-62643539e3b1","role":"prosecutor","phase":"openings","estimatedPromptTokens":141,"estimatedCompletionTokens":4,"cumulativeEstimatedTokens":145,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00029}}
{"id":"1d270256-da33-483e-9d0c-33caf04efeca","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"turn","at":"2026-02-28T23:54:14.629Z","payload":{"turn":{"id":"7f5c1e1c-da89-4394-908a-66310e303190","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","turnNumber":2,"speaker":"chora","role":"defense","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-02-28T23:54:14.627Z"}}}
{"id":"156c3858-8789-4bea-905e-13263b73a8f8","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"render_directive","at":"2026-02-28T23:54:14.629Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"7f5c1e1c-da89-4394-908a-66310e303190","phase":"openings","emittedAt":"2026-02-28T23:54:14.629Z"}}
{"id":"4eec5a34-bce5-4773-87fb-513f3cb7b623","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"token_budget_applied","at":"2026-02-28T23:54:14.629Z","payload":{"turnId":"7f5c1e1c-da89-4394-908a-66310e303190","speaker":"chora","role":"defense","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"63a68031-75af-4758-8817-ca1e52eec0cc","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"session_token_estimate","at":"2026-02-28T23:54:14.629Z","payload":{"turnId":"7f5c1e1c-da89-4394-908a-66310e303190","role":"defense","phase":"openings","estimatedPromptTokens":281,"estimatedCompletionTokens":26,"cumulativeEstimatedTokens":307,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.000614}}
{"id":"4c12e821-2852-4615-a8ed-6a1be7b89699","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"phase_changed","at":"2026-02-28T23:54:14.633Z","payload":{"phase":"witness_exam","phaseStartedAt":"2026-02-28T23:54:14.631Z","phaseDurationMs":40000}}
{"id":"0baeb9bb-1b9e-43d8-a186-553c24aa840c","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"turn","at":"2026-02-28T23:54:18.585Z","payload":{"turn":{"id":"db9232b1-cd78-46ea-b18d-3f09a592960b","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","turnNumber":3,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"Witness, did you observe the defendant deliberately expel intestinal gases into the cabin air, and if so, was this act performed with the freedom we commonly associate with a","createdAt":"2026-02-28T23:54:18.581Z"}}}
{"id":"8eb50810-7a1c-4660-8cd4-a77f0c98ef01","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"render_directive","at":"2026-02-28T23:54:18.585Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"db9232b1-cd78-46ea-b18d-3f09a592960b","phase":"witness_exam","emittedAt":"2026-02-28T23:54:18.585Z"}}
{"id":"a584187f-1bdd-44b0-b283-eb7a269c2ff8","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"token_budget_applied","at":"2026-02-28T23:54:18.585Z","payload":{"turnId":"db9232b1-cd78-46ea-b18d-3f09a592960b","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"c3ce2442-a4ab-478e-ac07-0c7941fae287","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"session_token_estimate","at":"2026-02-28T23:54:18.585Z","payload":{"turnId":"db9232b1-cd78-46ea-b18d-3f09a592960b","role":"judge","phase":"witness_exam","estimatedPromptTokens":449,"estimatedCompletionTokens":55,"cumulativeEstimatedTokens":504,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001008}}
{"id":"46b65be6-0fc3-44ef-8b49-568c0713635e","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"turn","at":"2026-02-28T23:54:22.168Z","payload":{"turn":{"id":"f983be3d-a6df-4660-bd2e-2ca2b99154b3","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","turnNumber":4,"speaker":"thaum","role":"witness_1","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:54:22.164Z"}}}
{"id":"3b6b1f07-a414-484b-bd67-9f1e0817d11c","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"render_directive","at":"2026-02-28T23:54:22.168Z","payload":{"directive":{"camera":"witness","poses":{"witness_1":"talk"}},"turnId":"f983be3d-a6df-4660-bd2e-2ca2b99154b3","phase":"witness_exam","emittedAt":"2026-02-28T23:54:22.168Z"}}
{"id":"5b951941-2816-4273-b5f4-124c8943f30b","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"witness_statement","at":"2026-02-28T23:54:22.168Z","payload":{"statement":{"witnessRole":"witness_1","agentId":"thaum","statementText":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","issuedAt":"2026-02-28T23:54:22.168Z"},"phase":"witness_exam","emittedAt":"2026-02-28T23:54:22.168Z"}}
{"id":"8c9dbe73-37bf-4aa2-a768-dd5fa1cb832e","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"token_budget_applied","at":"2026-02-28T23:54:22.168Z","payload":{"turnId":"f983be3d-a6df-4660-bd2e-2ca2b99154b3","speaker":"thaum","role":"witness_1","phase":"witness_exam","requestedMaxTokens":90,"appliedMaxTokens":90,"roleMaxTokens":160,"source":"requested"}}
{"id":"885e5e81-c0dc-4ac4-832e-13f482ed03c6","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"session_token_estimate","at":"2026-02-28T23:54:22.168Z","payload":{"turnId":"f983be3d-a6df-4660-bd2e-2ca2b99154b3","role":"witness_1","phase":"witness_exam","estimatedPromptTokens":649,"estimatedCompletionTokens":75,"cumulativeEstimatedTokens":724,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001448}}
{"id":"616e6434-5c0e-4dbb-8394-ec8f05551c3c","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"turn","at":"2026-02-28T23:54:24.827Z","payload":{"turn":{"id":"c84653a4-bffb-48bc-8eb7-4a784e27091e","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","turnNumber":5,"speaker":"subrosa","role":"prosecutor","phase":"witness_exam","dialogue":"Were you so sleep-deprived","createdAt":"2026-02-28T23:54:24.825Z"}}}
{"id":"c31d400c-de94-462c-83a9-2b8236d5b1ab","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"render_directive","at":"2026-02-28T23:54:24.828Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"c84653a4-bffb-48bc-8eb7-4a784e27091e","phase":"witness_exam","emittedAt":"2026-02-28T23:54:24.828Z"}}
{"id":"62a7abc3-9fa9-40e5-8d73-a22bd16ff1cd","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"token_budget_applied","at":"2026-02-28T23:54:24.828Z","payload":{"turnId":"c84653a4-bffb-48bc-8eb7-4a784e27091e","speaker":"subrosa","role":"prosecutor","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"989bf866-86af-4a90-bf91-e19332c4085a","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"session_token_estimate","at":"2026-02-28T23:54:24.828Z","payload":{"turnId":"c84653a4-bffb-48bc-8eb7-4a784e27091e","role":"prosecutor","phase":"witness_exam","estimatedPromptTokens":864,"estimatedCompletionTokens":79,"cumulativeEstimatedTokens":943,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001886}}
{"id":"f7d01fe7-20f4-48a9-8132-1234204fda61","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"turn","at":"2026-02-28T23:54:32.173Z","payload":{"turn":{"id":"49428cc1-df1c-44bf-8271-0069153c1def","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","turnNumber":6,"speaker":"chora","role":"defense","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:54:32.168Z"}}}
{"id":"be8e371f-765c-4047-a98f-e1614afaf905","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"render_directive","at":"2026-02-28T23:54:32.173Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"49428cc1-df1c-44bf-8271-0069153c1def","phase":"witness_exam","emittedAt":"2026-02-28T23:54:32.173Z"}}
{"id":"30c3c2c9-b633-4cef-8ccb-f384f0849ce6","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"token_budget_applied","at":"2026-02-28T23:54:32.173Z","payload":{"turnId":"49428cc1-df1c-44bf-8271-0069153c1def","speaker":"chora","role":"defense","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"d0cc440a-68ea-441c-bb00-eff8fa8a7e58","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"session_token_estimate","at":"2026-02-28T23:54:32.173Z","payload":{"turnId":"49428cc1-df1c-44bf-8271-0069153c1def","role":"defense","phase":"witness_exam","estimatedPromptTokens":1089,"estimatedCompletionTokens":99,"cumulativeEstimatedTokens":1188,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.002376}}
{"id":"de860702-c31b-4e74-b916-4ff1186b8151","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"turn","at":"2026-02-28T23:54:35.018Z","payload":{"turn":{"id":"d0b708b1-19c0-4e3e-afda-ca52f74a8f7f","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","turnNumber":7,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"Witness, did you observe the defendant engage in an unrestrained expulsion of intestinal gases into the cabin air, and","createdAt":"2026-02-28T23:54:35.014Z"}}}
{"id":"5e744623-ec3c-4694-acd7-b5bd64866be4","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"render_directive","at":"2026-02-28T23:54:35.018Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"d0b708b1-19c0-4e3e-afda-ca52f74a8f7f","phase":"witness_exam","emittedAt":"2026-02-28T23:54:35.018Z"}}
{"id":"5474f89a-6047-44ae-bf1e-c19e49529bae","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"token_budget_applied","at":"2026-02-28T23:54:35.018Z","payload":{"turnId":"d0b708b1-19c0-4e3e-afda-ca52f74a8f7f","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"0cef2f63-0ceb-4993-aac4-9a12dfab0d84","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"session_token_estimate","at":"2026-02-28T23:54:35.018Z","payload":{"turnId":"d0b708b1-19c0-4e3e-afda-ca52f74a8f7f","role":"judge","phase":"witness_exam","estimatedPromptTokens":1338,"estimatedCompletionTokens":118,"cumulativeEstimatedTokens":1456,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.002912}}
{"id":"2312b65f-ebe5-481d-937b-edc6deb92881","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"turn","at":"2026-02-28T23:54:37.205Z","payload":{"turn":{"id":"ebc25a41-1eab-4afb-9167-5983737d2126","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","turnNumber":8,"speaker":"praxis","role":"witness_2","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:54:37.199Z"}}}
{"id":"d2586c69-a18e-4755-9410-bfe91c451d9c","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"render_directive","at":"2026-02-28T23:54:37.205Z","payload":{"directive":{"camera":"witness","poses":{"witness_2":"talk"}},"turnId":"ebc25a41-1eab-4afb-9167-5983737d2126","phase":"witness_exam","emittedAt":"2026-02-28T23:54:37.205Z"}}
{"id":"ec903501-066c-4e6f-804b-c060e984b064","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"witness_statement","at":"2026-02-28T23:54:37.205Z","payload":{"statement":{"witnessRole":"witness_2","agentId":"praxis","statementText":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","issuedAt":"2026-02-28T23:54:37.205Z"},"phase":"witness_exam","emittedAt":"2026-02-28T23:54:37.205Z"}}
{"id":"51c148b5-91e6-4747-93f5-d8e74b9071ec","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"token_budget_applied","at":"2026-02-28T23:54:37.205Z","payload":{"turnId":"ebc25a41-1eab-4afb-9167-5983737d2126","speaker":"praxis","role":"witness_2","phase":"witness_exam","requestedMaxTokens":90,"appliedMaxTokens":90,"roleMaxTokens":160,"source":"requested"}}
{"id":"f36bbf3b-efe5-49ad-b90e-297cce44df92","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"session_token_estimate","at":"2026-02-28T23:54:37.205Z","payload":{"turnId":"ebc25a41-1eab-4afb-9167-5983737d2126","role":"witness_2","phase":"witness_exam","estimatedPromptTokens":1609,"estimatedCompletionTokens":138,"cumulativeEstimatedTokens":1747,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.003494}}
{"id":"6e372c76-c2c9-4c76-be16-11ae4af95c8b","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"turn","at":"2026-02-28T23:54:41.766Z","payload":{"turn":{"id":"91dc970b-09cb-4fd4-acc5-0b5ff138018f","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","turnNumber":9,"speaker":"subrosa","role":"prosecutor","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:54:41.761Z"}}}
{"id":"8487d70b-dac6-43ee-b814-ca227dbd54b3","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"render_directive","at":"2026-02-28T23:54:41.766Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"91dc970b-09cb-4fd4-acc5-0b5ff138018f","phase":"witness_exam","emittedAt":"2026-02-28T23:54:41.766Z"}}
{"id":"a3f3f871-3b2d-4f9a-9524-28c9aa4ed725","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"token_budget_applied","at":"2026-02-28T23:54:41.766Z","payload":{"turnId":"91dc970b-09cb-4fd4-acc5-0b5ff138018f","speaker":"subrosa","role":"prosecutor","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"48a5e469-c999-4269-9dfb-eb871c213fb0","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"session_token_estimate","at":"2026-02-28T23:54:41.766Z","payload":{"turnId":"91dc970b-09cb-4fd4-acc5-0b5ff138018f","role":"prosecutor","phase":"witness_exam","estimatedPromptTokens":1895,"estimatedCompletionTokens":158,"cumulativeEstimatedTokens":2053,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.004106}}
{"id":"68ba7641-7628-44dc-9bcc-d196b7cf5f2e","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"turn","at":"2026-02-28T23:54:45.406Z","payload":{"turn":{"id":"912e7930-b683-4703-9295-63e381e45b77","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","turnNumber":10,"speaker":"chora","role":"defense","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:54:45.402Z"}}}
{"id":"89811bd0-baf5-44b8-baeb-c15b6ddc155f","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"render_directive","at":"2026-02-28T23:54:45.406Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"912e7930-b683-4703-9295-63e381e45b77","phase":"witness_exam","emittedAt":"2026-02-28T23:54:45.406Z"}}
{"id":"bef4d9f3-b401-4bb6-9d05-f4dda897b2c0","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"token_budget_applied","at":"2026-02-28T23:54:45.407Z","payload":{"turnId":"912e7930-b683-4703-9295-63e381e45b77","speaker":"chora","role":"defense","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"dd66aaf5-45f6-4d23-bcd6-b70edc9060ab","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"session_token_estimate","at":"2026-02-28T23:54:45.407Z","payload":{"turnId":"912e7930-b683-4703-9295-63e381e45b77","role":"defense","phase":"witness_exam","estimatedPromptTokens":2201,"estimatedCompletionTokens":178,"cumulativeEstimatedTokens":2379,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.004758}}
{"id":"60d33d4a-d44c-418a-a432-ac9fb51df1fb","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"turn","at":"2026-02-28T23:54:48.297Z","payload":{"turn":{"id":"4f59078e-8253-4746-96f9-6bb6302763c0","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","turnNumber":11,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"Recap: The prosecutions case rests on placing the defendant at the snack cabinet at 2:03 AM with a spoon and what witnesses repeatedly termed \"emotional intent,\" yet no one has testified to observing the actual, alleged expulsion. The central question remains whether \"emotional intent\" with a spoon constitutes actionable flatulence, or merely a midnight snack crisis.","createdAt":"2026-02-28T23:54:48.293Z"}}}
{"id":"0a77de7a-9d20-4a1b-b7af-b5bd1ff40bf7","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"render_directive","at":"2026-02-28T23:54:48.297Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"4f59078e-8253-4746-96f9-6bb6302763c0","phase":"witness_exam","emittedAt":"2026-02-28T23:54:48.297Z"}}
{"id":"898ffc2c-c98b-47b8-9d13-1c2414aa8f18","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"token_budget_applied","at":"2026-02-28T23:54:48.297Z","payload":{"turnId":"4f59078e-8253-4746-96f9-6bb6302763c0","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"1e9ab0fe-63db-4964-8720-cd4495bb59dd","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"session_token_estimate","at":"2026-02-28T23:54:48.297Z","payload":{"turnId":"4f59078e-8253-4746-96f9-6bb6302763c0","role":"judge","phase":"witness_exam","estimatedPromptTokens":2511,"estimatedCompletionTokens":234,"cumulativeEstimatedTokens":2745,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00549}}
{"id":"42b24c3d-331c-41bc-a884-b1c8da02902a","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"judge_recap_emitted","at":"2026-02-28T23:54:48.304Z","payload":{"turnId":"4f59078e-8253-4746-96f9-6bb6302763c0","phase":"witness_exam","cycleNumber":2}}
{"id":"bb0eea1f-7865-49de-9474-2d0296e9e53e","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"phase_changed","at":"2026-02-28T23:54:49.108Z","payload":{"phase":"closings","phaseStartedAt":"2026-02-28T23:54:49.105Z","phaseDurationMs":30000}}
{"id":"deb67e0a-37e1-4590-974b-472c3420b30b","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"turn","at":"2026-02-28T23:54:52.213Z","payload":{"turn":{"id":"9cdd8b70-0f6f-4197-acee-ad143fd09b39","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","turnNumber":12,"speaker":"subrosa","role":"prosecutor","phase":"closings","dialogue":"At the end of the day, this is either a crime or a spectacular misunderstanding involving glitter and plausible deniability.","createdAt":"2026-02-28T23:54:52.208Z"}}}
{"id":"2aa187e8-e7e6-41de-a702-b9b385c5428c","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"render_directive","at":"2026-02-28T23:54:52.213Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"9cdd8b70-0f6f-4197-acee-ad143fd09b39","phase":"closings","emittedAt":"2026-02-28T23:54:52.213Z"}}
{"id":"f040e5a1-5124-46f3-b2dc-c88a593a780e","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"token_budget_applied","at":"2026-02-28T23:54:52.213Z","payload":{"turnId":"9cdd8b70-0f6f-4197-acee-ad143fd09b39","speaker":"subrosa","role":"prosecutor","phase":"closings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"4d592f41-25ce-45f7-afdc-f9c90c422a0c","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"session_token_estimate","at":"2026-02-28T23:54:52.213Z","payload":{"turnId":"9cdd8b70-0f6f-4197-acee-ad143fd09b39","role":"prosecutor","phase":"closings","estimatedPromptTokens":2841,"estimatedCompletionTokens":254,"cumulativeEstimatedTokens":3095,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00619}}
{"id":"f0a79f9f-92f3-4779-ad17-a0f61d866538","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"session_started","at":"2026-02-28T23:55:04.999Z","payload":{"sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","startedAt":"2026-02-28T23:54:05.863Z"}}
{"id":"abf6a89a-dcd0-4bea-87d2-65e78d79a4fc","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"case_file_generated","at":"2026-02-28T23:55:04.999Z","payload":{"caseFile":{"title":"is the defendant guilty of freely farting on an airplane?","genre":"workplace_tribunal","caseType":"criminal","synopsis":"is the defendant guilty of freely farting on an airplane?","charges":["As stated in case prompt"],"witnesses":[],"evidence":[],"sentenceOptions":["Community service in the meme archives","Banished to the shadow realm","Mandatory apology haikus","Ethics training hosted by a raccoon","Ukulele ankle-monitor probation"]},"sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","generatedAt":"2026-02-28T23:55:04.999Z"}}
{"id":"9bf03369-9693-4338-8b31-f6da590fcb66","sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","type":"session_failed","at":"2026-02-28T23:55:05.008Z","payload":{"sessionId":"926ee362-2b41-49da-9294-70d8407d58bb","reason":"Invalid phase transition: closings -> case_prompt","completedAt":"2026-02-28T23:55:05.005Z"}}

View File

@@ -0,0 +1,77 @@
{"id":"b4df3155-c9c0-49d3-8a3a-51b6b83688b4","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"session_created","at":"2026-02-28T23:51:26.084Z","payload":{"sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331"}}
{"id":"48658cde-25b3-44bb-a200-cf134d5d5d00","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"session_started","at":"2026-02-28T23:51:26.092Z","payload":{"sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","startedAt":"2026-02-28T23:51:26.087Z"}}
{"id":"7452ffa2-3d25-43a6-99b9-0811530bbaa2","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"case_file_generated","at":"2026-02-28T23:51:26.093Z","payload":{"caseFile":{"title":"is the defendant guilty of freely farting on an airplane?","genre":"absurd_civil","caseType":"criminal","synopsis":"is the defendant guilty of freely farting on an airplane?","charges":["As stated in case prompt"],"witnesses":[],"evidence":[],"sentenceOptions":["Community service in the meme archives","Banished to the shadow realm","Mandatory apology haikus","Ethics training hosted by a raccoon","Ukulele ankle-monitor probation"]},"sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","generatedAt":"2026-02-28T23:51:26.093Z"}}
{"id":"ce824afd-ea2c-4583-8b36-d3b4ac6bd6a4","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"phase_changed","at":"2026-02-28T23:51:26.103Z","payload":{"phase":"case_prompt","phaseStartedAt":"2026-02-28T23:51:26.098Z","phaseDurationMs":8000}}
{"id":"7936a5f6-a5ab-4189-8f8a-07a2855971d4","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"broadcast_hook_triggered","at":"2026-02-28T23:51:26.103Z","payload":{"phase":"case_prompt","hookType":"phase_stinger","triggeredAt":"2026-02-28T23:51:26.103Z"}}
{"id":"2ffb529c-96cd-46e3-8d2e-2b8564737b14","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"turn","at":"2026-02-28T23:51:26.108Z","payload":{"turn":{"id":"5a69b92d-92f6-4f16-84d7-858273501855","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","turnNumber":0,"speaker":"mux","role":"bailiff","phase":"case_prompt","dialogue":"All rise. The JuryRigged court is now in session. Case: is the defendant guilty of freely farting on an airplane?","createdAt":"2026-02-28T23:51:26.104Z"}}}
{"id":"c6f9bebd-6c93-4b42-b9ee-2478d513082e","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"phase_changed","at":"2026-02-28T23:51:27.316Z","payload":{"phase":"openings","phaseStartedAt":"2026-02-28T23:51:27.309Z","phaseDurationMs":30000}}
{"id":"d91b0ca8-4fe0-4044-b145-c7e461c54547","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"turn","at":"2026-02-28T23:51:31.953Z","payload":{"turn":{"id":"6153f5fe-633c-4ee2-8868-e3d273b2805e","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","turnNumber":1,"speaker":"subrosa","role":"prosecutor","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-02-28T23:51:31.949Z"}}}
{"id":"31a03df7-f935-403f-8862-b6664f7dea2d","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"render_directive","at":"2026-02-28T23:51:31.954Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"6153f5fe-633c-4ee2-8868-e3d273b2805e","phase":"openings","emittedAt":"2026-02-28T23:51:31.954Z"}}
{"id":"d323a50c-fea2-4d00-b389-5c5ce411b653","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"token_budget_applied","at":"2026-02-28T23:51:31.954Z","payload":{"turnId":"6153f5fe-633c-4ee2-8868-e3d273b2805e","speaker":"subrosa","role":"prosecutor","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"344db32c-3097-4985-8605-3998eadca13a","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"session_token_estimate","at":"2026-02-28T23:51:31.954Z","payload":{"turnId":"6153f5fe-633c-4ee2-8868-e3d273b2805e","role":"prosecutor","phase":"openings","estimatedPromptTokens":146,"estimatedCompletionTokens":22,"cumulativeEstimatedTokens":168,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.000336}}
{"id":"ac9f52c2-3280-44ac-ac7a-e71562b67932","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"turn","at":"2026-02-28T23:51:36.393Z","payload":{"turn":{"id":"e7bd4704-1397-4dd6-8c90-2f5b16f7f1e2","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","turnNumber":2,"speaker":"chora","role":"defense","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-02-28T23:51:36.390Z"}}}
{"id":"d50edccd-24c5-426c-b790-6ddf976e8a9e","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"render_directive","at":"2026-02-28T23:51:36.394Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"e7bd4704-1397-4dd6-8c90-2f5b16f7f1e2","phase":"openings","emittedAt":"2026-02-28T23:51:36.394Z"}}
{"id":"ae340317-0016-421e-921c-5605344f515e","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"token_budget_applied","at":"2026-02-28T23:51:36.394Z","payload":{"turnId":"e7bd4704-1397-4dd6-8c90-2f5b16f7f1e2","speaker":"chora","role":"defense","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"5da15f78-35dd-4e00-8e53-5a8e12761d7d","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"session_token_estimate","at":"2026-02-28T23:51:36.394Z","payload":{"turnId":"e7bd4704-1397-4dd6-8c90-2f5b16f7f1e2","role":"defense","phase":"openings","estimatedPromptTokens":306,"estimatedCompletionTokens":44,"cumulativeEstimatedTokens":350,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.0007}}
{"id":"b8f06ddf-8db3-4488-9383-8ce546a88b0a","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"phase_changed","at":"2026-02-28T23:51:36.398Z","payload":{"phase":"witness_exam","phaseStartedAt":"2026-02-28T23:51:36.396Z","phaseDurationMs":40000}}
{"id":"97bc906b-2826-4be8-ad83-25fa6e060ee6","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"turn","at":"2026-02-28T23:51:40.333Z","payload":{"turn":{"id":"bc2791fe-f2fa-4918-934e-0407e1c9ba29","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","turnNumber":3,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:51:40.329Z"}}}
{"id":"efe28a63-b766-4d8e-becd-4caa92aa3b0a","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"render_directive","at":"2026-02-28T23:51:40.333Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"bc2791fe-f2fa-4918-934e-0407e1c9ba29","phase":"witness_exam","emittedAt":"2026-02-28T23:51:40.333Z"}}
{"id":"b8615e6f-047c-4285-9725-54ff4ff5d841","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"token_budget_applied","at":"2026-02-28T23:51:40.333Z","payload":{"turnId":"bc2791fe-f2fa-4918-934e-0407e1c9ba29","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"a147bd21-cf64-4801-a4d8-01eeaacc2cba","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"session_token_estimate","at":"2026-02-28T23:51:40.333Z","payload":{"turnId":"bc2791fe-f2fa-4918-934e-0407e1c9ba29","role":"judge","phase":"witness_exam","estimatedPromptTokens":495,"estimatedCompletionTokens":64,"cumulativeEstimatedTokens":559,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001118}}
{"id":"bc563a51-7433-476f-af79-ed67cfa42bfd","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"turn","at":"2026-02-28T23:51:43.312Z","payload":{"turn":{"id":"3248fab8-b575-409c-a2e8-2a61e695b7a3","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","turnNumber":4,"speaker":"thaum","role":"witness_1","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:51:43.307Z"}}}
{"id":"bdc5b730-df09-4376-8c7f-0fe8b3ddcb5e","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"render_directive","at":"2026-02-28T23:51:43.312Z","payload":{"directive":{"camera":"witness","poses":{"witness_1":"talk"}},"turnId":"3248fab8-b575-409c-a2e8-2a61e695b7a3","phase":"witness_exam","emittedAt":"2026-02-28T23:51:43.312Z"}}
{"id":"9dac5655-acd3-48a1-a832-79a07da53c3c","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"witness_statement","at":"2026-02-28T23:51:43.312Z","payload":{"statement":{"witnessRole":"witness_1","agentId":"thaum","statementText":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","issuedAt":"2026-02-28T23:51:43.312Z"},"phase":"witness_exam","emittedAt":"2026-02-28T23:51:43.312Z"}}
{"id":"ed7e43cd-246c-47e4-85bc-aa0a4aa7ece8","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"token_budget_applied","at":"2026-02-28T23:51:43.312Z","payload":{"turnId":"3248fab8-b575-409c-a2e8-2a61e695b7a3","speaker":"thaum","role":"witness_1","phase":"witness_exam","requestedMaxTokens":90,"appliedMaxTokens":90,"roleMaxTokens":160,"source":"requested"}}
{"id":"71cb525d-e826-40f7-a39f-4f747eb670db","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"session_token_estimate","at":"2026-02-28T23:51:43.312Z","payload":{"turnId":"3248fab8-b575-409c-a2e8-2a61e695b7a3","role":"witness_1","phase":"witness_exam","estimatedPromptTokens":704,"estimatedCompletionTokens":84,"cumulativeEstimatedTokens":788,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001576}}
{"id":"aca6ae8a-9999-47d7-b9b2-ce600d62c95f","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"turn","at":"2026-02-28T23:51:49.338Z","payload":{"turn":{"id":"3005e309-7e6f-4043-ab05-107a0059680b","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","turnNumber":5,"speaker":"subrosa","role":"prosecutor","phase":"witness_exam","dialogue":"Witness, you were observing conduct at 2","createdAt":"2026-02-28T23:51:49.335Z"}}}
{"id":"dfa205d1-5cff-4cdf-a46a-6bade3114429","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"render_directive","at":"2026-02-28T23:51:49.338Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"3005e309-7e6f-4043-ab05-107a0059680b","phase":"witness_exam","emittedAt":"2026-02-28T23:51:49.338Z"}}
{"id":"972589b5-4fa5-4b4a-ac24-5bb1a750927f","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"token_budget_applied","at":"2026-02-28T23:51:49.338Z","payload":{"turnId":"3005e309-7e6f-4043-ab05-107a0059680b","speaker":"subrosa","role":"prosecutor","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"5a076db4-bfe1-495f-89b7-bd3408301be2","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"session_token_estimate","at":"2026-02-28T23:51:49.338Z","payload":{"turnId":"3005e309-7e6f-4043-ab05-107a0059680b","role":"prosecutor","phase":"witness_exam","estimatedPromptTokens":933,"estimatedCompletionTokens":91,"cumulativeEstimatedTokens":1024,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.002048}}
{"id":"1cd5b4bb-2d2c-4c22-ac3d-a1adb5e8debb","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"turn","at":"2026-02-28T23:51:53.362Z","payload":{"turn":{"id":"5ddd7482-bc79-415d-bc5d-c152c4548f0d","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","turnNumber":6,"speaker":"chora","role":"defense","phase":"witness_exam","dialogue":"Objection, your honor—my client was merely preparing a midnight yogurt parfait, not plotting a culinary crime spree.","createdAt":"2026-02-28T23:51:53.359Z"}}}
{"id":"a88345c6-6a94-4ceb-8cf7-595da9976173","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"render_directive","at":"2026-02-28T23:51:53.362Z","payload":{"directive":{"camera":"defense","poses":{"defense":"point"},"effect":"objection"},"turnId":"5ddd7482-bc79-415d-bc5d-c152c4548f0d","phase":"witness_exam","emittedAt":"2026-02-28T23:51:53.362Z"}}
{"id":"6e98c879-f9cb-46f4-8ec3-83ca7053e4e5","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"token_budget_applied","at":"2026-02-28T23:51:53.362Z","payload":{"turnId":"5ddd7482-bc79-415d-bc5d-c152c4548f0d","speaker":"chora","role":"defense","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"4067b154-080f-45b5-b921-a790c90081d2","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"session_token_estimate","at":"2026-02-28T23:51:53.363Z","payload":{"turnId":"5ddd7482-bc79-415d-bc5d-c152c4548f0d","role":"defense","phase":"witness_exam","estimatedPromptTokens":1172,"estimatedCompletionTokens":108,"cumulativeEstimatedTokens":1280,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00256}}
{"id":"270ae30a-e141-4dfa-818e-72a730b09dcb","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"turn","at":"2026-02-28T23:51:57.035Z","payload":{"turn":{"id":"98215fa1-a240-46f5-879c-451ce551dc96","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","turnNumber":7,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"Witness, did you observe the defendant's flatulence to be of a deliberate, volitional nature, or merely a gaseous happenstance of the pressurized cabin?","createdAt":"2026-02-28T23:51:57.034Z"}}}
{"id":"37d41cbe-8d86-4d2e-9d4b-5e19dcc833e7","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"render_directive","at":"2026-02-28T23:51:57.035Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"98215fa1-a240-46f5-879c-451ce551dc96","phase":"witness_exam","emittedAt":"2026-02-28T23:51:57.035Z"}}
{"id":"e6d123c1-26e6-4a14-8c17-35e8a2a5557b","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"token_budget_applied","at":"2026-02-28T23:51:57.035Z","payload":{"turnId":"98215fa1-a240-46f5-879c-451ce551dc96","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"4531c023-7ea5-4f1d-a079-bc63aee08dfa","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"session_token_estimate","at":"2026-02-28T23:51:57.036Z","payload":{"turnId":"98215fa1-a240-46f5-879c-451ce551dc96","role":"judge","phase":"witness_exam","estimatedPromptTokens":1433,"estimatedCompletionTokens":131,"cumulativeEstimatedTokens":1564,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.003128}}
{"id":"535f95bc-94ee-4e59-a869-3fab583ccfe6","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"turn","at":"2026-02-28T23:51:59.189Z","payload":{"turn":{"id":"c7332ade-f995-4f50-9385-c7140037b0fd","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","turnNumber":8,"speaker":"praxis","role":"witness_2","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:51:59.185Z"}}}
{"id":"ba8c6c0e-5085-4afb-a8a8-2d787dc402f9","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"render_directive","at":"2026-02-28T23:51:59.189Z","payload":{"directive":{"camera":"witness","poses":{"witness_2":"talk"}},"turnId":"c7332ade-f995-4f50-9385-c7140037b0fd","phase":"witness_exam","emittedAt":"2026-02-28T23:51:59.189Z"}}
{"id":"ce4ff56b-09f7-41cb-94fa-7da14583f134","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"witness_statement","at":"2026-02-28T23:51:59.189Z","payload":{"statement":{"witnessRole":"witness_2","agentId":"praxis","statementText":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","issuedAt":"2026-02-28T23:51:59.189Z"},"phase":"witness_exam","emittedAt":"2026-02-28T23:51:59.189Z"}}
{"id":"99c0e5b1-9e89-42f8-8a51-210c3714b334","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"token_budget_applied","at":"2026-02-28T23:51:59.189Z","payload":{"turnId":"c7332ade-f995-4f50-9385-c7140037b0fd","speaker":"praxis","role":"witness_2","phase":"witness_exam","requestedMaxTokens":90,"appliedMaxTokens":90,"roleMaxTokens":160,"source":"requested"}}
{"id":"3e1402b0-61f5-4b0e-9c0f-61d8b117a504","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"session_token_estimate","at":"2026-02-28T23:51:59.190Z","payload":{"turnId":"c7332ade-f995-4f50-9385-c7140037b0fd","role":"witness_2","phase":"witness_exam","estimatedPromptTokens":1717,"estimatedCompletionTokens":151,"cumulativeEstimatedTokens":1868,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.003736}}
{"id":"d1a4ae1d-11a7-4547-b66a-7b8cf95ac6e8","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"turn","at":"2026-02-28T23:52:08.076Z","payload":{"turn":{"id":"14b5748e-3c48-4f5f-b778-e01c34bb6f27","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","turnNumber":9,"speaker":"subrosa","role":"prosecutor","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:52:08.073Z"}}}
{"id":"5dace32d-f7e9-40e6-bbe9-ad6ccd2ce798","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"render_directive","at":"2026-02-28T23:52:08.076Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"14b5748e-3c48-4f5f-b778-e01c34bb6f27","phase":"witness_exam","emittedAt":"2026-02-28T23:52:08.076Z"}}
{"id":"6d09141b-0e7a-4ee2-82a9-6b47102f3bca","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"token_budget_applied","at":"2026-02-28T23:52:08.076Z","payload":{"turnId":"14b5748e-3c48-4f5f-b778-e01c34bb6f27","speaker":"subrosa","role":"prosecutor","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"2f6e804b-3f5d-48c6-a5e4-264026f0d519","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"session_token_estimate","at":"2026-02-28T23:52:08.076Z","payload":{"turnId":"14b5748e-3c48-4f5f-b778-e01c34bb6f27","role":"prosecutor","phase":"witness_exam","estimatedPromptTokens":2021,"estimatedCompletionTokens":171,"cumulativeEstimatedTokens":2192,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.004384}}
{"id":"f6f7bc40-c6c9-476e-9d69-b95530728afe","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"turn","at":"2026-02-28T23:52:16.001Z","payload":{"turn":{"id":"5584a6bb-a472-4d90-ac66-46cf9e906a49","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","turnNumber":10,"speaker":"chora","role":"defense","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:52:15.998Z"}}}
{"id":"b667b5ec-d52d-48b3-bf51-7089dc81a934","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"render_directive","at":"2026-02-28T23:52:16.001Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"5584a6bb-a472-4d90-ac66-46cf9e906a49","phase":"witness_exam","emittedAt":"2026-02-28T23:52:16.001Z"}}
{"id":"e529040d-44c1-4f75-8c87-26c3c358dd1b","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"token_budget_applied","at":"2026-02-28T23:52:16.001Z","payload":{"turnId":"5584a6bb-a472-4d90-ac66-46cf9e906a49","speaker":"chora","role":"defense","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"e1a7ff9e-1ec0-43f4-ad9b-679957de691a","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"session_token_estimate","at":"2026-02-28T23:52:16.001Z","payload":{"turnId":"5584a6bb-a472-4d90-ac66-46cf9e906a49","role":"defense","phase":"witness_exam","estimatedPromptTokens":2324,"estimatedCompletionTokens":191,"cumulativeEstimatedTokens":2515,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00503}}
{"id":"d07e1422-a101-4f91-bb6d-def817d13d08","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"turn","at":"2026-02-28T23:52:19.399Z","payload":{"turn":{"id":"8a7dbeeb-6354-4991-90d1-c9a07a96c3ba","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","turnNumber":11,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"Recap: The sole legal question before this court is whether the defendant's alleged emissions were a volitional act of atmospheric aggression or merely the cabin-pressure-induced sighs of a digesting digestive tract. We have heard testimony that the defendant held a spoon near the snack cabinet at 2:03 AM, an act the prosecution calls a pre-fart ritual and the defense calls a midnight par","createdAt":"2026-02-28T23:52:19.395Z"}}}
{"id":"35673ad1-8e22-4570-87c2-032270b8d657","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"render_directive","at":"2026-02-28T23:52:19.399Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"8a7dbeeb-6354-4991-90d1-c9a07a96c3ba","phase":"witness_exam","emittedAt":"2026-02-28T23:52:19.399Z"}}
{"id":"ab40f887-0c97-46fe-9c37-5cf11e78f387","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"token_budget_applied","at":"2026-02-28T23:52:19.399Z","payload":{"turnId":"8a7dbeeb-6354-4991-90d1-c9a07a96c3ba","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"44216f9c-033c-4fa0-9038-a2ada9f60b6a","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"session_token_estimate","at":"2026-02-28T23:52:19.399Z","payload":{"turnId":"8a7dbeeb-6354-4991-90d1-c9a07a96c3ba","role":"judge","phase":"witness_exam","estimatedPromptTokens":2632,"estimatedCompletionTokens":254,"cumulativeEstimatedTokens":2886,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.005772}}
{"id":"b6044886-791d-4d02-9da1-5384be5aa78f","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"judge_recap_emitted","at":"2026-02-28T23:52:19.403Z","payload":{"turnId":"8a7dbeeb-6354-4991-90d1-c9a07a96c3ba","phase":"witness_exam","cycleNumber":2}}
{"id":"6091d7a0-7b92-41c9-a00c-0a0fee1f6bbe","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"phase_changed","at":"2026-02-28T23:52:20.208Z","payload":{"phase":"closings","phaseStartedAt":"2026-02-28T23:52:20.204Z","phaseDurationMs":30000}}
{"id":"11ee3274-f134-4797-8e62-7e2774ed8892","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"turn","at":"2026-02-28T23:52:22.006Z","payload":{"turn":{"id":"6348b115-cbbf-4eb8-84d5-dbadd3066629","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","turnNumber":12,"speaker":"subrosa","role":"prosecutor","phase":"closings","dialogue":"At the end of the day, this is either a crime or a spectacular misunderstanding involving glitter and plausible deniability.","createdAt":"2026-02-28T23:52:22.003Z"}}}
{"id":"9c05a39a-de09-414b-a9a7-3c3b0505a7b0","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"render_directive","at":"2026-02-28T23:52:22.006Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"6348b115-cbbf-4eb8-84d5-dbadd3066629","phase":"closings","emittedAt":"2026-02-28T23:52:22.006Z"}}
{"id":"1ce2d0ac-eed7-4360-b1f7-902c178277cd","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"token_budget_applied","at":"2026-02-28T23:52:22.006Z","payload":{"turnId":"6348b115-cbbf-4eb8-84d5-dbadd3066629","speaker":"subrosa","role":"prosecutor","phase":"closings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"bfaccc30-c09f-4232-9a80-c5b59c6081b5","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"session_token_estimate","at":"2026-02-28T23:52:22.006Z","payload":{"turnId":"6348b115-cbbf-4eb8-84d5-dbadd3066629","role":"prosecutor","phase":"closings","estimatedPromptTokens":2978,"estimatedCompletionTokens":274,"cumulativeEstimatedTokens":3252,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.006504}}
{"id":"d9398657-865d-441d-aa80-62f5b73d69a5","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"turn","at":"2026-02-28T23:52:25.052Z","payload":{"turn":{"id":"bda1f377-f3ab-415b-82be-cc79cbf546dd","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","turnNumber":13,"speaker":"chora","role":"defense","phase":"closings","dialogue":"Your Honor, the state has failed to prove my clients","createdAt":"2026-02-28T23:52:25.049Z"}}}
{"id":"302f445e-1c8f-424c-89a8-6030cfe62053","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"render_directive","at":"2026-02-28T23:52:25.052Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"bda1f377-f3ab-415b-82be-cc79cbf546dd","phase":"closings","emittedAt":"2026-02-28T23:52:25.052Z"}}
{"id":"fc993310-a87a-4675-a1a9-f1ba16a1e81c","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"token_budget_applied","at":"2026-02-28T23:52:25.052Z","payload":{"turnId":"bda1f377-f3ab-415b-82be-cc79cbf546dd","speaker":"chora","role":"defense","phase":"closings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"b407f660-fb89-42be-991a-8ca127af3fab","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"session_token_estimate","at":"2026-02-28T23:52:25.052Z","payload":{"turnId":"bda1f377-f3ab-415b-82be-cc79cbf546dd","role":"defense","phase":"closings","estimatedPromptTokens":3319,"estimatedCompletionTokens":284,"cumulativeEstimatedTokens":3603,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.007206}}
{"id":"8ce449fd-10b1-4046-a7a2-a5f163705321","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"phase_changed","at":"2026-02-28T23:52:25.057Z","payload":{"phase":"verdict_vote","phaseStartedAt":"2026-02-28T23:52:25.054Z","phaseDurationMs":20000}}
{"id":"aa0185b8-90f5-4ed3-99c6-6b66755a9abe","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"analytics_event","at":"2026-02-28T23:52:25.057Z","payload":{"name":"poll_started","pollType":"verdict","phase":"verdict_vote"}}
{"id":"2975d2a5-b2f8-41e0-9a87-b36d7889b2bf","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"broadcast_hook_triggered","at":"2026-02-28T23:52:25.057Z","payload":{"phase":"verdict_vote","hookType":"scene_switch","triggeredAt":"2026-02-28T23:52:25.057Z"}}
{"id":"ab0d45dc-74c3-4e89-a15e-a0475f96f9aa","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"turn","at":"2026-02-28T23:52:25.060Z","payload":{"turn":{"id":"24d5d112-1fe5-43d5-be61-b767656f2d67","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","turnNumber":14,"speaker":"mux","role":"bailiff","phase":"verdict_vote","dialogue":"Jury poll is open: guilty / not_guilty. Cast your votes now.","createdAt":"2026-02-28T23:52:25.057Z"}}}
{"id":"ddd8b37b-330d-47b9-b1be-a537ecdab294","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"phase_changed","at":"2026-02-28T23:52:45.065Z","payload":{"phase":"sentence_vote","phaseStartedAt":"2026-02-28T23:52:45.061Z","phaseDurationMs":20000}}
{"id":"bb635d7b-af15-4d7b-aacd-fabe77f8185f","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"vote_closed","at":"2026-02-28T23:52:45.065Z","payload":{"pollType":"verdict","closedAt":"2026-02-28T23:52:45.061Z","votes":{},"nextPhase":"sentence_vote"}}
{"id":"d8955bf4-c86d-4a5e-81d3-77a9966b1e27","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"analytics_event","at":"2026-02-28T23:52:45.065Z","payload":{"name":"poll_closed","pollType":"verdict","phase":"sentence_vote"}}
{"id":"4893fc55-21e6-4372-998c-e5ef45c56a2a","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"analytics_event","at":"2026-02-28T23:52:45.065Z","payload":{"name":"poll_started","pollType":"sentence","phase":"sentence_vote"}}
{"id":"b207b20d-8c83-43ef-a0a9-c12f3458293d","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"broadcast_hook_triggered","at":"2026-02-28T23:52:45.065Z","payload":{"phase":"sentence_vote","hookType":"scene_switch","triggeredAt":"2026-02-28T23:52:45.065Z"}}
{"id":"6da03523-9010-4cc4-a0a3-ce6f9211fbe9","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"turn","at":"2026-02-28T23:52:45.067Z","payload":{"turn":{"id":"1b61a945-c03a-4c9c-a558-ab4d0d9f809e","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","turnNumber":15,"speaker":"mux","role":"bailiff","phase":"sentence_vote","dialogue":"Sentence poll is now open. Options: Community service in the meme archives | Banished to the shadow realm | Mandatory apology haikus | Ethics training hosted by a raccoon | Ukulele ankle-monitor probation","createdAt":"2026-02-28T23:52:45.065Z"}}}
{"id":"0edc9810-2c99-4256-8dd7-66348b299305","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"session_started","at":"2026-02-28T23:53:33.061Z","payload":{"sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","startedAt":"2026-02-28T23:51:26.087Z"}}
{"id":"26f4c6c7-a560-4098-abae-777d150e1a08","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"case_file_generated","at":"2026-02-28T23:53:33.062Z","payload":{"caseFile":{"title":"is the defendant guilty of freely farting on an airplane?","genre":"absurd_civil","caseType":"criminal","synopsis":"is the defendant guilty of freely farting on an airplane?","charges":["As stated in case prompt"],"witnesses":[],"evidence":[],"sentenceOptions":["Community service in the meme archives","Banished to the shadow realm","Mandatory apology haikus","Ethics training hosted by a raccoon","Ukulele ankle-monitor probation"]},"sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","generatedAt":"2026-02-28T23:53:33.062Z"}}
{"id":"df4e9563-5cd1-4a5d-bf76-52dbfc0a11bb","sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","type":"session_failed","at":"2026-02-28T23:53:33.069Z","payload":{"sessionId":"d082e8bc-9214-4560-9c55-d726b0b0e331","reason":"Invalid phase transition: sentence_vote -> case_prompt","completedAt":"2026-02-28T23:53:33.067Z"}}

View File

@@ -0,0 +1,82 @@
{"id":"22e267d2-1c81-4a84-a907-84aa1c1e804e","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"session_created","at":"2026-02-28T23:43:49.109Z","payload":{"sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d"}}
{"id":"43279f8f-492b-46bd-9a9a-d72c128133ae","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"session_started","at":"2026-02-28T23:43:49.113Z","payload":{"sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","startedAt":"2026-02-28T23:43:49.110Z"}}
{"id":"7f09cc85-7f26-4c25-92c2-46ec5d238619","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"case_file_generated","at":"2026-02-28T23:43:49.113Z","payload":{"caseFile":{"title":"is the defendant guilty of freely farting on an airplane?","genre":"workplace_tribunal","caseType":"criminal","synopsis":"is the defendant guilty of freely farting on an airplane?","charges":["As stated in case prompt"],"witnesses":[],"evidence":[],"sentenceOptions":["Community service in the meme archives","Banished to the shadow realm","Mandatory apology haikus","Ethics training hosted by a raccoon","Ukulele ankle-monitor probation"]},"sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","generatedAt":"2026-02-28T23:43:49.113Z"}}
{"id":"ed8e4167-68f8-4706-b7cc-95832643ed07","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"phase_changed","at":"2026-02-28T23:43:49.121Z","payload":{"phase":"case_prompt","phaseStartedAt":"2026-02-28T23:43:49.117Z","phaseDurationMs":8000}}
{"id":"22a4ac38-daf5-48bb-95f1-a0a9aec93c57","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"broadcast_hook_triggered","at":"2026-02-28T23:43:49.121Z","payload":{"phase":"case_prompt","hookType":"phase_stinger","triggeredAt":"2026-02-28T23:43:49.121Z"}}
{"id":"d55e2e83-ce6e-4aca-8410-19653207aa1b","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"turn","at":"2026-02-28T23:43:49.124Z","payload":{"turn":{"id":"d99daa8b-013f-46f9-ba68-34fd43dceaa7","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","turnNumber":0,"speaker":"mux","role":"bailiff","phase":"case_prompt","dialogue":"All rise. The JuryRigged court is now in session. Case: is the defendant guilty of freely farting on an airplane?","createdAt":"2026-02-28T23:43:49.121Z"}}}
{"id":"cf9e12ff-2834-4d91-bca9-07d694b7fc08","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"phase_changed","at":"2026-02-28T23:43:50.330Z","payload":{"phase":"openings","phaseStartedAt":"2026-02-28T23:43:50.325Z","phaseDurationMs":30000}}
{"id":"e60b4bf0-e0af-443d-bc9b-22278399265c","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"turn","at":"2026-02-28T23:43:50.334Z","payload":{"turn":{"id":"8f1c005e-cfc4-4c93-a2e7-cc06579de0a3","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","turnNumber":1,"speaker":"subrosa","role":"prosecutor","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-02-28T23:43:50.331Z"}}}
{"id":"5be83131-5a8f-45ed-bab2-11763665d83f","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"render_directive","at":"2026-02-28T23:43:50.334Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"8f1c005e-cfc4-4c93-a2e7-cc06579de0a3","phase":"openings","emittedAt":"2026-02-28T23:43:50.334Z"}}
{"id":"5ea795e9-dd15-4407-979f-fc2a5803fa17","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"token_budget_applied","at":"2026-02-28T23:43:50.334Z","payload":{"turnId":"8f1c005e-cfc4-4c93-a2e7-cc06579de0a3","speaker":"subrosa","role":"prosecutor","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"a57e6aa2-cd5c-4d12-afad-3811ae028b10","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"session_token_estimate","at":"2026-02-28T23:43:50.334Z","payload":{"turnId":"8f1c005e-cfc4-4c93-a2e7-cc06579de0a3","role":"prosecutor","phase":"openings","estimatedPromptTokens":141,"estimatedCompletionTokens":22,"cumulativeEstimatedTokens":163,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.000326}}
{"id":"91c4feee-6dd5-4330-a441-35b03961345b","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"turn","at":"2026-02-28T23:43:51.238Z","payload":{"turn":{"id":"ebf86395-45b3-4e1f-8149-253c30f40645","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","turnNumber":2,"speaker":"chora","role":"defense","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-02-28T23:43:51.235Z"}}}
{"id":"2fec530d-d446-4773-aafb-c03b169bd386","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"render_directive","at":"2026-02-28T23:43:51.238Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"ebf86395-45b3-4e1f-8149-253c30f40645","phase":"openings","emittedAt":"2026-02-28T23:43:51.238Z"}}
{"id":"17391916-03ab-4483-a60e-a6dfa08a8953","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"token_budget_applied","at":"2026-02-28T23:43:51.238Z","payload":{"turnId":"ebf86395-45b3-4e1f-8149-253c30f40645","speaker":"chora","role":"defense","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"5d754e52-69ac-4b7c-843e-7b532af0d839","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"session_token_estimate","at":"2026-02-28T23:43:51.238Z","payload":{"turnId":"ebf86395-45b3-4e1f-8149-253c30f40645","role":"defense","phase":"openings","estimatedPromptTokens":299,"estimatedCompletionTokens":44,"cumulativeEstimatedTokens":343,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.000686}}
{"id":"7a8d6c3c-ce3e-4c0b-aeb2-54c1675df006","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"phase_changed","at":"2026-02-28T23:43:51.244Z","payload":{"phase":"witness_exam","phaseStartedAt":"2026-02-28T23:43:51.241Z","phaseDurationMs":40000}}
{"id":"41ccaf5a-1563-4caa-b986-4ad5a45a7f4a","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"turn","at":"2026-02-28T23:43:51.849Z","payload":{"turn":{"id":"da808001-7d52-41e8-9386-1ced4688a7b3","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","turnNumber":3,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:43:51.844Z"}}}
{"id":"31d522cd-d517-428c-afd4-942f9e32f2fb","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"render_directive","at":"2026-02-28T23:43:51.849Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"da808001-7d52-41e8-9386-1ced4688a7b3","phase":"witness_exam","emittedAt":"2026-02-28T23:43:51.849Z"}}
{"id":"28d5d484-8de9-424c-883b-c8753193aff4","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"token_budget_applied","at":"2026-02-28T23:43:51.849Z","payload":{"turnId":"da808001-7d52-41e8-9386-1ced4688a7b3","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"4a0eb31f-6e8b-4ae2-8f40-1879151f24b3","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"session_token_estimate","at":"2026-02-28T23:43:51.849Z","payload":{"turnId":"da808001-7d52-41e8-9386-1ced4688a7b3","role":"judge","phase":"witness_exam","estimatedPromptTokens":485,"estimatedCompletionTokens":64,"cumulativeEstimatedTokens":549,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001098}}
{"id":"7962069e-52f5-44e0-b4cb-dd6173983718","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"turn","at":"2026-02-28T23:43:52.455Z","payload":{"turn":{"id":"32af1059-aa6d-4943-b991-a1af433b9aae","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","turnNumber":4,"speaker":"thaum","role":"witness_1","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:43:52.450Z"}}}
{"id":"ab5f7b5d-bb57-46fa-90c1-25286e271e1b","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"render_directive","at":"2026-02-28T23:43:52.455Z","payload":{"directive":{"camera":"witness","poses":{"witness_1":"talk"}},"turnId":"32af1059-aa6d-4943-b991-a1af433b9aae","phase":"witness_exam","emittedAt":"2026-02-28T23:43:52.455Z"}}
{"id":"57c85815-d25a-4243-97e2-4ebf77c41710","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"witness_statement","at":"2026-02-28T23:43:52.455Z","payload":{"statement":{"witnessRole":"witness_1","agentId":"thaum","statementText":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","issuedAt":"2026-02-28T23:43:52.455Z"},"phase":"witness_exam","emittedAt":"2026-02-28T23:43:52.455Z"}}
{"id":"c1cab810-463f-4f86-b3e9-885af996c55e","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"token_budget_applied","at":"2026-02-28T23:43:52.455Z","payload":{"turnId":"32af1059-aa6d-4943-b991-a1af433b9aae","speaker":"thaum","role":"witness_1","phase":"witness_exam","requestedMaxTokens":90,"appliedMaxTokens":90,"roleMaxTokens":160,"source":"requested"}}
{"id":"51bbdad3-346b-4bd9-9121-8c5ce30ebe00","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"session_token_estimate","at":"2026-02-28T23:43:52.455Z","payload":{"turnId":"32af1059-aa6d-4943-b991-a1af433b9aae","role":"witness_1","phase":"witness_exam","estimatedPromptTokens":694,"estimatedCompletionTokens":84,"cumulativeEstimatedTokens":778,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.001556}}
{"id":"0cee3dfa-74b0-44d1-8e64-c9ecdf4c735d","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"turn","at":"2026-02-28T23:43:53.060Z","payload":{"turn":{"id":"791e363d-c1c3-4fa0-9bd9-93c482844a45","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","turnNumber":5,"speaker":"subrosa","role":"prosecutor","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:43:53.055Z"}}}
{"id":"3fd10a18-e89c-4454-b430-f6eb6f9bc366","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"render_directive","at":"2026-02-28T23:43:53.060Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"791e363d-c1c3-4fa0-9bd9-93c482844a45","phase":"witness_exam","emittedAt":"2026-02-28T23:43:53.060Z"}}
{"id":"d679587c-b556-4376-a187-b738b71125d2","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"token_budget_applied","at":"2026-02-28T23:43:53.060Z","payload":{"turnId":"791e363d-c1c3-4fa0-9bd9-93c482844a45","speaker":"subrosa","role":"prosecutor","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"e992169d-b247-42a0-b602-9aff8cef236e","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"session_token_estimate","at":"2026-02-28T23:43:53.060Z","payload":{"turnId":"791e363d-c1c3-4fa0-9bd9-93c482844a45","role":"prosecutor","phase":"witness_exam","estimatedPromptTokens":918,"estimatedCompletionTokens":104,"cumulativeEstimatedTokens":1022,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.002044}}
{"id":"2fe0fc03-9b23-4995-8f37-4bb11e151b12","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"turn","at":"2026-02-28T23:43:53.665Z","payload":{"turn":{"id":"7e86437d-0151-481d-8645-7b92eb094171","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","turnNumber":6,"speaker":"chora","role":"defense","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:43:53.660Z"}}}
{"id":"93257351-cbf5-4f77-8c66-2aa48fd8200f","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"render_directive","at":"2026-02-28T23:43:53.665Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"7e86437d-0151-481d-8645-7b92eb094171","phase":"witness_exam","emittedAt":"2026-02-28T23:43:53.665Z"}}
{"id":"ad86c10a-bede-4c8d-bcc1-3dc2faefefc8","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"token_budget_applied","at":"2026-02-28T23:43:53.665Z","payload":{"turnId":"7e86437d-0151-481d-8645-7b92eb094171","speaker":"chora","role":"defense","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"fd8599d5-aa1f-42b0-bb0a-26d53ed5970d","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"session_token_estimate","at":"2026-02-28T23:43:53.665Z","payload":{"turnId":"7e86437d-0151-481d-8645-7b92eb094171","role":"defense","phase":"witness_exam","estimatedPromptTokens":1168,"estimatedCompletionTokens":124,"cumulativeEstimatedTokens":1292,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.002584}}
{"id":"c3782e20-f073-4acd-96af-ea3f13e1afd8","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"turn","at":"2026-02-28T23:43:54.471Z","payload":{"turn":{"id":"860cd57c-1055-4adf-a8d3-ea2e04d19a09","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","turnNumber":7,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:43:54.466Z"}}}
{"id":"865f77e4-622f-4973-ad6c-7007a3ade3b6","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"render_directive","at":"2026-02-28T23:43:54.471Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"860cd57c-1055-4adf-a8d3-ea2e04d19a09","phase":"witness_exam","emittedAt":"2026-02-28T23:43:54.471Z"}}
{"id":"f915f114-8c9b-4985-8c6e-64120b75c1d8","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"token_budget_applied","at":"2026-02-28T23:43:54.471Z","payload":{"turnId":"860cd57c-1055-4adf-a8d3-ea2e04d19a09","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"0acf126e-f938-4da7-bc0c-61ee31582a6c","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"session_token_estimate","at":"2026-02-28T23:43:54.471Z","payload":{"turnId":"860cd57c-1055-4adf-a8d3-ea2e04d19a09","role":"judge","phase":"witness_exam","estimatedPromptTokens":1442,"estimatedCompletionTokens":144,"cumulativeEstimatedTokens":1586,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.003172}}
{"id":"4d84ecd9-561d-4030-82d9-fba7373133f4","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"turn","at":"2026-02-28T23:43:55.076Z","payload":{"turn":{"id":"a997f939-3022-4c53-913a-ee44f37b6dd5","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","turnNumber":8,"speaker":"praxis","role":"witness_2","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:43:55.072Z"}}}
{"id":"c800c886-48a4-4788-8427-fd4ccd25a3aa","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"render_directive","at":"2026-02-28T23:43:55.076Z","payload":{"directive":{"camera":"witness","poses":{"witness_2":"talk"}},"turnId":"a997f939-3022-4c53-913a-ee44f37b6dd5","phase":"witness_exam","emittedAt":"2026-02-28T23:43:55.076Z"}}
{"id":"9da0f360-7ba9-449e-8a44-9cb1b7f4bc69","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"witness_statement","at":"2026-02-28T23:43:55.077Z","payload":{"statement":{"witnessRole":"witness_2","agentId":"praxis","statementText":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","issuedAt":"2026-02-28T23:43:55.076Z"},"phase":"witness_exam","emittedAt":"2026-02-28T23:43:55.077Z"}}
{"id":"ac98e32a-2278-414f-a06e-208e5d4de01e","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"token_budget_applied","at":"2026-02-28T23:43:55.077Z","payload":{"turnId":"a997f939-3022-4c53-913a-ee44f37b6dd5","speaker":"praxis","role":"witness_2","phase":"witness_exam","requestedMaxTokens":90,"appliedMaxTokens":90,"roleMaxTokens":160,"source":"requested"}}
{"id":"ea68dc51-145a-4d72-869d-aa2df41d2d4b","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"session_token_estimate","at":"2026-02-28T23:43:55.077Z","payload":{"turnId":"a997f939-3022-4c53-913a-ee44f37b6dd5","role":"witness_2","phase":"witness_exam","estimatedPromptTokens":1739,"estimatedCompletionTokens":164,"cumulativeEstimatedTokens":1903,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.003806}}
{"id":"02a43d26-0664-4a60-8362-4f77beff30b6","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"turn","at":"2026-02-28T23:43:55.681Z","payload":{"turn":{"id":"c6656523-309c-4854-8cc0-eb2df3fe4d7e","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","turnNumber":9,"speaker":"subrosa","role":"prosecutor","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:43:55.678Z"}}}
{"id":"6ce3d142-523e-496b-8451-f1ddfa1bc11b","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"render_directive","at":"2026-02-28T23:43:55.681Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"c6656523-309c-4854-8cc0-eb2df3fe4d7e","phase":"witness_exam","emittedAt":"2026-02-28T23:43:55.681Z"}}
{"id":"49f99865-52fb-4e41-b5ae-3a0bfd6a9f58","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"token_budget_applied","at":"2026-02-28T23:43:55.681Z","payload":{"turnId":"c6656523-309c-4854-8cc0-eb2df3fe4d7e","speaker":"subrosa","role":"prosecutor","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"cc3da6d9-6045-4872-86e3-c77684bb84c0","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"session_token_estimate","at":"2026-02-28T23:43:55.681Z","payload":{"turnId":"c6656523-309c-4854-8cc0-eb2df3fe4d7e","role":"prosecutor","phase":"witness_exam","estimatedPromptTokens":2051,"estimatedCompletionTokens":184,"cumulativeEstimatedTokens":2235,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00447}}
{"id":"adc59a76-ade1-40ef-92af-b9c65443879d","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"turn","at":"2026-02-28T23:43:56.284Z","payload":{"turn":{"id":"66b3d709-72a0-4f8e-8c96-996e6327e381","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","turnNumber":10,"speaker":"chora","role":"defense","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:43:56.281Z"}}}
{"id":"316ff789-b080-45b6-88d3-8d1e937842e0","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"render_directive","at":"2026-02-28T23:43:56.284Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"66b3d709-72a0-4f8e-8c96-996e6327e381","phase":"witness_exam","emittedAt":"2026-02-28T23:43:56.284Z"}}
{"id":"2a4f2db3-7c05-48f4-ad23-fed6c7afd024","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"token_budget_applied","at":"2026-02-28T23:43:56.284Z","payload":{"turnId":"66b3d709-72a0-4f8e-8c96-996e6327e381","speaker":"chora","role":"defense","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"f10bc198-1cbd-4fa2-941c-479210e7130a","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"session_token_estimate","at":"2026-02-28T23:43:56.284Z","payload":{"turnId":"66b3d709-72a0-4f8e-8c96-996e6327e381","role":"defense","phase":"witness_exam","estimatedPromptTokens":2365,"estimatedCompletionTokens":204,"cumulativeEstimatedTokens":2569,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.005138}}
{"id":"a37f3298-8aed-4bf3-9501-8fe52c9478e2","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"turn","at":"2026-02-28T23:43:56.890Z","payload":{"turn":{"id":"c3b75092-58c4-44a2-b424-dd2cd7380c65","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","turnNumber":11,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"Recap: Order in the court. I acknowledge the point and move us to the next absurdly important matter.","createdAt":"2026-02-28T23:43:56.885Z"}}}
{"id":"8fc77614-9dc1-4c8d-a1f4-a83a0922b0a0","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"render_directive","at":"2026-02-28T23:43:56.890Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"c3b75092-58c4-44a2-b424-dd2cd7380c65","phase":"witness_exam","emittedAt":"2026-02-28T23:43:56.890Z"}}
{"id":"03b9e1c4-e9c3-4ace-b84a-1b2cc81a6e91","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"token_budget_applied","at":"2026-02-28T23:43:56.890Z","payload":{"turnId":"c3b75092-58c4-44a2-b424-dd2cd7380c65","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"4a6dbd58-2a3f-474f-bbfb-a9d2babe19fc","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"session_token_estimate","at":"2026-02-28T23:43:56.890Z","payload":{"turnId":"c3b75092-58c4-44a2-b424-dd2cd7380c65","role":"judge","phase":"witness_exam","estimatedPromptTokens":2683,"estimatedCompletionTokens":222,"cumulativeEstimatedTokens":2905,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00581}}
{"id":"83033b0d-50fb-4a52-9be2-b15048885341","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"judge_recap_emitted","at":"2026-02-28T23:43:56.896Z","payload":{"turnId":"c3b75092-58c4-44a2-b424-dd2cd7380c65","phase":"witness_exam","cycleNumber":2}}
{"id":"1b486c63-ccb4-4c63-9157-624e458c17fa","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"phase_changed","at":"2026-02-28T23:43:57.702Z","payload":{"phase":"closings","phaseStartedAt":"2026-02-28T23:43:57.697Z","phaseDurationMs":30000}}
{"id":"ba43372b-c93f-4bec-bd40-71bd80648eb4","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"turn","at":"2026-02-28T23:43:57.705Z","payload":{"turn":{"id":"eb6993e2-ac60-406f-a3b8-0c0f64bf89ce","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","turnNumber":12,"speaker":"subrosa","role":"prosecutor","phase":"closings","dialogue":"At the end of the day, this is either a crime or a spectacular misunderstanding involving glitter and plausible deniability.","createdAt":"2026-02-28T23:43:57.703Z"}}}
{"id":"1ce5e8c7-7429-4e83-9857-60793bc48336","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"render_directive","at":"2026-02-28T23:43:57.705Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"eb6993e2-ac60-406f-a3b8-0c0f64bf89ce","phase":"closings","emittedAt":"2026-02-28T23:43:57.705Z"}}
{"id":"66801ec6-3819-4bc6-a586-ac2be23edd8e","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"token_budget_applied","at":"2026-02-28T23:43:57.705Z","payload":{"turnId":"eb6993e2-ac60-406f-a3b8-0c0f64bf89ce","speaker":"subrosa","role":"prosecutor","phase":"closings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"ad9b442d-d330-4aeb-94ab-4b22372d23f1","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"session_token_estimate","at":"2026-02-28T23:43:57.705Z","payload":{"turnId":"eb6993e2-ac60-406f-a3b8-0c0f64bf89ce","role":"prosecutor","phase":"closings","estimatedPromptTokens":2992,"estimatedCompletionTokens":242,"cumulativeEstimatedTokens":3234,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.006468}}
{"id":"3bfd5957-c31e-4ab7-98e3-d482e2fe48b2","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"turn","at":"2026-02-28T23:43:58.510Z","payload":{"turn":{"id":"12422285-a7c5-4b13-9729-66fa5c4e9736","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","turnNumber":13,"speaker":"chora","role":"defense","phase":"closings","dialogue":"At the end of the day, this is either a crime or a spectacular misunderstanding involving glitter and plausible deniability.","createdAt":"2026-02-28T23:43:58.507Z"}}}
{"id":"00366355-0b85-4145-ad7e-559a44a08897","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"render_directive","at":"2026-02-28T23:43:58.510Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"12422285-a7c5-4b13-9729-66fa5c4e9736","phase":"closings","emittedAt":"2026-02-28T23:43:58.510Z"}}
{"id":"cee4e74f-e458-4a40-9b68-9916dab772c3","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"token_budget_applied","at":"2026-02-28T23:43:58.510Z","payload":{"turnId":"12422285-a7c5-4b13-9729-66fa5c4e9736","speaker":"chora","role":"defense","phase":"closings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"af960f5e-9042-4f54-9a1d-09070fe8e1ef","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"session_token_estimate","at":"2026-02-28T23:43:58.511Z","payload":{"turnId":"12422285-a7c5-4b13-9729-66fa5c4e9736","role":"defense","phase":"closings","estimatedPromptTokens":3299,"estimatedCompletionTokens":262,"cumulativeEstimatedTokens":3561,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.007122}}
{"id":"43caff18-e799-4041-94d6-db83306c327f","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"phase_changed","at":"2026-02-28T23:43:58.514Z","payload":{"phase":"verdict_vote","phaseStartedAt":"2026-02-28T23:43:58.513Z","phaseDurationMs":20000}}
{"id":"e3e616f7-d492-4668-b23b-9d35c7a91959","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"analytics_event","at":"2026-02-28T23:43:58.514Z","payload":{"name":"poll_started","pollType":"verdict","phase":"verdict_vote"}}
{"id":"90f0344a-8eef-44a5-ad42-c749d39b329d","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"broadcast_hook_triggered","at":"2026-02-28T23:43:58.514Z","payload":{"phase":"verdict_vote","hookType":"scene_switch","triggeredAt":"2026-02-28T23:43:58.514Z"}}
{"id":"c63103b9-83f1-4ae5-b36d-de00454bc730","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"turn","at":"2026-02-28T23:43:58.518Z","payload":{"turn":{"id":"a9cad122-e31c-4fda-9a03-ee563206b1f9","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","turnNumber":14,"speaker":"mux","role":"bailiff","phase":"verdict_vote","dialogue":"Jury poll is open: guilty / not_guilty. Cast your votes now.","createdAt":"2026-02-28T23:43:58.515Z"}}}
{"id":"5efd8bca-6bef-45b8-b4dc-2adec818dab1","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"phase_changed","at":"2026-02-28T23:44:18.521Z","payload":{"phase":"sentence_vote","phaseStartedAt":"2026-02-28T23:44:18.519Z","phaseDurationMs":20000}}
{"id":"d252e55c-dd0e-4902-8219-e02fa7cfb589","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"vote_closed","at":"2026-02-28T23:44:18.521Z","payload":{"pollType":"verdict","closedAt":"2026-02-28T23:44:18.519Z","votes":{},"nextPhase":"sentence_vote"}}
{"id":"10a93925-fc95-417f-b95c-1d49466f8304","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"analytics_event","at":"2026-02-28T23:44:18.521Z","payload":{"name":"poll_closed","pollType":"verdict","phase":"sentence_vote"}}
{"id":"04d53f93-57ee-430b-8d12-54ba03aba97f","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"analytics_event","at":"2026-02-28T23:44:18.521Z","payload":{"name":"poll_started","pollType":"sentence","phase":"sentence_vote"}}
{"id":"f060ffe6-9d01-41c2-b459-7b04a18e7904","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"broadcast_hook_triggered","at":"2026-02-28T23:44:18.521Z","payload":{"phase":"sentence_vote","hookType":"scene_switch","triggeredAt":"2026-02-28T23:44:18.521Z"}}
{"id":"ee472abb-9171-449b-b18b-e14f95471f34","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"turn","at":"2026-02-28T23:44:18.523Z","payload":{"turn":{"id":"eb8e882d-9b61-4693-8494-b109e8d34a14","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","turnNumber":15,"speaker":"mux","role":"bailiff","phase":"sentence_vote","dialogue":"Sentence poll is now open. Options: Community service in the meme archives | Banished to the shadow realm | Mandatory apology haikus | Ethics training hosted by a raccoon | Ukulele ankle-monitor probation","createdAt":"2026-02-28T23:44:18.522Z"}}}
{"id":"2589c2e1-ede4-42f1-9e04-aa8bf259aac8","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"phase_changed","at":"2026-02-28T23:44:38.529Z","payload":{"phase":"final_ruling","phaseStartedAt":"2026-02-28T23:44:38.524Z","phaseDurationMs":20000}}
{"id":"fd6ed3bb-5c88-4723-9d6c-9d58a62f93fd","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"vote_closed","at":"2026-02-28T23:44:38.529Z","payload":{"pollType":"sentence","closedAt":"2026-02-28T23:44:38.524Z","votes":{},"nextPhase":"final_ruling"}}
{"id":"7a1f65ed-1639-4ecc-819a-33a2a1063bae","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"analytics_event","at":"2026-02-28T23:44:38.529Z","payload":{"name":"poll_closed","pollType":"sentence","phase":"final_ruling"}}
{"id":"08bd2a28-1c42-43f9-9c53-74e0346de968","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"turn","at":"2026-02-28T23:44:38.536Z","payload":{"turn":{"id":"31105a79-632a-471c-a720-87d34e715518","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","turnNumber":16,"speaker":"primus","role":"judge","phase":"final_ruling","dialogue":"On the charge of chaos in the first degree, this court finds the defendant dramatically guilty—with style points.","createdAt":"2026-02-28T23:44:38.534Z"}}}
{"id":"7de91484-af8b-4a0c-b885-327b4bb4a141","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"render_directive","at":"2026-02-28T23:44:38.537Z","payload":{"directive":{"camera":"verdict","poses":{"judge":"talk"}},"turnId":"31105a79-632a-471c-a720-87d34e715518","phase":"final_ruling","emittedAt":"2026-02-28T23:44:38.537Z"}}
{"id":"b3b298d8-6c38-4d3f-aa2d-cb497e929886","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"token_budget_applied","at":"2026-02-28T23:44:38.537Z","payload":{"turnId":"31105a79-632a-471c-a720-87d34e715518","speaker":"primus","role":"judge","phase":"final_ruling","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"d4a99aa5-8e9f-441b-a01b-bab5b2781179","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"session_token_estimate","at":"2026-02-28T23:44:38.537Z","payload":{"turnId":"31105a79-632a-471c-a720-87d34e715518","role":"judge","phase":"final_ruling","estimatedPromptTokens":3623,"estimatedCompletionTokens":280,"cumulativeEstimatedTokens":3903,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.007806}}
{"id":"36fb1a51-861e-46d5-ab70-0f78bdfb5881","sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","type":"session_completed","at":"2026-02-28T23:44:38.543Z","payload":{"sessionId":"f087ce7a-9c37-4f88-87e6-c20f8bd04c6d","completedAt":"2026-02-28T23:44:38.537Z"}}

View File

@@ -0,0 +1,23 @@
{"id":"fc9db50a-a6bf-4405-b7f3-d856438edefa","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"session_created","at":"2026-02-28T23:52:44.928Z","payload":{"sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a"}}
{"id":"b0abdf4f-5327-4562-b2ca-18dd95a5fdbf","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"session_started","at":"2026-02-28T23:52:44.931Z","payload":{"sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","startedAt":"2026-02-28T23:52:44.929Z"}}
{"id":"34f348b7-a1cd-42c2-a84f-2cb89a94e18b","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"case_file_generated","at":"2026-02-28T23:52:44.931Z","payload":{"caseFile":{"title":"Test LLM API connection","genre":"cosmic_crime","caseType":"criminal","synopsis":"Test LLM API connection","charges":["As stated in case prompt"],"witnesses":[],"evidence":[],"sentenceOptions":["Community service in the meme archives","Banished to the shadow realm","Mandatory apology haikus","Ethics training hosted by a raccoon","Ukulele ankle-monitor probation"]},"sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","generatedAt":"2026-02-28T23:52:44.931Z"}}
{"id":"f5810007-f9ba-4b0c-8117-753e6ba01142","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"phase_changed","at":"2026-02-28T23:52:44.936Z","payload":{"phase":"case_prompt","phaseStartedAt":"2026-02-28T23:52:44.934Z","phaseDurationMs":8000}}
{"id":"b895b480-6a11-497a-bfa4-73a72813b646","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"broadcast_hook_triggered","at":"2026-02-28T23:52:44.936Z","payload":{"phase":"case_prompt","hookType":"phase_stinger","triggeredAt":"2026-02-28T23:52:44.936Z"}}
{"id":"cc6b552d-7fbe-404c-ae96-ce640e4b405b","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"turn","at":"2026-02-28T23:52:44.938Z","payload":{"turn":{"id":"0819b571-ae5a-4e87-9063-2b1c2dea4f12","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","turnNumber":0,"speaker":"mux","role":"bailiff","phase":"case_prompt","dialogue":"All rise. The JuryRigged court is now in session. Case: Test LLM API connection","createdAt":"2026-02-28T23:52:44.937Z"}}}
{"id":"def90935-1880-47a9-ba57-f70736672b8a","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"phase_changed","at":"2026-02-28T23:52:46.143Z","payload":{"phase":"openings","phaseStartedAt":"2026-02-28T23:52:46.139Z","phaseDurationMs":30000}}
{"id":"6871a302-657e-4186-b41a-2b5013ad8897","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"turn","at":"2026-02-28T23:52:49.829Z","payload":{"turn":{"id":"75abe21a-3494-4b10-8dd1-7526f48f211d","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","turnNumber":1,"speaker":"subrosa","role":"prosecutor","phase":"openings","dialogue":"The defendant stands accused of reckless digital trespass—a test API call that sent ripples through the cosmic bandwidth,","createdAt":"2026-02-28T23:52:49.825Z"}}}
{"id":"bf1eb420-5f26-4a38-8665-9ee80ef6be23","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"render_directive","at":"2026-02-28T23:52:49.829Z","payload":{"directive":{"camera":"prosecution","poses":{"prosecutor":"talk"}},"turnId":"75abe21a-3494-4b10-8dd1-7526f48f211d","phase":"openings","emittedAt":"2026-02-28T23:52:49.829Z"}}
{"id":"b6b2a471-980f-4db0-85f4-f232ebf8245d","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"token_budget_applied","at":"2026-02-28T23:52:49.829Z","payload":{"turnId":"75abe21a-3494-4b10-8dd1-7526f48f211d","speaker":"subrosa","role":"prosecutor","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"135e4688-e14a-45a9-b67e-2742d94195bf","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"session_token_estimate","at":"2026-02-28T23:52:49.829Z","payload":{"turnId":"75abe21a-3494-4b10-8dd1-7526f48f211d","role":"prosecutor","phase":"openings","estimatedPromptTokens":137,"estimatedCompletionTokens":18,"cumulativeEstimatedTokens":155,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00031}}
{"id":"c978eb57-8ffb-4ea1-88a1-5be36b3ce877","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"turn","at":"2026-02-28T23:52:52.773Z","payload":{"turn":{"id":"32032507-4053-4f17-9c3e-337d313bee3f","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","turnNumber":2,"speaker":"chora","role":"defense","phase":"openings","dialogue":"Ladies and gentlemen of the jury, the facts are weird, the timeline is worse, and someone absolutely touched the thermostat without consent.","createdAt":"2026-02-28T23:52:52.770Z"}}}
{"id":"ce7988eb-474f-48a3-8c0a-e27aca91e0d2","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"render_directive","at":"2026-02-28T23:52:52.773Z","payload":{"directive":{"camera":"defense","poses":{"defense":"talk"}},"turnId":"32032507-4053-4f17-9c3e-337d313bee3f","phase":"openings","emittedAt":"2026-02-28T23:52:52.773Z"}}
{"id":"96e07cea-daf6-4c43-a850-7d6003477018","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"token_budget_applied","at":"2026-02-28T23:52:52.773Z","payload":{"turnId":"32032507-4053-4f17-9c3e-337d313bee3f","speaker":"chora","role":"defense","phase":"openings","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"c4e88dd1-5748-4836-8083-b55c3647f9a2","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"session_token_estimate","at":"2026-02-28T23:52:52.773Z","payload":{"turnId":"32032507-4053-4f17-9c3e-337d313bee3f","role":"defense","phase":"openings","estimatedPromptTokens":291,"estimatedCompletionTokens":40,"cumulativeEstimatedTokens":331,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.000662}}
{"id":"c3fa9149-70f4-4223-b439-c8c16b624032","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"phase_changed","at":"2026-02-28T23:52:52.777Z","payload":{"phase":"witness_exam","phaseStartedAt":"2026-02-28T23:52:52.775Z","phaseDurationMs":40000}}
{"id":"abeffadc-6bef-4a90-9458-736e9fb6d8b3","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"turn","at":"2026-02-28T23:52:55.315Z","payload":{"turn":{"id":"eb230321-3f04-43c9-ab06-6629d8253c87","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","turnNumber":3,"speaker":"primus","role":"judge","phase":"witness_exam","dialogue":"I saw the defendant near the snack cabinet at 2:03 AM, holding a spoon and what looked like emotional intent.","createdAt":"2026-02-28T23:52:55.311Z"}}}
{"id":"dd1559ba-df93-4cde-be82-893b02c8188c","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"render_directive","at":"2026-02-28T23:52:55.315Z","payload":{"directive":{"camera":"judge","poses":{"judge":"talk"}},"turnId":"eb230321-3f04-43c9-ab06-6629d8253c87","phase":"witness_exam","emittedAt":"2026-02-28T23:52:55.315Z"}}
{"id":"3e34b1ba-a957-4e90-96de-45d369c03a7a","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"token_budget_applied","at":"2026-02-28T23:52:55.315Z","payload":{"turnId":"eb230321-3f04-43c9-ab06-6629d8253c87","speaker":"primus","role":"judge","phase":"witness_exam","requestedMaxTokens":260,"appliedMaxTokens":220,"roleMaxTokens":220,"source":"env_role_cap"}}
{"id":"0d44c6a4-5244-470f-9a3d-b1db28fb83a2","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"session_token_estimate","at":"2026-02-28T23:52:55.316Z","payload":{"turnId":"eb230321-3f04-43c9-ab06-6629d8253c87","role":"judge","phase":"witness_exam","estimatedPromptTokens":465,"estimatedCompletionTokens":60,"cumulativeEstimatedTokens":525,"costPer1kTokensUsd":0.002,"estimatedCostUsd":0.00105}}
{"id":"3afcedb4-855a-4480-9e8c-d1d5a495cbc7","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"session_started","at":"2026-02-28T23:53:33.063Z","payload":{"sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","startedAt":"2026-02-28T23:52:44.929Z"}}
{"id":"41242127-30d8-43c3-8754-53de6cd0c6d0","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"case_file_generated","at":"2026-02-28T23:53:33.063Z","payload":{"caseFile":{"title":"Test LLM API connection","genre":"cosmic_crime","caseType":"criminal","synopsis":"Test LLM API connection","charges":["As stated in case prompt"],"witnesses":[],"evidence":[],"sentenceOptions":["Community service in the meme archives","Banished to the shadow realm","Mandatory apology haikus","Ethics training hosted by a raccoon","Ukulele ankle-monitor probation"]},"sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","generatedAt":"2026-02-28T23:53:33.063Z"}}
{"id":"e6187085-5abd-4a26-8843-b8129876e7f7","sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","type":"session_failed","at":"2026-02-28T23:53:33.071Z","payload":{"sessionId":"f2876c73-61e5-46a1-bc60-e2f77ce7f93a","reason":"Invalid phase transition: witness_exam -> case_prompt","completedAt":"2026-02-28T23:53:33.065Z"}}

118
renderer/audio.ts Normal file
View File

@@ -0,0 +1,118 @@
/**
* Audio System Integration
*
* Manages SFX playback via Howler.js
* Preloads sounds during initialization
*/
import { Howler, Howl } from 'howler';
export interface SFXConfig {
[soundName: string]: string; // sound name -> audio file path
}
export class AudioManager {
private sounds: Map<string, Howl> = new Map();
private isLoaded: boolean = false;
/**
* Preload SFX files
*/
public async loadSFX(config: SFXConfig): Promise<void> {
try {
for (const [name, path] of Object.entries(config)) {
const sound = new Howl({
src: [path],
preload: true,
});
await new Promise<void>((resolve, reject) => {
sound.once('load', () => resolve());
sound.once('loaderror', () => {
console.warn(
`Failed to load SFX: ${name} from ${path}`,
);
resolve(); // Don't reject, allow graceful fallback
});
sound.once('playerror', () => {
console.warn(`Playback error for SFX: ${name}`);
resolve();
});
});
this.sounds.set(name, sound);
}
this.isLoaded = true;
console.log(`[Audio] Loaded ${this.sounds.size} SFX files`);
} catch (err) {
console.error('[Audio] Error loading SFX:', err);
// Continue even if SFX loading fails
}
}
/**
* Play a sound effect by name
*/
public play(soundName: string): void {
if (!this.isLoaded) {
console.warn('[Audio] SFX not loaded yet');
return;
}
const sound = this.sounds.get(soundName);
if (sound) {
sound.play();
} else {
console.warn(`[Audio] Unknown SFX: ${soundName}`);
}
}
/**
* Stop a specific sound or all sounds
*/
public stop(soundName?: string): void {
if (soundName) {
const sound = this.sounds.get(soundName);
if (sound) {
sound.stop();
}
} else {
Howler.stop(); // Stop all sounds
}
}
/**
* Set global volume (0-1)
*/
public setVolume(volume: number): void {
Howler.volume(Math.max(0, Math.min(1, volume)));
}
public getVolume(): number {
return Howler.volume();
}
/**
* Cleanup
*/
public destroy(): void {
this.sounds.forEach(sound => {
sound.unload();
});
this.sounds.clear();
this.isLoaded = false;
}
}
/**
* Default SFX configuration
* Maps sound names to asset paths
*/
export const DEFAULT_SFX_CONFIG: SFXConfig = {
objection: '/assets/sfx/objection.mp3',
hold_it: '/assets/sfx/hold_it.mp3',
gavel: '/assets/sfx/gavel.mp3',
crowd_gasp: '/assets/sfx/crowd_gasp.mp3',
dramatic_sting: '/assets/sfx/dramatic_sting.mp3',
};

View File

@@ -0,0 +1,103 @@
/**
* Render Directive Consumer
*
* Consumes render directives from turn events via SSE stream
* and triggers corresponding effects in the renderer
*/
import { EffectsCueSystem } from './effects.js';
import { StingerExecutor } from './stingers.js';
export interface RenderDirective {
sfx?: string[];
fx?: Array<{
type: 'flash' | 'shake' | 'freeze' | 'hit_stop';
params?: Record<string, any>;
}>;
stinger?: string;
}
/**
* Handles execution of render directives
*/
export class RenderDirectiveHandler {
private effects: EffectsCueSystem;
private stingers: StingerExecutor;
constructor(effects: EffectsCueSystem, stingers: StingerExecutor) {
this.effects = effects;
this.stingers = stingers;
}
/**
* Process render directives from a turn event
*/
public async handle(directive: RenderDirective | undefined): Promise<void> {
if (!directive) {
return;
}
const promises: Promise<void>[] = [];
// Execute SFX
if (directive.sfx) {
for (const sfxName of directive.sfx) {
this.effects.playSfx(sfxName);
}
}
// Execute individual effects
if (directive.fx) {
for (const fx of directive.fx) {
const promise = this.executeFx(fx);
if (promise) {
promises.push(promise);
}
}
}
// Execute composite stinger (overrides individual effects)
if (directive.stinger) {
try {
const stingerName = directive.stinger as any;
await this.stingers.runStinger(stingerName);
} catch (err) {
console.error('Failed to run stinger:', err);
}
}
// Wait for all effects to complete
await Promise.all(promises);
}
/**
* Execute a single FX directive
*/
private executeFx(fx: {
type: 'flash' | 'shake' | 'freeze' | 'hit_stop';
params?: Record<string, any>;
}): Promise<void> | undefined {
const { type, params = {} } = fx;
switch (type) {
case 'flash':
return this.effects.flashWhite(params.durationMs || 120);
case 'shake':
return this.effects.shake(
params.intensity || 10,
params.durationMs || 200,
);
case 'freeze':
return this.effects.freezeFrame(params.durationMs || 100);
case 'hit_stop':
return this.effects.hitStop(params.durationMs || 50);
default:
console.warn(`Unknown FX type: ${type}`);
return undefined;
}
}
}

243
renderer/effects.ts Normal file
View File

@@ -0,0 +1,243 @@
/**
* Effects Cue System
*
* Primitives for SFX playback, screen shake, white flash, freeze frame, hit-stop,
* and "OBJECTION!" style stamp overlays. Effects run independently of dialogue.
*/
import * as PIXI from 'pixi.js';
import { SceneGraph } from './scene.js';
import { AudioManager } from './audio.js';
export class EffectsCueSystem {
private app: PIXI.Application;
private scene: SceneGraph;
private audio: AudioManager;
private activeTweens: Array<{ ticker: () => void; destroy: () => void }> =
[];
constructor(app: PIXI.Application, scene: SceneGraph) {
this.app = app;
this.scene = scene;
this.audio = new AudioManager();
}
/**
* Initialize audio system with SFX configuration
*/
public async initAudio(sfxConfig: Record<string, string>): Promise<void> {
await this.audio.loadSFX(sfxConfig);
}
/**
* Preload SFX from Howler.js
* Call during initialization
*/
public async loadSFX(soundMap: { [name: string]: string }): Promise<void> {
// Will be wired once Howler.js integrated
// For now, delegate to audio manager
await this.audio.loadSFX(soundMap);
}
/**
* Play a sound effect by name
* Silently ignores unknown SFX names
*/
public playSfx(name: string): void {
this.audio.play(name);
}
/**
* Flash white — full-screen white overlay that fades out over duration
*/
public flashWhite(durationMs: number): Promise<void> {
return new Promise(resolve => {
const graphics = new PIXI.Graphics();
graphics.rect(0, 0, this.app.canvas.width, this.app.canvas.height);
graphics.fill(0xffffff);
graphics.alpha = 1.0;
this.scene.getEffectsLayer().addChild(graphics);
const startTime = performance.now();
const ticker = () => {
const elapsed = performance.now() - startTime;
const progress = Math.min(elapsed / durationMs, 1);
graphics.alpha = 1.0 - progress;
if (progress >= 1.0) {
destroy();
resolve();
}
};
const destroy = () => {
this.app.ticker.remove(ticker);
this.scene.getEffectsLayer().removeChild(graphics);
graphics.destroy();
this.activeTweens = this.activeTweens.filter(
t => t.ticker !== ticker,
);
};
this.app.ticker.add(ticker);
this.activeTweens.push({ ticker, destroy });
});
}
/**
* Screen shake — Add random X/Y offset to camera container with decay
*/
public async shake(intensity: number, durationMs: number): Promise<void> {
return new Promise(resolve => {
const container = this.scene.getCameraContainer();
const startTime = performance.now();
const ticker = () => {
const elapsed = performance.now() - startTime;
const progress = Math.min(elapsed / durationMs, 1);
// Decay amplitude over duration
const remainingAmplitude = intensity * (1 - progress);
// Random X/Y offset
const offsetX = (Math.random() - 0.5) * 2 * remainingAmplitude;
const offsetY = (Math.random() - 0.5) * 2 * remainingAmplitude;
container.x = offsetX;
container.y = offsetY;
if (progress >= 1.0) {
destroy();
resolve();
}
};
const destroy = () => {
this.app.ticker.remove(ticker);
container.x = 0;
container.y = 0;
this.activeTweens = this.activeTweens.filter(
t => t.ticker !== ticker,
);
};
this.app.ticker.add(ticker);
this.activeTweens.push({ ticker, destroy });
});
}
/**
* Freeze frame — Pause ticker updates for specified duration (brief pause for impact)
* Note: This is distinct from hitStop; freezeFrame is typically longer
*/
public async freezeFrame(durationMs: number): Promise<void> {
return new Promise(resolve => {
const ticker = this.app.ticker;
const originalAutoUpdate = ticker.autoStart;
ticker.stop();
setTimeout(() => {
if (originalAutoUpdate) {
ticker.start();
}
resolve();
}, durationMs);
});
}
/**
* Hit stop — Tiny pause for impact feel (similar to freezeFrame but typically shorter)
*/
public async hitStop(durationMs: number): Promise<void> {
return this.freezeFrame(durationMs);
}
/**
* Stamp — Render bold overlay text (e.g., "OBJECTION!") that fades in and out
*/
public async stamp(text: string, durationMs: number): Promise<void> {
return new Promise(resolve => {
const textSprite = new PIXI.Text({
text,
style: {
fontSize: 80,
fontWeight: 'bold',
fontFamily: 'Arial',
fill: 0xff0000,
stroke: 0x000000,
strokeThickness: 4,
},
});
// Center text on canvas
textSprite.x = (this.app.canvas.width - textSprite.width) / 2;
textSprite.y = (this.app.canvas.height - textSprite.height) / 2;
textSprite.alpha = 0;
this.scene.getEffectsLayer().addChild(textSprite);
const startTime = performance.now();
let phase: 'fadeIn' | 'hold' | 'fadeOut' = 'fadeIn';
const fadeInDuration = 150;
const holdDuration = Math.max(durationMs - 300, durationMs * 0.5);
const fadeOutDuration = 150;
const ticker = () => {
const elapsed = performance.now() - startTime;
if (elapsed < fadeInDuration) {
// Fade in
textSprite.alpha = elapsed / fadeInDuration;
} else if (elapsed < fadeInDuration + holdDuration) {
// Hold
phase = 'hold';
textSprite.alpha = 1.0;
} else if (
elapsed <
fadeInDuration + holdDuration + fadeOutDuration
) {
// Fade out
phase = 'fadeOut';
const fadeElapsed = elapsed - fadeInDuration - holdDuration;
textSprite.alpha = 1.0 - fadeElapsed / fadeOutDuration;
} else {
destroy();
resolve();
}
};
const destroy = () => {
this.app.ticker.remove(ticker);
this.scene.getEffectsLayer().removeChild(textSprite);
textSprite.destroy();
this.activeTweens = this.activeTweens.filter(
t => t.ticker !== ticker,
);
};
this.app.ticker.add(ticker);
this.activeTweens.push({ ticker, destroy });
});
}
/**
* Stop all active effects
*/
public stopAll(): void {
this.activeTweens.forEach(t => t.destroy());
this.activeTweens = [];
// Reset camera container offset
this.scene.getCameraContainer().x = 0;
this.scene.getCameraContainer().y = 0;
}
/**
* Cleanup
*/
public destroy(): void {
this.stopAll();
this.audio.destroy();
}
}

119
renderer/renderer.ts Normal file
View File

@@ -0,0 +1,119 @@
/**
* PixiJS Application Setup
*
* Main renderer entry point. Initializes the PixiJS application with stage,
* viewport, and ticker. Manages lifecycle of effects system and scene.
*/
import * as PIXI from 'pixi.js';
import { EffectsCueSystem } from './effects.js';
import { SceneGraph } from './scene.js';
import { DEFAULT_SFX_CONFIG } from './audio.js';
export class CourtRenderer {
private app: PIXI.Application;
private scene: SceneGraph;
public effects: EffectsCueSystem;
constructor(
options: {
width?: number;
height?: number;
container?: HTMLElement;
} = {},
) {
const {
width = 1280,
height = 720,
container = document.body,
} = options;
// Initialize PixiJS application
this.app = new PIXI.Application({
width,
height,
backgroundColor: 0x000000,
resolution: window.devicePixelRatio || 1,
antialias: true,
sharedTicker: true,
});
container.appendChild(this.app.canvas);
// Initialize scene graph
this.scene = new SceneGraph(this.app.stage);
// Initialize effects system
this.effects = new EffectsCueSystem(this.app, this.scene);
// Start animation loop
this.app.ticker.start();
// Initialize audio (non-blocking, will load in background)
this.effects.initAudio(DEFAULT_SFX_CONFIG).catch((err: unknown) => {
console.warn('Failed to initialize audio:', err);
});
}
/**
* Get the PixiJS application instance
*/
public getApp(): PIXI.Application {
return this.app;
}
/**
* Get the scene graph
*/
public getScene(): SceneGraph {
return this.scene;
}
/**
* Resize canvas (e.g., on window resize)
*/
public resize(width: number, height: number): void {
this.app.renderer.resize(width, height);
this.scene.onResize(width, height);
}
/**
* Destroy renderer and clean up resources
*/
public destroy(): void {
this.effects.destroy();
this.scene.destroy();
this.app.destroy(true);
}
}
/**
* Global renderer instance (singleton pattern)
*/
let globalRenderer: CourtRenderer | null = null;
export function initRenderer(options?: {
width?: number;
height?: number;
container?: HTMLElement;
}): CourtRenderer {
if (globalRenderer) {
console.warn(
'Renderer already initialized, returning existing instance',
);
return globalRenderer;
}
globalRenderer = new CourtRenderer(options);
return globalRenderer;
}
export function getRenderer(): CourtRenderer | null {
return globalRenderer;
}
export function destroyRenderer(): void {
if (globalRenderer) {
globalRenderer.destroy();
globalRenderer = null;
}
}

110
renderer/scene.ts Normal file
View File

@@ -0,0 +1,110 @@
/**
* Scene Graph Management
*
* Manages hierarchical organization of sprites, backgrounds, UI layers.
* Provides z-index layering and camera system for effects like shake.
*/
import * as PIXI from 'pixi.js';
export class SceneGraph {
private root: PIXI.Container;
private cameraContainer: PIXI.Container;
private backgroundLayer: PIXI.Container;
private spriteLayer: PIXI.Container;
private uiLayer: PIXI.Container;
private effectsLayer: PIXI.Container;
constructor(stage: PIXI.Container) {
this.root = stage;
// Camera container — all scene content goes here so shake affects everything
this.cameraContainer = new PIXI.Container();
this.root.addChild(this.cameraContainer);
// Background layer (z: 0)
this.backgroundLayer = new PIXI.Container();
this.cameraContainer.addChild(this.backgroundLayer);
// Sprite layer (z: 10) — characters, evidence
this.spriteLayer = new PIXI.Container();
this.cameraContainer.addChild(this.spriteLayer);
// UI layer (z: 100) — dialogs, captions
this.uiLayer = new PIXI.Container();
this.cameraContainer.addChild(this.uiLayer);
// Effects layer (z: 1000) — flash, stamp, overlays
this.effectsLayer = new PIXI.Container();
this.root.addChild(this.effectsLayer);
}
/**
* Get the camera container for applying camera effects (shake, pan, zoom)
*/
public getCameraContainer(): PIXI.Container {
return this.cameraContainer;
}
/**
* Add a sprite to the sprite layer
*/
public addSprite(sprite: PIXI.Sprite | PIXI.Container): void {
this.spriteLayer.addChild(sprite);
}
/**
* Remove a sprite from the sprite layer
*/
public removeSprite(sprite: PIXI.DisplayObject): void {
this.spriteLayer.removeChild(sprite);
}
/**
* Get the background layer
*/
public getBackgroundLayer(): PIXI.Container {
return this.backgroundLayer;
}
/**
* Get the sprite layer
*/
public getSpriteLayer(): PIXI.Container {
return this.spriteLayer;
}
/**
* Get the UI layer
*/
public getUILayer(): PIXI.Container {
return this.uiLayer;
}
/**
* Get the effects layer (flash, stamp, etc.)
*/
public getEffectsLayer(): PIXI.Container {
return this.effectsLayer;
}
/**
* Handle window/canvas resize
*/
public onResize(width: number, height: number): void {
// Center layers if needed
// Can be extended for responsive layouts
}
/**
* Destroy all layers and cleanup
*/
public destroy(): void {
this.backgroundLayer.destroy();
this.spriteLayer.destroy();
this.uiLayer.destroy();
this.effectsLayer.destroy();
this.cameraContainer.destroy();
this.root.destroy();
}
}

260
renderer/stingers.ts Normal file
View File

@@ -0,0 +1,260 @@
/**
* Composite Effect Stingers
*
* Named timelines that compose primitives from EffectsCueSystem
* into memorable moments like "OBJECTION!" stinger from Ace Attorney
*/
import { EffectsCueSystem } from './effects.js';
export type StingerName =
| 'objection'
| 'hold_it'
| 'present'
| 'guilty_verdict'
| 'not_guilty_verdict';
export interface StingerDefinition {
name: StingerName;
steps: StingerStep[];
}
export interface StingerStep {
delayMs: number;
action: 'sfx' | 'flash' | 'shake' | 'freeze' | 'stamp' | 'pause';
params?: Record<string, any>;
}
/**
* Predefined stinger timelines
*/
export const STINGER_DEFINITIONS: Record<StingerName, StingerDefinition> = {
objection: {
name: 'objection',
steps: [
// t=0ms: SFX + white flash
{ delayMs: 0, action: 'sfx', params: { name: 'objection' } },
{ delayMs: 0, action: 'flash', params: { durationMs: 120 } },
// t=80ms: stamp "OBJECTION!"
{
delayMs: 80,
action: 'stamp',
params: { text: 'OBJECTION!', durationMs: 1200 },
},
// t=120ms: camera shake
{
delayMs: 120,
action: 'shake',
params: { intensity: 12, durationMs: 300 },
},
],
},
hold_it: {
name: 'hold_it',
steps: [
// t=0ms: SFX + white flash
{ delayMs: 0, action: 'sfx', params: { name: 'hold_it' } },
{ delayMs: 0, action: 'flash', params: { durationMs: 100 } },
// t=70ms: stamp "HOLD IT!"
{
delayMs: 70,
action: 'stamp',
params: { text: 'HOLD IT!', durationMs: 1000 },
},
// t=100ms: camera shake (less intense than objection)
{
delayMs: 100,
action: 'shake',
params: { intensity: 8, durationMs: 250 },
},
],
},
present: {
name: 'present',
steps: [
// t=0ms: SFX
{ delayMs: 0, action: 'sfx', params: { name: 'dramatic_sting' } },
// t=50ms: white flash
{ delayMs: 50, action: 'flash', params: { durationMs: 150 } },
// t=100ms: stamp "PRESENT!"
{
delayMs: 100,
action: 'stamp',
params: { text: 'PRESENT!', durationMs: 1200 },
},
// t=120ms: shake
{
delayMs: 120,
action: 'shake',
params: { intensity: 10, durationMs: 280 },
},
],
},
guilty_verdict: {
name: 'guilty_verdict',
steps: [
// t=0ms: Gavel sound
{ delayMs: 0, action: 'sfx', params: { name: 'gavel' } },
// t=40ms: Red flash (moderate)
{ delayMs: 40, action: 'flash', params: { durationMs: 100 } },
// t=80ms: stamp "GUILTY"
{
delayMs: 80,
action: 'stamp',
params: { text: 'GUILTY', durationMs: 2000 },
},
// t=100ms: shake (strong for guilty verdict)
{
delayMs: 100,
action: 'shake',
params: { intensity: 15, durationMs: 400 },
},
],
},
not_guilty_verdict: {
name: 'not_guilty_verdict',
steps: [
// t=0ms: Gavel sound
{ delayMs: 0, action: 'sfx', params: { name: 'gavel' } },
// t=40ms: Blue/white flash
{ delayMs: 40, action: 'flash', params: { durationMs: 100 } },
// t=80ms: stamp "NOT GUILTY"
{
delayMs: 80,
action: 'stamp',
params: { text: 'NOT GUILTY', durationMs: 2000 },
},
// t=100ms: lighter shake
{
delayMs: 100,
action: 'shake',
params: { intensity: 10, durationMs: 300 },
},
],
},
};
/**
* Stinger executor
* Runs a named stinger timeline with correct timing
*/
export class StingerExecutor {
private effects: EffectsCueSystem;
constructor(effects: EffectsCueSystem) {
this.effects = effects;
}
/**
* Run a named stinger
* Returns promise that resolves when stinger completes
*/
public async runStinger(stingerName: StingerName): Promise<void> {
const definition = STINGER_DEFINITIONS[stingerName];
if (!definition) {
console.warn(`Unknown stinger: ${stingerName}`);
return;
}
// Execute all steps with delays
const promises: Promise<void>[] = [];
for (const step of definition.steps) {
promises.push(
new Promise<void>(resolve => {
setTimeout(() => {
this.executeStep(step).finally(resolve);
}, step.delayMs);
}),
);
}
// Wait for all steps to complete
// The longest step determines total stinger duration
await Promise.all(promises);
}
/**
* Execute a single stinger step
*/
private async executeStep(step: StingerStep): Promise<void> {
try {
switch (step.action) {
case 'sfx':
this.effects.playSfx(step.params?.name || 'default');
break;
case 'flash':
return this.effects.flashWhite(
step.params?.durationMs || 100,
);
case 'shake':
return this.effects.shake(
step.params?.intensity || 10,
step.params?.durationMs || 200,
);
case 'freeze':
return this.effects.freezeFrame(
step.params?.durationMs || 100,
);
case 'stamp':
return this.effects.stamp(
step.params?.text || 'STAMP',
step.params?.durationMs || 1000,
);
case 'pause':
// Simple delay
return new Promise(resolve => {
setTimeout(resolve, step.params?.durationMs || 100);
});
default:
console.warn(`Unknown stinger action: ${step.action}`);
}
} catch (err) {
console.error(`Error executing stinger step: ${step.action}`, err);
}
}
}
/**
* Global stinger executor
*/
let globalExecutor: StingerExecutor | null = null;
export function initStingerExecutor(
effects: EffectsCueSystem,
): StingerExecutor {
if (globalExecutor) {
console.warn('Stinger executor already initialized');
return globalExecutor;
}
globalExecutor = new StingerExecutor(effects);
return globalExecutor;
}
export function getStingerExecutor(): StingerExecutor | null {
return globalExecutor;
}

View File

@@ -118,6 +118,8 @@ describe('Vote Lifecycle Integration', () => {
sentenceVoteWindowMs: 20000,
verdictVotes: {},
sentenceVotes: {},
pressVotes: {},
presentVotes: {},
},
});
@@ -177,6 +179,8 @@ describe('Vote Lifecycle Integration', () => {
sentenceVoteWindowMs: 20000,
verdictVotes: {},
sentenceVotes: {},
pressVotes: {},
presentVotes: {},
},
});
@@ -238,6 +242,8 @@ describe('Vote Lifecycle Integration', () => {
sentenceVoteWindowMs: 20000,
verdictVotes: {},
sentenceVotes: {},
pressVotes: {},
presentVotes: {},
},
});
@@ -290,6 +296,8 @@ describe('Vote Lifecycle Integration', () => {
sentenceVoteWindowMs: 20000,
verdictVotes: {},
sentenceVotes: {},
pressVotes: {},
presentVotes: {},
},
});
@@ -336,6 +344,8 @@ describe('Vote Lifecycle Integration', () => {
sentenceVoteWindowMs: 20000,
verdictVotes: {},
sentenceVotes: {},
pressVotes: {},
presentVotes: {},
},
});
@@ -383,6 +393,8 @@ describe('Vote Lifecycle Integration', () => {
sentenceVoteWindowMs: 20000,
verdictVotes: {},
sentenceVotes: {},
pressVotes: {},
presentVotes: {},
},
});

View File

@@ -57,6 +57,8 @@ test('e2e round completes with witness caps and recap cadence', async () => {
sentenceVoteWindowMs: 1,
verdictVotes: {},
sentenceVotes: {},
pressVotes: {},
presentVotes: {},
},
});
@@ -135,13 +137,17 @@ test('e2e round completes with witness caps and recap cadence', async () => {
assert.ok(judgeBudgetEvent);
assert.equal(judgeBudgetEvent?.payload.appliedMaxTokens, 18);
const lastTokenEstimate = tokenEstimateEvents[tokenEstimateEvents.length - 1];
const lastTokenEstimate =
tokenEstimateEvents[tokenEstimateEvents.length - 1];
assert.ok(lastTokenEstimate);
assert.equal(
typeof lastTokenEstimate?.payload.cumulativeEstimatedTokens,
'number',
);
assert.equal(typeof lastTokenEstimate?.payload.estimatedCostUsd, 'number');
assert.equal(
typeof lastTokenEstimate?.payload.estimatedCostUsd,
'number',
);
} finally {
if (previousCapTokens === undefined) {
delete process.env.WITNESS_MAX_TOKENS;

View File

@@ -5,7 +5,13 @@
* Use `assertEventPayload` to validate a raw `CourtEvent` at runtime.
*/
import type { CourtEvent, CourtPhase, RenderDirective, CaseFile, WitnessStatement } from './types.js';
import type {
CourtEvent,
CourtPhase,
RenderDirective,
CaseFile,
WitnessStatement,
} from './types.js';
// ---------------------------------------------------------------------------
// Payload interfaces
@@ -37,6 +43,14 @@ export interface TurnPayload {
dialogue: string;
createdAt: string;
};
render?: {
sfx?: string[];
fx?: Array<{
type: 'flash' | 'shake' | 'freeze' | 'hit_stop';
params?: Record<string, any>;
}>;
stinger?: string;
};
}
export interface VoteUpdatedPayload {
@@ -53,6 +67,18 @@ export interface VoteClosedPayload {
nextPhase: CourtPhase;
}
export interface PressVoteUpdatedPayload {
statementNumber: number;
pressVotes: Record<number, number>;
phase: CourtPhase;
}
export interface PresentVoteUpdatedPayload {
evidenceId: string;
presentVotes: Record<string, number>;
phase: CourtPhase;
}
export interface WitnessResponseCappedPayload {
turnId: string;
speaker: string;
@@ -248,6 +274,29 @@ export function assertEventPayload(event: CourtEvent): void {
}
break;
case 'press_vote_updated':
if (
!hasStringKeys(payload, ['phase']) ||
typeof payload['statementNumber'] !== 'number' ||
!hasObjectKey(payload, 'pressVotes')
) {
throw new TypeError(
`press_vote_updated payload missing required fields: statementNumber (number), pressVotes (object), phase`,
);
}
break;
case 'present_vote_updated':
if (
!hasStringKeys(payload, ['phase', 'evidenceId']) ||
!hasObjectKey(payload, 'presentVotes')
) {
throw new TypeError(
`present_vote_updated payload missing required fields: evidenceId, presentVotes (object), phase`,
);
}
break;
case 'vote_closed':
if (
!hasStringKeys(payload, [

View File

@@ -1,17 +1,28 @@
import type { LLMGenerateOptions } from '../types.js';
const FALLBACK_MODEL = 'deepseek/deepseek-chat-v3-0324:free';
const FALLBACK_MODELS = [
'google/gemma-3-27b-it:free',
'meta-llama/llama-3.3-70b-instruct:free',
'mistralai/mistral-small-3.1-24b-instruct:free',
];
function runtimeLLMConfig(env: NodeJS.ProcessEnv = process.env): {
apiKey: string;
model: string;
models: string[];
forceMock: boolean;
} {
const apiKey = (env.OPENROUTER_API_KEY ?? '').trim();
const model = (env.LLM_MODEL ?? FALLBACK_MODEL).trim() || FALLBACK_MODEL;
const modelsRaw = (env.LLM_MODELS ?? '').trim();
const models =
modelsRaw ?
modelsRaw
.split(',')
.map(m => m.trim())
.filter(Boolean)
: FALLBACK_MODELS;
const runningNodeTests = process.argv.includes('--test');
const forceMock = env.LLM_MOCK === 'true' || runningNodeTests;
return { apiKey, model, forceMock };
return { apiKey, models, forceMock };
}
function extractFromXml(text: string): string {
@@ -56,25 +67,15 @@ function mockReply(prompt: string): string {
return 'Order in the court. I acknowledge the point and move us to the next absurdly important matter.';
}
export async function llmGenerate(
options: LLMGenerateOptions,
): Promise<string> {
const config = runtimeLLMConfig();
const {
messages,
model = config.model,
temperature = 0.7,
maxTokens = 300,
} = options;
const latestUserMessage = [...messages]
.reverse()
.find(message => message.role === 'user')?.content;
if (!config.apiKey || config.forceMock) {
return mockReply(latestUserMessage ?? '');
}
async function tryModelGenerate(
model: string,
apiKey: string,
messages: LLMGenerateOptions['messages'],
temperature: number,
maxTokens: number,
): Promise<
{ success: true; text: string } | { success: false; reason: string }
> {
try {
const response = await fetch(
'https://openrouter.ai/api/v1/chat/completions',
@@ -82,7 +83,7 @@ export async function llmGenerate(
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${config.apiKey}`,
Authorization: `Bearer ${apiKey}`,
},
body: JSON.stringify({
model,
@@ -95,11 +96,10 @@ export async function llmGenerate(
if (!response.ok) {
const body = await response.text();
// eslint-disable-next-line no-console
console.warn(
`OpenRouter request failed (${response.status}); falling back to mock dialogue: ${body.slice(0, 160)}`,
);
return mockReply(latestUserMessage ?? '');
return {
success: false,
reason: `HTTP ${response.status}: ${body.slice(0, 100)}`,
};
}
const data = (await response.json()) as {
@@ -111,19 +111,65 @@ export async function llmGenerate(
const sanitized = sanitizeDialogue(text);
if (!sanitized) {
// eslint-disable-next-line no-console
console.warn(
`OpenRouter response returned empty content for model=${model}; falling back to mock dialogue.`,
);
return mockReply(latestUserMessage ?? '');
return {
success: false,
reason: 'Empty content after sanitization',
};
}
return sanitized;
return { success: true, text: sanitized };
} catch (error) {
// eslint-disable-next-line no-console
console.warn(
`OpenRouter request threw; falling back to mock dialogue: ${error instanceof Error ? error.message : String(error)}`,
);
return mockReply(latestUserMessage ?? '');
return {
success: false,
reason: error instanceof Error ? error.message : String(error),
};
}
}
export async function llmGenerate(
options: LLMGenerateOptions,
): Promise<string> {
const config = runtimeLLMConfig();
const { messages, temperature = 0.7, maxTokens = 300 } = options;
const latestUserMessage = [...messages]
.reverse()
.find(message => message.role === 'user')?.content;
if (!config.apiKey || config.forceMock) {
return mockReply(latestUserMessage ?? '');
}
// Try each model in sequence until one succeeds
const errors: string[] = [];
for (const model of config.models) {
const result = await tryModelGenerate(
model,
config.apiKey,
messages,
temperature,
maxTokens,
);
if (result.success) {
if (errors.length > 0) {
// eslint-disable-next-line no-console
console.info(
`[llm] model="${model}" succeeded after ${errors.length} failures`,
);
}
return result.text;
}
errors.push(`${model}: ${result.reason}`);
// eslint-disable-next-line no-console
console.warn(`[llm] model="${model}" failed: ${result.reason}`);
}
// All models failed, fall back to mock
// eslint-disable-next-line no-console
console.warn(
`[llm] All ${config.models.length} models failed; falling back to mock dialogue. Errors:\n${errors.join('\n')}`,
);
return mockReply(latestUserMessage ?? '');
}

View File

@@ -126,7 +126,10 @@ const SESSION_STATUSES: SessionStatus[] = [
function sanitizeLabel(value: string, fallback = 'unknown'): string {
const trimmed = value.trim();
if (!trimmed) return fallback;
return trimmed.toLowerCase().replace(/[^a-z0-9_:-]/g, '_').slice(0, 64);
return trimmed
.toLowerCase()
.replace(/[^a-z0-9_:-]/g, '_')
.slice(0, 64);
}
function classifyErrorType(error: unknown): string {
@@ -182,7 +185,9 @@ export function recordSseConnectionClosed(
sseConnectionDurationSeconds.observe(elapsedSecondsSince(openedAt));
}
async function syncSessionStatusGauges(store: CourtSessionStore): Promise<void> {
async function syncSessionStatusGauges(
store: CourtSessionStore,
): Promise<void> {
const sessions = await store.listSessions();
const counts = new Map<SessionStatus, number>(
SESSION_STATUSES.map(status => [status, 0]),
@@ -251,14 +256,12 @@ export function instrumentCourtSessionStore(
},
),
listSessions: wrapWithMetrics(
'list_sessions',
() => baseStore.listSessions(),
listSessions: wrapWithMetrics('list_sessions', () =>
baseStore.listSessions(),
),
getSession: wrapWithMetrics(
'get_session',
sessionId => baseStore.getSession(sessionId),
getSession: wrapWithMetrics('get_session', sessionId =>
baseStore.getSession(sessionId),
),
startSession: wrapWithMetrics(
@@ -288,24 +291,18 @@ export function instrumentCourtSessionStore(
}
},
addTurn: wrapWithMetrics(
'add_turn',
input => baseStore.addTurn(input),
addTurn: wrapWithMetrics('add_turn', input => baseStore.addTurn(input)),
castVote: wrapWithMetrics('cast_vote', input =>
baseStore.castVote(input),
),
castVote: wrapWithMetrics(
'cast_vote',
input => baseStore.castVote(input),
recordFinalRuling: wrapWithMetrics('record_final_ruling', input =>
baseStore.recordFinalRuling(input),
),
recordFinalRuling: wrapWithMetrics(
'record_final_ruling',
input => baseStore.recordFinalRuling(input),
),
recordRecap: wrapWithMetrics(
'record_recap',
input => baseStore.recordRecap(input),
recordRecap: wrapWithMetrics('record_recap', input =>
baseStore.recordRecap(input),
),
completeSession: wrapWithMetrics(
@@ -319,8 +316,7 @@ export function instrumentCourtSessionStore(
failSession: wrapWithMetrics(
'fail_session',
(sessionId, reason) =>
baseStore.failSession(sessionId, reason),
(sessionId, reason) => baseStore.failSession(sessionId, reason),
() => {
sessionLifecycleTotal.inc({ event: 'failed' });
scheduleSessionStatusSync();
@@ -342,6 +338,10 @@ export function instrumentCourtSessionStore(
emitEvent(sessionId, type, payload) {
baseStore.emitEvent(sessionId, type, payload);
},
patchMetadata(sessionId, patch) {
return baseStore.patchMetadata(sessionId, patch);
},
};
}
@@ -357,4 +357,4 @@ export async function renderMetrics(): Promise<string> {
return metricsRegistry.metrics();
}
export const metricsContentType = metricsRegistry.contentType;
export const metricsContentType = metricsRegistry.contentType;

211
src/twitch/bot.ts Normal file
View File

@@ -0,0 +1,211 @@
/**
* Twitch Chat Bot Integration
*
* IRC client for reading chat commands and EventSub webhook for channel point redemptions.
* Commands are forwarded to court API endpoints. Runs in noop mode when credentials absent.
*/
import type { EventEmitter } from 'events';
import {
CommandRateLimiter,
DEFAULT_COMMAND_RATE_LIMIT,
} from './command-rate-limit.js';
export interface BotConfig {
channel: string;
botToken: string;
clientId: string;
clientSecret: string;
apiBaseUrl: string;
}
export interface ParsedCommand {
action: 'press' | 'present' | 'vote' | 'sentence';
username: string;
timestamp: number;
params?: Record<string, any>;
}
export interface RedemptionEvent {
type: 'objection' | 'hold_it' | 'order_in_court';
username: string;
rewardId: string;
timestamp: number;
}
/**
* Main Twitch bot class
* Handles IRC chat commands and EventSub redemptions
*/
export class TwitchBot {
private config: BotConfig | null;
private isActive: boolean = false;
private eventEmitter: EventEmitter | null = null;
private commandRateLimiter: CommandRateLimiter;
constructor(config?: BotConfig) {
// Initialize rate limiter regardless of config
this.commandRateLimiter = new CommandRateLimiter(
DEFAULT_COMMAND_RATE_LIMIT,
);
// Graceful noop mode if credentials missing
if (!config || !this.hasRequiredEnvVars()) {
console.log(
'Twitch bot disabled: missing credentials. Set TWITCH_CHANNEL, TWITCH_BOT_TOKEN, TWITCH_CLIENT_ID.',
);
this.config = null;
this.isActive = false;
return;
}
this.config = config;
}
private hasRequiredEnvVars(): boolean {
return !!(
process.env.TWITCH_CHANNEL &&
process.env.TWITCH_BOT_TOKEN &&
process.env.TWITCH_CLIENT_ID &&
process.env.TWITCH_CLIENT_SECRET
);
}
/**
* Initialize bot: connect to IRC and register EventSub
*/
public async start(): Promise<void> {
if (!this.config || !this.isActive) {
return;
}
console.log(`[Twitch Bot] Starting bot for ${this.config.channel}`);
try {
await this.connectIRC();
console.log('[Twitch Bot] IRC connected');
await this.registerEventSub();
console.log('[Twitch Bot] EventSub registered');
this.isActive = true;
} catch (err) {
console.error('[Twitch Bot] Failed to start:', err);
this.isActive = false;
}
}
/**
* Connect to Twitch IRC
* Stub implementation — will use tmi.js
*/
private async connectIRC(): Promise<void> {
// Will be implemented with tmi.js
// For now, stub
console.log('[Twitch Bot] IRC connection stub');
}
/**
* Register WebSocket subscription for channel point redemptions
* Stub implementation — will use EventSub client
*/
private async registerEventSub(): Promise<void> {
// Will be implemented with EventSub API
// For now, stub
console.log('[Twitch Bot] EventSub registration stub');
}
/**
* Handle incoming chat command
* Returns parsed command or null if invalid
*/
public parseCommand(
message: string,
username: string,
): ParsedCommand | null {
// Check rate limit first
const rateLimitCheck = this.commandRateLimiter.check(username, message);
if (!rateLimitCheck.allowed) {
console.warn(
`[Twitch Bot] Command rate limited for ${username}: ${rateLimitCheck.reason}`,
);
return null;
}
// Will delegate to commands.ts parser
// For now, stub
console.log(`[Twitch Bot] Parsed command from ${username}: ${message}`);
return null;
}
/**
* Get the command rate limiter (for testing or external access)
*/
public getCommandRateLimiter(): CommandRateLimiter {
return this.commandRateLimiter;
}
/**
* Handle channel point redemption
*/
public handleRedemption(event: RedemptionEvent): void {
// Will be implemented
console.log(
`[Twitch Bot] Redemption: ${event.type} by ${event.username}`,
);
}
/**
* Stop bot and disconnect
*/
public async stop(): Promise<void> {
if (!this.isActive) {
return;
}
console.log('[Twitch Bot] Stopping bot');
this.isActive = false;
// Cleanup: disconnect IRC, unregister EventSub
}
public isRunning(): boolean {
return this.isActive;
}
}
/**
* Global bot instance
*/
let globalBot: TwitchBot | null = null;
export function initTwitchBot(config?: BotConfig): TwitchBot {
if (globalBot) {
console.warn(
'Twitch bot already initialized, returning existing instance',
);
return globalBot;
}
// Initialize from env vars if not provided
const finalConfig: BotConfig | undefined = config || {
channel: process.env.TWITCH_CHANNEL || '',
botToken: process.env.TWITCH_BOT_TOKEN || '',
clientId: process.env.TWITCH_CLIENT_ID || '',
clientSecret: process.env.TWITCH_CLIENT_SECRET || '',
apiBaseUrl: process.env.API_BASE_URL || 'http://localhost:3000',
};
globalBot = new TwitchBot(finalConfig);
return globalBot;
}
export function getTwitchBot(): TwitchBot | null {
return globalBot;
}
export function destroyTwitchBot(): void {
if (globalBot) {
globalBot.stop();
globalBot = null;
}
}

View File

@@ -0,0 +1,119 @@
/**
* Chat Command Rate Limiting
*
* Per-user rate limiting for Twitch chat commands
* Prevents spam from individual users
*/
export interface CommandRateLimitConfig {
maxCommandsPerWindow: number;
windowMs: number;
duplicateWindowMs: number;
}
export const DEFAULT_COMMAND_RATE_LIMIT: CommandRateLimitConfig = {
maxCommandsPerWindow: 5, // 5 commands per window per user
windowMs: 60_000, // 60 seconds
duplicateWindowMs: 5_000, // 5 seconds for duplicate detection
};
export interface RateLimitDecision {
allowed: boolean;
reason?: string;
retryAfterMs?: number;
}
/**
* Per-user rate limiter for chat commands
* Tracks command history per username
*/
export class CommandRateLimiter {
private userCommands: Map<
string,
{
count: number;
window: number;
lastCommand?: string;
lastCommandTime?: number;
}
> = new Map();
constructor(private config: CommandRateLimitConfig) {}
/**
* Check if a command from a user is allowed
*/
public check(username: string, commandText: string): RateLimitDecision {
const now = Date.now();
let entry = this.userCommands.get(username);
// Initialize or reset if window expired
if (!entry || now - entry.window > this.config.windowMs) {
entry = {
count: 0,
window: now,
};
}
// Check for duplicate command (exact same message within duplicate window)
if (
entry.lastCommand === commandText &&
entry.lastCommandTime &&
now - entry.lastCommandTime < this.config.duplicateWindowMs
) {
return {
allowed: false,
reason: 'duplicate_command',
retryAfterMs: this.config.duplicateWindowMs,
};
}
// Check command count in current window
if (entry.count >= this.config.maxCommandsPerWindow) {
const windowExpireTime = entry.window + this.config.windowMs;
const retryAfterMs = Math.max(0, windowExpireTime - now);
return {
allowed: false,
reason: 'rate_limited',
retryAfterMs,
};
}
// Allow command
entry.count++;
entry.lastCommand = commandText;
entry.lastCommandTime = now;
this.userCommands.set(username, entry);
return { allowed: true };
}
/**
* Reset rate limiter for a user (e.g., mods, special cases)
*/
public reset(username?: string): void {
if (username) {
this.userCommands.delete(username);
} else {
this.userCommands.clear();
}
}
/**
* Clean up old entries (call periodically)
*/
public cleanup(): void {
const now = Date.now();
const expired: string[] = [];
for (const [username, entry] of this.userCommands.entries()) {
if (now - entry.window > this.config.windowMs * 2) {
expired.push(username);
}
}
for (const username of expired) {
this.userCommands.delete(username);
}
}
}

205
src/twitch/commands.ts Normal file
View File

@@ -0,0 +1,205 @@
/**
* Twitch Chat Command Parser
*
* Parses chat commands like !press, !present, !vote, !sentence
* and validates parameters.
*/
export interface CommandParseResult {
action: 'press' | 'present' | 'vote' | 'sentence';
username: string;
timestamp: number;
params: Record<string, any>;
}
/**
* Parse a chat message into a command
* Returns null if invalid or not a command
*/
export function parseCommand(
rawMessage: string,
username: string,
): CommandParseResult | null {
const trimmed = rawMessage.trim();
// Must start with !
if (!trimmed.startsWith('!')) {
return null;
}
const parts = trimmed.split(/\s+/);
const command = parts[0].toLowerCase();
try {
switch (command) {
case '!press':
return parsePressCommand(parts, username);
case '!present':
return parsePresentCommand(parts, username);
case '!vote':
return parseVoteCommand(parts, username);
case '!sentence':
return parseSentenceCommand(parts, username);
default:
return null;
}
} catch (err) {
console.warn(`Failed to parse command: ${rawMessage}`, err);
return null;
}
}
/**
* Parse !press command
* Format: !press <statementNumber>
*/
function parsePressCommand(
parts: string[],
username: string,
): CommandParseResult | null {
if (parts.length < 2) {
console.warn(`Invalid !press command: missing statementNumber`);
return null;
}
const statementNumber = parseInt(parts[1], 10);
if (
isNaN(statementNumber) ||
statementNumber < 1 ||
statementNumber > 100
) {
console.warn(`Invalid statement number: ${parts[1]}`);
return null;
}
return {
action: 'press',
username,
timestamp: Date.now(),
params: { statementNumber },
};
}
/**
* Parse !present command
* Format: !present <evidenceId> [statementNumber]
*/
function parsePresentCommand(
parts: string[],
username: string,
): CommandParseResult | null {
if (parts.length < 2) {
console.warn(`Invalid !present command: missing evidenceId`);
return null;
}
const evidenceId = parts[1].toLowerCase();
if (!evidenceId || evidenceId.length > 64) {
console.warn(`Invalid evidenceId: ${parts[1]}`);
return null;
}
const statementNumber = parts[2] ? parseInt(parts[2], 10) : undefined;
if (statementNumber && (isNaN(statementNumber) || statementNumber < 1)) {
console.warn(`Invalid statement number: ${parts[2]}`);
return null;
}
return {
action: 'present',
username,
timestamp: Date.now(),
params: { evidenceId, statementNumber },
};
}
/**
* Parse !vote command
* Format: !vote <choice>
*/
function parseVoteCommand(
parts: string[],
username: string,
): CommandParseResult | null {
if (parts.length < 2) {
console.warn(`Invalid !vote command: missing choice`);
return null;
}
const choice = parts[1].toLowerCase();
if (!choice || choice.length > 64) {
console.warn(`Invalid vote choice: ${parts[1]}`);
return null;
}
return {
action: 'vote',
username,
timestamp: Date.now(),
params: { voteType: 'verdict', choice },
};
}
/**
* Parse !sentence command
* Format: !sentence <choice>
*/
function parseSentenceCommand(
parts: string[],
username: string,
): CommandParseResult | null {
if (parts.length < 2) {
console.warn(`Invalid !sentence command: missing sentence choice`);
return null;
}
const choice = parts[1].toLowerCase();
if (!choice || choice.length > 64) {
console.warn(`Invalid sentence choice: ${parts[1]}`);
return null;
}
return {
action: 'sentence',
username,
timestamp: Date.now(),
params: { voteType: 'sentence', choice },
};
}
/**
* Validate a command result (check for required fields, etc.)
*/
export function validateCommand(cmd: CommandParseResult): boolean {
if (!cmd.action || !cmd.username || cmd.timestamp <= 0) {
return false;
}
switch (cmd.action) {
case 'press':
return (
!isNaN(cmd.params.statementNumber) &&
cmd.params.statementNumber > 0
);
case 'present':
return (
typeof cmd.params.evidenceId === 'string' &&
cmd.params.evidenceId.length > 0
);
case 'vote':
case 'sentence':
return (
typeof cmd.params.choice === 'string' &&
cmd.params.choice.length > 0
);
default:
return false;
}
}

232
src/twitch/eventsub.ts Normal file
View File

@@ -0,0 +1,232 @@
/**
* Twitch EventSub Webhook Handler
*
* Handles channel point redemptions from Twitch EventSub webhook
* Maps redemptions to court actions (objection, hold it, order in court)
*/
import crypto from 'crypto';
import type { Request, Response } from 'express';
export interface EventSubEvent {
subscription: {
id: string;
type: string;
version: string;
status: string;
created_at: string;
transport: {
method: string;
callback: string;
};
condition: Record<string, string>;
};
event: {
id: string;
user_id: string;
user_login: string;
user_name: string;
broadcaster_user_id: string;
broadcaster_user_login: string;
broadcaster_user_name: string;
reward: {
id: string;
title: string;
cost: number;
};
redeemed_at: string;
status?: string;
};
}
/**
* Validates Twitch EventSub webhook signature
* Returns true if signature is valid, false otherwise
*/
export function validateEventSubSignature(
request: Request,
clientSecret: string,
): boolean {
const twitch_message_id = request.headers[
'twitch-eventsub-message-id'
] as string;
const twitch_timestamp = request.headers[
'twitch-eventsub-message-timestamp'
] as string;
const twitch_signature = request.headers[
'twitch-eventsub-message-signature'
] as string;
if (!twitch_message_id || !twitch_timestamp || !twitch_signature) {
console.warn('Missing EventSub headers');
return false;
}
// Prevent replay attacks (within 10 minutes)
const now = Math.floor(Date.now() / 1000);
const timestamp = parseInt(twitch_timestamp, 10);
if (Math.abs(now - timestamp) > 600) {
console.warn('EventSub message timestamp outside acceptable window');
return false;
}
const message =
twitch_message_id + twitch_timestamp + JSON.stringify(request.body);
const hmac = crypto.createHmac('sha256', clientSecret);
hmac.update(message);
const computed_signature = `sha256=${hmac.digest('hex')}`;
// Use constant-time comparison to prevent timing attacks
return crypto.timingSafeEqual(
Buffer.from(twitch_signature),
Buffer.from(computed_signature),
);
}
/**
* Parse EventSub webhook body
*/
export function parseEventSubWebhook(body: unknown): EventSubEvent | null {
if (typeof body !== 'object' || body === null) {
return null;
}
const event = body as any;
// Handle challenge request (initial verification)
if (event.subscription?.type === 'webhook_callback_verification') {
console.log('[EventSub] Received challenge request');
return null;
}
// Validate event structure
if (
!event.subscription ||
!event.event ||
!event.subscription.type ||
!event.event.user_name
) {
console.warn('[EventSub] Invalid event structure');
return null;
}
return event as EventSubEvent;
}
/**
* Map EventSub channel point redemption to court action
*/
export function mapRedemptionToAction(
rewardTitle: string,
): { action: 'objection' | 'hold_it' | 'order_in_court' } | null {
const normalized = rewardTitle.toLowerCase().trim();
if (normalized.includes('objection')) {
return { action: 'objection' };
}
if (normalized.includes('hold it') || normalized.includes('hold_it')) {
return { action: 'hold_it' };
}
if (normalized.includes('order')) {
return { action: 'order_in_court' };
}
return null;
}
/**
* Redemption rate limit configuration per phase loop
*/
export interface RedemptionRateLimitConfig {
maxPerPhaseLoop: number; // Max redemptions per witness_exam loop
maxPerSession: number; // Max redemptions per entire session
cooldownMs: number; // Cooldown between same redemption type
}
export const DEFAULT_REDEMPTION_RATE_LIMIT: RedemptionRateLimitConfig = {
maxPerPhaseLoop: 1,
maxPerSession: 10,
cooldownMs: 60_000, // 60 seconds
};
/**
* Track redemptions for rate limiting
*/
export class RedemptionRateLimiter {
private redemptions: Map<
string,
{
count: number;
lastTimestamp: number;
}
> = new Map();
constructor(private config: RedemptionRateLimitConfig) {}
/**
* Check if redemption is allowed
*/
public check(
sessionId: string,
action: string,
): { allowed: boolean; reason?: string } {
const key = `${sessionId}:${action}`;
const now = Date.now();
const entry = this.redemptions.get(key);
// Cooldown check
if (entry && now - entry.lastTimestamp < this.config.cooldownMs) {
return {
allowed: false,
reason: 'cooldown',
};
}
// Session limit check
if (entry && entry.count >= this.config.maxPerSession) {
return {
allowed: false,
reason: 'session_limit',
};
}
return { allowed: true };
}
/**
* Record a redemption
*/
public record(sessionId: string, action: string): void {
const key = `${sessionId}:${action}`;
const entry = this.redemptions.get(key) ?? {
count: 0,
lastTimestamp: 0,
};
entry.count++;
entry.lastTimestamp = Date.now();
this.redemptions.set(key, entry);
}
/**
* Reset cooldowns for a new phase loop
*/
public resetPhaseLoop(): void {
// Preserve counts but reset timestamps to allow new redemptions
for (const entry of this.redemptions.values()) {
entry.lastTimestamp = 0;
}
}
/**
* Clear all redemptions for a session
*/
public clearSession(sessionId: string): void {
for (const [key] of this.redemptions.entries()) {
if (key.startsWith(`${sessionId}:`)) {
this.redemptions.delete(key);
}
}
}
}