package tdd import ( "context" "encoding/json" iexec "github.com/mathiasbq/supervisor/internal/exec" "github.com/mathiasbq/supervisor/internal/registry" ) // ExecutorFn allows injecting a test double for the executor. type ExecutorFn func(ctx context.Context, req iexec.Request) (iexec.Result, error) type Config struct { SystemPrompt string SkillPrompt string ExecutorFn ExecutorFn // nil = no executor (tests that don't reach execute()) DefaultModel string SessionsDir string // optional: path to brain/sessions/ for history injection } type Skill struct { cfg Config } func New(cfg Config) *Skill { return &Skill{cfg: cfg} } func (s *Skill) Name() string { return "tdd" } func (s *Skill) Tools() []registry.ToolDef { schema := func(required []string, props map[string]any) json.RawMessage { b, _ := json.Marshal(map[string]any{ "type": "object", "required": required, "properties": props, }) return b } strProp := map[string]any{"type": "string"} return []registry.ToolDef{ { Name: "tdd_red", Description: "Write a failing test for the described behavior. Verifies the test fails before returning.", InputSchema: schema( []string{"project_root", "spec"}, map[string]any{ "project_root": strProp, "spec": strProp, "model": strProp, "test_cmd": strProp, }, ), }, { Name: "tdd_green", Description: "Write minimal implementation to make the test at test_path pass.", InputSchema: schema( []string{"project_root", "test_path"}, map[string]any{ "project_root": strProp, "test_path": strProp, "model": strProp, "test_cmd": strProp, "session_id": strProp, }, ), }, { Name: "tdd_refactor", Description: "Refactor the implementation at impl_path while keeping tests green.", InputSchema: schema( []string{"project_root", "test_path", "impl_path"}, map[string]any{ "project_root": strProp, "test_path": strProp, "impl_path": strProp, "model": strProp, "test_cmd": strProp, "session_id": strProp, }, ), }, } }