Commit 97d87a6

Eric Bower  ·  2026-05-08 15:43:31 -0400 EDT
parent 377fb0b
chore: restructure
3 files changed,  +19, -18
M main.go
+15, -14
 1@@ -599,10 +599,11 @@ func eventHandler(cfg *Cfg, eventData *Event) error {
 2 
 3 	// Store the event in the artifact directory so the monitor can access it
 4 	eventDir := filepath.Join(cfg.ArtifactDir, eventData.Name, jobID)
 5-	if err := os.MkdirAll(eventDir, 0755); err != nil {
 6-		log.Error("create event dir", "err", err)
 7+	artifactsDir := filepath.Join(eventDir, "artifacts")
 8+	if err := os.MkdirAll(artifactsDir, 0755); err != nil {
 9+		log.Error("create artifacts dir", "err", err)
10 	} else {
11-		if err := os.WriteFile(filepath.Join(eventDir, "event.json"), eventBytes, 0644); err != nil {
12+		if err := os.WriteFile(filepath.Join(artifactsDir, "event.json"), eventBytes, 0644); err != nil {
13 			log.Error("write event", "err", err)
14 		}
15 	}
16@@ -623,7 +624,7 @@ func eventHandler(cfg *Cfg, eventData *Event) error {
17 		"workspace_checksum": eng.Wk.Checksum(),
18 	}
19 	attestationBytes, _ := json.Marshal(attestation)
20-	if err := os.WriteFile(filepath.Join(eventDir, "attestation.json"), attestationBytes, 0644); err != nil {
21+	if err := os.WriteFile(filepath.Join(artifactsDir, "attestation.json"), attestationBytes, 0644); err != nil {
22 		log.Error("write attestation", "err", err)
23 	}
24 
25@@ -1061,7 +1062,7 @@ func monitorTick(cfg *Cfg, log *slog.Logger, output io.Writer, jobStates map[str
26 				log.Error("fetch history html", "session", s.Name, "err", err)
27 				continue
28 			}
29-			if err := stageArtifact(cfg.ArtifactDir, name, jobID, filepath.Join("sessions", s.Short), html, ".html"); err != nil {
30+			if err := stageArtifact(cfg.ArtifactDir, name, jobID, s.Short, html, ".html"); err != nil {
31 				log.Error("stage html artifact", "session", s.Short, "err", err)
32 			}
33 
34@@ -1070,7 +1071,7 @@ func monitorTick(cfg *Cfg, log *slog.Logger, output io.Writer, jobStates map[str
35 				log.Error("fetch history plain", "session", s.Name, "err", err)
36 				continue
37 			}
38-			if err := stageArtifact(cfg.ArtifactDir, name, jobID, filepath.Join("sessions", s.Short), plain, ".txt"); err != nil {
39+			if err := stageArtifact(cfg.ArtifactDir, name, jobID, s.Short, plain, ".txt"); err != nil {
40 				log.Error("stage txt artifact", "session", s.Short, "err", err)
41 			}
42 		}
43@@ -1098,7 +1099,7 @@ func monitorTick(cfg *Cfg, log *slog.Logger, output io.Writer, jobStates map[str
44 
45 		if allCompleted(group) {
46 			// Check sentinel — publish terminal status exactly once
47-			sentinel := filepath.Join(cfg.ArtifactDir, name, jobID, "published.json")
48+			sentinel := filepath.Join(cfg.ArtifactDir, name, jobID, "artifacts", "published.json")
49 			log.Debug("checking completion", "all_completed", true, "sentinel", sentinel)
50 			if _, err := os.Stat(sentinel); err == nil {
51 				log.Debug("terminal status already published, skipping", "sentinel", sentinel)
52@@ -1190,7 +1191,7 @@ func monitorTick(cfg *Cfg, log *slog.Logger, output io.Writer, jobStates map[str
53 // loadEvent reads the event.json for a job from the artifact directory.
54 func loadEvent(dir, name, jobID string) (Event, error) {
55 	var event Event
56-	data, err := os.ReadFile(filepath.Join(dir, name, jobID, "event.json"))
57+	data, err := os.ReadFile(filepath.Join(dir, name, jobID, "artifacts", "event.json"))
58 	if err != nil {
59 		return event, err
60 	}
61@@ -1479,7 +1480,7 @@ func stageArtifact(dir, name, jobID, short, content, ext string) error {
62 // syncJobArtifacts syncs artifacts for a single job.
63 func syncJobArtifacts(cfg *Cfg, repoName, jobID string, log *slog.Logger) error {
64 	jobDir := filepath.Join(cfg.ArtifactDir, repoName, jobID)
65-	eventPath := filepath.Join(jobDir, "event.json")
66+	eventPath := filepath.Join(jobDir, "artifacts", "event.json")
67 	data, err := os.ReadFile(eventPath)
68 	if err != nil {
69 		return fmt.Errorf("read event: %w", err)
70@@ -1536,7 +1537,7 @@ func syncArtifacts(cfg *Cfg, log *slog.Logger) error {
71 				continue
72 			}
73 			jobDir := filepath.Join(cfg.ArtifactDir, entry.Name(), repoEntry.Name())
74-			publishedPath := filepath.Join(jobDir, "published.json")
75+			publishedPath := filepath.Join(jobDir, "artifacts", "published.json")
76 
77 			// Skip if job is complete (published.json exists)
78 			// In-progress jobs are synced every tick; completed jobs are skipped.
79@@ -1819,14 +1820,14 @@ func generateJobIndex(artifactDir, name, jobID string, sessions []SessionInfo) (
80 		rows = append(rows, row)
81 	}
82 
83-	// Gather artifacts by scanning the job directory (excluding sessions/)
84+	// Gather artifacts by scanning the artifacts/ subfolder
85 	var artifacts []artifactRow
86-	jobDir := filepath.Join(artifactDir, name, jobID)
87+	artifactsDir := filepath.Join(artifactDir, name, jobID, "artifacts")
88 
89-	if entries, err := os.ReadDir(jobDir); err == nil {
90+	if entries, err := os.ReadDir(artifactsDir); err == nil {
91 		for _, entry := range entries {
92 			if entry.IsDir() {
93-				continue // skip subdirectories (e.g. sessions/)
94+				continue
95 			}
96 			info, err := entry.Info()
97 			if err != nil {
M main_test.go
+3, -3
 1@@ -126,8 +126,8 @@ zmx run step2 echo "hello from step2"
 2 
 3 				// Track per-session artifacts
 4 				for _, s := range p.Sessions {
 5-					htmlPath := filepath.Join(artifactDir, p.Name, p.JobID, "sessions", s.Short+".html")
 6-					txtPath := filepath.Join(artifactDir, p.Name, p.JobID, "sessions", s.Short+".txt")
 7+					htmlPath := filepath.Join(artifactDir, p.Name, p.JobID, s.Short+".html")
 8+					txtPath := filepath.Join(artifactDir, p.Name, p.JobID, s.Short+".txt")
 9 					if _, err := os.Stat(htmlPath); err == nil {
10 						sessionArtifactShorts[s.Short+"_html"] = true
11 					}
12@@ -215,7 +215,7 @@ zmx run step2 echo "hello from step2"
13 
14 	// 8. Assert HTML artifacts were staged for each session
15 	for _, s := range finalPayload.Sessions {
16-		artifactPath := filepath.Join(cfg.ArtifactDir, finalPayload.Name, finalPayload.JobID, "sessions", s.Short+".html")
17+		artifactPath := filepath.Join(cfg.ArtifactDir, finalPayload.Name, finalPayload.JobID, s.Short+".html")
18 		data, err := os.ReadFile(artifactPath)
19 		if err != nil {
20 			t.Errorf("read artifact %s: %v", artifactPath, err)
M tmpl/index.html
+1, -1
1@@ -37,7 +37,7 @@
2 <tbody>
3 {{range .Artifacts}}
4 <tr>
5-  <td><a href="{{.Name}}">{{.Name}}</a></td>
6+  <td><a href="artifacts/{{.Name}}">{{.Name}}</a></td>
7   <td>{{.Size}}</td>
8   <td>{{.ModTime}}</td>
9 </tr>