2026-05-24 13:38:27 +00:00
|
|
|
|
# Artifact Internals
|
|
|
|
|
|
|
|
|
|
|
|
## Purpose
|
|
|
|
|
|
|
2026-05-24 22:55:56 +00:00
|
|
|
|
Describes implemented artifact parsing, conversion, validation, and render-model
|
|
|
|
|
|
normalization internals.
|
2026-05-24 13:38:27 +00:00
|
|
|
|
|
|
|
|
|
|
## Artifact contracts
|
|
|
|
|
|
|
|
|
|
|
|
Public contracts live in `schema/`:
|
|
|
|
|
|
|
|
|
|
|
|
- full: `schema.Transcript`
|
|
|
|
|
|
- intermediate: `schema.IntermediateTranscript`
|
|
|
|
|
|
- minimal: `schema.MinimalTranscript`
|
|
|
|
|
|
|
|
|
|
|
|
Machine-readable schemas:
|
|
|
|
|
|
|
|
|
|
|
|
- `schema/full-output.schema.json`
|
|
|
|
|
|
- `schema/intermediate-output.schema.json`
|
|
|
|
|
|
- `schema/minimal-output.schema.json`
|
|
|
|
|
|
|
2026-05-24 22:55:56 +00:00
|
|
|
|
## Shared output-artifact parser
|
2026-05-24 13:38:27 +00:00
|
|
|
|
|
2026-05-24 22:55:56 +00:00
|
|
|
|
`internal/artifact/output_artifact.go` provides schema-aware parsing for
|
|
|
|
|
|
existing seriatim output artifacts.
|
2026-05-24 13:38:27 +00:00
|
|
|
|
|
2026-05-24 22:55:56 +00:00
|
|
|
|
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:
|
2026-05-24 13:38:27 +00:00
|
|
|
|
|
2026-05-24 22:55:56 +00:00
|
|
|
|
- `internal/trim` artifact-level trim flow
|
|
|
|
|
|
- `internal/render` artifact-level render flow
|
2026-05-24 13:38:27 +00:00
|
|
|
|
|
|
|
|
|
|
## Merge conversion behavior
|
|
|
|
|
|
|
2026-05-24 22:55:56 +00:00
|
|
|
|
`internal/artifact/transcript.go` converts `model.MergedTranscript` to public
|
|
|
|
|
|
contracts:
|
2026-05-24 13:38:27 +00:00
|
|
|
|
|
|
|
|
|
|
- full schema preserves source/provenance, overlap groups, and metadata module
|
2026-05-24 22:55:56 +00:00
|
|
|
|
lists
|
2026-05-24 13:38:27 +00:00
|
|
|
|
- intermediate schema emits segment timing/text/speaker with optional
|
2026-05-24 22:55:56 +00:00
|
|
|
|
categories and compact metadata
|
|
|
|
|
|
- minimal schema emits compact segment timing/text/speaker and compact metadata
|
2026-05-24 13:38:27 +00:00
|
|
|
|
|
2026-05-24 22:55:56 +00:00
|
|
|
|
Schema selection uses `internal/artifact.SelectedFromMerged`:
|
2026-05-24 13:38:27 +00:00
|
|
|
|
|
2026-05-24 22:55:56 +00:00
|
|
|
|
- `seriatim-full` -> `artifact.FromMerged`
|
|
|
|
|
|
- `seriatim-intermediate` -> `artifact.IntermediateFromMerged`
|
|
|
|
|
|
- `seriatim-minimal` -> `artifact.MinimalFromMerged`
|
|
|
|
|
|
- unknown/empty -> intermediate fallback
|
2026-05-24 13:38:27 +00:00
|
|
|
|
|
|
|
|
|
|
## Trim internals
|
|
|
|
|
|
|
2026-05-24 15:11:11 +00:00
|
|
|
|
`internal/trim` handles artifact-level projection and does not execute merge
|
|
|
|
|
|
pipeline modules.
|
2026-05-24 13:38:27 +00:00
|
|
|
|
|
2026-05-24 15:11:11 +00:00
|
|
|
|
Run layer (`run.go`):
|
2026-05-24 13:38:27 +00:00
|
|
|
|
|
2026-05-24 15:11:11 +00:00
|
|
|
|
1. Parse selector from validated config.
|
|
|
|
|
|
2. Read and parse input artifact JSON.
|
|
|
|
|
|
3. Apply trim projection through schema-aware artifact handling.
|
|
|
|
|
|
4. Resolve output schema (preserve input schema unless overridden).
|
|
|
|
|
|
5. Validate output artifact.
|
|
|
|
|
|
6. Write output JSON.
|
|
|
|
|
|
7. Optionally write report JSON with `trim-audit`.
|
|
|
|
|
|
|
|
|
|
|
|
Apply layer (`apply.go`):
|
|
|
|
|
|
|
|
|
|
|
|
- one shared projection policy for selector mode, input ID validation, selected
|
|
|
|
|
|
ID existence checks, keep/remove filtering, removed IDs, and old-to-new ID
|
|
|
|
|
|
mappings
|
|
|
|
|
|
- schema-specific segment reconstruction for full/intermediate/minimal outputs
|
|
|
|
|
|
- overlap-group recomputation only for full-schema outputs
|
|
|
|
|
|
|
2026-05-24 22:55:56 +00:00
|
|
|
|
Artifact conversion layer (`artifact.go`):
|
2026-05-24 15:11:11 +00:00
|
|
|
|
|
|
|
|
|
|
- schema-preserving trim application
|
|
|
|
|
|
- supported schema conversions:
|
|
|
|
|
|
- full -> intermediate/minimal
|
|
|
|
|
|
- intermediate -> minimal
|
|
|
|
|
|
- minimal -> intermediate
|
|
|
|
|
|
- rejected conversion:
|
|
|
|
|
|
- intermediate/minimal -> full
|
2026-05-24 13:38:27 +00:00
|
|
|
|
|
|
|
|
|
|
Trim invariants:
|
|
|
|
|
|
|
2026-05-24 22:55:56 +00:00
|
|
|
|
- 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`
|
2026-05-24 13:38:27 +00:00
|
|
|
|
|
|
|
|
|
|
## Normalize internals
|
|
|
|
|
|
|
|
|
|
|
|
`internal/normalize` canonicalizes transcript-like JSON input into a selected
|
|
|
|
|
|
public schema.
|
|
|
|
|
|
|
|
|
|
|
|
Parse layer (`parse.go`):
|
|
|
|
|
|
|
|
|
|
|
|
- accepts object-with-`segments` or bare segment array
|
|
|
|
|
|
- repairs missing timing deterministically
|
|
|
|
|
|
- swaps inverted timing
|
|
|
|
|
|
- fills missing/blank speaker with `Unknown_Speaker`
|
|
|
|
|
|
- drops missing/blank text segments
|
|
|
|
|
|
|
|
|
|
|
|
Build layer (`build.go`):
|
|
|
|
|
|
|
|
|
|
|
|
- sorts deterministically by `(start, end, input_index, speaker)`
|
|
|
|
|
|
- reassigns output IDs sequentially
|
|
|
|
|
|
- builds minimal/intermediate/full output shape
|
|
|
|
|
|
- validates selected output schema before write
|
|
|
|
|
|
|
|
|
|
|
|
Run layer (`normalize.go`):
|
|
|
|
|
|
|
|
|
|
|
|
- writes output JSON
|
|
|
|
|
|
- optionally writes report with `normalize-audit`
|
|
|
|
|
|
|
|
|
|
|
|
Normalize invariant:
|
|
|
|
|
|
|
2026-05-24 22:55:56 +00:00
|
|
|
|
- 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:SS–HH: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`)
|
2026-05-24 13:38:27 +00:00
|
|
|
|
|
|
|
|
|
|
## Boundaries
|
|
|
|
|
|
|
|
|
|
|
|
- CLI flag semantics belong to `docs/cli.md`.
|
|
|
|
|
|
- Runtime config/env surfaces belong to `docs/config.md`.
|
2026-05-24 22:55:56 +00:00
|
|
|
|
- This document describes internal conversion/validation behavior only.
|
2026-05-24 13:38:27 +00:00
|
|
|
|
|
|
|
|
|
|
## Failure behavior
|
|
|
|
|
|
|
|
|
|
|
|
Representative failure classes:
|
|
|
|
|
|
|
|
|
|
|
|
- malformed or unsupported input JSON shape
|
|
|
|
|
|
- schema validation failure for parsed artifact or built output
|
|
|
|
|
|
- unsupported schema conversion path (trim)
|
|
|
|
|
|
- selector or input-ID consistency errors (trim)
|
2026-05-24 22:55:56 +00:00
|
|
|
|
- unsupported renderer format (render)
|
2026-05-24 13:38:27 +00:00
|
|
|
|
- output/report file write failures from command paths
|
|
|
|
|
|
|
|
|
|
|
|
## Tests to inspect before changes
|
|
|
|
|
|
|
|
|
|
|
|
- `schema/output_test.go`
|
|
|
|
|
|
- `internal/artifact/transcript_test.go`
|
2026-05-24 22:55:56 +00:00
|
|
|
|
- `internal/artifact/output_artifact_test.go`
|
2026-05-24 13:38:27 +00:00
|
|
|
|
- `internal/trim/selector_test.go`
|
|
|
|
|
|
- `internal/trim/artifact_test.go`
|
|
|
|
|
|
- `internal/trim/apply_test.go`
|
|
|
|
|
|
- `internal/normalize/parse_test.go`
|
2026-05-24 22:55:56 +00:00
|
|
|
|
- `internal/render/normalize_test.go`
|
|
|
|
|
|
- `internal/render/markdown_test.go`
|
|
|
|
|
|
- `internal/render/registry_test.go`
|
2026-05-24 13:38:27 +00:00
|
|
|
|
- `internal/cli/trim_test.go`
|
|
|
|
|
|
- `internal/cli/normalize_test.go`
|
2026-05-24 22:55:56 +00:00
|
|
|
|
- `internal/cli/render_test.go`
|
2026-05-24 13:38:27 +00:00
|
|
|
|
|
|
|
|
|
|
## 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.
|
2026-05-24 22:55:56 +00:00
|
|
|
|
- Trim, normalize, and render stay artifact-level and do not execute merge
|
|
|
|
|
|
modules.
|