Files
narratio/docs/operations.md

23 KiB

Operations Guide

Operator workflow for running, recovering, and publishing Narratio sessions.

For command syntax, see docs/cli.md. For field-level config, see docs/config.md.

Campaign and Session Selection

Campaign selection priority:

  • --campaign-file
  • --campaign
  • pipeline.campaigns.default_campaign_id

Session source priority:

  • --session
  • local default search paths
  • remote session object (S3) when local session file is not found and storage is configured

Session Initialization

Use session init to generate a concrete session file for local or remote use.

Local file:

narratio session init 2026-04-04 --output ./session.yml --date 2026-04-04 --title "Session 12"

Remote session object:

narratio session init 2026-04-04 --remote --force

If campaign.yml sets session_template_file, session init renders it. Template variables must resolve to concrete values.

Campaigns must provide stable input files for speakers, autocorrect, glossary, players, and party, and may provide an optional spell-catalog overlay. Session files may override those paths for one session. The prepare stage materializes them under inputs/; configured consumers use the prepared files, never the original campaign or session source paths. Field definitions and source IDs are in Configuration.

Standard Session Workflow

  1. Select pipeline/campaign/session config.
  2. Validate session readiness:
narratio session validate 2026-04-04
  1. (Optional) inspect stage decisions:
narratio session plan 2026-04-04
  1. Run the pipeline:
narratio run 2026-04-04
  1. Check state:
narratio session status 2026-04-04

Run, plan, and status output identify the resolved pipeline profile (or none) and effective configuration digest. Status distinguishes the current resolved value from the last value persisted in the session manifest, which helps diagnose profile switches without changing resume authority.

Before switching an operational profile, compare its effective meaning with the current selection through narratio config diff <left-profile> <right-profile>. The command is read-only and succeeds whether it finds differences or not. Its sorted records describe defaulted, expanded concrete configuration—not source file layout—so it can be used to review model, artifact, and publish changes without creating a session or run. Select the same campaign explicitly when profiles could resolve different campaign paths; see the CLI reference for syntax and record format.

Stage Execution and Continuation Behavior

Canonical stage order:

  1. prepare
  2. transcribe
  3. merge
  4. polish
  5. normalize
  6. trim
  7. render
  8. extract
  9. analyze
  10. publish
  11. notify

Execution rules:

  • succeeded stages are skipped unless --force is set; stages with semantic configuration contracts additionally require matching versioned evidence, and missing legacy evidence causes a safe one-time rerun;
  • run continues interrupted or partially completed sessions by running non-succeeded stages;
  • forcing a stage marks succeeded transitive dependents as stale before the replacement runs; render and extract are independent siblings; and
  • an executed failure, changed self-skip, or success that replaces a different effective outcome uses the same fixed dependency relation. A repeated self-skip with the same reason and no outputs is stable and does not perpetually rerun dependent work.

Every aggregate stage except analyze currently provides semantic-configuration evidence; analyze retains its more precise per-artifact fingerprints and validator. Changing prepare selection semantics reruns all fixed descendants; changing WhisperX language/service identity reuses prepare; changing a Seriatim merge transformation reuses prepare and transcribe; and changing an Audita model reuses prepare, transcribe, and merge while rebuilding transcript refinement. A trim change invalidates both render and extract through the fixed dependency relation, while a render-only change preserves the extract sibling.

Operational timeouts, retry/concurrency tuning, executable paths, workspace/cache/spool placement, reports, diagnostics, and secret values are excluded. Configuration, models, prompts, modules, or resources loaded privately inside external tools remain unobservable to Narratio. If their contents change behind the same configured identifier, explicitly force the affected stage.

An explicit self-skip is a durable skipped stage outcome that later runs reconsider. It differs from successful no-output execution: disabled render and publish, and absent or no-executable analyze, record succeeded with metadata and no outputs. Ordinary later runs reuse those successful results; force the affected stage after enabling or configuring it. Optional artifact inputs are omitted only from the consuming artifact invocation and do not make the stage self-skip.

Single-stage execution:

narratio run-stage normalize 2026-04-04 --force

Contiguous bounded execution uses inclusive canonical endpoints:

narratio session plan 2026-04-04 --from extract --through analyze --force
narratio run 2026-04-04 --from extract --through analyze --force

Omitting --from selects from prepare; omitting --through selects through notify. Force applies only within the selected range. Repeating --from, --through, or --force is rejected instead of resolving by argument order. The plan command uses the same selection contract and prints only the selected range. Planning is read-only: it clones the loaded manifest, models selected stage transitions and invalidation in memory, and invokes resume validation without writing the manifest, creating run directories, materializing files, or invoking pipeline adapters. Analyze detail separates explicit targets, prerequisite rebuilds, scheduled execution, and current reuse. This lets a coarsely stale aggregate analyze stage show zero artifact executions when its selected artifact evidence is still semantically current.

