From cbef2da8debd31186e4a4d893972d285722bedb7 Mon Sep 17 00:00:00 2001 From: Mathias Bergqvist Date: Sun, 19 Apr 2026 09:28:52 +0200 Subject: [PATCH] feat(session): add FormatHistory for worker context injection Co-Authored-By: Claude Sonnet 4.6 --- internal/session/history.go | 38 +++++++++++++++++++++++++++++ internal/session/history_test.go | 41 ++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 internal/session/history.go create mode 100644 internal/session/history_test.go diff --git a/internal/session/history.go b/internal/session/history.go new file mode 100644 index 0000000..5d3f4f4 --- /dev/null +++ b/internal/session/history.go @@ -0,0 +1,38 @@ +// internal/session/history.go +package session + +import ( + "fmt" + "strings" +) + +// FormatHistory formats prior session entries as a structured block for +// injection into a worker task prompt. Entries matching excludePhase are +// omitted (pass the current phase to avoid circular injection). +func FormatHistory(entries []Entry, excludePhase string) string { + var filtered []Entry + for _, e := range entries { + if e.Phase != excludePhase { + filtered = append(filtered, e) + } + } + if len(filtered) == 0 { + return "" + } + + var b strings.Builder + b.WriteString("## Session history\n\n") + for _, e := range filtered { + b.WriteString(fmt.Sprintf("### Phase: %s\n", e.Phase)) + b.WriteString(fmt.Sprintf("- Skill: %s\n", e.Skill)) + b.WriteString(fmt.Sprintf("- Status: %s\n", e.FinalStatus)) + if e.FilePath != "" { + b.WriteString(fmt.Sprintf("- File: %s\n", e.FilePath)) + } + if e.Message != "" { + b.WriteString(fmt.Sprintf("- Summary: %s\n", e.Message)) + } + b.WriteString("\n") + } + return b.String() +} diff --git a/internal/session/history_test.go b/internal/session/history_test.go new file mode 100644 index 0000000..9117d23 --- /dev/null +++ b/internal/session/history_test.go @@ -0,0 +1,41 @@ +// internal/session/history_test.go +package session_test + +import ( + "testing" + "time" + + "github.com/mathiasbq/supervisor/internal/session" + "github.com/stretchr/testify/assert" +) + +func TestFormatHistoryEmpty(t *testing.T) { + result := session.FormatHistory(nil, "") + assert.Equal(t, "", result) +} + +func TestFormatHistoryFormatsEntries(t *testing.T) { + entries := []session.Entry{ + { + Skill: "tdd", Phase: "red", FinalStatus: "pass", + FilePath: "internal/foo/foo_test.go", + Message: "wrote failing test for Foo", + Timestamp: time.Now(), + }, + } + result := session.FormatHistory(entries, "") + assert.Contains(t, result, "## Session history") + assert.Contains(t, result, "Phase: red") + assert.Contains(t, result, "wrote failing test for Foo") + assert.Contains(t, result, "internal/foo/foo_test.go") +} + +func TestFormatHistoryExcludesCurrentPhase(t *testing.T) { + entries := []session.Entry{ + {Skill: "tdd", Phase: "red", Message: "red done", FinalStatus: "pass"}, + {Skill: "tdd", Phase: "green", Message: "green done", FinalStatus: "pass"}, + } + result := session.FormatHistory(entries, "green") + assert.Contains(t, result, "red done") + assert.NotContains(t, result, "green done") +}