Session configuration templates are now proceeded by narratio session init; all other commands require concrete configuration

This commit is contained in:
2026-05-22 17:38:23 -05:00
parent d0936fb022
commit 7324c5a686
20 changed files with 550 additions and 299 deletions

View File

@@ -10,6 +10,8 @@ This command uses default system discovery for `pipeline.yml`, `campaign.yml`, a
Default discovery checks system config locations only. Pass `--config`, `--campaign`, and `--session` to use files from the current working directory.
Ordinary local and remote `session.yml` files must be concrete YAML. Templates belong to `narratio session init`, which renders a configured campaign template before writing the concrete file.
## Command Overview
Implemented commands:
@@ -39,8 +41,8 @@ For config semantics, see [docs/config.md](./config.md). For operator lifecycle
- `--config <path>`: optional explicit `pipeline.yml` path.
- `--campaign <path>`: optional explicit `campaign.yml` path.
- `--session <path>`: optional explicit `session.yml` path.
- `--session-id <value>`: session template variable value.
- `--previous-session-id <value>`: previous-session template variable value.
- `--session-id <value>`: expected session identifier and remote session lookup value.
- `--previous-session-id <value>`: expected previous session identifier.
- `--force`: force stage execution.
- `--artifacts <names>`: analyze artifact keys to execute (repeatable or comma-separated).
@@ -160,6 +162,8 @@ Valid stage names:
- `--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>`
@@ -175,7 +179,7 @@ Valid stage names:
- `--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 session template value.
- `--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.
@@ -200,7 +204,8 @@ Success output:
Common failure cases:
- missing system default config/campaign/session paths when flags omitted.
- missing local session plus missing/unavailable remote `session.yml`.
- invalid template/rendered session mismatch.
- 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.
@@ -241,7 +246,7 @@ Success output:
- or `narratio resume: session <session_id>; executed=<n> skipped=<n>; manifest=<path>`
Common failure cases:
- same discovery/template/validation failures as `run`.
- same discovery and validation failures as `run`.
- manifest load errors when existing manifest is unreadable.
- invalid or unknown artifact selections.
@@ -297,7 +302,7 @@ Warnings do not fail the command. Any `ERROR` finding exits non-zero.
### `session init`
Purpose:
- Create a strict-decoded session skeleton locally or in object storage.
- Create a strict-decoded concrete `session.yml` locally or in object storage.
Syntax:
@@ -310,6 +315,9 @@ narratio session init --config <pipeline.yml> --campaign <campaign.yml> --sessio
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.

View File

@@ -19,11 +19,11 @@ These commands load and validate all three files before running:
Behavior:
- strict YAML decode is enabled (`KnownFields(true)`): unknown fields fail.
- session templates render before session YAML decode.
- remote `session.yml` uses the same strict decode and template behavior as local `session.yml`.
- ordinary local and remote `session.yml` files must be concrete YAML; template placeholders are rejected.
- defaults are applied for optional pipeline fields.
- campaign-level stable input paths fill missing session input paths.
- session-level stable input paths override campaign-level input paths.
- campaign config may point `session init` to a session template.
- validation enforces required fields, value formats, and cross-field constraints.
## 2. Config file discovery
@@ -66,18 +66,29 @@ Session config lookup:
## 3. Session templating
Template behavior for local and remote `session.yml`:
Template behavior for local and remote `session.yml` loaded by downstream commands:
- supported placeholders:
- `{{session_id}}`
- 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 `previous_session_id` mismatches `--previous-session-id`, load fails.
Template behavior for `narratio session init`:
- `campaign.yml` may set `session_template_file`.
- relative template paths resolve relative to `campaign.yml`.
- supported init template variables:
- `{{ session_id }}`
- `{{previous_session_id}}`
- `{{ previous_session_id }}`
- `--session-id <value>` supplies the placeholder value.
- `--previous-session-id <value>` supplies the previous-session placeholder value.
- unresolved placeholders fail load.
- if rendered `session_id` mismatches `--session-id`, load fails.
- if rendered `previous_session_id` mismatches `--previous-session-id`, load fails.
- `{{ date }}`
- `{{ title }}`
- `{{ audio_s3_prefix }}`
- `{{ audio_dir }}`
- each template variable must be supplied by the matching `session init` flag.
- template-related flags such as `--date`, `--title`, `--audio-s3-prefix`, `--audio-dir`, and `--previous-session-id` fail if the configured template does not use them.
- rendered output is strict-decoded and validated before it is written locally or remotely.
- if `session_template_file` is omitted, `session init` generates the minimal concrete session YAML directly.
## 4. Minimal config set
@@ -98,6 +109,7 @@ Why this is sufficient:
```yaml
campaign: sample-campaign
session_template_file: ./session.template.yml
inputs:
speakers_file: ./speakers.yml
autocorrect_file: ./autocorrect.yml
@@ -112,14 +124,14 @@ Why this is sufficient:
### `session.yml`
```yaml
session_id: "{{ session_id }}"
session_id: 2026-05-03
inputs:
audio_dir: ./audio
```
Why this is sufficient:
- `session_id` is required and can be rendered from `--session-id`.
- `session_id` is required.
- `campaign` can be omitted because it is supplied by `campaign.yml`.
- stable input paths can be omitted because `campaign.yml` supplies defaults.
- local `audio_dir` resolves relative to `session.yml`.
@@ -133,8 +145,8 @@ narratio run --config /path/to/pipeline.yml --campaign ./campaign.yml --session
Previous-session-enabled variant:
```yaml
session_id: "{{ session_id }}"
previous_session_id: "{{ previous_session_id }}"
session_id: 2026-05-03
previous_session_id: 2026-04-26
inputs:
audio_dir: ./audio
```
@@ -214,8 +226,8 @@ inputs:
### Local `session.yml`
```yaml
session_id: "{{ session_id }}"
previous_session_id: "{{ previous_session_id }}"
session_id: 2026-05-03
previous_session_id: 2026-04-26
date: 2026-05-03
title: The Black Cabin
inputs:
@@ -416,11 +428,12 @@ Restore-related implications:
| Path | Type | Required | Default |
| --- | --- | --- | --- |
| `campaign.campaign` | string | Yes | none |
| `campaign.session_template_file` | string | No | none |
| `campaign.inputs.speakers_file` | string | Yes | none |
| `campaign.inputs.autocorrect_file` | string | Yes | none |
| `campaign.inputs.glossary_file` | string | Yes | none |
Campaign input paths may be absolute or relative. Relative paths resolve from the directory containing `campaign.yml`.
Campaign input paths and `campaign.session_template_file` may be absolute or relative. Relative paths resolve from the directory containing `campaign.yml`.
## 8. Full session reference

