CLI cleanup to consolidate session-related subcommands
This commit is contained in:
638
docs/cli.md
638
docs/cli.md
@@ -3,10 +3,10 @@
|
||||
## Shortest Useful Command
|
||||
|
||||
```bash
|
||||
narratio run --session-id 2026-04-04
|
||||
narratio run 2026-04-04
|
||||
```
|
||||
|
||||
This command uses default system discovery for `pipeline.yml`, `campaign.yml`, and local `session.yml`. If local session discovery misses and S3 storage is configured, `--session-id` can load remote `session.yml` from the canonical session prefix.
|
||||
This command uses default system discovery for `pipeline.yml`, `campaign.yml`, and local `session.yml`. If local session discovery misses and S3 storage is configured, the positional session ID loads remote `session.yml` from the canonical session prefix.
|
||||
|
||||
Default discovery checks system config locations only. Pass `--config`, `--campaign`, and `--session` to use files from the current working directory.
|
||||
|
||||
@@ -14,89 +14,82 @@ Ordinary local and remote `session.yml` files must be concrete YAML. Templates b
|
||||
|
||||
## Command Overview
|
||||
|
||||
Implemented commands:
|
||||
Top-level commands:
|
||||
|
||||
- `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 an existing manifest or inspect local/remote state for a session.
|
||||
- `run-stage`: execute exactly one stage.
|
||||
- `analyze`: force-rerun the analyze stage.
|
||||
- `publish`: force-rerun the archive stage.
|
||||
- `restore`: restore durable local session state from the committed remote archive state.
|
||||
- `session validate`: run read-only preflight checks for a session.
|
||||
- `session init`: create local or remote `session.yml`.
|
||||
- `artifacts list`: list effective artifact source IDs.
|
||||
- `locks`: list, add, and remove archive promotion locks.
|
||||
- `clean`: remove local workspace/spool state for one session or all local sessions.
|
||||
- `run <session_id>`: execute pipeline stages and persist manifest state.
|
||||
- `run-stage <stage> <session_id>`: execute exactly one stage.
|
||||
- `resume <session_id>`: continue from first non-succeeded stage unless forced.
|
||||
- `analyze <session_id>`: force-rerun the analyze stage.
|
||||
- `publish <session_id>`: force-rerun the archive stage.
|
||||
- `clean <session_id>|--all`: remove local workspace/spool state.
|
||||
- `session <subcommand>`: session-scoped helper commands.
|
||||
|
||||
Session subcommands:
|
||||
|
||||
- `session init <session_id>`: create local or remote `session.yml`.
|
||||
- `session validate <session_id>`: run read-only preflight checks.
|
||||
- `session status <session_id>`: inspect local/remote session state.
|
||||
- `session plan <session_id>`: validate config, prepare workspace layout, and print stage run/skip decisions.
|
||||
- `session restore <session_id>`: restore durable local state from committed remote archive state.
|
||||
- `session artifacts <session_id>`: list effective artifact source IDs.
|
||||
- `session locks <session_id>`: list archive promotion locks.
|
||||
- `session locks add <session_id> <source>`: add or update a remote lock.
|
||||
- `session locks remove <session_id> <source>`: remove a remote lock.
|
||||
|
||||
Unknown commands print usage and exit non-zero.
|
||||
|
||||
For config semantics, see [docs/config.md](./config.md). For operator lifecycle and recovery, see [docs/operations.md](./operations.md).
|
||||
|
||||
## Complete Flag Reference
|
||||
## Common Flags
|
||||
|
||||
### `run`
|
||||
Most session-aware commands accept:
|
||||
|
||||
- `--config <path>`: optional explicit `pipeline.yml` path.
|
||||
- `--campaign <path>`: optional explicit `campaign.yml` path.
|
||||
- `--session <path>`: optional explicit `session.yml` path.
|
||||
- `--session-id <value>`: expected session identifier and remote session lookup value.
|
||||
- `--session <path>`: optional explicit concrete `session.yml` path.
|
||||
- `--previous-session-id <value>`: expected previous session identifier.
|
||||
- `--force`: force stage execution.
|
||||
- `--artifacts <names>`: configured artifact keys to execute and publish (repeatable or comma-separated).
|
||||
|
||||
### `plan`
|
||||
The positional `<session_id>` is required even when `--session` is provided. It is used as the expected session identity and as the remote session lookup value when local session discovery misses.
|
||||
|
||||
- `--config <path>`
|
||||
- `--campaign <path>`
|
||||
- `--session <path>`
|
||||
- `--session-id <value>`
|
||||
- `--previous-session-id <value>`
|
||||
- `--force`
|
||||
## Command Reference
|
||||
|
||||
### `run`
|
||||
|
||||
```bash
|
||||
narratio run <session_id> [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--previous-session-id <id>] [--force] [--artifacts <name[,name...]>]
|
||||
```
|
||||
|
||||
Purpose:
|
||||
- Execute configured stages in canonical order.
|
||||
|
||||
Success output:
|
||||
- `narratio run: session <session_id>; executed=<n> skipped=<n>; manifest=<path>`
|
||||
|
||||
Common failure cases:
|
||||
- missing system default config/campaign/session paths when flags are omitted.
|
||||
- missing local session plus missing/unavailable remote `session.yml`.
|
||||
- templated `session.yml`; run `narratio session init` to generate concrete YAML.
|
||||
- concrete session identity mismatch.
|
||||
- unknown configured artifact key in `--artifacts`.
|
||||
|
||||
### `resume`
|
||||
|
||||
- `--config <path>`
|
||||
- `--campaign <path>`
|
||||
- `--session <path>`
|
||||
- `--session-id <value>`
|
||||
- `--previous-session-id <value>`
|
||||
- `--force`
|
||||
- `--artifacts <names>`: configured artifact keys to execute and publish (repeatable or comma-separated).
|
||||
```bash
|
||||
narratio resume <session_id> [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--previous-session-id <id>] [--force] [--artifacts <name[,name...]>]
|
||||
```
|
||||
|
||||
Purpose:
|
||||
- Continue from session-manifest stage status.
|
||||
|
||||
Success output:
|
||||
- `narratio resume: session <session_id> has no remaining stages`
|
||||
- or `narratio resume: session <session_id>; executed=<n> skipped=<n>; manifest=<path>`
|
||||
|
||||
### `run-stage`
|
||||
|
||||
- `--config <path>`
|
||||
- `--campaign <path>`
|
||||
- `--session <path>`
|
||||
- `--session-id <value>`
|
||||
- `--previous-session-id <value>`
|
||||
- `--force`
|
||||
- `--artifacts <names>`: configured artifact keys to execute or publish (repeatable or comma-separated).
|
||||
- positional `<stage>`: required stage name.
|
||||
|
||||
### `analyze`
|
||||
|
||||
- `--config <path>`
|
||||
- `--campaign <path>`
|
||||
- `--session <path>`
|
||||
- `--session-id <value>`
|
||||
- `--previous-session-id <value>`
|
||||
- `--artifacts <names>`: configured artifact keys to execute (repeatable or comma-separated).
|
||||
|
||||
`analyze` is force-by-design and does not accept `--force`.
|
||||
|
||||
### `publish`
|
||||
|
||||
- `--config <path>`
|
||||
- `--campaign <path>`
|
||||
- `--session <path>`
|
||||
- `--session-id <value>`
|
||||
- `--previous-session-id <value>`
|
||||
- `--artifacts <names>`: configured artifact keys to publish (repeatable or comma-separated).
|
||||
|
||||
`publish` is force-by-design and does not accept `--force` or a stage positional argument.
|
||||
```bash
|
||||
narratio run-stage <stage> <session_id> [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--previous-session-id <id>] [--force] [--artifacts <name[,name...]>]
|
||||
```
|
||||
|
||||
Valid stage names:
|
||||
|
||||
@@ -110,378 +103,39 @@ Valid stage names:
|
||||
- `archive`
|
||||
- `notify`
|
||||
|
||||
### `restore`
|
||||
|
||||
- `--config <path>`
|
||||
- `--campaign <path>`
|
||||
- `--session <path>`
|
||||
- `--session-id <value>`
|
||||
- `--previous-session-id <value>`
|
||||
- `--dry-run`: plan restore actions without writing local files.
|
||||
- `--force`: overwrite local conflicting files with remote archive files.
|
||||
- `--include-audio`: include durable archived `audio/**` files in restore scope.
|
||||
|
||||
### `clean`
|
||||
|
||||
- `--session-id <value>`: required for session cleanup unless `--all` is set.
|
||||
- `--config <path>`
|
||||
- `--campaign <path>`
|
||||
- `--session <path>`
|
||||
- `--previous-session-id <value>`
|
||||
- `--all`: clean all local session work/spool state using pipeline config only.
|
||||
- `--dry-run`: print cleanup targets without deleting.
|
||||
- `--clear-cache`: also remove matching S3 audio cache entries.
|
||||
|
||||
### `status`
|
||||
|
||||
- `--manifest <path>`: inspect one manifest file.
|
||||
- `--config <path>`
|
||||
- `--campaign <path>`
|
||||
- `--session <path>`
|
||||
- `--session-id <value>`
|
||||
- `--previous-session-id <value>`
|
||||
|
||||
### `session validate`
|
||||
|
||||
- `--config <path>`
|
||||
- `--campaign <path>`
|
||||
- `--session <path>`
|
||||
- `--session-id <value>`
|
||||
- `--previous-session-id <value>`
|
||||
|
||||
### `session init`
|
||||
|
||||
- `--config <path>`: optional explicit `pipeline.yml` path.
|
||||
- `--campaign <path>`: optional explicit `campaign.yml` path.
|
||||
- `--session-id <value>`: required.
|
||||
- `--output <path>`: local `session.yml` target; mutually exclusive with `--remote`.
|
||||
- `--remote`: write remote `session.yml` to the canonical session prefix; mutually exclusive with `--output`.
|
||||
- `--previous-session-id <value>`
|
||||
- `--date <value>`
|
||||
- `--title <value>`
|
||||
- `--audio-s3-prefix <prefix>`: defaults to `audio/` when neither audio flag is provided.
|
||||
- `--audio-dir <path>`: local audio directory; mutually exclusive with `--audio-s3-prefix`.
|
||||
- `--force`: overwrite existing local or remote target.
|
||||
|
||||
When `campaign.yml` sets `session_template_file`, `session init` renders that template before writing the concrete session file. Template variables are supplied by these flags: `--session-id`, `--previous-session-id`, `--date`, `--title`, `--audio-s3-prefix`, and `--audio-dir`.
|
||||
|
||||
### `artifacts list`
|
||||
|
||||
- `--config <path>`
|
||||
- `--campaign <path>`
|
||||
- `--session <path>`
|
||||
- `--session-id <value>`
|
||||
- `--previous-session-id <value>`
|
||||
- `--remote`: check remote availability for configured archive promotion destinations.
|
||||
|
||||
### `locks`
|
||||
|
||||
- `--session-id <value>`: required for list, add, and remove.
|
||||
- `--config <path>`: optional explicit `pipeline.yml` path.
|
||||
- `--campaign <path>`: optional explicit `campaign.yml` path.
|
||||
- `--session <path>`: optional explicit `session.yml` path.
|
||||
- `--previous-session-id <value>`: optional expected previous session identifier.
|
||||
- `add <source>`: add a remote lock for one artifact or transcript source.
|
||||
- `add --reason <text>`: record an optional remote lock reason.
|
||||
- `add --force`: update the reason for an existing remote lock.
|
||||
- `remove <source>`: remove one remote lock.
|
||||
|
||||
## Command Reference
|
||||
|
||||
### `run`
|
||||
|
||||
Purpose:
|
||||
- Execute configured stages in canonical order.
|
||||
|
||||
Syntax:
|
||||
|
||||
```bash
|
||||
narratio run [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--session-id <id>] [--previous-session-id <id>] [--force] [--artifacts <name[,name...]>]
|
||||
```
|
||||
|
||||
Success output:
|
||||
- `narratio run: session <session_id>; executed=<n> skipped=<n>; manifest=<path>`
|
||||
|
||||
Common failure cases:
|
||||
- missing system default config/campaign/session paths when flags omitted.
|
||||
- missing local session plus missing/unavailable remote `session.yml`.
|
||||
- templated `session.yml`; run `narratio session init` to generate concrete YAML.
|
||||
- concrete session identity mismatch.
|
||||
- unknown/invalid `--artifacts` value.
|
||||
- `--artifacts` with unknown configured artifact key.
|
||||
|
||||
### `plan`
|
||||
|
||||
Purpose:
|
||||
- Validate config, load secrets (if configured), prepare workdir, and print stage run/skip decisions.
|
||||
|
||||
Syntax:
|
||||
|
||||
```bash
|
||||
narratio plan [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--session-id <id>] [--previous-session-id <id>] [--force]
|
||||
```
|
||||
|
||||
Success output includes:
|
||||
- `narratio plan: workdir prepared at <path>`
|
||||
- one line per stage (`<stage>: run|skip`)
|
||||
- `totals: run=<n> skip=<n>`
|
||||
|
||||
Common failure cases:
|
||||
- same config/campaign/session discovery and validation failures as `run`.
|
||||
- remote session fallback failures when local session discovery misses.
|
||||
- secrets directory read failures when `pipeline.secrets.env_dir` is configured.
|
||||
|
||||
### `resume`
|
||||
|
||||
Purpose:
|
||||
- Continue from session-manifest stage status.
|
||||
|
||||
Syntax:
|
||||
|
||||
```bash
|
||||
narratio resume [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--session-id <id>] [--previous-session-id <id>] [--force] [--artifacts <name[,name...]>]
|
||||
```
|
||||
|
||||
Success output:
|
||||
- `narratio resume: session <session_id> has no remaining stages`
|
||||
- or `narratio resume: session <session_id>; executed=<n> skipped=<n>; manifest=<path>`
|
||||
|
||||
Common failure cases:
|
||||
- same discovery and validation failures as `run`.
|
||||
- manifest load errors when existing manifest is unreadable.
|
||||
- invalid or unknown artifact selections.
|
||||
|
||||
### `status`
|
||||
|
||||
Purpose:
|
||||
- Inspect one manifest file, or inspect configured local/remote state for a session.
|
||||
|
||||
Syntax:
|
||||
|
||||
```bash
|
||||
narratio status --manifest <manifest.json>
|
||||
narratio status [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--session-id <id>] [--previous-session-id <id>]
|
||||
```
|
||||
|
||||
Manifest output includes:
|
||||
- `session_id: <id>`
|
||||
- `updated_at: <timestamp>`
|
||||
- `stages:` entries (`- <stage>: <status>`)
|
||||
|
||||
Session output includes:
|
||||
- session ID, campaign, workspace, session config source.
|
||||
- local manifest state when present.
|
||||
- remote current archive state when storage is configured.
|
||||
- catalog-based remote output availability for expected transcript and artifact sources.
|
||||
- effective archive locks and conservative next actions.
|
||||
|
||||
Common failure cases:
|
||||
- missing `--manifest` when no config/session flags are provided.
|
||||
- unreadable or invalid manifest path.
|
||||
- invalid config or remote session fallback failure in session mode.
|
||||
|
||||
### `session validate`
|
||||
|
||||
Purpose:
|
||||
- Run read-only preflight checks for a session.
|
||||
|
||||
Syntax:
|
||||
|
||||
```bash
|
||||
narratio session validate [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--session-id <id>] [--previous-session-id <id>]
|
||||
```
|
||||
|
||||
Checks include:
|
||||
- effective config and session source.
|
||||
- stable input files.
|
||||
- local or remote audio availability.
|
||||
- previous-session requirements.
|
||||
- archive promotions and effective locks.
|
||||
|
||||
Warnings do not fail the command. Any `ERROR` finding exits non-zero.
|
||||
|
||||
### `session init`
|
||||
|
||||
Purpose:
|
||||
- Create a strict-decoded concrete `session.yml` locally or in object storage.
|
||||
|
||||
Syntax:
|
||||
|
||||
```bash
|
||||
narratio session init --session-id <id> --output ./session.yml
|
||||
narratio session init --session-id <id> --remote
|
||||
narratio session init --config <pipeline.yml> --campaign <campaign.yml> --session-id <id> --remote
|
||||
```
|
||||
|
||||
Behavior:
|
||||
- exactly one of `--output` or `--remote` is required.
|
||||
- `--config` and `--campaign` are optional overrides; omitted values use normal default config discovery.
|
||||
- if `campaign.yml` sets `session_template_file`, the template path is resolved relative to `campaign.yml` and rendered from init flags.
|
||||
- if no session template is configured, a minimal concrete session file is generated directly.
|
||||
- template variables must be supplied by matching flags, and supplied template-related flags must be used by the template.
|
||||
- remote writes target `{root_prefix}/campaigns/{campaign}/sessions/{session_id}/session.yml`.
|
||||
- existing local or remote targets fail unless `--force` is passed.
|
||||
- remote writes use existence checks, not compare-and-swap.
|
||||
|
||||
### `artifacts list`
|
||||
|
||||
Purpose:
|
||||
- List built-in, configured, previous-session, promoted, and locked artifact sources.
|
||||
|
||||
Syntax:
|
||||
|
||||
```bash
|
||||
narratio artifacts list [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--session-id <id>] [--previous-session-id <id>] [--remote]
|
||||
```
|
||||
|
||||
`--remote` checks promoted top-level object availability through the storage adapter. Remote markers appear only in the `Promoted` section, which reports each configured archive promotion destination and includes `dest=<path>` when that destination differs from the source's canonical path.
|
||||
|
||||
### `locks`
|
||||
|
||||
Purpose:
|
||||
- Inspect and mutate source-based archive promotion locks for one session.
|
||||
|
||||
Syntax:
|
||||
|
||||
```bash
|
||||
narratio locks --session-id <id>
|
||||
narratio locks add --session-id <id> [--reason <text>] [--force] <source>
|
||||
narratio locks remove --session-id <id> <source>
|
||||
```
|
||||
|
||||
Behavior:
|
||||
- `--session-id` is required for list, add, and remove.
|
||||
- optional `--config`, `--campaign`, and `--session` override default config discovery.
|
||||
- list mode prints effective locks from static `pipeline.archive.locks` and remote `{session_prefix}/locks.yml`.
|
||||
- `locks add` writes only the remote lock store and fails if the source is already locked by pipeline config.
|
||||
- `locks remove` removes only remote locks and cannot remove static pipeline locks.
|
||||
- `locks add --force` is required to update an existing remote lock reason.
|
||||
|
||||
Examples:
|
||||
|
||||
```bash
|
||||
narratio locks --session-id 2026-04-04
|
||||
narratio locks add --session-id 2026-04-04 --reason "manual transcript review" narratio.transcript.final_trimmed
|
||||
narratio locks remove --session-id 2026-04-04 narratio.transcript.final_trimmed
|
||||
```
|
||||
|
||||
### `run-stage`
|
||||
|
||||
Purpose:
|
||||
- Execute exactly one stage.
|
||||
|
||||
Syntax:
|
||||
|
||||
```bash
|
||||
narratio run-stage [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--session-id <id>] [--previous-session-id <id>] [--force] [--artifacts <name[,name...]>] <stage>
|
||||
```
|
||||
|
||||
Success output:
|
||||
- `narratio run-stage: stage=<name> executed=<n> skipped=<n> force=<true|false>; manifest=<path>`
|
||||
|
||||
`--artifacts` behavior:
|
||||
- accepted only when `<stage>` is `analyze` or `archive`.
|
||||
- names are normalized (trimmed, deduplicated, sorted).
|
||||
- unknown configured artifact keys fail.
|
||||
- for `archive`, unselected configured artifact promotions are skipped; built-in transcript and bounds promotions still run.
|
||||
|
||||
Common failure cases:
|
||||
- missing stage positional arg.
|
||||
- unknown stage name.
|
||||
- using `--artifacts` with any stage other than `analyze` or `archive`.
|
||||
`--artifacts` is accepted only for `analyze` and `archive`.
|
||||
|
||||
### `analyze`
|
||||
|
||||
Purpose:
|
||||
- Force-rerun the analyze stage.
|
||||
- Provide a shorter equivalent for `narratio run-stage --force analyze`.
|
||||
|
||||
Syntax:
|
||||
|
||||
```bash
|
||||
narratio analyze [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--session-id <id>] [--previous-session-id <id>] [--artifacts <name[,name...]>]
|
||||
narratio analyze <session_id> [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--previous-session-id <id>] [--artifacts <name[,name...]>]
|
||||
```
|
||||
|
||||
Success output:
|
||||
- `narratio analyze: executed=<n> skipped=<n> force=true; manifest=<path>`
|
||||
Purpose:
|
||||
- Force-rerun the analyze stage.
|
||||
- Shorter equivalent for `narratio run-stage analyze <session_id> --force`.
|
||||
|
||||
Common failure cases:
|
||||
- positional arguments.
|
||||
- `--force`, because force is implicit.
|
||||
- unknown configured artifact keys.
|
||||
`analyze` is force-by-design and does not accept `--force`.
|
||||
|
||||
### `publish`
|
||||
|
||||
```bash
|
||||
narratio publish <session_id> [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--previous-session-id <id>] [--artifacts <name[,name...]>]
|
||||
```
|
||||
|
||||
Purpose:
|
||||
- Force-rerun the archive stage.
|
||||
- Provide a shorter equivalent for `narratio run-stage --force archive`.
|
||||
- Shorter equivalent for `narratio run-stage archive <session_id> --force`.
|
||||
|
||||
Syntax:
|
||||
|
||||
```bash
|
||||
narratio publish [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--session-id <id>] [--previous-session-id <id>] [--artifacts <name[,name...]>]
|
||||
```
|
||||
|
||||
Success output:
|
||||
- `narratio publish: executed=<n> skipped=<n> force=true; manifest=<path>`
|
||||
|
||||
Common failure cases:
|
||||
- positional arguments.
|
||||
- `--force`, because force is implicit.
|
||||
- unknown configured artifact keys.
|
||||
- archive-stage failures such as missing required promotion sources or locked storage errors.
|
||||
|
||||
### `restore`
|
||||
|
||||
Purpose:
|
||||
- Restore durable session state from the committed remote archive current state.
|
||||
- Default restore installs `manifest.json`, `transcripts/**`, and `artifacts/**` from the current session archive.
|
||||
- When configured previous-session inputs require it, restore reconstructs `previous/**` from the previous session's committed current archive, matching what `prepare` would hydrate.
|
||||
- `audio/**` is restored only with `--include-audio`.
|
||||
|
||||
Syntax:
|
||||
|
||||
```bash
|
||||
narratio restore [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--session-id <id>] [--previous-session-id <id>] [--dry-run] [--force] [--include-audio]
|
||||
```
|
||||
|
||||
Success output (dry-run):
|
||||
- `Restore plan for <campaign>/<session_id>`
|
||||
- `Remote run: <run_id>`
|
||||
- `Would download: <n>`
|
||||
- `Would skip unchanged: <n>`
|
||||
- `Conflicts: <n>`
|
||||
|
||||
Success output (non-dry-run):
|
||||
- `Restored session archive for <campaign>/<session_id>`
|
||||
- `Remote run: <run_id>`
|
||||
- `Downloaded: <n>`
|
||||
- `Skipped unchanged: <n>`
|
||||
- `Conflicts: <n>`
|
||||
|
||||
Common failure cases:
|
||||
- storage backend is not configured.
|
||||
- remote `current/run_id.txt` missing/empty.
|
||||
- remote `current/manifest.json` missing or invalid.
|
||||
- remote manifest session/campaign mismatch.
|
||||
- required previous-session current state or artifact missing.
|
||||
- local conflicts without `--force`.
|
||||
- session lock conflict.
|
||||
|
||||
Dry-run output may include planned previous-cache downloads. Existing differing files under `previous/**` follow the normal restore conflict policy and require `--force` to overwrite.
|
||||
|
||||
When `--include-audio` is set, S3 audio files are restored through the shared audio cache. Cache hits avoid re-downloading large audio objects.
|
||||
`publish` is force-by-design and does not accept `--force` or a stage positional argument.
|
||||
|
||||
### `clean`
|
||||
|
||||
Purpose:
|
||||
- Remove local Narratio work/spool state for testing, reruns, or recovery from corrupted local files.
|
||||
- Preserve durable S3 audio cache state unless `--clear-cache` is passed.
|
||||
|
||||
Syntax:
|
||||
|
||||
```bash
|
||||
narratio clean --session-id <id> [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--previous-session-id <id>] [--dry-run] [--clear-cache]
|
||||
narratio clean <session_id> [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--previous-session-id <id>] [--dry-run] [--clear-cache]
|
||||
narratio clean --all [--config <pipeline.yml>] [--dry-run] [--clear-cache]
|
||||
```
|
||||
|
||||
@@ -499,68 +153,173 @@ Cache behavior:
|
||||
- `--all --clear-cache` removes the configured Narratio S3 audio cache namespace for the configured bucket/root prefix.
|
||||
- `--clear-cache` does not delete arbitrary files under `pipeline.cache.root`.
|
||||
|
||||
Common failure cases:
|
||||
- missing `--session-id` when `--all` is not set.
|
||||
- combining `--all` with `--campaign`, `--session`, `--session-id`, or `--previous-session-id`.
|
||||
- unsafe cleanup target, such as a symlink, a non-directory session target, a configured root directory, or a path outside the configured root.
|
||||
### `session plan`
|
||||
|
||||
```bash
|
||||
narratio session plan <session_id> [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--previous-session-id <id>] [--force]
|
||||
```
|
||||
|
||||
Purpose:
|
||||
- Validate config, load secrets if configured, prepare workdir, and print stage run/skip decisions.
|
||||
|
||||
Success output includes:
|
||||
- `narratio session plan: workdir prepared at <path>`
|
||||
- one line per stage (`<stage>: run|skip`)
|
||||
- `totals: run=<n> skip=<n>`
|
||||
|
||||
### `session status`
|
||||
|
||||
```bash
|
||||
narratio session status <session_id> [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--previous-session-id <id>]
|
||||
```
|
||||
|
||||
Output includes:
|
||||
- session ID, campaign, workspace, and session config source.
|
||||
- local manifest state when present.
|
||||
- remote current archive state when storage is configured.
|
||||
- catalog-based promoted output availability for expected transcript and artifact sources.
|
||||
- effective archive locks and conservative next actions.
|
||||
|
||||
### `session validate`
|
||||
|
||||
```bash
|
||||
narratio session validate <session_id> [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--previous-session-id <id>]
|
||||
```
|
||||
|
||||
Checks include:
|
||||
- effective config and session source.
|
||||
- stable input files.
|
||||
- local or remote audio availability.
|
||||
- previous-session requirements.
|
||||
- archive promotions and effective locks.
|
||||
|
||||
Warnings do not fail the command. Any `ERROR` finding exits non-zero.
|
||||
|
||||
### `session init`
|
||||
|
||||
```bash
|
||||
narratio session init <session_id> --output ./session.yml
|
||||
narratio session init <session_id> --remote
|
||||
narratio session init <session_id> --config <pipeline.yml> --campaign <campaign.yml> --remote
|
||||
```
|
||||
|
||||
Additional flags:
|
||||
|
||||
- `--previous-session-id <value>`
|
||||
- `--date <value>`
|
||||
- `--title <value>`
|
||||
- `--audio-s3-prefix <prefix>`: defaults to `audio/` when neither audio flag is provided.
|
||||
- `--audio-dir <path>`: local audio directory; mutually exclusive with `--audio-s3-prefix`.
|
||||
- `--force`: overwrite existing local or remote target.
|
||||
|
||||
Behavior:
|
||||
- exactly one of `--output` or `--remote` is required.
|
||||
- `--config` and `--campaign` are optional overrides; omitted values use normal default config discovery.
|
||||
- if `campaign.yml` sets `session_template_file`, the template path is resolved relative to `campaign.yml` and rendered from init flags.
|
||||
- if no session template is configured, a minimal concrete session file is generated directly.
|
||||
- template variables must be supplied by matching flags, and supplied template-related flags must be used by the template.
|
||||
- remote writes target `{root_prefix}/campaigns/{campaign}/sessions/{session_id}/session.yml`.
|
||||
- existing local or remote targets fail unless `--force` is passed.
|
||||
- remote writes use existence checks, not compare-and-swap.
|
||||
|
||||
### `session restore`
|
||||
|
||||
```bash
|
||||
narratio session restore <session_id> [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--previous-session-id <id>] [--dry-run] [--force] [--include-audio]
|
||||
```
|
||||
|
||||
Purpose:
|
||||
- Restore durable session state from the committed remote archive current state.
|
||||
- Default restore installs `manifest.json`, `transcripts/**`, and `artifacts/**` from the current session archive.
|
||||
- When configured previous-session inputs require it, restore reconstructs `previous/**` from the previous session's committed current archive.
|
||||
- `audio/**` is restored only with `--include-audio`.
|
||||
|
||||
Dry-run output may include planned previous-cache downloads. Existing differing files under `previous/**` follow the normal restore conflict policy and require `--force` to overwrite.
|
||||
|
||||
When `--include-audio` is set, S3 audio files are restored through the shared audio cache. Cache hits avoid re-downloading large audio objects.
|
||||
|
||||
### `session artifacts`
|
||||
|
||||
```bash
|
||||
narratio session artifacts <session_id> [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--previous-session-id <id>] [--remote]
|
||||
```
|
||||
|
||||
Purpose:
|
||||
- List built-in, configured, previous-session, promoted, and locked artifact sources.
|
||||
|
||||
`--remote` checks promoted top-level object availability through the storage adapter. Remote markers appear only in the `Promoted` section, which reports each configured archive promotion destination and includes `dest=<path>` when that destination differs from the source's canonical path.
|
||||
|
||||
### `session locks`
|
||||
|
||||
```bash
|
||||
narratio session locks <session_id> [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--previous-session-id <id>]
|
||||
narratio session locks add <session_id> <source> [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--previous-session-id <id>] [--reason <text>] [--force]
|
||||
narratio session locks remove <session_id> <source> [--config <pipeline.yml>] [--campaign <campaign.yml>] [--session <session.yml>] [--previous-session-id <id>]
|
||||
```
|
||||
|
||||
Behavior:
|
||||
- list mode prints effective locks from static `pipeline.archive.locks` and remote `{session_prefix}/locks.yml`.
|
||||
- `locks add` writes only the remote lock store and fails if the source is already locked by pipeline config.
|
||||
- `locks remove` removes only remote locks and cannot remove static pipeline locks.
|
||||
- `locks add --force` is required to update an existing remote lock reason.
|
||||
|
||||
## Common Workflows
|
||||
|
||||
Default-discovery run:
|
||||
|
||||
```bash
|
||||
narratio run --session-id 2026-04-04
|
||||
narratio run 2026-04-04
|
||||
```
|
||||
|
||||
Run only selected analyze artifacts:
|
||||
|
||||
```bash
|
||||
narratio run --session-id 2026-04-04 --artifacts session_recap,player_handout
|
||||
narratio run 2026-04-04 --artifacts session_recap,player_handout
|
||||
```
|
||||
|
||||
Resume with selected analyze artifacts:
|
||||
|
||||
```bash
|
||||
narratio resume --session-id 2026-04-04 --artifacts player_handout
|
||||
narratio resume 2026-04-04 --artifacts player_handout
|
||||
```
|
||||
|
||||
Force-rerun analyze with selected artifacts:
|
||||
|
||||
```bash
|
||||
narratio analyze --session-id 2026-04-04 --artifacts player_handout
|
||||
narratio analyze 2026-04-04 --artifacts player_handout
|
||||
```
|
||||
|
||||
Force-rerun archive publishing:
|
||||
|
||||
```bash
|
||||
narratio publish --session-id 2026-04-04
|
||||
narratio publish 2026-04-04
|
||||
```
|
||||
|
||||
Preview restore actions without writes:
|
||||
|
||||
```bash
|
||||
narratio restore --session-id 2026-04-04 --dry-run
|
||||
narratio session restore 2026-04-04 --dry-run
|
||||
```
|
||||
|
||||
Restore and then force analyze:
|
||||
|
||||
```bash
|
||||
narratio restore --session-id 2026-04-04
|
||||
narratio analyze --session-id 2026-04-04
|
||||
narratio session restore 2026-04-04
|
||||
narratio analyze 2026-04-04
|
||||
```
|
||||
|
||||
Rehydrate canonical previous-session inputs after artifact-input changes:
|
||||
|
||||
```bash
|
||||
narratio run-stage --session-id 2026-04-04 --force prepare
|
||||
narratio run-stage prepare 2026-04-04 --force
|
||||
```
|
||||
|
||||
Reset local state before testing restore:
|
||||
|
||||
```bash
|
||||
narratio clean --session-id 2026-04-04 --dry-run
|
||||
narratio clean --session-id 2026-04-04
|
||||
narratio restore --session-id 2026-04-04 --include-audio
|
||||
narratio clean 2026-04-04 --dry-run
|
||||
narratio clean 2026-04-04
|
||||
narratio session restore 2026-04-04 --include-audio
|
||||
```
|
||||
|
||||
Clean all local sessions while keeping cached S3 audio:
|
||||
@@ -569,17 +328,6 @@ Clean all local sessions while keeping cached S3 audio:
|
||||
narratio clean --all
|
||||
```
|
||||
|
||||
## Diagnostic / Recovery Commands
|
||||
|
||||
Inspect stage status:
|
||||
|
||||
```bash
|
||||
narratio status --manifest <manifest.json>
|
||||
```
|
||||
|
||||
Get manifest path from previous output:
|
||||
- `run`, `resume`, `run-stage`, `analyze`, and `publish` print `manifest=<path>` on success.
|
||||
|
||||
## `--artifacts` and `--force`
|
||||
|
||||
- `--artifacts` filters which configured artifacts are executable when analyze runs and which configured artifact promotions archive publishes.
|
||||
|
||||
@@ -11,10 +11,17 @@ Narratio loads three YAML files:
|
||||
These commands load and validate all three files before running:
|
||||
|
||||
- `narratio run`
|
||||
- `narratio plan`
|
||||
- `narratio resume`
|
||||
- `narratio run-stage`
|
||||
- `narratio restore`
|
||||
- `narratio analyze`
|
||||
- `narratio publish`
|
||||
- `narratio session plan`
|
||||
- `narratio session status`
|
||||
- `narratio session validate`
|
||||
- `narratio session restore`
|
||||
- `narratio session artifacts`
|
||||
- `narratio session locks`
|
||||
- `narratio clean <session_id>`
|
||||
|
||||
Behavior:
|
||||
|
||||
@@ -31,10 +38,17 @@ Behavior:
|
||||
These commands use the same config discovery behavior:
|
||||
|
||||
- `narratio run`
|
||||
- `narratio plan`
|
||||
- `narratio resume`
|
||||
- `narratio run-stage`
|
||||
- `narratio restore`
|
||||
- `narratio analyze`
|
||||
- `narratio publish`
|
||||
- `narratio session plan`
|
||||
- `narratio session status`
|
||||
- `narratio session validate`
|
||||
- `narratio session restore`
|
||||
- `narratio session artifacts`
|
||||
- `narratio session locks`
|
||||
- `narratio clean <session_id>`
|
||||
|
||||
Pipeline config lookup:
|
||||
|
||||
@@ -59,7 +73,7 @@ Session config lookup:
|
||||
1. `/usr/local/etc/narratio/session.yml`
|
||||
2. `/etc/narratio/session.yml`
|
||||
- first existing local file wins.
|
||||
- if no local session file is found, `--session-id <value>` is present, storage is configured, and campaign identity is resolved, Narratio loads remote `session.yml` from:
|
||||
- if no local session file is found, a positional `<session_id>` is present, storage is configured, and campaign identity is resolved, Narratio loads remote `session.yml` from:
|
||||
- `{root_prefix}/campaigns/{campaign}/sessions/{session_id}/session.yml`
|
||||
- local discovery always runs before remote fallback.
|
||||
- local files in the current working directory are used only when passed explicitly, for example `--config ./pipeline.yml --campaign ./campaign.yml --session ./session.yml`.
|
||||
@@ -71,7 +85,7 @@ Template behavior for local and remote `session.yml` loaded by downstream comman
|
||||
- downstream commands do not render templates.
|
||||
- local and remote `session.yml` must be concrete.
|
||||
- any `{{ ... }}` placeholder in loaded `session.yml` fails with guidance to run `narratio session init`.
|
||||
- if concrete `session_id` mismatches `--session-id`, load fails.
|
||||
- if concrete `session_id` mismatches the positional `<session_id>`, load fails.
|
||||
- if concrete `previous_session_id` mismatches `--previous-session-id`, load fails.
|
||||
|
||||
Template behavior for `narratio session init`:
|
||||
@@ -139,7 +153,7 @@ Why this is sufficient:
|
||||
Minimal local-file usage:
|
||||
|
||||
```bash
|
||||
narratio run --config /path/to/pipeline.yml --campaign ./campaign.yml --session ./session.yml --session-id 2026-05-03
|
||||
narratio run 2026-05-03 --config /path/to/pipeline.yml --campaign ./campaign.yml --session ./session.yml
|
||||
```
|
||||
|
||||
Previous-session-enabled variant:
|
||||
@@ -152,7 +166,7 @@ inputs:
|
||||
```
|
||||
|
||||
```bash
|
||||
narratio run --config /path/to/pipeline.yml --campaign ./campaign.yml --session ./session.yml --session-id 2026-05-03 --previous-session-id 2026-04-26
|
||||
narratio run 2026-05-03 --config /path/to/pipeline.yml --campaign ./campaign.yml --session ./session.yml --previous-session-id 2026-04-26
|
||||
```
|
||||
|
||||
## 5. Production-oriented config set
|
||||
@@ -246,7 +260,7 @@ For S3-first operation, upload the same `session.yml` content to:
|
||||
Then run with explicit or discovered pipeline/campaign config and no `--session`:
|
||||
|
||||
```bash
|
||||
narratio run --config /usr/local/etc/narratio/pipeline.yml --campaign /usr/local/etc/narratio/campaign.yml --session-id 2026-05-03 --previous-session-id 2026-04-26
|
||||
narratio run 2026-05-03 --config /usr/local/etc/narratio/pipeline.yml --campaign /usr/local/etc/narratio/campaign.yml --previous-session-id 2026-04-26
|
||||
```
|
||||
|
||||
Operational notes:
|
||||
@@ -406,7 +420,7 @@ Remote mutable lock store:
|
||||
|
||||
- path: `{root_prefix}/campaigns/{campaign}/sessions/{session_id}/locks.yml`.
|
||||
- strict YAML shape: top-level `locks`, each with `source` and optional `reason`.
|
||||
- `narratio locks add` and `narratio locks remove` mutate only the remote lock store.
|
||||
- `narratio session locks add` and `narratio session locks remove` mutate only the remote lock store.
|
||||
- writes use existence checks plus `--force` for updates; they are not compare-and-swap atomic.
|
||||
|
||||
Restore-related implications:
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
# Internal: Command Restore
|
||||
|
||||
## Purpose
|
||||
Define the implemented `narratio restore` contract: committed remote-state discovery, deterministic plan classification, safe file install semantics, and restore reporting.
|
||||
Define the implemented `narratio session restore` contract: committed remote-state discovery, deterministic plan classification, safe file install semantics, and restore reporting.
|
||||
|
||||
## Inputs and outputs
|
||||
Inputs:
|
||||
- CLI flags: `--config`, `--session`, `--session-id`, `--previous-session-id`, `--dry-run`, `--force`, `--include-audio`.
|
||||
- CLI syntax: `narratio session restore <session_id>`.
|
||||
- CLI flags: `--config`, `--campaign`, `--session`, `--previous-session-id`, `--dry-run`, `--force`, `--include-audio`.
|
||||
- Resolved/validated `pipeline.yml` and `session.yml`.
|
||||
- Configured remote object store.
|
||||
- Remote committed current-state markers (`current/run_id.txt`, `current/manifest.json`).
|
||||
|
||||
@@ -48,7 +48,7 @@ None directly in this subsystem. Stages may use object storage adapters and then
|
||||
- For S3 audio sessions, `prepare` records work/cache paths, S3 provenance, and spool path when the invocation downloaded the object.
|
||||
- `previous/**` is reconstructed from configured previous-session requirements; restore uses the previous session's committed current archive rather than treating current-session archived `previous/**` as authoritative.
|
||||
- Durable cache state under `pipeline.cache.root` is not workspace state and is preserved by default by `narratio clean`.
|
||||
- `narratio clean --session-id <id>` removes the session work root and session spool root.
|
||||
- `narratio clean <id>` removes the session work root and session spool root.
|
||||
- `narratio clean --all` removes all local session work under `workspace.root/work` and spool children under `spool.root`.
|
||||
- `narratio clean --clear-cache` is the explicit opt-in for deleting matching S3 audio cache entries.
|
||||
|
||||
|
||||
@@ -11,22 +11,22 @@ For field-level configuration, see [docs/config.md](./config.md). For full comma
|
||||
3. Run Narratio:
|
||||
|
||||
```bash
|
||||
narratio run --session-id 2026-04-04
|
||||
narratio run 2026-04-04
|
||||
```
|
||||
|
||||
4. Read success output:
|
||||
- `narratio run: session <session_id>; executed=<n> skipped=<n>; manifest=<path>`
|
||||
- use `manifest=<path>` with `status` for inspection.
|
||||
- use `narratio session status <session_id>` for inspection.
|
||||
|
||||
Notes:
|
||||
- default config/campaign/session discovery checks system config locations unless `--config`, `--campaign`, and `--session` are passed.
|
||||
- when local `session.yml` discovery misses, `--session-id` loads remote `session.yml` from `{root_prefix}/campaigns/{campaign}/sessions/{session_id}/session.yml`.
|
||||
- when local `session.yml` discovery misses, positional `<session_id>` loads remote `session.yml` from `{root_prefix}/campaigns/{campaign}/sessions/{session_id}/session.yml`.
|
||||
- S3 audio mode requires `session.inputs.audio_s3.prefix` and valid object-store access.
|
||||
|
||||
Initialize a remote session skeleton:
|
||||
|
||||
```bash
|
||||
narratio session init --session-id 2026-04-04 --remote
|
||||
narratio session init 2026-04-04 --remote
|
||||
```
|
||||
|
||||
Remote init uses normal default config discovery and writes `{root_prefix}/campaigns/{campaign}/sessions/{session_id}/session.yml`. If `campaign.yml` sets `session_template_file`, init renders that template from the supplied flags and writes concrete YAML. Pass `--config` and `--campaign` when testing non-system config files. It fails if the object already exists unless `--force` is passed.
|
||||
@@ -34,7 +34,7 @@ Remote init uses normal default config discovery and writes `{root_prefix}/campa
|
||||
Validate before running:
|
||||
|
||||
```bash
|
||||
narratio session validate --session-id 2026-04-04
|
||||
narratio session validate 2026-04-04
|
||||
```
|
||||
|
||||
## Restore workflow
|
||||
@@ -44,19 +44,19 @@ Use restore when local durable session state is missing or stale and archive cur
|
||||
Dry-run (no local writes):
|
||||
|
||||
```bash
|
||||
narratio restore --session-id 2026-04-04 --dry-run
|
||||
narratio session restore 2026-04-04 --dry-run
|
||||
```
|
||||
|
||||
Execution:
|
||||
|
||||
```bash
|
||||
narratio restore --session-id 2026-04-04
|
||||
narratio session restore 2026-04-04
|
||||
```
|
||||
|
||||
Post-restore analyze rerun pattern:
|
||||
|
||||
```bash
|
||||
narratio analyze --session-id 2026-04-04
|
||||
narratio analyze 2026-04-04
|
||||
```
|
||||
|
||||
Restore source-of-truth:
|
||||
@@ -73,9 +73,9 @@ Restore default scope:
|
||||
Reset local state before restore testing:
|
||||
|
||||
```bash
|
||||
narratio clean --session-id 2026-04-04 --dry-run
|
||||
narratio clean --session-id 2026-04-04
|
||||
narratio restore --session-id 2026-04-04 --include-audio
|
||||
narratio clean 2026-04-04 --dry-run
|
||||
narratio clean 2026-04-04
|
||||
narratio session restore 2026-04-04 --include-audio
|
||||
```
|
||||
|
||||
`clean` removes the local session work directory and session spool directory. It preserves the durable S3 audio cache by default, so repeated restore or forced prepare tests do not re-download large audio files.
|
||||
@@ -136,18 +136,18 @@ Canonical previous-session input behavior:
|
||||
- canonical sources use `narratio.previous_session.artifact.<artifact_key>`.
|
||||
- these inputs are hydrated by `prepare` and by `restore`; `analyze` expects the local previous cache to already exist.
|
||||
- if analyze fails due to missing canonical previous cache, rerun:
|
||||
- `narratio run-stage --session-id <id> --force prepare`
|
||||
- or `narratio restore --session-id <id>` when remote archive current state is authoritative.
|
||||
- `narratio run-stage prepare <id> --force`
|
||||
- or `narratio session restore <id>` when remote archive current state is authoritative.
|
||||
|
||||
## Remote archive layout and publish contract
|
||||
|
||||
Preferred manual publish command:
|
||||
|
||||
```bash
|
||||
narratio publish --session-id <id>
|
||||
narratio publish <id>
|
||||
```
|
||||
|
||||
`publish` is equivalent to `narratio run-stage --force archive`; use `run-stage` when you need the general single-stage command form.
|
||||
`publish` is equivalent to `narratio run-stage archive <id> --force`; use `run-stage` when you need the general single-stage command form.
|
||||
|
||||
When archive is enabled and run upload is enabled, archive publishes under:
|
||||
|
||||
@@ -176,10 +176,10 @@ Archive promotion is explicit and source-based:
|
||||
- locked required promotions are treated as intentional successful skips and are recorded in archive metadata.
|
||||
|
||||
Lock helper behavior:
|
||||
- `narratio locks --session-id <id>` lists effective static and remote locks.
|
||||
- `narratio locks add --session-id <id> --reason <text> <source>` writes a remote lock.
|
||||
- `narratio locks add --session-id <id> --force --reason <text> <source>` updates an existing remote lock reason.
|
||||
- `narratio locks remove --session-id <id> <source>` removes only a remote lock.
|
||||
- `narratio session locks <id>` lists effective static and remote locks.
|
||||
- `narratio session locks add <id> <source> --reason <text>` writes a remote lock.
|
||||
- `narratio session locks add <id> <source> --force --reason <text>` updates an existing remote lock reason.
|
||||
- `narratio session locks remove <id> <source>` removes only a remote lock.
|
||||
- `locks remove` cannot remove static pipeline locks.
|
||||
- remote lock writes check whether the lock store exists, but are not compare-and-swap atomic.
|
||||
|
||||
@@ -214,7 +214,7 @@ Automatic cleanup toggles:
|
||||
- `pipeline.workspace.cleanup_after_archive=true` deletes run-scoped local run directory.
|
||||
|
||||
Manual cleanup:
|
||||
- `narratio clean --session-id <id>` deletes `{workspace.root}/work/{campaign}/{session_id}` and `{spool.root}/{campaign}/{session_id}`.
|
||||
- `narratio clean <id>` deletes `{workspace.root}/work/{campaign}/{session_id}` and `{spool.root}/{campaign}/{session_id}`.
|
||||
- `narratio clean --all` deletes all local session work under `{workspace.root}/work` and all spool children under `{spool.root}`.
|
||||
- `--dry-run` prints targets without deleting.
|
||||
- `--clear-cache` also removes matching S3 audio cache files. Without it, cache is preserved.
|
||||
@@ -248,25 +248,19 @@ Recommended recovery:
|
||||
1. inspect state:
|
||||
|
||||
```bash
|
||||
narratio status --session-id 2026-04-04
|
||||
narratio session status 2026-04-04
|
||||
```
|
||||
|
||||
This reports local manifest state, committed remote current state, expected remote transcript/artifact availability, and archive locks.
|
||||
|
||||
2. for one manifest file, run:
|
||||
2. for restore-specific checks, run:
|
||||
|
||||
```bash
|
||||
narratio status --manifest <manifest-path>
|
||||
narratio session restore 2026-04-04 --dry-run
|
||||
```
|
||||
|
||||
3. for restore-specific checks, run:
|
||||
|
||||
```bash
|
||||
narratio restore --session-id 2026-04-04 --dry-run
|
||||
```
|
||||
|
||||
4. fix root cause (config/input/credentials/storage/service availability).
|
||||
5. continue with `resume`, or targeted `run-stage --force` followed by `resume`.
|
||||
3. fix root cause (config/input/credentials/storage/service availability).
|
||||
4. continue with `resume`, or targeted `run-stage <stage> <id> --force` followed by `resume`.
|
||||
|
||||
## Restore report
|
||||
|
||||
@@ -283,9 +277,8 @@ Dry-run does not write restore report files.
|
||||
|
||||
## Operational caveats
|
||||
|
||||
- `status` with no config/session flags still requires explicit `--manifest`.
|
||||
- `status --session-id <id>` uses normal config/session loading, including remote session fallback.
|
||||
- `status --session-id <id>` includes the same promoted remote output availability view as `artifacts list --remote` when storage is configured.
|
||||
- `session status <session_id>` uses normal config/session loading, including remote session fallback.
|
||||
- `session status <session_id>` includes the same promoted remote output availability view as `session artifacts <session_id> --remote` when storage is configured.
|
||||
- local and S3 audio input modes are mutually exclusive.
|
||||
- archive publish requires upstream stages through `analyze` to be `succeeded`.
|
||||
- required configured artifact promotions for unselected `--artifacts` keys are skipped intentionally; selected required promotions still fail if their files are missing.
|
||||
|
||||
255
docs/roadmap/cli.md
Normal file
255
docs/roadmap/cli.md
Normal file
@@ -0,0 +1,255 @@
|
||||
# Roadmap: Session-Oriented CLI Cleanup
|
||||
|
||||
Status: Implemented
|
||||
|
||||
## Problem
|
||||
|
||||
Narratio's public CLI has accumulated too many top-level commands. Several
|
||||
commands are session-scoped operator helpers, but they currently appear as
|
||||
independent top-level verbs:
|
||||
|
||||
- `plan`
|
||||
- `status`
|
||||
- `restore`
|
||||
- `artifacts list`
|
||||
- `locks`
|
||||
- `session validate`
|
||||
- `session init`
|
||||
|
||||
This makes the command surface harder to learn because the CLI does not clearly
|
||||
separate primary workflow actions from session inspection, initialization,
|
||||
restore, and helper operations.
|
||||
|
||||
## Target Model
|
||||
|
||||
Keep primary workflow commands at top level:
|
||||
|
||||
- `run`
|
||||
- `run-stage`
|
||||
- `resume`
|
||||
- `analyze`
|
||||
- `publish`
|
||||
- `clean`
|
||||
- `session`
|
||||
|
||||
Keep `clean` top-level because it can operate on one session or all local
|
||||
sessions and is a workspace maintenance command, not only a session helper.
|
||||
|
||||
Move session-scoped helper commands under `narratio session` and use positional
|
||||
session identifiers:
|
||||
|
||||
- `narratio session init <session_id> [--remote|--output <path>] [--flags]`
|
||||
- `narratio session validate <session_id> [--flags]`
|
||||
- `narratio session status <session_id> [--flags]`
|
||||
- `narratio session plan <session_id> [--flags]`
|
||||
- `narratio session restore <session_id> [--flags]`
|
||||
- `narratio session artifacts <session_id> [--remote] [--flags]`
|
||||
- `narratio session locks <session_id> [--flags]`
|
||||
- `narratio session locks add <session_id> <source> [--reason <text>] [--force] [--flags]`
|
||||
- `narratio session locks remove <session_id> <source> [--flags]`
|
||||
|
||||
Update top-level workflow commands to use positional session identifiers:
|
||||
|
||||
- `narratio run <session_id> [--flags]`
|
||||
- `narratio resume <session_id> [--flags]`
|
||||
- `narratio analyze <session_id> [--flags]`
|
||||
- `narratio publish <session_id> [--flags]`
|
||||
- `narratio run-stage <stage> <session_id> [--flags]`
|
||||
|
||||
The positional session ID replaces `--session-id` as the primary public
|
||||
interface. Existing `--config`, `--campaign`, `--session`, and
|
||||
`--previous-session-id` flags remain available where they are meaningful.
|
||||
|
||||
## Command Mapping
|
||||
|
||||
| Current command | Target command |
|
||||
| --- | --- |
|
||||
| `narratio run --session-id <id>` | `narratio run <id>` |
|
||||
| `narratio resume --session-id <id>` | `narratio resume <id>` |
|
||||
| `narratio analyze --session-id <id>` | `narratio analyze <id>` |
|
||||
| `narratio publish --session-id <id>` | `narratio publish <id>` |
|
||||
| `narratio run-stage [flags] <stage> --session-id <id>` | `narratio run-stage <stage> <id> [flags]` |
|
||||
| `narratio plan --session-id <id>` | `narratio session plan <id>` |
|
||||
| `narratio status --session-id <id>` | `narratio session status <id>` |
|
||||
| `narratio restore --session-id <id>` | `narratio session restore <id>` |
|
||||
| `narratio artifacts list --session-id <id>` | `narratio session artifacts <id>` |
|
||||
| `narratio locks --session-id <id>` | `narratio session locks <id>` |
|
||||
| `narratio locks add --session-id <id> <source>` | `narratio session locks add <id> <source>` |
|
||||
| `narratio locks remove --session-id <id> <source>` | `narratio session locks remove <id> <source>` |
|
||||
| `narratio session validate --session-id <id>` | `narratio session validate <id>` |
|
||||
| `narratio session init --session-id <id>` | `narratio session init <id>` |
|
||||
| `narratio clean --session-id <id>` | `narratio clean <id>` |
|
||||
| `narratio clean --all` | unchanged |
|
||||
|
||||
`clean` remains top-level, but its session-scoped form should also move from
|
||||
`--session-id` to positional `<session_id>` for consistency.
|
||||
|
||||
## Compatibility Policy
|
||||
|
||||
This is a hard public CLI cleanup after the migration step lands.
|
||||
|
||||
During Step 1, old forms may remain as compatibility aliases to keep the
|
||||
implementation reviewable. During Step 2, remove the old forms from command
|
||||
dispatch, tests, docs, and examples:
|
||||
|
||||
- remove top-level `plan`;
|
||||
- remove top-level `status`;
|
||||
- remove top-level `restore`;
|
||||
- remove top-level `artifacts`;
|
||||
- remove top-level `locks`;
|
||||
- remove `--session-id` from the public command syntax for session-aware
|
||||
commands.
|
||||
|
||||
Do not keep long-term deprecated aliases unless a later roadmap explicitly
|
||||
chooses a compatibility window.
|
||||
|
||||
`status --manifest` does not fit the session-oriented command shape. Remove it
|
||||
from the public CLI in this cleanup. If direct manifest inspection is needed
|
||||
later, add a separate diagnostic command in a future roadmap rather than keeping
|
||||
it as a special case in `session status`.
|
||||
|
||||
## Implementation Step 1: Add New Session-Oriented Interface
|
||||
|
||||
Status: Implemented
|
||||
|
||||
Add the target command forms while preserving current behavior internally.
|
||||
|
||||
Implementation requirements:
|
||||
|
||||
- Add positional session ID parsing helpers in `internal/app`.
|
||||
- Keep the existing `loadCommandConfig` behavior and populate
|
||||
`config.SessionLoadOptions.SessionID` from the positional ID.
|
||||
- Add or update command wrappers:
|
||||
- `Run(ctx, args, out)` parses `run <session_id>`.
|
||||
- `Resume(ctx, args, out)` parses `resume <session_id>`.
|
||||
- `Analyze(ctx, args, out)` parses `analyze <session_id>`.
|
||||
- `Publish(ctx, args, out)` parses `publish <session_id>`.
|
||||
- `RunStage(ctx, args, out)` parses `run-stage <stage> <session_id>`.
|
||||
- `Clean(ctx, args, out)` parses `clean <session_id>` and keeps
|
||||
`clean --all`.
|
||||
- Extend `Session(ctx, args, out)` dispatch to support:
|
||||
- `init <session_id>`
|
||||
- `validate <session_id>`
|
||||
- `status <session_id>`
|
||||
- `plan <session_id>`
|
||||
- `restore <session_id>`
|
||||
- `artifacts <session_id>`
|
||||
- `locks <session_id>`
|
||||
- `locks add <session_id> <source>`
|
||||
- `locks remove <session_id> <source>`
|
||||
- Keep storage access through the existing app-level object-store helper.
|
||||
- Keep AWS SDK details behind storage adapters.
|
||||
- Keep the runner, stages, manifest behavior, archive behavior, restore
|
||||
planning, lock semantics, and artifact catalog behavior unchanged.
|
||||
|
||||
Acceptance criteria:
|
||||
|
||||
- New forms execute the same code paths and produce equivalent results.
|
||||
- Positional session ID mismatch with concrete local or remote `session.yml`
|
||||
fails through existing session identity checks.
|
||||
- Remote session fallback still uses the positional session ID as the lookup
|
||||
value.
|
||||
- Current command tests cover the new forms before old forms are removed.
|
||||
|
||||
## Implementation Step 2: Remove Old Public Forms
|
||||
|
||||
Status: Implemented
|
||||
|
||||
Remove compatibility aliases and make the session-oriented interface the only
|
||||
documented and supported public CLI.
|
||||
|
||||
Implementation requirements:
|
||||
|
||||
- Remove top-level dispatch for:
|
||||
- `plan`
|
||||
- `status`
|
||||
- `restore`
|
||||
- `artifacts`
|
||||
- `locks`
|
||||
- Remove `--session-id` flags from public session-aware commands.
|
||||
- Keep `--previous-session-id` as an expected previous-session identity flag.
|
||||
- Keep explicit `--session <path>` for loading a local concrete session file,
|
||||
but still require the positional session ID for commands that operate on a
|
||||
session.
|
||||
- Remove `status --manifest`.
|
||||
- Update usage text and invalid-command errors.
|
||||
- Update `docs/cli.md` and `docs/operations.md` to use only the new forms.
|
||||
- Update any roadmap docs that mention old helper command names.
|
||||
- Update tests to expect old top-level helper commands and `--session-id` forms
|
||||
to fail.
|
||||
|
||||
Acceptance criteria:
|
||||
|
||||
- Top-level command list is exactly:
|
||||
- `run`
|
||||
- `run-stage`
|
||||
- `resume`
|
||||
- `analyze`
|
||||
- `publish`
|
||||
- `clean`
|
||||
- `session`
|
||||
- All session-oriented commands use `narratio session <subcommand>
|
||||
<session_id> [--flags]`, except nested lock mutation forms, which use
|
||||
`narratio session locks add|remove <session_id> <source> [--flags]`.
|
||||
- `clean <session_id>` and `clean --all` remain top-level.
|
||||
- Current-behavior docs and tests no longer advertise `--session-id`.
|
||||
|
||||
## Test Guidance
|
||||
|
||||
Focused tests:
|
||||
|
||||
- `go test ./internal/app -run TestExecute -v`
|
||||
- `go test ./internal/app -run 'Session|Status|Restore|Clean|Locks|Artifacts|Plan|RunStage|Analyze|Publish' -v`
|
||||
- `go test ./internal/config -v`
|
||||
|
||||
Full validation:
|
||||
|
||||
- `go test ./...`
|
||||
|
||||
Test cases to add or update:
|
||||
|
||||
- `run <session_id>` loads local and remote sessions through the existing
|
||||
config path.
|
||||
- `resume <session_id>`, `analyze <session_id>`, and `publish <session_id>`
|
||||
preserve current behavior.
|
||||
- `run-stage <stage> <session_id>` preserves current run-stage output and
|
||||
force/artifact-selection behavior.
|
||||
- `session plan <session_id>` replaces top-level `plan`.
|
||||
- `session status <session_id>` replaces top-level session status.
|
||||
- `session validate <session_id>` replaces `session validate --session-id`.
|
||||
- `session init <session_id>` writes the same local or remote concrete
|
||||
`session.yml`.
|
||||
- `session restore <session_id>` preserves restore planning/execution.
|
||||
- `session artifacts <session_id> --remote` preserves promoted-output
|
||||
availability reporting.
|
||||
- `session locks <session_id>`, `session locks add <session_id> <source>`, and
|
||||
`session locks remove <session_id> <source>` preserve static/remote lock
|
||||
semantics.
|
||||
- `clean <session_id>` preserves session cleanup behavior, while `clean --all`
|
||||
remains unchanged.
|
||||
- Old top-level helper commands fail after Step 2.
|
||||
- `--session-id` fails after Step 2.
|
||||
- `status --manifest` fails after Step 2.
|
||||
|
||||
## Documentation Guidance
|
||||
|
||||
Update only after implementation lands:
|
||||
|
||||
- `docs/cli.md`
|
||||
- `docs/operations.md`
|
||||
- any internal docs that list command names or examples
|
||||
|
||||
Keep planned behavior only in this roadmap until the command refactor is
|
||||
implemented.
|
||||
|
||||
## Architecture Guardrails
|
||||
|
||||
- Keep Narratio explicit and stage-driven.
|
||||
- Do not introduce a generic workflow or command framework abstraction.
|
||||
- Reuse existing app command helpers where practical.
|
||||
- Keep config loading strict and centralized.
|
||||
- Keep storage details behind `storage.ObjectStore`.
|
||||
- Keep secret-backed object-store construction in `internal/app`.
|
||||
- Preserve manifest-driven resume and restore behavior.
|
||||
- Treat command renaming as a public CLI contract change, not a runtime stage
|
||||
behavior change.
|
||||
@@ -6,7 +6,7 @@ Canonical operator troubleshooting guide for recurring implemented Narratio fail
|
||||
## Config file discovery failure
|
||||
|
||||
Symptom:
|
||||
- `run`, `plan`, `resume`, `run-stage`, or `restore` fails with config/session not found.
|
||||
- `run`, `resume`, `run-stage`, `session plan`, or `session restore` fails with config/session not found.
|
||||
|
||||
Likely Cause:
|
||||
- `pipeline.yml`, `campaign.yml`, or `session.yml` is missing from system discovery paths.
|
||||
@@ -40,7 +40,7 @@ Likely Cause:
|
||||
Diagnostics:
|
||||
|
||||
```bash
|
||||
narratio plan --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --session ./session.yml --session-id 2026-04-04
|
||||
narratio session plan 2026-04-04 --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --session ./session.yml
|
||||
```
|
||||
|
||||
Safe Fix:
|
||||
@@ -62,7 +62,7 @@ Likely Cause:
|
||||
Diagnostics:
|
||||
|
||||
```bash
|
||||
narratio plan --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --session /path/to/session.yml --session-id 2026-04-04
|
||||
narratio session plan 2026-04-04 --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --session /path/to/session.yml
|
||||
```
|
||||
|
||||
Safe Fix:
|
||||
@@ -84,7 +84,7 @@ Likely Cause:
|
||||
Diagnostics:
|
||||
|
||||
```bash
|
||||
narratio run --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --session /path/to/session.yml --session-id 2026-04-04 --artifacts player_handout
|
||||
narratio run 2026-04-04 --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --session /path/to/session.yml --artifacts player_handout
|
||||
```
|
||||
|
||||
Safe Fix:
|
||||
@@ -95,22 +95,22 @@ Links:
|
||||
- [docs/cli.md](./cli.md)
|
||||
- [docs/config.md](./config.md)
|
||||
|
||||
## `run-stage --artifacts` on non-analyze stage
|
||||
## `run-stage --artifacts` on unsupported stage
|
||||
|
||||
Symptom:
|
||||
- `run-stage` fails with `--artifacts is only supported for stage "analyze"`.
|
||||
- `run-stage` fails because `--artifacts` is only supported for `analyze` and `archive`.
|
||||
|
||||
Likely Cause:
|
||||
- `--artifacts` was used with a non-`analyze` stage.
|
||||
- `--artifacts` was used with a stage other than `analyze` or `archive`.
|
||||
|
||||
Diagnostics:
|
||||
|
||||
```bash
|
||||
narratio run-stage --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --session /path/to/session.yml --session-id 2026-04-04 --artifacts session_recap polish
|
||||
narratio run-stage polish 2026-04-04 --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --session /path/to/session.yml --artifacts session_recap
|
||||
```
|
||||
|
||||
Safe Fix:
|
||||
- use `--artifacts` only with `run-stage ... analyze`.
|
||||
- use `--artifacts` only with `run-stage analyze ...` or `run-stage archive ...`.
|
||||
|
||||
Links:
|
||||
- [docs/cli.md](./cli.md)
|
||||
@@ -129,7 +129,7 @@ Likely Cause:
|
||||
Diagnostics:
|
||||
|
||||
```bash
|
||||
narratio plan --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --session /path/to/session.yml --session-id 2026-04-04
|
||||
narratio session plan 2026-04-04 --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --session /path/to/session.yml
|
||||
```
|
||||
|
||||
Safe Fix:
|
||||
@@ -153,8 +153,8 @@ Likely Cause:
|
||||
Diagnostics:
|
||||
|
||||
```bash
|
||||
narratio status --manifest /path/to/manifest.json
|
||||
narratio run-stage --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --session /path/to/session.yml --session-id 2026-04-04 --artifacts player_handout analyze
|
||||
narratio session status 2026-04-04
|
||||
narratio run-stage analyze 2026-04-04 --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --session /path/to/session.yml --artifacts player_handout
|
||||
```
|
||||
|
||||
Safe Fix:
|
||||
@@ -168,22 +168,21 @@ Links:
|
||||
## Manifest/status path failure
|
||||
|
||||
Symptom:
|
||||
- `status` fails because manifest path is missing, unreadable, or invalid.
|
||||
- `session status` fails because config/session state is missing, unreadable, or invalid.
|
||||
|
||||
Likely Cause:
|
||||
- wrong manifest path.
|
||||
- wrong session ID.
|
||||
- wrong config/campaign/session file selected.
|
||||
- manifest removed after cleanup.
|
||||
- `--manifest` omitted.
|
||||
|
||||
Diagnostics:
|
||||
|
||||
```bash
|
||||
narratio status --manifest /path/to/manifest.json
|
||||
ls -l /path/to/manifest.json
|
||||
narratio session status 2026-04-04
|
||||
```
|
||||
|
||||
Safe Fix:
|
||||
- use manifest path printed by `run`, `resume`, or `run-stage`.
|
||||
- use the same session ID and config files that will be used for `run`, `resume`, or `run-stage`.
|
||||
|
||||
Links:
|
||||
- [docs/cli.md](./cli.md)
|
||||
@@ -192,7 +191,7 @@ Links:
|
||||
## Session lock conflict (`.lock`)
|
||||
|
||||
Symptom:
|
||||
- `run`, `resume`, `run-stage`, or `restore` fails with lock conflict for session workdir.
|
||||
- `run`, `resume`, `run-stage`, or `session restore` fails with lock conflict for session workdir.
|
||||
|
||||
Likely Cause:
|
||||
- another Narratio process is running same session.
|
||||
@@ -217,7 +216,7 @@ Links:
|
||||
## Restore remote current pointer or manifest missing
|
||||
|
||||
Symptom:
|
||||
- `restore` fails with remote current pointer or current manifest errors.
|
||||
- `session restore` fails with remote current pointer or current manifest errors.
|
||||
|
||||
Likely Cause:
|
||||
- `current/run_id.txt` was never published.
|
||||
@@ -227,7 +226,7 @@ Likely Cause:
|
||||
Diagnostics:
|
||||
|
||||
```bash
|
||||
narratio restore --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --session /path/to/session.yml --session-id 2026-04-04 --dry-run
|
||||
narratio session restore 2026-04-04 --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --session /path/to/session.yml --dry-run
|
||||
```
|
||||
|
||||
Safe Fix:
|
||||
@@ -241,20 +240,20 @@ Links:
|
||||
## Restore manifest identity mismatch
|
||||
|
||||
Symptom:
|
||||
- `restore` fails because remote manifest session or campaign does not match requested values.
|
||||
- `session restore` fails because remote manifest session or campaign does not match requested values.
|
||||
|
||||
Likely Cause:
|
||||
- wrong `--session-id` or wrong session config selected.
|
||||
- wrong positional session ID or wrong session config selected.
|
||||
- archive prefix points to a different campaign/session.
|
||||
|
||||
Diagnostics:
|
||||
|
||||
```bash
|
||||
narratio restore --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --session /path/to/session.yml --session-id 2026-04-04 --dry-run
|
||||
narratio session restore 2026-04-04 --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --session /path/to/session.yml --dry-run
|
||||
```
|
||||
|
||||
Safe Fix:
|
||||
- use the correct session config and `--session-id`.
|
||||
- use the correct session config and positional session ID.
|
||||
- verify campaign/session identity in local config before restore.
|
||||
|
||||
Links:
|
||||
@@ -264,7 +263,7 @@ Links:
|
||||
## Restore conflict without `--force`
|
||||
|
||||
Symptom:
|
||||
- `restore` fails with `restore conflict` and conflict counts.
|
||||
- `session restore` fails with `restore conflict` and conflict counts.
|
||||
|
||||
Likely Cause:
|
||||
- local durable file differs from remote file for one or more planned restore paths.
|
||||
@@ -272,7 +271,7 @@ Likely Cause:
|
||||
Diagnostics:
|
||||
|
||||
```bash
|
||||
narratio restore --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --session /path/to/session.yml --session-id 2026-04-04 --dry-run
|
||||
narratio session restore 2026-04-04 --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --session /path/to/session.yml --dry-run
|
||||
```
|
||||
|
||||
Safe Fix:
|
||||
@@ -342,7 +341,7 @@ Likely Cause:
|
||||
Diagnostics:
|
||||
|
||||
```bash
|
||||
narratio run-stage --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --session /path/to/session.yml --session-id 2026-04-04 prepare
|
||||
narratio run-stage prepare 2026-04-04 --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --session /path/to/session.yml
|
||||
```
|
||||
|
||||
Safe Fix:
|
||||
@@ -365,8 +364,8 @@ Likely Cause:
|
||||
Diagnostics:
|
||||
|
||||
```bash
|
||||
narratio status --manifest /path/to/manifest.json
|
||||
narratio run-stage --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --session /path/to/session.yml --session-id 2026-04-04 archive
|
||||
narratio session status 2026-04-04
|
||||
narratio run-stage archive 2026-04-04 --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --session /path/to/session.yml
|
||||
```
|
||||
|
||||
Safe Fix:
|
||||
|
||||
Reference in New Issue
Block a user