Clear superseded session stage result details

This commit is contained in:
2026-08-10 02:53:28 +00:00
parent b99bd38eb4
commit b556fc2f4f
6 changed files with 127 additions and 21 deletions

View File

@@ -171,10 +171,20 @@ func TestExtractLifecycleForcedSelfSkipInvalidatesDownstream(t *testing.T) {
func TestExtractLifecycleForcedFailureInvalidatesDownstream(t *testing.T) {
cfg, env, runner := extractionLifecycleFixture(t, true)
runner.failuresRemaining = 1
markLifecycleStageSucceeded(t, cfg, "analyze")
plan, _ := BuildSingleStagePlan("extract")
first, err := executeStages(context.Background(), cfg, plan, RunOptions{Env: env})
if err != nil {
t.Fatalf("initial executeStages() error = %v", err)
}
succeeded := loadLifecycleManifest(t, cfg).Stages["extract"]
if succeeded == nil || succeeded.Status != manifest.StatusSucceeded || len(succeeded.Outputs) == 0 || len(succeeded.Logs) == 0 || len(succeeded.Metadata) == 0 {
t.Fatalf("initial extraction result = %#v, want succeeded result details", succeeded)
}
markLifecycleStageSucceeded(t, cfg, "analyze")
runner.failuresRemaining = 1
if _, err := executeStages(context.Background(), cfg, plan, RunOptions{Env: env, Force: true}); err == nil {
t.Fatal("executeStages() error = nil, want forced extraction failure")
}
@@ -185,6 +195,21 @@ func TestExtractLifecycleForcedFailureInvalidatesDownstream(t *testing.T) {
if loaded.Stages["analyze"].Error == nil || loaded.Stages["analyze"].Error.Message != staleReasonForcedReplacement {
t.Fatalf("analyze stale reason = %#v, want %q", loaded.Stages["analyze"].Error, staleReasonForcedReplacement)
}
failed := loaded.Stages["extract"]
if len(failed.Outputs) != 0 || len(failed.Logs) != 0 || len(failed.GeneratedConfigs) != 0 || len(failed.Metadata) != 0 {
t.Fatalf("failed replacement inherited extraction result details: %#v", failed)
}
historical, err := (&manifest.LocalStore{}).LoadRun(context.Background(), first.RunManifestPath)
if err != nil {
t.Fatalf("LoadRun(initial) error = %v", err)
}
historicalExtract := historical.Stages["extract"]
if historicalExtract == nil || historicalExtract.Status != manifest.StatusSucceeded || len(historicalExtract.Outputs) == 0 || len(historicalExtract.Logs) == 0 || len(historicalExtract.Metadata) == 0 {
t.Fatalf("historical extraction result = %#v, want preserved succeeded details", historicalExtract)
}
if _, err := os.Stat(succeeded.Outputs[0].LocalPath); err != nil {
t.Fatalf("durable extraction output was not preserved: %v", err)
}
}
func TestExtractLifecycleRepeatedSelfSkipPreservesSucceededDownstream(t *testing.T) {

View File

@@ -248,7 +248,6 @@ func executeStages(ctx context.Context, cfg *config.Config, stages []stage.Stage
skipped = append(skipped, s.Name())
skippedAt := nowUTC()
m.MarkStageSkipped(s.Name(), skippedAt, result.SkipReason)
clearStageResultDetails(m.Stages[s.Name()])
applyStageResultToManifest(m, s.Name(), result)
if !priorOutcome.isSameSelfSkip(result.SkipReason) {
invalidateDownstreamSucceededStagesWithReason(m, s.Name(), skippedAt, staleReasonSelfSkip)
@@ -562,15 +561,6 @@ func applyStageResultToManifest(m *manifest.Manifest, stageName string, result *
}
}
func clearStageResultDetails(sr *manifest.StageRecord) {
if sr == nil {
return
}
sr.Logs = nil
sr.GeneratedConfigs = nil
sr.Metadata = nil
}
func ensureManifestIdentity(cfg *config.Config, m *manifest.Manifest, runID string) (bool, error) {
if cfg == nil || cfg.Pipeline == nil || cfg.Session == nil || m == nil {
return false, nil

View File

@@ -742,6 +742,41 @@ func TestExecuteStagesForceRerunsSucceeded(t *testing.T) {
}
}
func TestExecuteStagesSuccessfulReplacementDoesNotInheritResultDetails(t *testing.T) {
cfg := testConfig(t)
manifestPath := manifestPathFor(cfg)
store := &manifest.LocalStore{}
existing := manifest.New(cfg.Session.SessionID, time.Date(2026, 5, 3, 1, 0, 0, 0, time.UTC))
existing.MarkStageSucceeded("transcribe", time.Date(2026, 5, 3, 1, 1, 0, 0, time.UTC), []manifest.ArtifactRecord{{
Kind: "transcript_raw", LocalPath: "transcripts/old.json",
}})
existingStage := existing.Stages["transcribe"]
existingStage.Logs = []string{"logs/old.log"}
existingStage.GeneratedConfigs = []string{"generated/old.yaml"}
existingStage.Metadata = map[string]any{"old_result": true}
if err := store.Save(context.Background(), manifestPath, existing); err != nil {
t.Fatalf("Save manifest error = %v", err)
}
runs := 0
replacement := resultStage{name: "transcribe", result: &stage.StageResult{}, runs: &runs}
if _, err := executeStages(context.Background(), cfg, []stage.Stage{replacement}, RunOptions{Force: true}); err != nil {
t.Fatalf("executeStages() error = %v", err)
}
loaded, err := store.Load(context.Background(), manifestPath)
if err != nil {
t.Fatalf("Load manifest error = %v", err)
}
record := loaded.Stages["transcribe"]
if runs != 1 || record == nil || record.Status != manifest.StatusSucceeded {
t.Fatalf("runs = %d, record = %#v, want one successful replacement", runs, record)
}
if len(record.Outputs) != 0 || len(record.Logs) != 0 || len(record.GeneratedConfigs) != 0 || len(record.Metadata) != 0 {
t.Fatalf("replacement inherited result details: %#v", record)
}
}
func TestExecuteStagesForceSuccessInvalidatesDownstreamSucceededStages(t *testing.T) {
cfg := testConfig(t)
manifestPath := manifestPathFor(cfg)