From 950fba17ce4f7fbfb0aaa92ce6fa1a7105cec833 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Sun, 26 Jul 2026 17:14:16 +0000 Subject: [PATCH] Add JSON run result mode --- internal/cli/run.go | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/internal/cli/run.go b/internal/cli/run.go index 1f1d18c..90afe1e 100644 --- a/internal/cli/run.go +++ b/internal/cli/run.go @@ -5,6 +5,7 @@ import ( "crypto/sha256" "encoding/hex" "encoding/json" + "errors" "flag" "fmt" "io" @@ -28,7 +29,7 @@ import ( const defaultConfigPath = "/usr/local/etc/notarius/config.yml" const usage = `Usage: notarius help - notarius run --input path/to/source.json [--config path/to/config.yml] [--output-dir path] [--chunk_cache auto|bypass|refresh] [--resume] [--recompute-step step-id] [--debug [--debug-dir path]] [--only lane-a,lane-b] [--session-id id] [--reference selector=path] [--without-reference selector] + notarius run --input path/to/source.json [--config path/to/config.yml] [--output-dir path] [--json] [--chunk_cache auto|bypass|refresh] [--resume] [--recompute-step step-id] [--debug [--debug-dir path]] [--only lane-a,lane-b] [--session-id id] [--reference selector=path] [--without-reference selector] notarius config validate --config path/to/config.yml [--pipeline pipeline-id] [--only lane-a,lane-b] notarius pipelines list --config path/to/config.yml [--json] ` @@ -132,6 +133,7 @@ func runPipelineCommand(args []string, stdout, stderr io.Writer, opts Options) i inputPath := fs.String("input", "", "source input file path") onlyRaw := fs.String("only", "", "comma-separated artifact lanes") outputDir := fs.String("output-dir", "", "output directory") + machineOutput := fs.Bool("json", false, "write the successful run result as JSON") debug := fs.Bool("debug", false, "write a debug bundle") debugDir := fs.String("debug-dir", "", "debug bundle directory") llmProfile := fs.String("llm-profile", "", "LLM profile override") @@ -415,6 +417,17 @@ func runPipelineCommand(args []string, stdout, stderr io.Writer, opts Options) i if err := writePartialSummary(summary, output); err != nil { return failPipelineCommand(stderr, commandState, terminalWriter, fmt.Errorf("write debug summary: %w", err)) } + var encodedResult []byte + if *machineOutput { + result, err := newRunResult(effective.ResolvedPipeline, output, runOutputDir, debugPath) + if err != nil { + return failPipelineCommand(stderr, commandState, terminalWriter, err) + } + encodedResult, err = encodeRunResult(result) + if err != nil { + return failPipelineCommand(stderr, commandState, terminalWriter, err) + } + } if err := writeOutputFiles(runOutputDir, output.OutputFiles); err != nil { return failPipelineCommand(stderr, commandState, terminalWriter, err) } @@ -422,9 +435,15 @@ func runPipelineCommand(args []string, stdout, stderr io.Writer, opts Options) i return writePipelineCommandFailure(stderr, commandState, primaryErr, persistenceErr) } - fmt.Fprintf(stdout, "pipeline %q complete: outputs=%d rejected=%d output=%s\n", effective.PipelineID, len(output.NormalizeOutputs), len(output.Rejected), runOutputDir) - if debugPath != "" { - fmt.Fprintf(stdout, "debug=%s\n", debugPath) + if *machineOutput { + if err := writeRunResult(stdout, encodedResult); err != nil { + return writePipelineCommandFailure(stderr, commandState, errors.New("write run result"), nil) + } + } else { + fmt.Fprintf(stdout, "pipeline %q complete: outputs=%d rejected=%d output=%s\n", effective.PipelineID, len(output.NormalizeOutputs), len(output.Rejected), runOutputDir) + if debugPath != "" { + fmt.Fprintf(stdout, "debug=%s\n", debugPath) + } } if len(output.Warnings) > 0 { fmt.Fprintf(stderr, "notarius: run completed with %d warning(s)\n", len(output.Warnings))