6.8 KiB
Narratio Architecture
1. Purpose
narratio is a Go orchestrator for D&D session processing. It runs a stage-based local pipeline from audio input through transcript processing and artifact generation, with manifest-based skip/force/resume behavior.
Narratio integrates with Scriptorium through the public CLI (scriptorium run and scriptorium render) via synchronous subprocess execution.
2. Current Status
Implemented:
- strict
pipeline.yml+session.ymlloading with strict YAML field checking (KnownFields(true)) - local workspace/session layout, lock file handling, artifact path helpers, checksums, and atomic writes
- manifest store and stage status transitions for resumable runs
- real
prepare,transcribe,merge, andpolishstages - real WhisperX HTTP adapter
- real Seriatim subprocess adapter
- real Audita subprocess adapter
- real Scriptorium subprocess adapter
- real
analyzestage for initialsession_recapgeneration - optional Scriptorium render diagnostics (
render_debug) before production run
Still placeholder/future:
trimstage behaviorarchivestage behaviornotifystage behavior- additional Scriptorium artifact types beyond
session_recap - artifact-to-artifact workflows beyond the initial single-artifact implementation
- generic stale detection based on input/config checksums
3. Pipeline and Stage Boundaries
Canonical stage order:
preparetranscribemergepolishtrimanalyzearchivenotify
Boundary rules:
- orchestration logic lives in
internal/app - stage business logic lives in
internal/stage - external-tool CLI construction lives in adapter packages
- Scriptorium CLI details stay in
internal/adapters/scriptorium
4. Scriptorium Integration Model
Integration mode:
- public CLI subprocesses only (no Scriptorium internal Go packages, no HTTP API)
- production generation uses
scriptorium run - diagnostics/testing render uses
scriptorium render --format json
Run invocation shape used by adapter:
scriptorium run --prompt <prompt_id> --input name=path --out <output_path>
Optional flags passed when configured:
--config <path>--profile <profile_id>- repeated
--var name=value - repeated
--input name=path --timeout <duration>--api-key-env <ENV_NAME>when configured
Render invocation shape used by adapter:
scriptorium render --prompt <prompt_id> --input name=path --format json --out <render_output_path>
Adapter behavior:
- always passes
--out - captures stdout/stderr separately
- writes generated invocation metadata YAML (redacted, no secrets)
- treats exit code
0as success - treats exit code
1as failure - treats exit code
2as failure withvalidation_failed=trueand preserves output metadata when available - validates successful output files exist and are non-empty
- does not treat non-empty stderr as failure by itself
5. Configuration Contract
pipeline.scriptorium is optional. Existing pipelines without Scriptorium continue to work.
When pipeline.scriptorium is present:
binaryis required and non-emptyconfig_pathis optional; when provided it must be non-emptytimeoutis optional; when provided it must parse as a Go duration- default
timeoutis10m - unknown YAML fields fail strict decode
Artifacts are configured as a map under pipeline.scriptorium.artifacts so multiple artifacts are possible in the config shape.
For each artifact definition:
enabled: truerequires non-emptyprompt_idenabled: truerequires non-emptyoutput_pathtimeoutmust parse as Go duration when present- optional per-artifact
render_debugmay override globalscriptorium.render_debug inputsare named and each input requires non-emptysource- inputs may be optional (
required: false) varsvalues currently supportstringandbool
Prompt IDs and profile IDs are configuration values, not hardcoded stage logic.
6. Analyze Stage (Current Implementation)
The current real analyze implementation supports only scriptorium.artifacts.session_recap.
Behavior:
- if
pipeline.scriptoriumis missing, analyze returns a skipped result with metadata - if no Scriptorium artifacts are enabled, analyze returns a skipped result with metadata
- if enabled artifacts exist but
session_recapis not enabled, analyze fails clearly - processed transcript input is resolved from manifest (
polishoutput kindtranscript_processed) when available, otherwise fallback pathwork/<session_id>/transcripts/processed.json - processed transcript is validated as JSON with top-level
segmentsarray - configured inputs are resolved by source
- optional
previous_recapis omitted when unavailable - required
previous_recapfails before invocation when unavailable - vars are built from config + session metadata
render_debugcontrols pre-runscriptorium renderdiagnostics- render failure stops stage before production run
- render output is validated as JSON
- production call uses Scriptorium adapter
RunArtifact - successful run output must exist and be non-empty
- manifest records output refs, logs, generated config paths, and non-secret provenance metadata
7. Session Recap Paths
Current expected paths for session_recap:
- artifact output:
artifacts/session_recap.md - run stdout log:
logs/scriptorium.session_recap.stdout.log - run stderr log:
logs/scriptorium.session_recap.stderr.log - run generated invocation/config:
config/scriptorium.session_recap.generated.yml - render output (when enabled):
artifacts/session_recap.render.json - render stdout log:
logs/scriptorium.session_recap.render.stdout.log - render stderr log:
logs/scriptorium.session_recap.render.stderr.log - render generated invocation/config:
config/scriptorium.session_recap.render.generated.yml
8. Security and Privacy
- do not store secrets in pipeline YAML, generated invocation YAML, logs, or manifest metadata
- if API-key integration is configured, pass env var names only (never raw key values)
- avoid logging transcript content or rendered prompt content by default
- treat generated artifacts and logs as potentially sensitive session material
9. Roadmap
Planned next steps:
- extend analyze beyond
session_recapto additional configured artifacts - support artifact inputs that consume prior generated artifacts
- keep this composable without adding a generic DAG engine in the near term
- implement real
archivebackend behavior - implement real
notifybackend behavior - add checksum-based stale detection and stale transitions
Architectural invariants remain:
- strict config decoding/validation
- manifest-driven run control
- clear stage/adapter separation
- configuration-driven prompt/profile/input/vars/output mapping
- Scriptorium integration through public CLI subprocess contract