Add assembled pipeline configuration regression coverage

This commit is contained in:
2026-08-30 15:26:23 +00:00
parent 4c203d8588
commit 3da97ca50c
2 changed files with 186 additions and 1 deletions

View File

@@ -1185,7 +1185,7 @@ describe the completed feature once, at the correct canonical owners.
## Stage 22 — Assembled Workflow Regression And Final Validation ## Stage 22 — Assembled Workflow Regression And Final Validation
**Status: Pending** **Status: Completed**
### Goal ### Goal

View File

@@ -3,8 +3,11 @@ package app
import ( import (
"bytes" "bytes"
"context" "context"
"io"
"os"
"path/filepath" "path/filepath"
"reflect" "reflect"
"strings"
"testing" "testing"
"time" "time"
@@ -271,6 +274,188 @@ func TestAssembledLegacyAnalyzeTransitionPublishesOnlyCurrentRecords(t *testing.
} }
} }
func TestAssembledSplitBundleCommandsUseOneEffectiveFamilyConfiguration(t *testing.T) {
pipelinePath, campaignPath, sessionPath := assembledSplitBundlePaths()
workspacePath := filepath.Join(filepath.Dir(pipelinePath), "workspace")
if _, err := os.Stat(workspacePath); !os.IsNotExist(err) {
t.Fatalf("example workspace stat = %v, want absent", err)
}
var validated bytes.Buffer
if err := ConfigValidate(context.Background(), []string{"--config", pipelinePath, "--campaign-file", campaignPath}, &validated); err != nil {
t.Fatalf("validate production default: %v", err)
}
if !strings.Contains(validated.String(), "profile=production") {
t.Fatalf("validate output = %q, want production profile", validated.String())
}
for _, command := range []func(context.Context, []string, io.Writer) error{ConfigShow, ConfigSources} {
if err := command(context.Background(), []string{
"--config", pipelinePath, "--campaign-file", campaignPath, "--profile", "testing",
}, io.Discard); err != nil {
t.Fatalf("testing inspection command %T: %v", command, err)
}
}
var diff bytes.Buffer
if err := ConfigDiff(context.Background(), []string{
"production", "testing", "--config", pipelinePath, "--campaign-file", campaignPath,
}, &diff); err != nil {
t.Fatalf("compare profiles: %v", err)
}
if !strings.Contains(diff.String(), "audita.model") || !strings.Contains(diff.String(), "character_items_arannis.profile_id") {
t.Fatalf("profile diff = %q, want model and expanded family changes", diff.String())
}
common := []string{
"2026-05-03", "--config", pipelinePath, "--campaign-file", campaignPath,
"--session", sessionPath, "--profile", "testing",
}
var planned bytes.Buffer
if err := Plan(context.Background(), common, &planned); err != nil {
t.Fatalf("plan testing bundle: %v", err)
}
if !strings.Contains(planned.String(), "profile=testing") {
t.Fatalf("plan output = %q, want testing provenance", planned.String())
}
original := executeStagesFn
t.Cleanup(func() { executeStagesFn = original })
var capturedCfg *config.Config
var capturedPlan BoundedPlan
var capturedOptions RunOptions
executeStagesFn = func(_ context.Context, cfg *config.Config, plan BoundedPlan, options RunOptions) (*RunSummary, error) {
capturedCfg = cfg
capturedPlan = plan
capturedOptions = options
return &RunSummary{SessionID: cfg.Session.SessionID, ManifestPath: manifestPathForConfig(cfg.Pipeline.Workspace.Root)}, nil
}
runArgs := append(append([]string(nil), common...), "--from", "analyze", "--through", "analyze", "--artifacts", "character_items_arannis")
var runOut bytes.Buffer
if err := Run(context.Background(), runArgs, &runOut); err != nil {
t.Fatalf("bounded family run: %v", err)
}
if !reflect.DeepEqual(capturedPlan.Names(), []string{"analyze"}) {
t.Fatalf("bounded plan = %#v, want analyze only", capturedPlan.Names())
}
if profile, ok := config.SelectedPipelineProfile(capturedCfg.Pipeline); !ok || profile.Name != "testing" {
t.Fatalf("captured profile = %#v, selected=%t", profile, ok)
}
if digest := config.EffectivePipelineDigest(capturedCfg.Pipeline); digest == "" || !strings.Contains(runOut.String(), "digest="+digest) {
t.Fatalf("run output = %q, want effective digest %q", runOut.String(), digest)
}
if got := capturedOptions.EffectiveArtifacts.Keys(); !reflect.DeepEqual(got, []string{"character_items_arannis"}) {
t.Fatalf("effective artifact keys = %#v", got)
}
if origin, ok := capturedOptions.EffectiveArtifacts.Origin("character_items_arannis"); !ok || origin.Family != "character_items" || origin.CharacterID != "arannis" {
t.Fatalf("family origin = %#v, present=%t", origin, ok)
}
fullFamily, err := resolveEffectiveArtifacts(capturedCfg, []string{"character_items"})
if err != nil {
t.Fatalf("resolve complete family: %v", err)
}
if got := fullFamily.Keys(); !reflect.DeepEqual(got, []string{"character_items_arannis", "character_items_brenna"}) {
t.Fatalf("full family keys = %#v", got)
}
if _, err := os.Stat(workspacePath); !os.IsNotExist(err) {
t.Fatalf("inspection or bounded run created example workspace: %v", err)
}
}
func TestAssembledSplitBundleProfileSwitchRecordsProvenanceAndLimitsReuse(t *testing.T) {
production := loadAssembledSplitBundleConfig(t, "")
testingCfg := loadAssembledSplitBundleConfig(t, "testing")
workspace := t.TempDir()
production.Pipeline.Workspace.Root = workspace
testingCfg.Pipeline.Workspace.Root = workspace
names := []string{"prepare", "transcribe", "merge", "polish", "normalize", "trim", "render"}
providers := make([]stage.SemanticConfigFingerprinter, len(names))
seed := manifest.New(production.Session.SessionID, time.Now().UTC())
seed.Campaign = production.Session.Campaign
for _, candidate := range stage.All() {
seed.MarkStageSucceeded(candidate.Name(), time.Now().UTC(), nil)
}
for index, name := range names {
providers[index] = canonicalSemanticProvider(t, name)
fingerprint, err := providers[index].SemanticConfigFingerprint(&stage.Env{Config: production})
if err != nil {
t.Fatalf("production %s fingerprint: %v", name, err)
}
seed.Stages[name].SemanticConfig = &fingerprint
}
store := &manifest.LocalStore{}
if err := store.Save(context.Background(), manifestPathForConfig(workspace), seed); err != nil {
t.Fatal(err)
}
productionRuns := make([]int, len(names))
productionStages := assembledSemanticStages(names, providers, productionRuns)
productionSummary, err := executeStages(context.Background(), production, productionStages, RunOptions{})
if err != nil {
t.Fatalf("record production provenance: %v", err)
}
if !reflect.DeepEqual(productionRuns, make([]int, len(names))) {
t.Fatalf("production runs = %v, want complete reuse", productionRuns)
}
assertAssembledProvenance(t, store, productionSummary, "production", config.EffectivePipelineDigest(production.Pipeline))
testingRuns := make([]int, len(names))
testingStages := assembledSemanticStages(names, providers, testingRuns)
testingSummary, err := executeStages(context.Background(), testingCfg, testingStages, RunOptions{})
if err != nil {
t.Fatalf("switch to testing profile: %v", err)
}
if got, want := testingRuns, []int{0, 0, 0, 1, 1, 1, 1}; !reflect.DeepEqual(got, want) {
t.Fatalf("testing profile runs = %v, want %v", got, want)
}
assertAssembledProvenance(t, store, testingSummary, "testing", config.EffectivePipelineDigest(testingCfg.Pipeline))
}
func assembledSplitBundlePaths() (pipelinePath, campaignPath, sessionPath string) {
examplesDir := filepath.Join("..", "..", "examples")
return filepath.Join(examplesDir, "production-testing", "pipeline.yml"),
filepath.Join(examplesDir, "campaigns", "sample-campaign", "campaign.yml"),
filepath.Join(examplesDir, "session.local-audio.yml")
}
func loadAssembledSplitBundleConfig(t *testing.T, profile string) *config.Config {
t.Helper()
pipelinePath, campaignPath, sessionPath := assembledSplitBundlePaths()
options := config.SessionLoadOptions{}
if profile != "" {
options.Profile = &profile
}
cfg, err := config.LoadWithSessionOptions(pipelinePath, campaignPath, sessionPath, options)
if err != nil {
t.Fatalf("load split bundle profile %q: %v", profile, err)
}
return cfg
}
func assembledSemanticStages(names []string, providers []stage.SemanticConfigFingerprinter, runs []int) []stage.Stage {
stages := make([]stage.Stage, 0, len(names))
for index, name := range names {
stages = append(stages, semanticContractRunStub{name: name, provider: providers[index], runs: &runs[index]})
}
return stages
}
func assertAssembledProvenance(t *testing.T, store *manifest.LocalStore, summary *RunSummary, profile, digest string) {
t.Helper()
session, err := store.Load(context.Background(), summary.ManifestPath)
if err != nil {
t.Fatal(err)
}
run, err := store.LoadRun(context.Background(), summary.RunManifestPath)
if err != nil {
t.Fatal(err)
}
for _, value := range []*manifest.EffectiveConfigProvenance{session.EffectiveConfig, run.EffectiveConfig} {
if value == nil || value.SelectedProfile == nil || value.SelectedProfile.Name != profile || value.EffectiveConfigDigest != digest {
t.Fatalf("effective configuration provenance = %#v, want profile=%q digest=%q", value, profile, digest)
}
}
}
func seedAllStagesSucceeded(t *testing.T, cfg *config.Config) { func seedAllStagesSucceeded(t *testing.T, cfg *config.Config) {
t.Helper() t.Helper()
m := manifest.New(cfg.Session.SessionID, time.Now().UTC()) m := manifest.New(cfg.Session.SessionID, time.Now().UTC())