// Command harness is the CLI entry point: flag parsing, wiring, and (from // Phase 1) the REPL. package main import ( "encoding/json" "flag" "fmt" "os" "path/filepath" "time" "harness/internal/metrics" "harness/internal/tools" ) func main() { if err := run(); err != nil { fmt.Fprintln(os.Stderr, "harness:", err) os.Exit(1) } } func run() error { workdir := flag.String("C", ".", "working root the agent operates in") logPath := flag.String("metrics", metrics.DefaultPath, "JSONL event log path") flag.Parse() root, err := filepath.Abs(*workdir) if err != nil { return err } session := time.Now().UTC().Format("20060102T150405Z") log, err := metrics.Open(filepath.Join(root, *logPath), session) if err != nil { return err } defer log.Close() log.Log(metrics.Event{Type: "session_start", Extra: map[string]any{"root": root}}) reg := tools.NewRegistry(log) // Tools land here in Phase 1 (read_file) and Phase 2 (the rest). fmt.Printf("harness session %s\nroot: %s\nmetrics: %s\ntools: %d registered\n", session, root, filepath.Join(root, *logPath), len(reg.List())) for _, t := range reg.List() { schema, _ := json.Marshal(json.RawMessage(t.InputSchema())) fmt.Printf(" %-12s %s\n %s\n", t.Name(), t.Description(), schema) } fmt.Println("\nno agent loop yet — Phase 1.") return nil }