refactor(config): add goal lookup across areas

Amolith created

Adds GoalMatch type and FindGoalsByKey helper for collision detection.
Also adds json tags to config structs for JSON output.

Assisted-by: Claude Opus 4.5 via Crush

Change summary

internal/config/config.go | 52 ++++++++++++++++++++++++++++++----------
1 file changed, 39 insertions(+), 13 deletions(-)

Detailed changes

internal/config/config.go 🔗

@@ -39,31 +39,31 @@ type Defaults struct {
 
 // Area represents a Lunatask area of life with its goals.
 type Area struct {
-	ID    string `toml:"id"`
-	Name  string `toml:"name"`
-	Key   string `toml:"key"`
-	Goals []Goal `toml:"goals"`
+	ID    string `json:"id"    toml:"id"`
+	Name  string `json:"name"  toml:"name"`
+	Key   string `json:"key"   toml:"key"`
+	Goals []Goal `json:"goals" toml:"goals"`
 }
 
 // Goal represents a goal within an area.
 type Goal struct {
-	ID   string `toml:"id"`
-	Name string `toml:"name"`
-	Key  string `toml:"key"`
+	ID   string `json:"id"   toml:"id"`
+	Name string `json:"name" toml:"name"`
+	Key  string `json:"key"  toml:"key"`
 }
 
 // Notebook represents a Lunatask notebook for notes.
 type Notebook struct {
-	ID   string `toml:"id"`
-	Name string `toml:"name"`
-	Key  string `toml:"key"`
+	ID   string `json:"id"   toml:"id"`
+	Name string `json:"name" toml:"name"`
+	Key  string `json:"key"  toml:"key"`
 }
 
 // Habit represents a trackable habit.
 type Habit struct {
-	ID   string `toml:"id"`
-	Name string `toml:"name"`
-	Key  string `toml:"key"`
+	ID   string `json:"id"   toml:"id"`
+	Name string `json:"name" toml:"name"`
+	Key  string `json:"key"  toml:"key"`
 }
 
 // Path returns the path to the config file.
@@ -168,3 +168,29 @@ func (a *Area) GoalByKey(key string) *Goal {
 
 	return nil
 }
+
+// GoalMatch pairs a goal with its parent area.
+type GoalMatch struct {
+	Goal *Goal
+	Area *Area
+}
+
+// FindGoalsByKey returns all goals matching the given key across all areas.
+func (c *Config) FindGoalsByKey(key string) []GoalMatch {
+	var matches []GoalMatch
+
+	for i := range c.Areas {
+		area := &c.Areas[i]
+
+		for j := range area.Goals {
+			if area.Goals[j].Key == key {
+				matches = append(matches, GoalMatch{
+					Goal: &area.Goals[j],
+					Area: area,
+				})
+			}
+		}
+	}
+
+	return matches
+}