Add Seriatim normalize adapter support
This commit is contained in:
@@ -77,10 +77,8 @@ func NewSubprocessRunner(cfg SubprocessRunnerConfig) (*SubprocessRunner, error)
|
||||
if strings.TrimSpace(cfg.OutputSchema) == "" {
|
||||
return nil, fmt.Errorf("seriatim output schema is required")
|
||||
}
|
||||
switch cfg.OutputSchema {
|
||||
case "seriatim-minimal", "seriatim-intermediate", "seriatim-full":
|
||||
default:
|
||||
return nil, fmt.Errorf("seriatim output schema %q is unsupported", cfg.OutputSchema)
|
||||
if err := validateOutputSchema(cfg.OutputSchema); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cfg.CoalesceGap != nil && *cfg.CoalesceGap < 0 {
|
||||
return nil, fmt.Errorf("seriatim coalesce gap must be >= 0")
|
||||
@@ -96,6 +94,15 @@ func NewSubprocessRunner(cfg SubprocessRunnerConfig) (*SubprocessRunner, error)
|
||||
}, nil
|
||||
}
|
||||
|
||||
func validateOutputSchema(schema string) error {
|
||||
switch strings.TrimSpace(schema) {
|
||||
case "seriatim-minimal", "seriatim-intermediate", "seriatim-full":
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("seriatim output schema %q is unsupported", schema)
|
||||
}
|
||||
}
|
||||
|
||||
// Run executes Seriatim merge with deterministic flags and validates output artifacts.
|
||||
func (r *SubprocessRunner) Run(ctx context.Context, req MergeRequest) (MergeResult, error) {
|
||||
if r == nil {
|
||||
@@ -271,6 +278,112 @@ func (r *SubprocessRunner) Trim(ctx context.Context, req TrimRequest) (TrimResul
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Normalize executes Seriatim normalize with deterministic flags and validates output artifacts.
|
||||
func (r *SubprocessRunner) Normalize(ctx context.Context, req NormalizeRequest) (NormalizeResult, error) {
|
||||
if r == nil {
|
||||
return NormalizeResult{}, fmt.Errorf("seriatim subprocess runner is nil")
|
||||
}
|
||||
if strings.TrimSpace(req.InputTranscriptPath) == "" {
|
||||
return NormalizeResult{}, fmt.Errorf("seriatim normalize input path is required")
|
||||
}
|
||||
if strings.TrimSpace(req.OutputNormalizedPath) == "" {
|
||||
return NormalizeResult{}, fmt.Errorf("seriatim normalize output path is required")
|
||||
}
|
||||
|
||||
binary := r.binary
|
||||
if strings.TrimSpace(req.Binary) != "" {
|
||||
binary = strings.TrimSpace(req.Binary)
|
||||
}
|
||||
|
||||
timeout := r.timeout
|
||||
if req.Timeout < 0 {
|
||||
return NormalizeResult{}, fmt.Errorf("seriatim normalize timeout must be >= 0")
|
||||
}
|
||||
if req.Timeout > 0 {
|
||||
timeout = req.Timeout
|
||||
}
|
||||
|
||||
outputSchema := strings.TrimSpace(req.OutputSchema)
|
||||
if outputSchema == "" {
|
||||
outputSchema = r.outputSchema
|
||||
}
|
||||
if err := validateOutputSchema(outputSchema); err != nil {
|
||||
return NormalizeResult{}, err
|
||||
}
|
||||
|
||||
args := buildNormalizeArgs(req, outputSchema)
|
||||
if req.GeneratedConfigPath != "" {
|
||||
if err := writeNormalizeInvocationConfig(req, args, binary, timeout, outputSchema); err != nil {
|
||||
return NormalizeResult{}, fmt.Errorf("write seriatim normalize invocation config %q: %w", req.GeneratedConfigPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
runRes, err := subprocess.Run(ctx, subprocess.RunRequest{
|
||||
Executable: binary,
|
||||
Args: args,
|
||||
Timeout: timeout,
|
||||
StdoutLogPath: req.StdoutLogPath,
|
||||
StderrLogPath: req.StderrLogPath,
|
||||
})
|
||||
if err != nil {
|
||||
return NormalizeResult{
|
||||
OutputNormalizedPath: req.OutputNormalizedPath,
|
||||
ReportPath: req.ReportPath,
|
||||
StdoutLogPath: req.StdoutLogPath,
|
||||
StderrLogPath: req.StderrLogPath,
|
||||
GeneratedConfigPath: req.GeneratedConfigPath,
|
||||
ExitCode: runRes.ExitCode,
|
||||
Duration: runRes.Duration,
|
||||
InvokedBinary: binary,
|
||||
OutputSchema: outputSchema,
|
||||
}, fmt.Errorf("run seriatim normalize (binary=%q): %w", binary, err)
|
||||
}
|
||||
|
||||
if err := validateJSONFileWithSegments(req.OutputNormalizedPath); err != nil {
|
||||
return NormalizeResult{
|
||||
OutputNormalizedPath: req.OutputNormalizedPath,
|
||||
ReportPath: req.ReportPath,
|
||||
StdoutLogPath: req.StdoutLogPath,
|
||||
StderrLogPath: req.StderrLogPath,
|
||||
GeneratedConfigPath: req.GeneratedConfigPath,
|
||||
ExitCode: runRes.ExitCode,
|
||||
Duration: runRes.Duration,
|
||||
InvokedBinary: binary,
|
||||
OutputSchema: outputSchema,
|
||||
}, fmt.Errorf("validate seriatim normalized output %q: %w", req.OutputNormalizedPath, err)
|
||||
}
|
||||
if strings.TrimSpace(req.ReportPath) != "" {
|
||||
if err := validateJSONFile(req.ReportPath); err != nil {
|
||||
return NormalizeResult{
|
||||
OutputNormalizedPath: req.OutputNormalizedPath,
|
||||
ReportPath: req.ReportPath,
|
||||
StdoutLogPath: req.StdoutLogPath,
|
||||
StderrLogPath: req.StderrLogPath,
|
||||
GeneratedConfigPath: req.GeneratedConfigPath,
|
||||
ExitCode: runRes.ExitCode,
|
||||
Duration: runRes.Duration,
|
||||
InvokedBinary: binary,
|
||||
OutputSchema: outputSchema,
|
||||
}, fmt.Errorf("validate seriatim normalize report output %q: %w", req.ReportPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
return NormalizeResult{
|
||||
OutputNormalizedPath: req.OutputNormalizedPath,
|
||||
ReportPath: req.ReportPath,
|
||||
StdoutLogPath: req.StdoutLogPath,
|
||||
StderrLogPath: req.StderrLogPath,
|
||||
GeneratedConfigPath: req.GeneratedConfigPath,
|
||||
ExitCode: runRes.ExitCode,
|
||||
Duration: runRes.Duration,
|
||||
InvokedBinary: binary,
|
||||
OutputSchema: outputSchema,
|
||||
Metadata: map[string]any{
|
||||
"adapter": "seriatim_subprocess",
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *SubprocessRunner) buildMergeArgs(req MergeRequest) []string {
|
||||
args := []string{"merge"}
|
||||
|
||||
@@ -354,6 +467,19 @@ func buildTrimArgs(req TrimRequest) []string {
|
||||
}
|
||||
}
|
||||
|
||||
func buildNormalizeArgs(req NormalizeRequest, outputSchema string) []string {
|
||||
args := []string{
|
||||
"normalize",
|
||||
"--input-file", req.InputTranscriptPath,
|
||||
"--output-file", req.OutputNormalizedPath,
|
||||
"--output-schema", outputSchema,
|
||||
}
|
||||
if strings.TrimSpace(req.ReportPath) != "" {
|
||||
args = append(args, "--report-file", req.ReportPath)
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
func writeTrimInvocationConfig(req TrimRequest, args []string, binary string, timeout time.Duration) error {
|
||||
payload := map[string]any{
|
||||
"schema": "seriatim.generated.v1",
|
||||
@@ -368,6 +494,21 @@ func writeTrimInvocationConfig(req TrimRequest, args []string, binary string, ti
|
||||
return subprocess.WriteYAMLAtomic(req.GeneratedConfigPath, payload, 0o644)
|
||||
}
|
||||
|
||||
func writeNormalizeInvocationConfig(req NormalizeRequest, args []string, binary string, timeout time.Duration, outputSchema string) error {
|
||||
payload := map[string]any{
|
||||
"schema": "seriatim.generated.v1",
|
||||
"command": "normalize",
|
||||
"binary": binary,
|
||||
"args": args,
|
||||
"timeout": timeout.String(),
|
||||
"input_path": req.InputTranscriptPath,
|
||||
"output_path": req.OutputNormalizedPath,
|
||||
"output_schema": outputSchema,
|
||||
"report_path": req.ReportPath,
|
||||
}
|
||||
return subprocess.WriteYAMLAtomic(req.GeneratedConfigPath, payload, 0o644)
|
||||
}
|
||||
|
||||
func validateJSONFile(path string) error {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user