brain-mcp: capture with a tickets array fails; decide whether it graduates to its own repo (from infra#265) #91
Closed
opened 2026-08-11 21:15:54 +00:00 by mathias
·
5 comments
No Branch/Tag Specified
main
fix/pipeline-writes-158
fix/edit-path-io-192
fix/create-regular-188
fix/guard-special-179
fix/linkcheck-keeps-write-178
fix/write-dir-redirect-173
fix/tunnel-detect-174
fix/pipeline-root-157
w3/154-mcp-auth-wiring
fix/tunnel-traversal
test/in-brain-targets-171
fix/brain-scan-root-157
fix/graph-wiki-root-157
fix/vectorstore-root-157
fix/notes-root-157
fix/search-root-157
fix/brainwide-root-157
fix/raw-symlinks-153
feat/symlink-tripwire-157
fix/rest-auth-149
fix/123-brain-edit-envelope-check
feat/106-page-aware-extraction
fix/105-source-drift-on-main
fix/104-surface-merge-conflicts-on-main
agent/b1-compile-on-ingest
agent/104-surface-merge-conflicts
agent/105-source-drift
agent/107-loud-unconfigured-alerting
feat/brain-read-edit
fix/capture-i1-refusal-names-target
renovate/configure
feat/consolidate-single-harness
icebox/cmd-routing
feat/brain-pending-promote
fix/close-session-classification-refresh
fix/capture-summarywriter
v0.24.0
v0.23.1
v0.23.0
v0.22.0
v0.21.1
v0.21.0
v0.20.1
v0.20.0
v0.19.1
v0.19.0
v0.18.4
v0.18.3
v0.18.2
v0.18.1
v0.18.0
v0.17.0
v0.16.1
v0.16.0
v0.15.0
v0.14.0
v0.13.2
v0.13.1
v0.13.0
v0.12.1
v0.12.0
v0.11.2
icebox/cmd-routing-2026-07-01
v0.11.1
v0.11.0
v0.10.0
v0.9.0
v0.8.0
v0.7.0
v0.6.0
v0.5.0
v0.4.1
v0.4.0
v0.3.0
v0.2.0
v0.1.0
Labels
Clear labels
agent/ready
blocked/client
blocked/supplier
blocked/upstream
risk/high
risk/low
risk/medium
size/l
size/m
size/s
size/xs
status:dispatch
status:dispatched
status:review
status:reviewing
type/chore
type/decision
type/docs
type/feat
type/fix
type/ops
type/research
type/test
Meets the agent-ready contract; authorizes unattended execution
Waiting on the client
Waiting on a supplier
Waiting on an upstream project or vendor
Irreversible, security-relevant, or control plane
Reversible, local, test-covered
Touches shared state, deploys or data
Too big - split it
Under two days
Under half a day
Under an hour
Maintenance, no behaviour change
Human decision required; never agent/ready
Documentation only
New capability
Corrects broken behaviour
Infrastructure, deploy, runtime
Investigate; output is a finding, not code
Test coverage only
No labels
status:dispatch
Milestone
No items
No Milestone
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: mathias/hyperguild#91
Reference in New Issue
Block a user
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.
Filed from infra#265, which is closing — brain-mcp's code lives here, not in infra.
Where this actually lives
Confirmed 2026-08-11 from koala:
So brain-mcp is a component inside hyperguild's
ingestionservice, not a standalone deployable. The original issue's "can't find where this code lives" complaint was accurate — that's the finding, not a side note.Part 1 — the bug
capturewith aticketsarray fails. Callers currently fall back to N individualissue_createcalls: no data loss, but N round-trips instead of one.ticketsarray of length 1Part 2 — the repo question (decide, don't build)
Should brain-mcp graduate to
mathias/brain-mcp? Zero runtime blast radius either way; this is purely about whether a service with its own public ingress and its own consumers should be discoverable at its own name. Worth deciding rather than leaving implicit — the discoverability problem is what generated the original issue.Refs
docs/superpowers/specs/2026-08-11-backlog-verification.mdSprint-planning split (2026-08-18): this issue bundles a mechanical bug fix with a repo-graduation decision. For CAD execution, only part 1 is dispatchable — a headless agent should fix the
ticketsarray bug + regression test and stop there. Part 2 ("does brain-mcp graduate to its own repo?") is aDECISION NEEDEDfor Mathias, not something an autonomous run should resolve — leave that half open/unaddressed rather than guessing.Part 2 — decided: brain-mcp stays inside
ingestionADR in the brain:
wiki/hyperguild/decisions/brain-mcp-stays-in-ingestion-fix-discoverability-by-name.First, a flag: your comment above says part 2 is a
DECISION NEEDEDand an autonomous run should leave it alone. That still holds for headless CAD. This one was decided with you present and directing it, so the ADR records you as decider — but if you read the reasoning below and disagree, the decision is wrong, not the process.The split isn't actually on offer
internal/mcpimports 17 of ingestion's other internal packages —api,audit,brain,brainstore,capture,capturehttp,classification,extract,graph,graphstore,graphsync,pipeline,reranker,search,session,textutil,vectorstore. 3 007 lines of the service's 11 171, and exactly one importer:cmd/server/main.go.That is not a component sitting in the wrong repo. It is the MCP facade over the service's own internals — the tools are thin adapters onto the same store, index, graph and search that the HTTP API and the watcher use. So "graduate to
mathias/brain-mcp" resolves to one of:ingestion, it doesn't split it;None is worth paying for a naming problem.
Precedent cuts both ways, and it lands here
mathias/litellm-infrawas split out and absorbed back within three months — a new repo has to earn itself.mathias/gitea-mcpis correctly its own repo, but it fronts a remote API and shares no store; that is what a standalone MCP server actually looks like, and brain-mcp isn't shaped like it.mcp-chassisalready extracted the genuinely reusable half, so what remains ininternal/mcpis brain-specific by construction.The discoverability gap is real — I measured it
brain-mcp, never the hostname.brain-mcp.d-ma.beappears only inCLAUDE.md/AGENTS.md— generated agent-context files, not the human front door.So searching the forge for "brain-mcp" finds nothing, which is precisely the experience that generated infra#265. That is fixable with a description, a README line, and a docs pointer to
ingestion/internal/mcp. Cheap, and it addresses the actual complaint rather than a proxy for it.I did not file that as a new issue yet — checking
issue_list state=allfirst per convention, and it may just belong in this one's part 2 checklist. Say the word and I'll do it as a small PR alongside part 1.Reversal trigger, so this isn't permanent by default
Revisit if brain-mcp needs a release cadence independent of ingestion (today they are one pod, and no consumer is asking), or if the shared surface shrinks to ≤3 stable packages. If it ever does split, the unit is the whole
ingestionservice renamed — notinternal/mcpcarved out.The general rule
"It has its own ingress and its own consumers" is an argument about the deployment surface. "Where does the code live" is about the source surface. They're allowed to differ, and conflating them turns a naming problem into a migration.
Consequence for the rest of the queue: brain#4 (
brain_read/brain_edit) lands inhyperguild/ingestion/internal/mcp, not a new repo. Item 3 is unblocked on my side.Part 1 (the
ticketsarray bug) is untouched and next.Reproduction probe for part 1 (
capturewith aticketsarray, length 1, real write). Posted by the capture tool itself — if this comment exists, the array path worked from this harness.Second reproduction probe:
ticketsarray of length 2, mixed actions (create+comment), real write. Both landed in one call — so the array path works from this harness at both lengths tested.Both parts closed
Part 1 — PR #95 merged (
eb9e3e6). Theticketsarray was never broken; the I1 refusal hid its cause, so a caller with 20 tickets could not tell which repo tripped it and reasonably concluded the array was at fault. Refusals now name the escalating target. Regression tests at length 1 and 20 pin the path that was already correct.Part 2 — decided: brain-mcp stays inside
ingestion. ADR at brainwiki/hyperguild/decisions/brain-mcp-stays-in-ingestion-fix-discoverability-by-name; reasoning in the comment above.Also fixed, since it was the actual blocker
The refusal that started infra#265 was correct policy applied to a repo nobody had classified.
classification.yamlhad 10 of 47 repos tagged, so 37 — includingcad,dispatch,gitea-mcp,skills,brain-ui— would each have refused the next capture. Tagged the dev stack in one reviewed sweep (109c7c6,2568dcf), leaving eight deliberately absent with reasons in the file:schoolsoft,email-triage-agent, the threeharg-*repos,journal, and two tombstones.Done as an allowlist, not a relaxed default — the fail-safe is what protects the next client repo, and flipping it would make every future untagged repo us-nexus-eligible silently. Verified both directions against the live loader and through the running service.
Follow-through still open
#94 — brain-mcp is unfindable by name (repo description, README, topics). That is the discoverability half of the part-2 decision, and it is the thing that actually answers infra#265's complaint. Not done here.
Closing.