// ingestion/internal/wiki/inventory.go package wiki import ( "bufio" "os" "path/filepath" "strings" ) // LoadInventory walks brain/wiki/ and returns all pages grouped by type. // Missing subdirectories are silently skipped. func LoadInventory(brainDir string) (map[PageType][]Entry, error) { result := map[PageType][]Entry{ PageTypeConcept: {}, PageTypeEntity: {}, PageTypeSource: {}, } for pt := range result { dir := filepath.Join(brainDir, "wiki", string(pt)) entries, err := os.ReadDir(dir) if os.IsNotExist(err) { continue } if err != nil { return nil, err } for _, e := range entries { if e.IsDir() || !strings.HasSuffix(e.Name(), ".md") { continue } slug := strings.TrimSuffix(e.Name(), ".md") path := filepath.Join(dir, e.Name()) title := readTitle(path, slug) result[pt] = append(result[pt], Entry{Slug: slug, Title: title, Type: pt}) } } return result, nil } // readTitle extracts the title from YAML frontmatter, falling back to slug. func readTitle(path, fallback string) string { f, err := os.Open(path) if err != nil { return fallback } defer f.Close() scanner := bufio.NewScanner(f) inFM := false for scanner.Scan() { line := scanner.Text() if strings.TrimSpace(line) == "---" { if !inFM { inFM = true continue } break } if inFM { key, val, ok := strings.Cut(line, ":") if ok && strings.TrimSpace(key) == "title" { return strings.Trim(strings.TrimSpace(val), `"'`) } } } return fallback }