Add generated text state artifacts

This commit is contained in:
2026-06-14 04:51:52 +00:00
parent f6a68426e1
commit 316ab8f3fc
5 changed files with 310 additions and 45 deletions

View File

@@ -40,6 +40,35 @@ func TestPathsUseRunIDAndWorkspace(t *testing.T) {
}
}
func TestGeneratedTextArtifactPathsUseSnapshotTree(t *testing.T) {
store := newTestStore(t)
resolved := resolveHourlyAt(t, "2026-05-29T05:00:00-05:00")
paths, err := store.Paths(resolved)
if err != nil {
t.Fatalf("Paths() error = %v", err)
}
runID := "20260529T100000.000000000Z_hourly"
wants := map[string]string{
"GeneratedTextRaw": filepath.Join("snapshots", "hourly", "2026-05-29", runID+".generated_text.raw.json"),
"GeneratedTextResult": filepath.Join("snapshots", "hourly", "2026-05-29", runID+".generated_text.run.json"),
"GeneratedText": filepath.Join("snapshots", "hourly", "2026-05-29", runID+".generated_text.json"),
"RenderContext": filepath.Join("snapshots", "hourly", "2026-05-29", runID+".render_context.json"),
}
got := map[string]string{
"GeneratedTextRaw": paths.GeneratedTextRaw,
"GeneratedTextResult": paths.GeneratedTextResult,
"GeneratedText": paths.GeneratedText,
"RenderContext": paths.RenderContext,
}
for name, want := range wants {
if !strings.Contains(got[name], want) {
t.Fatalf("%s path = %q, want component %q", name, got[name], want)
}
}
}
func TestSaveArtifactsAndMetadataRoundTrip(t *testing.T) {
store := newTestStore(t)
resolved := resolveDailyAt(t, "2026-05-29T05:00:00-05:00")
@@ -180,6 +209,117 @@ func TestSaveArtifactsAndMetadataRoundTrip(t *testing.T) {
if strings.Contains(string(data), "MetadataPath") || strings.Contains(string(data), "metadataPath") {
t.Fatalf("metadata JSON includes runtime-only MetadataPath:\n%s", string(data))
}
for _, unexpected := range []string{"generatedTextSchemaId", "generatedTextRawPath", "generatedTextResultPath", "generatedTextPath", "renderContextPath"} {
if strings.Contains(string(data), unexpected) {
t.Fatalf("metadata JSON includes generated-text field %q for Markdown report:\n%s", unexpected, string(data))
}
}
}
func TestSaveGeneratedTextArtifactsAndMetadataRoundTrip(t *testing.T) {
store := newTestStore(t)
resolved := resolveHourlyAt(t, "2026-05-29T05:00:00-05:00")
briefingMetadata := stateBriefingMetadata(resolved)
rawPath, err := store.SaveGeneratedTextRaw(context.Background(), resolved, []byte(`{"summary":"raw"}`))
if err != nil {
t.Fatalf("SaveGeneratedTextRaw() error = %v", err)
}
resultPath, err := store.SaveGeneratedTextResult(context.Background(), resolved, map[string]any{
"command": []string{"scriptorium", "run"},
"status": "succeeded",
})
if err != nil {
t.Fatalf("SaveGeneratedTextResult() error = %v", err)
}
generatedPath, err := store.SaveGeneratedText(context.Background(), resolved, []byte(`{"summary":"Storm chances increase.","timing":"Late morning.","impacts":"Brief downpours."}`))
if err != nil {
t.Fatalf("SaveGeneratedText() error = %v", err)
}
contextPath, err := store.SaveRenderContext(context.Background(), resolved, struct {
ReportTitle string `json:"reportTitle"`
Location string `json:"location"`
}{
ReportTitle: "Hourly Report",
Location: "Brentwood",
})
if err != nil {
t.Fatalf("SaveRenderContext() error = %v", err)
}
for _, path := range []string{rawPath, resultPath, generatedPath, contextPath} {
if _, err := os.Stat(path); err != nil {
t.Fatalf("expected generated-text artifact %q: %v", path, err)
}
}
rawData, err := store.LoadGeneratedText(context.Background(), rawPath)
if err != nil {
t.Fatalf("LoadGeneratedText() raw error = %v", err)
}
if string(rawData) != `{"summary":"raw"}` {
t.Fatalf("raw data = %q, want saved bytes", rawData)
}
generatedData, err := store.LoadGeneratedText(context.Background(), generatedPath)
if err != nil {
t.Fatalf("LoadGeneratedText() generated error = %v", err)
}
if !strings.Contains(string(generatedData), `"timing":"Late morning."`) {
t.Fatalf("generated text = %q, want saved normalized JSON", generatedData)
}
var runResult struct {
Command []string `json:"command"`
Status string `json:"status"`
}
if err := store.LoadGeneratedTextResult(context.Background(), resultPath, &runResult); err != nil {
t.Fatalf("LoadGeneratedTextResult() error = %v", err)
}
if runResult.Status != "succeeded" || strings.Join(runResult.Command, " ") != "scriptorium run" {
t.Fatalf("run result = %#v, want saved result", runResult)
}
var renderContext struct {
ReportTitle string `json:"reportTitle"`
Location string `json:"location"`
}
if err := store.LoadRenderContext(context.Background(), contextPath, &renderContext); err != nil {
t.Fatalf("LoadRenderContext() error = %v", err)
}
if renderContext.ReportTitle != "Hourly Report" || renderContext.Location != "Brentwood" {
t.Fatalf("render context = %#v, want saved context", renderContext)
}
paths, err := store.Paths(resolved)
if err != nil {
t.Fatalf("Paths() error = %v", err)
}
metadata := BuildMetadataFromBriefingMetadata(resolved, briefingMetadata, ArtifactPaths{
ModuleSnapshot: paths.ModuleSnapshot,
Metadata: paths.Metadata,
DataPackage: paths.DataPackage,
Preflight: paths.Preflight,
RenderedReport: paths.RenderedReport,
GeneratedTextRaw: rawPath,
GeneratedTextResult: resultPath,
GeneratedText: generatedPath,
RenderContext: contextPath,
})
metadataPath, err := store.SaveMetadata(context.Background(), metadata)
if err != nil {
t.Fatalf("SaveMetadata() error = %v", err)
}
var decoded Metadata
metadataData, err := os.ReadFile(metadataPath)
if err != nil {
t.Fatalf("read metadata: %v", err)
}
if err := json.Unmarshal(metadataData, &decoded); err != nil {
t.Fatalf("decode metadata: %v", err)
}
if decoded.GeneratedTextSchemaID != "hourly" {
t.Fatalf("GeneratedTextSchemaID = %q, want hourly", decoded.GeneratedTextSchemaID)
}
if decoded.GeneratedTextRawPath != rawPath || decoded.GeneratedTextResultPath != resultPath || decoded.GeneratedTextPath != generatedPath || decoded.RenderContextPath != contextPath {
t.Fatalf("metadata generated-text paths = %#v, want saved artifact paths", decoded)
}
}
func TestSaveMetadataUsesExplicitMetadataPath(t *testing.T) {
@@ -471,5 +611,9 @@ func pathsString(paths ArtifactPaths) string {
paths.Preflight,
paths.Notification,
paths.RenderedReport,
paths.GeneratedTextRaw,
paths.GeneratedTextResult,
paths.GeneratedText,
paths.RenderContext,
}, "\n")
}