fix: wire ai-sessions SummaryWriter into the capture relay (#66) #68

Merged
mathias merged 3 commits from fix/capture-summarywriter into main 2026-06-23 15:22:42 +00:00
Owner

Fixes #66 — the deployed relay had a nil SummaryWriter, so a capture carrying a summary block returned summary.ok=false, "no summary writer configured" (the 2026-06-23 claude.ai dogfood partial-success).

Fix (code-only, no new secret)

  • gitea.Client.WriteFile (contents API) — the Gitea client now also implements capture.SummaryWriter. Upserts: a GET resolves the current blob sha so a re-captured session updates its summary (the richer-fidelity-supersedes rule) instead of 422'ing on a duplicate path.
  • main: inject the Gitea client as the SummaryWriter (type-asserted from the tracker — same *gitea.Client). Summaries write to mathias/ai-sessions at summaries/<harness>/<YYYY-MM>/<date>-<slug>-<ref8>.md.

On the #66 STOP point (ai-sessions credential)

The relay already has BRAIN_GITEA_TOKEN (owner mathias, used by the tracker for mathias/* issue writes). I reused it — did not mint or hardcode a new credential. So no infra/manifest change.

⚠️ One assumption for you to confirm: this needs the token to carry write:repository/contents scope on mathias/ai-sessions, not just issue scope. It already does issue writes; if it's issue-scoped only, the live summary write will 422 and you'll need to widen the token scope in 1Password (a secret call — yours, not a code fix). Everything else lands regardless (partial-receipt semantics).

Acceptance

  • SummaryWriter concretely wired in the relay (reuses present credential)
  • A capture with a summary writes to ai-sessions and returns summary.ok=true (service test with writer + gitea WriteFile httptest tests: create, update-with-sha, error-no-token-leak)
  • No manifest change needed — credential already present (corrects the issue's "likely cause")
  • Re-dogfood from claude.ai (insights + ticket + summary all ok=true) — yours, and gated on #67 (until ai-sessions is tagged internal, the I1 gate refuses the capture from us-nexus)
  • task check green; secret-handling respected

Verification order

Per the dispatch, end-to-end claude.ai verification needs #67 first (tag homelab repos internal) — otherwise a capture touching ai-sessions fail-safes to confidential and is refused before the summary path is reached. #67 PR follows (held for your sovereignty review of the repo→level map).

Closes #66

🤖 Generated with Claude Code

Fixes #66 — the deployed relay had a nil `SummaryWriter`, so a capture carrying a `summary` block returned `summary.ok=false, "no summary writer configured"` (the 2026-06-23 claude.ai dogfood partial-success). ## Fix (code-only, no new secret) - **`gitea.Client.WriteFile`** (contents API) — the Gitea client now also implements `capture.SummaryWriter`. Upserts: a GET resolves the current blob sha so a re-captured session **updates** its summary (the richer-fidelity-supersedes rule) instead of 422'ing on a duplicate path. - **main:** inject the Gitea client as the `SummaryWriter` (type-asserted from the tracker — same `*gitea.Client`). Summaries write to `mathias/ai-sessions` at `summaries/<harness>/<YYYY-MM>/<date>-<slug>-<ref8>.md`. ## On the #66 STOP point (ai-sessions credential) The relay **already has** `BRAIN_GITEA_TOKEN` (owner `mathias`, used by the tracker for `mathias/*` issue writes). I **reused it** — did **not** mint or hardcode a new credential. So no infra/manifest change. ⚠️ **One assumption for you to confirm:** this needs the token to carry **`write:repository`/contents scope** on `mathias/ai-sessions`, not just issue scope. It already does issue writes; if it's issue-scoped only, the live summary write will **422** and you'll need to widen the token scope in 1Password (a secret call — yours, not a code fix). Everything else lands regardless (partial-receipt semantics). ## Acceptance - [x] `SummaryWriter` concretely wired in the relay (reuses present credential) - [x] A capture with a `summary` writes to ai-sessions and returns `summary.ok=true` (service test with writer + gitea WriteFile httptest tests: create, update-with-sha, error-no-token-leak) - [x] No manifest change needed — credential already present (corrects the issue's "likely cause") - [ ] **Re-dogfood from claude.ai** (insights + ticket + summary all `ok=true`) — yours, and **gated on #67** (until ai-sessions is tagged `internal`, the I1 gate refuses the capture from us-nexus) - [x] `task check` green; secret-handling respected ## Verification order Per the dispatch, end-to-end claude.ai verification needs **#67 first** (tag homelab repos `internal`) — otherwise a capture touching `ai-sessions` fail-safes to confidential and is refused before the summary path is reached. #67 PR follows (held for your sovereignty review of the repo→level map). Closes #66 🤖 Generated with [Claude Code](https://claude.com/claude-code)
mathias added 2 commits 2026-06-23 08:47:20 +00:00
Adds Client.WriteFile (Gitea contents API) so the Gitea client also
implements capture.SummaryWriter. Upserts: a GET resolves the current
blob sha so an existing file is updated (the richer-fidelity-supersedes
rule for re-captured sessions) rather than 422'd. Owner stays the fixed
const; token only in the Authorization header (no leak — regression
tested). Refactors the HTTP path into a shared request() helper so the
contents flow can branch on 404 without it being an error.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix(capture): wire ai-sessions SummaryWriter into the relay (#66)
CI / Lint / Test / Vet (pull_request) Successful in 13s
CI / Mirror to GitHub (pull_request) Has been skipped
2368564523
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/<harness>/<YYYY-MM>/...

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) <noreply@anthropic.com>
mathias added 1 commit 2026-06-23 15:22:38 +00:00
fix(gitea): WriteFile creates via POST, updates via PUT (real contents API)
CI / Lint / Test / Vet (pull_request) Successful in 13s
CI / Mirror to GitHub (pull_request) Has been skipped
5288554338
A live token-scope probe against mathias/ai-sessions revealed gitea's
contents API uses POST to create and PUT (sha required) to update — the
first impl always PUT'd, so creating a new summary 422'd "[SHA]: Required".
The httptest mock had the same wrong assumption. Pick the method by
whether the file exists (GET sha). Token confirmed contents:write
(push:true) by the probe.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mathias merged commit d39a18dd69 into main 2026-06-23 15:22:42 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mathias/hyperguild#68