548 lines
21 KiB
Markdown
548 lines
21 KiB
Markdown
# Operations Guide
|
|
|
|
Operator workflow for running, recovering, and publishing Narratio sessions.
|
|
|
|
For command syntax, see [docs/cli.md](./cli.md). For field-level config, see [docs/config.md](./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:
|
|
|
|
```bash
|
|
narratio session init 2026-04-04 --output ./session.yml --date 2026-04-04 --title "Session 12"
|
|
```
|
|
|
|
Remote session object:
|
|
|
|
```bash
|
|
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](./config.md#notarius-reference-bindings).
|
|
|
|
## Standard Session Workflow
|
|
|
|
1. Select pipeline/campaign/session config.
|
|
2. Validate session readiness:
|
|
|
|
```bash
|
|
narratio session validate 2026-04-04
|
|
```
|
|
|
|
3. (Optional) inspect stage decisions:
|
|
|
|
```bash
|
|
narratio session plan 2026-04-04
|
|
```
|
|
|
|
4. Run the pipeline:
|
|
|
|
```bash
|
|
narratio run 2026-04-04
|
|
```
|
|
|
|
5. Check state:
|
|
|
|
```bash
|
|
narratio session status 2026-04-04
|
|
```
|
|
|
|
## 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:
|
|
|
|
```bash
|
|
narratio run-stage normalize 2026-04-04 --force
|
|
```
|
|
|
|
Contiguous bounded execution uses inclusive canonical endpoints:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
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](./troubleshooting.md#analysis-artifact-evidence-is-not-current).
|
|
|
|
## Artifact Selection
|
|
|
|
`--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.
|
|
Inspect the effective stable-input inventory and
|
|
prepared-file readiness with:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
narratio publish 2026-04-04
|
|
```
|
|
|
|
Equivalent:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
narratio session restore 2026-04-04 --dry-run
|
|
```
|
|
|
|
Apply:
|
|
|
|
```bash
|
|
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](#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:
|
|
|
|
```bash
|
|
narratio clean 2026-04-04
|
|
```
|
|
|
|
Global cleanup:
|
|
|
|
```bash
|
|
narratio clean --all
|
|
```
|
|
|
|
Dry-run and cache variants:
|
|
|
|
```bash
|
|
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.
|