// ingestion/internal/wiki/inventory.go package wiki import ( "bufio" "fmt" "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, fmt.Errorf("read dir %s: %w", dir, 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, aliases := readFrontmatter(path, slug) result[pt] = append(result[pt], Entry{Slug: slug, Title: title, Aliases: aliases, Type: pt}) } } return result, nil } // readFrontmatter extracts title and aliases from YAML frontmatter. // Falls back to slug for title and empty aliases on any error. func readFrontmatter(path, fallbackSlug string) (title string, aliases []string) { title = fallbackSlug f, err := os.Open(path) if err != nil { return } defer f.Close() //nolint:errcheck scanner := bufio.NewScanner(f) inFM := false inAliases := false for scanner.Scan() { line := scanner.Text() if strings.TrimSpace(line) == "---" { if !inFM { inFM = true continue } break // end of frontmatter } if !inFM { continue } // Detect alias list items (lines starting with " - "). if inAliases { trimmed := strings.TrimSpace(line) if strings.HasPrefix(trimmed, "- ") { aliases = append(aliases, strings.TrimPrefix(trimmed, "- ")) continue } inAliases = false // end of alias block } key, val, ok := strings.Cut(line, ":") if !ok { continue } switch strings.TrimSpace(key) { case "title": title = strings.Trim(strings.TrimSpace(val), `"'`) case "aliases": inAliases = true } } return }