From 2368564523b6fa80e1076f9fc2921924d9192056 Mon Sep 17 00:00:00 2001 From: Mathias Date: Tue, 23 Jun 2026 10:47:00 +0200 Subject: [PATCH] fix(capture): wire ai-sessions SummaryWriter into the relay (#66) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The deployed CaptureService was constructed with a nil SummaryWriter, so a capture carrying a summary block returned the partial-failure "no summary writer configured" (surfaced in the 2026-06-23 claude.ai dogfood). The Gitea client already reaches mathias/* over BRAIN_GITEA_TOKEN and now implements SummaryWriter, so inject it (type-asserted from the tracker) — no new credential, no manifest change. Session summaries now write to mathias/ai-sessions at summaries///... Reuses the existing token deliberately; assumes it carries contents:write scope on ai-sessions (it already does issue writes for the tracker). If the token is issue-scoped only, the live write 422s — a token-scope widen, not a code fix. Co-Authored-By: Claude Opus 4.8 (1M context) --- ingestion/cmd/server/main.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ingestion/cmd/server/main.go b/ingestion/cmd/server/main.go index 2294b32..d3a3f18 100644 --- a/ingestion/cmd/server/main.go +++ b/ingestion/cmd/server/main.go @@ -410,8 +410,12 @@ func main() { os.Exit(1) } auditSink := buildAuditSink(ctx, brainDir, logger) + // The Gitea client also satisfies SummaryWriter (#66): session + // summaries are written to mathias/ai-sessions over the same API + // token. nil only if a future tracker impl lacks file writes. + summaryWriter, _ := tracker.(capture.SummaryWriter) captureSvc := capture.NewService( - mcpSrv.BrainStore(), tracker, nil, classCfg, auditSink) + mcpSrv.BrainStore(), tracker, summaryWriter, classCfg, auditSink) sovereign := splitList(os.Getenv("BRAIN_CAPTURE_SOVEREIGN_PRINCIPALS")) resolver := capturehttp.NewOriginResolver(sovereign) captureH := capturehttp.New(captureSvc, jwtValidator, mcpToken, "local-cli", resolver)