Integrate previous-session artifact hydration into prepare stage

This commit is contained in:
2026-05-20 14:53:22 +00:00
parent 2b08c34539
commit 2ca700195c
4 changed files with 307 additions and 6 deletions

View File

@@ -145,6 +145,20 @@ func (prepareStage) Run(ctx context.Context, env *Env, m *manifest.Manifest) (*S
}
}
previousRequirements := collectPreparePreviousRequirements(env.Config)
var previousHydration *previousSessionHydrationResult
if len(previousRequirements) > 0 {
if err := clearManagedPreviousState(paths); err != nil {
return nil, fmt.Errorf("prepare: clear previous-session cache: %w", err)
}
hydration, err := hydratePreviousSessionArtifacts(ctx, env, paths, previousRequirements)
if err != nil {
return nil, fmt.Errorf("prepare: hydrate previous-session artifacts: %w", err)
}
previousHydration = hydration
inputs = append(inputs, hydration.Inputs...)
}
sort.Slice(inputs, func(i, j int) bool {
if inputs[i].Kind != inputs[j].Kind {
return inputs[i].Kind < inputs[j].Kind
@@ -153,13 +167,27 @@ func (prepareStage) Run(ctx context.Context, env *Env, m *manifest.Manifest) (*S
})
m.Inputs = inputs
metadata := map[string]any{
"prepared": true,
"stage": "prepare",
"inputs_count": len(inputs),
"audio_files_resolved": countAudioInputs(inputs),
}
if len(previousRequirements) > 0 {
metadata["previous_requirements_count"] = len(previousRequirements)
if previousHydration != nil {
metadata["previous_artifacts_hydrated"] = append([]string(nil), previousHydration.Hydrated...)
metadata["previous_artifacts_hydrated_count"] = len(previousHydration.Hydrated)
metadata["previous_artifacts_missing_optional"] = append([]string(nil), previousHydration.SkippedMissing...)
metadata["previous_artifacts_missing_optional_count"] = len(previousHydration.SkippedMissing)
if strings.TrimSpace(previousHydration.PreviousRunID) != "" {
metadata["previous_session_run_id"] = strings.TrimSpace(previousHydration.PreviousRunID)
}
}
}
return &StageResult{
Metadata: map[string]any{
"prepared": true,
"stage": "prepare",
"inputs_count": len(inputs),
"audio_files_resolved": countAudioInputs(inputs),
},
Metadata: metadata,
}, nil
}
@@ -354,6 +382,35 @@ func countAudioInputs(inputs []manifest.InputRecord) int {
return count
}
func collectPreparePreviousRequirements(cfg *config.Config) []artifacts.PreviousArtifactRequirement {
if cfg == nil || cfg.Pipeline == nil || cfg.Pipeline.Scriptorium == nil {
return nil
}
return artifacts.CollectPreviousArtifactRequirements(cfg.Pipeline.Scriptorium.Artifacts)
}
func clearManagedPreviousState(paths artifacts.SessionPaths) error {
previousDir := filepath.Clean(paths.PreviousDir)
sessionRoot := filepath.Clean(paths.Root)
if strings.TrimSpace(previousDir) == "" || strings.TrimSpace(sessionRoot) == "" {
return fmt.Errorf("previous/session root paths are required")
}
if previousDir == sessionRoot {
return fmt.Errorf("refusing to clear session root as previous cache: %q", previousDir)
}
prefix := sessionRoot + string(filepath.Separator)
if !strings.HasPrefix(previousDir, prefix) {
return fmt.Errorf("refusing to clear path outside session root: %q", previousDir)
}
if filepath.Base(previousDir) != config.PathPreviousDirSegment {
return fmt.Errorf("refusing to clear non-previous path %q", previousDir)
}
if err := os.RemoveAll(previousDir); err != nil {
return err
}
return os.MkdirAll(previousDir, 0o755)
}
func pathsWorkDirForManifest(env *Env, m *manifest.Manifest, sessionID string) string {
if env == nil || env.Config == nil || env.Config.Pipeline == nil || env.Config.Session == nil {
return ""