mathiasandClaude Sonnet 5 09aeaa91f5
CI / Lint / Test / Vet (pull_request) Successful in 31s
CI / Mirror to GitHub (pull_request) Skipped
fix(wiki): give the preamble its own field instead of overloading heading==""
Second review pass on PR #103 found a third bug in the same file: the
preamble fix from the prior commit represented "content before the first
## heading" as a section with heading=="" — which collides with a literal
degenerate `## ` (marker, no title text; strings.TrimPrefix also yields
"").  Two entries sharing one key in Merge's idx map means one loses
lookup visibility. Reproduced: a has only a preamble, b introduces a
genuinely new degenerate `## ` section — Merge's idx wrongly reports it
as "already exists" (it's really a's unrelated preamble) and never adds
it, so b's section vanishes from the output entirely.

Fixed by giving parseSections a dedicated preamble return value instead
of folding it into the sections slice. It can no longer collide with
anything, degenerate or otherwise, because it's no longer keyed by
heading at all. Merge and rebuildContent updated to thread it through
directly. No other caller of parseSections/rebuildContent in this repo.

Also fixed a doc-comment left misplaced by the prior commit (appendNew's
comment had drifted onto canonicalLine, inserted between them).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 23:40:29 +02:00
2026-08-18 00:08:07 +02:00
2026-08-18 00:08:07 +02:00

hyperguild

An MCP server that acts as a disciplined AI supervisor for Claude Code sessions. Instead of letting Claude Code do whatever it wants, hyperguild enforces structured workflows (TDD red/green/refactor), logs every session, and accumulates learnings into a searchable brain.

This repo is also where brain-mcp lives — the MCP server at brain-mcp.d-ma.be that brain_query, brain_write, brain_read, brain_edit and capture are served from. It is not a separate deployable; see Where brain-mcp lives.

Hypothesis

We believe routing skill tasks through local models, backed by brain context, produces measurably better outcomes than raw Claude Code alone — measurable by per-skill pass rate over rolling 30-day windows (available at GET /pass-rate?skill=<name>&window=30d on the brain pod).

This is the falsifiable claim the routing pod and pass-rate infrastructure exist to test. If per-skill pass rates don't improve over baseline (all-cloud) after 30 days of real usage, the fast-model routing path should be reconsidered.

Harness

hyperguild = Claude Code + MCP. This is a supervisor for Claude Code sessions specifically. For multi-agent orchestration (OpenCode + LiteLLM, executor/reviewer pipelines), see agentsquad — a separate harness for a different orchestration model. Skills (mathias/skills) are shared between both.

How it works

Your Claude Code session (in any project)
    │
    │  MCP over HTTP (Tailscale)
    ├──▶ routing     :3210 (NodePort 30310 on koala) — review, debug, retrospective, trainer
    └──▶ brain       :3300 (NodePort 30330 on koala) — brain_query, brain_write, brain_ingest, session_log
                       │
                       └─ also serves the legacy REST endpoints (/query, /write, /ingest, …)
    │
    ▼
