package claudecode import "strings" type Milestone struct { Label string `json:"label"` Status string `json:"status"` // "done", "active", "pending" } type ProgressTracker struct { filesSeen map[string]bool milestones []Milestone } func NewProgressTracker() *ProgressTracker { return &ProgressTracker{ filesSeen: make(map[string]bool), milestones: []Milestone{ {Label: "Setting up project", Status: "active"}, {Label: "Creating data models", Status: "pending"}, {Label: "Building UI components", Status: "pending"}, {Label: "Adding styling and polish", Status: "pending"}, {Label: "Final checks", Status: "pending"}, }, } } func (pt *ProgressTracker) Milestones() []Milestone { cp := make([]Milestone, len(pt.milestones)) copy(cp, pt.milestones) return cp } func (pt *ProgressTracker) ProcessLine(line string) { lower := strings.ToLower(line) if strings.Contains(lower, "\"tool\":\"write\"") || strings.Contains(lower, "\"tool\":\"create\"") { pt.advanceTo(0) } if containsAny(lower, "model", "schema", "database", "migration", "struct", "type ") { pt.advanceTo(1) } if containsAny(lower, "component", "page", "route", "template", "html", "tsx", "jsx", "vue") { pt.advanceTo(2) } if containsAny(lower, "css", "style", "tailwind", "theme", "color", "font", "layout") { pt.advanceTo(3) } if containsAny(lower, "test", "readme", "done", "complete", "finish", "final") { pt.advanceTo(4) } } func (pt *ProgressTracker) advanceTo(idx int) { for i := range pt.milestones { if i < idx { pt.milestones[i].Status = "done" } else if i == idx { pt.milestones[i].Status = "active" } } } func containsAny(s string, substrs ...string) bool { for _, sub := range substrs { if strings.Contains(s, sub) { return true } } return false }