feat(skills): wire session.Append and PrependHistory into tdd

This commit is contained in:
Mathias Bergqvist
2026-04-22 13:37:06 +02:00
parent 85f142ade0
commit f9f804cd49

View File

@@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"time"
iexec "github.com/mathiasbq/supervisor/internal/exec"
"github.com/mathiasbq/supervisor/internal/session"
@@ -70,8 +71,15 @@ func (s *Skill) handleGreen(ctx context.Context, raw json.RawMessage) (json.RawM
"phase: green\nproject_root: %s\ntest_path: %s\nmodel: %s\ntest_cmd: %s",
args.ProjectRoot, args.TestPath, s.resolveModel(args.Model), args.TestCmd,
)
task = s.prependHistory(args.SessionID, "green", task)
return s.execute(ctx, task)
task = session.PrependHistory(s.cfg.SessionsDir, args.SessionID, "green", task)
t0 := time.Now()
result, err := s.execute(ctx, task)
if err != nil {
return nil, err
}
s.logAttempt(args.SessionID, args.ProjectRoot, "tdd", "green", t0, result)
return result, nil
}
type refactorArgs struct {
@@ -101,23 +109,15 @@ func (s *Skill) handleRefactor(ctx context.Context, raw json.RawMessage) (json.R
"phase: refactor\nproject_root: %s\ntest_path: %s\nimpl_path: %s\nmodel: %s\ntest_cmd: %s",
args.ProjectRoot, args.TestPath, args.ImplPath, s.resolveModel(args.Model), args.TestCmd,
)
task = s.prependHistory(args.SessionID, "refactor", task)
return s.execute(ctx, task)
}
task = session.PrependHistory(s.cfg.SessionsDir, args.SessionID, "refactor", task)
func (s *Skill) prependHistory(sessionID, currentPhase, task string) string {
if sessionID == "" || s.cfg.SessionsDir == "" {
return task
t0 := time.Now()
result, err := s.execute(ctx, task)
if err != nil {
return nil, err
}
entries, err := session.Read(s.cfg.SessionsDir, sessionID)
if err != nil || len(entries) == 0 {
return task
}
history := session.FormatHistory(entries, currentPhase)
if history == "" {
return task
}
return history + "\n---\n\n" + task
s.logAttempt(args.SessionID, args.ProjectRoot, "tdd", "refactor", t0, result)
return result, nil
}
func (s *Skill) resolveModel(override string) string {
@@ -127,6 +127,7 @@ func (s *Skill) resolveModel(override string) string {
return s.cfg.DefaultModel
}
// execute calls ExecutorFn and returns the marshaled result.
func (s *Skill) execute(ctx context.Context, task string) (json.RawMessage, error) {
if s.cfg.ExecutorFn == nil {
return nil, fmt.Errorf("no executor configured")
@@ -141,3 +142,28 @@ func (s *Skill) execute(ctx context.Context, task string) (json.RawMessage, erro
}
return json.Marshal(result)
}
// logAttempt writes a session.Entry for a completed phase if session_id is set.
// raw is the marshaled Result returned by execute; we unmarshal to extract fields.
func (s *Skill) logAttempt(sessionID, projectRoot, skill, phase string, t0 time.Time, raw json.RawMessage) {
if sessionID == "" || s.cfg.SessionsDir == "" {
return
}
var result iexec.Result
if err := json.Unmarshal(raw, &result); err != nil {
return
}
_ = session.Append(s.cfg.SessionsDir, sessionID, session.Entry{
SessionID: sessionID,
Timestamp: time.Now(),
Skill: skill,
Phase: phase,
ProjectRoot: projectRoot,
Attempts: session.AttemptsFrom(result.Attempts),
FinalStatus: result.Status,
FilePath: result.FilePath,
ModelUsed: result.ModelUsed,
DurationMs: time.Since(t0).Milliseconds(),
Message: result.Message,
})
}