Add Weekend Outlook generation

This commit is contained in:
2026-05-29 18:16:10 +00:00
parent 4c9d396f9b
commit 5d543b6b4d
21 changed files with 760 additions and 69 deletions

View File

@@ -155,7 +155,7 @@ func RunBatch(ctx context.Context, req BatchRequest) error {
}
func isGeneratedReport(id report.ID) bool {
return isDailyReport(id) || id == report.ThreeDay
return isDailyReport(id) || id == report.ThreeDay || id == report.Weekend
}
func isDailyReport(id report.ID) bool {
@@ -443,11 +443,19 @@ func BuildBriefing(req BriefingRequest, bundle *forecast.Bundle) (briefing.Packa
Units: req.Config.WeatherAPI.Units,
Timezone: req.Config.WeatherAPI.Timezone,
}, summary)
case report.ThreeDay:
case report.ThreeDay, report.Weekend:
summaries, err := forecast.BuildPeriodDailySummaries(bundle, req.Resolved.ValidPeriod, location, dayparts)
if err != nil {
return briefing.Package{}, err
}
if req.Resolved.Definition.ID == report.Weekend {
return briefing.BuildWeekend(briefing.BuildContext{
Resolved: req.Resolved,
Bundle: bundle,
Units: req.Config.WeatherAPI.Units,
Timezone: req.Config.WeatherAPI.Timezone,
}, summaries)
}
return briefing.BuildThreeDay(briefing.BuildContext{
Resolved: req.Resolved,
Bundle: bundle,
@@ -486,6 +494,8 @@ func recentChanges(ctx context.Context, store state.Store, priorSnapshot *state.
return changes.CompareDaily(previous, current, thresholds)
case report.ThreeDay:
return changes.CompareThreeDay(previous, current, thresholds)
case report.Weekend:
return changes.CompareWeekend(previous, current, thresholds)
default:
return nil, nil
}

View File

@@ -598,6 +598,81 @@ func TestGenerateThreeDayReportWritesReportAndRecentChanges(t *testing.T) {
}
}
func TestGenerateWeekendReportWritesReportAndRecentChanges(t *testing.T) {
server := dailyBundleServer(t)
cfg := config.Defaults()
cfg.WeatherAPI.BaseURL = server.URL + "/"
cfg.WeatherAPI.Timezone = "America/Chicago"
cfg.Workspace.Root = t.TempDir()
store, err := state.NewFilesystemStore(cfg.Workspace)
if err != nil {
t.Fatalf("NewFilesystemStore() error = %v", err)
}
priorResolved, err := ResolveGenerate(GenerateRequest{
Config: cfg,
Report: ReportWeekend,
}, mustParse("2026-05-29T04:00:00-05:00"))
if err != nil {
t.Fatalf("ResolveGenerate(prior) error = %v", err)
}
priorBriefing := priorWeekendBriefing(priorResolved)
priorBriefingPath, err := store.SaveBriefing(context.Background(), priorResolved, priorBriefing)
if err != nil {
t.Fatalf("SaveBriefing() error = %v", err)
}
priorPaths, err := store.Paths(priorResolved)
if err != nil {
t.Fatalf("Paths() error = %v", err)
}
_, err = store.SaveMetadata(context.Background(), state.BuildMetadata(priorResolved, priorBriefing, state.ArtifactPaths{
Briefing: priorBriefingPath,
DataPackage: priorPaths.DataPackage,
Preflight: priorPaths.Preflight,
RenderedReport: priorPaths.RenderedReport,
}))
if err != nil {
t.Fatalf("SaveMetadata() error = %v", err)
}
currentResolved, err := ResolveGenerate(GenerateRequest{
Config: cfg,
Report: ReportWeekend,
}, mustParse("2026-05-29T05:00:00-05:00"))
if err != nil {
t.Fatalf("ResolveGenerate(current) error = %v", err)
}
renderer := &recordingRenderer{
renderResult: &scriptorium.RenderResult{ExitCode: 0},
runResult: &scriptorium.RunResult{ExitCode: 0},
runBody: "# Weekend Outlook\n",
}
result, err := GenerateReport(context.Background(), ReportRequest{
Config: cfg,
Resolved: currentResolved,
Renderer: renderer,
Store: store,
})
if err != nil {
t.Fatalf("GenerateReport() error = %v", err)
}
if result.Briefing.Weekend == nil {
t.Fatal("Weekend = nil")
}
if len(result.Briefing.Weekend.Days) != 3 {
t.Fatalf("Weekend days = %d, want 3", len(result.Briefing.Weekend.Days))
}
if renderer.renderRequest.PromptID != "weather.weekend_outlook" {
t.Fatalf("render PromptID = %q, want weather.weekend_outlook", renderer.renderRequest.PromptID)
}
if result.PriorSnapshot == nil {
t.Fatal("PriorSnapshot = nil, want prior weekend snapshot")
}
if len(result.RecentChanges) == 0 {
t.Fatal("RecentChanges length = 0, want changes from prior weekend snapshot")
}
}
func TestResolveGenerateMapsCommandToReportDefinition(t *testing.T) {
cfg := config.Defaults()
cfg.WeatherAPI.Timezone = "America/Chicago"
@@ -756,6 +831,35 @@ func priorThreeDayBriefing(resolved report.Resolved) briefing.Package {
}
}
func priorWeekendBriefing(resolved report.Resolved) briefing.Package {
high := 58.0
precip := 10.0
return briefing.Package{
Metadata: briefing.Metadata{
SchemaVersion: briefing.SchemaVersion,
RunID: resolved.Metadata().RunID,
ReportID: resolved.Definition.ID,
PromptID: resolved.Definition.PromptID,
GeneratedAt: resolved.GeneratedAt,
Units: "us",
Timezone: resolved.Timezone,
ValidPeriod: resolved.ValidPeriod,
},
Weekend: &briefing.Weekend{
Days: []briefing.OutlookDay{
{
Date: "2026-05-30",
Temperature: forecast.Range{Max: &high},
MaxPrecipitationProbability: &forecast.TimedValue{
Value: precip,
Time: resolved.ValidPeriod.Start.Add(12 * time.Hour),
},
},
},
},
}
}
type recordingRenderer struct {
renderCalls int
runCalls int