From 97e5739bfb4e868b1d84be1a8bd932465399dc20 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Thu, 5 Nov 2026 19:57:13 +0000 Subject: [PATCH] Update tests for captured repository lookups --- docs/roadmap/implementation.md | 4 ++ internal/usecase/profile_inspection_test.go | 5 ++ internal/usecase/prompt_inspection_test.go | 38 ++++++++----- .../usecase/requirements_inspection_test.go | 45 +++------------ internal/usecase/runner_test.go | 55 +++++++++++++++++-- internal/usecase/smoke_selection_test.go | 4 ++ 6 files changed, 94 insertions(+), 57 deletions(-) diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index 3921ba5..91f184b 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -145,6 +145,10 @@ Use-case tests may remain uncompilable until Stage 4; no transitional fallback i ## Stage 4: Migrate Repository Fixtures And Inspection Tests +**Completed:** Private repositories now supply captured lookup operations and +inspection tests cover captured hashes, metadata, identities, and errors. Go +1.27.3 `go test ./internal/configuration ./internal/usecase` passed. + **Finding:** 3. **Scope:** private repository fixtures in use-case tests and affected configuration tests. 1. Update small repository fixtures to supply captured hashes, metadata, and diff --git a/internal/usecase/profile_inspection_test.go b/internal/usecase/profile_inspection_test.go index 35786c0..37d26eb 100644 --- a/internal/usecase/profile_inspection_test.go +++ b/internal/usecase/profile_inspection_test.go @@ -26,6 +26,11 @@ func (r *inspectionProfileRepository) GetProfile(_ context.Context, id string) ( return r.profile, nil } +func (r *inspectionProfileRepository) GetProfileIdentity(ctx context.Context, id string) (string, error) { + _, err := r.GetProfile(ctx, id) + return id, err +} + func TestRunnerInspectProfileUsesExactSnapshotAndCopiesTarget(t *testing.T) { configured := domain.ExecutionTarget{ BackendID: "backend", Endpoint: "https://backend.example/v1", Model: "model", diff --git a/internal/usecase/prompt_inspection_test.go b/internal/usecase/prompt_inspection_test.go index a417a96..5e21b33 100644 --- a/internal/usecase/prompt_inspection_test.go +++ b/internal/usecase/prompt_inspection_test.go @@ -7,6 +7,7 @@ import ( "testing" "go.maximumdirect.net/promptkit/internal/domain" + "go.maximumdirect.net/promptkit/internal/prompt" "go.maximumdirect.net/promptkit/internal/promptdef" ) @@ -23,20 +24,33 @@ type promptMetadataRepository struct { lookupID string } -func (r *inspectionPromptRepository) GetPromptDefinition( +func (r *inspectionPromptRepository) GetPromptSnapshot( _ context.Context, id string, -) (*domain.PromptDefinition, error) { +) (*domain.PromptDefinition, string, error) { r.calls++ r.id = id if r.err != nil { - return nil, r.err + return nil, "", r.err } - return r.definition, nil + return r.definition, "captured-hash", nil } -func (r *promptMetadataRepository) GetPromptDefinition(context.Context, string) (*domain.PromptDefinition, error) { - return nil, errors.New("full prompt definition should not be requested") +func (r *inspectionPromptRepository) GetPromptInspection(ctx context.Context, id string) (*domain.PromptInspection, error) { + definition, hash, err := r.GetPromptSnapshot(ctx, id) + return fixturePromptInspection(definition, hash), err +} + +func (*inspectionPromptRepository) GetRequirementSnapshot(string) (prompt.RequirementSnapshot, bool) { + return prompt.RequirementSnapshot{}, false +} + +func (r *promptMetadataRepository) GetPromptSnapshot(context.Context, string) (*domain.PromptDefinition, string, error) { + return nil, "", errors.New("full prompt definition should not be requested") +} + +func (*promptMetadataRepository) GetRequirementSnapshot(string) (prompt.RequirementSnapshot, bool) { + return prompt.RequirementSnapshot{}, false } func (r *promptMetadataRepository) GetPromptInspection( @@ -71,15 +85,11 @@ func TestRunnerInspectPromptResolvesOneDefinitionWithoutExecutionCollaborators(t if err != nil { t.Fatalf("inspect prompt: %v", err) } - wantHash, err := hashPromptDefinition(definition) - if err != nil { - t.Fatalf("hash prompt definition: %v", err) - } if repository.calls != 1 || repository.id != " prompt-id " { t.Fatalf("prompt lookup=(calls=%d id=%q), want one unchanged ID lookup", repository.calls, repository.id) } if inspection.PromptID != definition.ID || - inspection.PromptHash != wantHash || + inspection.PromptHash != "captured-hash" || inspection.DefaultProfileID != definition.DefaultProfile || !reflect.DeepEqual(inspection.Inputs, definition.Inputs) || inspection.OutputContract != definition.Validation { @@ -96,7 +106,7 @@ func TestRunnerInspectPromptResolvesOneDefinitionWithoutExecutionCollaborators(t } } -func TestRunnerInspectPromptUsesOwnedMetadataWhenRepositorySupportsIt(t *testing.T) { +func TestRunnerInspectPromptUsesOwnedCapturedMetadata(t *testing.T) { repository := &promptMetadataRepository{inspection: domain.PromptInspection{ PromptID: "captured.prompt", PromptHash: "cached-prompt-hash", DefaultProfileID: "partial-profile", @@ -119,7 +129,7 @@ func TestRunnerInspectPromptUsesOwnedMetadataWhenRepositorySupportsIt(t *testing } } -func TestRunnerInspectPromptUsesCapturedHashWhenMetadataCapabilityIsAbsent(t *testing.T) { +func TestRunnerInspectPromptUsesCapturedHashAndMetadata(t *testing.T) { repository := &requirementInspectionPromptRepository{ definition: &domain.PromptDefinition{ ID: "captured.prompt", Inputs: []domain.PromptInput{{Name: "document"}}, @@ -128,7 +138,7 @@ func TestRunnerInspectPromptUsesCapturedHashWhenMetadataCapabilityIsAbsent(t *te inspection, err := (&Runner{promptDefs: repository}).InspectPrompt(context.Background(), " requested-id ") if err != nil || inspection.PromptID != "captured.prompt" || inspection.PromptHash != "captured-hash" || inspection.Inputs[0].Name != "document" { - t.Fatalf("captured-hash fallback inspection=(%+v, %v)", inspection, err) + t.Fatalf("captured inspection=(%+v, %v)", inspection, err) } } diff --git a/internal/usecase/requirements_inspection_test.go b/internal/usecase/requirements_inspection_test.go index 9744472..3714b11 100644 --- a/internal/usecase/requirements_inspection_test.go +++ b/internal/usecase/requirements_inspection_test.go @@ -45,13 +45,6 @@ func (repository *inspectionProfileIdentityRepository) GetProfileIdentity( return repository.identity, repository.identityErr } -func (repository *requirementInspectionPromptRepository) GetPromptDefinition( - context.Context, - string, -) (*domain.PromptDefinition, error) { - return repository.definition, repository.lookupErr -} - func (repository *requirementPromptMetadataRepository) GetPromptInspection( _ context.Context, id string, @@ -71,6 +64,11 @@ func (repository *requirementInspectionPromptRepository) GetPromptSnapshot( return repository.definition, "captured-hash", repository.lookupErr } +func (repository *requirementInspectionPromptRepository) GetPromptInspection(ctx context.Context, id string) (*domain.PromptInspection, error) { + definition, hash, err := repository.GetPromptSnapshot(ctx, id) + return fixturePromptInspection(definition, hash), err +} + func (repository *requirementInspectionPromptRepository) GetRequirementSnapshot( id string, ) (prompt.RequirementSnapshot, bool) { @@ -163,7 +161,7 @@ func TestRunnerInspectRequirementsUsesPromptMetadataAndExactRequirementSnapshot( } } -func TestRunnerInspectRequirementsUsesProfileIdentityCapabilityOrFallback(t *testing.T) { +func TestRunnerInspectRequirementsUsesProfileIdentity(t *testing.T) { message, err := prompt.CompileTemplate("message", `{{.name}}`) if err != nil { t.Fatal(err) @@ -177,7 +175,7 @@ func TestRunnerInspectRequirementsUsesProfileIdentityCapabilityOrFallback(t *tes } requestedID := " literal-profile " - t.Run("optional capability", func(t *testing.T) { + t.Run("identity lookup", func(t *testing.T) { profiles := &inspectionProfileIdentityRepository{ inspectionProfileRepository: &inspectionProfileRepository{profile: &domain.ExecutionProfile{ ID: "repository-profile", ResolvedTarget: &domain.ExecutionTarget{}, @@ -196,21 +194,7 @@ func TestRunnerInspectRequirementsUsesProfileIdentityCapabilityOrFallback(t *tes } }) - t.Run("full-profile fallback", func(t *testing.T) { - profiles := &inspectionProfileRepository{profile: &domain.ExecutionProfile{ - ID: "repository-profile", ResolvedTarget: &domain.ExecutionTarget{}, - }} - inspection, err := (&Runner{promptDefs: makePromptRepository(), profiles: profiles}).InspectRequirements( - context.Background(), RequirementInspectionRequest{ - PromptID: "selected", ProfileID: requestedID, Vars: map[string]string{"name": "Ada"}, - }, - ) - if err != nil || inspection.ProfileID != requestedID || profiles.calls != 1 || profiles.id != requestedID { - t.Fatalf("fallback inspection=(%+v, %v), full lookup=(%d,%q)", inspection, err, profiles.calls, profiles.id) - } - }) - - t.Run("capability failure", func(t *testing.T) { + t.Run("identity failure", func(t *testing.T) { lookupErr := errors.New("profile identity lookup failed") profiles := &inspectionProfileIdentityRepository{ inspectionProfileRepository: &inspectionProfileRepository{}, @@ -329,14 +313,6 @@ func TestRunnerInspectRequirementsClassifiesSelectionAndSnapshotFailures(t *test } }) - t.Run("repository lacks snapshot capability", func(t *testing.T) { - _, err := (&Runner{promptDefs: &inspectionPromptRepository{definition: &domain.PromptDefinition{ID: "selected", DefaultProfile: "profile"}}, - profiles: &inspectionProfileRepository{profile: &domain.ExecutionProfile{ID: "profile", ResolvedTarget: &domain.ExecutionTarget{}}}, - }).InspectRequirements(context.Background(), RequirementInspectionRequest{PromptID: "selected"}) - if !errors.Is(err, ErrPromptLoad) { - t.Fatalf("missing capability error=%v", err) - } - }) if _, err := (*Runner)(nil).InspectRequirements(context.Background(), RequirementInspectionRequest{PromptID: "selected"}); !errors.Is(err, ErrPromptLoad) { t.Fatalf("nil runner error=%v", err) } @@ -348,11 +324,6 @@ func TestRunnerInspectRequirementsClassifiesSelectionAndSnapshotFailures(t *test ); !errors.Is(err, ErrProfileLoad) { t.Fatalf("missing profile error=%v", err) } - if _, err := (&Runner{promptDefs: &requirementInspectionPromptRepository{definition: &domain.PromptDefinition{ID: "selected", DefaultProfile: "profile"}}, - profiles: &inspectionProfileRepository{profile: &domain.ExecutionProfile{ID: "profile"}}, - }).InspectRequirements(context.Background(), RequirementInspectionRequest{PromptID: "selected"}); !errors.Is(err, ErrProfileLoad) { - t.Fatalf("unresolved profile error=%v", err) - } if _, err := (&Runner{promptDefs: &requirementInspectionPromptRepository{lookupErr: promptdef.ErrPromptDefinitionNotFound}}).InspectRequirements( context.Background(), RequirementInspectionRequest{PromptID: "missing"}, ); !errors.Is(err, ErrPromptLoad) || !errors.Is(err, promptdef.ErrPromptDefinitionNotFound) { diff --git a/internal/usecase/runner_test.go b/internal/usecase/runner_test.go index 67197e5..07d3c01 100644 --- a/internal/usecase/runner_test.go +++ b/internal/usecase/runner_test.go @@ -21,6 +21,7 @@ import ( "go.maximumdirect.net/promptkit/internal/generation" "go.maximumdirect.net/promptkit/internal/llm" "go.maximumdirect.net/promptkit/internal/prompt" + "go.maximumdirect.net/promptkit/internal/promptdef" "go.maximumdirect.net/promptkit/internal/validate" ) @@ -40,11 +41,31 @@ type staticPromptRepo struct { def *domain.PromptDefinition } -func (r staticPromptRepo) GetPromptDefinition( +func (r staticPromptRepo) GetPromptSnapshot( context.Context, string, -) (*domain.PromptDefinition, error) { - return r.def, nil +) (*domain.PromptDefinition, string, error) { + hash, err := promptdef.HashDefinition(r.def) + return r.def, hash, err +} + +func (r staticPromptRepo) GetPromptInspection(ctx context.Context, id string) (*domain.PromptInspection, error) { + definition, hash, err := r.GetPromptSnapshot(ctx, id) + return fixturePromptInspection(definition, hash), err +} + +func (staticPromptRepo) GetRequirementSnapshot(string) (prompt.RequirementSnapshot, bool) { + return prompt.RequirementSnapshot{}, false +} + +func fixturePromptInspection(definition *domain.PromptDefinition, hash string) *domain.PromptInspection { + if definition == nil { + return nil + } + return &domain.PromptInspection{ + PromptID: definition.ID, PromptHash: hash, DefaultProfileID: definition.DefaultProfile, + Inputs: append([]domain.PromptInput(nil), definition.Inputs...), OutputContract: definition.Validation, + } } type staticExecutionProfileRepo struct { @@ -59,6 +80,10 @@ func (r staticExecutionProfileRepo) GetProfile( return &value, nil } +func (staticExecutionProfileRepo) GetProfileIdentity(_ context.Context, id string) (string, error) { + return id, nil +} + type staticArtifactReader struct{} func (staticArtifactReader) Read( @@ -93,12 +118,30 @@ func (f *fakeExecutionProfileRepo) GetProfile(ctx context.Context, id string) (* return nil, errors.New("profile not found") } -func (f *fakePromptRepo) GetPromptDefinition(ctx context.Context, id string) (*domain.PromptDefinition, error) { +func (f *fakeExecutionProfileRepo) GetProfileIdentity(ctx context.Context, id string) (string, error) { + _, err := f.GetProfile(ctx, id) + return id, err +} + +func (f *fakePromptRepo) GetPromptSnapshot(ctx context.Context, id string) (*domain.PromptDefinition, string, error) { f.lastID = id if f.err != nil { - return nil, f.err + return nil, "", f.err } - return f.def, nil + if f.def == nil { + return nil, "", nil + } + hash, err := promptdef.HashDefinition(f.def) + return f.def, hash, err +} + +func (f *fakePromptRepo) GetPromptInspection(ctx context.Context, id string) (*domain.PromptInspection, error) { + definition, hash, err := f.GetPromptSnapshot(ctx, id) + return fixturePromptInspection(definition, hash), err +} + +func (*fakePromptRepo) GetRequirementSnapshot(string) (prompt.RequirementSnapshot, bool) { + return prompt.RequirementSnapshot{}, false } type fakeArtifactReader struct { diff --git a/internal/usecase/smoke_selection_test.go b/internal/usecase/smoke_selection_test.go index 0901ad7..17c66a8 100644 --- a/internal/usecase/smoke_selection_test.go +++ b/internal/usecase/smoke_selection_test.go @@ -58,6 +58,10 @@ func (r *selectionTestRepositories) GetProfile(ctx context.Context, id string) ( return r.profiles.GetProfile(ctx, id) } +func (r *selectionTestRepositories) GetProfileIdentity(ctx context.Context, id string) (string, error) { + return r.profiles.GetProfileIdentity(ctx, id) +} + func (r *selectionTestRepositories) GetBackend(id string) (domain.Backend, error) { return r.backends.GetBackend(id) }