Closes#94. Follow-through on the #91 part 2 decision: brain-mcp stays in ingestion, so discoverability is answered by naming.
Already applied outside this diff (forge API, not files)
Repo description — was "MCP supervisor for disciplined Claude Code sessions", now:
MCP supervisor for disciplined Claude Code sessions — also home of brain-mcp (brain-mcp.d-ma.be), served from ingestion/internal/mcp
Topics — were empty ([]), now mcp, brain, brain-mcp, claude-code, go, agent-infrastructure.
Verified against the acceptance criterion rather than assumed — both the plain and topic-scoped forge searches now return this repo and nothing else:
GET /repos/search?q=brain-mcp → mathias/hyperguild
GET /repos/search?q=brain-mcp&topic=true → mathias/hyperguild
In this diff
A "Where brain-mcp lives" section plus one line in the opening paragraph, so the string brain-mcp and the hostname appear on the human front door rather than only in the generated CLAUDE.md/AGENTS.md.
The section answers "where does this code live" with a lookup table — MCP tool surface → ingestion/internal/mcp, REST API → ingestion/internal/api, session ingestion → ingestion/internal/claudewatcher, deployment → config/supervisor, and explicitly that the brain content is mathias/brain, a different repo. That last row is the distinction most likely to send someone to the wrong place, and nothing stated it before.
Then a short "why it is not its own repo" with the 17-imports fact and a pointer to the ADR for the full reasoning and the reversal trigger.
The Harness section links agentsquad as http://gitea.d-ma.be/mathias/agentsquad — a decommissioned alias (infra#126 removed the ingress hosts and the redirect), so it is a dead link on the front door. One line, but unrelated to naming brain-mcp, and I would rather not fold an unrelated fix into a docs PR about discoverability. Happy to push it here if you would prefer one pass; otherwise it wants its own issue.
Risk: LOW — documentation and forge metadata.
Closes #94. Follow-through on the #91 part 2 decision: brain-mcp stays in `ingestion`, so discoverability is answered by naming.
## Already applied outside this diff (forge API, not files)
**Repo description** — was *"MCP supervisor for disciplined Claude Code sessions"*, now:
> MCP supervisor for disciplined Claude Code sessions — also home of brain-mcp (brain-mcp.d-ma.be), served from ingestion/internal/mcp
**Topics** — were empty (`[]`), now `mcp`, `brain`, `brain-mcp`, `claude-code`, `go`, `agent-infrastructure`.
Verified against the acceptance criterion rather than assumed — both the plain and topic-scoped forge searches now return this repo and nothing else:
```
GET /repos/search?q=brain-mcp → mathias/hyperguild
GET /repos/search?q=brain-mcp&topic=true → mathias/hyperguild
```
## In this diff
A **"Where brain-mcp lives"** section plus one line in the opening paragraph, so the string `brain-mcp` and the hostname appear on the human front door rather than only in the generated `CLAUDE.md`/`AGENTS.md`.
The section answers "where does this code live" with a lookup table — MCP tool surface → `ingestion/internal/mcp`, REST API → `ingestion/internal/api`, session ingestion → `ingestion/internal/claudewatcher`, deployment → `config/supervisor`, and explicitly that the brain **content** is [`mathias/brain`](https://git.d-ma.be/mathias/brain), a different repo. That last row is the distinction most likely to send someone to the wrong place, and nothing stated it before.
Then a short "why it is not its own repo" with the 17-imports fact and a pointer to the ADR for the full reasoning and the reversal trigger.
Docs only. No code moved, nothing structural. `task check` exit 0.
## Noticed, not fixed here
The **Harness** section links agentsquad as `http://gitea.d-ma.be/mathias/agentsquad` — a decommissioned alias (infra#126 removed the ingress hosts and the redirect), so it is a dead link on the front door. One line, but unrelated to naming brain-mcp, and I would rather not fold an unrelated fix into a docs PR about discoverability. Happy to push it here if you would prefer one pass; otherwise it wants its own issue.
**Risk:** LOW — documentation and forge metadata.
A forge search for "brain-mcp" returned nothing for this repo: the
description mentions neither the brain nor brain-mcp, and the README said
"accumulates learnings into a searchable brain" without ever using the
string `brain-mcp` or its hostname. Both appeared only in CLAUDE.md and
AGENTS.md — generated agent-context files, not the human front door. That
is precisely the experience that generated infra#265.
Since #91 part 2 decided the code stays in ingestion, discoverability has
to be answered by naming.
Adds a "Where brain-mcp lives" section: the ingress, the package, a table
mapping what-you-are-looking-for to where-it-is (including that the brain
*content* is a different repo), and why it is not standalone, with a
pointer to the ADR for the full reasoning and the reversal trigger.
Docs only. Repo description and topics are set through the forge API, not
in this diff.
Refs #94, #91.
The three forge links in README.md used http://gitea.d-ma.be, an alias
whose ingress was removed by infra#126. Verified rather than assumed: DNS
still resolves the name to the same IP, but a public repo returns 404
there and 200 on git.d-ma.be, with no redirect — so the links are broken,
not merely old.
Scope is README.md only. The dated files under docs/superpowers/plans and
specs are records of what was done in April/May 2026, when that hostname
was correct; rewriting them would falsify the record rather than fix a
link.
Note the agentsquad link still 404s unauthenticated — that repo is
private, which is expected and not a URL problem.
Refs #94, infra#126.
Pushed ecbef33 — the dead-link fix from the "noticed, not fixed here" note above, per your call.
Verified before changing anything
My first check was wrong and worth flagging, because it would have produced a confident false negative: I curled https://git.d-ma.be/mathias/agentsquad and got 404, which looks like "the new host is broken too." That repo is simply private, so an unauthenticated request 404s by design.
Re-checked against a public repo, which is the instrument that actually discriminates:
So the name still resolves but the vhost is gone and nothing redirects — the links were broken, not merely old. Consistent with infra#126 having removed the ingress hosts and the NPM redirect.
Post-fix, each target checked individually: mathias/skills → 200, mathias/hyperguild/issues → 200, mathias/agentsquad → 404 because it is private (confirmed private: true via an authenticated API call). That last one is expected and not a URL problem.
Scope
README.md only — three links, http://gitea.d-ma.be → https://git.d-ma.be.
Deliberately not touched: the ~15 further occurrences under docs/superpowers/plans/ and docs/superpowers/specs/. Those are dated records from April/May 2026, when that hostname was the correct one — including a CD-pipeline plan whose registry auth blocks are literally about pushing to gitea.d-ma.be. Editing them would falsify the record rather than fix a link.
Worth its own issue, not this PR
gitea.d-ma.be still has a live DNS A record pointing at the ingress IP while no vhost answers for it. A dangling record that resolves is worse than one that does not: every stale reference fails as a 404 (looks like a missing repo) instead of a DNS failure (looks like a dead hostname), which is exactly why this link read as plausible for months. That is an infra concern — happy to file it there if you want it tracked.
task check exit 0.
Pushed `ecbef33` — the dead-link fix from the "noticed, not fixed here" note above, per your call.
## Verified before changing anything
My first check was wrong and worth flagging, because it would have produced a confident false negative: I curled `https://git.d-ma.be/mathias/agentsquad` and got **404**, which looks like "the new host is broken too." That repo is simply private, so an unauthenticated request 404s by design.
Re-checked against a **public** repo, which is the instrument that actually discriminates:
```
getent hosts gitea.d-ma.be → 5.150.212.35 (still resolves)
getent hosts git.d-ma.be → 5.150.212.35 (same IP)
http://gitea.d-ma.be/mathias/hyperguild → 404, no redirect
https://git.d-ma.be/mathias/hyperguild → 200
```
So the name still resolves but the vhost is gone and nothing redirects — the links were broken, not merely old. Consistent with infra#126 having removed the ingress hosts and the NPM redirect.
Post-fix, each target checked individually: `mathias/skills` → 200, `mathias/hyperguild/issues` → 200, `mathias/agentsquad` → 404 **because it is private** (confirmed `private: true` via an authenticated API call). That last one is expected and not a URL problem.
## Scope
`README.md` only — three links, `http://gitea.d-ma.be` → `https://git.d-ma.be`.
Deliberately **not** touched: the ~15 further occurrences under `docs/superpowers/plans/` and `docs/superpowers/specs/`. Those are dated records from April/May 2026, when that hostname was the correct one — including a CD-pipeline plan whose registry auth blocks are literally about pushing to `gitea.d-ma.be`. Editing them would falsify the record rather than fix a link.
## Worth its own issue, not this PR
`gitea.d-ma.be` still has a live DNS A record pointing at the ingress IP while no vhost answers for it. A dangling record that resolves is worse than one that does not: every stale reference fails as a 404 (looks like a missing repo) instead of a DNS failure (looks like a dead hostname), which is exactly why this link read as plausible for months. That is an infra concern — happy to file it there if you want it tracked.
`task check` exit 0.
Correction to my previous comment — the "dangling DNS A record, worth filing with infra" suggestion was wrong, and I'd rather not leave it here for someone to act on.
There is no per-name record for gitea.d-ma.be. DNS is a wildcard *.d-ma.be → the public IP, so every name under the zone resolves, including ones that never existed. getent hosts gitea.d-ma.be returning the ingress IP is the wildcard doing its job, not a leftover. Nothing to remove, and no removal would have changed anything.
What actually decides the outcome is the reverse proxy in front (openresty / Nginx Proxy Manager), and the current behaviour is already the decommissioned state:
http://gitea.d-ma.be/ → 200, NPM "Default Site" page
http://gitea.d-ma.be/mathias/hyperguild → 404 (static default page has no such path)
http://never-existed.d-ma.be/ → 200, same Default Site
https://never-existed.d-ma.be/ → TLS failure (no certificate for the name)
So the 404 that made the README link look plausible was just the default page lacking that path — not a half-configured vhost. Consistent with infra#126 having removed both the ingress host and the NPM redirect.
The fix in this PR — correcting the references — was the right and sufficient one. No infra ticket needed.
The only optional improvement left is cosmetic and global, not specific to this name: NPM's Default Site could return an explicit "this host is not a service" page (or 410) instead of a generic 200, so a future typo'd or retired hostname fails legibly instead of looking like a live site with a missing page. That is a one-setting change in NPM, and deliberately not a redirect from gitea.d-ma.be to git.d-ma.be — a redirect would keep the retired alias working forever, which is exactly what infra#126 set out to stop.
**Correction to my previous comment** — the "dangling DNS A record, worth filing with infra" suggestion was wrong, and I'd rather not leave it here for someone to act on.
There is no per-name record for `gitea.d-ma.be`. DNS is a wildcard `*.d-ma.be` → the public IP, so **every** name under the zone resolves, including ones that never existed. `getent hosts gitea.d-ma.be` returning the ingress IP is the wildcard doing its job, not a leftover. Nothing to remove, and no removal would have changed anything.
What actually decides the outcome is the reverse proxy in front (openresty / Nginx Proxy Manager), and the current behaviour is already the decommissioned state:
```
http://gitea.d-ma.be/ → 200, NPM "Default Site" page
http://gitea.d-ma.be/mathias/hyperguild → 404 (static default page has no such path)
http://never-existed.d-ma.be/ → 200, same Default Site
https://never-existed.d-ma.be/ → TLS failure (no certificate for the name)
```
So the 404 that made the README link look plausible was just the default page lacking that path — not a half-configured vhost. Consistent with infra#126 having removed both the ingress host and the NPM redirect.
The fix in this PR — correcting the references — was the right and sufficient one. No infra ticket needed.
The only optional improvement left is cosmetic and global, not specific to this name: NPM's Default Site could return an explicit "this host is not a service" page (or 410) instead of a generic 200, so a future typo'd or retired hostname fails legibly instead of looking like a live site with a missing page. That is a one-setting change in NPM, and deliberately **not** a redirect from `gitea.d-ma.be` to `git.d-ma.be` — a redirect would keep the retired alias working forever, which is exactly what infra#126 set out to stop.
Closed off the proxy side too — no infra ticket needed
Found the NPM access path in the brain (wiki/homelab/facts/npm-api-le-cert-empty-meta-quirk — API at http://piguard:81/api, creds in 1P NPM_ADMIN, secrets on stdin never argv) and made the one-setting change discussed above.
settings/default-site: congratulations → 404.
That setting was the whole explanation for the confusing signature:
before: http://retired-host/ → 200 (the default page exists at /)
http://retired-host/some/path → 404 (default page has no such path)
after: both → 404
A stale link with a path 404ing reads as "the repo moved," not "this hostname is dead" — which is exactly why the README link stayed plausible for months. Now an unmatched host reads as absent, for every future retired or typo'd name, not just this one.
Still deliberately not a gitea → git redirect: that repairs stale references forever and guarantees no consumer ever migrates. Fixing the references, as this PR does, is the terminating move.
Verified, including for regressions
The PUT applies on nginx reload, not on save — / still served 200 for a few seconds after a successful response, so the first re-check was a false negative.
Swept all 16 cluster-served hosts afterwards. No regressions:
404 at /: brain-mcp, cad-mcp, git-mcp — app-level, expected. MCP servers serve /mcp, not /. Confirmed by the body (Go's plain 404 page not found vs nginx's <title>404 Not Found</title>) and by all three answering 401 on /mcp, i.e. alive and gated. brain-mcp additionally answered a real tools/list with 17 tools.
000: pages.git.d-ma.be — TLS handshake failure, pre-existing. A default-site value decides an HTTP response; the handshake fails before that, so this change cannot cause it. Not chased.
Recorded at brain wiki/homelab/decisions/retiring-a-hostname-under-wildcard-dns-is-a-proxy-decision-not-a-dns-one, including the three verification traps hit along the way.
No file changes in this PR from the above — it is proxy configuration, which lives in NPM's own database rather than in git.
## Closed off the proxy side too — no infra ticket needed
Found the NPM access path in the brain (`wiki/homelab/facts/npm-api-le-cert-empty-meta-quirk` — API at `http://piguard:81/api`, creds in 1P `NPM_ADMIN`, secrets on stdin never argv) and made the one-setting change discussed above.
**`settings/default-site`: `congratulations` → `404`.**
That setting was the whole explanation for the confusing signature:
```
before: http://retired-host/ → 200 (the default page exists at /)
http://retired-host/some/path → 404 (default page has no such path)
after: both → 404
```
A stale link *with a path* 404ing reads as "the repo moved," not "this hostname is dead" — which is exactly why the README link stayed plausible for months. Now an unmatched host reads as absent, for every future retired or typo'd name, not just this one.
Still deliberately **not** a `gitea → git` redirect: that repairs stale references forever and guarantees no consumer ever migrates. Fixing the references, as this PR does, is the terminating move.
### Verified, including for regressions
The PUT applies on nginx reload, not on save — `/` still served 200 for a few seconds after a successful response, so the first re-check was a false negative.
Swept all 16 cluster-served hosts afterwards. No regressions:
- `200`: brain, chat, d-ma.be, git, ntfy, www
- `302` (auth redirect, healthy): atlas, auth, books, grafana, jaeger, tapir
- `404` at `/`: brain-mcp, cad-mcp, git-mcp — **app-level, expected.** MCP servers serve `/mcp`, not `/`. Confirmed by the body (Go's plain `404 page not found` vs nginx's `<title>404 Not Found</title>`) and by all three answering `401` on `/mcp`, i.e. alive and gated. brain-mcp additionally answered a real `tools/list` with 17 tools.
- `000`: `pages.git.d-ma.be` — TLS handshake failure, pre-existing. A default-site value decides an HTTP response; the handshake fails before that, so this change cannot cause it. Not chased.
Recorded at brain `wiki/homelab/decisions/retiring-a-hostname-under-wildcard-dns-is-a-proxy-decision-not-a-dns-one`, including the three verification traps hit along the way.
No file changes in this PR from the above — it is proxy configuration, which lives in NPM's own database rather than in git.
mathias
merged commit b6ceccca26 into main2026-08-22 06:10:06 +00:00
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.
Closes #94. Follow-through on the #91 part 2 decision: brain-mcp stays in
ingestion, so discoverability is answered by naming.Already applied outside this diff (forge API, not files)
Repo description — was "MCP supervisor for disciplined Claude Code sessions", now:
Topics — were empty (
[]), nowmcp,brain,brain-mcp,claude-code,go,agent-infrastructure.Verified against the acceptance criterion rather than assumed — both the plain and topic-scoped forge searches now return this repo and nothing else:
In this diff
A "Where brain-mcp lives" section plus one line in the opening paragraph, so the string
brain-mcpand the hostname appear on the human front door rather than only in the generatedCLAUDE.md/AGENTS.md.The section answers "where does this code live" with a lookup table — MCP tool surface →
ingestion/internal/mcp, REST API →ingestion/internal/api, session ingestion →ingestion/internal/claudewatcher, deployment →config/supervisor, and explicitly that the brain content ismathias/brain, a different repo. That last row is the distinction most likely to send someone to the wrong place, and nothing stated it before.Then a short "why it is not its own repo" with the 17-imports fact and a pointer to the ADR for the full reasoning and the reversal trigger.
Docs only. No code moved, nothing structural.
task checkexit 0.Noticed, not fixed here
The Harness section links agentsquad as
http://gitea.d-ma.be/mathias/agentsquad— a decommissioned alias (infra#126 removed the ingress hosts and the redirect), so it is a dead link on the front door. One line, but unrelated to naming brain-mcp, and I would rather not fold an unrelated fix into a docs PR about discoverability. Happy to push it here if you would prefer one pass; otherwise it wants its own issue.Risk: LOW — documentation and forge metadata.
Pushed
ecbef33— the dead-link fix from the "noticed, not fixed here" note above, per your call.Verified before changing anything
My first check was wrong and worth flagging, because it would have produced a confident false negative: I curled
https://git.d-ma.be/mathias/agentsquadand got 404, which looks like "the new host is broken too." That repo is simply private, so an unauthenticated request 404s by design.Re-checked against a public repo, which is the instrument that actually discriminates:
So the name still resolves but the vhost is gone and nothing redirects — the links were broken, not merely old. Consistent with infra#126 having removed the ingress hosts and the NPM redirect.
Post-fix, each target checked individually:
mathias/skills→ 200,mathias/hyperguild/issues→ 200,mathias/agentsquad→ 404 because it is private (confirmedprivate: truevia an authenticated API call). That last one is expected and not a URL problem.Scope
README.mdonly — three links,http://gitea.d-ma.be→https://git.d-ma.be.Deliberately not touched: the ~15 further occurrences under
docs/superpowers/plans/anddocs/superpowers/specs/. Those are dated records from April/May 2026, when that hostname was the correct one — including a CD-pipeline plan whose registry auth blocks are literally about pushing togitea.d-ma.be. Editing them would falsify the record rather than fix a link.Worth its own issue, not this PR
gitea.d-ma.bestill has a live DNS A record pointing at the ingress IP while no vhost answers for it. A dangling record that resolves is worse than one that does not: every stale reference fails as a 404 (looks like a missing repo) instead of a DNS failure (looks like a dead hostname), which is exactly why this link read as plausible for months. That is an infra concern — happy to file it there if you want it tracked.task checkexit 0.Correction to my previous comment — the "dangling DNS A record, worth filing with infra" suggestion was wrong, and I'd rather not leave it here for someone to act on.
There is no per-name record for
gitea.d-ma.be. DNS is a wildcard*.d-ma.be→ the public IP, so every name under the zone resolves, including ones that never existed.getent hosts gitea.d-ma.bereturning the ingress IP is the wildcard doing its job, not a leftover. Nothing to remove, and no removal would have changed anything.What actually decides the outcome is the reverse proxy in front (openresty / Nginx Proxy Manager), and the current behaviour is already the decommissioned state:
So the 404 that made the README link look plausible was just the default page lacking that path — not a half-configured vhost. Consistent with infra#126 having removed both the ingress host and the NPM redirect.
The fix in this PR — correcting the references — was the right and sufficient one. No infra ticket needed.
The only optional improvement left is cosmetic and global, not specific to this name: NPM's Default Site could return an explicit "this host is not a service" page (or 410) instead of a generic 200, so a future typo'd or retired hostname fails legibly instead of looking like a live site with a missing page. That is a one-setting change in NPM, and deliberately not a redirect from
gitea.d-ma.betogit.d-ma.be— a redirect would keep the retired alias working forever, which is exactly what infra#126 set out to stop.Closed off the proxy side too — no infra ticket needed
Found the NPM access path in the brain (
wiki/homelab/facts/npm-api-le-cert-empty-meta-quirk— API athttp://piguard:81/api, creds in 1PNPM_ADMIN, secrets on stdin never argv) and made the one-setting change discussed above.settings/default-site:congratulations→404.That setting was the whole explanation for the confusing signature:
A stale link with a path 404ing reads as "the repo moved," not "this hostname is dead" — which is exactly why the README link stayed plausible for months. Now an unmatched host reads as absent, for every future retired or typo'd name, not just this one.
Still deliberately not a
gitea → gitredirect: that repairs stale references forever and guarantees no consumer ever migrates. Fixing the references, as this PR does, is the terminating move.Verified, including for regressions
The PUT applies on nginx reload, not on save —
/still served 200 for a few seconds after a successful response, so the first re-check was a false negative.Swept all 16 cluster-served hosts afterwards. No regressions:
200: brain, chat, d-ma.be, git, ntfy, www302(auth redirect, healthy): atlas, auth, books, grafana, jaeger, tapir404at/: brain-mcp, cad-mcp, git-mcp — app-level, expected. MCP servers serve/mcp, not/. Confirmed by the body (Go's plain404 page not foundvs nginx's<title>404 Not Found</title>) and by all three answering401on/mcp, i.e. alive and gated. brain-mcp additionally answered a realtools/listwith 17 tools.000:pages.git.d-ma.be— TLS handshake failure, pre-existing. A default-site value decides an HTTP response; the handshake fails before that, so this change cannot cause it. Not chased.Recorded at brain
wiki/homelab/decisions/retiring-a-hostname-under-wildcard-dns-is-a-proxy-decision-not-a-dns-one, including the three verification traps hit along the way.No file changes in this PR from the above — it is proxy configuration, which lives in NPM's own database rather than in git.