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 }