2026-05-19 22:32:55 -05:00
# Internal: Command Restore
## Purpose
2026-05-20 15:17:04 +00:00
Define the implemented `narratio restore` contract: committed remote-state discovery, deterministic plan classification, safe file install semantics, and restore reporting.
2026-05-19 22:32:55 -05:00
## Inputs and outputs
Inputs:
2026-05-20 15:17:04 +00:00
- CLI flags: `--config` , `--session` , `--session-id` , `--previous-session-id` , `--dry-run` , `--force` , `--include-audio` .
2026-05-19 22:32:55 -05:00
- Resolved/validated `pipeline.yml` and `session.yml` .
- Configured remote object store.
- Remote committed current-state markers (`current/run_id.txt` , `current/manifest.json` ).
Outputs:
- Dry-run summary to stdout (plan + counts).
- Non-dry-run completion summary to stdout.
- Local durable session files restored under canonical session root.
- Non-dry-run restore report at `reports/restore-latest.json` .
## Boundaries
Owns:
- Restore command flag parsing and command wiring.
- Remote current-state discovery and identity validation.
- Restore plan construction and conflict classification.
- Restore execution for planned downloads.
- Restore report model and persistence.
Does not own:
- Stage execution orchestration (`run` , `resume` , `run-stage` ).
- Archive publish behavior (owned by archive stage).
- Storage transport implementation details (owned by storage adapters).
## Config fields used
- Config/session discovery and templating fields consumed by all commands.
- `pipeline.workspace.root` (local restore target root).
- `pipeline.storage.*` (remote backend + archive identity derivation).
- `pipeline.storage.s3.*` identity components used by archive prefix helpers.
2026-05-21 22:22:08 -05:00
- `pipeline.spool.root` for active audio downloads.
- `pipeline.cache.root` and `pipeline.cache.s3_audio` for reusable S3 audio cache.
2026-05-19 22:32:55 -05:00
- `session.session_id`
- `session.campaign`
## External adapters used
- `storage.ObjectStore` for `Exists` , `List` , `Download` .
- `artifacts.Store` (`LocalStore` ) for layout and session lock management.
- `manifest.LocalStore` for manifest decode/validation and identity checks.
## State and manifest behavior
- Restore is not a pipeline run and does not create a run manifest.
- Restore uses committed remote current state only:
- `current/run_id.txt` must exist and be non-empty.
- `current/manifest.json` must decode and match requested session/campaign.
- Non-dry-run writes restore files to canonical session paths.
2026-05-21 22:22:08 -05:00
- With `--include-audio` , restore uses the shared S3 audio cache for `audio/**` objects. Cache hits avoid object downloads; cache misses download through spool, install the work file, and populate cache.
2026-05-19 22:32:55 -05:00
- Manifest install behavior:
- validated before replacement.
- installed last among download actions.
- existing local manifest is preserved if restored manifest validation/install fails.
- Non-dry-run report persists summary/action status metadata in `reports/restore-latest.json` .
2026-05-20 15:17:04 +00:00
Restore path scope:
- includes:
- `manifest.json`
- `transcripts/**`
- `artifacts/**`
- `previous/**`
- `audio/**` only when `--include-audio` is set
- excludes:
- `runs/**`
- `logs/**`
- `reports/**`
- `config/**`
- `inputs/**`
- remote `current/**` pointer files as local restore targets
2026-05-19 22:32:55 -05:00
## Skip and resume behavior
- Restore does not participate in stage skip/resume decisions.
- Restore provides durable local state so subsequent stage commands can resume or rerun based on restored manifest state.
2026-05-21 22:22:08 -05:00
- Audio cache is outside the workspace and is reused across restore and prepare invocations.
2026-05-19 22:32:55 -05:00
- Dry-run is read-only and returns plan output only.
## Failure behavior
- Fails when storage backend is unavailable or archive identity cannot be resolved.
- Fails when remote current pointer/manifest is missing or invalid.
- Fails when remote manifest identity mismatches requested campaign/session.
- Fails on local conflicts unless `--force` is set.
- Fails fast on session lock acquisition conflict for non-dry-run execution.
- On execution failure, previously installed files remain; no rollback is performed.
## Tests to inspect before changing
- `internal/app/restore_test.go`
- `internal/app/restore_discovery_test.go`
- `internal/app/restore_plan_test.go`
- `internal/app/restore_execution_test.go`
- `internal/app/restore_workflow_test.go`
- `internal/artifacts/archive_identity_test.go`
## Architectural invariants
- Restore relies on centralized archive identity/key helpers (`internal/artifacts` ) rather than ad hoc key building.
- `current/run_id.txt` is the remote commit marker; restore must not infer committed state from incidental files.
- Local path mapping is traversal-safe and constrained to session root.
- Restore scope is deterministic and path-classified:
2026-05-20 15:17:04 +00:00
- include `manifest.json` , `transcripts/**` , `artifacts/**` , `previous/**`
2026-05-19 22:32:55 -05:00
- include `audio/**` only with `--include-audio`
- exclude `runs/**` , `logs/**` , `reports/**` , `config/**` , `inputs/**`
- Command remains standalone; no implicit `run --restore` behavior.