auto-update-daily-20260202
  1// Package config handles configuration loading and defaults.
  2package config
  3
  4import (
  5	"os"
  6	"path/filepath"
  7	"strings"
  8
  9	"gopkg.in/yaml.v3"
 10)
 11
 12// Config represents the complete configuration.
 13type Config struct {
 14	User   UserConfig   `yaml:"user"`
 15	GitHub GitHubConfig `yaml:"github"`
 16	Org    OrgConfig    `yaml:"org"`
 17	Jira   JiraConfig   `yaml:"jira"`
 18	Claude ClaudeConfig `yaml:"claude"`
 19	Output OutputConfig `yaml:"output"`
 20}
 21
 22// UserConfig holds user identification.
 23type UserConfig struct {
 24	Name  string `yaml:"name"`
 25	Email string `yaml:"email"`
 26}
 27
 28// GitHubConfig configures the GitHub source.
 29type GitHubConfig struct {
 30	Enabled            bool     `yaml:"enabled"`
 31	Username           string   `yaml:"username"`
 32	Repos              []string `yaml:"repos,omitempty"`
 33	IncludePRs         bool     `yaml:"include_prs"`
 34	IncludeIssues      bool     `yaml:"include_issues"`
 35	IncludeReviews     bool     `yaml:"include_reviews"`
 36	IncludeCommits     bool     `yaml:"include_commits"`
 37	IncludeDiscussions bool     `yaml:"include_discussions"`
 38	IncludeComments    bool     `yaml:"include_comments"`
 39}
 40
 41// OrgConfig configures the org-mode source.
 42type OrgConfig struct {
 43	Enabled             bool     `yaml:"enabled"`
 44	Files               []string `yaml:"files"`
 45	ArchiveDir          string   `yaml:"archive_dir,omitempty"` // Optional archive directory to scan
 46	IncludeDone         bool     `yaml:"include_done"`
 47	IncludeStateChanges bool     `yaml:"include_state_changes"`
 48	IncludeClockEntries bool     `yaml:"include_clock_entries"`
 49}
 50
 51// JiraConfig configures the Jira source.
 52type JiraConfig struct {
 53	Enabled  bool     `yaml:"enabled"`
 54	Server   string   `yaml:"server"`
 55	Projects []string `yaml:"projects,omitempty"`
 56	Username string   `yaml:"username"`
 57}
 58
 59// ClaudeConfig configures the Claude history source.
 60type ClaudeConfig struct {
 61	Enabled          bool   `yaml:"enabled"`
 62	HistoryDir       string `yaml:"history_dir"`
 63	IncludeSessions  bool   `yaml:"include_sessions"`
 64	IncludeLearnings bool   `yaml:"include_learnings"`
 65	IncludeResearch  bool   `yaml:"include_research"`
 66}
 67
 68// OutputConfig configures output formatting.
 69type OutputConfig struct {
 70	DefaultFormat  string `yaml:"default_format"`
 71	IncludeSummary bool   `yaml:"include_summary"`
 72}
 73
 74// DefaultConfigPath returns the default config file location.
 75func DefaultConfigPath() string {
 76	home, _ := os.UserHomeDir()
 77	return filepath.Join(home, ".config", "review-tool", "config.yaml")
 78}
 79
 80// Load reads configuration from file, falling back to defaults.
 81func Load(path string) (*Config, error) {
 82	if path == "" {
 83		path = DefaultConfigPath()
 84	}
 85
 86	cfg := DefaultConfig()
 87
 88	data, err := os.ReadFile(path)
 89	if err != nil {
 90		if os.IsNotExist(err) {
 91			return cfg, nil // Use defaults if no config file
 92		}
 93		return nil, err
 94	}
 95
 96	if err := yaml.Unmarshal(data, cfg); err != nil {
 97		return nil, err
 98	}
 99
100	// Expand ~ in paths
101	cfg.expandPaths()
102
103	return cfg, nil
104}
105
106// DefaultConfig returns a configuration with sensible defaults.
107func DefaultConfig() *Config {
108	home, _ := os.UserHomeDir()
109
110	return &Config{
111		User: UserConfig{},
112		GitHub: GitHubConfig{
113			Enabled:            true,
114			IncludePRs:         true,
115			IncludeIssues:      true,
116			IncludeReviews:     true,
117			IncludeCommits:     false,
118			IncludeDiscussions: true,
119			IncludeComments:    true,
120		},
121		Org: OrgConfig{
122			Enabled: true,
123			Files: []string{
124				filepath.Join(home, "desktop", "org", "todos.org"),
125			},
126			ArchiveDir:          filepath.Join(home, "desktop", "org", "archive"),
127			IncludeDone:         true,
128			IncludeStateChanges: true,
129			IncludeClockEntries: true,
130		},
131		Jira: JiraConfig{
132			Enabled: false,
133		},
134		Claude: ClaudeConfig{
135			Enabled:          true,
136			HistoryDir:       filepath.Join(home, ".config", "claude", "history"),
137			IncludeSessions:  true,
138			IncludeLearnings: true,
139			IncludeResearch:  true,
140		},
141		Output: OutputConfig{
142			DefaultFormat:  "markdown",
143			IncludeSummary: true,
144		},
145	}
146}
147
148func (c *Config) expandPaths() {
149	home, _ := os.UserHomeDir()
150
151	// Expand org files
152	for i, f := range c.Org.Files {
153		c.Org.Files[i] = expandHome(f, home)
154	}
155
156	// Expand org archive dir
157	c.Org.ArchiveDir = expandHome(c.Org.ArchiveDir, home)
158
159	// Expand Claude history dir
160	c.Claude.HistoryDir = expandHome(c.Claude.HistoryDir, home)
161}
162
163func expandHome(path, home string) string {
164	if strings.HasPrefix(path, "~/") {
165		return filepath.Join(home, path[2:])
166	}
167	if path == "~" {
168		return home
169	}
170	return path
171}