View File

@@ -29,7 +29,7 @@ Initialize a remote session skeleton:
narratio session init --session-id 2026-04-04 --remote
```
Remote init uses normal default config discovery and writes `{root_prefix}/campaigns/{campaign}/sessions/{session_id}/session.yml`. Pass `--config` and `--campaign` when testing non-system config files. It fails if the object already exists unless `--force` is passed.
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.
Validate before running:

View File

@@ -1,52 +0,0 @@
# Roadmap: Operator Helper Commands
## Status
Implemented.
The operator helper command set is no longer conceptual. Current behavior is documented in:
- `docs/cli.md`
- `docs/operations.md`
- `docs/config.md`
- `docs/internal/artifacts.md`
- `docs/internal/stage-archive.md`
## Implemented Commands
- `narratio session validate`
- `narratio status --manifest <path>`
- `narratio status --session-id <id>`
- `narratio session init --output <path>`
- `narratio session init --remote`
- `narratio artifacts list`
- `narratio artifacts list --remote`
- `narratio locks`
- `narratio locks add <source>`
- `narratio locks remove <source>`
## Implemented Decisions
- Helper output is text-only. No JSON schema exists yet.
- `status` remains a top-level command.
- `session validate`, `session init`, and `artifacts list` are nested helper commands.
- `locks` is the single top-level command for listing, adding, and removing archive promotion locks.
- Remote session initialization requires explicit `--remote`.
- Local session initialization requires `--output`.
- Remote artifact availability is opt-in with `artifacts list --remote`.
- Mutable locks are source-based and stored at `{session_prefix}/locks.yml`.
- The remote lock store uses strict YAML with top-level `locks`.
- Static `pipeline.archive.locks` and remote locks are merged; static locks win on duplicate sources.
- `locks remove` removes only remote locks.
- Ordinary execution `--force` does not override locks.
- Remote lock writes use existence checks and `--force` for updates; there is no compare-and-swap protection.
## Remaining Future Enhancements
These are intentionally not implemented:
- `--json` output for helper commands.
- Optimistic concurrency or ETag compare-and-swap for remote lock mutations.
- Rich remote artifact availability across historical run-local objects.
- Session-lock acquisition for remote mutation helpers.
- Broader campaign helper commands such as `campaign validate` or `campaign publish`.

View File

@@ -28,14 +28,14 @@ Links:
- [docs/config.md](./config.md)
- [docs/cli.md](./cli.md)
## Session template rendering failure
## Templated session file rejected
Symptom:
- load fails with unresolved placeholder or `session_id` mismatch.
- load fails with a message that `session.yml must be concrete`.
Likely Cause:
- templated `session.yml` used without `--session-id`.
- rendered `session_id` differs from passed `--session-id`.
- a template authoring file such as `session.template.yml` was passed to `--session` or uploaded as remote `session.yml`.
- `session.yml` still contains `{{ ... }}` placeholders.
Diagnostics:
@@ -44,8 +44,8 @@ narratio plan --config /path/to/pipeline.yml --campaign /path/to/campaign.yml --
```
Safe Fix:
- pass `--session-id` when template placeholders are present.
- ensure rendered `session_id` matches intended run session id.
- generate concrete YAML with `narratio session init`.
- pass the generated concrete `session.yml` to downstream commands or upload it through `session init --remote`.
Links:
- [docs/config.md](./config.md)