Files
narratio/docs/internal/command-restore.md

4.2 KiB

Internal: Command Restore

Purpose

Explain the implemented restore discovery, planning, installation, and reporting flow in internal/app. User invocation belongs in CLI, and the operator recovery procedure and physical restore scope belong in Operations.

Restore separates remote authority, local conflict policy, and filesystem mutation so each remains testable independently.

Discovery Contract

Discovery delegates current-state pointer and manifest loading to internal/artifacts, then validates the result against the resolved request:

  • campaign must match;
  • session ID must match.
  • run ID must match the pointer-selected committed run.

Restore treats any missing or invalid remote current state as a command error.

Planning Contract

Restore planner action kinds:

  • download;
  • skip_same;
  • conflict.

Planner behavior:

  • a new-protocol restore uses only the selected commit's declared artifact set; each action carries that artifact's immutable key, checksum, size, and generation. Coherent legacy state remains on the isolated compatibility path;
  • remote-to-local mapping is traversal-safe;
  • actions are sorted by local relative path and then remote key;
  • force converts differing eligible regular files from conflicts to downloads; directories and other non-regular targets remain conflicts.

For a non-dry-run restore, planning/classification happens only after acquiring the session lock. Runner manifest/reuse checks acquire that same lock first.

Previous-cache files are planned separately through previouscache.BuildPlan when configured previous-session requirements exist.

Execution Contract

Execution order and safety:

  • non-manifest downloads happen before manifest install;
  • manifest.json installs last;
  • downloads use sibling temp files plus atomic rename;
  • manifest replacement is validated before rename;
  • each committed object is verified against its declared checksum, size, and generation before installation;
  • failed installs do not roll back files already written in the same execution.
  • a durable .restore-incomplete.json marker is written before installation. It blocks runners until a restore retry completes all verified installs and the local manifest replacement, at which point it is removed.
  • restored manifest local references are rebased beneath the selected local session root. Unsafe relative references and producer-machine absolute paths outside the manifest's producer session root are rejected; producer-local spool/cache and cleanup locations are not restored as authority.

Audio restore path:

  • uses audio.MaterializeS3Audio;
  • integrates spool and S3 audio cache paths;
  • reuses cached audio only when its no-follow regular file, content digest, and identity sidecar all match the selected remote object version; otherwise it refreshes through the durable download path.

Reporting Contract

  • dry-run mode prints a summary and performs no local writes;
  • execution mode persists the canonical restore report described in Operations;
  • report includes plan counts, per-action status, and execution failures.

Invariants

  • restore uses committed remote current state as authority;
  • one restore or status inspection observes the single pointer-selected commit loaded at discovery; later pointer changes cannot add objects or substitute a different run into its plan;
  • a verified current/commit-pointer.json and its selected immutable commit establish new-protocol remote commitment; coherent legacy current/run_id.txt plus current/manifest.json remains read-only migration support;
  • restore does not execute pipeline stages.

Implementation And Tests

  • Discovery: internal/app/restore_discovery.go
  • Planning: internal/app/restore_plan.go, internal/previouscache
  • Execution: internal/app/restore_execute.go
  • Reporting and command coordination: internal/app/restore_report.go, internal/app/restore.go
  • Tests: internal/app/restore_discovery_test.go, internal/app/restore_plan_test.go, internal/app/restore_execution_test.go, internal/app/restore_workflow_test.go