To not block the Phase-1 milestone, brain-audit will ship an interim filesystem reader over a read-only checkout of git.d-ma.be/mathias/brain (wiki/<wing>/<hall>/<slug>.md + knowledge/<slug>.md), behind a brain.Reader interface. That's strictly read-only, gives the full corpus + frontmatter, and satisfies both brain-audit invariants (no brain-write verb; no internet egress).
This issue is the proper long-term backend that drops in behind the same brain.Reader interface once it exists.
Proposed scope — strictly read-only
Add to the brain-mcp HTTP surface (ingestion/), authed like /query:
/list (or brain_list) — enumerate all entry paths, optionally filtered by wing/hall. Paginated. Returns {path, content_hash, frontmatter} without bodies (cheap manifest).
/get over HTTP — already exists as brain_get on MCP; expose the same read on HTTP so non-MCP Go consumers can fetch {path, frontmatter, body, content_hash}.
/graph over HTTP — expose the existing brain_graph neighbors/subgraph ops so wikilink-graph checks don't have to reconstruct edges client-side.
Hard constraint: read-only. No write/update/tunnel verbs on this surface. brain-audit's invariant #1 (no brain-write path in the binary) means the consumer must not even be able to mutate through this API.
Open questions / feedback wanted
Is the interim FS reader acceptable as the Phase-1 backend, with this HTTP surface as a fast-follow — or do you want brain-audit to wait for this before going end-to-end? (My lean: ship FS reader now, this later; the brain.Reader seam makes the swap a one-file change.)
Does this belong in ingestion/ (the brain-mcp server) or is there a cleaner home given the #43 brain-interface analysis?
/list without bodies + lazy /get per node, or a single streaming full-dump endpoint? The audit reads everything, so a bulk dump might be simpler than N+1 gets — but breaks the per-node access pattern other consumers want.
## Why
`mathias/brain-gardener` Phase-1 `brain-audit` ([issue #2](https://git.d-ma.be/mathias/brain-gardener/issues/2)) needs to read the **entire brain corpus** (every entry, every wing) to compute graph-health checks — orphans, broken `[[wikilinks]]`, dup pairs, dangling supersede chains. The current brain-mcp surfaces can't enumerate that:
- HTTP `/query` = BM25 **search** (top-N matches), not "list all".
- `brain_get` = single path. MCP `brain_query` = search, same ceiling.
So there is no read path that returns the full set of entries. brain-audit's spine is blocked on it.
## Decision context (from brain-gardener#2, comment 1770)
To not block the Phase-1 milestone, brain-audit will ship an **interim filesystem reader** over a read-only checkout of `git.d-ma.be/mathias/brain` (`wiki/<wing>/<hall>/<slug>.md` + `knowledge/<slug>.md`), behind a `brain.Reader` interface. That's strictly read-only, gives the full corpus + frontmatter, and satisfies both brain-audit invariants (no brain-write verb; no internet egress).
**This issue is the proper long-term backend** that drops in behind the same `brain.Reader` interface once it exists.
## Proposed scope — strictly read-only
Add to the brain-mcp HTTP surface (`ingestion/`), authed like `/query`:
1. **`/list`** (or `brain_list`) — enumerate all entry paths, optionally filtered by wing/hall. Paginated. Returns `{path, content_hash, frontmatter}` without bodies (cheap manifest).
2. **`/get`** over HTTP — already exists as `brain_get` on MCP; expose the same read on HTTP so non-MCP Go consumers can fetch `{path, frontmatter, body, content_hash}`.
3. **`/graph`** over HTTP — expose the existing `brain_graph` neighbors/subgraph ops so wikilink-graph checks don't have to reconstruct edges client-side.
**Hard constraint:** read-only. No write/update/tunnel verbs on this surface. brain-audit's invariant #1 (no brain-write path in the binary) means the consumer must not even be *able* to mutate through this API.
## Open questions / feedback wanted
- Is the **interim FS reader acceptable** as the Phase-1 backend, with this HTTP surface as a fast-follow — or do you want brain-audit to wait for this before going end-to-end? (My lean: ship FS reader now, this later; the `brain.Reader` seam makes the swap a one-file change.)
- Does this belong in `ingestion/` (the brain-mcp server) or is there a cleaner home given the #43 brain-interface analysis?
- `/list` without bodies + lazy `/get` per node, or a single streaming full-dump endpoint? The audit reads everything, so a bulk dump might be simpler than N+1 gets — but breaks the per-node access pattern other consumers want.
Related: #43 (brain interface mismatch), #47 (read-after-write semantics — same read surface).
Approved scope. Ship FS reader now; this is the fast-follow.
Three answers:
1. Interim FS reader — yes, acceptable; do NOT wait on this issue.
The brain.Reader seam makes the swap a one-file change, so blocking the Phase-1 end-to-end milestone on a different repo's new endpoint would be self-inflicted. Ship the FS reader now (verified viable against mathias/brain HEAD — 674 md, correct wiki/<wing>/<hall>/ shape). This HTTP surface drops in behind the same interface later.
2. Home — ingestion/ is right, but sequence after #43.
It's the brain-mcp server, so that's the correct module. One dependency check: if #43 (brain-interface mismatch) is about to relocate or restructure that surface, build #71after#43's structural call — don't bake new endpoints into a module that's about to move. Not a block, just a one-line check before you start.
3. Bulk-dump vs N+1 — do both; it's not actually a fork.
bulk /get accepting a set of paths (or a streaming full-dump) → the audit's read-everything path.
single /get stays for per-node consumers.
The audit uses /list + bulk-fetch; other consumers use single /get. Bonus from the manifest's content_hash: the audit can skip-unchanged across runs later (incremental audits).
Hard constraint (non-negotiable)
The entire surface must be physically incapable of mutation — not merely "exposes no write," but no write/update/tunnel verb reachable through this auth scope at all. brain-audit's invariant #1 (no brain-write path in the binary) must hold even against a compromised or buggy consumer. If a write verb is reachable through the same credential, this surface fails its purpose.
No rush — FS reader is the unblock; this lands when #43 settles.
## Approved scope. Ship FS reader now; this is the fast-follow.
Three answers:
### 1. Interim FS reader — **yes, acceptable; do NOT wait on this issue.**
The `brain.Reader` seam makes the swap a one-file change, so blocking the Phase-1 end-to-end milestone on a different repo's new endpoint would be self-inflicted. Ship the FS reader now (verified viable against `mathias/brain` HEAD — 674 md, correct `wiki/<wing>/<hall>/` shape). This HTTP surface drops in behind the same interface later.
### 2. Home — **`ingestion/` is right, but sequence after #43.**
It's the brain-mcp server, so that's the correct module. One dependency check: if #43 (brain-interface mismatch) is about to relocate or restructure that surface, build #71 *after* #43's structural call — don't bake new endpoints into a module that's about to move. Not a block, just a one-line check before you start.
### 3. Bulk-dump vs N+1 — **do both; it's not actually a fork.**
- **`/list`** → bodiless manifest `{path, content_hash, frontmatter}`, paginated, wing/hall filter. Cheap.
- **bulk `/get`** accepting a set of paths (or a streaming full-dump) → the audit's read-everything path.
- **single `/get`** stays for per-node consumers.
The audit uses `/list` + bulk-fetch; other consumers use single `/get`. Bonus from the manifest's `content_hash`: the audit can skip-unchanged across runs later (incremental audits).
### Hard constraint (non-negotiable)
The entire surface must be **physically incapable of mutation** — not merely "exposes no write," but **no write/update/tunnel verb reachable through this auth scope at all**. brain-audit's invariant #1 (no brain-write path in the binary) must hold even against a compromised or buggy consumer. If a write verb is reachable through the same credential, this surface fails its purpose.
No rush — FS reader is the unblock; this lands when #43 settles.
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.
Why
mathias/brain-gardenerPhase-1brain-audit(issue #2) needs to read the entire brain corpus (every entry, every wing) to compute graph-health checks — orphans, broken[[wikilinks]], dup pairs, dangling supersede chains. The current brain-mcp surfaces can't enumerate that:/query= BM25 search (top-N matches), not "list all".brain_get= single path. MCPbrain_query= search, same ceiling.So there is no read path that returns the full set of entries. brain-audit's spine is blocked on it.
Decision context (from brain-gardener#2, comment 1770)
To not block the Phase-1 milestone, brain-audit will ship an interim filesystem reader over a read-only checkout of
git.d-ma.be/mathias/brain(wiki/<wing>/<hall>/<slug>.md+knowledge/<slug>.md), behind abrain.Readerinterface. That's strictly read-only, gives the full corpus + frontmatter, and satisfies both brain-audit invariants (no brain-write verb; no internet egress).This issue is the proper long-term backend that drops in behind the same
brain.Readerinterface once it exists.Proposed scope — strictly read-only
Add to the brain-mcp HTTP surface (
ingestion/), authed like/query:/list(orbrain_list) — enumerate all entry paths, optionally filtered by wing/hall. Paginated. Returns{path, content_hash, frontmatter}without bodies (cheap manifest)./getover HTTP — already exists asbrain_geton MCP; expose the same read on HTTP so non-MCP Go consumers can fetch{path, frontmatter, body, content_hash}./graphover HTTP — expose the existingbrain_graphneighbors/subgraph ops so wikilink-graph checks don't have to reconstruct edges client-side.Hard constraint: read-only. No write/update/tunnel verbs on this surface. brain-audit's invariant #1 (no brain-write path in the binary) means the consumer must not even be able to mutate through this API.
Open questions / feedback wanted
brain.Readerseam makes the swap a one-file change.)ingestion/(the brain-mcp server) or is there a cleaner home given the #43 brain-interface analysis?/listwithout bodies + lazy/getper node, or a single streaming full-dump endpoint? The audit reads everything, so a bulk dump might be simpler than N+1 gets — but breaks the per-node access pattern other consumers want.Related: #43 (brain interface mismatch), #47 (read-after-write semantics — same read surface).
Approved scope. Ship FS reader now; this is the fast-follow.
Three answers:
1. Interim FS reader — yes, acceptable; do NOT wait on this issue.
The
brain.Readerseam makes the swap a one-file change, so blocking the Phase-1 end-to-end milestone on a different repo's new endpoint would be self-inflicted. Ship the FS reader now (verified viable againstmathias/brainHEAD — 674 md, correctwiki/<wing>/<hall>/shape). This HTTP surface drops in behind the same interface later.2. Home —
ingestion/is right, but sequence after #43.It's the brain-mcp server, so that's the correct module. One dependency check: if #43 (brain-interface mismatch) is about to relocate or restructure that surface, build #71 after #43's structural call — don't bake new endpoints into a module that's about to move. Not a block, just a one-line check before you start.
3. Bulk-dump vs N+1 — do both; it's not actually a fork.
/list→ bodiless manifest{path, content_hash, frontmatter}, paginated, wing/hall filter. Cheap./getaccepting a set of paths (or a streaming full-dump) → the audit's read-everything path./getstays for per-node consumers.The audit uses
/list+ bulk-fetch; other consumers use single/get. Bonus from the manifest'scontent_hash: the audit can skip-unchanged across runs later (incremental audits).Hard constraint (non-negotiable)
The entire surface must be physically incapable of mutation — not merely "exposes no write," but no write/update/tunnel verb reachable through this auth scope at all. brain-audit's invariant #1 (no brain-write path in the binary) must hold even against a compromised or buggy consumer. If a write verb is reachable through the same credential, this surface fails its purpose.
No rush — FS reader is the unblock; this lands when #43 settles.