Motivation
Resolving a conflict in the WebUI throws an error, but the cause isn't visible from the browser — you have to reach the container logs. We need logging of everything surfaced in the WebUI with easy copy buttons, so errors (like the conflict one) can be captured and shared without shell access.
Scope
internal/logbuf — a thread-safe in-memory ring buffer (io.Writer, bounded to the last N lines) with conservative secret redaction (PATs, Bearer …, token=…) so exposing logs never leaks credentials.
- HTTP process wiring (
cmd/http) — route both the stdlib log output (5xx internal errors via writeError) and the chi access log (every request + status, so 4xx like the conflict error also show) through io.MultiWriter(stderr, ring). Container logs are unchanged; the ring is an extra sink.
GET /api/logs — read endpoint returning the recent lines (same read posture as /system, /health).
- WebUI Logs tab — scrollable log view, Copy all button + per-line copy, refresh, auto-scroll to newest.
- Docs: SYSTEM.md (§9 operability + §16 security note on log exposure) + Decision Log.
Notes / security
- The HTTP server process is what serves the WebUI and handles conflict resolution, so its logs cover the reported bug. The MCP server is a separate stdio process (logs to Claude's stderr) — out of scope for the WebUI viewer.
- Logs can contain request paths and search queries; the endpoint follows the existing open-read posture (protect the whole surface via the reverse proxy, §16). Redaction guards against obvious credential leakage.
Follow-up
Once this ships, capture the actual conflict-resolution error from the Logs tab and open a separate bug issue with the real message (hypothesis: write endpoints require bearer auth the WebUI doesn't send).
Motivation
Resolving a conflict in the WebUI throws an error, but the cause isn't visible from the browser — you have to reach the container logs. We need logging of everything surfaced in the WebUI with easy copy buttons, so errors (like the conflict one) can be captured and shared without shell access.
Scope
internal/logbuf— a thread-safe in-memory ring buffer (io.Writer, bounded to the last N lines) with conservative secret redaction (PATs,Bearer …,token=…) so exposing logs never leaks credentials.cmd/http) — route both the stdliblogoutput (5xx internal errors viawriteError) and the chi access log (every request + status, so 4xx like the conflict error also show) throughio.MultiWriter(stderr, ring). Container logs are unchanged; the ring is an extra sink.GET /api/logs— read endpoint returning the recent lines (same read posture as/system,/health).Notes / security
Follow-up
Once this ships, capture the actual conflict-resolution error from the Logs tab and open a separate bug issue with the real message (hypothesis: write endpoints require bearer auth the WebUI doesn't send).