This roadmap describes the implementation strategy for first-class previous-session artifact support in Narratio. It belongs under `docs/roadmap/previous.md` until the feature is implemented. After implementation, current behavior should be documented in the appropriate user-facing and internal documentation files, and this roadmap should be removed or marked complete according to the documentation policy.
## Summary
Narratio should support using artifacts from a previous session as inputs to artifacts generated for the current session.
The primary use case is session recap continuity: a current session recap should be able to consume the previous session recap. The design should support arbitrary previous-session artifacts from the start, not just `session_recap`.
Previous-session artifacts are materialized during the `prepare` stage into a current-session top-level `previous/` directory. Downstream stages consume only the local `previous/` copies. The S3 backend is authoritative for previous-session state.
## Design Decisions
### 1. Add `previous_session_id` to `session.yml`
Add an optional top-level session key:
```yaml
session_id: "{{ session_id }}"
previous_session_id: "{{ previous_session_id }}"
campaign: sample-campaign
```
Rules:
-`previous_session_id` is optional.
- If present, it identifies the previous session within the same campaign.
- It must not equal `session_id`.
- It should use the same validation rules as `session_id`.
- It may be supplied through session templating.
- Add a CLI/template value such as `--previous-session-id <id>` if required by the existing session templating implementation.
- If a template placeholder for `previous_session_id` is present and no value is supplied, loading should fail with a clear unresolved-template error.
### 2. Use canonical previous-session artifact source IDs
Support this source pattern in Scriptorium artifact input definitions:
-`<artifact_name>` must be a valid configured artifact key.
- Use the same artifact key validation rules as current-session runtime artifacts.
- Do not special-case `session_recap`.
- Do not limit implementation to a fixed list of previous artifacts.
### 3. Add a top-level `previous/` workspace directory
Extend the session workspace layout with:
```text
previous/
manifest.json
artifacts/
<artifact outputs copied from the previous session>
```
The `previous/` directory is current-session state. It is a prepared input cache, not a full mirror of the previous session workspace.
Conceptually:
```text
work/<campaign>/<current_session_id>/
previous/
manifest.json
artifacts/
session_recap.md
quest_log.json
```
The current session should not read directly from the previous session's local workspace during ordinary operation.
### 4. S3 is authoritative for previous-session state
For this initial implementation, previous-session artifacts should be downloaded from the configured S3 backend.
Do not compare local and remote copies.
Do not prefer local previous-session workspace state.
Do not implement a `--local` override in this roadmap. That can be considered later.
The simplified stage behavior is:
1. If the local manifest indicates `prepare` already succeeded and `--force` is not supplied, the runner skips `prepare`. No previous-session download occurs.
2. If `prepare` has not succeeded, `prepare` runs and downloads referenced previous-session artifacts from S3.
3. If `prepare` previously succeeded but `--force` is supplied, `prepare` runs again and overwrites local `previous/` state from S3.
### 5. Materialize only referenced previous-session artifacts
During `prepare`, scan the current resolved pipeline/session configuration for Scriptorium artifact inputs whose source matches:
Only those referenced previous-session artifacts need to be downloaded.
Do not blindly download every previous-session artifact.
If no previous-session artifact sources are referenced, `prepare` should not require `previous_session_id` and should not touch `previous/`.
### 6. Preserve stage boundaries
`prepare` owns previous-session artifact materialization because these files are inputs to later stages.
`analyze` should not talk to S3.
The Scriptorium adapter should not know about previous sessions.
The storage adapter should not infer campaign, session, run, or root-prefix semantics. Callers should continue to provide explicit bucket-relative keys.
### 7. Archive and restore `previous/`
After implementation:
-`archive` should include `previous/` as durable current-session prepared input state.
-`restore` should restore `previous/` along with the rest of the durable session state it already restores.
-`previous/` should not be treated as current-session generated artifacts.
-`previous/` entries should be recorded as inputs/provenance, not as outputs produced by the current session.
Implement a narrow service/helper used by `prepare` to resolve previous-session artifact files from S3.
Responsibilities:
1. Locate the previous session's current remote state.
2. Download the previous session manifest, or the minimum remote metadata needed to resolve artifact source IDs.
3. Resolve `narratio.artifact.<name>` inside the previous session's artifact catalog/manifest.
4. Download the resolved artifact into the current session's `previous/` directory.
5. Download/store the previous session manifest as `previous/manifest.json`.
6. Return provenance records for manifest input recording.
Important archive invariant:
- Remote current state must be based on the committed archive marker.
- Do not treat incomplete archive uploads as current state.
- Use the existing archive/current remote layout and commit-marker rules.
-`current/run_id.txt` is the final remote commit marker and should be respected when locating current remote state.
Do not put prefix semantics into the storage adapter. Compute explicit bucket-relative keys in app/stage/archive helper code, then call the storage adapter.
Required vs optional behavior:
- Required previous artifact missing from S3/current manifest: fail `prepare`.
- Optional previous artifact missing from S3/current manifest: continue without materializing that input.
- Previous session missing entirely:
- fail if any referenced previous artifact is required;
- continue if all referenced previous artifacts are optional.
- If previous_session_id is unset:
- fail if any referenced previous artifact is required;
- continue and omit all previous-session inputs if all are optional.
Validation behavior:
- Downloaded artifacts should pass the same validation rules as current-session artifacts where practical.
- Generic Scriptorium artifacts should at least be non-empty.
- Invalid required artifact: fail.
- Invalid optional artifact: prefer fail if the object exists but is invalid, because invalid archived data is usually an operator problem rather than absence.
Tests:
- downloads previous manifest;
- downloads required previous artifact;
- skips missing optional previous artifact;
- fails missing required previous artifact;
- fails required previous artifact when previous_session_id is unset;
- optional previous artifact with no previous_session_id does not fail;
- respects current remote commit marker;
- does not use local previous-session workspace state;
- uses storage adapter with explicit keys.
### Phase 6: Integrate with `prepare`
Extend the `prepare` stage:
1. Run existing input materialization as before.
2. Detect previous-session artifact requirements.
3. If requirements exist, hydrate `previous/` from S3 according to the rules above.
4. Record hydrated previous artifacts in `manifest.Inputs`.
5. Preserve existing prepare outputs and provenance behavior.
Overwrite behavior:
- If `prepare` runs, it owns `previous/`.
- Before hydrating, clear the managed `previous/` directory, or clear the managed previous artifact paths.
- Prefer clearing the whole `previous/` directory if no other feature writes there.
- Under `--force`, this naturally overwrites local `previous/` state.
- Do not compare local and remote copies.
Skip behavior:
- Do not add stage-local skip logic.
- Runner-level skip remains authoritative.
- If the manifest says `prepare` succeeded and `--force` is not supplied, `prepare` does not run and no S3 downloads occur.
- If users add a new previous-session input after `prepare` already succeeded, they must rerun prepare with `--force`.
Error message requirement:
If an analyze-stage input cannot be resolved because `previous/` is missing or stale, the error should tell the operator to run:
```bash
narratio run-stage --force prepare
```
or the appropriate existing CLI command shape.
Tests:
- ordinary prepare without previous_session_id remains unchanged;
- prepare with optional previous artifact and no previous_session_id succeeds;
- prepare with required previous artifact and no previous_session_id fails;
- prepare with required previous artifact downloads to `previous/`;
- force prepare overwrites `previous/`;
- prepare records manifest inputs for previous artifacts;
- prepare skip behavior remains controlled by runner tests;
- no regression in S3 audio prepare behavior.
### Phase 7: Artifact resolver support
Update artifact resolution so Scriptorium inputs can resolve:
- optional previous recap omitted when not prepared;
- required previous recap fails when not prepared;
- render-debug path works with previous-session inputs;
- no S3 calls occur from analyze.
### Phase 9: Archive `previous/`
Update archive behavior so the current session's durable `previous/` directory is uploaded/preserved.
Rules:
-`previous/` is current-session input/provenance state.
- It is not a generated current-session artifact.
- Archive it with the current session's durable state, alongside other durable session files according to the current archive layout.
- Preserve existing archive commit ordering.
- Do not make `previous/` upload the final commit marker.
- Do not treat missing `previous/` as an error when no previous-session inputs were prepared.
Tests:
- archive includes `previous/manifest.json` and prepared previous artifacts when present;
- archive omits or tolerates absent `previous/` when unused;
- archive commit ordering remains valid;
- cleanup behavior does not delete durable `previous/` before archive commit.
### Phase 10: Restore `previous/`
Update `narratio restore` so it restores the current session's archived `previous/` directory.
Rules:
- Restore `previous/` as durable current-session state.
- Do not infer or restore the previous session workspace merely because `previous_session_id` exists.
- Do not redownload previous-session artifacts from the previous session archive during restore; restore the current session's archived `previous/` cache.
- Respect existing restore flags and overwrite behavior.
Tests:
- restore downloads `previous/` when present;
- restore succeeds when `previous/` is absent;
- restore with force overwrites local `previous/` according to existing restore semantics;
- restored current session can run analyze using `previous/` without needing previous session archive access.
### Phase 11: Documentation updates after implementation
After implementation, update current-behavior docs. Do not document implemented behavior only in this roadmap.
Likely files:
-`docs/config.md`
-`docs/cli.md`
-`docs/operations.md`
-`docs/internal/stage-prepare.md`
-`docs/internal/artifacts.md`
-`docs/internal/storage.md` only if storage contracts change