diff --git a/docs/plans/2026-03-10-admin-log-panel-design.md b/docs/plans/2026-03-10-admin-log-panel-design.md new file mode 100644 index 0000000..026ef4d --- /dev/null +++ b/docs/plans/2026-03-10-admin-log-panel-design.md @@ -0,0 +1,82 @@ +# Admin & Log Panel Design + +## Overview + +Add two new tabs to the left panel: an Admin tab (A) for runtime constant editing behind password authentication, and a Log tab (L) for streaming server-side operational logs. + +## Admin Tab + +### Authentication +- Password-gated: "dwarf" hardcoded server-side (will move to .env later) +- Authenticated once per session; stays unlocked until page refresh +- Server validates password via `admin-auth` socket event, never trusts client + +### Constant Editor +- Exposes gameplay tuning constants only (not world size, asset/rendering): + - Tick rates: TICK_RATE, BROADCAST_EVERY_N_TICKS + - Needs: HUNGER_DECAY_PER_TICK, ENERGY_DECAY_PER_TICK, HUNGER_THRESHOLD, ENERGY_THRESHOLD + - Sleep: ENERGY_RECOVERY_PER_TICK, WAKE_THRESHOLD, VOLUNTARY_SLEEP_THRESHOLD + - Day/night: DAY_DURATION_SECONDS, DAY_NIGHT_RATIO + - Social: AWARENESS_RADIUS, FACING_DURATION, PAUSING_DURATION, EMOTING_DURATION, COOLDOWN_DURATION +- Each constant displayed as: label, editable number input, muted default value +- Changes apply immediately (debounced ~300ms) +- "Reset to Defaults" button restores all to compiled defaults + +### Protocol +- `admin-auth` (client→server): { password } → { success, constants? } +- `admin-update-constant` (client→server): { key, value } → server validates and applies +- `admin-reset-defaults` (client→server): resets all to defaults +- `admin-constants-updated` (server→client): full current constants object + +### Server: Runtime Constants +- `server/src/config/runtimeConstants.ts`: initializes from shared constants +- Exposes `getRuntimeConstants()`, `updateConstant(key, value)`, `resetDefaults()` +- Stores original defaults for reset +- Systems switch imports from shared constants to runtime constants object + +## Log Tab + +### UI +- Scrollable reverse-chronological log entries +- Each entry: wall-clock timestamp, severity (error/warning/info), category tag, message +- Severity color-coded: red (error), yellow (warning), blue (info) +- Category tags: LLM, Save, Network, Performance, Game + +### Protocol (subscribe/unsubscribe pattern) +- `log-subscribe` (client→server): starts streaming → server sends `log-history` (recent buffer) +- `log-entry` (server→client): pushed while subscribed +- `log-unsubscribe` (client→server): stops streaming + +### Server: LogService +- Ring buffer of last 200 entries +- `log(severity, category, message)` method +- Tracks subscribed sockets, pushes only to subscribers + +### Log Sources (11 categories) +1. **LLM failures** — HTTP errors, bad responses +2. **LLM timeouts** — 15s default exceeded +3. **LLM rate limits** — 429 responses, fallback model switches +4. **LLM parse failures** — JSON parse errors on backstory/desire/invention responses +5. **LLM token milestones** — every 100 requests summary +6. **Save/load errors** — SQLite write failures, schema migration issues +7. **Serialization failures** — component data that can't serialize/deserialize +8. **NPC spawn failures** — appearance generation or ID assignment errors +9. **Player connect/disconnect** — network join/leave events +10. **Socket errors** — unexpected disconnects +11. **Tick overruns** — game tick exceeds tick interval duration + +## Integration + +### Left Panel +- Grows from 4 tabs (S/E/I/R) to 6 tabs (S/E/I/R/L/A) +- New files: `client/src/ui/AdminPanel.ts`, `client/src/ui/LogPanel.ts` +- Passed to LeftPanel constructor like existing content panels + +### Shared Types +- New socket event types added to `shared/src/types.ts` +- `TunableConstants` interface for the editable constant subset + +### Unchanged +- Right-side NPC info panel +- Existing 4 left panel tab content +- Game system behavior (just reads from runtime constants instead of imports)