From 01eb7aa1aa1cfbaf30561dc23280e49cd14f48b0 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Wed, 20 May 2026 14:55:44 +0000 Subject: [PATCH] Add prepare rerun guidance for unresolved previous-session analyze inputs --- internal/stage/analyze.go | 9 +++++++++ internal/stage/analyze_test.go | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/internal/stage/analyze.go b/internal/stage/analyze.go index 19e0fac..d5d5fb3 100644 --- a/internal/stage/analyze.go +++ b/internal/stage/analyze.go @@ -631,6 +631,15 @@ func resolveScriptoriumInput( runtimeCatalog *artifacts.ArtifactCatalog, ) (string, bool, *artifacts.ResolvedSessionArtifact, error) { source := strings.TrimSpace(inputCfg.Source) + if artifacts.IsPreviousSessionArtifactSource(source) { + if inputCfg.Required { + return "", false, nil, fmt.Errorf( + "required previous-session input source %q is unavailable; run narratio run-stage --force prepare", + source, + ) + } + return "", false, nil, nil + } switch source { case "previous_session_artifact": if strings.TrimSpace(inputCfg.Path) == "" { diff --git a/internal/stage/analyze_test.go b/internal/stage/analyze_test.go index fea4ea6..88c0391 100644 --- a/internal/stage/analyze_test.go +++ b/internal/stage/analyze_test.go @@ -717,6 +717,25 @@ func TestAnalyzeOmitsOptionalMissingConfiguredArtifactInput(t *testing.T) { } } +func TestAnalyzeRequiredPreviousSessionArtifactInputGuidesPrepareForce(t *testing.T) { + env, m, _ := setupAnalyzeEnv(t) + + sessionRecap := env.Config.Pipeline.Scriptorium.Artifacts["session_recap"] + sessionRecap.Inputs["previous_recap"] = config.ScriptoriumInputConfig{ + Source: "narratio.previous_session.artifact.session_recap", + Required: true, + } + env.Config.Pipeline.Scriptorium.Artifacts["session_recap"] = sessionRecap + + _, err := (analyzeStage{}).Run(context.Background(), env, m) + if err == nil { + t.Fatal("expected error, got nil") + } + if !strings.Contains(err.Error(), "run narratio run-stage --force prepare") { + t.Fatalf("error = %q, want guidance to run force prepare", err.Error()) + } +} + func TestAnalyzeFailsWhenOutputPathMissing(t *testing.T) { env, m, fake := setupAnalyzeEnv(t) paths := sessionPathsForEnv(env, m.SessionID)