Implement artifact-level render command with Markdown output and update docs

This commit is contained in:
2026-05-24 22:55:56 +00:00
parent a90859114a
commit c37ea70dcb
28 changed files with 1619 additions and 99 deletions

View File

@@ -16,6 +16,8 @@ const (
DefaultInputReader = "json-files"
DefaultOutputModules = "json"
DefaultOutputSchema = OutputSchemaIntermediate
DefaultRenderTitle = "Transcript"
RenderFormatMarkdown = "markdown"
DefaultPreprocessingModules = "validate-raw,normalize-speakers,trim-text"
DefaultPostprocessingModules = "detect-overlaps,resolve-overlaps,backchannel,filler,resolve-danglers,coalesce,detect-overlaps,autocorrect,assign-ids,validate-output"
DefaultOverlapWordRunGap = 1.0
@@ -69,6 +71,17 @@ type NormalizeOptions struct {
OutputModules string
}
// RenderOptions captures raw CLI option values before validation.
type RenderOptions struct {
InputFile string
OutputFile string
Format string
Title string
IncludeTimestamps bool
IncludeSegmentIDs bool
IncludeMetadata bool
}
// Config is the validated runtime configuration for a merge invocation.
type Config struct {
InputFiles []string
@@ -108,6 +121,17 @@ type NormalizeConfig struct {
OutputModules []string
}
// RenderConfig is the validated runtime configuration for a render invocation.
type RenderConfig struct {
InputFile string
OutputFile string
Format string
Title string
IncludeTimestamps bool
IncludeSegmentIDs bool
IncludeMetadata bool
}
// NewMergeConfig validates raw merge options and returns normalized config.
func NewMergeConfig(opts MergeOptions) (Config, error) {
cfg := Config{
@@ -303,6 +327,42 @@ func NewNormalizeConfig(opts NormalizeOptions) (NormalizeConfig, error) {
}, nil
}
// NewRenderConfig validates raw render options and returns normalized config.
func NewRenderConfig(opts RenderOptions) (RenderConfig, error) {
inputFile, err := normalizeSingleInputFile(opts.InputFile, "--input-file")
if err != nil {
return RenderConfig{}, err
}
outputFile, err := normalizeOutputPath(opts.OutputFile, "--output-file")
if err != nil {
return RenderConfig{}, err
}
format := strings.TrimSpace(opts.Format)
if format == "" {
return RenderConfig{}, errors.New("--format is required")
}
if err := validateRenderFormat(format); err != nil {
return RenderConfig{}, err
}
title := strings.TrimSpace(opts.Title)
if title == "" {
title = DefaultRenderTitle
}
return RenderConfig{
InputFile: inputFile,
OutputFile: outputFile,
Format: format,
Title: title,
IncludeTimestamps: opts.IncludeTimestamps,
IncludeSegmentIDs: opts.IncludeSegmentIDs,
IncludeMetadata: opts.IncludeMetadata,
}, nil
}
func parseModuleList(value string) ([]string, error) {
value = strings.TrimSpace(value)
if value == "" {
@@ -485,3 +545,12 @@ func validateNormalizeOutputModules(modules []string) error {
}
return nil
}
func validateRenderFormat(format string) error {
switch format {
case RenderFormatMarkdown:
return nil
default:
return fmt.Errorf("--format must be %q", RenderFormatMarkdown)
}
}