246 lines
7.6 KiB
Markdown
246 lines
7.6 KiB
Markdown
# 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`
|
|
|
|
## 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
|