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

@@ -2,8 +2,8 @@
## Purpose
Describes public artifact conversion and validation internals for merge output,
trim, and normalize.
Describes implemented artifact parsing, conversion, validation, and render-model
normalization internals.
## Artifact contracts
@@ -19,35 +19,40 @@ Machine-readable schemas:
- `schema/intermediate-output.schema.json`
- `schema/minimal-output.schema.json`
## Schema selection
## Shared output-artifact parser
Merge pipeline conversion uses `internal/artifact.SelectedFromMerged`:
`internal/artifact/output_artifact.go` provides schema-aware parsing for
existing seriatim output artifacts.
Behavior:
- accepts only valid full, intermediate, or minimal seriatim output artifacts
- validates through `schema` semantic + JSON schema checks
- rejects malformed JSON
- rejects raw WhisperX-style JSON and other non-seriatim shapes
Consumers:
- `internal/trim` artifact-level trim flow
- `internal/render` artifact-level render flow
## Merge conversion behavior
`internal/artifact/transcript.go` converts `model.MergedTranscript` to public
contracts:
- full schema preserves source/provenance, overlap groups, and metadata module
lists
- intermediate schema emits segment timing/text/speaker with optional
categories and compact metadata
- minimal schema emits compact segment timing/text/speaker and compact metadata
Schema selection uses `internal/artifact.SelectedFromMerged`:
- `seriatim-full` -> `artifact.FromMerged`
- `seriatim-intermediate` -> `artifact.IntermediateFromMerged`
- `seriatim-minimal` -> `artifact.MinimalFromMerged`
Unknown/empty selection falls back to intermediate conversion.
## Merge conversion behavior
`internal/artifact` converts `model.MergedTranscript` to public contracts:
- full schema preserves source/provenance, overlap groups, and metadata module
lists.
- intermediate schema emits segment timing/text/speaker with optional
categories and compact metadata.
- minimal schema emits compact segment timing/text/speaker and compact
metadata.
## Validation behavior
`schema/output.go` validates both structure and semantics:
- embedded JSON Schema validation via `jsonschema/v6`
- semantic checks for sequential segment IDs starting at `1`
- semantic checks for non-inverted segment timing (`end >= start`)
- full schema overlap-group timing checks (`group.end >= group.start`)
- unknown/empty -> intermediate fallback
## Trim internals
@@ -72,9 +77,8 @@ Apply layer (`apply.go`):
- schema-specific segment reconstruction for full/intermediate/minimal outputs
- overlap-group recomputation only for full-schema outputs
Artifact layer (`artifact.go`):
Artifact conversion layer (`artifact.go`):
- schema detection for full/intermediate/minimal artifacts
- schema-preserving trim application
- supported schema conversions:
- full -> intermediate/minimal
@@ -85,10 +89,10 @@ Artifact layer (`artifact.go`):
Trim invariants:
- selected IDs must exist in input.
- input IDs must be positive, unique, sequential.
- retained segment order follows input transcript order.
- output IDs are reassigned to `1..N`.
- selected IDs must exist in input
- input IDs must be positive, unique, sequential
- retained segment order follows input transcript order
- output IDs are reassigned to `1..N`
## Normalize internals
@@ -117,13 +121,64 @@ Run layer (`normalize.go`):
Normalize invariant:
- report events do not embed transcript text.
- report events do not embed transcript text
## Render internals
`internal/render` is an artifact-level, downstream-only renderer.
Model normalization (`normalize.go`):
- converts full/intermediate/minimal artifacts into a common render model
- preserves segment order and segment IDs
- normalizes per-segment fields to ID, start, end, speaker, text, categories
- emits empty categories slice when categories are absent in input
Renderer registry (`registry.go`):
- resolves renderers by public format name
- currently registers `markdown`
Markdown renderer (`markdown.go`):
- writes title header `# {title}`
- renders optional `[HH:MM:SSHH:MM:SS]` timestamps
- renders optional `[#id]` segment references
- renders `**speaker:** text`
- italicizes text when categories include `background`, `backchannel`, or
`filler`
- ignores unknown categories
- optionally includes metadata summary block
Run layer (`run.go`):
1. Read input artifact JSON.
2. Parse via shared output-artifact parser.
3. Normalize to render model.
4. Resolve renderer by `--format`.
5. Render text output.
6. Write output file.
Render invariants:
- does not run merge/trim/normalize modules
- does not expose report output
- deterministic for identical input artifact and render flags
## Validation behavior
`schema/output.go` validates both structure and semantics:
- embedded JSON Schema validation via `jsonschema/v6`
- semantic checks for sequential segment IDs starting at `1`
- semantic checks for non-inverted segment timing (`end >= start`)
- full schema overlap-group timing checks (`group.end >= group.start`)
## Boundaries
- CLI flag semantics belong to `docs/cli.md`.
- Runtime config/env surfaces belong to `docs/config.md`.
- This doc describes internal conversion/validation behavior only.
- This document describes internal conversion/validation behavior only.
## Failure behavior
@@ -133,22 +188,29 @@ Representative failure classes:
- schema validation failure for parsed artifact or built output
- unsupported schema conversion path (trim)
- selector or input-ID consistency errors (trim)
- unsupported renderer format (render)
- output/report file write failures from command paths
## Tests to inspect before changes
- `schema/output_test.go`
- `internal/artifact/transcript_test.go`
- `internal/artifact/output_artifact_test.go`
- `internal/trim/selector_test.go`
- `internal/trim/artifact_test.go`
- `internal/trim/apply_test.go`
- `internal/normalize/parse_test.go`
- `internal/render/normalize_test.go`
- `internal/render/markdown_test.go`
- `internal/render/registry_test.go`
- `internal/cli/trim_test.go`
- `internal/cli/normalize_test.go`
- `internal/cli/render_test.go`
## Invariants
- Public artifacts are validated through `schema` before acceptance.
- Segment IDs in emitted artifacts are sequential and deterministic.
- Internal-only fields are not emitted in minimal/intermediate contracts.
- Trim and normalize stay artifact-level and do not execute merge modules.
- Trim, normalize, and render stay artifact-level and do not execute merge
modules.

View File

@@ -73,7 +73,8 @@ coalesce gap and overlap thresholds).
- Pipeline does not parse CLI flags.
- Pipeline does not normalize raw CLI strings.
- Pipeline delegates conversion to public output contracts to `internal/artifact`.
- Artifact-level commands `trim` and `normalize` are outside this pipeline.
- Artifact-level commands `trim`, `normalize`, and `render` are outside this
pipeline.
## Failure behavior