diff --git a/docs/cli.md b/docs/cli.md index c68f237..44d5251 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -6,44 +6,46 @@ narratio run --session-id 2026-04-04 ``` -This uses default config discovery for `pipeline.yml` and `session.yml`; both files must be discoverable for this command to run. +This command uses default config discovery for `pipeline.yml` and `session.yml`; both files must be discoverable unless you pass explicit `--config` and `--session` paths. ## Command Overview Implemented commands: -- `run`: execute the full stage plan and persist manifest state. -- `plan`: validate config, prepare workdir, and print run/skip decisions. -- `resume`: continue from the first non-succeeded stage in the manifest. -- `status`: read and print stage statuses from an existing manifest file. -- `run-stage`: execute exactly one selected stage. +- `run`: execute pipeline stages and persist manifest state. +- `plan`: validate config, prepare workspace layout, and print stage run/skip decisions. +- `resume`: continue from first non-succeeded stage unless forced. +- `status`: read and print stage statuses from an existing manifest. +- `run-stage`: execute exactly one stage. -Unknown commands print usage (`Usage: narratio `) and exit non-zero. +Unknown commands print usage and exit non-zero. -For configuration field details, see [docs/config.md](./config.md). For operational lifecycle details, see [docs/operations.md](./operations.md). +For config semantics, see [docs/config.md](./config.md). For operator lifecycle and recovery, see [docs/operations.md](./operations.md). ## Complete Flag Reference ### `run` -- `--config `: optional explicit `pipeline.yml` path; if omitted, default locations are searched. -- `--session `: optional explicit `session.yml` path; if omitted, default locations are searched. -- `--session-id `: session template variable value for `session.yml` rendering. -- `--force`: force stage execution (prevents skip of already-succeeded stages). +- `--config `: optional explicit `pipeline.yml` path. +- `--session `: optional explicit `session.yml` path. +- `--session-id `: session template variable value. +- `--force`: force stage execution. +- `--artifacts `: analyze artifact keys to execute (repeatable or comma-separated). ### `plan` - `--config ` - `--session ` - `--session-id ` -- `--force`: show forced run decisions instead of normal skip behavior. +- `--force` ### `resume` - `--config ` - `--session ` - `--session-id ` -- `--force`: run full stage order rather than starting at first non-succeeded stage. +- `--force` +- `--artifacts `: analyze artifact keys to execute (repeatable or comma-separated). ### `run-stage` @@ -51,6 +53,7 @@ For configuration field details, see [docs/config.md](./config.md). For operatio - `--session ` - `--session-id ` - `--force` +- `--artifacts `: analyze artifact keys to execute (repeatable or comma-separated). - positional ``: required stage name. Valid stage names: @@ -74,31 +77,27 @@ Valid stage names: ### `run` Purpose: - -- Validate configuration and execute all stages in canonical order. +- Execute configured stages in canonical order. Syntax: ```bash -narratio run [--config ] [--session ] [--session-id ] [--force] +narratio run [--config ] [--session ] [--session-id ] [--force] [--artifacts ] ``` Success output: - - `narratio run: session ; executed= skipped=; manifest=` Common failure cases: - -- no pipeline config found in default search paths when `--config` is omitted. -- no session config found in default search paths when `--session` is omitted. -- invalid flags or unexpected positional arguments. -- config/template/validation errors. +- missing default config/session paths when flags omitted. +- invalid template/rendered session mismatch. +- unknown/invalid `--artifacts` value. +- `--artifacts` with unknown configured artifact key. ### `plan` Purpose: - -- Validate config, load secrets (if configured), prepare workspace layout, and print per-stage run/skip decisions. +- Validate config, load secrets (if configured), prepare workdir, and print stage run/skip decisions. Syntax: @@ -107,43 +106,38 @@ narratio plan [--config ] [--session ] [--session-id ``` Success output includes: - - `narratio plan: workdir prepared at ` - one line per stage (`: run|skip`) - `totals: run= skip=` Common failure cases: - -- same discovery, template, and validation failures as `run`. +- same config/session discovery and validation failures as `run`. - secrets directory read failures when `pipeline.secrets.env_dir` is configured. ### `resume` Purpose: - -- Continue execution from manifest state for the same session. +- Continue from session-manifest stage status. Syntax: ```bash -narratio resume [--config ] [--session ] [--session-id ] [--force] +narratio resume [--config ] [--session ] [--session-id ] [--force] [--artifacts ] ``` Success output: - -- either `narratio resume: session has no remaining stages` +- `narratio resume: session has no remaining stages` - or `narratio resume: session ; executed= skipped=; manifest=` Common failure cases: - - same discovery/template/validation failures as `run`. -- manifest load errors when an existing manifest is unreadable. +- manifest load errors when existing manifest is unreadable. +- invalid or unknown artifact selections. ### `status` Purpose: - -- Inspect an existing manifest file without running stages. +- Inspect one manifest file without executing stages. Syntax: @@ -152,37 +146,37 @@ narratio status --manifest ``` Success output includes: - - `session_id: ` - `updated_at: ` -- `stages:` section with `- : ` entries. +- `stages:` entries (`- : `) Common failure cases: - - missing `--manifest`. -- manifest path unreadable or invalid JSON shape. +- unreadable or invalid manifest path. ### `run-stage` Purpose: - -- Execute exactly one stage from the supported stage set. +- Execute exactly one stage. Syntax: ```bash -narratio run-stage [--config ] [--session ] [--session-id ] [--force] +narratio run-stage [--config ] [--session ] [--session-id ] [--force] [--artifacts ] ``` Success output: - - `narratio run-stage: stage= executed= skipped= force=; manifest=` -Common failure cases: +`--artifacts` behavior: +- accepted only when `` is `analyze`. +- names are normalized (trimmed, deduplicated, sorted). +- unknown configured artifact keys fail. -- missing stage positional argument. +Common failure cases: +- missing stage positional arg. - unknown stage name. -- same discovery/template/validation failures as `run`. +- using `--artifacts` with any non-`analyze` stage. ## Common Workflows @@ -192,39 +186,37 @@ Default-discovery run: narratio run --session-id 2026-04-04 ``` -Explicit config/session run: +Run only selected analyze artifacts: ```bash -narratio run --config /etc/narratio/pipeline.yml --session ./session.yml --session-id 2026-04-04 +narratio run --session-id 2026-04-04 --artifacts session_recap,player_handout ``` -Plan before run: +Resume with selected analyze artifacts: ```bash -narratio plan --config /etc/narratio/pipeline.yml --session ./session.yml --session-id 2026-04-04 +narratio resume --session-id 2026-04-04 --artifacts player_handout ``` -Resume interrupted work: +Run only analyze stage with selected artifacts: ```bash -narratio resume --config /etc/narratio/pipeline.yml --session ./session.yml --session-id 2026-04-04 -``` - -Run one stage: - -```bash -narratio run-stage --config /etc/narratio/pipeline.yml --session ./session.yml --session-id 2026-04-04 polish +narratio run-stage --session-id 2026-04-04 --artifacts player_handout analyze ``` ## Diagnostic / Recovery Commands -Read stage status from a manifest: +Inspect stage status: ```bash narratio status --manifest ``` -How to get manifest path: +Get manifest path from previous output: +- `run`, `resume`, and `run-stage` print `manifest=` on success. -- `run`, `resume`, and `run-stage` success output includes `manifest=`. -- use that path with `status` for direct inspection. +## `--artifacts` and `--force` + +- `--artifacts` filters which configured artifacts are executable when analyze runs. +- `--artifacts` does not imply `--force`. +- If analyze is already `succeeded` and `--force` is not set, runner-level skip still applies. diff --git a/docs/config.md b/docs/config.md index ce46def..21907cc 100644 --- a/docs/config.md +++ b/docs/config.md @@ -14,45 +14,42 @@ These commands load and validate both files before running: - `narratio resume` - `narratio run-stage` -Configuration behavior: +Behavior: - strict YAML decode is enabled (`KnownFields(true)`): unknown fields fail. -- session templates are rendered before session YAML decode. -- defaults are applied for many optional pipeline fields. +- session templates render before session YAML decode. +- defaults are applied for optional pipeline fields. - validation enforces required fields, value formats, and cross-field constraints. ## 2. Config file discovery Pipeline config lookup for `run`, `plan`, `resume`, and `run-stage`: -- If `--config ` is provided, that explicit path is used. -- If `--config` is omitted, Narratio searches in order: +- If `--config ` is provided, that path is used. +- If omitted, Narratio searches in order: 1. `/usr/local/etc/narratio/pipeline.yml` 2. `/etc/narratio/pipeline.yml` -- The first existing file wins. -- If none exist, the command fails with a searched-paths error. +- First existing file wins. ## 3. Session file discovery and templating Session config lookup for `run`, `plan`, `resume`, and `run-stage`: -- If `--session ` is provided, that explicit path is used. -- If `--session` is omitted, Narratio searches in order: +- If `--session ` is provided, that path is used. +- If omitted, Narratio searches in order: 1. `./session.yml` 2. `/usr/local/etc/narratio/session.yml` 3. `/etc/narratio/session.yml` -- The first existing file wins. -- If none exist, the command fails and asks you to pass `--session`. +- First existing file wins. -Session templating: +Template behavior: - Supported placeholders: - `{{session_id}}` - `{{ session_id }}` -- `--session-id ` supplies the template value. -- Unresolved placeholders fail with a template-rendering error. -- If `--session-id` is provided and rendered `session_id` differs, load fails with a mismatch error. -- Strict YAML decode still applies after template rendering. +- `--session-id ` supplies the placeholder value. +- unresolved placeholders fail load. +- if rendered `session_id` mismatches `--session-id`, load fails. ## 4. Minimal pipeline config @@ -64,9 +61,8 @@ whisperx: Why this is sufficient: - `whisperx.transcribe_url` is required. -- `workspace.root` is optional and defaults to `/var/lib/narratio`. -- Seriatim and Audita sections may be omitted; defaults are applied. -- Archive, storage, spool, normalize, and other optional sections get defaults when omitted. +- `workspace.root` defaults to `/var/lib/narratio`. +- optional sections (`seriatim`, `audita`, `archive`, `scriptorium`, `trim`, `normalize`, etc.) receive defaults or stay inactive. ## 5. Minimal session template @@ -119,18 +115,26 @@ archive: whisperx: transcribe_url: "https://transcription.example.com/transcribe" + +scriptorium: + artifacts: + session_recap: + enabled: true + prompt_id: dnd.session_recap + output_path: artifacts/session_recap.md + inputs: + transcript: + source: narratio.transcript.trimmed + required: true ``` Operational notes: -- `workspace.cleanup_after_archive` controls run-scoped workspace cleanup after successful archive commit. -- `spool.delete_audio_after_archive` controls run-scoped spool-audio cleanup after successful archive commit. -- S3 archive/session-audio workflows require `storage.s3.bucket`. +- archive promotion is explicit and path-based via `archive.promote_artifacts`. +- Narratio does not auto-promote all generated analyze artifacts. ## 7. Full pipeline reference -Defaults listed here are effective runtime defaults after load. - | Path | Type | Required | Default | | --- | --- | --- | --- | | `pipeline.workspace.root` | string | No | `/var/lib/narratio` | @@ -150,7 +154,7 @@ Defaults listed here are effective runtime defaults after load. | `pipeline.spool.delete_audio_after_archive` | bool | No | `false` | | `pipeline.archive.enabled` | bool | No | `true` | | `pipeline.archive.upload_run` | bool | No | `true` | -| `pipeline.archive.promote_artifacts[]` | list | No | two default rules | +| `pipeline.archive.promote_artifacts[]` | list | No | trimmed + session_recap rules | | `pipeline.archive.promote_artifacts[].from` | string | Yes (per rule) | none | | `pipeline.archive.promote_artifacts[].to` | string | Yes (per rule) | none | | `pipeline.archive.promote_artifacts[].required` | bool | No | `true` | @@ -203,6 +207,7 @@ Defaults listed here are effective runtime defaults after load. | `pipeline.scriptorium.render_debug` | bool | No | `false` | | `pipeline.scriptorium.artifacts` | map | No | empty | | `pipeline.scriptorium.artifacts..enabled` | bool | No | `false` | +| `pipeline.scriptorium.artifacts..depends_on[]` | list[string] | No | empty | | `pipeline.scriptorium.artifacts..render_debug` | bool | No | unset | | `pipeline.scriptorium.artifacts..prompt_id` | string | Conditional | none | | `pipeline.scriptorium.artifacts..profile_id` | string | No | empty | @@ -221,6 +226,18 @@ Defaults listed here are effective runtime defaults after load. | `pipeline.notification.recipient` | string | No | empty | | `pipeline.notification.timeout` | duration string | No | empty | +Scriptorium artifact-key and dependency rules: + +- artifact keys must match `^[a-z][a-z0-9_]*$`. +- enabled artifacts require `prompt_id` and `output_path`. +- `output_path` must be relative, traversal-safe, and under `artifacts/`. +- configured artifact input sources use `narratio.artifact.`. +- if input source references `narratio.artifact.`, artifact `` must exist and must be listed in `depends_on`. +- every `depends_on` entry must be a configured artifact key. +- self-dependency is rejected. +- enabled dependency cycles are rejected. +- any artifact referenced by `depends_on` or `narratio.artifact.` source must define `output_path` (even if not enabled). + Allowed `pipeline.scriptorium.artifacts..inputs..source` values: - `previous_session_artifact` @@ -229,7 +246,7 @@ Allowed `pipeline.scriptorium.artifacts..inputs..source` values: - `narratio.transcript.full` - `narratio.transcript.trimmed` - `narratio.bounds.session` -- `narratio.artifact.session_recap` +- `narratio.artifact.` ## 8. Full session reference @@ -248,11 +265,11 @@ Allowed `pipeline.scriptorium.artifacts..inputs..source` values: Audio-source rule: -- You must configure exactly one audio source mode: +- configure exactly one mode: - `audio_dir`, or - `audio_files` (at least one), or - `audio_s3.prefix` -- `audio_s3` cannot be combined with `audio_dir` or `audio_files`. +- `audio_s3` cannot be combined with local audio fields. ## 9. Secrets @@ -261,22 +278,21 @@ Narratio supports filesystem-based secret injection via `pipeline.secrets.env_di Behavior: - `env_dir` may be absolute or relative. -- Relative `env_dir` is resolved from Narratio’s current working directory. -- Each top-level file with a valid env-var filename (`[A-Za-z_][A-Za-z0-9_]*`) is loaded. -- File contents become env-var values, with trailing `\n` / `\r\n` trimmed. -- Existing process environment variables are preserved and not overwritten. -- Invalid names and directories inside `env_dir` are skipped. -- Missing/unreadable `env_dir` fails command execution. +- relative `env_dir` resolves from current working directory. +- files with valid env-var names (`[A-Za-z_][A-Za-z0-9_]*`) are loaded. +- values are loaded from file contents with trailing newline trimming. +- existing process env vars are preserved. +- invalid names and subdirectories are skipped. +- missing/unreadable `env_dir` fails command execution. Guidance: -- Store secret values in secret files or pre-set environment variables. -- Do not put secret values directly in `pipeline.yml` or `session.yml`. -- Use config fields like `llm_api_key_env` and S3 credential env names to reference secret variable names, not secret data. +- do not put secret values directly in YAML. +- configure env var names in config and provide values via env/secrets files. ## 10. Examples -Maintained config examples: +Maintained examples: - `docs/examples/pipeline.minimal.yml` - `docs/examples/pipeline.production.yml` @@ -285,4 +301,4 @@ Maintained config examples: - `docs/examples/session.local-audio.yml` - `docs/examples/session.s3-audio.yml` -These examples are covered by configuration load/validate tests in `internal/config`. +These examples are validated by `internal/config` tests. diff --git a/docs/examples/pipeline.full.annotated.yml b/docs/examples/pipeline.full.annotated.yml index 4dd7b79..e19d1bf 100644 --- a/docs/examples/pipeline.full.annotated.yml +++ b/docs/examples/pipeline.full.annotated.yml @@ -2,8 +2,8 @@ # Values are safe placeholders and must be adapted per environment. workspace: - # Required: local workspace root. - root: ./tmp/narratio-workspace + # Optional: defaults to /var/lib/narratio. + root: /var/lib/narratio/workspace # Optional: remove run-scoped workdir after successful archive commit. cleanup_after_archive: false @@ -14,7 +14,7 @@ workspace: storage: # Optional storage backend selector; use "s3" for archive + S3 audio workflows. backend: s3 - # Legacy fields retained in schema for compatibility. + # Compatibility fields retained in schema. bucket: "" prefix: "" s3: @@ -40,7 +40,7 @@ archive: # Optional booleans; defaults are true. enabled: true upload_run: true - # Optional promotions; defaults shown explicitly. + # Optional promotion rules; required files fail archive if missing. promote_artifacts: - from: transcripts/trimmed.json to: transcripts/trimmed.json @@ -48,6 +48,9 @@ archive: - from: artifacts/session_recap.md to: artifacts/session_recap.md required: true + - from: artifacts/player_handout.md + to: artifacts/player_handout.md + required: false whisperx: # Required. @@ -118,6 +121,7 @@ scriptorium: timeout: 10m render_debug: false artifacts: + # Configured artifact keys map to source IDs narratio.artifact.. session_recap: enabled: true prompt_id: dnd.session_recap @@ -140,6 +144,29 @@ scriptorium: previous_session_id: true output_kind: session_recap + # Example dependent artifact: + # - depends_on entries use artifact keys. + # - narratio.artifact. sources require matching depends_on membership. + player_handout: + enabled: true + depends_on: + - session_recap + prompt_id: dnd.player_handout + profile_id: local-fast + output_path: artifacts/player_handout.md + timeout: 10m + inputs: + recap: + source: narratio.artifact.session_recap + required: true + transcript: + source: narratio.transcript.trimmed + required: true + vars: + session_id: true + campaign_name: true + output_kind: player_handout + analyzer: # Optional adapter settings. binary_path: "" diff --git a/docs/examples/pipeline.production.yml b/docs/examples/pipeline.production.yml index be693e6..f48b82a 100644 --- a/docs/examples/pipeline.production.yml +++ b/docs/examples/pipeline.production.yml @@ -25,6 +25,9 @@ archive: - from: artifacts/session_recap.md to: artifacts/session_recap.md required: true + - from: artifacts/player_handout.md + to: artifacts/player_handout.md + required: false whisperx: transcribe_url: "https://transcription.example.com/transcribe" @@ -87,6 +90,24 @@ scriptorium: campaign_name: true previous_session_id: true output_kind: session_recap + player_handout: + enabled: true + depends_on: + - session_recap + prompt_id: dnd.player_handout + profile_id: local-fast + output_path: artifacts/player_handout.md + timeout: 10m + inputs: + recap: + source: narratio.artifact.session_recap + required: true + transcript: + source: narratio.transcript.trimmed + required: true + vars: + session_id: true + output_kind: player_handout analyzer: timeout: 2m diff --git a/docs/internal/README.md b/docs/internal/README.md index 46b23fe..dcbe04f 100644 --- a/docs/internal/README.md +++ b/docs/internal/README.md @@ -4,13 +4,13 @@ Developers and LLM coding agents changing Narratio internals. ## Scope -Implementation-accurate contracts for workspace/state, stages, and external adapter boundaries. +Implementation-accurate contracts for workspace/state, manifests, stages, artifact resolution, and adapter boundaries. ## Component Docs - `adapters.md`: external adapter map, runtime wiring, and boundary ownership. - `storage.md`: remote storage backend contracts and object-store invariants. - `manifest.md`: session/run manifest schemas, lifecycle transitions, and persistence semantics. -- `artifacts.md`: supported artifact IDs, transcript tiers, and source-resolution behavior. +- `artifacts.md`: built-in artifact registry, runtime artifact catalog, and source-resolution behavior. - `workspace.md`: local state model, manifests, run-local layout, promotion, and cleanup invariants. - `stage-prepare.md`: input materialization and provenance capture. - `stage-transcribe.md`: WhisperX transcript generation. @@ -18,7 +18,7 @@ Implementation-accurate contracts for workspace/state, stages, and external adap - `stage-polish.md`: Audita transcript polishing. - `stage-normalize.md`: post-polish normalization. - `stage-trim.md`: bounds-driven transcript trimming. -- `stage-analyze.md`: Scriptorium session recap generation. +- `stage-analyze.md`: dependency-ordered Scriptorium artifact generation for selected configured artifacts. - `stage-archive.md`: archive upload and current-pointer publish contract. ## External Integration Notes diff --git a/docs/internal/artifacts.md b/docs/internal/artifacts.md index bd8e3fd..1b4d518 100644 --- a/docs/internal/artifacts.md +++ b/docs/internal/artifacts.md @@ -1,39 +1,40 @@ # Internal: Artifacts ## Purpose -Describe supported session artifact IDs, transcript tiers, and artifact resolution/provenance behavior used by stage logic and Scriptorium input configuration. +Define Narratio's artifact identity and resolution model for built-in transcript/bounds artifacts and runtime-configured analyze artifacts. ## Inputs and outputs Inputs: -- Artifact source identifiers from stage config/runtime (for example `pipeline.scriptorium.artifacts.*.inputs.*.source`). -- Session paths and optional session manifest stage outputs. +- artifact sources from config/runtime (`pipeline.scriptorium.artifacts.*.inputs.*.source`) +- session paths and optional session manifest stage outputs +- runtime artifact catalog state for configured artifact sources Outputs: -- Resolved local artifact path + provenance (`ResolvedSessionArtifact`). -- Validation errors for unsupported or unreadable artifact sources. +- resolved local artifact path and provenance (`ResolvedSessionArtifact`) +- runtime catalog entries for planned/executable/available artifacts +- validation errors for unsupported, missing, or invalid artifact sources ## Boundaries Owns: -- Canonical artifact ID registry and metadata (`internal/artifacts/artifact_resolver.go`). -- Alias normalization for legacy source names. -- Resolution order and artifact content validation. +- built-in artifact registry and content validation rules +- runtime artifact catalog for configured artifact source IDs +- source resolution behavior for built-in and configured artifact sources Does not own: -- Artifact generation (stages produce files). -- Manifest transition policy. -- Remote archive publishing behavior. +- artifact generation (stages produce files) +- manifest transition policy +- archive promotion behavior ## Config fields used -Artifact source usage is driven by: +- `pipeline.scriptorium.artifacts..enabled` +- `pipeline.scriptorium.artifacts..output_path` - `pipeline.scriptorium.artifacts..inputs..source` -- Optional source-specific fields for previous artifact input (`artifact`, `path`, `required`). ## External adapters used -- No external service adapters. -- Resolver relies on local filesystem checks + session manifest state. +- none ## State and manifest behavior -Supported canonical IDs and current mappings: +Built-in registry entries: | Artifact ID | Canonical file | Producer stage | Output kind | | --- | --- | --- | --- | @@ -42,39 +43,45 @@ Supported canonical IDs and current mappings: | `narratio.transcript.full` | `transcripts/normalized.json` | `normalize` | `transcript_normalized` | | `narratio.transcript.trimmed` | `transcripts/trimmed.json` | `trim` | `transcript_trimmed` | | `narratio.bounds.session` | `artifacts/session_bounds.json` | `trim` | `session_bounds` | -| `narratio.artifact.session_recap` | `artifacts/session_recap.md` | `analyze` | `session_recap` | -Resolution order: -1. Session manifest producer-stage outputs (if readable/valid). -2. Canonical session path fallback. +Runtime catalog entries include built-ins and configured `narratio.artifact.` sources. -Provenance fields: -- `ProducerStage` -- `OutputKind` -- `ProducerRunID` (when resolved from manifest output) -- `Provenance` (`manifest..outputs` or `fallback.canonical_path`) +Catalog states: +- `planned`: source is registered and known for this run +- `executable`: configured artifact is selected for analyze execution +- `available`: artifact has a usable file path (generated this run or reused from disk) -Content validation by artifact type: -- Transcript artifacts: JSON with top-level `segments` array. -- `narratio.bounds.session`: valid JSON. -- `narratio.artifact.session_recap`: non-empty text. +Resolution behavior: +- built-in sources resolve via manifest producer outputs first, then canonical fallback path +- configured `narratio.artifact.` sources resolve through runtime catalog availability +- configured source lookup requires catalog context + +Configured artifact provenance values: +- `generated.current_analyze_run` +- `filesystem.disabled_artifact_output` + +Content validation: +- transcript built-ins: JSON with top-level `segments` array +- bounds built-in: valid JSON +- configured artifacts: non-empty text file ## Skip and resume behavior -- Resolver has no direct skip/resume logic. -- Resolver output influences stage behavior (for example analyze input resolution and required-input failures). +- resolver and catalog have no direct skip/resume decisions +- stage/runner skip-resume behavior consumes catalog/resolver results ## Failure behavior -- Unsupported or empty artifact source -> normalization error. -- Known source not found/readable -> `ErrSessionArtifactNotFound` wrapped error. -- Found but invalid content -> validation error. +- unsupported source -> source validation error +- known source unavailable -> `ErrSessionArtifactNotFound` +- configured source without catalog -> resolution error +- resolved file with invalid content -> validation error ## Tests to inspect before changing - `internal/artifacts/artifact_resolver_test.go` -- `internal/artifacts/resolve_test.go` +- `internal/artifacts/catalog_test.go` - `internal/stage/analyze_test.go` - `internal/config/scriptorium_test.go` ## Architectural invariants -- Artifact IDs are canonical interface values for stage/config integration. -- Alias support is compatibility behavior layered on top of canonical IDs. -- Manifest producer outputs are preferred over canonical fallback when both exist. +- built-in IDs are static and registry-backed +- configured artifact IDs are runtime-derived (`narratio.artifact.`) and catalog-backed +- built-in/source resolution remains deterministic and validation-gated diff --git a/docs/internal/manifest.md b/docs/internal/manifest.md index 39261c2..341bb2e 100644 --- a/docs/internal/manifest.md +++ b/docs/internal/manifest.md @@ -55,6 +55,7 @@ Relationship during execution: - Runner updates both manifests for every stage transition. - Session manifest is the durable pipeline-progress ledger. - Run manifest is invocation history and audit record. +- Analyze stage outputs are persisted as `kind=scriptorium_artifact` with `source_id=narratio.artifact.` for configured artifact identity. ## Skip and resume behavior - Resume and skip decisions are based on session-manifest stage statuses. diff --git a/docs/internal/stage-analyze.md b/docs/internal/stage-analyze.md index bbfa73f..11fd9d5 100644 --- a/docs/internal/stage-analyze.md +++ b/docs/internal/stage-analyze.md @@ -1,25 +1,31 @@ # Stage: analyze ## Purpose -Generate the session recap artifact using configured Scriptorium artifact settings. +Execute selected configured Scriptorium artifacts in deterministic dependency order and promote successful outputs to canonical session artifact paths. ## Inputs and Outputs Inputs: -- transcript inputs as requested by selected artifact config (processed/normalized/trimmed/current recap, depending on `pipeline.scriptorium.artifacts.session_recap.inputs`) +- configured artifact definitions from `pipeline.scriptorium.artifacts` +- selected artifact filter from runtime (`--artifacts`) when provided +- resolved artifact input sources declared per artifact (`inputs.*.source`) +- optional previous-session file inputs (`previous_session_artifact`) Outputs: -- `artifacts/session_recap.md` +- one promoted output file per executed configured artifact at that artifact's configured `output_path` +- stage metadata containing generated artifact entries and reused disabled-artifact entries ## Boundaries Owns: -- Selecting supported analyze artifact (`session_recap` only) -- Resolving transcript/reference inputs and vars -- Optional render-debug execution before run -- Main Scriptorium run and output promotion +- runtime artifact catalog construction for analyze execution +- selected-artifact planning and dependency ordering +- per-artifact input resolution, var resolution, timeout/render-debug resolution +- Scriptorium run/render invocation for each selected artifact +- run-local output generation and canonical promotion Does not own: -- Transcript processing pipeline stages -- Archive publish/pointer behavior +- transcript generation/processing stages +- archive promotion policy +- per-artifact resume semantics ## Config Fields Used - `session.session_id` @@ -29,8 +35,9 @@ Does not own: - `pipeline.scriptorium.config_path` - `pipeline.scriptorium.timeout` - `pipeline.scriptorium.render_debug` -- `pipeline.scriptorium.artifacts.session_recap.*` +- `pipeline.scriptorium.artifacts..*` - `enabled` + - `depends_on` - `prompt_id` - `profile_id` - `timeout` @@ -41,29 +48,37 @@ Does not own: ## External Adapters Used - Scriptorium adapter: - - optional `RenderArtifact` (debug diagnostics) - - `RunArtifact` (actual recap generation) + - optional `RenderArtifact` (render debug) + - `RunArtifact` (artifact generation) ## State and Manifest Behavior -- If `pipeline.scriptorium` is nil, stage returns success metadata with `skipped=true`. -- If no enabled artifacts exist, stage returns success metadata with `skipped=true`. -- If enabled artifacts exist but any artifact other than `session_recap` is enabled, stage fails. -- Uses run-local output/log/config/reports paths when run layout is enabled. -- Promotes canonical recap output and records adapter metadata. +- If `pipeline.scriptorium` is absent, stage returns success metadata with `skipped=true`. +- If no artifacts are configured, stage returns success metadata with `skipped=true`. +- If zero artifacts are executable after `enabled` + `--artifacts` filtering, stage returns success metadata with `skipped=true`. +- Builds runtime catalog with built-ins and configured artifacts. +- Non-executable configured artifacts are marked available only when their configured output file exists and is valid on disk. +- Executes selected configured artifacts in topological order with deterministic tie-breaking. +- For each generated artifact, records metadata fields including `name`, `source_id`, `output_kind`, `path`, `prompt_id`, `profile_id`, and `provenance`. +- Reused disabled artifacts are recorded separately in `reused_artifacts` with provenance `filesystem.disabled_artifact_output`. ## Skip and Resume Behavior -- Runner-level skip applies when already succeeded and not forced. -- Forced reruns can stale downstream succeeded stages. -- Stage-local "skipped" metadata is distinct from runner-level stage status skip. +- Runner-level skip applies when analyze is already `succeeded` and `--force` is not set. +- Analyze remains stage-scoped for resume/skip; there is no per-artifact resume state. +- `--artifacts` filters which configured artifacts are executable when analyze runs; it does not imply `--force`. ## Failure Behavior -- Fails on missing required resolved inputs, invalid transcript inputs, render/run adapter failures, or validation-failed run results. +- Fails on invalid dependency ordering, unavailable required configured inputs, invalid built-in input prerequisites, render/run adapter failures, validation-failed adapter results, or missing/empty outputs. +- Required configured dependency missing from catalog availability fails clearly before invocation. +- Optional missing inputs are omitted. ## Tests to Inspect Before Changing - `internal/stage/analyze_test.go` +- `internal/artifacts/catalog_test.go` +- `internal/artifacts/artifact_resolver_test.go` - `internal/adapters/scriptorium/subprocess_test.go` ## Architectural Invariants -- Analyze implementation supports only `artifacts.session_recap` as executable artifact. -- Optional inputs may be omitted; required inputs must resolve. -- Successful output must exist and be non-empty before promotion. +- Configured artifacts are identified by `narratio.artifact.` source IDs. +- Artifact-to-artifact references rely on explicit `depends_on` declarations validated in config. +- Generated analyze outputs are treated uniformly as Scriptorium artifacts. +- Successful outputs must exist and be non-empty before promotion. diff --git a/docs/operations.md b/docs/operations.md index 3a9b9fc..e0c75ca 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -6,8 +6,7 @@ For field-level configuration, see [docs/config.md](./config.md). For full comma ## Normal workflow (S3-first path) -1. Upload session `.flac` files to the session audio prefix in object storage: - - `{root_prefix}/campaigns/{campaign}/sessions/{session_id}/{audio_s3.prefix}` +1. Upload session `.flac` files to object storage under the session audio prefix. 2. Run Narratio: ```bash @@ -15,28 +14,24 @@ narratio run --session-id 2026-04-04 ``` 3. Read success output: - - `narratio run: session ; executed= skipped=; manifest=` - - `manifest=` is the local session manifest path to use with `status`. +- `narratio run: session ; executed= skipped=; manifest=` +- use `manifest=` with `status` for inspection. Notes: - -- This command relies on discoverable `pipeline.yml` and `session.yml` unless `--config` and `--session` are passed explicitly. -- For S3 audio input, `session.inputs.audio_s3.prefix` must be configured and audio files must already exist remotely. +- default config/session discovery applies unless `--config` and `--session` are passed. +- S3 audio mode requires `session.inputs.audio_s3.prefix` and valid object-store access. ## Local filesystem layout and state artifacts Session root: - - `{workspace.root}/work/{campaign}/{session_id}/` Primary state: - -- `manifest.json`: session-level manifest (authoritative local stage state). -- `runs/{run_id}/manifest.json`: run-level manifest for one invocation. -- `.lock`: session lock file while a run is active. +- `manifest.json`: session-level stage state. +- `runs/{run_id}/manifest.json`: invocation-level state. +- `.lock`: session lock while a run is active. Canonical session directories: - - `inputs/` - `audio/` - `transcripts/` @@ -48,123 +43,107 @@ Canonical session directories: - `runs/` Run-local stage directories: +- `runs/{run_id}/{stage}/` with stage-local `outputs/`, `logs/`, `reports/`, `config/`, `scratch/`. -- `runs/{run_id}/{stage}/` -- Stage runtime files are written under deterministic run-local subdirectories such as: - - `outputs/`, `logs/`, `reports/`, `config/`, `scratch/` +Behavior: +- directory creation is idempotent. +- stage outputs are generally generated run-local first, then promoted to canonical paths on success. -Behavior notes: +## Analyze artifact execution lifecycle -- Layout creation is idempotent. -- Durable outputs are promoted to canonical session paths after stage success. -- Run-local artifacts remain in `runs/{run_id}/...` unless configured post-archive cleanup removes that run scope. +Analyze executes configured artifacts from `pipeline.scriptorium.artifacts`. + +Execution model: +- executable set = enabled artifacts, filtered by `--artifacts` when provided. +- artifact-to-artifact dependencies are declared via `depends_on`. +- selected artifacts run in deterministic dependency order. +- after each successful artifact run, output is promoted to configured canonical `output_path`. + +Configured artifact source reuse: +- a non-executable configured artifact can satisfy inputs if its configured output file already exists and is valid. +- reused configured artifact provenance is `filesystem.disabled_artifact_output`. + +`--artifacts` behavior: +- accepted on `run`, `resume`, and `run-stage analyze`. +- filters analyze execution only; does not force stage rerun. ## Remote archive layout and publish contract -When archive is enabled and run upload is enabled, archive publishes to object storage under: +When archive is enabled and run upload is enabled, archive publishes under: -- Session prefix: `{root_prefix}/campaigns/{campaign}/sessions/{session_id}/` -- Run prefix: `{session_prefix}/runs/{run_id}/` +- session prefix: `{root_prefix}/campaigns/{campaign}/sessions/{session_id}/` +- run prefix: `{session_prefix}/runs/{run_id}/` Archive uploads: +- run record files from run root (excluding `audio/`). +- promoted files from explicit `archive.promote_artifacts` rules. -- Run record files from run root (including stage subtrees and run manifest), excluding local `audio/`. -- Promoted artifacts from `archive.promote_artifacts` to session-level keys. +Publish order: +1. upload `current/manifest.json` +2. upload `current/run_id.txt` last -Publish order (commit contract): +`current/run_id.txt` is the remote commit marker. -1. Upload `current/manifest.json` -2. Upload `current/run_id.txt` last - -Meaning of `current/run_id.txt`: - -- It is the effective remote commit marker for published session state. -- It is written only after required run uploads and required promotions succeed. +Archive promotion is explicit and path-based: +- Narratio does not auto-promote all generated analyze artifacts. +- missing required promotion sources fail archive stage. +- missing optional promotion sources are skipped. ## Resume, retry, and safe rerun behavior -Default skip behavior: +Default skip: +- `run` and `run-stage` skip already-succeeded stages unless `--force` is set. -- `run` and `run-stage` skip stages already marked `succeeded` unless `--force` is set. +Resume: +- `resume` starts at first non-succeeded stage. +- `resume --force` runs full stage order. -Resume behavior: +Forced reruns: +- force-rerunning an upstream succeeded stage marks downstream succeeded stages as `stale`. -- `resume` starts at the first non-`succeeded` stage in canonical stage order. -- If all stages are `succeeded`, `resume` prints that no stages remain. -- `resume --force` runs full stage order rather than starting at first non-succeeded. - -Forced rerun behavior: - -- Successful forced rerun of an upstream stage marks downstream previously `succeeded` stages as `stale`. -- `stale` stages are not treated as complete and are eligible to run in subsequent commands. - -Targeted rerun with one stage: - -```bash -narratio run-stage --force -``` - -Valid stage names: - -- `prepare`, `transcribe`, `merge`, `polish`, `normalize`, `trim`, `analyze`, `archive`, `notify` - -Safe operator pattern: - -1. Force-rerun the stage that changed. -2. Run `resume` to rebuild downstream stages in order. +Safe rerun pattern: +1. rerun the changed stage with `--force`. +2. run `resume` to rebuild downstream stages. ## Cleanup behavior -Cleanup is considered only after run execution completes and only when archive stage both executed and succeeded. +Cleanup is considered only when archive stage executed and succeeded. -Configured cleanup toggles: +Cleanup toggles: +- `pipeline.spool.delete_audio_after_archive=true` deletes run-scoped spool audio. +- `pipeline.workspace.cleanup_after_archive=true` deletes run-scoped local run directory. -- `pipeline.spool.delete_audio_after_archive=true` - - deletes only run-scoped spool audio directory: `{spool.root}/{campaign}/{session_id}/{run_id}/audio/` -- `pipeline.workspace.cleanup_after_archive=true` - - deletes only run-scoped local run directory: `{workspace.root}/work/{campaign}/{session_id}/runs/{run_id}/` +Cleanup eligibility gates: +- archive enabled +- archive run upload enabled +- run record upload completed +- current pointer write completed (`current/run_id.txt` written) -Eligibility gates for cleanup: - -- archive is enabled -- archive run upload is enabled -- archive metadata indicates run record upload happened -- archive metadata indicates `current` pointer write completed (`current/run_id.txt` written) - -Cleanup does not run for: - -- failed runs -- incomplete runs -- unarchived runs -- archive-skipped runs (`archive.enabled=false` or `archive.upload_run=false`) +No cleanup for failed/incomplete/unarchived/archive-skipped runs. ## Failure and recovery playbooks -What remains after failure: +After failure, Narratio keeps: +- session manifest +- run manifest +- run-local artifacts/logs/config/reports -- Session manifest remains on disk. -- Run manifest remains under `runs/{run_id}/manifest.json`. -- Run-local stage artifacts/logs/config/reports remain under `runs/{run_id}/...`. -- Failed/incomplete runs remain local-only. -- Remote current pointer is not committed if archive prerequisite or pointer-write steps fail. +Failed or incomplete runs remain local-only. -Recommended recovery flow: +Recommended recovery: -1. Inspect current state: +1. inspect state: ```bash -narratio status --manifest +narratio status --manifest ``` -2. Fix the root cause (config, input, credentials, adapter availability, etc.). -3. Continue with: - - `narratio resume --session-id ` for ordered continuation, or - - `narratio run-stage --force ` for targeted correction, then `resume`. +2. fix root cause (config/input/credentials/service availability). +3. continue with `resume`, or targeted `run-stage --force` followed by `resume`. ## Operational caveats -- `status` requires an explicit manifest path; there is no direct session-id lookup command. -- S3 audio mode and local audio mode are mutually exclusive in session config. -- Archive verifies stage prerequisites (`prepare` through `analyze`) before publishing. -- By default, archive does not upload local `audio/` into run history. -- Unknown CLI commands fail and print usage. +- `status` requires explicit `--manifest`; there is no session-id lookup command. +- local and S3 audio input modes are mutually exclusive. +- archive publish requires upstream stages through `analyze` to be `succeeded`. +- required promotion rules can fail when selected analyze artifacts did not generate a required file path. diff --git a/docs/roadmap/runtime-artifacts.md b/docs/roadmap/runtime-artifacts.md index 21905bd..1f8a1fc 100644 --- a/docs/roadmap/runtime-artifacts.md +++ b/docs/roadmap/runtime-artifacts.md @@ -663,6 +663,8 @@ Tests: ### Phase 8: Documentation and Examples +Status: complete. + Update documentation after the implementation is complete. Recommended documentation changes: diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 2c8d14d..a6cf4b7 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -6,11 +6,11 @@ Canonical operator troubleshooting guide for recurring implemented Narratio fail ## Config file discovery failure Symptom: -- `run`, `plan`, `resume`, or `run-stage` fails saying config/session file was not found. +- `run`, `plan`, `resume`, or `run-stage` fails with config/session not found. Likely Cause: -- `pipeline.yml` or `session.yml` is missing from default search paths. -- Wrong working directory when relying on `./session.yml`. +- `pipeline.yml` or `session.yml` is missing from discovery paths. +- wrong working directory when relying on `./session.yml`. Diagnostics: @@ -21,8 +21,8 @@ ls -l /usr/local/etc/narratio/pipeline.yml /etc/narratio/pipeline.yml ``` Safe Fix: -- Pass explicit paths with `--config` and `--session`. -- Or place files in documented discovery paths. +- pass explicit `--config` and `--session`. +- or place files in documented discovery paths. Links: - [docs/config.md](./config.md) @@ -31,11 +31,11 @@ Links: ## Session template rendering failure Symptom: -- Load fails with unresolved template placeholder or `session_id` mismatch. +- load fails with unresolved placeholder or `session_id` mismatch. Likely Cause: -- `session.yml` contains `{{session_id}}`/`{{ session_id }}` but `--session-id` was omitted. -- Provided `--session-id` does not match rendered `session_id`. +- templated `session.yml` used without `--session-id`. +- rendered `session_id` differs from passed `--session-id`. Diagnostics: @@ -44,8 +44,8 @@ narratio plan --session ./session.yml --session-id 2026-04-04 ``` Safe Fix: -- Always pass `--session-id` when using template placeholders. -- Ensure rendered `session_id` equals intended run session id. +- pass `--session-id` when template placeholders are present. +- ensure rendered `session_id` matches intended run session id. Links: - [docs/config.md](./config.md) @@ -53,12 +53,11 @@ Links: ## Strict YAML decode or validation failure Symptom: -- Config load fails with unknown field, missing required field, invalid duration, or invalid cross-field constraint. +- config load fails with unknown field or validation error. Likely Cause: -- YAML key typo or stale field name. -- Required fields missing. -- Invalid value format (for example duration/URL/env var name). +- typo/stale field name. +- missing required fields or invalid constraints. Diagnostics: @@ -67,22 +66,114 @@ narratio plan --config /path/to/pipeline.yml --session /path/to/session.yml --se ``` Safe Fix: -- Correct fields/values to match canonical reference and examples. -- Validate against `docs/examples/` shapes. +- align fields/values to canonical config reference and examples. Links: - [docs/config.md](./config.md) - [docs/examples/](./examples/) +## `--artifacts` selection failure + +Symptom: +- `run`/`resume`/`run-stage` fails with invalid or unknown artifact selection. + +Likely Cause: +- `--artifacts` contains blank names or unknown artifact keys. +- `pipeline.scriptorium.artifacts` missing while using `--artifacts`. + +Diagnostics: + +```bash +narratio run --config /path/to/pipeline.yml --session /path/to/session.yml --session-id 2026-04-04 --artifacts player_handout +``` + +Safe Fix: +- use configured artifact keys only. +- ensure `pipeline.scriptorium.artifacts` is defined. + +Links: +- [docs/cli.md](./cli.md) +- [docs/config.md](./config.md) + +## `run-stage --artifacts` on non-analyze stage + +Symptom: +- `run-stage` fails with `--artifacts is only supported for stage "analyze"`. + +Likely Cause: +- `--artifacts` was used with a non-`analyze` stage. + +Diagnostics: + +```bash +narratio run-stage --config /path/to/pipeline.yml --session /path/to/session.yml --session-id 2026-04-04 --artifacts session_recap polish +``` + +Safe Fix: +- use `--artifacts` only with `run-stage ... analyze`. + +Links: +- [docs/cli.md](./cli.md) + +## Configured artifact dependency/input validation failure + +Symptom: +- config validation fails for `depends_on`, `narratio.artifact.` source, or artifact output path. + +Likely Cause: +- `narratio.artifact.` source missing matching `depends_on` key. +- dependency references unknown artifact key. +- dependency self-reference or enabled dependency cycle. +- artifact output path missing/invalid/outside `artifacts/` root. + +Diagnostics: + +```bash +narratio plan --config /path/to/pipeline.yml --session /path/to/session.yml --session-id 2026-04-04 +``` + +Safe Fix: +- ensure artifact-to-artifact inputs have explicit `depends_on` entries using artifact keys. +- ensure referenced artifacts exist and define valid `output_path` values. +- keep output paths relative and under `artifacts/`. + +Links: +- [docs/config.md](./config.md) +- [docs/internal/stage-analyze.md](./internal/stage-analyze.md) + +## Required configured artifact input unavailable at analyze time + +Symptom: +- analyze fails because configured input source is unavailable. + +Likely Cause: +- required upstream configured artifact was not selected/executed this run. +- non-executable dependency output file is missing or invalid on disk. + +Diagnostics: + +```bash +narratio status --manifest /path/to/manifest.json +narratio run-stage --config /path/to/pipeline.yml --session /path/to/session.yml --session-id 2026-04-04 --artifacts player_handout analyze +``` + +Safe Fix: +- run analyze with needed artifacts selected. +- or ensure dependency output file exists at configured path and is valid. + +Links: +- [docs/operations.md](./operations.md) +- [docs/config.md](./config.md) + ## Manifest/status path failure Symptom: - `status` fails because manifest path is missing, unreadable, or invalid. Likely Cause: -- Wrong manifest path. -- Manifest removed after cleanup. -- Trying to run `status` without `--manifest`. +- wrong manifest path. +- manifest removed after cleanup. +- `--manifest` omitted. Diagnostics: @@ -92,8 +183,7 @@ ls -l /path/to/manifest.json ``` Safe Fix: -- Use manifest path printed by `run`, `resume`, or `run-stage` output. -- Re-run with correct session/config if inspecting a different session. +- use manifest path printed by `run`, `resume`, or `run-stage`. Links: - [docs/cli.md](./cli.md) @@ -102,11 +192,11 @@ Links: ## Session lock conflict (`.lock`) Symptom: -- Run fails with lock conflict indicating session workdir is already locked. +- run fails with lock conflict for session workdir. Likely Cause: -- Another Narratio process is actively running the same session. -- Prior run exited unexpectedly and left a stale lock file. +- another Narratio process is running same session. +- stale lock from interrupted prior run. Diagnostics: @@ -117,21 +207,21 @@ ps aux | grep narratio ``` Safe Fix: -- If another run is active, wait for it to finish. -- If no process is active and lock is stale, remove only that session `.lock` file and retry. +- wait for active run to finish. +- if no process is active, remove only stale session `.lock` file. Links: - [docs/operations.md](./operations.md) - [docs/internal/workspace.md](./internal/workspace.md) -## Secrets env-dir or credential env failure +## Secrets env-dir or credential-env failure Symptom: -- Startup fails loading secrets directory, or a stage fails because required credential env var is missing. +- startup fails loading secrets directory, or stage fails due to missing credential env vars. Likely Cause: -- `pipeline.secrets.env_dir` path is wrong/unreadable. -- Credential env var referenced in config is unset or empty. +- invalid `pipeline.secrets.env_dir` path/permissions. +- required credential env var unset/empty. Diagnostics: @@ -141,24 +231,22 @@ env | grep -E 'AUDITA|OBJECT_STORAGE|AWS|SCRIPTORIUM' ``` Safe Fix: -- Fix `pipeline.secrets.env_dir` path/permissions. -- Ensure required env vars are set to non-empty values. -- Keep secrets out of YAML; use env references only. +- fix secrets directory and credential env vars. +- keep secret values out of YAML. Links: - [docs/config.md](./config.md) -- [docs/operations.md](./operations.md) ## S3-audio prepare failure Symptom: -- `prepare` fails in S3 mode (no audio found, list/download failure, backend missing, path conflict). +- `prepare` fails in S3 mode (listing/downloading/no audio/backend error). Likely Cause: -- Wrong `session.inputs.audio_s3.prefix`. -- No `.flac` files at expected prefix. -- Missing or invalid S3 backend credentials/config. -- Conflicting audio-source settings (`audio_s3` plus local audio fields). +- wrong `session.inputs.audio_s3.prefix`. +- no `.flac` files at resolved prefix. +- invalid/missing object-store credentials or backend config. +- mixed local+S3 audio input config. Diagnostics: @@ -167,24 +255,21 @@ narratio run-stage --config /path/to/pipeline.yml --session /path/to/session.yml ``` Safe Fix: -- Ensure `audio_s3` is the only audio source configured for that session. -- Confirm `.flac` objects exist under the resolved session audio prefix. -- Fix S3 storage configuration and credentials. +- configure exactly one audio source mode. +- verify `.flac` files and storage access. Links: - [docs/config.md](./config.md) - [docs/operations.md](./operations.md) -- [docs/internal/stage-prepare.md](./internal/stage-prepare.md) -## Archive prerequisite or promotion/current-pointer failure +## Archive promotion/current-pointer failure Symptom: -- `archive` fails due to prerequisite stage status, missing required promotion source, or pointer write failure. +- archive fails on required promotion source missing or pointer write failure. Likely Cause: -- One or more prerequisite stages are not `succeeded`. -- Required promoted artifact does not exist. -- Remote upload failure before `current/run_id.txt` write. +- required promoted file absent (including analyze outputs not generated for this run). +- storage upload failed before `current/run_id.txt` commit marker write. Diagnostics: @@ -194,36 +279,11 @@ narratio run-stage --config /path/to/pipeline.yml --session /path/to/session.yml ``` Safe Fix: -- Resume or rerun failed upstream stage(s). -- Ensure required promoted artifact paths exist locally before archive. -- Retry archive after storage/connectivity issue is resolved. +- rerun or resume upstream stages to generate required files. +- adjust promotion rules to match files that must exist. +- retry after storage issue is resolved. Links: - [docs/operations.md](./operations.md) - [docs/config.md](./config.md) - [docs/internal/stage-archive.md](./internal/stage-archive.md) - -## `run-stage` invalid stage name or invalid flags - -Symptom: -- `run-stage` fails with unknown stage or invalid flag/argument usage. - -Likely Cause: -- Stage name typo. -- Missing positional stage argument. -- Unsupported/incorrect flag syntax. - -Diagnostics: - -```bash -narratio run-stage --config /path/to/pipeline.yml --session /path/to/session.yml --session-id 2026-04-04 normalize -``` - -Safe Fix: -- Use only supported stage names. -- Provide exactly one positional stage argument. -- Align flags to documented command reference. - -Links: -- [docs/cli.md](./cli.md) -- [docs/operations.md](./operations.md)