# narratio `narratio` is a Go orchestration application for processing D&D session audio into transcripts and generated artifacts. ## Current Implementation Implemented now: - strict config loading/validation (`pipeline.yml` and `session.yml`) - local workspace/session layout, locking, and manifest persistence - resumable stage control (`run`, `plan`, `resume`, `run-stage`, `status`) - real `prepare`, `transcribe`, `merge`, `polish`, `trim`, and `analyze` stages - real WhisperX, Seriatim, and Audita adapters - real Scriptorium subprocess adapter - optional Scriptorium render diagnostics (`render_debug`) Not implemented yet: - real `archive` behavior - real `notify` behavior - additional analyze artifacts beyond `session_recap` - generic DAG orchestration ## Config Files Narratio expects two YAML files: - `pipeline.yml`: pipeline/workspace settings - `session.yml`: per-session settings YAML decoding is strict (`KnownFields(true)`), so unknown fields fail fast. ## Canonical Stage Order 1. `prepare` 2. `transcribe` 3. `merge` 4. `polish` 5. `trim` 6. `analyze` 7. `archive` 8. `notify` ## Transcript Tiers - `transcripts/merged.json`: canonical deterministic merged transcript from Seriatim merge - `transcripts/processed.json`: full polished transcript from Audita polish - `transcripts/trimmed.json`: gameplay-only polished transcript from trim stage ## Trim Configuration `pipeline.trim` is optional. If omitted, no trim config is loaded. If `trim.enabled` is omitted, it defaults to `false`. When `trim.enabled: true`: - `trim.output_path` is required - `trim.bounds.prompt_id` is required - `trim.bounds.transcript_input_name` is required - `trim.bounds.output_path` is required - `trim.bounds.timeout` must be a valid Go duration when provided - `trim.bounds.render_debug: true` requires `trim.bounds.render_output_path` - `trim.bounds.profile_id` may be empty to use the prompt default profile Trim paths are treated as session-workdir-relative when not absolute. Example trim config: ```yaml trim: enabled: true output_path: "transcripts/trimmed.json" bounds: prompt_id: "dnd_session.bounds" profile_id: "" transcript_input_name: "transcript" output_path: "artifacts/session_bounds.json" timeout: "10m" render_debug: false render_output_path: "artifacts/session_bounds.render.json" seriatim: report: false ``` Trim behavior summary: - trim discovers and validates `transcripts/processed.json` - trim uses Scriptorium bounds (`dnd_session.bounds` by example config) to produce `artifacts/session_bounds.json` - bounds IDs are validated against the same processed transcript ID space that Seriatim trim will consume - trim converts bounds to Seriatim keep selector (for example `10-868`) and runs Seriatim trim - if trim is disabled, Narratio copies processed transcript to trimmed transcript and records `trim_action=copy_disabled` Trim outputs and diagnostics: - `artifacts/session_bounds.json` - `transcripts/trimmed.json` - `logs/scriptorium.bounds.stdout.log` - `logs/scriptorium.bounds.stderr.log` - `config/scriptorium.bounds.generated.yml` - `logs/seriatim.trim.stdout.log` - `logs/seriatim.trim.stderr.log` - `config/seriatim.trim.generated.yml` - optional bounds render-debug outputs: - `artifacts/session_bounds.render.json` - `logs/scriptorium.bounds.render.stdout.log` - `logs/scriptorium.bounds.render.stderr.log` - `config/scriptorium.bounds.render.generated.yml` Render-debug files are diagnostics and are not treated as canonical stage output artifact refs. ## Scriptorium Configuration `pipeline.scriptorium` is optional. When present, Narratio validates and uses it for analyze-stage artifact generation. Key points: - `scriptorium.binary` is required when section is present - `scriptorium.config_path` is optional - `scriptorium.timeout` defaults to `10m` when omitted - `scriptorium.render_debug` enables render diagnostics globally - artifacts are configured under `scriptorium.artifacts` (map shape supports multiple artifacts) - enabled artifacts require `prompt_id` and `output_path` - artifact `render_debug` may override global render setting - `vars` currently support boolean and string values Example `session_recap` artifact definition: ```yaml scriptorium: binary: "scriptorium" config_path: "/etc/scriptorium/config.yml" timeout: "10m" render_debug: false artifacts: session_recap: enabled: true prompt_id: "dnd.session_recap" profile_id: "local-quality" # optional output_path: "artifacts/session_recap.md" timeout: "10m" # render_debug: true # optional per-artifact override inputs: transcript: source: "trimmed_transcript" required: true previous_recap: source: "previous_session_artifact" artifact: "session_recap" path: "" # optional; set when available required: false vars: session_id: true session_date: true campaign_name: true previous_session_id: true output_kind: "session_recap" ``` Prompt IDs and profile IDs are configuration values. They are not hardcoded in analyze-stage logic. Do not put secrets in `pipeline.yml`. If API-key behavior is configured, use env var names only. ## Scriptorium Runtime Behavior Narratio integrates with Scriptorium through the public CLI subprocess contract: - generation: `scriptorium run` - diagnostics/testing: `scriptorium render --format json` when `render_debug` is enabled For the initial implementation, only `session_recap` generation is supported. Analyze-stage session recap behavior: - session recap should use gameplay-only transcript input (`source: trimmed_transcript`) - Narratio resolves `trimmed_transcript` from trim manifest output (`transcript_trimmed`) or fallback `transcripts/trimmed.json` - missing trimmed transcript fails clearly and advises running trim stage first - full polished transcript input (`source: processed_transcript`) remains supported for future table/meta-analysis artifacts - optionally includes `previous_recap` when configured and resolvable - omits optional previous recap when unavailable - fails if required inputs are missing - validates output file exists and is non-empty Expected session output paths: - `artifacts/session_recap.md` - `logs/scriptorium.session_recap.stdout.log` - `logs/scriptorium.session_recap.stderr.log` - `config/scriptorium.session_recap.generated.yml` - `artifacts/session_recap.render.json` when render diagnostics are enabled ## Examples Starter files: - `examples/pipeline.minimal.yml` - `examples/session.minimal.yml` - `examples/speakers.yml` ## Commands Run tests: ```bash go test ./... ``` Plan a run: ```bash go run ./cmd/narratio plan --config examples/pipeline.minimal.yml --session examples/session.minimal.yml ``` Run full pipeline: ```bash go run ./cmd/narratio run --config examples/pipeline.minimal.yml --session examples/session.minimal.yml ``` Run analyze only: ```bash go run ./cmd/narratio run-stage --config examples/pipeline.minimal.yml --session examples/session.minimal.yml analyze ``` ## Operational Note Checksum-based stale detection is not implemented yet. If prepared inputs or prompt/runtime config change, rerun the appropriate upstream stages before relying on downstream artifacts. Examples: - glossary/autocorrect/speaker-context changes: rerun at least `merge`, `polish`, `trim`, and `analyze` - trim bounds prompt/profile/config changes: rerun at least `trim` and `analyze` - session recap prompt/profile/input-source changes: rerun `analyze` ## Roadmap Near-term roadmap: - extend analyze to additional configured artifacts - support workflows where later artifacts consume earlier generated artifacts - keep orchestration explicit without a generic DAG engine - implement archive and notify backends