11 KiB
Architecture
This document defines Narratio's intended high-level architecture and the
invariants that changes must preserve. Implemented component details belong in
the Internal Overview and its linked documents.
Significant architectural decision history belongs under docs/adr/ when such
records exist.
System Shape
Narratio is a small Go application that turns D&D session audio into polished transcripts and generated session artifacts. It is an explicit, stage-driven orchestrator, not a general workflow engine.
Narratio coordinates specialized external systems rather than reimplementing their domains:
- WhisperX performs transcription;
- Seriatim performs deterministic transcript processing and rendering;
- Audita performs transcript correction and polishing;
- Notarius extracts validated structured artifact bundles; and
- Scriptorium executes prompts and produces configured artifacts.
Narratio owns orchestration, configuration resolution, session and run state, artifact and path modeling, manifest persistence, stage sequencing, resume, restore, cleanup gates, and publish semantics. External contracts are defined in the integration documentation.
The pipeline has one canonical ordered stage set. Configuration may enable, disable, or parameterize supported behavior, but it must not turn that sequence into an arbitrary DAG or hide orchestration in generic workflow abstractions. The implemented stage inventory belongs in the Internal Overview.
Narratio is contract-first without being abstraction-heavy. Interfaces and extension points should protect demonstrated boundaries. New abstraction is not itself an architectural goal.
Ownership And Dependency Direction
The application boundary owns command dispatch, configuration selection, production composition, session locking, and top-level lifecycle. It may depend on concrete implementations to assemble a run.
Stage orchestration expresses intent in Narratio-level data and interfaces. Stages may depend on configuration, manifest, artifact, path, and adapter contracts, but they must not depend on transport-specific request types, subprocess argument construction, cloud SDK types, or downstream tool internals.
Adapters translate between Narratio contracts and external systems. They own HTTP, subprocess, notification, and object-storage mechanics, including command construction, transport behavior, provider response handling, and external error adaptation. External dependency types must remain inside the adapter that owns them unless that dependency is the adapter's explicit public contract. WhisperX HTTP behavior, Seriatim, Audita, Notarius, and Scriptorium command construction, notification transport, and object-storage SDK details remain behind these boundaries.
State and path services must not infer stage policy. Storage implementations receive explicit bucket-relative keys and do not infer campaign, session, run, or root-prefix semantics. Manifest persistence records transitions but does not choose orchestration policy. Artifact resolution identifies and validates artifacts but does not execute producers.
Dependencies should remain narrow and point toward Narratio-owned contracts. Prefer the Go standard library. Add an external dependency only when it provides a clear correctness, security, interoperability, or complexity benefit, and confine it to the boundary that needs it.
Stage Boundaries
Each stage has one explicit responsibility and declares:
- required input state;
- produced output state;
- configuration it consumes;
- external adapters it uses;
- manifest references and metadata it reads or writes;
- skip, force, invalidation, and resume behavior; and
- failure behavior.
Stages write and validate run-local results before materializing canonical outputs where that distinction applies. A stage is complete only after its required outputs have been written, validated, and recorded in durable manifest state. Later stages depend on recorded success and artifact resolution, not merely on incidental files existing on disk.
A failed or interrupted stage must not be presented as successful. Failure should preserve enough local state and diagnostics for inspection, recovery, and resume. Forcing an upstream stage invalidates succeeded downstream work according to the canonical stage order.
A stage may explicitly self-skip with a stable reason and no outputs. That outcome is persisted, clears older outputs owned by the stage, and is reconsidered on a later invocation. A stage may also validate whether an otherwise successful recorded result is still resumable; an obsolete result is staled and rerun, while an unsafe condition that prevents a sound decision stops execution.
Shared behavior should live behind a narrow service or helper with one clear owner. Stages must not reach across boundaries or reproduce adapter, manifest, artifact, or path policy ad hoc.
Manifest, Resume, And Restore
The session manifest is the durable ledger for progress across invocations. It records session and run identity, stage state, input and output references, diagnostic references, checksums or provenance where useful, and non-secret adapter and publish metadata.
Resume and skip decisions are manifest-driven. Filesystem state may be inspected and validated, but file presence alone does not replace recorded stage state. Invocation-scoped run records provide an audit of one execution; they do not replace the session manifest as progress authority.
Restore treats committed remote current state as its authority. It must plan deterministically, confine remote-to-local paths, protect local conflicts, and install the validated session manifest after other restored durable files. The physical workflow and recovery procedures belong in Operations.
Configuration
Configuration is strict, explicit, centralized, and operator-oriented.
- YAML decoding rejects unknown fields.
- Defaults are centralized and testable.
- Empty configured values do not silently replace meaningful defaults.
- Validation rejects invalid composition before stage execution where practical.
- Session templating remains narrow and deterministic rather than becoming a general configuration language.
- Secret values are supplied indirectly and are not persisted in ordinary configuration.
Narratio must not become a second configuration system for downstream tools. External systems own their runtime defaults wherever practical; Narratio passes the paths required by its stage contracts and explicit operator overrides. The field-level contract and credential-supply mechanisms belong in Configuration.
Artifacts, Paths, And Storage
Artifact identities and local and remote paths are application contracts. Canonical helpers own workspace, spool, cache, session, run, input, transcript, artifact, log, report, configuration, and publish-current paths. Callers must not reconstruct canonical paths through scattered string concatenation.
Artifact resolution is deterministic and manifest-aware. Producers materialize canonical outputs before reporting success, and consumers resolve declared artifact identities rather than infer files from unrelated directory contents. External artifact bundles become current only through validated immutable promotion and manifest records; directory presence alone never establishes availability.
Writes, moves, replacements, and deletions must use narrow, explicit, root-confined destinations. Symlinks, traversal, broad roots, and ambiguous relative destinations must not expand the scope of an operation. Cleanup is permitted only through explicit operator action or configured post-publish gates, and it must preserve durable cache unless cache removal is explicitly requested.
Physical layout, retention, and operational lifecycle belong in Operations. Logical external formats and durable integration contracts belong under Integrations.
Publish Commit Boundary
Publish has one explicit remote commit boundary. A remote run becomes current
only after Narratio has successfully uploaded the run record, required published
outputs, current/manifest.json, and finally current/run_id.txt.
current/run_id.txt is the commit marker and must be written last. Failed,
incomplete, skipped, or uncommitted publish attempts must not be presented as
current remote state. Publish locks remain authoritative and are not bypassed by
a forced run.
Automatic local cleanup is permitted only after a successful publish commit, only when explicitly configured, and only through the path-safety guardrails.
Security, Privacy, And Diagnostics
Narratio handles private campaign material. Transcripts, prompts, generated artifacts, reports, logs, manifests, and diagnostic files are potentially sensitive.
Raw secrets must not be stored in pipeline, campaign, or session YAML or written to manifests, logs, generated configuration, reports, publish metadata, documentation, or examples. Secrets enter through configured environment variable names or secret-file references. Diagnostics should avoid transcript and prompt content unless a deliberate, bounded inspection mechanism requires it.
Logs, reports, generated invocation files, generated configuration, and render debug files are diagnostics, not canonical pipeline products. They should be durable and discoverable where configured, and manifest references must preserve the distinction between diagnostics and artifacts.
Documentation security rules belong in the Documentation Policy. Credential supply belongs in Configuration, while permissions, sensitive runtime-artifact handling, and recovery belong in Operations.
Determinism And Testability
Narratio prefers deterministic behavior where practical, including stable local and remote layouts, sorted operation order, predictable generated configuration, repeatable command construction, deterministic artifact resolution, and reproducible planning.
Run IDs and timestamps may be intentionally variable, but surrounding behavior must remain controllable in tests. Core behavior should be testable without live external services; expensive, nondeterministic, destructive, or external boundaries should be replaceable with focused test doubles. General testing philosophy and sufficiency rules belong in the Testing Policy.
Documentation And Decision Records
Documentation follows the Documentation Policy. Current
behavior belongs in its canonical user, operator, integration, architecture, or
internal owner. Proposed behavior and implementation status belong under
docs/roadmap/.
Significant architectural decisions may be recorded under docs/adr/ using the
format and lifecycle defined by the documentation policy. ADR acceptance does
not establish that a decision has been implemented.
Architectural Non-Goals
Narratio does not aim to provide:
- a generic DAG or workflow engine;
- a replacement configuration layer for WhisperX, Seriatim, Audita, Scriptorium, or other downstream tools;
- a storage abstraction broader than the needs of this pipeline;
- stage logic coupled directly to cloud SDKs, transports, subprocess details, or downstream implementation internals;
- raw-secret persistence;
- implicit cross-stage behavior that bypasses manifest and artifact contracts; or
- a prompt-authoring system.