Compare commits
7 Commits
v1.3.0
...
d23a95471c
| Author | SHA1 | Date | |
|---|---|---|---|
| d23a95471c | |||
| f8ab117bfc | |||
| 88018c9e76 | |||
| b3e7dc3136 | |||
| 385c62a5b4 | |||
| 7d9bf33d18 | |||
| b7cc5fb980 |
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2026 eric.
|
||||
Copyright (c) 2026 Eric Rakestraw.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
|
||||
536
README.md
536
README.md
@@ -1,513 +1,45 @@
|
||||
# seriatim
|
||||
|
||||
`seriatim` merges per-speaker WhisperX-style JSON transcripts into a single JSON transcript that preserves speaker identity and chronological order. It also trims existing seriatim output artifacts by segment ID and normalizes external transcript-like JSON into standard seriatim output schemas.
|
||||
`seriatim` is a Go CLI for transcript artifact processing.
|
||||
|
||||
The current implementation supports the `merge`, `trim`, and `normalize` commands. `merge` reads one or more input JSON files, optionally maps each input file to a canonical speaker using `speakers.yml`, sorts all segments by timestamp, detects and resolves overlaps when word-level timing is available, assigns consecutive numeric `id` values, and writes a merged JSON artifact. `trim` reads an existing seriatim output artifact and projects it to a retained segment subset. `normalize` reads transcript-like JSON input, validates required segment fields, sorts deterministically, assigns fresh IDs, and emits a selected seriatim output schema.
|
||||
It merges per-speaker WhisperX-style JSON into one deterministic transcript, trims existing seriatim artifacts by segment ID, and normalizes transcript-like JSON into standard seriatim output schemas.
|
||||
|
||||
## Usage
|
||||
## Quickstart
|
||||
|
||||
Run from source:
|
||||
Shortest useful merge command:
|
||||
|
||||
```sh
|
||||
go run ./cmd/seriatim merge \
|
||||
--input-file samples/raw/2026-04-19-Eric_Rakestraw.json \
|
||||
--input-file samples/raw/2026-04-19-Mike_Brown.json \
|
||||
--input-file speaker-a.json \
|
||||
--input-file speaker-b.json \
|
||||
--output-file merged.json
|
||||
```
|
||||
|
||||
Optional report output:
|
||||
|
||||
```sh
|
||||
go run ./cmd/seriatim merge \
|
||||
--input-file eric.json \
|
||||
--input-file mike.json \
|
||||
--output-file merged.json \
|
||||
--report-file report.json
|
||||
```
|
||||
|
||||
Trim an existing seriatim artifact:
|
||||
|
||||
```sh
|
||||
go run ./cmd/seriatim trim \
|
||||
--input-file merged.json \
|
||||
--output-file trimmed.json \
|
||||
--keep "1-10, 15, 20-25"
|
||||
```
|
||||
|
||||
Normalize external transcript-style JSON:
|
||||
|
||||
```sh
|
||||
go run ./cmd/seriatim normalize \
|
||||
--input-file transcript.json \
|
||||
--output-file normalized.json
|
||||
```
|
||||
|
||||
Normalize an Audita-style bare segment array to full schema with report output:
|
||||
|
||||
```sh
|
||||
go run ./cmd/seriatim normalize \
|
||||
--input-file audita-segments.json \
|
||||
--output-file normalized-full.json \
|
||||
--output-schema seriatim-full \
|
||||
--report-file normalize-report.json
|
||||
```
|
||||
|
||||
## CLI
|
||||
|
||||
```text
|
||||
seriatim merge [flags]
|
||||
seriatim trim [flags]
|
||||
seriatim normalize [flags]
|
||||
```
|
||||
|
||||
Global flags:
|
||||
|
||||
| Flag | Description |
|
||||
| --- | --- |
|
||||
| `--help` | Show command help. |
|
||||
| `--version` | Show application version. Local builds default to `dev`; release builds inject the release version. |
|
||||
|
||||
`merge` flags:
|
||||
|
||||
| Flag | Required | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--input-file` | Yes | none | Input transcript JSON file. Repeat once per speaker/input file. |
|
||||
| `--output-file` | Yes | none | Merged transcript JSON output path. |
|
||||
| `--report-file` | No | none | Optional report JSON output path. |
|
||||
| `--speakers` | No | none | Speaker map YAML file. When omitted, input file basenames are used as speaker labels. |
|
||||
| `--autocorrect` | No | none | Autocorrect rules YAML file. When omitted, the default `autocorrect` module leaves text unchanged. |
|
||||
| `--input-reader` | No | `json-files` | Input reader module. |
|
||||
| `--output-modules` | No | `json` | Comma-separated output modules. |
|
||||
| `--output-schema` | No | `seriatim-intermediate` | JSON output contract. Allowed values are `seriatim-minimal`, `seriatim-intermediate`, and `seriatim-full`. If omitted, the runtime default is used; consumers that depend on a specific shape should set this explicitly. |
|
||||
| `--preprocessing-modules` | No | `validate-raw,normalize-speakers,trim-text` | Comma-separated preprocessing modules, evaluated in order. |
|
||||
| `--postprocessing-modules` | No | `detect-overlaps,resolve-overlaps,backchannel,filler,resolve-danglers,coalesce,detect-overlaps,autocorrect,assign-ids,validate-output` | Comma-separated postprocessing modules, evaluated in order. |
|
||||
| `--coalesce-gap` | No | `3.0` | Maximum same-speaker gap in seconds for `coalesce`; also used as the `resolve-overlaps` context window. Must be a non-negative float. |
|
||||
|
||||
`trim` flags:
|
||||
|
||||
| Flag | Required | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--input-file` | Yes | none | Input seriatim output artifact JSON file. |
|
||||
| `--output-file` | Yes | none | Trimmed transcript JSON output path. |
|
||||
| `--keep` | Exactly one of `--keep` or `--remove` is required | none | Segment ID selector to retain. |
|
||||
| `--remove` | Exactly one of `--keep` or `--remove` is required | none | Segment ID selector to drop. |
|
||||
| `--output-schema` | No | preserve input artifact schema | Optional output schema override: `seriatim-minimal`, `seriatim-intermediate`, or `seriatim-full`. |
|
||||
| `--report-file` | No | none | Optional report JSON output path. |
|
||||
| `--allow-empty` | No | `false` | Allow trimming to zero retained segments. |
|
||||
|
||||
`trim` selection rules:
|
||||
|
||||
- `--keep` and `--remove` are mutually exclusive.
|
||||
- Exactly one of `--keep` or `--remove` is required.
|
||||
- Selection is by segment ID only.
|
||||
- Invalid selected segment IDs fail the command by default.
|
||||
|
||||
`trim` selector syntax:
|
||||
|
||||
- Segment IDs are positive 1-based integers.
|
||||
- Inclusive ranges are supported: `1-10`.
|
||||
- Comma-separated selectors are supported: `1-10,15,20-25`.
|
||||
- Whitespace around numbers, commas, and hyphens is allowed: `1 - 10, 15, 20 - 25`.
|
||||
- Duplicate and overlapping ranges are accepted and normalized as a union.
|
||||
- Descending ranges (for example `10-1`) are rejected.
|
||||
|
||||
`trim` behavior:
|
||||
|
||||
- `trim` consumes existing seriatim JSON output artifacts only.
|
||||
- `trim` does not accept raw WhisperX transcript JSON as input.
|
||||
- Retained output segment IDs are renumbered sequentially from `1` to `N`.
|
||||
- Transcript order is preserved from input transcript order; selector order does not reorder output.
|
||||
- When output schema is `seriatim-full`, overlap groups are recomputed from retained segments.
|
||||
- `--output-schema seriatim-full` is supported when trim has full-schema artifact data to emit; trim does not synthesize missing full-schema provenance from minimal/intermediate input artifacts.
|
||||
- `trim` does not run merge postprocessors such as `resolve-overlaps`, `coalesce`, or `autocorrect`.
|
||||
|
||||
`trim` report output:
|
||||
|
||||
- When `--report-file` is provided, the report includes standard trim/validation/output events.
|
||||
- The report includes a `trim-audit` event containing trim operation metadata, including selected IDs, retained/removed counts, removed IDs, and old-to-new segment ID mapping.
|
||||
- Old-to-new ID mapping is emitted as a deterministic ordered array of `{old_id, new_id}` pairs.
|
||||
|
||||
`normalize` flags:
|
||||
|
||||
| Flag | Required | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--input-file` | Yes | none | Input transcript JSON file. |
|
||||
| `--output-file` | Yes | none | Normalized transcript JSON output path. |
|
||||
| `--output-schema` | No | `seriatim-intermediate` (resolved via `SERIATIM_OUTPUT_SCHEMA` when set) | Output JSON schema: `seriatim-minimal`, `seriatim-intermediate`, or `seriatim-full`. |
|
||||
| `--output-modules` | No | `json` | Comma-separated output modules. Current normalize support is `json` only. |
|
||||
| `--report-file` | No | none | Optional report JSON output path. |
|
||||
|
||||
`normalize` input shapes:
|
||||
|
||||
- Top-level object with a `segments` array.
|
||||
- Bare top-level array of segment objects (for example, Audita-style output).
|
||||
|
||||
`normalize` behavior:
|
||||
|
||||
- Repairs missing timing fields deterministically:
|
||||
if one of `start`/`end` is present, sets both to that value;
|
||||
if both are missing, uses midpoint of previous `end` and next `start`,
|
||||
with edge fallback to available neighbor and `0.0` for single-segment inputs.
|
||||
- If `end < start`, swaps them.
|
||||
- Fills missing/empty `speaker` with `Unknown_Speaker`.
|
||||
- Drops segments with missing, empty, or whitespace-only `text`.
|
||||
- Validates repaired timing with `start >= 0`.
|
||||
- Accepts existing input `id` values as provenance only.
|
||||
- Reassigns output segment IDs sequentially from `1` to `N`.
|
||||
- Sorts deterministically by `(start, end, original_input_index, speaker)`.
|
||||
- Uses original input order only as a tie-breaker.
|
||||
- Does not run merge postprocessors such as overlap detection, overlap resolution, coalescing, or autocorrect.
|
||||
- Useful for converting external transcript outputs into standard seriatim artifacts.
|
||||
|
||||
`normalize` report output:
|
||||
|
||||
- When `--report-file` is provided, normalize emits deterministic report events with input shape detection, segment counts, schema/module selections, sorting/ID diagnostics, and output write/validation summaries.
|
||||
- A machine-readable `normalize-audit` event is included for downstream tooling.
|
||||
|
||||
Environment variables:
|
||||
|
||||
| Environment Variable | Default | Description |
|
||||
| --- | --- | --- |
|
||||
| `SERIATIM_OUTPUT_SCHEMA` | `seriatim-intermediate` | Output schema used when `--output-schema` is not explicitly provided. Allowed values are `seriatim-minimal`, `seriatim-intermediate`, and `seriatim-full`. The CLI flag takes precedence. |
|
||||
| `SERIATIM_OVERLAP_WORD_RUN_GAP` | `1.0` | Maximum gap in seconds between adjacent timed words when `resolve-overlaps` builds word-run replacement segments. Must be a positive float. |
|
||||
| `SERIATIM_OVERLAP_WORD_RUN_REORDER_WINDOW` | `1.0` | Near-start window in seconds for ordering replacement word runs shortest-first. Must be a positive float. |
|
||||
| `SERIATIM_BACKCHANNEL_MAX_DURATION` | `2.0` | Maximum duration in seconds for `backchannel` classification. Must be a positive float. |
|
||||
| `SERIATIM_FILLER_MAX_DURATION` | `1.25` | Maximum duration in seconds for `filler` classification. Must be a positive float. |
|
||||
|
||||
## Input JSON Format
|
||||
|
||||
Each input file must be valid JSON with a top-level `segments` array. The current parser accepts the WhisperX segment subset needed for merging:
|
||||
|
||||
```json
|
||||
{
|
||||
"segments": [
|
||||
{
|
||||
"start": 1.25,
|
||||
"end": 3.5,
|
||||
"text": "Hello there.",
|
||||
"words": [
|
||||
{"word": "Hello", "start": 1.25, "end": 1.55, "score": 0.98},
|
||||
{"word": "there.", "start": 1.7, "end": 2.0}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Required segment fields:
|
||||
|
||||
- `start`: number, must be `>= 0`.
|
||||
- `end`: number, must be `>= start`.
|
||||
- `text`: string.
|
||||
|
||||
Optional word fields:
|
||||
|
||||
- `words`: array of word timing objects.
|
||||
- `words[].word`: string.
|
||||
- `words[].start`: optional number, must be `>= 0` when present.
|
||||
- `words[].end`: optional number, must be `>= start` when present with `start`.
|
||||
- `words[].score`: optional number.
|
||||
- `words[].speaker`: optional raw speaker label string.
|
||||
|
||||
Word-level timing is preserved internally for overlap resolution. If a word is missing `start` or `end`, seriatim keeps the word text, emits a warning in the optional report, and does not use that word as a timing anchor. Word timing is not emitted in the final JSON artifact.
|
||||
|
||||
## Speaker Map Format
|
||||
|
||||
`speakers.yml` maps input files to canonical speaker names using ordered substring rules:
|
||||
|
||||
This file is optional. If `--speakers` is omitted, `seriatim` uses each input file basename as the segment speaker label.
|
||||
|
||||
```yaml
|
||||
match:
|
||||
- speaker: "Eric Rakestraw"
|
||||
match:
|
||||
- "Eric_Rakestraw"
|
||||
- "Eric"
|
||||
|
||||
- speaker: "Mike Brown"
|
||||
match:
|
||||
- "Mike_Brown"
|
||||
- "mb"
|
||||
```
|
||||
|
||||
For each `--input-file`, `seriatim` takes the file basename and evaluates the rules in order. The first rule with a matching substring wins, and no later rules are evaluated.
|
||||
|
||||
For example, this input:
|
||||
|
||||
```text
|
||||
samples/raw/2026-04-19-Eric_Rakestraw.json
|
||||
```
|
||||
|
||||
matches this rule because the basename contains `Eric_Rakestraw`:
|
||||
|
||||
```yaml
|
||||
- speaker: "Eric Rakestraw"
|
||||
match:
|
||||
- "Eric_Rakestraw"
|
||||
```
|
||||
|
||||
Important details:
|
||||
|
||||
- Matching is against the input file basename, not the full path.
|
||||
- Matching is case-insensitive.
|
||||
- Rules are evaluated from first to last.
|
||||
- Each rule must have a non-empty `speaker`.
|
||||
- Each rule must have at least one non-empty `match` string.
|
||||
- Duplicate speaker names are invalid.
|
||||
- Every input file must match at least one rule or the command fails.
|
||||
|
||||
Deprecated old format:
|
||||
|
||||
```yaml
|
||||
inputs:
|
||||
eric.json:
|
||||
speaker: "Eric Rakestraw"
|
||||
```
|
||||
|
||||
The old `inputs:` direct mapping format is no longer supported.
|
||||
|
||||
## Output JSON Format
|
||||
|
||||
`--output-modules json` controls the writer. `--output-schema` controls the JSON contract that writer serializes.
|
||||
|
||||
The named schemas are stable public contracts. If a consumer depends on a specific shape, it should request that schema explicitly at runtime. The runtime default selection may change in a future release.
|
||||
|
||||
The `seriatim-intermediate` schema is the current default selection when neither `--output-schema` nor `SERIATIM_OUTPUT_SCHEMA` is set. It stays close to the minimal schema, but adds optional `categories` on each segment:
|
||||
|
||||
```json
|
||||
{
|
||||
"metadata": {
|
||||
"application": "seriatim",
|
||||
"version": "dev",
|
||||
"output_schema": "seriatim-intermediate"
|
||||
},
|
||||
"segments": [
|
||||
{
|
||||
"id": 1,
|
||||
"start": 1.25,
|
||||
"end": 3.5,
|
||||
"speaker": "Eric Rakestraw",
|
||||
"text": "Hello there.",
|
||||
"categories": ["backchannel"]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The `seriatim-full` schema uses the full seriatim envelope:
|
||||
|
||||
```json
|
||||
{
|
||||
"metadata": {
|
||||
"application": "seriatim",
|
||||
"version": "dev",
|
||||
"input_reader": "json-files",
|
||||
"input_files": ["eric.json", "mike.json"],
|
||||
"preprocessing_modules": ["validate-raw", "normalize-speakers", "trim-text"],
|
||||
"postprocessing_modules": ["detect-overlaps", "resolve-overlaps", "backchannel", "filler", "resolve-danglers", "coalesce", "detect-overlaps", "autocorrect", "assign-ids", "validate-output"],
|
||||
"output_modules": ["json"]
|
||||
},
|
||||
"segments": [
|
||||
{
|
||||
"id": 1,
|
||||
"source": "eric.json",
|
||||
"source_segment_index": 0,
|
||||
"speaker": "Eric Rakestraw",
|
||||
"start": 1.25,
|
||||
"end": 3.5,
|
||||
"text": "Hello there.",
|
||||
"overlap_group_id": 1
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"source": "eric.json",
|
||||
"source_ref": "word-run:1:1:1",
|
||||
"derived_from": ["eric.json#0"],
|
||||
"speaker": "Eric Rakestraw",
|
||||
"start": 2.0,
|
||||
"end": 2.5,
|
||||
"text": "Resolved word run",
|
||||
"categories": ["backchannel"]
|
||||
}
|
||||
],
|
||||
"overlap_groups": [
|
||||
{
|
||||
"id": 1,
|
||||
"start": 1.25,
|
||||
"end": 4.0,
|
||||
"segments": ["eric.json#0", "mike.json#0"],
|
||||
"speakers": ["Eric Rakestraw", "Mike Brown"],
|
||||
"class": "unknown",
|
||||
"resolution": "unresolved"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The `seriatim-minimal` schema emits minimal metadata and compact ordered segments:
|
||||
|
||||
```json
|
||||
{
|
||||
"metadata": {
|
||||
"application": "seriatim",
|
||||
"version": "dev",
|
||||
"output_schema": "seriatim-minimal"
|
||||
},
|
||||
"segments": [
|
||||
{
|
||||
"id": 1,
|
||||
"start": 1.25,
|
||||
"end": 3.5,
|
||||
"speaker": "Eric Rakestraw",
|
||||
"text": "Hello there."
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Minimal output intentionally omits categories, overlap groups, source/provenance fields, and pipeline configuration metadata.
|
||||
|
||||
Intermediate output intentionally omits overlap groups and source/provenance fields, but keeps optional `categories` and minimal metadata.
|
||||
|
||||
Segments are sorted deterministically by:
|
||||
|
||||
```text
|
||||
(start, end, source, source_segment_index/source_ref, speaker)
|
||||
```
|
||||
|
||||
Final segment IDs are assigned after sorting and start at `1`.
|
||||
|
||||
The public Go output contract is available from:
|
||||
|
||||
```go
|
||||
import "gitea.maximumdirect.net/eric/seriatim/schema"
|
||||
```
|
||||
|
||||
The same package embeds machine-readable JSON Schemas in `schema/full-output.schema.json`, `schema/intermediate-output.schema.json`, and `schema/minimal-output.schema.json`. The default `validate-output` postprocessor validates the selected output shape and verifies final segment IDs are present, sequential, and start at `1`.
|
||||
|
||||
## Overlap Detection
|
||||
|
||||
The default postprocessing pipeline detects overlapping segment groups.
|
||||
|
||||
Overlap behavior:
|
||||
|
||||
- A strict timing overlap is required: `next.start < current_group_end`.
|
||||
- Segments that only touch at a boundary are not grouped.
|
||||
- Groups require at least two distinct speakers.
|
||||
- Transitive overlaps are grouped together.
|
||||
- Segments in detected groups receive `overlap_group_id`.
|
||||
- `overlap_groups[].segments` contains stable references in `source#source_segment_index` format.
|
||||
- `class` is currently `unknown`.
|
||||
- `resolution` is `unresolved` until `resolve-overlaps` replaces the group.
|
||||
|
||||
## Overlap Resolution
|
||||
|
||||
The default postprocessing pipeline runs `detect-overlaps`, then `resolve-overlaps`, then `backchannel`, then `filler`, then `resolve-danglers`, then `coalesce`, then a second `detect-overlaps` pass.
|
||||
|
||||
For each detected overlap group, `resolve-overlaps` uses preserved WhisperX word timing to build smaller word-run replacement segments:
|
||||
|
||||
- The resolution window expands the detected overlap group by `--coalesce-gap` seconds on both sides.
|
||||
- Nearby same-speaker context segments are included when they intersect the expanded window and their start or end is within `--coalesce-gap` of the original overlap boundary.
|
||||
- Once a segment is selected for replacement, all timed words from that segment participate in word-run construction; the window controls segment selection, not per-word clipping.
|
||||
- Context segments that are part of another detected overlap group are not pulled into the current group.
|
||||
- Untimed words are included in replacement text in original word order when nearby timed words create a replacement run.
|
||||
- Untimed words do not affect replacement segment start/end times or word-run gap splitting.
|
||||
- Words for the same speaker are merged into one run when the gap between adjacent words is no greater than `SERIATIM_OVERLAP_WORD_RUN_GAP`.
|
||||
- The default word-run gap is `1.0` seconds.
|
||||
- Set `SERIATIM_OVERLAP_WORD_RUN_GAP` to a positive number of seconds to override the default.
|
||||
- Near-start replacement word runs are reordered so shorter segments come first when adjacent starts are within `SERIATIM_OVERLAP_WORD_RUN_REORDER_WINDOW`.
|
||||
- The default word-run reorder window is `1.0` seconds.
|
||||
- Set `SERIATIM_OVERLAP_WORD_RUN_REORDER_WINDOW` to a positive number of seconds to override the default.
|
||||
- Replacement segment text is built by joining word text with single spaces.
|
||||
- Replacement segments include `source_ref` and `derived_from`.
|
||||
- Replacement segments omit `source_segment_index` because they are derived from one or more original segments.
|
||||
- Resolved overlap groups are removed before the second detection pass.
|
||||
- Replacement segments are left without `overlap_group_id` until the second detection pass annotates any remaining overlap.
|
||||
- If a speaker has no usable word timing in a group, that speaker's original segment is kept.
|
||||
- If no speakers in a group have usable word timing, the original group and annotations remain unchanged.
|
||||
|
||||
## Backchannels
|
||||
|
||||
The default pipeline runs `backchannel` before `coalesce`. It tags short acknowledgement segments with:
|
||||
|
||||
```json
|
||||
"categories": ["backchannel"]
|
||||
```
|
||||
|
||||
Backchannel matching is case-insensitive, ignores punctuation for matching and word-count purposes, trims surrounding whitespace, and requires a matching acknowledgement phrase, no more than three whitespace-delimited words, and duration no greater than `SERIATIM_BACKCHANNEL_MAX_DURATION` seconds. The default maximum duration is `2.0` seconds.
|
||||
|
||||
## Fillers
|
||||
|
||||
The default pipeline runs `filler` after `backchannel` and before `coalesce`. It tags short filler utterances with:
|
||||
|
||||
```json
|
||||
"categories": ["filler"]
|
||||
```
|
||||
|
||||
Filler matching is case-insensitive, ignores punctuation for matching and word-count purposes, trims surrounding whitespace, and requires only filler tokens such as `um`, `uh`, `er`, `erm`, `ah`, `eh`, `hmm`, `mm`, or repeated combinations of those tokens. Matching segments must contain no more than three whitespace-delimited words and have duration no greater than `SERIATIM_FILLER_MAX_DURATION` seconds. The default maximum duration is `1.25` seconds.
|
||||
|
||||
## Dangler Resolution
|
||||
|
||||
The default pipeline runs `resolve-danglers` before `coalesce` and before the second overlap detection pass. It repairs short derived fragments when they share provenance with a nearby segment:
|
||||
|
||||
- Dangling-end fragments have no more than two words and end in punctuation.
|
||||
- Dangling-start fragments have no more than two words.
|
||||
- Matching uses same-speaker segments with any shared `derived_from` value.
|
||||
- Merged segments use `source_ref` values such as `resolve-danglers:1`, keep the target segment's transcript position, and union `derived_from`.
|
||||
|
||||
## Coalescing
|
||||
|
||||
The default pipeline runs `coalesce` after `resolve-danglers` and before the second overlap detection pass. It merges adjacent same-speaker segments in the transcript's current order when `next.start - current.end <= --coalesce-gap`.
|
||||
|
||||
Coalesced segments use `source_ref` values such as `coalesce:1`, include `derived_from`, and omit `source_segment_index`.
|
||||
|
||||
Different-speaker backchannel and filler segments do not block coalescing of surrounding same-speaker segments. Same-speaker backchannel and filler segments are merged normally when they are within `--coalesce-gap`. When same-speaker segments are coalesced, any `backchannel` or `filler` category from the merged inputs is dropped from the coalesced segment.
|
||||
|
||||
## Autocorrect
|
||||
|
||||
Autocorrect is included in the default postprocessing pipeline. If `--autocorrect` is omitted, the module leaves transcript text unchanged and records a skip event in the optional report.
|
||||
|
||||
Enable corrections by passing `--autocorrect`:
|
||||
|
||||
```sh
|
||||
go run ./cmd/seriatim merge \
|
||||
--input-file input.json \
|
||||
--autocorrect autocorrect.yml \
|
||||
--output-file merged.json
|
||||
```
|
||||
|
||||
`autocorrect.yml` format:
|
||||
|
||||
```yaml
|
||||
autocorrect:
|
||||
- target: "Hrank"
|
||||
match:
|
||||
- "hrank"
|
||||
- "Frank"
|
||||
|
||||
- target: "Mike Brown"
|
||||
match:
|
||||
- "Mike Pat"
|
||||
```
|
||||
|
||||
Matching behavior:
|
||||
|
||||
- Matching is case-sensitive.
|
||||
- Matches apply only to whole tokens, not substrings inside larger words.
|
||||
- Punctuation and whitespace can surround a match.
|
||||
- Multi-word and hyphenated matches are supported.
|
||||
- Duplicate match strings are invalid, including duplicates across separate rules.
|
||||
|
||||
## Current Limitations
|
||||
|
||||
- Only JSON input is supported.
|
||||
- Overlap resolution depends on WhisperX word timing; groups without usable word timing remain unresolved.
|
||||
- Alternate output formats are not implemented yet.
|
||||
|
||||
## Release Builds
|
||||
|
||||
Local builds record version metadata as `dev`. Release builds should inject the release version with `ldflags`:
|
||||
|
||||
```sh
|
||||
go build -ldflags "-X gitea.maximumdirect.net/eric/seriatim/internal/buildinfo.Version=v1.0.0" ./cmd/seriatim
|
||||
```
|
||||
## Commands
|
||||
|
||||
- `merge`: merge one or more input transcript JSON files.
|
||||
- `trim`: keep/remove segment IDs from an existing seriatim artifact.
|
||||
- `normalize`: canonicalize transcript-like JSON into a seriatim artifact.
|
||||
|
||||
## Documentation
|
||||
|
||||
- CLI reference: [docs/cli.md](docs/cli.md)
|
||||
- Configuration reference: [docs/config.md](docs/config.md)
|
||||
- Operations guide: [docs/operations.md](docs/operations.md)
|
||||
- Troubleshooting: [docs/troubleshooting.md](docs/troubleshooting.md)
|
||||
- Integrations:
|
||||
- [docs/integrations/whisperx-json.md](docs/integrations/whisperx-json.md)
|
||||
- [docs/integrations/output-schemas.md](docs/integrations/output-schemas.md)
|
||||
- Development architecture policy: [docs/policy/architecture.md](docs/policy/architecture.md)
|
||||
- Contributor workflow: [docs/policy/development.md](docs/policy/development.md)
|
||||
- Documentation policy: [docs/policy/documentation.md](docs/policy/documentation.md)
|
||||
- Internal implementation docs:
|
||||
- [docs/internal/pipeline.md](docs/internal/pipeline.md)
|
||||
- [docs/internal/artifacts.md](docs/internal/artifacts.md)
|
||||
- [docs/internal/modules.md](docs/internal/modules.md)
|
||||
- Public JSON schemas:
|
||||
- [schema/minimal-output.schema.json](schema/minimal-output.schema.json)
|
||||
- [schema/intermediate-output.schema.json](schema/intermediate-output.schema.json)
|
||||
- [schema/full-output.schema.json](schema/full-output.schema.json)
|
||||
- Synthetic examples: [examples/README.md](examples/README.md)
|
||||
- Documentation roadmap: [docs/roadmap/documentation.md](docs/roadmap/documentation.md)
|
||||
|
||||
524
architecture.md
524
architecture.md
@@ -1,524 +0,0 @@
|
||||
# seriatim Architecture
|
||||
|
||||
`seriatim` is a deterministic transcript utility for:
|
||||
|
||||
- merging multiple per-speaker transcript inputs into a single chronologically ordered diarized transcript, and
|
||||
- projecting existing seriatim transcript artifacts through deterministic segment-ID trimming, and
|
||||
- canonicalizing external transcript-style JSON inputs into standard seriatim output schemas.
|
||||
|
||||
The initial use case is merging independently transcribed speaker audio tracks from the same recorded session, such as a weekly tabletop RPG session. The architecture should also support meetings, podcasts, interviews, and other multi-speaker events.
|
||||
|
||||
`seriatim` is implemented in Go.
|
||||
|
||||
## Goals
|
||||
|
||||
`seriatim` should:
|
||||
|
||||
1. Validate runtime configuration before performing transcript processing.
|
||||
2. Support multiple input methods and formats through input readers.
|
||||
3. Normalize raw per-speaker transcripts into a canonical internal model.
|
||||
4. Apply deterministic preprocessing modules to canonical per-speaker transcripts.
|
||||
5. Merge all segments into a deterministic global chronological order.
|
||||
6. Apply deterministic postprocessing modules to the merged transcript.
|
||||
7. Preserve word-level timing data when available.
|
||||
8. Detect and annotate overlapping speech regions.
|
||||
9. Emit one or more output artifacts through output writers.
|
||||
10. Produce report data for validation findings, corrections, and transformations.
|
||||
11. Support artifact-level transcript projection commands that operate on existing seriatim output.
|
||||
|
||||
## Non-goals
|
||||
|
||||
The 1.0 release does not attempt to:
|
||||
|
||||
- Perform transcription.
|
||||
- Perform audio diarization.
|
||||
- Use an LLM.
|
||||
- Summarize transcript content.
|
||||
- Infer speaker identity from audio or text.
|
||||
- Fully resolve every crosstalk case.
|
||||
- Load arbitrary third-party code as dynamic plugins.
|
||||
|
||||
The application supports runtime composition of built-in modules by canonical module name. Arbitrary external plugin loading can be considered later.
|
||||
|
||||
## Core Assumption
|
||||
|
||||
The merge algorithm assumes that all input transcript timestamps are measured against the same session clock.
|
||||
|
||||
This is expected when each speaker has a separate recording that preserves silence and starts at the same session recording time. If input files have independent local timelines, `seriatim` cannot safely merge them without a separate alignment step.
|
||||
|
||||
## Pipeline Overview
|
||||
|
||||
The internal pipeline is:
|
||||
|
||||
```text
|
||||
configuration check
|
||||
-> input
|
||||
-> preprocessing
|
||||
-> merge
|
||||
-> postprocessing
|
||||
-> output
|
||||
```
|
||||
|
||||
Each stage has an explicit data contract. Input and output stages perform I/O. Processing stages should be deterministic transformations over in-memory models and should record report events for validation findings, corrections, and transformations.
|
||||
|
||||
`merge` runs this pipeline. `trim` and `normalize` are intentionally separate from this pipeline and operate at the artifact layer.
|
||||
|
||||
## Stage Contracts
|
||||
|
||||
### 1. Configuration Check
|
||||
|
||||
The configuration stage validates all CLI flags, environment variables, module names, input paths, output paths, and module-specific options before transcript data is processed.
|
||||
|
||||
Configuration validation should fail fast for:
|
||||
|
||||
- Missing required input.
|
||||
- Unknown module names.
|
||||
- Unknown input or output formats.
|
||||
- Ambiguous speaker mappings.
|
||||
- Invalid correction policies.
|
||||
- Invalid timing thresholds.
|
||||
- Invalid output paths.
|
||||
|
||||
The configuration stage produces an application config value that is passed through the pipeline.
|
||||
|
||||
### 2. Input Stage
|
||||
|
||||
The input stage converts external inputs into raw transcript documents with source metadata.
|
||||
|
||||
The current input method is one or more JSON files passed with repeated `--input-file` flags:
|
||||
|
||||
```text
|
||||
seriatim merge --input-file eric.json --input-file mike.json --output-file merged.json
|
||||
```
|
||||
|
||||
Future input methods may include:
|
||||
|
||||
- A `.tar.gz` bundle.
|
||||
- A URI.
|
||||
- A directory.
|
||||
|
||||
Future input formats may include:
|
||||
|
||||
- JSON.
|
||||
- SRT.
|
||||
- VTT.
|
||||
|
||||
Input readers should be selected from an explicit registry. A reader is responsible for loading external data and returning raw transcript documents, not for canonical normalization.
|
||||
|
||||
### 3. Preprocessing Stage
|
||||
|
||||
The preprocessing stage applies zero or more modules before global merge.
|
||||
|
||||
Preprocessing starts with raw transcript documents from input readers and must end with canonical per-speaker transcripts. Some preprocessing modules operate on raw transcripts, some perform raw-to-canonical normalization, and some operate only on canonical transcripts.
|
||||
|
||||
Preprocessing modules are selected at runtime with a comma-separated list of canonical module names:
|
||||
|
||||
```text
|
||||
--preprocessing-modules validate-raw,normalize-speakers,trim-text
|
||||
```
|
||||
|
||||
Modules run in the exact order provided. Unknown module names are configuration errors.
|
||||
|
||||
Potential preprocessing modules include:
|
||||
|
||||
- Structural raw transcript validation.
|
||||
- Semantic transcript validation.
|
||||
- Raw-to-canonical transcript normalization.
|
||||
- Speaker name normalization based on input filename.
|
||||
- Timing validation and deterministic correction.
|
||||
- Text trimming.
|
||||
|
||||
Preprocessing should not depend on global chronological ordering across speakers. Modules that need the globally merged transcript belong in postprocessing.
|
||||
|
||||
Each preprocessing module must declare the model state it requires and the model state it produces. For example, `validate-raw` requires raw transcripts and produces raw transcripts, while `normalize-speakers` requires raw transcripts and produces canonical transcripts. Configuration validation should reject module orders that cannot type-check.
|
||||
|
||||
### 4. Merge Stage
|
||||
|
||||
The merge stage extracts all canonical segments from the preprocessed per-speaker transcripts and sorts them into a single deterministic chronological sequence.
|
||||
|
||||
The recommended sort key is:
|
||||
|
||||
```text
|
||||
(start, end, source, source_segment_index, speaker)
|
||||
```
|
||||
|
||||
The exact tie-breaker must be documented and stable across runs.
|
||||
|
||||
The merge stage should assign temporary internal references if needed, but it should not assign final output IDs until after all order-affecting postprocessing is complete.
|
||||
|
||||
### 5. Postprocessing Stage
|
||||
|
||||
The postprocessing stage applies zero or more modules to the merged transcript.
|
||||
|
||||
Postprocessing modules are selected at runtime with a comma-separated list of canonical module names:
|
||||
|
||||
```text
|
||||
--postprocessing-modules detect-overlaps,resolve-overlaps,backchannel,filler,resolve-danglers,coalesce,detect-overlaps,autocorrect,assign-ids,validate-output
|
||||
```
|
||||
|
||||
Modules run in the exact order provided. Unknown module names are configuration errors.
|
||||
|
||||
Potential postprocessing modules include:
|
||||
|
||||
- Overlap group detection.
|
||||
- Overlap group refinement.
|
||||
- Same-speaker segment coalescing.
|
||||
- Deterministic grammar cleanup.
|
||||
- Word replacement from `autocorrect.yml`.
|
||||
- Final segment ID assignment.
|
||||
- Output model validation.
|
||||
|
||||
Any module that can reorder, split, merge, drop, or create segments must run before final ID assignment.
|
||||
|
||||
### 6. Output Stage
|
||||
|
||||
The output stage emits one or more artifacts from the final transcript and report model.
|
||||
|
||||
The current output format is JSON, specified with:
|
||||
|
||||
```text
|
||||
--output-file merged.json
|
||||
```
|
||||
|
||||
The current named JSON schemas are:
|
||||
|
||||
- `seriatim-minimal`
|
||||
- `seriatim-intermediate`
|
||||
- `seriatim-full`
|
||||
|
||||
The current runtime default selection is `seriatim-intermediate`, but default selection may change over time. Consumers that depend on a specific schema should request it explicitly.
|
||||
|
||||
Future output formats may include:
|
||||
|
||||
- Markdown.
|
||||
- SRT.
|
||||
- VTT.
|
||||
- Validation reports.
|
||||
- Overlap reports.
|
||||
|
||||
Output writers should be selected from an explicit registry and should consume the final transcript model read-only. Multiple output writers may run for a single invocation.
|
||||
|
||||
### 7. Artifact Projection Stage (`trim` command)
|
||||
|
||||
`trim` is an artifact-level command that reads an existing seriatim output artifact and emits a projected artifact containing a segment-ID subset.
|
||||
|
||||
Design constraints:
|
||||
|
||||
- `trim` runs after `merge`, not as a merge postprocessor.
|
||||
- `trim` validates the input artifact against supported seriatim output schemas.
|
||||
- `trim` performs deterministic keep/remove selection by segment ID.
|
||||
- `trim` renumbers retained IDs to `1..N` in transcript order.
|
||||
- `trim` validates the final output against the selected output schema before writing.
|
||||
- `trim` records audit metadata in report output.
|
||||
|
||||
`trim` is intentionally separate from merge postprocessing because it consumes already-emitted public artifacts. This separation keeps merge semantics stable and avoids rerunning merge-only transforms on projected artifacts.
|
||||
|
||||
`trim` must not rerun merge postprocessors such as `resolve-overlaps`, `coalesce`, or `autocorrect`.
|
||||
|
||||
### 8. Artifact Canonicalization Stage (`normalize` command)
|
||||
|
||||
`normalize` is an artifact-level command that reads transcript-like JSON and emits a standard seriatim output artifact in a selected schema.
|
||||
|
||||
Design constraints:
|
||||
|
||||
- `normalize` runs outside the merge pipeline and does not invoke merge preprocessing or postprocessing modules.
|
||||
- `normalize` accepts two input shapes: object-with-`segments` and bare segment arrays.
|
||||
- `normalize` applies deterministic repair rules for missing/irregular `start`, `end`, and `speaker`, and drops segments with missing/empty `text`.
|
||||
- `normalize` sorts segments deterministically by chronological keys and stable input-index tie-breakers.
|
||||
- `normalize` assigns fresh sequential output IDs (`1..N`) after sorting.
|
||||
- `normalize` validates final output against the selected schema before writing.
|
||||
- `normalize` writes optional deterministic report diagnostics when `--report-file` is requested.
|
||||
|
||||
`normalize` is intended for canonicalizing external transcript outputs (including Audita-style bare arrays) into seriatim contracts, not for running merge-time language or overlap transformations.
|
||||
|
||||
`normalize` must not run merge postprocessors such as overlap detection, overlap resolution, coalescing, or autocorrect.
|
||||
|
||||
## Module Classification
|
||||
|
||||
Modules should be classified by their contract and allowed effects.
|
||||
|
||||
| Class | Input | Output | Allowed effects |
|
||||
| --- | --- | --- | --- |
|
||||
| `InputReader` | External source spec | Raw transcript documents | Reads external data |
|
||||
| `Validator` | Raw, canonical, merged, or final model | Same model plus report events | Observes only |
|
||||
| `Normalizer` | Raw model | Canonical model | Converts representation |
|
||||
| `Corrector` | Canonical model | Canonical model plus report events | Deterministic mutation |
|
||||
| `Annotator` | Canonical or merged model | Same model plus annotations | Adds metadata |
|
||||
| `Transformer` | Canonical or merged model | Updated model plus report events | May reorder, split, merge, drop, or create segments |
|
||||
| `OutputWriter` | Final transcript and report | External artifact | Writes output |
|
||||
|
||||
This classification should guide Go interfaces and package boundaries. It should also determine where a module is allowed to run.
|
||||
|
||||
## Runtime Module Composition
|
||||
|
||||
The application supports runtime composition of built-in modules.
|
||||
|
||||
Module names are canonical strings registered at startup. CLI flags refer to those names. The configuration stage resolves names into module instances before the pipeline runs.
|
||||
|
||||
Example:
|
||||
|
||||
```text
|
||||
seriatim merge \
|
||||
--input-file eric.json \
|
||||
--input-file mike.json \
|
||||
--speakers speakers.yml \
|
||||
--autocorrect autocorrect.yml \
|
||||
--preprocessing-modules validate-raw,normalize-speakers,trim-text \
|
||||
--postprocessing-modules detect-overlaps,resolve-overlaps,backchannel,filler,resolve-danglers,coalesce,detect-overlaps,autocorrect,assign-ids,validate-output \
|
||||
--output-modules json \
|
||||
--output-schema seriatim-intermediate \
|
||||
--output-file merged.json \
|
||||
--report-file report.json
|
||||
```
|
||||
|
||||
Composition rules:
|
||||
|
||||
- Module order is exactly the order specified by the user.
|
||||
- An empty module list is valid when the stage supports zero modules.
|
||||
- Unknown module names are fatal configuration errors.
|
||||
- Module-specific options are read from the validated application config.
|
||||
- A module must declare which pipeline stage and model type it supports.
|
||||
- Modules should be deterministic for the same inputs, config, and application version.
|
||||
- Modules should not perform I/O unless their class explicitly allows it.
|
||||
|
||||
Some modules may be recommended defaults. Defaults should be explicit in documentation and should be equivalent to passing the corresponding module list.
|
||||
|
||||
## Go Interface Sketch
|
||||
|
||||
The exact implementation may evolve, but the core interfaces should resemble:
|
||||
|
||||
```go
|
||||
type InputReader interface {
|
||||
Name() string
|
||||
Read(ctx context.Context, spec InputSpec, cfg Config) ([]RawTranscript, []ReportEvent, error)
|
||||
}
|
||||
|
||||
type Preprocessor interface {
|
||||
Name() string
|
||||
Requires() ModelState
|
||||
Produces() ModelState
|
||||
Process(ctx context.Context, in PreprocessState, cfg Config) (PreprocessState, []ReportEvent, error)
|
||||
}
|
||||
|
||||
type Merger interface {
|
||||
Merge(ctx context.Context, in []CanonicalTranscript, cfg Config) (MergedTranscript, []ReportEvent, error)
|
||||
}
|
||||
|
||||
type Postprocessor interface {
|
||||
Name() string
|
||||
Process(ctx context.Context, in MergedTranscript, cfg Config) (MergedTranscript, []ReportEvent, error)
|
||||
}
|
||||
|
||||
type OutputWriter interface {
|
||||
Name() string
|
||||
Write(ctx context.Context, out any, report Report, cfg Config) ([]ReportEvent, error)
|
||||
}
|
||||
```
|
||||
|
||||
`PreprocessState` should carry either raw transcripts, canonical transcripts, or both during migration between representations. The pipeline should validate that the ordered preprocessing list transitions from raw input state to canonical output state exactly once before merge.
|
||||
|
||||
The interfaces should favor value returns over hidden mutation. If pointer-based implementations are chosen for performance, mutation boundaries must still be clear and tested.
|
||||
|
||||
## Canonical Internal Model
|
||||
|
||||
The canonical model should be richer than the final output schema.
|
||||
|
||||
Canonical segment fields should include:
|
||||
|
||||
- Temporary internal reference.
|
||||
- Source identifier.
|
||||
- Source segment index.
|
||||
- Canonical speaker.
|
||||
- Start time.
|
||||
- End time.
|
||||
- Text.
|
||||
- Word-level timing data, if available.
|
||||
- Raw diarization labels, if useful for reporting.
|
||||
- Validation and correction metadata, if needed internally.
|
||||
|
||||
The final output model can omit internal-only fields, but the report should retain enough provenance to diagnose corrections and transformations.
|
||||
|
||||
## Validation Strategy
|
||||
|
||||
Validation occurs at multiple boundaries:
|
||||
|
||||
- Configuration validation before processing.
|
||||
- Raw input structural validation after input loading.
|
||||
- Raw input semantic validation before normalization or correction.
|
||||
- Canonical model validation after normalization and preprocessing.
|
||||
- Merged model validation after merge and postprocessing.
|
||||
- Final output schema validation before writing artifacts.
|
||||
|
||||
Structural validation answers whether data has the required shape and types.
|
||||
|
||||
Semantic validation answers whether the data is plausible and internally consistent.
|
||||
|
||||
Correctable issues should be deterministic and reportable. Fatal issues should stop the run with a non-zero exit code.
|
||||
|
||||
Examples of correctable issues:
|
||||
|
||||
- Leading or trailing whitespace.
|
||||
- Segment `end < start`, when configured correction policy allows deterministic repair.
|
||||
- Missing word speaker labels when canonical speaker is known.
|
||||
- Raw diarization labels that should be replaced with the canonical speaker.
|
||||
|
||||
Examples of fatal issues:
|
||||
|
||||
- Input file is not valid JSON.
|
||||
- Required transcript fields are missing.
|
||||
- Speaker map does not identify a canonical speaker for an input.
|
||||
- Unknown module name.
|
||||
- Output fails final schema validation.
|
||||
|
||||
## Overlap Handling
|
||||
|
||||
Overlap detection should create overlap groups rather than only pairwise annotations.
|
||||
|
||||
Two adjacent sorted segments overlap when:
|
||||
|
||||
```text
|
||||
next.start < current_group_end
|
||||
```
|
||||
|
||||
This supports transitive overlap groups:
|
||||
|
||||
```text
|
||||
A: 10.0-14.0
|
||||
B: 12.0-13.0
|
||||
C: 13.5-15.0
|
||||
```
|
||||
|
||||
These belong to one overlap group spanning `10.0-15.0`.
|
||||
|
||||
Overlap groups should record:
|
||||
|
||||
- Overlap group ID.
|
||||
- Group start time.
|
||||
- Group end time.
|
||||
- Segment references.
|
||||
- Speakers involved.
|
||||
- Classification, if known.
|
||||
- Resolution status.
|
||||
|
||||
Initial classifications may include:
|
||||
|
||||
- `unknown`
|
||||
- `minor_overlap`
|
||||
- `handoff`
|
||||
- `backchannel`
|
||||
- `crosstalk`
|
||||
|
||||
The `resolve-overlaps` module uses preserved word-level timing to replace detected overlap-group segments with smaller word-run segments when usable timing is available. Resolution expands each overlap window by the configured coalesce gap so nearby same-speaker context can be absorbed into the replacement runs. Once a segment is selected for replacement, all timed words from that segment participate in word-run construction so text is not clipped at the window boundary. Groups without usable word timing remain unresolved for later passes or human review.
|
||||
|
||||
Overlap resolution should be non-destructive. Original segment text, timing, and source metadata must remain recoverable.
|
||||
|
||||
## Final ID Assignment
|
||||
|
||||
Final segment IDs should be assigned by an explicit postprocessing module after every transformation that can affect segment order.
|
||||
|
||||
Final IDs should be sequential integers starting from `1`.
|
||||
|
||||
Final IDs should reflect final chronological order.
|
||||
|
||||
Before final ID assignment, modules should reference segments using stable internal references rather than final output IDs.
|
||||
|
||||
## Output Invariants
|
||||
|
||||
A valid merged transcript should satisfy:
|
||||
|
||||
- Every segment has a unique integer ID.
|
||||
- Segment IDs begin at `1`.
|
||||
- Segment IDs increase in final chronological order.
|
||||
- Every segment has a canonical speaker.
|
||||
- Every segment has a source.
|
||||
- Every segment has `start >= 0`.
|
||||
- Every segment has `end >= start`.
|
||||
- The segments array is sorted deterministically.
|
||||
- Any `overlap_group_id` on a segment refers to an existing overlap group.
|
||||
- Every overlap group references at least two segments.
|
||||
- Every referenced segment exists.
|
||||
- Output validates against the selected output schema.
|
||||
|
||||
For full-schema trim output, overlap groups are recomputed from retained segments so overlap annotations and group references remain internally consistent after projection.
|
||||
|
||||
## Determinism Requirements
|
||||
|
||||
Given the same inputs, config, and application version, `seriatim` should produce byte-stable JSON output where practical.
|
||||
|
||||
To support this:
|
||||
|
||||
- Sort input specs deterministically unless explicit input order is meaningful.
|
||||
- Use stable sort keys.
|
||||
- Assign final IDs only after final ordering.
|
||||
- Avoid Go map iteration order affecting output.
|
||||
- Emit JSON through structs with stable field ordering.
|
||||
- Record application version in output metadata.
|
||||
- Record enabled module names and module order in output metadata or report data.
|
||||
|
||||
Trim-specific determinism requirements:
|
||||
|
||||
- Selector normalization and retained IDs are deterministic.
|
||||
- Old-to-new ID mapping in trim reports is emitted in deterministic order.
|
||||
- Full-schema overlap recomputation is deterministic for the same input artifact and selector.
|
||||
|
||||
Normalize-specific determinism requirements:
|
||||
|
||||
- Input-shape detection is deterministic.
|
||||
- Segment ordering is deterministic for identical input data.
|
||||
- Output IDs are always reassigned sequentially after deterministic sorting.
|
||||
- Normalize diagnostic reports are deterministic for identical inputs and configuration.
|
||||
|
||||
## Go Package Layout
|
||||
|
||||
```text
|
||||
cmd/seriatim/ CLI entrypoint
|
||||
internal/config/ CLI/env/config loading and validation
|
||||
internal/pipeline/ Pipeline orchestration and module registry
|
||||
internal/builtin/ Built-in pipeline modules
|
||||
internal/artifact/ Conversion from internal model to public output schema
|
||||
internal/normalize/ Normalize input parsing, validation, deterministic sorting, schema conversion, and diagnostics
|
||||
internal/trim/ Artifact parsing, trim selection, schema conversion, overlap recomputation for full schema
|
||||
internal/buildinfo/ Build-time version metadata
|
||||
internal/speaker/ Speaker map parsing and lookup
|
||||
internal/model/ Canonical and merged transcript models
|
||||
internal/overlap/ Overlap detection and refinement helpers
|
||||
internal/autocorrect/ Word replacement rules
|
||||
internal/report/ Report model and event accumulation
|
||||
schema/ Public output contract and JSON Schema validation
|
||||
```
|
||||
|
||||
Package boundaries should follow data ownership. Shared models belong in `internal/model`; stage-specific behavior belongs in the relevant stage package.
|
||||
|
||||
For trim:
|
||||
|
||||
- `internal/trim` contains pure transformation logic over artifact structs.
|
||||
- CLI command code handles only flag parsing, file I/O, and report emission.
|
||||
- Transform logic is deterministic and pure except for command-layer I/O.
|
||||
|
||||
For normalize:
|
||||
|
||||
- `internal/normalize` contains parsing/validation and deterministic schema conversion logic.
|
||||
- CLI command code handles flag parsing and delegates execution.
|
||||
- Normalize remains artifact-level and does not compose merge pipeline modules.
|
||||
|
||||
## Default Modules
|
||||
|
||||
The default pipeline is equivalent to explicit module lists.
|
||||
|
||||
Recommended default preprocessing modules:
|
||||
|
||||
```text
|
||||
validate-raw,normalize-speakers,trim-text
|
||||
```
|
||||
|
||||
Recommended default postprocessing modules:
|
||||
|
||||
```text
|
||||
detect-overlaps,resolve-overlaps,backchannel,filler,resolve-danglers,coalesce,detect-overlaps,autocorrect,assign-ids,validate-output
|
||||
```
|
||||
|
||||
The default output module is:
|
||||
|
||||
```text
|
||||
json
|
||||
```
|
||||
182
docs/cli.md
Normal file
182
docs/cli.md
Normal file
@@ -0,0 +1,182 @@
|
||||
# CLI Reference
|
||||
|
||||
## Shortest useful command
|
||||
|
||||
```sh
|
||||
go run ./cmd/seriatim merge \
|
||||
--input-file speaker-a.json \
|
||||
--input-file speaker-b.json \
|
||||
--output-file merged.json
|
||||
```
|
||||
|
||||
## Command overview
|
||||
|
||||
| Command | Purpose |
|
||||
| --- | --- |
|
||||
| `merge` | Merge one or more raw transcript JSON inputs into one seriatim artifact. |
|
||||
| `trim` | Keep or remove segment IDs from an existing seriatim artifact. |
|
||||
| `normalize` | Canonicalize transcript-like JSON into a seriatim artifact. |
|
||||
|
||||
Root usage:
|
||||
|
||||
```text
|
||||
seriatim [command]
|
||||
```
|
||||
|
||||
## Global flags
|
||||
|
||||
| Flag | Description |
|
||||
| --- | --- |
|
||||
| `-h, --help` | Show help. |
|
||||
| `-v, --version` | Show build version. |
|
||||
|
||||
## `merge`
|
||||
|
||||
Usage:
|
||||
|
||||
```text
|
||||
seriatim merge [flags]
|
||||
```
|
||||
|
||||
Flags:
|
||||
|
||||
| Flag | Required | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--input-file stringArray` | Yes, repeat at least once | none | Input transcript JSON file(s). |
|
||||
| `--output-file string` | Yes | none | Output transcript JSON file path. |
|
||||
| `--report-file string` | No | none | Optional report JSON path. |
|
||||
| `--speakers string` | No | none | Speaker-map YAML file. |
|
||||
| `--autocorrect string` | No | none | Autocorrect YAML file. |
|
||||
| `--input-reader string` | No | `json-files` | Input reader module name. |
|
||||
| `--output-modules string` | No | `json` | Comma-separated output module names. |
|
||||
| `--output-schema string` | No | `seriatim-intermediate` | Output schema name: `seriatim-minimal`, `seriatim-intermediate`, `seriatim-full`. |
|
||||
| `--preprocessing-modules string` | No | `validate-raw,normalize-speakers,trim-text` | Comma-separated preprocessing module names, run in order. |
|
||||
| `--postprocessing-modules string` | No | `detect-overlaps,resolve-overlaps,backchannel,filler,resolve-danglers,coalesce,detect-overlaps,autocorrect,assign-ids,validate-output` | Comma-separated postprocessing module names, run in order. |
|
||||
| `--coalesce-gap string` | No | `3.0` | Non-negative seconds for coalescing and overlap-resolution context. |
|
||||
|
||||
`merge` behavior and validation:
|
||||
|
||||
- Unknown input reader, preprocessing module, postprocessing module, or output module fails the command.
|
||||
- Preprocessing order must satisfy module state requirements (`raw` -> `canonical`); invalid order fails.
|
||||
- Input files are validated, deduplicated, normalized, then sorted for deterministic processing.
|
||||
- Optional report output is written only when `--report-file` is set.
|
||||
- When `--output-schema` is omitted, schema resolution is: `SERIATIM_OUTPUT_SCHEMA` -> default `seriatim-intermediate`.
|
||||
|
||||
## `trim`
|
||||
|
||||
Usage:
|
||||
|
||||
```text
|
||||
seriatim trim [flags]
|
||||
```
|
||||
|
||||
Flags:
|
||||
|
||||
| Flag | Required | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--input-file string` | Yes | none | Input seriatim artifact JSON file. |
|
||||
| `--output-file string` | Yes | none | Output transcript JSON file path. |
|
||||
| `--keep string` | Exactly one of `--keep` / `--remove` | none | Segment ID selector to keep. |
|
||||
| `--remove string` | Exactly one of `--keep` / `--remove` | none | Segment ID selector to remove. |
|
||||
| `--output-schema string` | No | preserve input artifact schema | Output schema override: `seriatim-minimal`, `seriatim-intermediate`, `seriatim-full`. |
|
||||
| `--report-file string` | No | none | Optional report JSON path. |
|
||||
| `--allow-empty` | No | `false` | Allow output with zero segments. |
|
||||
|
||||
Selector rules:
|
||||
|
||||
- IDs must be positive integers.
|
||||
- Single IDs and inclusive ranges are supported: `1`, `1-10`.
|
||||
- Comma-separated selectors are supported: `1-10,15,20-25`.
|
||||
- Whitespace around commas and hyphens is allowed.
|
||||
- Descending ranges (example `10-1`) are invalid.
|
||||
- Duplicates and overlapping ranges are normalized as a union.
|
||||
|
||||
`trim` behavior:
|
||||
|
||||
- Input must already be a valid seriatim artifact (not raw merge input JSON).
|
||||
- Output keeps transcript order from input and renumbers retained segment IDs sequentially.
|
||||
- If `--output-schema` is omitted, the input artifact schema is preserved.
|
||||
- `trim` never runs merge preprocessing/postprocessing modules.
|
||||
|
||||
## `normalize`
|
||||
|
||||
Usage:
|
||||
|
||||
```text
|
||||
seriatim normalize [flags]
|
||||
```
|
||||
|
||||
Flags:
|
||||
|
||||
| Flag | Required | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--input-file string` | Yes | none | Input transcript JSON file. |
|
||||
| `--output-file string` | Yes | none | Output transcript JSON file path. |
|
||||
| `--output-schema string` | No | `seriatim-intermediate` | Output schema name: `seriatim-minimal`, `seriatim-intermediate`, `seriatim-full`. |
|
||||
| `--output-modules string` | No | `json` | Comma-separated output module names (`json` only). |
|
||||
| `--report-file string` | No | none | Optional report JSON path. |
|
||||
|
||||
`normalize` input shapes:
|
||||
|
||||
- Object with top-level `segments` array.
|
||||
- Bare top-level segment array.
|
||||
|
||||
`normalize` behavior:
|
||||
|
||||
- Sorts deterministically and reassigns output IDs sequentially from `1`.
|
||||
- Fills missing/blank speakers with `Unknown_Speaker`.
|
||||
- Repairs/sanitizes timing fields deterministically; rejects invalid repaired timing.
|
||||
- Drops segments with missing or blank text.
|
||||
- Does not run merge modules.
|
||||
- When `--output-schema` is omitted, schema resolution is: `SERIATIM_OUTPUT_SCHEMA` -> default `seriatim-intermediate`.
|
||||
|
||||
## Common workflows
|
||||
|
||||
Merge with a speaker map and report output:
|
||||
|
||||
```sh
|
||||
go run ./cmd/seriatim merge \
|
||||
--input-file examples/minimal-merge/input-alice.json \
|
||||
--input-file examples/minimal-merge/input-bob.json \
|
||||
--speakers examples/minimal-merge/speakers.yml \
|
||||
--output-file /tmp/seriatim-example-merge.json \
|
||||
--report-file /tmp/seriatim-example-merge-report.json
|
||||
```
|
||||
|
||||
Trim to a segment subset:
|
||||
|
||||
```sh
|
||||
go run ./cmd/seriatim trim \
|
||||
--input-file examples/trim/input-full.json \
|
||||
--output-file /tmp/seriatim-example-trim.json \
|
||||
--keep "1-2"
|
||||
```
|
||||
|
||||
Normalize an external transcript JSON file:
|
||||
|
||||
```sh
|
||||
go run ./cmd/seriatim normalize \
|
||||
--input-file examples/normalize/object-with-segments.json \
|
||||
--output-file /tmp/seriatim-example-normalize-object.json
|
||||
```
|
||||
|
||||
## Exit and errors
|
||||
|
||||
- Commands return exit code `0` on success.
|
||||
- On error, the CLI prints one error line to stderr and exits with status `1`.
|
||||
- Cobra usage text is silenced on runtime errors; use `--help` for command usage.
|
||||
|
||||
## Related docs
|
||||
|
||||
- Configuration reference: [config.md](config.md)
|
||||
- Operations guide: [operations.md](operations.md)
|
||||
- Troubleshooting: [troubleshooting.md](troubleshooting.md)
|
||||
- Integration notes:
|
||||
- [integrations/whisperx-json.md](integrations/whisperx-json.md)
|
||||
- [integrations/output-schemas.md](integrations/output-schemas.md)
|
||||
- Synthetic examples: [../examples/README.md](../examples/README.md)
|
||||
- Public output schemas:
|
||||
- [../schema/minimal-output.schema.json](../schema/minimal-output.schema.json)
|
||||
- [../schema/intermediate-output.schema.json](../schema/intermediate-output.schema.json)
|
||||
- [../schema/full-output.schema.json](../schema/full-output.schema.json)
|
||||
- Documentation roadmap: [roadmap/documentation.md](roadmap/documentation.md)
|
||||
168
docs/config.md
Normal file
168
docs/config.md
Normal file
@@ -0,0 +1,168 @@
|
||||
# Configuration Reference
|
||||
|
||||
## Configuration surfaces
|
||||
|
||||
seriatim has no central JSON/TOML/YAML application config file.
|
||||
|
||||
Runtime configuration comes from:
|
||||
|
||||
1. CLI flags
|
||||
2. Environment variables (`SERIATIM_*`)
|
||||
3. Optional YAML rule files referenced by CLI flags (`--speakers`, `--autocorrect`)
|
||||
|
||||
## Output schema precedence
|
||||
|
||||
For `merge` and `normalize`:
|
||||
|
||||
1. `--output-schema` flag (when explicitly set)
|
||||
2. `SERIATIM_OUTPUT_SCHEMA`
|
||||
3. default `seriatim-intermediate`
|
||||
|
||||
For `trim`:
|
||||
|
||||
- If `--output-schema` is omitted, output preserves the input artifact schema.
|
||||
- If `--output-schema` is set, it must be one of `seriatim-minimal`, `seriatim-intermediate`, `seriatim-full`.
|
||||
|
||||
## Merge module defaults
|
||||
|
||||
Default merge module selections:
|
||||
|
||||
- `--input-reader`: `json-files`
|
||||
- `--preprocessing-modules`: `validate-raw,normalize-speakers,trim-text`
|
||||
- `--postprocessing-modules`: `detect-overlaps,resolve-overlaps,backchannel,filler,resolve-danglers,coalesce,detect-overlaps,autocorrect,assign-ids,validate-output`
|
||||
- `--output-modules`: `json`
|
||||
|
||||
Module-list notes:
|
||||
|
||||
- Lists are comma-separated.
|
||||
- Empty module names are invalid.
|
||||
- Unknown module names fail the command.
|
||||
- Preprocessing order must satisfy state requirements.
|
||||
|
||||
## Environment variables
|
||||
|
||||
| Variable | Default | Used by | Rules |
|
||||
| --- | --- | --- | --- |
|
||||
| `SERIATIM_OUTPUT_SCHEMA` | `seriatim-intermediate` | `merge`, `normalize` | Must be `seriatim-minimal`, `seriatim-intermediate`, or `seriatim-full`. Ignored when `--output-schema` is explicitly set. |
|
||||
| `SERIATIM_OVERLAP_WORD_RUN_GAP` | `1.0` | `merge` | Positive float (`> 0`). |
|
||||
| `SERIATIM_OVERLAP_WORD_RUN_REORDER_WINDOW` | `1.0` | `merge` | Positive float (`> 0`). |
|
||||
| `SERIATIM_BACKCHANNEL_MAX_DURATION` | `2.0` | `merge` | Positive float (`> 0`). |
|
||||
| `SERIATIM_FILLER_MAX_DURATION` | `1.25` | `merge` | Positive float (`> 0`). |
|
||||
|
||||
Additional merge threshold flag:
|
||||
|
||||
- `--coalesce-gap` defaults to `3.0` and must be a non-negative float (`>= 0`).
|
||||
|
||||
## `speakers.yml`
|
||||
|
||||
Purpose:
|
||||
|
||||
- Maps each merge input filename basename to a canonical speaker label.
|
||||
|
||||
Top-level key:
|
||||
|
||||
- `match` (array of ordered rules)
|
||||
|
||||
Rule fields:
|
||||
|
||||
- `speaker` (required, non-empty)
|
||||
- `match` (required, non-empty array of non-empty strings)
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
match:
|
||||
- speaker: "Alice"
|
||||
match:
|
||||
- "alice_track"
|
||||
- "alice"
|
||||
|
||||
- speaker: "Bob"
|
||||
match:
|
||||
- "bob_track"
|
||||
```
|
||||
|
||||
Behavior:
|
||||
|
||||
- Matching is case-insensitive.
|
||||
- Matching is against basename only (not full path).
|
||||
- First matching rule wins.
|
||||
- Duplicate `speaker` values are invalid.
|
||||
- If any input file has no match, merge fails.
|
||||
|
||||
## `autocorrect.yml`
|
||||
|
||||
Purpose:
|
||||
|
||||
- Applies ordered token-level text replacements during merge `autocorrect` postprocessing.
|
||||
|
||||
Top-level key:
|
||||
|
||||
- `autocorrect` (array of rules)
|
||||
|
||||
Rule fields:
|
||||
|
||||
- `target` (required, non-empty)
|
||||
- `match` (required, non-empty array of non-empty strings)
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
autocorrect:
|
||||
- target: "Godfrey"
|
||||
match:
|
||||
- "God-free"
|
||||
|
||||
- target: "Mike Brown"
|
||||
match:
|
||||
- "Mike Pat"
|
||||
```
|
||||
|
||||
Behavior:
|
||||
|
||||
- Match strings are case-sensitive.
|
||||
- Replacements are whole-token only (no substring replacement inside larger tokens).
|
||||
- Duplicate match strings within one rule are invalid.
|
||||
- Duplicate match strings across different rules are invalid.
|
||||
- If `--autocorrect` is not provided, the autocorrect module is skipped.
|
||||
|
||||
## Path and validation rules
|
||||
|
||||
All commands:
|
||||
|
||||
- `--input-file` paths must exist and must be files.
|
||||
- Output/report parent directories must already exist.
|
||||
- Paths are normalized before use.
|
||||
|
||||
`merge`:
|
||||
|
||||
- Requires at least one `--input-file`.
|
||||
- Rejects duplicate `--input-file` paths.
|
||||
- Sorts normalized input file paths for deterministic execution.
|
||||
- `--speakers` and `--autocorrect` are optional, but when set they must point to existing files.
|
||||
|
||||
`trim`:
|
||||
|
||||
- Requires exactly one of `--keep` or `--remove`.
|
||||
- `--keep` and `--remove` are mutually exclusive.
|
||||
- Validates optional `--output-schema` when provided.
|
||||
|
||||
`normalize`:
|
||||
|
||||
- Validates `--output-schema` through the same schema set as `merge`.
|
||||
- Currently accepts only `json` in `--output-modules`.
|
||||
|
||||
## Related docs
|
||||
|
||||
- CLI reference: [cli.md](cli.md)
|
||||
- Operations guide: [operations.md](operations.md)
|
||||
- Troubleshooting: [troubleshooting.md](troubleshooting.md)
|
||||
- YAML example files:
|
||||
- [../examples/speakers.yml](../examples/speakers.yml)
|
||||
- [../examples/autocorrect.yml](../examples/autocorrect.yml)
|
||||
- Synthetic examples: [../examples/README.md](../examples/README.md)
|
||||
- Public output schemas:
|
||||
- [../schema/minimal-output.schema.json](../schema/minimal-output.schema.json)
|
||||
- [../schema/intermediate-output.schema.json](../schema/intermediate-output.schema.json)
|
||||
- [../schema/full-output.schema.json](../schema/full-output.schema.json)
|
||||
- Documentation roadmap: [roadmap/documentation.md](roadmap/documentation.md)
|
||||
68
docs/integrations/output-schemas.md
Normal file
68
docs/integrations/output-schemas.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Output Schemas
|
||||
|
||||
## Scope
|
||||
|
||||
seriatim emits one of three public JSON output contracts:
|
||||
|
||||
- `seriatim-minimal`
|
||||
- `seriatim-intermediate`
|
||||
- `seriatim-full`
|
||||
|
||||
These are used by `merge`, `trim`, and `normalize`.
|
||||
|
||||
## Schema roles
|
||||
|
||||
`seriatim-minimal`:
|
||||
|
||||
- compact metadata plus ordered transcript segments
|
||||
- no source/provenance fields
|
||||
- no overlap groups
|
||||
|
||||
`seriatim-intermediate`:
|
||||
|
||||
- compact metadata plus ordered segments
|
||||
- includes optional segment `categories`
|
||||
- no source/provenance fields
|
||||
- no overlap groups
|
||||
|
||||
`seriatim-full`:
|
||||
|
||||
- full metadata (`input_reader`, module lists, input files, output modules)
|
||||
- source/provenance fields on segments
|
||||
- overlap-group data
|
||||
- version metadata populated from build info (`internal/buildinfo`)
|
||||
|
||||
## Semantic invariants
|
||||
|
||||
All schema outputs enforce:
|
||||
|
||||
- segment IDs are sequential starting at `1`
|
||||
- segment timing uses `end >= start`
|
||||
|
||||
Full schema also enforces overlap-group timing (`end >= start`).
|
||||
|
||||
## Validation APIs
|
||||
|
||||
Go package: `gitea.maximumdirect.net/eric/seriatim/schema`
|
||||
|
||||
Key validators:
|
||||
|
||||
- `schema.ValidateMinimalTranscript`
|
||||
- `schema.ValidateIntermediateTranscript`
|
||||
- `schema.ValidateTranscript`
|
||||
- `schema.ValidateMinimalJSON`
|
||||
- `schema.ValidateIntermediateJSON`
|
||||
- `schema.ValidateJSON`
|
||||
|
||||
## Machine-readable schema files
|
||||
|
||||
- [../../schema/minimal-output.schema.json](../../schema/minimal-output.schema.json)
|
||||
- [../../schema/intermediate-output.schema.json](../../schema/intermediate-output.schema.json)
|
||||
- [../../schema/full-output.schema.json](../../schema/full-output.schema.json)
|
||||
|
||||
## Related docs and examples
|
||||
|
||||
- CLI reference: [../cli.md](../cli.md)
|
||||
- Artifact internals: [../internal/artifacts.md](../internal/artifacts.md)
|
||||
- Trim example input artifact:
|
||||
- [../../examples/trim/input-full.json](../../examples/trim/input-full.json)
|
||||
85
docs/integrations/whisperx-json.md
Normal file
85
docs/integrations/whisperx-json.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# WhisperX-Like JSON Input
|
||||
|
||||
## Scope
|
||||
|
||||
This document covers the implemented JSON subset consumed by `seriatim merge`.
|
||||
It does not describe full WhisperX output.
|
||||
No explicit WhisperX version is encoded in the repository.
|
||||
|
||||
## Supported top-level shape
|
||||
|
||||
Merge expects a JSON object with top-level `segments` array:
|
||||
|
||||
```json
|
||||
{
|
||||
"segments": [
|
||||
{
|
||||
"start": 0.0,
|
||||
"end": 1.2,
|
||||
"text": "hello"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Supported segment fields
|
||||
|
||||
Required per segment:
|
||||
|
||||
- `start` (number, `>= 0`)
|
||||
- `end` (number, `>= start`)
|
||||
- `text` (string)
|
||||
|
||||
Optional per segment:
|
||||
|
||||
- `words` (array)
|
||||
|
||||
## Supported word fields
|
||||
|
||||
Required when a word object is present:
|
||||
|
||||
- `word` (string)
|
||||
|
||||
Optional word timing fields:
|
||||
|
||||
- `start` (number)
|
||||
- `end` (number)
|
||||
|
||||
Timing rules:
|
||||
|
||||
- if both `start` and `end` are present, they must be numeric and `end >= start`
|
||||
- if either timing field is missing, the word is accepted but not used as a
|
||||
timing anchor for overlap resolution
|
||||
|
||||
Additional optional word fields:
|
||||
|
||||
- `score` (number)
|
||||
- `speaker` (string)
|
||||
|
||||
## Validation and failure behavior
|
||||
|
||||
Merge fails for:
|
||||
|
||||
- malformed JSON
|
||||
- missing top-level `segments`
|
||||
- non-array `segments`
|
||||
- missing required segment fields
|
||||
- wrong field types
|
||||
- negative segment/word start times
|
||||
- segment/word end before start
|
||||
|
||||
Word timing missing from a word does not fail merge; it emits a warning event
|
||||
in the optional report.
|
||||
|
||||
## Overlap-resolution impact
|
||||
|
||||
- overlap resolution uses timed words when available
|
||||
- untimed words are kept in replacement text but do not provide timing anchors
|
||||
|
||||
## Related docs and examples
|
||||
|
||||
- CLI reference: [../cli.md](../cli.md)
|
||||
- Configuration reference: [../config.md](../config.md)
|
||||
- Minimal merge example inputs:
|
||||
- [../../examples/minimal-merge/input-alice.json](../../examples/minimal-merge/input-alice.json)
|
||||
- [../../examples/minimal-merge/input-bob.json](../../examples/minimal-merge/input-bob.json)
|
||||
140
docs/internal/artifacts.md
Normal file
140
docs/internal/artifacts.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# Artifact Internals
|
||||
|
||||
## Purpose
|
||||
|
||||
Describes public artifact conversion and validation internals for merge output,
|
||||
trim, and normalize.
|
||||
|
||||
## 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`
|
||||
|
||||
## Schema selection
|
||||
|
||||
Merge pipeline conversion 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`)
|
||||
|
||||
## Trim internals
|
||||
|
||||
`internal/trim` is artifact-level projection, not merge reprocessing.
|
||||
|
||||
Core flow:
|
||||
|
||||
1. Parse selector (`internal/trim/selector.go`).
|
||||
2. Parse input artifact and detect schema (`ParseArtifactJSON`).
|
||||
3. Apply keep/remove projection with sequential ID renumbering.
|
||||
4. Recompute overlap groups only for full-schema artifacts.
|
||||
5. Optionally convert output schema when supported.
|
||||
6. Validate output artifact before write.
|
||||
|
||||
Schema-conversion limits:
|
||||
|
||||
- full -> intermediate/minimal supported.
|
||||
- intermediate -> minimal supported.
|
||||
- minimal -> intermediate supported.
|
||||
- intermediate/minimal -> full is rejected.
|
||||
|
||||
Trim invariants:
|
||||
|
||||
- selected IDs must exist in input.
|
||||
- input IDs must be positive, unique, sequential.
|
||||
- retained order follows input transcript order.
|
||||
- output IDs are reassigned to `1..N`.
|
||||
|
||||
## 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:
|
||||
|
||||
- report events do not embed transcript text.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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)
|
||||
- output/report file write failures from command paths
|
||||
|
||||
## Tests to inspect before changes
|
||||
|
||||
- `schema/output_test.go`
|
||||
- `internal/artifact/transcript_test.go`
|
||||
- `internal/trim/selector_test.go`
|
||||
- `internal/trim/artifact_test.go`
|
||||
- `internal/trim/apply_test.go`
|
||||
- `internal/normalize/parse_test.go`
|
||||
- `internal/cli/trim_test.go`
|
||||
- `internal/cli/normalize_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.
|
||||
119
docs/internal/modules.md
Normal file
119
docs/internal/modules.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# Built-In Modules
|
||||
|
||||
## Purpose
|
||||
|
||||
Describes implemented built-in module behavior and boundaries in
|
||||
`internal/builtin`.
|
||||
|
||||
## Implemented module set
|
||||
|
||||
Input reader:
|
||||
|
||||
- `json-files`
|
||||
|
||||
Preprocessing:
|
||||
|
||||
- `validate-raw`
|
||||
- `normalize-speakers`
|
||||
- `trim-text`
|
||||
|
||||
Merger:
|
||||
|
||||
- `chronological-merge`
|
||||
|
||||
Postprocessing:
|
||||
|
||||
- `detect-overlaps`
|
||||
- `resolve-overlaps`
|
||||
- `backchannel`
|
||||
- `filler`
|
||||
- `resolve-danglers`
|
||||
- `coalesce`
|
||||
- `autocorrect`
|
||||
- `assign-ids`
|
||||
- `validate-output`
|
||||
|
||||
Output writer:
|
||||
|
||||
- `json`
|
||||
|
||||
## Inputs, outputs, and side effects
|
||||
|
||||
- `json-files`: reads JSON files from `cfg.InputFiles`, parses supported
|
||||
segment/word fields, emits warnings for untimed words.
|
||||
- `validate-raw`: validates raw source/timing invariants.
|
||||
- `normalize-speakers`: converts raw transcripts to canonical segments,
|
||||
optionally resolving speakers from `cfg.SpeakersFile`.
|
||||
- `trim-text`: trims canonical segment text whitespace.
|
||||
- `chronological-merge`: flattens canonical segments and applies deterministic
|
||||
sort (`model.SegmentLess`).
|
||||
- `detect-overlaps`: annotates overlap groups.
|
||||
- `resolve-overlaps`: rewrites overlap groups using timed words and thresholds.
|
||||
- `backchannel`/`filler`: classify short utterances using duration thresholds.
|
||||
- `resolve-danglers`: merges dangling derived fragments.
|
||||
- `coalesce`: merges adjacent same-speaker segments within configured gap.
|
||||
- `autocorrect`: applies YAML replacement rules when configured.
|
||||
- `assign-ids`: assigns final sequential IDs.
|
||||
- `validate-output`: validates selected public artifact shape.
|
||||
- `json`: writes artifact JSON to `cfg.OutputFile`.
|
||||
|
||||
Filesystem side effects are limited to:
|
||||
|
||||
- reading configured input/YAML files
|
||||
- writing configured output artifact
|
||||
|
||||
## Config fields used
|
||||
|
||||
Primary module inputs from `config.Config`:
|
||||
|
||||
- file paths: `InputFiles`, `SpeakersFile`, `AutocorrectFile`, `OutputFile`
|
||||
- schema/modules: `OutputSchema`, `OutputModules`
|
||||
- overlap/coalesce thresholds: `OverlapWordRunGap`,
|
||||
`WordRunReorderWindow`, `CoalesceGap`
|
||||
- category thresholds: `BackchannelMaxDuration`, `FillerMaxDuration`
|
||||
|
||||
## Ordering constraints
|
||||
|
||||
- Preprocessing must satisfy state contracts from `raw` to `canonical`.
|
||||
- Order-sensitive transforms should run before `assign-ids`.
|
||||
- `validate-output` should run after final ID assignment and output-shape
|
||||
mutations.
|
||||
- Default configuration includes a second `detect-overlaps` pass after
|
||||
transformations.
|
||||
|
||||
## Boundaries
|
||||
|
||||
- Modules implement behavior; CLI/config parsing remains outside modules.
|
||||
- Modules communicate through explicit model contracts and report events.
|
||||
- Output modules operate on final artifacts and do not re-run transform logic.
|
||||
|
||||
## Failure behavior
|
||||
|
||||
Representative failures:
|
||||
|
||||
- invalid input JSON shape or typed field errors (`json-files`)
|
||||
- invalid YAML or unmatched speaker map entries
|
||||
- unknown module names during registry resolution
|
||||
- invalid ordering/state transitions in preprocessing chain
|
||||
- validation failure in `validate-output`
|
||||
- output write failure in `json` writer
|
||||
|
||||
## Tests to inspect before changes
|
||||
|
||||
- `internal/builtin/preprocess_test.go`
|
||||
- `internal/builtin/postprocess_test.go`
|
||||
- `internal/overlap/resolve_test.go`
|
||||
- `internal/overlap/detect_test.go`
|
||||
- `internal/coalesce/coalesce_test.go`
|
||||
- `internal/danglers/danglers_test.go`
|
||||
- `internal/backchannel/backchannel_test.go`
|
||||
- `internal/filler/filler_test.go`
|
||||
- `internal/autocorrect/autocorrect_test.go`
|
||||
- `internal/cli/merge_test.go`
|
||||
|
||||
## Invariants
|
||||
|
||||
- Modules are selected by canonical name through the registry.
|
||||
- Execution is sequential and deterministic for a fixed configuration.
|
||||
- `assign-ids` defines final public segment IDs.
|
||||
- `validate-output` enforces public artifact contracts through `schema`.
|
||||
102
docs/internal/pipeline.md
Normal file
102
docs/internal/pipeline.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# Pipeline Internals
|
||||
|
||||
## Purpose
|
||||
|
||||
Describes implemented merge pipeline orchestration in `internal/pipeline`.
|
||||
|
||||
## Inputs and outputs
|
||||
|
||||
Input:
|
||||
|
||||
- `config.Config`
|
||||
- registry-resolved modules from `internal/builtin`
|
||||
|
||||
Output:
|
||||
|
||||
- selected public artifact written by output writer modules
|
||||
- optional report JSON when `cfg.ReportFile` is set
|
||||
|
||||
## Stage contracts
|
||||
|
||||
The runner executes these contracts in order:
|
||||
|
||||
1. `InputReader`: external inputs -> `[]model.RawTranscript`
|
||||
2. `Preprocessor`: `PreprocessState` transformations (`raw` -> `canonical`)
|
||||
3. `Merger`: canonical transcripts -> `model.MergedTranscript`
|
||||
4. `Postprocessor`: merged transcript transformations
|
||||
5. `OutputWriter`: serialized artifact writes
|
||||
|
||||
`PreprocessState` must end in `StateCanonical` before merge.
|
||||
|
||||
## Registry resolution
|
||||
|
||||
`resolvePlan` maps configured names to modules:
|
||||
|
||||
- input reader: `cfg.InputReader`
|
||||
- preprocessors: `cfg.PreprocessingModules`
|
||||
- postprocessors: `cfg.PostprocessingModules`
|
||||
- output writers: `cfg.OutputModules`
|
||||
- merger: single registered merger
|
||||
|
||||
Unknown names fail fast with contextual errors.
|
||||
|
||||
## Execution order and reporting
|
||||
|
||||
- Modules run sequentially in configured order.
|
||||
- Events returned by modules are appended in execution order.
|
||||
- Report metadata includes input reader, input files, and module lists.
|
||||
- Output writer events are appended before optional report write.
|
||||
|
||||
## Config fields used
|
||||
|
||||
Runner-level fields:
|
||||
|
||||
- `InputReader`
|
||||
- `InputFiles`
|
||||
- `PreprocessingModules`
|
||||
- `PostprocessingModules`
|
||||
- `OutputModules`
|
||||
- `OutputSchema` (via `artifact.SelectedFromMerged`)
|
||||
- `ReportFile`
|
||||
|
||||
Module-specific settings are consumed inside builtin modules (for example
|
||||
coalesce gap and overlap thresholds).
|
||||
|
||||
## Adapters used
|
||||
|
||||
- Input adapters: registered `InputReader` implementations (default `json-files`).
|
||||
- Output adapters: registered `OutputWriter` implementations (default `json`).
|
||||
- Report adapter: `report.WriteJSON` when `cfg.ReportFile` is provided.
|
||||
|
||||
## Boundaries
|
||||
|
||||
- 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.
|
||||
|
||||
## Failure behavior
|
||||
|
||||
Pipeline returns errors from:
|
||||
|
||||
- registry resolution (unknown modules, missing merger)
|
||||
- invalid preprocessing state transitions
|
||||
- module read/process/merge/write failures
|
||||
- optional report write failure
|
||||
|
||||
No retry/resume state is stored.
|
||||
|
||||
## Tests to inspect before changes
|
||||
|
||||
- `internal/pipeline/runner_test.go`
|
||||
- `internal/builtin/preprocess_test.go`
|
||||
- `internal/builtin/postprocess_test.go`
|
||||
- `internal/cli/merge_test.go`
|
||||
|
||||
## Invariants
|
||||
|
||||
- Sequential deterministic execution order.
|
||||
- Preprocessing state must type-check from `raw` to `canonical`.
|
||||
- Module selection is explicit by canonical names.
|
||||
- Report event order reflects actual execution order.
|
||||
- Output artifact selection is schema-driven via `internal/artifact`.
|
||||
136
docs/operations.md
Normal file
136
docs/operations.md
Normal file
@@ -0,0 +1,136 @@
|
||||
# Operations Guide
|
||||
|
||||
## Scope
|
||||
|
||||
This document covers runtime operation of the implemented CLI commands:
|
||||
|
||||
- `merge`
|
||||
- `trim`
|
||||
- `normalize`
|
||||
|
||||
## Runtime model
|
||||
|
||||
seriatim is a single-process, filesystem-only CLI.
|
||||
|
||||
- Each invocation reads input files, processes in memory, and writes output files.
|
||||
- There is no daemon, queue, database, resume checkpoint, remote storage, or background worker.
|
||||
- On error, the command exits non-zero; there is no built-in retry/resume flow.
|
||||
|
||||
## Filesystem expectations
|
||||
|
||||
All commands require accessible local files and existing parent directories for outputs.
|
||||
|
||||
- Input paths must exist and must be files.
|
||||
- Output/report parent directories must already exist.
|
||||
- Output and report files are created with `os.Create`, so existing files at those paths are overwritten.
|
||||
|
||||
Command-specific expectations:
|
||||
|
||||
- `merge`: requires at least one `--input-file`; optional `--speakers` and `--autocorrect` paths must exist when provided.
|
||||
- `trim`: input must be an existing valid seriatim artifact JSON file.
|
||||
- `normalize`: input must be a JSON object with `segments` or a top-level segment array.
|
||||
|
||||
## Normal workflow
|
||||
|
||||
### Merge
|
||||
|
||||
1. Provide one or more `--input-file` values.
|
||||
2. Optionally provide `--speakers`, `--autocorrect`, and `--report-file`.
|
||||
3. Provide `--output-file`.
|
||||
4. Run command.
|
||||
|
||||
Example:
|
||||
|
||||
```sh
|
||||
go run ./cmd/seriatim merge \
|
||||
--input-file speaker-a.json \
|
||||
--input-file speaker-b.json \
|
||||
--output-file merged.json \
|
||||
--report-file merge-report.json
|
||||
```
|
||||
|
||||
### Trim
|
||||
|
||||
1. Provide existing artifact with `--input-file`.
|
||||
2. Select segments with exactly one of `--keep` or `--remove`.
|
||||
3. Provide `--output-file`.
|
||||
4. Optionally provide `--output-schema`, `--allow-empty`, and `--report-file`.
|
||||
|
||||
Example:
|
||||
|
||||
```sh
|
||||
go run ./cmd/seriatim trim \
|
||||
--input-file merged.json \
|
||||
--output-file trimmed.json \
|
||||
--keep "1-20,25"
|
||||
```
|
||||
|
||||
### Normalize
|
||||
|
||||
1. Provide `--input-file` containing supported JSON shape.
|
||||
2. Provide `--output-file`.
|
||||
3. Optionally provide `--output-schema`, `--output-modules`, and `--report-file`.
|
||||
|
||||
Example:
|
||||
|
||||
```sh
|
||||
go run ./cmd/seriatim normalize \
|
||||
--input-file external.json \
|
||||
--output-file normalized.json \
|
||||
--report-file normalize-report.json
|
||||
```
|
||||
|
||||
## Output and report artifacts
|
||||
|
||||
Primary output:
|
||||
|
||||
- `--output-file` writes JSON transcript artifact in selected schema.
|
||||
|
||||
Optional report output:
|
||||
|
||||
- `--report-file` writes deterministic JSON report events.
|
||||
- `merge` report metadata records reader/modules and event sequence.
|
||||
- `trim` report includes a `trim-audit` event with mode/selector/counts and old-to-new ID mapping.
|
||||
- `normalize` report includes a `normalize-audit` event with input shape, repair stats, and output selection details.
|
||||
|
||||
## Failure and retry behavior
|
||||
|
||||
Failure behavior:
|
||||
|
||||
- Errors are printed once to stderr by the root command and exit status is `1`.
|
||||
- There is no partial-state recovery mechanism.
|
||||
|
||||
Retry guidance:
|
||||
|
||||
1. Fix the reported input/config/path issue.
|
||||
2. Re-run the same command.
|
||||
3. If a prior run created a partial or unwanted output/report file, remove it and rerun.
|
||||
|
||||
Operational note:
|
||||
|
||||
- With identical inputs/config/version, merge behavior is deterministic and input files are sorted before processing.
|
||||
|
||||
## Cleanup
|
||||
|
||||
seriatim does not manage retention.
|
||||
|
||||
- Remove unneeded output/report artifacts manually.
|
||||
- No cache, state directory, or lock files are maintained by the application.
|
||||
|
||||
## Privacy considerations
|
||||
|
||||
Transcript artifacts and reports are local files and may contain sensitive conversational data.
|
||||
|
||||
- Store outputs in controlled directories with appropriate OS permissions.
|
||||
- Share report files carefully; they include file paths and processing diagnostics.
|
||||
- Normalize report events intentionally avoid embedding transcript text, but output artifacts contain transcript content.
|
||||
|
||||
## Related docs
|
||||
|
||||
- CLI reference: [cli.md](cli.md)
|
||||
- Configuration reference: [config.md](config.md)
|
||||
- Troubleshooting: [troubleshooting.md](troubleshooting.md)
|
||||
- Integration notes:
|
||||
- [integrations/whisperx-json.md](integrations/whisperx-json.md)
|
||||
- [integrations/output-schemas.md](integrations/output-schemas.md)
|
||||
- Synthetic examples: [../examples/README.md](../examples/README.md)
|
||||
218
docs/policy/architecture.md
Normal file
218
docs/policy/architecture.md
Normal file
@@ -0,0 +1,218 @@
|
||||
# Architecture Policy
|
||||
|
||||
## Purpose
|
||||
|
||||
This document defines seriatim's development architecture and invariants for
|
||||
maintainers and automated coding agents. It describes how the implemented
|
||||
system is intended to be built and changed. It is not a user manual, CLI
|
||||
reference, config reference, or roadmap.
|
||||
|
||||
Keep this document aligned with [documentation policy](documentation.md). It
|
||||
must describe current behavior only; planned or speculative work belongs under
|
||||
`docs/roadmap/`.
|
||||
|
||||
## Project Shape
|
||||
|
||||
seriatim is a Go CLI for transcript artifact processing. The implemented
|
||||
commands are `merge`, `trim`, and `normalize`.
|
||||
|
||||
`merge` reads one or more JSON transcript files, optionally maps input files to
|
||||
canonical speakers, runs a registry-selected preprocessing chain, merges
|
||||
canonical segments into deterministic chronological order, runs a
|
||||
registry-selected postprocessing chain, validates the selected output schema,
|
||||
and writes JSON output plus an optional JSON report.
|
||||
|
||||
`trim` and `normalize` are artifact-level commands outside the merge pipeline.
|
||||
`trim` reads an existing seriatim output artifact and projects it by segment ID.
|
||||
`normalize` reads transcript-like JSON and emits one of seriatim's supported
|
||||
output schemas. Neither command runs merge preprocessing or postprocessing
|
||||
modules.
|
||||
|
||||
The supported public output schemas are `seriatim-minimal`,
|
||||
`seriatim-intermediate`, and `seriatim-full`. For command and flag details, use
|
||||
[CLI reference](../cli.md) and [configuration reference](../config.md).
|
||||
|
||||
## Core Design Principles
|
||||
|
||||
- Keep a hexagonal architecture boundary. Domain models, stage contracts, and
|
||||
deterministic transformations must stay separate from CLI parsing,
|
||||
filesystem access, config loading, reporting, and other external adapters.
|
||||
- Keep stages and modules composable. Built-in modules are selected by
|
||||
canonical registry names and implement explicit interfaces for their pipeline
|
||||
role.
|
||||
- Preserve deterministic behavior. Given the same inputs, configuration, and
|
||||
version, output ordering, segment IDs, schema validation, and report event
|
||||
ordering should remain stable.
|
||||
- Current command execution is sequential. There is no scheduler, worker pool,
|
||||
or concurrent module execution in the implemented pipeline. Any concurrency
|
||||
added later must be bounded, observable, and must not make output handling
|
||||
nondeterministic.
|
||||
- Prefer the Go standard library. Third-party dependencies should remain narrow
|
||||
and justified, such as Cobra for CLI structure, YAML parsing, and JSON Schema
|
||||
validation.
|
||||
- Document current behavior. Architecture, user, and internal docs must not
|
||||
describe planned features as implemented behavior.
|
||||
|
||||
## Architectural Boundaries
|
||||
|
||||
Core transcript data belongs in `internal/model` and public artifact contracts
|
||||
belong in `schema`. Conversion from internal merged data to public JSON shapes
|
||||
belongs at the artifact boundary, not inside CLI code or transformation
|
||||
packages.
|
||||
|
||||
Pipeline orchestration belongs in `internal/pipeline`. It resolves registered
|
||||
modules, validates preprocessing state transitions, executes stages in order,
|
||||
collects report events, converts the final transcript, and writes optional
|
||||
reports. Built-in adapters and modules are registered from `internal/builtin`.
|
||||
|
||||
CLI code in `internal/cli` should parse flags, build validated config values,
|
||||
and delegate. `merge` delegates to `pipeline.Run`; `trim` and `normalize`
|
||||
perform artifact-level orchestration and delegate deterministic parsing,
|
||||
validation, and transformation work to their internal packages.
|
||||
|
||||
Config loading and validation belongs in `internal/config`. Filesystem reads and
|
||||
writes are adapter concerns and should not spread into pure transformation
|
||||
helpers. Existing built-in modules that load configured YAML files must keep
|
||||
that I/O narrow and explicit.
|
||||
|
||||
Reports belong in `internal/report`. Modules and commands should emit concise
|
||||
events for validation findings, corrections, and transformations without
|
||||
turning report messages into a duplicate output artifact.
|
||||
|
||||
Tests and samples are supporting evidence for behavior. Tests should verify
|
||||
stable contracts and edge cases; samples should remain valid examples, not
|
||||
hidden architecture dependencies.
|
||||
|
||||
## Modules or Stages
|
||||
|
||||
The merge pipeline has these implemented stages:
|
||||
|
||||
- `InputReader`: reads configured external input into raw transcripts.
|
||||
- `Preprocessor`: transforms `PreprocessState` from raw to canonical state.
|
||||
- `Merger`: combines canonical transcripts into one merged transcript.
|
||||
- `Postprocessor`: transforms or annotates the merged transcript.
|
||||
- `OutputWriter`: writes the selected output artifact.
|
||||
|
||||
Modules must keep narrow responsibilities, declare their stage through the
|
||||
interface they implement, and use explicit config values. Preprocessors must
|
||||
declare `Requires()` and `Produces()` states; the runner rejects invalid
|
||||
raw/canonical ordering before processing completes.
|
||||
|
||||
Modules run in the configured order. Order-affecting modules must run before
|
||||
`assign-ids`, and `validate-output` must see final IDs that match the selected
|
||||
schema. Accepted and rejected transformations should be deterministic and, when
|
||||
observable, recorded through report events.
|
||||
|
||||
Transformation helpers should avoid hidden global state. Shared caches, such as
|
||||
compiled JSON schemas, must be protected and must not affect output ordering.
|
||||
|
||||
## State, Inputs, and Outputs
|
||||
|
||||
seriatim is file-based. It reads JSON inputs and optional YAML rule files, then
|
||||
writes JSON transcript artifacts and optional JSON reports.
|
||||
|
||||
The implemented application has no durable database, daemon state, resume
|
||||
state, remote storage, or background job state. Runtime state is held in memory
|
||||
for the current command invocation and serialized only through requested output
|
||||
and report files.
|
||||
|
||||
Input file paths are normalized and validated during config construction.
|
||||
`merge` sorts input file paths before processing, then uses stable segment sort
|
||||
keys. `trim` preserves transcript order while renumbering retained IDs.
|
||||
`normalize` sorts by implemented deterministic keys and assigns fresh IDs.
|
||||
|
||||
## Configuration and CLI Boundaries
|
||||
|
||||
The CLI surface is an adapter over validated config structs. Cobra command code
|
||||
should stay thin: parse flags, account for flag/default precedence, call config
|
||||
constructors, and delegate.
|
||||
|
||||
Config constructors validate required paths, output parent directories, module
|
||||
lists, selected schemas, mutually exclusive trim selector options, and supported
|
||||
environment-derived settings. Module name validation is split between config
|
||||
where command-specific names are fixed and the pipeline registry where module
|
||||
composition is resolved.
|
||||
|
||||
Do not duplicate full CLI or config reference material here. Use
|
||||
[CLI reference](../cli.md) and [configuration reference](../config.md) for
|
||||
canonical user-facing details.
|
||||
|
||||
## Errors, Logging, and Diagnostics
|
||||
|
||||
Commands return errors instead of printing inside deep logic. The root command
|
||||
silences Cobra usage/error output, and `cmd/seriatim/main.go` prints one error
|
||||
to stderr and exits with status `1`.
|
||||
|
||||
Validation failures should fail fast with contextual errors. Correctable
|
||||
conditions should be deterministic and, where reports are requested, reflected
|
||||
as report events. Optional reports contain metadata and ordered events; they are
|
||||
not required for command success unless the report file itself cannot be
|
||||
written.
|
||||
|
||||
The implemented code does not use a logging subsystem. Diagnostics are returned
|
||||
as errors or written to optional report JSON. Normalize report events avoid
|
||||
embedding transcript text; keep that privacy-oriented behavior when changing
|
||||
normalize diagnostics.
|
||||
|
||||
## Testing Expectations
|
||||
|
||||
`go test ./...` is the repository-wide check. There is currently no Makefile,
|
||||
taskfile, linter config, or dedicated documentation check.
|
||||
|
||||
When changing config or CLI behavior, inspect `internal/config` and
|
||||
`internal/cli` tests. When changing pipeline composition or stage contracts,
|
||||
inspect `internal/pipeline` and `internal/builtin` tests. When changing
|
||||
correction or annotation modules, inspect the package tests for overlap,
|
||||
coalesce, danglers, backchannel, filler, and autocorrect behavior.
|
||||
|
||||
When changing artifact-level commands, inspect `internal/trim`,
|
||||
`internal/normalize`, and their CLI tests. When changing public output shape or
|
||||
schema validation, inspect `schema` and `internal/artifact` tests. Report and
|
||||
diagnostic changes should be covered through the command or package tests that
|
||||
emit the affected events.
|
||||
|
||||
## Dependency Policy
|
||||
|
||||
Prefer the Go standard library for parsing, data transformation, concurrency
|
||||
primitives, filesystem work, and testing wherever it is reasonable.
|
||||
|
||||
Third-party dependencies must be narrow, justified, and preferably de facto
|
||||
standard for their purpose. Existing examples include Cobra for CLI structure,
|
||||
`gopkg.in/yaml.v3` for YAML files, and `jsonschema/v6` for validating embedded
|
||||
public JSON schemas. Avoid broad framework dependencies for behavior that is
|
||||
already simple and local.
|
||||
|
||||
## Documentation Expectations
|
||||
|
||||
Architecture docs must stay aligned with [documentation policy](documentation.md).
|
||||
Current-behavior docs must not become aspirational. If code and docs disagree,
|
||||
fix the inaccurate current-behavior doc or put planned work under
|
||||
`docs/roadmap/`.
|
||||
|
||||
Prefer links to canonical docs instead of repeating full CLI, config, schema, or
|
||||
operations reference material. Keep examples real, tested where practical, and
|
||||
free of secrets or private transcript data.
|
||||
|
||||
## Architectural Invariants
|
||||
|
||||
- Keep core/domain logic separate from CLI, config, filesystem, reporting, and
|
||||
other adapter concerns.
|
||||
- Keep modules narrowly scoped, explicitly configured, and composable by
|
||||
registry name.
|
||||
- Preserve deterministic ordering, final segment ID assignment, and schema
|
||||
validation before output acceptance.
|
||||
- Keep `trim` and `normalize` artifact-level; do not run merge modules from
|
||||
those commands.
|
||||
- Keep public output schemas validated through `schema`.
|
||||
- Keep optional reports ordered, concise, and diagnostic.
|
||||
- Avoid broad dependencies without a concrete maintainability benefit.
|
||||
- Do not document unimplemented behavior outside `docs/roadmap/`.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
The implemented application does not perform transcription, audio diarization,
|
||||
speaker inference from audio or text, summarization, daemon operation, remote
|
||||
storage, dynamic external plugin loading, or concurrent pipeline execution.
|
||||
|
||||
The architecture policy is not a package-by-package reference, CLI manual,
|
||||
config reference, schema reference, or roadmap.
|
||||
110
docs/policy/development.md
Normal file
110
docs/policy/development.md
Normal file
@@ -0,0 +1,110 @@
|
||||
# Development Policy
|
||||
|
||||
## Purpose
|
||||
|
||||
This document defines contributor workflow for maintainers and coding agents.
|
||||
It complements [architecture policy](architecture.md) and
|
||||
[documentation policy](documentation.md).
|
||||
|
||||
## Repository layout
|
||||
|
||||
- `cmd/seriatim/`: process entrypoint.
|
||||
- `internal/cli/`: Cobra commands and flag wiring.
|
||||
- `internal/config/`: option normalization and validation.
|
||||
- `internal/pipeline/`: orchestration interfaces, registry, runner.
|
||||
- `internal/builtin/`: implemented input/pre/post/output modules and merger.
|
||||
- `internal/artifact/`: conversion from internal merged model to public shapes.
|
||||
- `internal/trim/`: artifact-level trim logic.
|
||||
- `internal/normalize/`: artifact-level normalize parsing/building.
|
||||
- `internal/*` domain packages: overlap, coalesce, danglers, filler,
|
||||
backchannel, speaker, autocorrect, report, model.
|
||||
- `schema/`: public structs plus embedded JSON Schemas and validation.
|
||||
- `docs/`: policy, user docs, roadmap, and internal docs.
|
||||
|
||||
## Local checks
|
||||
|
||||
Primary repository check:
|
||||
|
||||
```sh
|
||||
go test ./...
|
||||
```
|
||||
|
||||
Useful manual checks for CLI-facing changes:
|
||||
|
||||
```sh
|
||||
go run ./cmd/seriatim --help
|
||||
go run ./cmd/seriatim merge --help
|
||||
go run ./cmd/seriatim trim --help
|
||||
go run ./cmd/seriatim normalize --help
|
||||
```
|
||||
|
||||
Current toolchain note:
|
||||
|
||||
- There is no Makefile.
|
||||
- There is no taskfile.
|
||||
- There is no committed linter configuration.
|
||||
- There is no automated documentation checker.
|
||||
|
||||
## Coding conventions
|
||||
|
||||
- Keep core behavior deterministic for identical inputs/config/version.
|
||||
- Keep CLI command functions thin: parse flags, construct config, delegate.
|
||||
- Keep validation in `internal/config` and package-specific validators.
|
||||
- Return errors from deep logic; do not print inside internal packages.
|
||||
- Preserve clear package boundaries between adapters and domain transforms.
|
||||
|
||||
## Dependency policy
|
||||
|
||||
Prefer the Go standard library first.
|
||||
|
||||
Third-party dependencies should stay narrow and justified. Current direct
|
||||
runtime dependencies are:
|
||||
|
||||
- `github.com/spf13/cobra` for CLI structure.
|
||||
- `gopkg.in/yaml.v3` for YAML rule files.
|
||||
- `github.com/santhosh-tekuri/jsonschema/v6` for public schema validation.
|
||||
|
||||
## Adding CLI flags
|
||||
|
||||
1. Add the flag in the relevant `internal/cli/*.go` command.
|
||||
2. Thread the raw value through `config.*Options`.
|
||||
3. Add normalization/validation in `internal/config/config.go`.
|
||||
4. Update or add CLI/config tests.
|
||||
5. Update canonical docs (`docs/cli.md`, `docs/config.md`) if user-visible.
|
||||
|
||||
## Adding config fields or environment variables
|
||||
|
||||
1. Add field(s) to the relevant config struct(s).
|
||||
2. Parse and validate in `internal/config/config.go`.
|
||||
3. Add tests in `internal/config/config_test.go`.
|
||||
4. Thread validated values into consuming modules.
|
||||
5. Update `docs/config.md` and related docs.
|
||||
|
||||
## Adding modules or pipeline behavior
|
||||
|
||||
1. Implement the module in the appropriate package (often `internal/builtin`).
|
||||
2. Expose a stable module name via `Name()`.
|
||||
3. Register it in `internal/builtin/registry.go`.
|
||||
4. Ensure preprocessing modules declare correct `Requires()`/`Produces()`
|
||||
states.
|
||||
5. Add/adjust tests in module packages and `internal/cli/merge_test.go`.
|
||||
6. Document internal behavior changes in `docs/internal/`.
|
||||
|
||||
## Schema and artifact changes
|
||||
|
||||
1. Update public structs and validation logic in `schema/`.
|
||||
2. Update embedded JSON Schema files (`schema/*.schema.json`) if contract
|
||||
changes.
|
||||
3. Update conversion behavior in `internal/artifact`, `internal/trim`, and/or
|
||||
`internal/normalize` as needed.
|
||||
4. Add tests in `schema/`, `internal/artifact/`, `internal/trim/`,
|
||||
`internal/normalize/`, and CLI tests.
|
||||
5. Update user and internal docs that reference output contracts.
|
||||
|
||||
## Documentation expectations
|
||||
|
||||
- Outside `docs/roadmap/`, document only implemented behavior.
|
||||
- Keep canonical homes: CLI in `docs/cli.md`, config in `docs/config.md`,
|
||||
operations in `docs/operations.md`, troubleshooting in
|
||||
`docs/troubleshooting.md`, internals in `docs/internal/`.
|
||||
- When behavior changes, update docs in the same change.
|
||||
356
docs/policy/documentation.md
Normal file
356
docs/policy/documentation.md
Normal file
@@ -0,0 +1,356 @@
|
||||
# Go Project Documentation Policy
|
||||
|
||||
## Purpose
|
||||
|
||||
Project documentation must help four audiences:
|
||||
|
||||
1. users who need to run the application;
|
||||
2. administrators/operators who need to configure and operate it;
|
||||
3. developers who need to understand and change it safely;
|
||||
4. LLM coding agents that need clear scope, boundaries, and invariants.
|
||||
|
||||
Docs should be accurate, concise, task-oriented, and organized by audience. Prefer links to canonical docs over repetition.
|
||||
|
||||
## Core Rules
|
||||
|
||||
### 1. Keep docs concise
|
||||
|
||||
Each document should cover a defined scope and only the essentials for that scope.
|
||||
|
||||
Avoid:
|
||||
- long background explanations;
|
||||
- repeated reference material;
|
||||
- implementation detail in user-facing docs;
|
||||
- aspirational language outside roadmap docs;
|
||||
- verbose examples where one minimal example is clearer.
|
||||
|
||||
### 2. Document only implemented behavior outside roadmap files
|
||||
|
||||
Unimplemented, planned, aspirational, experimental, or future work may be described only under:
|
||||
|
||||
- `docs/roadmap/`
|
||||
|
||||
No other documentation file, including `README.md`, should describe code, features, modules, stages, commands, config fields, or behaviors that do not currently exist.
|
||||
|
||||
If a feature is partial, non-roadmap docs may describe only the implemented portion and its current boundary.
|
||||
|
||||
### 3. Use canonical homes
|
||||
|
||||
Each type of information should have one canonical location.
|
||||
|
||||
Canonical homes:
|
||||
|
||||
- project purpose and quickstart: `README.md`
|
||||
- development principles: `docs/policy/architecture.md`
|
||||
- configuration reference: `docs/config.md`
|
||||
- CLI reference: `docs/cli.md`
|
||||
- operations and recovery: `docs/operations.md`
|
||||
- troubleshooting: `docs/troubleshooting.md`
|
||||
- implemented internals: `docs/internal/`
|
||||
- future work: `docs/roadmap/`
|
||||
- contributor workflow: `docs/policy/development.md`
|
||||
- copyable examples: `examples/`
|
||||
|
||||
Other files should summarize briefly and link to the canonical source.
|
||||
|
||||
### 4. Keep examples real
|
||||
|
||||
Examples should be valid, maintained, and free of secrets.
|
||||
|
||||
Where practical:
|
||||
- example configs should load successfully;
|
||||
- example commands should match real CLI syntax;
|
||||
- important examples should be covered by tests.
|
||||
|
||||
## Documentation Profiles
|
||||
|
||||
All projects require:
|
||||
|
||||
- `README.md`
|
||||
- `docs/policy/architecture.md`
|
||||
|
||||
Additional docs depend on the project.
|
||||
|
||||
### Small library
|
||||
|
||||
Recommended:
|
||||
- `docs/policy/development.md`, if contributor conventions are non-obvious
|
||||
|
||||
### Simple CLI
|
||||
|
||||
Required:
|
||||
- `docs/cli.md`
|
||||
|
||||
Recommended:
|
||||
- `docs/policy/development.md`
|
||||
|
||||
### Config-driven CLI
|
||||
|
||||
Required:
|
||||
- `docs/cli.md`
|
||||
- `docs/config.md`
|
||||
|
||||
Recommended:
|
||||
- `examples/`
|
||||
- `docs/policy/development.md`
|
||||
|
||||
### Stateful or operator-facing application
|
||||
|
||||
Required:
|
||||
- `docs/cli.md`, if CLI-based
|
||||
- `docs/config.md`, if config-driven
|
||||
- `docs/operations.md`
|
||||
|
||||
Recommended:
|
||||
- `docs/troubleshooting.md`
|
||||
- `examples/`
|
||||
- `docs/policy/development.md`
|
||||
|
||||
### Modular, staged, service-oriented, or orchestration application
|
||||
|
||||
Required:
|
||||
- `docs/cli.md`, if CLI-based
|
||||
- `docs/config.md`, if config-driven
|
||||
- `docs/operations.md`
|
||||
- `docs/internal/`
|
||||
- `docs/policy/development.md`
|
||||
|
||||
Recommended:
|
||||
- `docs/troubleshooting.md`
|
||||
- validated examples under `examples/`
|
||||
|
||||
## Required Documents
|
||||
|
||||
### README.md
|
||||
|
||||
**Audience:** users, administrators, operators
|
||||
|
||||
The README is the outward-facing project orientation page.
|
||||
|
||||
It should include, in order:
|
||||
|
||||
1. concise description;
|
||||
2. elevator pitch;
|
||||
3. shortest useful command or usage example;
|
||||
4. links to targeted docs.
|
||||
|
||||
The README should be short. It is not a manual.
|
||||
|
||||
The “shortest useful command” means the simplest command that performs the project’s core use case. (It does not mean `app --help`.)
|
||||
|
||||
### docs/policy/architecture.md
|
||||
|
||||
**Audience:** developers, LLM coding agents
|
||||
|
||||
`docs/policy/architecture.md` is required for every project.
|
||||
|
||||
It is an inward-facing development policy document. It should describe how the project is intended to be built and changed.
|
||||
|
||||
It should include:
|
||||
|
||||
- project shape;
|
||||
- core design principles;
|
||||
- package and boundary philosophy;
|
||||
- state/persistence philosophy, if applicable;
|
||||
- external integration philosophy, if applicable;
|
||||
- error-handling and logging principles;
|
||||
- testing expectations;
|
||||
- documentation expectations;
|
||||
- architectural invariants;
|
||||
- explicit non-goals, if useful.
|
||||
|
||||
For small projects, this file may be brief. It may simply state that the project is intentionally narrow, monolithic, and dependency-light.
|
||||
|
||||
### docs/policy/development.md
|
||||
|
||||
**Audience:** developers, LLM coding agents
|
||||
|
||||
Required for projects maintained by humans and LLM coding agents.
|
||||
|
||||
It should include:
|
||||
|
||||
- repository layout;
|
||||
- build/test commands;
|
||||
- coding conventions;
|
||||
- dependency policy;
|
||||
- how to add config fields;
|
||||
- how to add CLI flags;
|
||||
- how to add stages/modules/adapters, if applicable;
|
||||
- how to update examples;
|
||||
- documentation update expectations.
|
||||
|
||||
### docs/config.md
|
||||
|
||||
**Audience:** administrators, operators, advanced users
|
||||
|
||||
Required for applications with configuration files.
|
||||
|
||||
It should include, in order:
|
||||
|
||||
1. config file locations and discovery precedence;
|
||||
2. minimal working config;
|
||||
3. production-oriented config;
|
||||
4. full configuration reference;
|
||||
5. secrets handling, if applicable;
|
||||
6. links to maintained examples.
|
||||
|
||||
The full configuration reference should be canonical.
|
||||
|
||||
### docs/cli.md
|
||||
|
||||
**Audience:** users, administrators, operators
|
||||
|
||||
Required for CLI applications.
|
||||
|
||||
It should include, in order:
|
||||
|
||||
1. shortest useful command;
|
||||
2. command overview;
|
||||
3. complete flag reference;
|
||||
4. common workflows;
|
||||
5. diagnostic or recovery commands, if applicable.
|
||||
|
||||
Explain when commands are useful, not just their syntax.
|
||||
|
||||
### docs/operations.md
|
||||
|
||||
**Audience:** administrators, operators
|
||||
|
||||
Required for applications that maintain state, support resume behavior, run multiple stages, write durable artifacts, use remote storage, or require recovery procedures.
|
||||
|
||||
It should cover:
|
||||
|
||||
- normal workflow;
|
||||
- filesystem layout;
|
||||
- remote storage layout, if applicable;
|
||||
- logs and manifests;
|
||||
- resume/retry behavior;
|
||||
- cleanup behavior;
|
||||
- archive/backup behavior;
|
||||
- safe recovery procedures;
|
||||
- operational caveats.
|
||||
|
||||
### docs/troubleshooting.md
|
||||
|
||||
**Audience:** administrators, operators
|
||||
|
||||
Recommended once recurring failure modes exist.
|
||||
|
||||
Each entry should include:
|
||||
|
||||
- symptom;
|
||||
- likely cause;
|
||||
- diagnostic command or inspection step;
|
||||
- safe fix;
|
||||
- relevant links.
|
||||
|
||||
### docs/internal/
|
||||
|
||||
**Audience:** developers, LLM coding agents
|
||||
|
||||
Required for modular, staged, service-oriented, or orchestration projects.
|
||||
|
||||
This directory describes implemented internal components. It is not the roadmap.
|
||||
|
||||
Use one file per major component where useful.
|
||||
|
||||
Each component doc should include:
|
||||
|
||||
1. purpose;
|
||||
2. inputs and outputs;
|
||||
3. boundaries;
|
||||
4. config fields used;
|
||||
5. external adapters used;
|
||||
6. state or manifest behavior, if applicable;
|
||||
7. skip/resume behavior, if applicable;
|
||||
8. failure behavior;
|
||||
9. tests to inspect before changing;
|
||||
10. architectural invariants.
|
||||
|
||||
### docs/roadmap/
|
||||
|
||||
**Audience:** maintainers, developers, LLM coding agents
|
||||
|
||||
This is the only place for planned, future, aspirational, experimental, or unimplemented work.
|
||||
|
||||
Roadmap docs should clearly distinguish:
|
||||
|
||||
- proposed work;
|
||||
- accepted plans;
|
||||
- deferred ideas;
|
||||
- rejected ideas;
|
||||
- implementation prompts or task breakdowns, if useful.
|
||||
|
||||
Roadmap docs should not be confused with current behavior.
|
||||
|
||||
### docs/integrations/
|
||||
|
||||
**Audience:** developers, LLM coding agents
|
||||
|
||||
Required for projects that depend on external CLIs, APIs, services, protocols, or file formats where the integration contract is important to maintain.
|
||||
|
||||
This directory contains concise, versioned reference notes for external integration contracts. It should document only the parts of the external system that this project actually uses.
|
||||
|
||||
Use one file per integration where useful.
|
||||
|
||||
## Examples Directory
|
||||
|
||||
Projects with non-trivial configuration or workflows should include `examples/`.
|
||||
|
||||
Useful examples include:
|
||||
|
||||
- minimal working config;
|
||||
- production-oriented config;
|
||||
- full annotated config;
|
||||
- local development config;
|
||||
- remote/object-storage config;
|
||||
- minimal session/input file.
|
||||
|
||||
Examples should be valid, maintained, tested when practical, and linked from relevant docs.
|
||||
|
||||
## Security and Privacy
|
||||
|
||||
Docs and examples must not include:
|
||||
|
||||
- real API keys;
|
||||
- tokens;
|
||||
- passwords;
|
||||
- private keys;
|
||||
- private environment dumps;
|
||||
- sensitive user data;
|
||||
- raw private transcripts;
|
||||
- private infrastructure details unless intentionally public.
|
||||
|
||||
Document secret-handling mechanisms, not actual secret values.
|
||||
|
||||
## Maintenance Rules
|
||||
|
||||
When docs change, verify the affected behavior.
|
||||
|
||||
Where practical:
|
||||
|
||||
- load example config files in tests;
|
||||
- test CLI examples or command parser behavior;
|
||||
- validate documented flags against real flags;
|
||||
- remove stale references;
|
||||
- update links after renames;
|
||||
- keep roadmap content out of non-roadmap docs.
|
||||
|
||||
If documentation and code disagree, fix the documentation and/or open a roadmap item; do not leave aspirational behavior in current-behavior docs.
|
||||
|
||||
Documentation is complete only when it matches the current code.
|
||||
|
||||
## Documentation Change Checklist
|
||||
|
||||
Before merging documentation changes, verify:
|
||||
|
||||
- README is concise and orientation-focused.
|
||||
- `docs/policy/architecture.md` describes development principles.
|
||||
- Future work appears only under `docs/roadmap/`.
|
||||
- User-facing docs avoid unnecessary internals.
|
||||
- Developer-facing docs preserve boundaries and invariants.
|
||||
- Config examples match the schema.
|
||||
- CLI examples match real commands and flags.
|
||||
- Defaults appear in the canonical config reference.
|
||||
- No secrets or private data are included.
|
||||
- Links are accurate.
|
||||
586
docs/roadmap/documentation.md
Normal file
586
docs/roadmap/documentation.md
Normal file
@@ -0,0 +1,586 @@
|
||||
# Documentation Roadmap
|
||||
|
||||
## Purpose
|
||||
|
||||
This roadmap defines the work required to bring seriatim's documentation into
|
||||
compliance with `docs/policy/documentation.md` and the current implementation.
|
||||
It is grounded in the repository as it exists now: the Go CLI, config loading,
|
||||
pipeline modules, artifact commands, schemas, reports, samples, and tests.
|
||||
|
||||
Outside `docs/roadmap/`, documentation must describe only implemented
|
||||
behavior. Planned, future, deprecated, experimental, or unimplemented work must
|
||||
remain in roadmap documents until the code exists.
|
||||
|
||||
## Repository Documentation Inventory
|
||||
|
||||
- `README.md` - keep and rewrite. It currently mixes project orientation,
|
||||
quickstart, full CLI reference, config/env reference, file formats, module
|
||||
internals, limitations, and release build notes. Policy says README should be
|
||||
concise and link to canonical docs.
|
||||
- `docs/policy/documentation.md` - keep and lightly update only if the policy
|
||||
itself changes. It is the controlling documentation layout and maintenance
|
||||
policy.
|
||||
- `docs/policy/architecture.md` - keep and lightly update as implementation
|
||||
changes. It is the canonical development architecture policy.
|
||||
- Root `architecture.md` - delete after salvage, or move only truly roadmap
|
||||
material into `docs/roadmap/`. It is in the wrong canonical home and contains
|
||||
future-oriented and aspirational claims.
|
||||
- `docs/roadmap/documentation.md` - create new. This file is the planning
|
||||
artifact for the documentation migration.
|
||||
- `samples/` - split or move after audit. It contains sample raw transcripts,
|
||||
merged artifacts, reports, `speakers.yml`, and `autocorrect.yml`, but
|
||||
copyable examples belong under `examples/`. The raw sample data is large and
|
||||
should be reviewed for privacy and maintainability before linking from docs.
|
||||
- `schema/*.schema.json` - keep. These are public output contracts and should
|
||||
be linked from documentation instead of duplicated in full.
|
||||
- Missing canonical docs - create `docs/cli.md`, `docs/config.md`,
|
||||
`docs/operations.md`, `docs/policy/development.md`, `docs/internal/`, and
|
||||
likely `docs/troubleshooting.md`, `docs/integrations/`, and `examples/`.
|
||||
|
||||
## Policy Compliance Assessment
|
||||
|
||||
Required documents missing for seriatim's current shape as a modular, staged,
|
||||
CLI/config-driven project:
|
||||
|
||||
- `docs/cli.md`
|
||||
- `docs/config.md`
|
||||
- `docs/operations.md`
|
||||
- `docs/internal/`
|
||||
- `docs/policy/development.md`
|
||||
|
||||
Recommended documents and directories missing:
|
||||
|
||||
- `docs/troubleshooting.md`
|
||||
- maintained copyable examples under `examples/`
|
||||
- concise integration notes under `docs/integrations/`
|
||||
|
||||
Existing compliance issues:
|
||||
|
||||
- `README.md` is too broad for its canonical scope. It should keep project
|
||||
purpose, quickstart, and links, then delegate CLI, config, operations,
|
||||
internals, and schema details.
|
||||
- Root `architecture.md` is stale and in the wrong home. It includes future
|
||||
input methods and formats, future output formats, dynamic plugin speculation,
|
||||
an LLM non-goal, interface sketches that diverge from code, and other
|
||||
development-policy content now covered by `docs/policy/architecture.md`.
|
||||
- Non-roadmap docs should not carry forward claims about future defaults,
|
||||
future formats, unimplemented plugin systems, or unimplemented alternate
|
||||
input/output methods.
|
||||
- Historical or deprecated wording, such as the old speaker map format, should
|
||||
move out of the README unless it is still needed in troubleshooting or a
|
||||
narrow migration note.
|
||||
- There is no `examples/` directory. `samples/` exists but is not the canonical
|
||||
examples home and should not be treated as copyable public examples without a
|
||||
privacy and size audit.
|
||||
- Links need verification after migration: README should link to all new
|
||||
canonical docs, docs should link to schema files and maintained examples, and
|
||||
no doc should link to the deleted root `architecture.md`.
|
||||
|
||||
## Target Documentation Set
|
||||
|
||||
### `README.md`
|
||||
|
||||
- Audience: users, administrators, and operators.
|
||||
- Purpose: project orientation and shortest useful quickstart.
|
||||
- Canonical scope: concise project purpose, elevator pitch, one minimal command,
|
||||
and links to targeted docs.
|
||||
- Recommended outline: project description; shortest merge command; command
|
||||
summary; links to CLI, config, operations, architecture, development, schemas,
|
||||
examples, and troubleshooting.
|
||||
- Source of truth: current `README.md`, `internal/cli`, `internal/config`,
|
||||
`cmd/seriatim/main.go`, and CLI tests.
|
||||
- Acceptance criteria: no full flag tables, no full config reference, no module
|
||||
manual, no future-feature claims, and all links resolve.
|
||||
|
||||
### `docs/cli.md`
|
||||
|
||||
- Audience: users, administrators, and operators.
|
||||
- Purpose: canonical CLI reference and workflows.
|
||||
- Canonical scope: shortest useful command, command overview, complete flag
|
||||
reference, common workflows, diagnostics and report flags.
|
||||
- Recommended outline: shortest useful command; global flags; `merge`; `trim`;
|
||||
`normalize`; common workflows; exit/error behavior; links to config,
|
||||
operations, examples, and schemas.
|
||||
- Source of truth: `internal/cli/root.go`, `internal/cli/merge.go`,
|
||||
`internal/cli/trim.go`, `internal/cli/normalize.go`, `internal/config`, and
|
||||
`internal/cli/*_test.go`.
|
||||
- Acceptance criteria: every documented flag, default, and required/mutually
|
||||
exclusive rule matches code; package internals are linked rather than
|
||||
explained in depth.
|
||||
|
||||
### `docs/config.md`
|
||||
|
||||
- Audience: administrators, operators, and advanced users.
|
||||
- Purpose: canonical runtime configuration reference.
|
||||
- Canonical scope: environment variables, default module lists, output schema
|
||||
selection, `speakers.yml`, `autocorrect.yml`, path validation, and precedence.
|
||||
- Recommended outline: config surfaces; output schema precedence; merge module
|
||||
defaults; environment variables; speaker map YAML; autocorrect YAML; path and
|
||||
validation rules; links to examples.
|
||||
- Source of truth: `internal/config/config.go`, `internal/speaker/map.go`,
|
||||
`internal/autocorrect/autocorrect.go`, `internal/config/config_test.go`,
|
||||
`internal/speaker/map_test.go`, and `internal/autocorrect/autocorrect_test.go`.
|
||||
- Acceptance criteria: all config fields and `SERIATIM_*` env vars match code;
|
||||
unsupported config files or unimplemented formats are not described.
|
||||
|
||||
### `docs/operations.md`
|
||||
|
||||
- Audience: administrators and operators.
|
||||
- Purpose: operational behavior for running commands safely.
|
||||
- Canonical scope: file workflow, filesystem layout expectations, output and
|
||||
report files, retry behavior, cleanup, validation failures, and operational
|
||||
caveats.
|
||||
- Recommended outline: normal workflow; input/output/report files; no durable
|
||||
state; failure and retry behavior; reports and diagnostics; cleanup; privacy
|
||||
considerations for transcript artifacts.
|
||||
- Source of truth: `cmd/seriatim/main.go`, `internal/cli`, `internal/config`,
|
||||
`internal/report`, `internal/builtin/output.go`, `internal/normalize`, and
|
||||
trim/merge/normalize CLI tests.
|
||||
- Acceptance criteria: clearly states there is no daemon, database, resume
|
||||
state, remote storage, or background job state; does not invent recovery
|
||||
workflows.
|
||||
|
||||
### `docs/policy/development.md`
|
||||
|
||||
- Audience: developers and coding agents.
|
||||
- Purpose: contributor workflow and change guidance.
|
||||
- Canonical scope: repository layout, build/test commands, coding conventions,
|
||||
dependency policy, adding flags/config fields/modules/docs/examples.
|
||||
- Recommended outline: repo layout; local checks; coding conventions; adding
|
||||
CLI flags; adding config/env vars; adding modules/stages; schema changes;
|
||||
examples and documentation updates.
|
||||
- Source of truth: `docs/policy/documentation.md`,
|
||||
`docs/policy/architecture.md`, `go.mod`, package layout, and test layout.
|
||||
- Acceptance criteria: includes `go test ./...`; states there is no current
|
||||
Makefile, taskfile, linter config, or automated doc checker; aligns with the
|
||||
architecture policy.
|
||||
|
||||
### `docs/internal/pipeline.md`
|
||||
|
||||
- Audience: developers and coding agents.
|
||||
- Purpose: implemented merge pipeline internals.
|
||||
- Canonical scope: registry, stage interfaces, preprocessing state transitions,
|
||||
module order, report event accumulation, final output/report writing.
|
||||
- Recommended outline: purpose; inputs and outputs; stage contracts; registry
|
||||
resolution; execution order; config fields used; adapters; failure behavior;
|
||||
tests; invariants.
|
||||
- Source of truth: `internal/pipeline`, `internal/builtin`, `internal/model`,
|
||||
`internal/report`, `internal/pipeline/runner_test.go`,
|
||||
`internal/builtin/*_test.go`, and `internal/cli/merge_test.go`.
|
||||
- Acceptance criteria: describes only implemented sequential execution; does
|
||||
not document concurrency, plugins, or future formats.
|
||||
|
||||
### `docs/internal/artifacts.md`
|
||||
|
||||
- Audience: developers and coding agents.
|
||||
- Purpose: public artifact conversion and validation internals.
|
||||
- Canonical scope: schema structs, embedded JSON Schemas, conversion from merged
|
||||
model, trim/normalize artifact handling, and output validation.
|
||||
- Recommended outline: artifact contracts; schema selection; conversion;
|
||||
validation; trim projection; normalize canonicalization; tests; invariants.
|
||||
- Source of truth: `schema`, `internal/artifact`, `internal/trim`,
|
||||
`internal/normalize`, and related tests.
|
||||
- Acceptance criteria: links to `schema/*.schema.json`; does not duplicate full
|
||||
schemas or describe unavailable output formats.
|
||||
|
||||
### `docs/internal/modules.md`
|
||||
|
||||
- Audience: developers and coding agents.
|
||||
- Purpose: implemented built-in module behavior and boundaries.
|
||||
- Canonical scope: `json-files`, preprocessing modules, chronological merge,
|
||||
postprocessing modules, and JSON output writer.
|
||||
- Recommended outline: module list; inputs/outputs; config fields used; allowed
|
||||
side effects; ordering constraints; failure behavior; tests; invariants.
|
||||
- Source of truth: `internal/builtin`, `internal/overlap`, `internal/coalesce`,
|
||||
`internal/danglers`, `internal/backchannel`, `internal/filler`,
|
||||
`internal/autocorrect`, and package tests.
|
||||
- Acceptance criteria: avoids full CLI/config duplication; identifies
|
||||
order-sensitive transforms that must run before `assign-ids`.
|
||||
|
||||
### `docs/troubleshooting.md`
|
||||
|
||||
- Audience: users, administrators, and operators.
|
||||
- Purpose: common failure symptoms and safe fixes.
|
||||
- Canonical scope: implemented validation and runtime failures observed in
|
||||
error paths and tests.
|
||||
- Recommended outline: invalid JSON/input shape; missing required flags; invalid
|
||||
output parent directory; invalid speaker/autocorrect YAML; unknown module;
|
||||
invalid output schema; invalid trim selector; schema validation failure;
|
||||
report write failure.
|
||||
- Source of truth: `internal/config`, `internal/cli/*_test.go`,
|
||||
`internal/trim/*_test.go`, `internal/normalize/*_test.go`,
|
||||
`internal/speaker/*_test.go`, and `internal/autocorrect/*_test.go`.
|
||||
- Acceptance criteria: each entry has symptom, likely cause, inspection step,
|
||||
safe fix, and link; no speculative failure modes.
|
||||
|
||||
### `docs/integrations/whisperx-json.md`
|
||||
|
||||
- Audience: developers and coding agents.
|
||||
- Purpose: external input JSON contract used by `merge`.
|
||||
- Canonical scope: the supported WhisperX-like subset only.
|
||||
- Recommended outline: top-level shape; required segment fields; optional word
|
||||
timing fields; validation/failure behavior; how word timing affects overlap
|
||||
resolution; links to CLI and examples.
|
||||
- Source of truth: `internal/builtin/input.go`, merge CLI tests, and README
|
||||
input-format material.
|
||||
- Acceptance criteria: does not attempt to document full WhisperX behavior or
|
||||
unsupported input formats.
|
||||
|
||||
### `docs/integrations/output-schemas.md`
|
||||
|
||||
- Audience: developers, coding agents, and artifact consumers.
|
||||
- Purpose: orientation to public JSON output contracts.
|
||||
- Canonical scope: minimal/intermediate/full schema roles and links to schema
|
||||
files.
|
||||
- Recommended outline: schema selection; minimal; intermediate; full; semantic
|
||||
invariants; validation APIs; links to `schema/*.schema.json`.
|
||||
- Source of truth: `schema/output.go`, `schema/*.schema.json`,
|
||||
`schema/output_test.go`, and `internal/artifact`.
|
||||
- Acceptance criteria: links to machine-readable schemas instead of copying
|
||||
them in full.
|
||||
|
||||
### `examples/`
|
||||
|
||||
- Audience: users, administrators, operators, developers, and coding agents.
|
||||
- Purpose: maintained copyable examples.
|
||||
- Canonical scope: small synthetic inputs and config files for implemented
|
||||
commands only.
|
||||
- Source of truth: examples created during the documentation migration and
|
||||
validated through actual command invocations.
|
||||
- Acceptance criteria: examples are valid, free of secrets/private transcript
|
||||
data, and linked from README, CLI, config, and operations docs.
|
||||
|
||||
## File-by-File Rewrite Guidance
|
||||
|
||||
### README
|
||||
|
||||
Cover what seriatim is, the shortest useful `merge` command, a brief command
|
||||
summary, and links to canonical docs. Avoid full flag tables, config/env
|
||||
reference, module internals, schema examples, troubleshooting details, future
|
||||
formats, or release-history narrative. Inspect `internal/cli`, `internal/config`,
|
||||
and CLI tests before updating commands.
|
||||
|
||||
### CLI Reference
|
||||
|
||||
Document actual `merge`, `trim`, and `normalize` flags from `internal/cli`.
|
||||
Include required flags, defaults, mutually exclusive selector rules, schema
|
||||
selection, report flags, and common workflows. Link to `docs/config.md` for
|
||||
environment variables and YAML formats. Avoid internal package explanations.
|
||||
Inspect `internal/cli/*_test.go` for edge cases and examples.
|
||||
|
||||
### Config Reference
|
||||
|
||||
Document all implemented config surfaces: flags that become config values,
|
||||
`SERIATIM_OUTPUT_SCHEMA`, `SERIATIM_OVERLAP_WORD_RUN_GAP`,
|
||||
`SERIATIM_OVERLAP_WORD_RUN_REORDER_WINDOW`,
|
||||
`SERIATIM_BACKCHANNEL_MAX_DURATION`, `SERIATIM_FILLER_MAX_DURATION`, module
|
||||
lists, output schemas, `speakers.yml`, and `autocorrect.yml`. Avoid command
|
||||
tutorials and unimplemented config files. Inspect `internal/config`,
|
||||
`internal/speaker`, `internal/autocorrect`, and tests.
|
||||
|
||||
### Operations
|
||||
|
||||
Document filesystem-only command execution, output/report artifacts, validation
|
||||
failures, retry behavior, and cleanup. Explicitly say there is no daemon,
|
||||
database, remote storage, resume state, or background job state. Avoid
|
||||
unimplemented recovery procedures.
|
||||
|
||||
### Development Policy
|
||||
|
||||
Document repository layout, `go test ./...`, package conventions,
|
||||
standard-library-first dependency guidance, how to add flags/config/modules,
|
||||
and documentation update expectations. State that no Makefile, taskfile,
|
||||
linter config, or automated documentation checker currently exists.
|
||||
|
||||
### Internal Docs
|
||||
|
||||
Keep internal docs behavior-level and concise. Describe implemented inputs,
|
||||
outputs, boundaries, config fields used, adapters, failure behavior, tests, and
|
||||
invariants. Avoid future plugins, future input/output formats, concurrency, or
|
||||
duplicating CLI/config reference material.
|
||||
|
||||
### Root `architecture.md`
|
||||
|
||||
Do not carry forward future input methods, future formats, future output
|
||||
formats, LLM text, dynamic plugin speculation, or interface sketches that
|
||||
diverge from code. Salvage only current-behavior details that are not already
|
||||
covered in `docs/policy/architecture.md` and move any legitimate future ideas
|
||||
under `docs/roadmap/`.
|
||||
|
||||
## Examples Plan
|
||||
|
||||
Create small synthetic examples under `examples/` rather than relying on the
|
||||
current large `samples/raw` data.
|
||||
|
||||
- `examples/minimal-merge/`
|
||||
- Purpose: shortest complete merge workflow with two small raw JSON files and
|
||||
optional `speakers.yml`.
|
||||
- Expected validity check: run `go run ./cmd/seriatim merge` with the example
|
||||
files and validate JSON output is produced.
|
||||
- Docs to link: README, `docs/cli.md`, `docs/config.md`,
|
||||
`docs/operations.md`.
|
||||
- `examples/normalize/`
|
||||
- Purpose: normalize object-with-`segments` and bare segment array inputs.
|
||||
- Expected validity check: run `go run ./cmd/seriatim normalize` for both
|
||||
shapes.
|
||||
- Docs to link: `docs/cli.md`, `docs/operations.md`, and any Audita/bare
|
||||
array integration note if created.
|
||||
- `examples/trim/`
|
||||
- Purpose: trim a small existing seriatim artifact by `--keep` and/or
|
||||
`--remove`.
|
||||
- Expected validity check: run `go run ./cmd/seriatim trim` and validate
|
||||
sequential retained IDs.
|
||||
- Docs to link: `docs/cli.md`, `docs/operations.md`.
|
||||
- `examples/speakers.yml` and `examples/autocorrect.yml`
|
||||
- Purpose: copyable YAML rule examples if linked from `docs/config.md`.
|
||||
- Expected validity check: load through merge command or package tests.
|
||||
- Docs to link: `docs/config.md`, `docs/cli.md`.
|
||||
|
||||
Do not invent examples for unimplemented input methods, output formats,
|
||||
services, or plugin systems. Do not reuse `samples/raw` as public examples
|
||||
without privacy and size review.
|
||||
|
||||
## Internal Documentation Plan
|
||||
|
||||
### Pipeline
|
||||
|
||||
- Path: `docs/internal/pipeline.md`
|
||||
- Purpose: document implemented merge pipeline orchestration.
|
||||
- Inputs and outputs: `config.Config`, raw transcripts, canonical transcripts,
|
||||
merged transcript, selected public artifact, optional report.
|
||||
- Boundaries: registry and runner orchestration; no CLI flag parsing; no schema
|
||||
details beyond output selection.
|
||||
- Config fields used: input reader, module lists, output modules, output schema,
|
||||
input/output/report files, timing thresholds passed through modules.
|
||||
- Adapters used: input reader, output writer, report writer.
|
||||
- Failure behavior: unknown modules, invalid preprocessing state, stage errors,
|
||||
output/report write failures.
|
||||
- Tests to inspect: `internal/pipeline/runner_test.go`,
|
||||
`internal/builtin/*_test.go`, `internal/cli/merge_test.go`.
|
||||
- Architectural invariants: deterministic sequential stage order, explicit
|
||||
raw-to-canonical preprocessing state, output validation before acceptance.
|
||||
|
||||
### Artifacts and Schemas
|
||||
|
||||
- Path: `docs/internal/artifacts.md`
|
||||
- Purpose: document public artifact conversion and validation internals.
|
||||
- Inputs and outputs: merged model, schema structs, serialized JSON artifacts,
|
||||
parsed trim/normalize artifacts.
|
||||
- Boundaries: conversion and validation only; CLI docs own user-facing flags.
|
||||
- Config fields used: output schema, output modules, input files for metadata.
|
||||
- Adapters used: embedded JSON Schema files and JSON encoders/decoders.
|
||||
- Failure behavior: schema validation errors, unsupported artifact/schema
|
||||
conversion, invalid IDs/timing.
|
||||
- Tests to inspect: `schema/output_test.go`,
|
||||
`internal/artifact/transcript_test.go`, `internal/trim/*_test.go`,
|
||||
`internal/normalize/*_test.go`.
|
||||
- Architectural invariants: sequential IDs, selected schema validation, no
|
||||
internal-only fields in public schemas.
|
||||
|
||||
### Built-In Modules
|
||||
|
||||
- Path: `docs/internal/modules.md`
|
||||
- Purpose: document implemented module responsibilities and ordering
|
||||
constraints.
|
||||
- Inputs and outputs: raw transcripts, preprocess state, merged transcript,
|
||||
report events, selected JSON output.
|
||||
- Boundaries: module behavior only; no full CLI/config reference.
|
||||
- Config fields used: speaker file, autocorrect file, coalesce gap, overlap word
|
||||
gap, word run reorder window, backchannel/filler max durations.
|
||||
- Adapters used: JSON input/output, speaker YAML, autocorrect YAML, report
|
||||
events.
|
||||
- Failure behavior: input validation errors, invalid YAML, unknown module names,
|
||||
invalid output schema before write.
|
||||
- Tests to inspect: `internal/builtin`, `internal/overlap`,
|
||||
`internal/coalesce`, `internal/danglers`, `internal/backchannel`,
|
||||
`internal/filler`, `internal/autocorrect`, and CLI merge tests.
|
||||
- Architectural invariants: order-sensitive transforms run before `assign-ids`;
|
||||
modules stay narrow and explicitly configured.
|
||||
|
||||
### Trim
|
||||
|
||||
- Path: include in `docs/internal/artifacts.md` or create
|
||||
`docs/internal/trim.md` if artifacts doc grows too large.
|
||||
- Purpose: document artifact-level segment projection.
|
||||
- Inputs and outputs: existing seriatim artifact, selector, selected output
|
||||
schema, optional report.
|
||||
- Boundaries: no merge postprocessors; no raw WhisperX input.
|
||||
- Config fields used: input/output/report files, keep/remove selector,
|
||||
optional output schema, allow-empty.
|
||||
- Adapters used: file I/O in CLI, artifact parsing/validation, report writer.
|
||||
- Failure behavior: malformed selector, invalid artifact, missing selected IDs,
|
||||
non-sequential input IDs, empty output unless allowed, unsupported schema
|
||||
up-conversion.
|
||||
- Tests to inspect: `internal/trim/*_test.go`, `internal/cli/trim_test.go`.
|
||||
- Architectural invariants: preserve transcript order, renumber retained IDs,
|
||||
recompute full-schema overlap groups, never run merge modules.
|
||||
|
||||
### Normalize
|
||||
|
||||
- Path: include in `docs/internal/artifacts.md` or create
|
||||
`docs/internal/normalize.md` if artifacts doc grows too large.
|
||||
- Purpose: document artifact-level transcript canonicalization.
|
||||
- Inputs and outputs: transcript-like JSON object or bare array, selected
|
||||
seriatim output schema, optional report.
|
||||
- Boundaries: no merge preprocessing or postprocessing modules.
|
||||
- Config fields used: input/output/report files, output schema, output modules.
|
||||
- Adapters used: file I/O, JSON parsing, schema validation, report writer.
|
||||
- Failure behavior: invalid JSON, unsupported top-level shape, invalid timing
|
||||
after repair, unsupported output module/schema, report write failure.
|
||||
- Tests to inspect: `internal/normalize/*_test.go`,
|
||||
`internal/cli/normalize_test.go`.
|
||||
- Architectural invariants: deterministic repair/sort/ID assignment, no
|
||||
transcript text in normalize report events, no merge modules.
|
||||
|
||||
## Integration Documentation Plan
|
||||
|
||||
- `docs/integrations/whisperx-json.md`
|
||||
- External system or contract: WhisperX-like JSON transcript subset.
|
||||
- Current usage: `merge` reads a top-level `segments` array with required
|
||||
segment timing/text and optional word timing.
|
||||
- Version or compatibility notes: no explicit WhisperX version is encoded in
|
||||
the repository; document only the accepted subset.
|
||||
- Document: supported fields, validation, word timing behavior, errors.
|
||||
- Do not document: full WhisperX schema, audio diarization, non-JSON formats.
|
||||
- `docs/integrations/output-schemas.md`
|
||||
- External system or contract: seriatim public JSON output contracts.
|
||||
- Current usage: `merge`, `trim`, and `normalize` emit
|
||||
`seriatim-minimal`, `seriatim-intermediate`, or `seriatim-full`.
|
||||
- Version or compatibility notes: schemas are embedded from `schema/`; release
|
||||
version metadata is injected through build info.
|
||||
- Document: schema roles, semantic invariants, validation APIs, links to
|
||||
schema files.
|
||||
- Do not document: unimplemented output formats or full schema copies.
|
||||
- YAML rule files
|
||||
- Prefer documenting speaker and autocorrect YAML contracts in
|
||||
`docs/config.md`. Create `docs/integrations/yaml-rule-files.md` only if the
|
||||
config reference becomes too large.
|
||||
- Audita-style bare arrays
|
||||
- Cover under `docs/cli.md` normalize behavior unless maintainers need a
|
||||
separate integration note. Do not generalize beyond implemented bare segment
|
||||
arrays.
|
||||
- No external CLI/API/service docs are needed now. The repository implements no
|
||||
external CLI, network API, daemon, remote storage, or service integration.
|
||||
|
||||
## Recommended Implementation Sequence
|
||||
|
||||
### Stage 1: Write Documentation Roadmap
|
||||
|
||||
- Goal: review and finalize this roadmap as the implementation plan for the
|
||||
documentation migration.
|
||||
- Files: `docs/roadmap/documentation.md` only.
|
||||
- Repository areas inspected: documentation policy, architecture policy,
|
||||
`README.md`, root `architecture.md`, and CLI/config/pipeline/schema/report
|
||||
code and tests.
|
||||
- Completion status: complete (2026-05-24).
|
||||
- Completion evidence:
|
||||
- `go test ./...` passed.
|
||||
- `git status --short` confirmed no unrelated working-tree changes before
|
||||
roadmap-only edits.
|
||||
- Acceptance criteria: roadmap is present, action-oriented, and constrained to
|
||||
implemented behavior outside `docs/roadmap/`.
|
||||
- Suggested validation commands: `go test ./...`; `git status --short`.
|
||||
- Prompt size: one implementation prompt.
|
||||
|
||||
### Stage 2: User-Facing Canonical Docs and Slim README
|
||||
|
||||
- Goal: move user reference material out of README into canonical docs.
|
||||
- Files: update `README.md`; create `docs/cli.md` and `docs/config.md`.
|
||||
- Repository areas to inspect: `internal/cli`, `internal/config`,
|
||||
`internal/speaker`, `internal/autocorrect`, CLI/config tests.
|
||||
- Acceptance criteria: README is concise; CLI/config docs match flags, defaults,
|
||||
env vars, YAML formats, and validation; no roadmap-only content appears.
|
||||
- Suggested validation commands: `go test ./...`;
|
||||
`go run ./cmd/seriatim --help`;
|
||||
`go run ./cmd/seriatim merge --help`;
|
||||
`go run ./cmd/seriatim trim --help`;
|
||||
`go run ./cmd/seriatim normalize --help`;
|
||||
stale-term grep from the validation plan.
|
||||
- Prompt size: one prompt if concise; split if README rewrite or config
|
||||
reference grows too large.
|
||||
|
||||
### Stage 3: Operations and Troubleshooting
|
||||
|
||||
- Goal: document runtime operation, reports, failure behavior, and common fixes.
|
||||
- Files: create `docs/operations.md` and `docs/troubleshooting.md`.
|
||||
- Repository areas to inspect: `cmd/seriatim/main.go`, `internal/cli`,
|
||||
`internal/config`, `internal/report`, output writer, normalize/trim/merge
|
||||
tests.
|
||||
- Acceptance criteria: docs describe filesystem-only operation and current
|
||||
failure modes; no daemon, resume, remote storage, or recovery behavior is
|
||||
invented.
|
||||
- Suggested validation commands: `go test ./...`; manual link review.
|
||||
- Prompt size: one prompt.
|
||||
|
||||
### Stage 4: Developer and Internal Docs
|
||||
|
||||
- Goal: create developer workflow and implemented internal component docs.
|
||||
- Files: create `docs/policy/development.md`,
|
||||
`docs/internal/pipeline.md`, `docs/internal/artifacts.md`, and
|
||||
`docs/internal/modules.md`.
|
||||
- Repository areas to inspect: architecture policy, pipeline, modules, schema,
|
||||
artifact conversion, trim/normalize packages, tests.
|
||||
- Acceptance criteria: docs preserve boundaries, avoid CLI/config duplication,
|
||||
and identify tests/invariants for future changes.
|
||||
- Suggested validation commands: `go test ./...`; grep for unimplemented
|
||||
future-format/plugin/concurrency claims outside roadmap.
|
||||
- Prompt size: split into development policy and internal docs if needed.
|
||||
|
||||
### Stage 5: Integrations and Examples
|
||||
|
||||
- Goal: add concise integration notes and maintained synthetic examples.
|
||||
- Files: create `docs/integrations/whisperx-json.md`,
|
||||
`docs/integrations/output-schemas.md`, and `examples/*`; decide whether
|
||||
`samples/` should remain separate.
|
||||
- Repository areas to inspect: `internal/builtin/input.go`, `schema`,
|
||||
`internal/artifact`, CLI tests, existing `samples/`.
|
||||
- Acceptance criteria: examples are small, synthetic, valid, and linked from
|
||||
relevant docs; integration docs document only implemented contracts.
|
||||
- Suggested validation commands: `go test ./...`; run documented example
|
||||
`go run` commands; validate example YAML through command paths.
|
||||
- Prompt size: split if examples need tests or sample cleanup decisions.
|
||||
|
||||
### Stage 6: Stale Documentation Cleanup
|
||||
|
||||
- Goal: remove wrong-home and stale documentation after canonical replacements
|
||||
exist.
|
||||
- Files: delete or relocate root `architecture.md`; remove stale material from
|
||||
README; update links across docs.
|
||||
- Repository areas to inspect: all docs, README, roadmap, root files.
|
||||
- Acceptance criteria: no links to deleted root `architecture.md`; no
|
||||
unimplemented behavior outside `docs/roadmap/`; canonical homes are respected.
|
||||
- Suggested validation commands: `go test ./...`; stale-term grep; manual link
|
||||
check; `git status --short`.
|
||||
- Prompt size: one prompt.
|
||||
|
||||
## Validation Plan
|
||||
|
||||
Use these checks during or after documentation migration:
|
||||
|
||||
- Run `go test ./...`.
|
||||
- Run `go run ./cmd/seriatim --help`.
|
||||
- Run `go run ./cmd/seriatim merge --help`.
|
||||
- Run `go run ./cmd/seriatim trim --help`.
|
||||
- Run `go run ./cmd/seriatim normalize --help`.
|
||||
- Once examples exist, run each documented example command and verify output is
|
||||
produced in a temporary path.
|
||||
- Load example YAML through the merge command or package tests.
|
||||
- Validate example JSON through existing CLI/schema paths where practical.
|
||||
- Grep outside `docs/roadmap/` for stale or roadmap-only terms:
|
||||
`Future input`, `Future output`, `LLM`, `plugin`, `SRT`, `VTT`, `.tar.gz`,
|
||||
`URI`, `old format`, `not implemented yet`, and
|
||||
`runtime default may change`.
|
||||
- Manually check links unless a link checker is added. No automated
|
||||
documentation checker currently exists.
|
||||
- Verify docs and examples contain no secrets, private transcript data, API
|
||||
keys, tokens, passwords, or private infrastructure details.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Should `samples/` be removed, kept as non-doc sample data, or replaced by
|
||||
small synthetic `examples/`? Recommendation: create small synthetic examples
|
||||
first, then audit `samples/` for privacy, size, and ongoing maintenance before
|
||||
deleting or linking it.
|
||||
- Should Audita-style bare-array normalization have a separate integration doc?
|
||||
Recommendation: cover it in `docs/cli.md` normalize behavior unless a
|
||||
stronger external-contract requirement emerges.
|
||||
102
docs/troubleshooting.md
Normal file
102
docs/troubleshooting.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# Troubleshooting
|
||||
|
||||
Each entry includes symptom, likely cause, inspection step, and safe fix.
|
||||
|
||||
## Missing required flags
|
||||
|
||||
- Symptom: command fails with messages like `--input-file is required`, `--output-file is required`, or `exactly one of --keep or --remove is required`.
|
||||
- Likely cause: required command flags were omitted.
|
||||
- Inspection: run command help for the failing command:
|
||||
- `go run ./cmd/seriatim merge --help`
|
||||
- `go run ./cmd/seriatim trim --help`
|
||||
- `go run ./cmd/seriatim normalize --help`
|
||||
- Safe fix: provide all required flags; for `trim`, provide exactly one selector mode (`--keep` or `--remove`).
|
||||
|
||||
## Invalid output or report path
|
||||
|
||||
- Symptom: errors like `--output-file parent directory ...` or `--report-file parent directory ...`.
|
||||
- Likely cause: parent directory does not exist, is not a directory, or path points to an unusable target.
|
||||
- Inspection: verify paths:
|
||||
- `dirname <path>`
|
||||
- `ls -ld <parent-dir>`
|
||||
- Safe fix: create/fix the parent directory and rerun; avoid using directory paths directly as output/report file targets.
|
||||
|
||||
## Invalid merge input JSON
|
||||
|
||||
- Symptom: merge fails with messages like `parse input file`, `must contain top-level segments array`, `segment 0 missing numeric start`, or `segment 0 words must be an array`.
|
||||
- Likely cause: malformed JSON or unsupported/missing fields in a merge input file.
|
||||
- Inspection: validate input JSON and required fields (`start`, `end`, `text`):
|
||||
- `jq . <input-file>`
|
||||
- Safe fix: correct the JSON structure and segment/word field types, then rerun `merge`.
|
||||
|
||||
## Invalid normalize input shape
|
||||
|
||||
- Symptom: normalize fails with messages like `must contain a "segments" field`, `"segments" must be an array`, or `top-level object with "segments" or a top-level segment array`.
|
||||
- Likely cause: normalize input is neither supported object-with-segments nor top-level segment array.
|
||||
- Inspection: inspect top-level JSON shape:
|
||||
- `jq 'type' <input-file>`
|
||||
- `jq 'keys' <input-file>` (for object input)
|
||||
- Safe fix: reshape input into one supported form and rerun `normalize`.
|
||||
|
||||
## Invalid speaker map or autocorrect YAML
|
||||
|
||||
- Symptom: merge fails with errors such as `must contain at least one match rule`, `must include speaker`, `must include target`, or duplicate match/speaker validation failures.
|
||||
- Likely cause: YAML rule file structure/content does not match expected schema.
|
||||
- Inspection: check YAML validity and required top-level keys:
|
||||
- `speakers.yml` requires top-level `match` rules.
|
||||
- `autocorrect.yml` requires top-level `autocorrect` rules.
|
||||
- Safe fix: correct YAML structure and rule content, then rerun `merge`.
|
||||
|
||||
## Unknown module names
|
||||
|
||||
- Symptom: errors like `unknown input reader`, `unknown preprocessing module`, `unknown postprocessing module`, or `unknown output module`.
|
||||
- Likely cause: module name typo or unsupported module in flag lists.
|
||||
- Inspection: compare provided module names against defaults in CLI help and config docs.
|
||||
- Safe fix: use implemented module names only or remove unsupported modules from comma-separated lists.
|
||||
|
||||
## Invalid output schema value
|
||||
|
||||
- Symptom: errors like `--output-schema must be one of ...`.
|
||||
- Likely cause: unsupported schema value from flag or `SERIATIM_OUTPUT_SCHEMA`.
|
||||
- Inspection: check effective value:
|
||||
- command flags
|
||||
- `echo "$SERIATIM_OUTPUT_SCHEMA"`
|
||||
- Safe fix: use one of `seriatim-minimal`, `seriatim-intermediate`, or `seriatim-full`.
|
||||
|
||||
## Invalid trim selector
|
||||
|
||||
- Symptom: trim fails with messages like `invalid selector ... malformed element`, `segment ID must be positive`, or descending-range errors.
|
||||
- Likely cause: selector syntax is invalid.
|
||||
- Inspection: verify selector format:
|
||||
- single ID: `7`
|
||||
- range: `1-10`
|
||||
- list: `1-10,15,20-25`
|
||||
- Safe fix: correct selector syntax and rerun `trim`.
|
||||
|
||||
## Schema validation failures
|
||||
|
||||
- Symptom: errors such as `validate-output: ...` in merge or `input JSON is not a valid seriatim output artifact` in trim.
|
||||
- Likely cause:
|
||||
- merge module order/config produced invalid final artifact (for example, validating before IDs are assigned), or
|
||||
- trim input is not a valid seriatim artifact.
|
||||
- Inspection:
|
||||
- for merge: inspect customized module ordering flags.
|
||||
- for trim: verify input artifact against known seriatim schema files in `schema/`.
|
||||
- Safe fix:
|
||||
- restore valid merge postprocessing order ending with assigned IDs before validation, or
|
||||
- provide a valid seriatim artifact as trim input.
|
||||
|
||||
## Report write failure
|
||||
|
||||
- Symptom: errors like `write --report-file ...` or file-create failures when report writing is requested.
|
||||
- Likely cause: report path is not writable or is an invalid target (for example a directory path).
|
||||
- Inspection:
|
||||
- `ls -ld <report-parent-dir>`
|
||||
- verify `--report-file` is a file path, not a directory
|
||||
- Safe fix: choose a writable file path under an existing directory and rerun.
|
||||
|
||||
## Related docs
|
||||
|
||||
- CLI reference: [cli.md](cli.md)
|
||||
- Configuration reference: [config.md](config.md)
|
||||
- Operations guide: [operations.md](operations.md)
|
||||
61
examples/README.md
Normal file
61
examples/README.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# Examples
|
||||
|
||||
These are small synthetic, copyable example assets for the implemented CLI
|
||||
commands.
|
||||
This directory is the canonical examples home for documentation.
|
||||
|
||||
## Merge example
|
||||
|
||||
Inputs:
|
||||
|
||||
- `minimal-merge/input-alice.json`
|
||||
- `minimal-merge/input-bob.json`
|
||||
- `minimal-merge/speakers.yml`
|
||||
|
||||
Run:
|
||||
|
||||
```sh
|
||||
go run ./cmd/seriatim merge \
|
||||
--input-file examples/minimal-merge/input-alice.json \
|
||||
--input-file examples/minimal-merge/input-bob.json \
|
||||
--speakers examples/minimal-merge/speakers.yml \
|
||||
--output-file /tmp/seriatim-example-merge.json
|
||||
```
|
||||
|
||||
## Normalize examples
|
||||
|
||||
Object-with-segments input:
|
||||
|
||||
```sh
|
||||
go run ./cmd/seriatim normalize \
|
||||
--input-file examples/normalize/object-with-segments.json \
|
||||
--output-file /tmp/seriatim-example-normalize-object.json
|
||||
```
|
||||
|
||||
Bare-array input:
|
||||
|
||||
```sh
|
||||
go run ./cmd/seriatim normalize \
|
||||
--input-file examples/normalize/bare-segments-array.json \
|
||||
--output-file /tmp/seriatim-example-normalize-array.json
|
||||
```
|
||||
|
||||
## Trim example
|
||||
|
||||
Input artifact:
|
||||
|
||||
- `trim/input-full.json`
|
||||
|
||||
Run:
|
||||
|
||||
```sh
|
||||
go run ./cmd/seriatim trim \
|
||||
--input-file examples/trim/input-full.json \
|
||||
--output-file /tmp/seriatim-example-trim.json \
|
||||
--keep "1-2"
|
||||
```
|
||||
|
||||
## YAML rule examples
|
||||
|
||||
- `speakers.yml`
|
||||
- `autocorrect.yml`
|
||||
8
examples/autocorrect.yml
Normal file
8
examples/autocorrect.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
autocorrect:
|
||||
- target: "General Kenobi"
|
||||
match:
|
||||
- "General Kenobi."
|
||||
|
||||
- target: "Okay"
|
||||
match:
|
||||
- "Okay."
|
||||
14
examples/minimal-merge/input-alice.json
Normal file
14
examples/minimal-merge/input-alice.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"segments": [
|
||||
{
|
||||
"start": 0.0,
|
||||
"end": 1.2,
|
||||
"text": " Hello there. "
|
||||
},
|
||||
{
|
||||
"start": 2.6,
|
||||
"end": 3.1,
|
||||
"text": "Okay."
|
||||
}
|
||||
]
|
||||
}
|
||||
9
examples/minimal-merge/input-bob.json
Normal file
9
examples/minimal-merge/input-bob.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"segments": [
|
||||
{
|
||||
"start": 1.3,
|
||||
"end": 2.4,
|
||||
"text": "General Kenobi."
|
||||
}
|
||||
]
|
||||
}
|
||||
8
examples/minimal-merge/speakers.yml
Normal file
8
examples/minimal-merge/speakers.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
match:
|
||||
- speaker: "Alice Example"
|
||||
match:
|
||||
- "alice"
|
||||
|
||||
- speaker: "Bob Example"
|
||||
match:
|
||||
- "bob"
|
||||
13
examples/normalize/bare-segments-array.json
Normal file
13
examples/normalize/bare-segments-array.json
Normal file
@@ -0,0 +1,13 @@
|
||||
[
|
||||
{
|
||||
"start": 2.5,
|
||||
"end": 3.0,
|
||||
"speaker": "Bob",
|
||||
"text": "later"
|
||||
},
|
||||
{
|
||||
"end": 2.0,
|
||||
"speaker": "",
|
||||
"text": "no start uses end"
|
||||
}
|
||||
]
|
||||
19
examples/normalize/object-with-segments.json
Normal file
19
examples/normalize/object-with-segments.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"segments": [
|
||||
{
|
||||
"id": 7,
|
||||
"start": 2.0,
|
||||
"end": 2.5,
|
||||
"speaker": "Bob",
|
||||
"text": "second"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"start": 1.0,
|
||||
"end": 1.3,
|
||||
"speaker": "Alice",
|
||||
"text": "first",
|
||||
"categories": ["backchannel"]
|
||||
}
|
||||
]
|
||||
}
|
||||
8
examples/speakers.yml
Normal file
8
examples/speakers.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
match:
|
||||
- speaker: "Alice Example"
|
||||
match:
|
||||
- "alice"
|
||||
|
||||
- speaker: "Bob Example"
|
||||
match:
|
||||
- "bob"
|
||||
64
examples/trim/input-full.json
Normal file
64
examples/trim/input-full.json
Normal file
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"metadata": {
|
||||
"application": "seriatim",
|
||||
"version": "dev",
|
||||
"input_reader": "json-files",
|
||||
"input_files": [
|
||||
"examples/minimal-merge/input-alice.json",
|
||||
"examples/minimal-merge/input-bob.json"
|
||||
],
|
||||
"preprocessing_modules": [
|
||||
"validate-raw",
|
||||
"normalize-speakers",
|
||||
"trim-text"
|
||||
],
|
||||
"postprocessing_modules": [
|
||||
"detect-overlaps",
|
||||
"resolve-overlaps",
|
||||
"backchannel",
|
||||
"filler",
|
||||
"resolve-danglers",
|
||||
"coalesce",
|
||||
"detect-overlaps",
|
||||
"autocorrect",
|
||||
"assign-ids",
|
||||
"validate-output"
|
||||
],
|
||||
"output_modules": [
|
||||
"json"
|
||||
]
|
||||
},
|
||||
"segments": [
|
||||
{
|
||||
"id": 1,
|
||||
"source": "examples/minimal-merge/input-alice.json",
|
||||
"source_segment_index": 0,
|
||||
"speaker": "Alice Example",
|
||||
"start": 0,
|
||||
"end": 1.2,
|
||||
"text": "Hello there."
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"source": "examples/minimal-merge/input-bob.json",
|
||||
"source_segment_index": 0,
|
||||
"speaker": "Bob Example",
|
||||
"start": 1.3,
|
||||
"end": 2.4,
|
||||
"text": "General Kenobi."
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"source": "examples/minimal-merge/input-alice.json",
|
||||
"source_segment_index": 1,
|
||||
"speaker": "Alice Example",
|
||||
"start": 2.6,
|
||||
"end": 3.1,
|
||||
"text": "Okay.",
|
||||
"categories": [
|
||||
"backchannel"
|
||||
]
|
||||
}
|
||||
],
|
||||
"overlap_groups": []
|
||||
}
|
||||
Reference in New Issue
Block a user