107 lines
4.8 KiB
Markdown
107 lines
4.8 KiB
Markdown
# Internal: Command Restore
|
|
|
|
## Purpose
|
|
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 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`).
|
|
|
|
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.
|
|
- `pipeline.spool.root` for active audio downloads.
|
|
- `pipeline.cache.root` and `pipeline.cache.s3_audio` for reusable S3 audio cache.
|
|
- `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.
|
|
- 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.
|
|
- 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`.
|
|
|
|
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
|
|
|
|
## 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.
|
|
- Audio cache is outside the workspace and is reused across restore and prepare invocations.
|
|
- 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:
|
|
- include `manifest.json`, `transcripts/**`, `artifacts/**`, `previous/**`
|
|
- include `audio/**` only with `--include-audio`
|
|
- exclude `runs/**`, `logs/**`, `reports/**`, `config/**`, `inputs/**`
|
|
- Command remains standalone; no implicit `run --restore` behavior.
|