Files
patterm/internal/harness/recorder.go

60 lines
1.8 KiB
Go

package harness
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
"time"
)
type Artifact struct {
Dir string `json:"artifact_dir"`
}
func (s *Session) DumpArtifacts(sc *Scenario, failingStep int, cause error) (*Artifact, error) {
name := sc.Name
if name == "" {
name = strings.TrimSuffix(filepath.Base(sc.Path), filepath.Ext(sc.Path))
}
if name == "" {
name = "scenario"
}
root, err := repoRoot()
if err != nil {
return nil, err
}
base := filepath.Join(root, "internal", "harness", ".artifacts")
if err := os.MkdirAll(base, 0o700); err != nil {
return nil, err
}
abs, err := os.MkdirTemp(base, fmt.Sprintf("%s-%d-*", name, time.Now().UnixNano()))
if err != nil {
return nil, err
}
screen, _ := s.em.ScreenText()
_ = os.WriteFile(filepath.Join(abs, "grid.log"), []byte(screen), 0o600)
_ = os.WriteFile(filepath.Join(abs, "raw.bytes"), s.rawBytes(), 0o600)
if b, err := s.em.SerializeVT(); err == nil {
_ = os.WriteFile(filepath.Join(abs, "serialize.vt"), b, 0o600)
}
envBytes, _ := json.MarshalIndent(s.env, "", " ")
_ = os.WriteFile(filepath.Join(abs, "env.json"), append(envBytes, '\n'), 0o600)
annotated := map[string]any{"scenario": sc, "failing_step": failingStep}
if cause != nil {
annotated["error"] = cause.Error()
}
ab, _ := json.MarshalIndent(annotated, "", " ")
_ = os.WriteFile(filepath.Join(abs, "scenario.annotated.json"), append(ab, '\n'), 0o600)
snapshot := map[string]json.RawMessage{}
for _, method := range []string{"whoami", "list_processes", "get_project_status"} {
if raw, err := s.mcp.Call(method, map[string]any{}); err == nil {
snapshot[method] = raw
}
}
sb, _ := json.MarshalIndent(snapshot, "", " ")
_ = os.WriteFile(filepath.Join(abs, "mcp-snapshot.json"), append(sb, '\n'), 0o600)
return &Artifact{Dir: abs}, nil
}