First live dogfood of brain:capture from claude.ai (2026-06-23 closeout) returned a partial success: insights + ticket landed, but the summary failed with:
The SummaryWriter port has no concrete implementation wired in the deployed relay — so summary.{title,body,repos_touched} is accepted, validated, and then silently no-ops with an error in the receipt. Insights (BrainStore) and tickets (IssueTracker) work; the ai-sessions summary path does not.
What worked (so this is a wiring gap, not a design fault)
4 insights written to brain (wiki/hyperguild/{decisions,failures}/...)
effective_classification correctly resolved to internal; I1 gate passed
partial-failure semantics worked as specced (§4): no rollback, honest per-item receipt naming exactly the failed component. That's the best-effort design validated under a real failure.
Likely cause
The SummaryWriter impl (writes to mathias/ai-sessions at summaries/<harness>/<YYYY-MM>/...) is either not constructed or not injected into the deployed CaptureService wiring. Capture sub-issue #54/#49d-e built the port + adapter; the deploy (infra #152) may not have provided the ai-sessions Gitea target/token to the relay, or the constructor leaves SummaryWriter nil and the service treats nil as "not configured."
Acceptance
SummaryWriter concretely wired in the deployed relay (ai-sessions repo + token/credential present)
A capture with a summary block writes the file to ai-sessions and returns summary.ok=true with the path
If SummaryWriter is intentionally optional, the receipt should distinguish "not configured" (operator gap) from a write error — and a capture that supplies a summary to a relay without a writer should surface as a louder warning, not a quiet per-item error
Verify the deploy manifest (infra k3s/apps/**) provides the ai-sessions target + credential
Re-dogfood from claude.ai: full capture (insights + ticket + summary) all ok=true
Repro
Run any brain:capture from the claude.ai connector with a populated summary block. Insights/tickets succeed; summary returns ok:false, "no summary writer configured".
Related
#49 (capture epic), #54 (audit/adapter), infra #152 (relay deploy)
The 2026-06-23 closeout that surfaced this; insights captured at wiki/hyperguild/decisions/the-capture-capability-shipped-v0-11-0-hyperguild-49.md et al.
## Symptom
First live dogfood of `brain:capture` from claude.ai (2026-06-23 closeout) returned a **partial success**: insights + ticket landed, but the summary failed with:
```
"summary": {"ok": false}
"errors": [{"item": "summary", "error": "no summary writer configured"}]
```
The `SummaryWriter` port has no concrete implementation wired in the **deployed relay** — so `summary.{title,body,repos_touched}` is accepted, validated, and then silently no-ops with an error in the receipt. Insights (BrainStore) and tickets (IssueTracker) work; the ai-sessions summary path does not.
## What worked (so this is a wiring gap, not a design fault)
- 4 insights written to brain (`wiki/hyperguild/{decisions,failures}/...`)
- ticket filed (this issue's sibling, #65)
- effective_classification correctly resolved to `internal`; I1 gate passed
- **partial-failure semantics worked as specced** (§4): no rollback, honest per-item receipt naming exactly the failed component. That's the best-effort design validated under a real failure.
## Likely cause
The `SummaryWriter` impl (writes to `mathias/ai-sessions` at `summaries/<harness>/<YYYY-MM>/...`) is either not constructed or not injected into the deployed `CaptureService` wiring. Capture sub-issue #54/#49d-e built the port + adapter; the deploy (infra #152) may not have provided the ai-sessions Gitea target/token to the relay, or the constructor leaves `SummaryWriter` nil and the service treats nil as "not configured."
## Acceptance
- [ ] `SummaryWriter` concretely wired in the deployed relay (ai-sessions repo + token/credential present)
- [ ] A capture with a `summary` block writes the file to `ai-sessions` and returns `summary.ok=true` with the path
- [ ] If `SummaryWriter` is *intentionally* optional, the receipt should distinguish "not configured" (operator gap) from a write error — and a capture that supplies a summary to a relay without a writer should surface as a louder warning, not a quiet per-item error
- [ ] Verify the deploy manifest (infra `k3s/apps/**`) provides the ai-sessions target + credential
- [ ] Re-dogfood from claude.ai: full capture (insights + ticket + summary) all `ok=true`
## Repro
Run any `brain:capture` from the claude.ai connector with a populated `summary` block. Insights/tickets succeed; summary returns `ok:false, "no summary writer configured"`.
## Related
- #49 (capture epic), #54 (audit/adapter), infra #152 (relay deploy)
- The 2026-06-23 closeout that surfaced this; insights captured at `wiki/hyperguild/decisions/the-capture-capability-shipped-v0-11-0-hyperguild-49.md` et al.
Koala dispatch — "make capture fully work from claude.ai" (pairs #66 + #67)
Goal: after this session, a brain:capture call from the claude.ai connector with insights + tickets + summary touching the normal homelab repos succeeds fully (all ok=true, no I1 refusal). Two sibling fixes get there; do both, in this order.
Order matters
#67 first (classification.yaml). Until homelab repos are tagged internal, any capture touching ai-sessions fail-safes to confidential and the I1 gate refuses it — which would make a #66 fix untestable from claude.ai. So tag first, then you can actually verify the summary path end-to-end.
#66 second (SummaryWriter wiring). Wire the ai-sessions SummaryWriter into the deployed relay so the summary block stops returning no summary writer configured.
Autonomy boundaries — STOP and ask Mathias, do not invent:
#66 credential: wiring the SummaryWriter needs the relay to reach mathias/ai-sessions with a token. If no ai-sessions-capable credential is already in the relay's env/secret, stop — do not mint or hardcode one. Secret provisioning (1Password vault + external-secrets) is Mathias's call, and any new secret + manifest change is a GitOps/I3 change in infra/k3s/apps/**, not a code-only fix.
#67 repo→level map: the classification map is a sovereignty decision (which repos are safe through us-nexus), not a mechanical fill. Draft the internal list, but have Mathias confirm it before merge. When unsure, leave a repo untagged (fail-safe confidential) rather than tag it permissively.
Verify before claiming done
Re-run a capture from a test principal (or have Mathias re-dogfood from claude.ai) with insights + ticket + summary, all touching only tagged-internal repos → expect effective_classification: internal, every item ok=true, a real summary.path.
Regression: an untagged/unknown repo still resolves confidential (don't break the fail-safe).
task check green; secret-handling respected (no token in argv/logs).
Context koala should read first
specs/capture-bdd-spec.md (the binding design — esp. §4.1 classification model C, §4.4 audit posture)
#56 diff (ingestion/internal/classification/) for the classification.yaml schema + defaultFor() behavior
brain wiki/hyperguild/failures/first-live-dogfood-of-braincapture-surfaced-two-real-operat.md (why both gaps exist)
Both are bounded and testable. The only non-autonomous parts are the two STOP points above — flag them and wait, don't work around them.
## Koala dispatch — "make capture fully work from claude.ai" (pairs #66 + #67)
**Goal:** after this session, a `brain:capture` call from the claude.ai connector with insights + tickets + **summary** touching the normal homelab repos succeeds fully (all `ok=true`, no I1 refusal). Two sibling fixes get there; do both, in this order.
### Order matters
1. **#67 first (classification.yaml).** Until homelab repos are tagged `internal`, any capture touching `ai-sessions` fail-safes to confidential and the I1 gate refuses it — which would make a #66 fix untestable from claude.ai. So tag first, then you can actually verify the summary path end-to-end.
2. **#66 second (SummaryWriter wiring).** Wire the ai-sessions `SummaryWriter` into the deployed relay so the summary block stops returning `no summary writer configured`.
### Autonomy boundaries — STOP and ask Mathias, do not invent:
- **#66 credential:** wiring the SummaryWriter needs the relay to reach `mathias/ai-sessions` with a token. If no ai-sessions-capable credential is already in the relay's env/secret, **stop** — do not mint or hardcode one. Secret provisioning (1Password vault + external-secrets) is Mathias's call, and any new secret + manifest change is a GitOps/I3 change in `infra/k3s/apps/**`, not a code-only fix.
- **#67 repo→level map:** the classification map is a **sovereignty decision** (which repos are safe through us-nexus), not a mechanical fill. Draft the `internal` list, but have Mathias confirm it before merge. When unsure, leave a repo untagged (fail-safe confidential) rather than tag it permissively.
### Verify before claiming done
- Re-run a capture from a test principal (or have Mathias re-dogfood from claude.ai) with insights + ticket + **summary**, all touching only tagged-internal repos → expect `effective_classification: internal`, every item `ok=true`, a real `summary.path`.
- Regression: an untagged/unknown repo still resolves confidential (don't break the fail-safe).
- `task check` green; secret-handling respected (no token in argv/logs).
### Context koala should read first
- `specs/capture-bdd-spec.md` (the binding design — esp. §4.1 classification model C, §4.4 audit posture)
- #56 diff (`ingestion/internal/classification/`) for the `classification.yaml` schema + `defaultFor()` behavior
- brain `wiki/hyperguild/failures/first-live-dogfood-of-braincapture-surfaced-two-real-operat.md` (why both gaps exist)
Both are bounded and testable. The only non-autonomous parts are the two STOP points above — flag them and wait, don't work around them.
gitea.Client.WriteFile (contents API, upsert) → the client now implements capture.SummaryWriter; injected into the deployed CaptureService. Summaries write to mathias/ai-sessions at summaries/<harness>/<YYYY-MM>/….
STOP point handled, not worked around: the relay already carries BRAIN_GITEA_TOKEN (owner mathias, used for tracker issue writes). I reused it — did not mint/hardcode a credential, so no new secret + no infra change. The issue's "likely cause" (deploy didn't provide an ai-sessions target/token) turned out not to need one.
⚠️One thing for you to confirm: the token must have contents/write:repository scope on mathias/ai-sessions, not issue-only. If it's issue-scoped, the live write 422s → widen the token in 1P (your secret call, not a code fix). Tests cover create / update-with-sha / error-no-token-leak.
Re-dogfood is gated on #67 — until ai-sessions is tagged internal, the I1 gate refuses a claude.ai capture before the summary path runs. Merge order: brain #12 (#67) → restart → #68 → re-dogfood. task check green.
## Fixed — PR #68 (code-only, no manifest change)
`gitea.Client.WriteFile` (contents API, upsert) → the client now implements `capture.SummaryWriter`; injected into the deployed `CaptureService`. Summaries write to `mathias/ai-sessions` at `summaries/<harness>/<YYYY-MM>/…`.
**STOP point handled, not worked around:** the relay already carries `BRAIN_GITEA_TOKEN` (owner mathias, used for tracker issue writes). I **reused it** — did not mint/hardcode a credential, so no new secret + no infra change. The issue's "likely cause" (deploy didn't provide an ai-sessions target/token) turned out not to need one.
⚠️ **One thing for you to confirm:** the token must have **contents/`write:repository` scope** on `mathias/ai-sessions`, not issue-only. If it's issue-scoped, the live write 422s → widen the token in 1P (your secret call, not a code fix). Tests cover create / update-with-sha / error-no-token-leak.
**Re-dogfood is gated on #67** — until ai-sessions is tagged `internal`, the I1 gate refuses a claude.ai capture before the summary path runs. Merge order: brain #12 (#67) → restart → #68 → re-dogfood. `task check` green.
summary → summaries/claudeai-chat/2026-07/2026-07-07-capture-re-dogfood-...-8360f6dd.md ← the path type that returned no summary writer configured on 2026-06-23, now writing.
Token scope — BRAIN_GITEA_TOKEN has contents/write on ai-sessions (the live write didn't 422; the issue-scope caveat from PR #68 is moot).
POST-create/PUT-update fix works against the real Gitea API, not just the httptest mock (the mock-validates-the-bug trap that hid the original 422 is genuinely closed).
Capture epic #49 is now verified end-to-end from claude.ai. No open capture items remain.
## ✅ Live re-dogfood passed (2026-07-07) — loop closed
Full `brain:capture` from the claude.ai connector, `dry_run: false`, all items `ok=true`, `errors: []`:
- insight → `wiki/hyperguild/facts/capture-re-dogfood-verification-2026-07-07-confirming-the.md`
- **summary → `summaries/claudeai-chat/2026-07/2026-07-07-capture-re-dogfood-...-8360f6dd.md`** ← the path type that returned `no summary writer configured` on 2026-06-23, now writing.
- `effective_classification: internal`, I1 gate passed.
This confirms the two things a dry-run couldn't:
1. **Token scope** — `BRAIN_GITEA_TOKEN` has contents/write on `ai-sessions` (the live write didn't 422; the issue-scope caveat from PR #68 is moot).
2. **POST-create/PUT-update** fix works against the **real** Gitea API, not just the httptest mock (the mock-validates-the-bug trap that hid the original 422 is genuinely closed).
Capture epic #49 is now verified end-to-end from claude.ai. No open capture items remain.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Symptom
First live dogfood of
brain:capturefrom claude.ai (2026-06-23 closeout) returned a partial success: insights + ticket landed, but the summary failed with:The
SummaryWriterport has no concrete implementation wired in the deployed relay — sosummary.{title,body,repos_touched}is accepted, validated, and then silently no-ops with an error in the receipt. Insights (BrainStore) and tickets (IssueTracker) work; the ai-sessions summary path does not.What worked (so this is a wiring gap, not a design fault)
wiki/hyperguild/{decisions,failures}/...)internal; I1 gate passedLikely cause
The
SummaryWriterimpl (writes tomathias/ai-sessionsatsummaries/<harness>/<YYYY-MM>/...) is either not constructed or not injected into the deployedCaptureServicewiring. Capture sub-issue #54/#49d-e built the port + adapter; the deploy (infra #152) may not have provided the ai-sessions Gitea target/token to the relay, or the constructor leavesSummaryWriternil and the service treats nil as "not configured."Acceptance
SummaryWriterconcretely wired in the deployed relay (ai-sessions repo + token/credential present)summaryblock writes the file toai-sessionsand returnssummary.ok=truewith the pathSummaryWriteris intentionally optional, the receipt should distinguish "not configured" (operator gap) from a write error — and a capture that supplies a summary to a relay without a writer should surface as a louder warning, not a quiet per-item errork3s/apps/**) provides the ai-sessions target + credentialok=trueRepro
Run any
brain:capturefrom the claude.ai connector with a populatedsummaryblock. Insights/tickets succeed; summary returnsok:false, "no summary writer configured".Related
wiki/hyperguild/decisions/the-capture-capability-shipped-v0-11-0-hyperguild-49.mdet al.Koala dispatch — "make capture fully work from claude.ai" (pairs #66 + #67)
Goal: after this session, a
brain:capturecall from the claude.ai connector with insights + tickets + summary touching the normal homelab repos succeeds fully (allok=true, no I1 refusal). Two sibling fixes get there; do both, in this order.Order matters
internal, any capture touchingai-sessionsfail-safes to confidential and the I1 gate refuses it — which would make a #66 fix untestable from claude.ai. So tag first, then you can actually verify the summary path end-to-end.SummaryWriterinto the deployed relay so the summary block stops returningno summary writer configured.Autonomy boundaries — STOP and ask Mathias, do not invent:
mathias/ai-sessionswith a token. If no ai-sessions-capable credential is already in the relay's env/secret, stop — do not mint or hardcode one. Secret provisioning (1Password vault + external-secrets) is Mathias's call, and any new secret + manifest change is a GitOps/I3 change ininfra/k3s/apps/**, not a code-only fix.internallist, but have Mathias confirm it before merge. When unsure, leave a repo untagged (fail-safe confidential) rather than tag it permissively.Verify before claiming done
effective_classification: internal, every itemok=true, a realsummary.path.task checkgreen; secret-handling respected (no token in argv/logs).Context koala should read first
specs/capture-bdd-spec.md(the binding design — esp. §4.1 classification model C, §4.4 audit posture)ingestion/internal/classification/) for theclassification.yamlschema +defaultFor()behaviorwiki/hyperguild/failures/first-live-dogfood-of-braincapture-surfaced-two-real-operat.md(why both gaps exist)Both are bounded and testable. The only non-autonomous parts are the two STOP points above — flag them and wait, don't work around them.
Fixed — PR #68 (code-only, no manifest change)
gitea.Client.WriteFile(contents API, upsert) → the client now implementscapture.SummaryWriter; injected into the deployedCaptureService. Summaries write tomathias/ai-sessionsatsummaries/<harness>/<YYYY-MM>/….STOP point handled, not worked around: the relay already carries
BRAIN_GITEA_TOKEN(owner mathias, used for tracker issue writes). I reused it — did not mint/hardcode a credential, so no new secret + no infra change. The issue's "likely cause" (deploy didn't provide an ai-sessions target/token) turned out not to need one.⚠️ One thing for you to confirm: the token must have contents/
write:repositoryscope onmathias/ai-sessions, not issue-only. If it's issue-scoped, the live write 422s → widen the token in 1P (your secret call, not a code fix). Tests cover create / update-with-sha / error-no-token-leak.Re-dogfood is gated on #67 — until ai-sessions is tagged
internal, the I1 gate refuses a claude.ai capture before the summary path runs. Merge order: brain #12 (#67) → restart → #68 → re-dogfood.task checkgreen.✅ Live re-dogfood passed (2026-07-07) — loop closed
Full
brain:capturefrom the claude.ai connector,dry_run: false, all itemsok=true,errors: []:wiki/hyperguild/facts/capture-re-dogfood-verification-2026-07-07-confirming-the.mdsummaries/claudeai-chat/2026-07/2026-07-07-capture-re-dogfood-...-8360f6dd.md← the path type that returnedno summary writer configuredon 2026-06-23, now writing.effective_classification: internal, I1 gate passed.This confirms the two things a dry-run couldn't:
BRAIN_GITEA_TOKENhas contents/write onai-sessions(the live write didn't 422; the issue-scope caveat from PR #68 is moot).Capture epic #49 is now verified end-to-end from claude.ai. No open capture items remain.