Slice 3 of dev-overlay-end-to-end. Adds a fourth DevOverlay tab that
tails every log record from every Jarvis subsystem in real time —
agent, voice, vision, memory, MCP, bus, replay, system — without
polling files or relying on Console.app.
How it works:
1. `LogBroadcaster` (new) — process-wide actor with a 500-line ring
buffer + subscriber set. Borrowed shape from
OrchestratorEventBroadcaster so the project's three broadcasters
share a mental model. New subscribers replay the buffer in order,
then go live.
2. `BroadcastLogHandler` (new) — swift-log LogHandler conformance.
Formats each log call into a `LogLine` and schedules an unstructured
`Task { await LogBroadcaster.shared.publish(...) }` so the logging
caller never blocks on actor isolation. Synchronous handler contract
preserved; ordering is best-effort under heavy load.
3. `LoggingBootstrap.make(label:)` now returns
`MultiplexLogHandler([file, os, broadcast])` — the new handler is
purely additive. File rotation + os.Logger streaming unchanged.
4. `DevOverlayLogsView` (new) — fourth tab in the overlay. Subscribes
to `LogBroadcaster.shared` on appear, caps at 1000 lines, renders
monospaced. Per-channel filter (Menu w/ checkboxes), per-level
filter (debug → critical), substring search, Pause/Resume button
(Cmd+P), auto-scroll-to-bottom while not paused. Color-coded by
level (warn=orange, error/critical=red).
Tests:
- 5 new LogBroadcasterTests covering publish/cap/replay/live/handler.
- swift test --package-path packages/Logging → 22/22 pass.
- swift test --package-path packages/DevOverlay → 14/14 pass.
- bash scripts/check-app-builds.sh → PASS.
- 18/18 boundary gates green.
Redaction note: file handler still routes through Redact.apply for
disk writes; the broadcaster sees raw messages because the DevOverlay
is a developer-only in-process surface. If this ever becomes
user-facing, route through Redact before publishing.
Logging
Library product JarvisLogging. Channel taxonomy + swift-log bootstrap + file rotation + the Redact helper.
Key public types
| Type | Purpose |
|---|---|
JarvisLogChannel |
Channel enum — agent, tools, ui, system, plus subsystem-specific |
LoggingBootstrap |
Wires swift-log to OSLogHandler (default) + FileLogHandler (rotation) |
OSLogHandler |
os_log backend |
FileLogHandler |
NDJSON rotating file backend |
FileRotatingWriter |
Size + time-based rotation |
Redact |
Mask helper for secrets in logger.debug strings |
LogPaths |
~/Library/Application Support/Jarvis/logs/ resolver |
DateProvider |
Test seam for deterministic timestamps |
Depends on
External only: swift-log.
Used by
Every package and App/. This is the leaf logging dependency for the whole project.
Key invariants / contracts
- Bootstrap is idempotent. Calling
LoggingBootstrap.bootstrap()twice is a no-op. - Channels match the taxonomy in CLAUDE.md. Don't invent ad-hoc subsystems — extend the enum.
Redactis the only sanitizer for log strings that may contain secrets / PII / transcript text.- T-06-05-03: never log voice transcript text. Enforced by code review + reading every Voice/Memory
logger.debugsite. - File rotation: size cap + age cap. Old logs get rolled to
.gzsiblings, then pruned.
Tests
XCTest. Round-trip log emission, rotation triggers, redact patterns.
Notable files
Sources/JarvisLogging/JarvisLogChannel.swift— channel enumSources/JarvisLogging/LoggingBootstrap.swift— entry pointSources/JarvisLogging/Redact.swift— sanitizerSources/JarvisLogging/FileRotatingWriter.swift— rotation