feat: structured brain — Hall taxonomy, Obsidian-compatible layout, and filtered query #1
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
The brain currently stores notes as a flat list of
.mdfiles underbrain/knowledge/andbrain/wiki/with a shallow three-way taxonomy (concepts/,entities/,sources/). Retrieval is term-frequency full-text search across all files.Two problems emerge as the brain grows:
This issue introduces a Hall dimension borrowed from the MemPalace architecture, restructures the wiki directory layout to be natively Obsidian-compatible, and adds a
hallfilter tobrain_query.Design
Concept: Wings and Halls
Every note lives at a two-dimensional address:
jepa-fx,hyperguild,bathroom-plumbing). Maps directly to a subdirectory.factsdecisionsfailureshypothesessourceswiki/sources/)Directory layout (after migration)
This layout is a valid Obsidian vault. Open
brain/as a vault and you get Wing-level folders in the file explorer, Hall subfolders, and Obsidian's graph view will show natural clusters by Wing.Obsidian integration properties
wing,hall,created_at, and optionaltags[[other-note]]) written byretrospectiveorbrain_writewill resolve natively in Obsidian_index.mdfiles at Wing level act as MOC (Map of Content) — auto-generated, listing all notes in that Wing with their HallImplementation
1. New path resolver:
ingestion/internal/brain/path.goWing and slug are sanitised (lowercase, alphanumeric + hyphens, no path separators). Hall is validated against
ValidHalls.2. Extend
WriteNoteiningestion/internal/api/handler.goAdd optional
wingandhallfields towriteRequest:When
wing+hallare provided, route tobrain/wiki/<wing>/<hall>/<filename>viabrain.NotePath. When absent, fall back to currentbrain/knowledge/behaviour. This is fully backwards-compatible — no existing callers break.Inject YAML frontmatter automatically:
3. Extend
search.Queryiningestion/internal/search/search.goAdd
hallandwingfilter parameters:Path-based filtering: when
wingis set, only walkbrain/wiki/<wing>/. Whenhallis additionally set, only walkbrain/wiki/<wing>/<hall>/. This is O(1) directory scoping — no change to the scoring logic.Update
Resultto includewingandhallfields extracted from frontmatter or path segments.4. Update MCP tool schemas
In
ingestion/internal/mcp/:brain_write— add optionalwing(string) andhall(enum: facts/decisions/failures/hypotheses/sources) parameters.brain_query— add optionalwing(string) andhall(enum) parameters.5. Index generation:
brain_indexNew MCP tool (and REST endpoint
POST /index) that walksbrain/wiki/and regenerates_index.mdat each Wing directory:Called automatically after every
brain_writewithwing+hall, and available as a manual trigger.6. Migration script:
scripts/migrate-brain-halls.shOne-time script to migrate existing
brain/wiki/concepts/andbrain/wiki/entities/files into the new layout. Reads existing frontmattertype:anddomain:fields to infer Wing and Hall. Falls back towing=general,hall=factsfor unmapped files. Non-destructive: leaves originals in place until--commitflag is passed.Acceptance criteria
POST /writewith{"wing":"jepa-fx","hall":"decisions","content":"...","filename":"my-decision"}writes tobrain/wiki/jepa-fx/decisions/my-decision.mdwith correct frontmatterPOST /writewithoutwing/hallcontinues to write tobrain/knowledge/unchangedPOST /querywith{"query":"lejpa","wing":"jepa-fx","hall":"facts"}only searchesbrain/wiki/jepa-fx/facts/brain_writeMCP tool accepts and passes throughwingandhallbrain_queryMCP tool accepts and passes throughwingandhallbrain/as an Obsidian vault shows Wing folders in the file explorer with Hall subfolders_index.mdat each Wing directory lists all notes in that Wing with Hall columnBranch
feat/brain-hallsfrommainOut of scope
brain/sessions/orbrain/raw/layoutCreated via git-mcp on behalf of @mathiasbq
Shipped in
75685e7. All acceptance criteria met.What landed
New package
ingestion/internal/brain/ValidHalls,IsValidHall,Sanitise(s),NotePath(brainDir, wing, hall, slug)— path.goBuildWingIndex(brainDir, wing),BuildAllWingIndexes(brainDir)— index.goAPI surface
writeRequestgainswing,hall.WriteNoterefactored toWriteNoteOptions. With wing+hall set → routes tobrain/wiki/<wing>/<hall>/<slug>.mdwithwing/hall/created_atYAML frontmatter injected. Without → legacybrain/knowledge/path preserved (no breaking change).queryRequestgainswing,hall.search.Querynow takesQueryOptions{Query, Limit, Wing, Hall}. Walksbrain/wiki/<wing>/<hall>/when scoped, bothknowledge/andwiki/otherwise.Resultcarries wing/hall from frontmatter or path.POST /indexREST endpoint.MCP
brain_writeschema: optionalwing+hall(enum-validated).brain_queryschema: optionalwing+hall(enum-validated).brain_index(optionalwingarg; absent = rebuild all).brain_writewith wing+hall triggersBuildWingIndexon the affected wing.Migration
scripts/migrate-brain-halls.sh— dry-run by default,--commitapplies. Mapstype:→ hall (decision/hypothesis/failure/source → eponymous; concept/entity/other → facts),domain:→ wing (sanitised; defaultgeneral). Idempotent. Tested against synthetic brain: 3 notes migrate cleanly, re-run no-ops, empty brain handled.Acceptance criteria
POST /write {wing,hall,content,filename}→brain/wiki/<wing>/<hall>/<file>.mdwith correct frontmatterPOST /writewithout wing/hall →brain/knowledge/(legacy preserved)POST /query {query,wing,hall}scopes searchbrain_writeMCP tool accepts wing/hallbrain_queryMCP tool accepts wing/hall_index.mdat each wing root listing notes with Hall|Note|Created columnstask checkcleanOut of scope
Tunnels → #16. Embeddings → #8. Both depend on this issue and are now unblocked.
Closing.