Write reports to operator-selected outputs

This commit is contained in:
2026-08-01 19:33:12 +00:00
parent ac8d618111
commit 62a12dd661
17 changed files with 393 additions and 94 deletions

View File

@@ -101,6 +101,11 @@ func TestRunnerHelpListsOnlySupportedCommands(t *testing.T) {
t.Fatalf("help contains retired command %q:\n%s", retired, output.stdout)
}
}
for _, description := range []string{"Write the generated Markdown report to PATH.", "Write generated Markdown reports beneath PATH"} {
if !strings.Contains(output.stdout, description) {
t.Fatalf("help missing output description %q:\n%s", description, output.stdout)
}
}
}
func TestRunnerVersion(t *testing.T) {
@@ -185,6 +190,7 @@ func TestResolveSupportedCommandsAndFlags(t *testing.T) {
func TestResolveGenerateAndRunApplySharedActionFlags(t *testing.T) {
configPath := writeCLIConfig(t, t.TempDir(), "")
runner, _ := countingRunner(cliExecutor{})
runner.WorkingDir = t.TempDir()
generate, generateOpts, err := runner.resolveGenerateAction([]string{
"daily", "--config", configPath, "--date", "2026-05-30", "--units", "metric", "--tz", "UTC",
@@ -193,7 +199,7 @@ func TestResolveGenerateAndRunApplySharedActionFlags(t *testing.T) {
if err != nil {
t.Fatalf("resolveGenerateAction() error = %v", err)
}
if generate.Config.WeatherAPI.Units != "metric" || generate.Config.WeatherAPI.Timezone != "UTC" || generate.OutputPath != "daily.md" || generate.LLMDebugDir != "/safe/debug" || !generateOpts.Quiet {
if generate.Config.WeatherAPI.Units != "metric" || generate.Config.WeatherAPI.Timezone != "UTC" || generate.OutputPath != filepath.Join(runner.WorkingDir, "daily.md") || generate.WorkingDir != runner.WorkingDir || generate.LLMDebugDir != "/safe/debug" || !generateOpts.Quiet {
t.Fatalf("generate request/options = %#v/%#v", generate, generateOpts)
}
if got := generate.Date.Format(timeutil.DateLayout); got != "2026-05-30" {
@@ -207,7 +213,7 @@ func TestResolveGenerateAndRunApplySharedActionFlags(t *testing.T) {
if err != nil {
t.Fatalf("resolveRunAction() error = %v", err)
}
if batch.Config.WeatherAPI.Units != "metric" || batch.Config.WeatherAPI.Timezone != "UTC" || batch.OutputDir != "reports" || batch.LLMDebugDir != "/safe/debug" || !batchOpts.Quiet {
if batch.Config.WeatherAPI.Units != "metric" || batch.Config.WeatherAPI.Timezone != "UTC" || batch.OutputDir != filepath.Join(runner.WorkingDir, "reports") || batch.WorkingDir != runner.WorkingDir || batch.LLMDebugDir != "/safe/debug" || !batchOpts.Quiet {
t.Fatalf("batch request/options = %#v/%#v", batch, batchOpts)
}
}
@@ -280,6 +286,7 @@ func TestRunnerSuccessfulSingleAndBatchActions(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
fixture := newCLIFixture(t)
runner, constructions := countingRunner(cliExecutor{})
runner.WorkingDir = t.TempDir()
output, err := runCLICommand(runner, tt.args(fixture.configPath, fixture.path("copies"))...)
if err != nil {
t.Fatalf("Run() error = %v", err)
@@ -314,6 +321,7 @@ func TestRunnerSuccessfulSingleAndBatchActions(t *testing.T) {
func TestRunnerPreRunFailureAndQuietMode(t *testing.T) {
runner, constructions := countingRunner(cliExecutor{})
runner.WorkingDir = t.TempDir()
output, err := runCLICommand(runner, "generate", "daily")
if err == nil || output.stdout != "" || output.stderr != "" {
t.Fatalf("pre-run output/error = %#v/%v, want error without summary", output, err)
@@ -324,6 +332,7 @@ func TestRunnerPreRunFailureAndQuietMode(t *testing.T) {
fixture := newCLIFixture(t)
runner, _ = countingRunner(cliExecutor{})
runner.WorkingDir = t.TempDir()
output, err = runCLICommand(runner, "generate", "today", "--config", fixture.configPath, "--quiet")
if err != nil || output.stdout != "" || output.stderr != "" {
t.Fatalf("quiet output/error = %#v/%v", output, err)
@@ -333,6 +342,7 @@ func TestRunnerPreRunFailureAndQuietMode(t *testing.T) {
func TestRunnerFailedActionReportsSafePartialSummary(t *testing.T) {
fixture := newCLIFixture(t)
runner, constructions := countingRunner(cliExecutor{fail: true})
runner.WorkingDir = t.TempDir()
output, err := runCLICommand(runner, "generate", "today", "--config", fixture.configPath)
if err == nil {
t.Fatal("Run() error = nil, want execution failure")
@@ -364,6 +374,7 @@ func TestRunnerFailedActionReportsSafePartialSummary(t *testing.T) {
func TestRunnerMixedBatchReportsSafePartialFailure(t *testing.T) {
fixture := newCLIFixture(t)
runner, constructions := countingRunner(cliExecutor{failPrompt: "weather.tomorrow_generated_text"})
runner.WorkingDir = t.TempDir()
output, err := runCLICommand(runner, "run", "morning", "--config", fixture.configPath)
if err == nil {
t.Fatal("Run() error = nil, want aggregate batch failure")
@@ -399,6 +410,7 @@ func TestRunnerMixedBatchReportsSafePartialFailure(t *testing.T) {
func TestRunnerInspectsReportsAndCurrentArtifacts(t *testing.T) {
fixture := newCLIFixture(t)
runner, _ := countingRunner(cliExecutor{})
runner.WorkingDir = t.TempDir()
first := runSuccessfulGenerate(t, runner, fixture.configPath, time.Date(2026, 5, 29, 11, 0, 0, 0, time.UTC))
second := runSuccessfulGenerate(t, runner, fixture.configPath, time.Date(2026, 5, 29, 12, 0, 0, 0, time.UTC))