brain/
├── sessions/       — JSONL log, one file per session_id
├── wiki/           — searchable knowledge (wing/hall layout)
│   ├── homelab/
│   ├── claude-sessions/
│   └── ...
└── knowledge/      — legacy flat notes (migration pending: hyperguild#22)

Where brain-mcp lives

brain-mcp is served from ingestion/internal/mcp in this repo, at brain-mcp.d-ma.be. It is a component inside the ingestion service, not a standalone deployable — one pod in the supervisor namespace serves the MCP endpoint, the REST API, and the claudewatcher together.

You are looking for It is here
The MCP tool surface (brain_query, brain_write, brain_read, brain_edit, capture, …) ingestion/internal/mcp
The HTTP/REST API (/query, /write, /ingest) ingestion/internal/api
Session ingestion from Claude Code transcripts ingestion/internal/claudewatcher
The brain content (notes, wings, halls) mathias/brain — a separate repo
Deployment manifests config/supervisor

Why it is not its own repo

Asked and decided in #91 (part 2). internal/mcp imports 17 of ingestion's other internal packages and has exactly one importer — it is the MCP facade over the service's own internals, so "move it out" resolves to renaming ingestion, publishing 17 packages as a shared library, or maintaining a shim. The discoverability problem that prompted the question is answered by naming it here instead.

Full reasoning, including the reversal trigger: brain wiki/hyperguild/decisions/brain-mcp-stays-in-ingestion-fix-discoverability-by-name.

Ingest revises, it does not overwrite

Re-ingesting a source merges into the page already on disk rather than replacing it. Previously the write was unconditional, so a second ingest of the same source discarded everything accumulated since — including hand-written sections.

The merge is deliberately asymmetric in the existing page's favour:

On the page In the fresh extraction Result
a section the same section the on-disk version wins
— a new section added
a bullet list (Sources, Key Claims, …) more bullets unioned, no duplicates
an append section (Open Questions, Updates, …) more lines only genuinely new lines appended
frontmatter frontmatter the on-disk frontmatter wins

So an extraction can add to a note but never silently rewrite what a human put there, which is what makes it safe to run on every ingest rather than behind a review gate.

Re-ingesting unchanged content is byte-identical — no diff, so brain-sync does not commit noise that hides real edits.

Known limitation: because the on-disk frontmatter wins, last_updated keeps its first-ingest date on a revised page.

Phase 1 tools (available now)

Tool What it does
session_log Appends a structured entry to the session JSONL log
retrospective Reads the session log, identifies novel learnings, writes to brain
review Structured code review via local model, brain-context injected
debug Hypothesis-driven debugging via local model
brain_query Full-text search over brain/wiki/
brain_write Writes a note to brain (with wing/hall routing)
brain_answer BM25 + LLM synthesis — Q&A over brain corpus
tier Returns the current connectivity tier (1=cloud, 2=LAN, 3=offline)

Note: tdd_red/green/refactor and spec were retired in Plan 7 (2026-05-12). They are now SKILL.md files in mathias/skills.

Connect a project

Create .mcp.json in your project root:

{
  "mcpServers": {
    "routing": {
      "type": "http",
      "url": "http://koala:30310/mcp"
    },
    "brain": {
      "type": "http",
      "url": "http://koala:30330/mcp"
    }
  }
}

Two MCP servers are exposed, both reachable over Tailscale:

  • routing at koala:30310 — skill workers (review, debug, retrospective, trainer). Routes each call to fast local model or thinking model based on per-skill pass rate.
  • brain at koala:30330 — knowledge access (brain_query, brain_write, brain_ingest, brain_ingest_raw, brain_answer, brain_classify) and session_log.

No local binary or stdio shim is required — Claude Code talks to both via HTTP.

Open Claude Code in your project — run /mcp to confirm both servers are listed.

A typical session

1. Call review      → brain context injected + local model review → findings
2. Call session_log → log each phase result
3. Call retrospective → extracts learnings → brain
4. Future sessions: call brain_query / brain_answer to retrieve relevant context

Tier detection

The routing pod probes connectivity at call time:

Tier Label Condition
1 full-online Can reach api.anthropic.com
2 lan-only Can reach LiteLLM but not Anthropic
3 airplane No external connectivity

Model routing

The routing pod selects models per skill call based on historical pass rate:

Pass rate Decision
≥ 0.90 (FLOOR) Fast model (HYPERGUILD_FAST_MODEL)
≤ 0.70 (CEIL) Thinking model (HYPERGUILD_THINKING_MODEL)
between CEIL and FLOOR Sample band — probabilistic routing
nil (no history yet) Defaults to thinking model

Bootstrap note: With no session history, all calls route to the thinking model. The fast-model path activates only after real pass-rate data accumulates at /pass-rate. Seed with real usage — don't try to pre-populate.

Key env vars

Variable Default Purpose
INGEST_BRAIN_DIR ../brain Brain directory for ingestion server
INGEST_PORT 3300 Ingestion server port
INGEST_BASE_URL http://localhost:3300 Routing pod → brain
LITELLM_BASE_URL — LiteLLM proxy for Tier 2 model routing
ROUTING_PORT 3210 Routing pod's listen port
ROUTING_MCP_TOKEN — Optional bearer token; when empty, no auth enforced
BRAIN_URL http://ingestion.supervisor:3300 Routing pod → brain (in-cluster)
HYPERGUILD_FAST_MODEL koala/qwen35-9b-fast Fast model for high-pass-rate skill calls
HYPERGUILD_THINKING_MODEL iguana/gemma4-26b Thinking model for low-pass-rate skill calls
HYPERGUILD_ROUTE_LOCAL_FLOOR 0.90 Fast model threshold
HYPERGUILD_ROUTE_LOCAL_CEIL 0.70 Thinking model threshold
HYPERGUILD_PASS_RATE_TTL_SECONDS 60 Per-skill pass-rate cache TTL

Operator note: LiteLLM at LITELLM_BASE_URL must register both HYPERGUILD_FAST_MODEL and HYPERGUILD_THINKING_MODEL. If a model is missing, the fail-open retry also fails and the only signal is final_status: "fail" on _routing entries in the brain.

Open issues

See issues — key open items:

  • #25 — skills platform overhaul (audit first, then lazy loading + brain feedback loop)
  • #24 — reduce context burn from skill listing
  • #22 — migrate legacy brain notes to wing/hall layout (one-shot script, low risk)
  • #31 — connect routing-mcp to claude.ai as custom connector
S
Description
MCP supervisor for disciplined Claude Code sessions — also home of brain-mcp (brain-mcp.d-ma.be), served from ingestion/internal/mcp
Readme
3.5 MiB
Languages
Go 98.7%
Shell 0.9%
Python 0.3%