138 lines
4.3 KiB
Go
138 lines
4.3 KiB
Go
package audita
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"path/filepath"
|
|
|
|
"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, false); err != nil {
|
|
return PolishResult{}, err
|
|
}
|
|
return PolishResult{
|
|
ProcessedTranscriptPath: req.OutputProcessedPath,
|
|
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, true); err != nil {
|
|
return PolishResult{}, err
|
|
}
|
|
res := f.Result
|
|
if res.ProcessedTranscriptPath == "" {
|
|
res.ProcessedTranscriptPath = req.OutputProcessedPath
|
|
}
|
|
if res.Reports == (ReportBundle{}) {
|
|
dir := filepath.Dir(req.OutputProcessedPath)
|
|
res.Reports = ReportBundle{
|
|
ErrorsPath: filepath.Join(dir, "errors.yml"),
|
|
RecoveriesPath: filepath.Join(dir, "recoveries.yml"),
|
|
OverviewPath: filepath.Join(dir, "report.md"),
|
|
}
|
|
}
|
|
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, reports bool) error {
|
|
if req.GeneratedConfigPath != "" {
|
|
payload := map[string]any{
|
|
"schema": "audita.generated.v2",
|
|
"placeholder": true,
|
|
"merged_transcript_path": req.MergedTranscriptPath,
|
|
"output_path": req.OutputProcessedPath,
|
|
}
|
|
if err := writeGeneratedYAML(req.GeneratedConfigPath, payload); err != nil {
|
|
return fmt.Errorf("write generated config %q: %w", req.GeneratedConfigPath, err)
|
|
}
|
|
}
|
|
if req.StdoutLogPath != "" {
|
|
if err := fileops.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 := fileops.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 !reports {
|
|
return nil
|
|
}
|
|
for _, report := range []struct{ name, contents string }{
|
|
{"errors.yml", "schema: audita-errors\nversion: 1\nstatus: completed\nerrors: []\n"},
|
|
{"recoveries.yml", "schema: audita-recoveries\nversion: 1\nstatus: completed\nrecoveries: []\n"},
|
|
{"report.md", "# Audita report\n"},
|
|
} {
|
|
path := filepath.Join(filepath.Dir(req.OutputProcessedPath), report.name)
|
|
if err := fileops.WriteFileAtomic(path, []byte(report.contents), fileops.WorkspaceFileMode); err != nil {
|
|
return fmt.Errorf("write report %q: %w", path, 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 := fileops.WriteFileAtomic(path, data, fileops.WorkspaceFileMode); err != nil {
|
|
return fmt.Errorf("write placeholder json %q: %w", path, err)
|
|
}
|
|
return nil
|
|
}
|