package action import ( "context" "encoding/json" "fmt" "os" "path/filepath" ) // Lesson represents a learned lesson from a failed attempt. type Lesson struct { Attempt int `json:"attempt"` Critique string `json:"critique"` FailedApproachSummary string `json:"failed_approach_summary"` Timestamp string `json:"timestamp"` } // ReadLessonsInput is input to ReadLessonsActivity. type ReadLessonsInput struct { TargetRepoPath string TaskID string } // ReadLessonsOutput is the output of ReadLessonsActivity. type ReadLessonsOutput struct { Lessons string // JSONL or formatted string of lessons } // ReadLessonsActivity reads lessons for a task. func ReadLessonsActivity(ctx context.Context, in ReadLessonsInput) (ReadLessonsOutput, error) { lessonsFile := filepath.Join(in.TargetRepoPath, "tasks", ".orchestrator", "lessons", in.TaskID+".jsonl") // If file doesn't exist, return empty lessons if _, err := os.Stat(lessonsFile); os.IsNotExist(err) { return ReadLessonsOutput{Lessons: ""}, nil } // Read and format lessons data, err := os.ReadFile(lessonsFile) if err != nil { return ReadLessonsOutput{}, fmt.Errorf("failed to read lessons file: %w", err) } // Format lessons as plain text lines := string(data) return ReadLessonsOutput{Lessons: lines}, nil } // UpdateLessonsInput is input to UpdateLessonsActivity. type UpdateLessonsInput struct { TargetRepoPath string TaskID string Attempt int Critique string FailedApproachSummary string } // UpdateLessonsActivity appends a lesson to the lessons file. func UpdateLessonsActivity(ctx context.Context, in UpdateLessonsInput) error { lessonsDir := filepath.Join(in.TargetRepoPath, "tasks", ".orchestrator", "lessons") // Create directory if it doesn't exist if err := os.MkdirAll(lessonsDir, 0755); err != nil { return fmt.Errorf("failed to create lessons directory: %w", err) } lessonsFile := filepath.Join(lessonsDir, in.TaskID+".jsonl") // Create lesson entry lesson := map[string]any{ "attempt": in.Attempt, "critique": in.Critique, "failed_approach_summary": in.FailedApproachSummary, "timestamp": "", } // Marshal to JSON data, err := json.Marshal(lesson) if err != nil { return fmt.Errorf("failed to marshal lesson: %w", err) } // Append to file f, err := os.OpenFile(lessonsFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) if err != nil { return fmt.Errorf("failed to open lessons file: %w", err) } defer f.Close() _, err = f.Write(append(data, '\n')) if err != nil { return fmt.Errorf("failed to write lesson: %w", err) } return nil }