package app import ( "context" "testing" "gitea.maximumdirect.net/eric/narratio/internal/config" "gitea.maximumdirect.net/eric/narratio/internal/manifest" "gitea.maximumdirect.net/eric/narratio/internal/stage" ) // executeStages keeps runner tests focused on controlled stage doubles. The // production command path always supplies one validated BoundedPlan directly. func executeStages(ctx context.Context, cfg *config.Config, stages []stage.Stage, opts RunOptions) (*RunSummary, error) { plan := BoundedPlan{stages: append([]stage.Stage(nil), stages...)} return executePlan(ctx, cfg, plan, opts) } func seedCurrentSemanticEvidence(t *testing.T, cfg *config.Config, m *manifest.Manifest, names ...string) { t.Helper() providers := make(map[string]stage.SemanticConfigFingerprinter) for _, candidate := range stage.All() { if provider, ok := candidate.(stage.SemanticConfigFingerprinter); ok { providers[candidate.Name()] = provider } } for _, name := range names { record := m.Stages[name] if record == nil { t.Fatalf("stage %q must exist before semantic evidence is seeded", name) } provider, ok := providers[name] if !ok { t.Fatalf("stage %q has no semantic fingerprint provider", name) } fingerprint, err := provider.SemanticConfigFingerprint(&stage.Env{Config: cfg}) if err != nil { t.Fatalf("fingerprint stage %q: %v", name, err) } record.SemanticConfig = &fingerprint } } func loadConfigForSemanticEvidence(t *testing.T, pipelinePath, campaignPath, sessionPath string) *config.Config { t.Helper() cfg, err := config.Load(pipelinePath, campaignPath, sessionPath) if err != nil { t.Fatalf("load config for semantic evidence: %v", err) } return cfg }