Files
narratio/internal/adapters/audita/fake.go

132 lines
3.9 KiB
Go

package audita
import (
"context"
"encoding/json"
"fmt"
"path/filepath"
"gitea.maximumdirect.net/eric/narratio/internal/adapters/subprocess"
"gitea.maximumdirect.net/eric/narratio/internal/fileops"
)
// NoopRunner is a deterministic no-op audita adapter.
type NoopRunner struct{}
// Run returns requested output path with placeholder metadata.
func (n *NoopRunner) Run(ctx context.Context, req PolishRequest) (PolishResult, error) {
if err := ctx.Err(); err != nil {
return PolishResult{}, err
}
if err := materializePlaceholders(req); err != nil {
return PolishResult{}, err
}
return PolishResult{
ProcessedTranscriptPath: req.OutputProcessedPath,
ReportPath: req.ReportPath,
WorkDir: req.WorkDir,
StdoutLogPath: req.StdoutLogPath,
StderrLogPath: req.StderrLogPath,
GeneratedConfigPath: req.GeneratedConfigPath,
Metadata: map[string]any{"placeholder": true},
}, nil
}
// FakeRunner captures polish requests and returns deterministic responses.
type FakeRunner struct {
Requests []PolishRequest
Err error
Result PolishResult
}
// Run records request and returns configured response.
func (f *FakeRunner) Run(ctx context.Context, req PolishRequest) (PolishResult, error) {
if err := ctx.Err(); err != nil {
return PolishResult{}, err
}
f.Requests = append(f.Requests, req)
if f.Err != nil {
return PolishResult{}, f.Err
}
if err := materializePlaceholders(req); err != nil {
return PolishResult{}, err
}
res := f.Result
if res.ProcessedTranscriptPath == "" {
res.ProcessedTranscriptPath = req.OutputProcessedPath
}
if res.ReportPath == "" {
res.ReportPath = req.ReportPath
}
if res.WorkDir == "" {
res.WorkDir = req.WorkDir
}
if res.StdoutLogPath == "" {
res.StdoutLogPath = req.StdoutLogPath
}
if res.StderrLogPath == "" {
res.StderrLogPath = req.StderrLogPath
}
if res.GeneratedConfigPath == "" {
res.GeneratedConfigPath = req.GeneratedConfigPath
}
if res.Metadata == nil {
res.Metadata = map[string]any{"fake": true}
}
return res, nil
}
func materializePlaceholders(req PolishRequest) error {
if req.GeneratedConfigPath != "" {
payload := map[string]any{
"schema": "audita.generated.v1",
"placeholder": true,
"merged_transcript_path": req.MergedTranscriptPath,
"output_path": req.OutputProcessedPath,
}
if err := subprocess.WriteYAMLAtomic(req.GeneratedConfigPath, payload, fileops.WorkspaceFileMode); err != nil {
return fmt.Errorf("write generated config %q: %w", req.GeneratedConfigPath, err)
}
}
if req.StdoutLogPath != "" {
if err := subprocess.WriteFileAtomic(req.StdoutLogPath, []byte("audita noop/fake stdout placeholder\n"), fileops.WorkspaceFileMode); err != nil {
return fmt.Errorf("write stdout log %q: %w", req.StdoutLogPath, err)
}
}
if req.StderrLogPath != "" {
if err := subprocess.WriteFileAtomic(req.StderrLogPath, []byte("audita noop/fake stderr placeholder\n"), fileops.WorkspaceFileMode); err != nil {
return fmt.Errorf("write stderr log %q: %w", req.StderrLogPath, err)
}
}
if err := writeJSONIfRequested(req.OutputProcessedPath, map[string]any{
"schema": "audita.processed.v1",
"segments": []any{},
}); err != nil {
return err
}
if err := writeJSONIfRequested(req.ReportPath, map[string]any{
"schema": "audita.report.v1",
"steps": []any{},
}); err != nil {
return err
}
return nil
}
func writeJSONIfRequested(path string, payload any) error {
if path == "" {
return nil
}
if err := fileops.EnsureWorkspaceDirectory(filepath.Dir(path)); err != nil {
return fmt.Errorf("create parent directory %q: %w", filepath.Dir(path), err)
}
data, err := json.Marshal(payload)
if err != nil {
return fmt.Errorf("marshal placeholder json for %q: %w", path, err)
}
if err := subprocess.WriteFileAtomic(path, data, fileops.WorkspaceFileMode); err != nil {
return fmt.Errorf("write placeholder json %q: %w", path, err)
}
return nil
}