- WriteReport generiše markdown izveštaj u reports/ - formatDuration, truncateOutput za formatiranje - Kreira folder ako ne postoji, skraćuje output na 50 linija - 10 reporter testova — svi prolaze - T03 premešten u done/ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
96 lines
2.6 KiB
Go
96 lines
2.6 KiB
Go
package supervisor
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// WriteReport generates a markdown report for a completed task and writes it
|
|
// to the reports directory. Returns the path to the generated report file.
|
|
func WriteReport(task Task, run RunResult, verify VerifyResult, reportsDir string) (string, error) {
|
|
if err := os.MkdirAll(reportsDir, 0755); err != nil {
|
|
return "", fmt.Errorf("create reports dir: %w", err)
|
|
}
|
|
|
|
filename := fmt.Sprintf("%s-report.md", task.ID)
|
|
path := filepath.Join(reportsDir, filename)
|
|
|
|
content := buildReport(task, run, verify)
|
|
|
|
if err := os.WriteFile(path, []byte(content), 0644); err != nil {
|
|
return "", fmt.Errorf("write report: %w", err)
|
|
}
|
|
|
|
return path, nil
|
|
}
|
|
|
|
// buildReport generates the markdown content for a task report.
|
|
func buildReport(task Task, run RunResult, verify VerifyResult) string {
|
|
var b strings.Builder
|
|
|
|
// Header
|
|
fmt.Fprintf(&b, "# %s: %s\n\n", task.ID, task.Title)
|
|
|
|
// Metadata
|
|
fmt.Fprintf(&b, "**Datum:** %s\n", run.StartedAt.Format("2006-01-02 15:04"))
|
|
fmt.Fprintf(&b, "**Trajanje:** %s\n", formatDuration(run.Duration))
|
|
|
|
if verify.AllPassed {
|
|
b.WriteString("**Status:** ✅ Završen\n")
|
|
} else {
|
|
b.WriteString("**Status:** ❌ Neuspešan\n")
|
|
}
|
|
|
|
// Verification
|
|
b.WriteString("\n## Verifikacija\n")
|
|
for _, c := range []CheckResult{verify.Build, verify.Vet, verify.Test} {
|
|
icon := "✅"
|
|
if c.Status == "fail" {
|
|
icon = "❌"
|
|
}
|
|
line := fmt.Sprintf("- %s %s (%s)", icon, c.Name, c.Duration.Round(time.Millisecond))
|
|
if c.Name == "test" && c.TestCount > 0 {
|
|
line = fmt.Sprintf("- %s %s (%d testova, %s)", icon, c.Name, c.TestCount, c.Duration.Round(time.Millisecond))
|
|
}
|
|
b.WriteString(line + "\n")
|
|
}
|
|
|
|
// Agent output
|
|
b.WriteString("\n## Agent output\n")
|
|
b.WriteString(truncateOutput(run.Output, 50))
|
|
b.WriteString("\n")
|
|
|
|
return b.String()
|
|
}
|
|
|
|
// formatDuration formats a duration as "Xm Ys" or "Xs" for short durations.
|
|
func formatDuration(d time.Duration) string {
|
|
d = d.Round(time.Second)
|
|
minutes := int(d.Minutes())
|
|
seconds := int(d.Seconds()) % 60
|
|
|
|
if minutes > 0 {
|
|
return fmt.Sprintf("%dm %ds", minutes, seconds)
|
|
}
|
|
return fmt.Sprintf("%ds", seconds)
|
|
}
|
|
|
|
// truncateOutput keeps only the last maxLines lines of output.
|
|
func truncateOutput(output string, maxLines int) string {
|
|
if output == "" {
|
|
return "(nema outputa)\n"
|
|
}
|
|
|
|
lines := strings.Split(strings.TrimRight(output, "\n"), "\n")
|
|
if len(lines) <= maxLines {
|
|
return strings.Join(lines, "\n") + "\n"
|
|
}
|
|
|
|
truncated := lines[len(lines)-maxLines:]
|
|
return fmt.Sprintf("... (skraćeno, prikazano poslednjih %d od %d linija)\n%s\n",
|
|
maxLines, len(lines), strings.Join(truncated, "\n"))
|
|
}
|