Before a bounded run or plan whose range starts after prepare, every excluded prefix stage must already have a session-manifest status of succeeded or skipped. Narratio reports the first absent, pending, running, failed, stale, or interrupted prerequisite without creating a run record or changing session state. Widen --from to include that stage, or recover it explicitly before retrying. Excluded prefix stages are not resume-validated or repaired as part of the bounded invocation; selected stages still reject missing, unsafe, or manifest-inconsistent inputs at their owning boundary.

Stages after --through are not prerequisites and are never scheduled by the bounded invocation. A selected forced stage can mark one of those succeeded dependents stale through the fixed invalidation relation, but the dependent does not execute until a later invocation selects it. Production composition likewise initializes only collaborators needed by the selected range and shared session lifecycle. In particular, render does not require Notarius or Scriptorium, extract does not require Scriptorium, and analyze does not require the transcription, Seriatim, Audita, or Notarius adapters.

For the common post-transcript development loop, use:

narratio regenerate-artifacts 2026-04-04
narratio regenerate-artifacts 2026-04-04 --artifacts session_recap,player_handout

This command is a transparent expansion to a forced bounded run from extract through analyze. Extraction always rebuilds its complete configured bundle. Analysis rebuilds the selected targets and their required analysis prerequisites, or uses the normal default selection when no artifact names are given. The command does not run publish or notify; delivery remains a separate operator action.

Inspect current artifact evidence, then publish explicitly when the regenerated set is ready:

narratio session artifacts 2026-04-04
narratio publish 2026-04-04

If planning or execution reports stale, missing, failed, legacy, or tampered analysis evidence, regenerate the affected target instead of copying an older canonical file into place or editing the manifest. See Troubleshooting: Analysis artifact evidence is not current.

Artifact Selection

For a configured artifact family, selecting its family key expands to every concrete character artifact. Select a concrete generated key to operate on one member only. Manifests and plan output retain the concrete key as the durable identity and include the family and character ID as optional provenance.

--artifacts can be used on run, session plan, run-stage, analyze, and publish. For a bounded run or plan, the selected range must contain analyze or publish.

Selection behavior:

  • validates names against pipeline.scriptorium.artifacts;
  • selects explicit analyze targets and permits their required configured prerequisites to be reused or rebuilt first;
  • filters publish rules for narratio.artifact.<name> sources only;
  • does not suppress built-in transcript, bounds, or explicitly configured narratio.extraction.<name> publish sources; and
  • never partially selects Notarius lanes.

Extraction Workflow

When Notarius is omitted or disabled, extract records an explicit skipped outcome with reason notarius_disabled and no outputs. A later invocation reconsiders the skipped stage, so enabling Notarius does not require force.

When Notarius extraction is enabled, the stage consumes the final trimmed JSON and preserves the complete validated Notarius bundle at:

  • artifacts/notarius/{narratio_run_id}/

The directory is immutable once promoted. Configured lanes become narratio.extraction.<name> sources for Scriptorium and explicit publish rules; the bundle and index.json are retained for audit and resume validation but are not selectable or published implicitly.

Configured Notarius references resolve only from the current manifest-backed prepared inputs. Their canonical locations are inputs/party.yml, inputs/players.yml, inputs/glossary.yml, and, when configured, inputs/spell_catalog.json. Extraction supplies Notarius with verified copies under runs/<run_id>/extract/references/ so a concurrent refresh of canonical prepared files cannot change the bytes consumed by an in-flight invocation. For a canonical party, preparation retains the validated authored party bytes at inputs/party.yml and generates inputs/players.yml from that roster. The manifest records their checksums separately, with the players input marked as derived from the party; refresh preparation after changing the roster rather than editing either prepared file. Inspect the effective stable-input inventory and prepared-file readiness with:

narratio session status 2026-04-04
narratio session validate 2026-04-04

Reference metadata records selector, source ID, session-relative path, checksum, and byte size, but never payload contents. Changing a prepared reference changes extraction identity: ordinary continuation rejects the old result, reruns Notarius, and marks successful downstream stages stale. If the prepared file is missing or inconsistent with its manifest checksum, repair the source configuration and refresh prepared state first:

narratio run-stage prepare 2026-04-04 --force

Starting a replacement clears the previous extraction payload from the current session-stage record. If that replacement fails or self-skips, the current record does not fall back to the earlier outputs. The earlier run manifest and immutable bundle remain available for inspection, but downstream resolution requires a new current successful extraction record.

