package seriatim import ( "context" "fmt" "gitea.maximumdirect.net/eric/narratio/internal/adapters/subprocess" ) // NoopRunner is a deterministic no-op seriatim adapter. type NoopRunner struct{} // Run returns the requested output path with placeholder metadata. func (n *NoopRunner) Run(ctx context.Context, req MergeRequest) (MergeResult, error) { if err := ctx.Err(); err != nil { return MergeResult{}, err } if err := materializePlaceholders(req); err != nil { return MergeResult{}, err } return MergeResult{ MergedTranscriptPath: req.OutputMergedTranscriptPath, ReportPath: req.ReportPath, StdoutLogPath: req.StdoutLogPath, StderrLogPath: req.StderrLogPath, GeneratedConfigPath: req.GeneratedConfigPath, InvokedBinary: "noop", Metadata: map[string]any{"placeholder": true}, }, nil } // FakeRunner captures merge requests and returns deterministic responses. type FakeRunner struct { Requests []MergeRequest Err error Result MergeResult } // Run records request and returns configured response. func (f *FakeRunner) Run(ctx context.Context, req MergeRequest) (MergeResult, error) { if err := ctx.Err(); err != nil { return MergeResult{}, err } f.Requests = append(f.Requests, req) if f.Err != nil { return MergeResult{}, f.Err } if err := materializePlaceholders(req); err != nil { return MergeResult{}, err } res := f.Result if res.MergedTranscriptPath == "" { res.MergedTranscriptPath = req.OutputMergedTranscriptPath } if res.ReportPath == "" { res.ReportPath = req.ReportPath } if res.StdoutLogPath == "" { res.StdoutLogPath = req.StdoutLogPath } if res.StderrLogPath == "" { res.StderrLogPath = req.StderrLogPath } if res.GeneratedConfigPath == "" { res.GeneratedConfigPath = req.GeneratedConfigPath } if res.InvokedBinary == "" { res.InvokedBinary = "fake" } if res.Metadata == nil { res.Metadata = map[string]any{"fake": true} } return res, nil } func materializePlaceholders(req MergeRequest) error { if req.OutputMergedTranscriptPath != "" { if err := subprocess.WriteFileAtomic(req.OutputMergedTranscriptPath, []byte(`{"schema":"seriatim.intermediate.v1","segments":[]}`), 0o644); err != nil { return fmt.Errorf("write merged transcript %q: %w", req.OutputMergedTranscriptPath, err) } } if req.GeneratedConfigPath != "" { payload := map[string]any{ "schema": "seriatim.generated.v1", "placeholder": true, "input_transcript_paths": req.InputTranscriptPaths, "output_path": req.OutputMergedTranscriptPath, } if err := subprocess.WriteYAMLAtomic(req.GeneratedConfigPath, payload, 0o644); err != nil { return fmt.Errorf("write generated config %q: %w", req.GeneratedConfigPath, err) } } if req.StdoutLogPath != "" { if err := subprocess.WriteFileAtomic(req.StdoutLogPath, []byte("seriatim noop/fake stdout placeholder\n"), 0o644); err != nil { return fmt.Errorf("write stdout log %q: %w", req.StdoutLogPath, err) } } if req.StderrLogPath != "" { if err := subprocess.WriteFileAtomic(req.StderrLogPath, []byte("seriatim noop/fake stderr placeholder\n"), 0o644); err != nil { return fmt.Errorf("write stderr log %q: %w", req.StderrLogPath, err) } } if req.ReportPath != "" { if err := subprocess.WriteFileAtomic(req.ReportPath, []byte(`{"schema":"seriatim.report.v1","placeholder":true}`), 0o644); err != nil { return fmt.Errorf("write report %q: %w", req.ReportPath, err) } } return nil }