Atomic Notarius bundle promotion is supported on Linux and macOS. On Windows and other operating systems, extraction fails before copying the bundle into a temporary promotion tree because Narratio has no verified atomic no-replace directory primitive there. This is an extraction limitation, not a broader platform-support guarantee for every Narratio workflow.

External Command Lifecycle

When an external command is cancelled or times out, Narratio terminates its owned descendants as well as the command itself. Cancellation first requests termination where the platform supports it, then force terminates after a bounded wait. A command is not considered finished until its leader has been reaped, and descendants that keep standard output or error open cannot keep the invocation blocked. Other operating systems fail closed rather than launch a command without tree ownership.

Subprocess stdout and stderr diagnostics are separately redacted and capped at 8 MiB per invocation. Narratio does not retain configured credential values in these logs or their error tails; reaching a capture limit terminates the command tree and reports which stream exceeded the limit.

Run-local diagnostics are:

  • runs/{run_id}/extract/notarius.receipt.json
  • runs/{run_id}/extract/notarius.stderr.log
  • runs/{run_id}/extract/notarius-output/ before durable promotion

The run-record upload is an allowlist derived from the validated run manifest, not a workspace scan. Each declared source is opened without following symlinked ancestors or the leaf, verified as a regular file, and streamed from that verified descriptor. Unlisted files and unsafe entries are never uploaded. The durable bundle is never scanned for implicit publication; only lanes named by explicit pipeline.publish.outputs rules are uploaded.

To intentionally replace the current extraction result, run:

narratio run-stage extract 2026-04-04 --force

Narratio automatically reruns extraction when its recorded invocation contract, prepared Narratio reference identities, or durable output validation changes. The semantic portion covers Notarius enablement, pipeline identity, declared reference mapping, and output contracts. Executable, timeout, working directory, and private config-file paths are operational and do not invalidate a current result. It cannot fingerprint configuration files, profiles, prompts, modules, or other references loaded transitively by Notarius itself. Force extraction after changing any of those inputs, even when the top-level Narratio and Notarius config paths remain the same. A forced extract marks successful downstream stages stale. Ordinary extraction failures or outcome changes also stale affected downstream stages, while an identical repeated notarius_disabled self-skip does not repeatedly invalidate them.

Publish reuse additionally tracks enabled/run-upload behavior, normalized output rules, static locks, and remote backend/bucket/region/endpoint/root identity. Credential environment names, local workspace placement, and run IDs are excluded. Regardless of semantic reuse evidence, executing publish still revalidates mutable remote locks immediately before commit selection.

Publish Workflow

Run publish only:

narratio publish 2026-04-04

Equivalent:

narratio run-stage publish 2026-04-04 --force

Publish commit model:

  • uploads eligible run files under {session_prefix}/runs/{run_id}/, excluding audio and the run-local Notarius staging bundle;
  • uploads configured published outputs and previous/** cache files into the same immutable run scope, including only explicitly configured extraction lanes;
  • writes {session_prefix}/runs/{run_id}/commit.json after all declared immutable objects are uploaded and verified; and
  • writes {session_prefix}/current/commit-pointer.json once, last.

current/commit-pointer.json is the remote current-state commit marker. It selects exactly one immutable commit, which declares the complete object set.

Remote Commit Migration

The immutable remote commit contract uses runs/{run_id}/commit.json to declare a run's complete object set and a small current/commit-pointer.json to select it. The pointer binds the selected commit by version, checksum, size, and storage generation; committed artifacts are also checksum- and generation-bound. Readers accept this contract now and strictly reject mismatched or unknown data.

Legacy reads are limited to a coherent current/manifest.json and current/run_id.txt pair; a torn pair is rejected. New publication does not write that pair and remote commit state does not carry local current_pointer_written metadata.

Publish Locks

Lock sources:

  • static locks in pipeline.publish.locks
  • mutable remote locks in {session_prefix}/locks.yml

Effective lock rules:

  • static and remote locks are merged;
  • static locks win on source collisions;
  • locked outputs are intentional skips;
  • lock add/remove commands mutate only remote lock state through generation-bound conditional writes. A command retries a bounded number of concurrent conflicts while its invocation context remains active, so it never replaces a different lock-document generation; and
  • a publish re-reads remote locks immediately before it writes the current commit pointer. A lock committed before that recheck prevents selecting the new snapshot, even though its already-uploaded immutable objects may remain available for a later retry.

Examples:

narratio session locks 2026-04-04
narratio session locks add 2026-04-04 narratio.artifact.session_recap --reason "manual edits" --force
narratio session locks remove 2026-04-04 narratio.artifact.session_recap

Restore Workflow

Use restore when local durable session state is missing or stale and remote committed current state is authoritative.

Dry run:

narratio session restore 2026-04-04 --dry-run

Apply:

narratio session restore 2026-04-04

--dry-run does not write durable session files. It still reads the selected remote current state and may read object identity/content needed to classify the plan, so it is not a network-free operation.

Default restore scope:

  • the committed session manifest and the committed transcript/artifact objects declared by the selected remote commit
  • previous/** when needed by configured previous-session artifact inputs

Optional:

  • --include-audio to include audio/**
  • --force to overwrite eligible conflicting regular files; it never replaces directories or other non-regular local targets

Restore writes an execution report at reports/restore-latest.json.

If restore fails after beginning installation, it leaves a durable .restore-incomplete.json marker in the session root. Pipeline runs will stop until you rerun the same restore command and it completes. Restore intentionally does not try to roll back files already installed; retrying the selected remote snapshot is the recovery procedure.

Local State Layout

Session root:

  • {workspace.root}/work/{campaign}/{session_id}

Durable session paths:

  • manifest.json
  • inputs/**
  • audio/**
  • transcripts/**
  • artifacts/**
  • previous/**
  • reports/**
  • logs/**
  • config/**
  • runs/**

Validated Notarius bundles live below artifacts/notarius/{run_id}/; receipt, stderr, and pre-promotion output remain in the producing run's extract directory as described in Extraction Workflow.

Run-local layout:

  • runs/{run_id}/{stage}/outputs
  • runs/{run_id}/{stage}/logs
  • runs/{run_id}/{stage}/reports
  • runs/{run_id}/{stage}/config
  • runs/{run_id}/{stage}/scratch

Spool layout (runtime/transient):

  • {spool.root}/{campaign}/{session_id}/{run_id}/...
  • restore audio spool under {spool.root}/{campaign}/{session_id}/restore/audio

Cache layout (durable S3 audio cache):

  • {cache.root}/s3/{bucket}/...

Each cached audio file has an adjacent managed identity record. It binds the file to its remote object version and verified digest; deleting or altering the record simply causes Narratio to download and verify the object again.

Workspace Permissions

Ordinary Narratio workspace content is intentionally shareable with the workspace group. On POSIX systems, Narratio-created workspace, spool, and cache directories converge on setgid 02775; ordinary files, including manifests, transcripts, generated configuration, logs, reports, and Notarius artifacts, converge on 0664. Narratio explicitly applies these modes so a restrictive caller umask does not remove group write or setgid. It does not change file or directory ownership: the configured workspace's existing group is inherited.

Windows does not implement POSIX mode bits or setgid semantics. Configure the workspace, spool, and cache locations with an ACL that grants the collaborating group read/write access, and configure credential locations with an ACL limited to the intended credential owner. Do not use POSIX mode displays as evidence of Windows access control.

API keys are credentials, not ordinary workspace data. Store them outside the shared workspace or in a separately restricted credential location; ordinary workspace group access must never be treated as authorization to read keys. On POSIX, provision a credential directory as 0700 and credential files as 0600; Narratio rejects group- or other-readable configured credential paths. On Windows, restrict the directory and files with ACLs to the credential owner.

External adapter results are individually bounded before Narratio validates or materializes them. These per-file limits do not reserve disk space: prevent hard disk exhaustion with filesystem, service, container, or volume quotas sized for the session workload.

Cleanup

Session-scoped cleanup:

narratio clean 2026-04-04

Global cleanup:

narratio clean --all

Dry-run and cache variants:

narratio clean 2026-04-04 --dry-run --clear-cache
narratio clean --all --dry-run --clear-cache

Rules:

  • clean deletes work/spool session state;
  • cache is preserved unless --clear-cache is set;
  • each deletion is confined beneath its configured workspace, spool, or cache root and refuses symlinked paths;
  • automatic post-publish cleanup is gated by successful publish commit plus:
    • pipeline.spool.delete_audio_after_publish=true
    • pipeline.workspace.cleanup_after_publish=true
    • Narratio first records the exact run-scoped cleanup obligation. If cleanup reports incomplete, the remote committed snapshot remains current; rerun publish to retry only the outstanding confined local cleanup.

Post-publish cleanup is evaluated only when publish actually executes in the current invocation. A bounded range that excludes publish does not replay a cleanup obligation as an unrelated side effect.

Operational Caveats

  • Local and S3 audio modes are mutually exclusive.
  • Publish requires prerequisite stages through render and analyze to be succeeded.
  • Markdown publish defaults require render outputs (transcripts/final.md and transcripts/final.trimmed.md).
  • Restore requires configured object storage and committed remote current state.
  • Storage-backed commands load filesystem secrets before object-store initialization.