Remove internal prompt version metadata

This commit is contained in:
2026-11-02 04:03:39 +00:00
parent fd6e9742a1
commit 500b0aa1c8
29 changed files with 65 additions and 228 deletions

View File

@@ -412,6 +412,14 @@ Validation: focused domain/use-case tests when runnable and symbol searches for
remaining label plumbing. Do not promise old hash values or remove source-version remaining label plumbing. Do not promise old hash values or remove source-version
checks, collection release labels, or session metadata. checks, collection release labels, or session metadata.
Completion: internal prompt definitions, identities, snapshots, execution,
inspection, smoke diagnostics, and observations no longer propagate prompt
labels. Label-only tests were removed while retained-field ownership and metadata
checks remain. Domain, observation, and prompt package tests passed, as did
focused runner and inspection tests with Go 1.27.0; symbol review and
`git diff --check` passed. Full use-case tests still have failing configuration
fixtures awaiting their scheduled list conversion; public facade cleanup follows.
## Stage 10: Remove Public Prompt Labels And Serialized Fields ## Stage 10: Remove Public Prompt Labels And Serialized Fields
Scope: `types.go`, `listing.go`, `requirements.go`, `observations.go`, Scope: `types.go`, `listing.go`, `requirements.go`, `observations.go`,

View File

@@ -262,7 +262,7 @@ func BenchmarkInspectionSelection(b *testing.B) {
} }
ctx := context.Background() ctx := context.Background()
definition, hash, err := result.GetPromptSnapshot(ctx, "inspection") definition, hash, err := result.GetPromptSnapshot(ctx, "inspection")
if err != nil || definition.ID != "inspection" || definition.Version == nil || *definition.Version != "1" || hash == "" || if err != nil || definition.ID != "inspection" || hash == "" ||
len(definition.Inputs) != 1 || definition.Inputs[0].Name != "transcript" || !definition.Inputs[0].Required { len(definition.Inputs) != 1 || definition.Inputs[0].Name != "transcript" || !definition.Inputs[0].Required {
b.Fatalf("prompt lookup fixture is invalid: definition=%+v hash=%q err=%v", definition, hash, err) b.Fatalf("prompt lookup fixture is invalid: definition=%+v hash=%q err=%v", definition, hash, err)
} }
@@ -272,7 +272,7 @@ func BenchmarkInspectionSelection(b *testing.B) {
b.Fatalf("profile lookup fixture is invalid: profile=%+v err=%v", profile, err) b.Fatalf("profile lookup fixture is invalid: profile=%+v err=%v", profile, err)
} }
inspection, err := result.GetPromptInspection(ctx, "inspection") inspection, err := result.GetPromptInspection(ctx, "inspection")
if err != nil || inspection.PromptID != "inspection" || inspection.PromptVersion == nil || *inspection.PromptVersion != "1" || if err != nil || inspection.PromptID != "inspection" ||
len(inspection.Inputs) != 1 || inspection.Inputs[0].Name != "transcript" { len(inspection.Inputs) != 1 || inspection.Inputs[0].Name != "transcript" {
b.Fatalf("prompt inspection fixture is invalid: inspection=%+v err=%v", inspection, err) b.Fatalf("prompt inspection fixture is invalid: inspection=%+v err=%v", inspection, err)
} }

View File

@@ -77,9 +77,6 @@ func (state *loaded) ListPrompts(ctx context.Context) ([]domain.PromptIdentity,
return nil, err return nil, err
} }
prompts := append([]domain.PromptIdentity(nil), state.promptIDs...) prompts := append([]domain.PromptIdentity(nil), state.promptIDs...)
for index := range prompts {
prompts[index].Version = stringPointerValue(prompts[index].Version)
}
if err := ctx.Err(); err != nil { if err := ctx.Err(); err != nil {
return nil, err return nil, err
} }

View File

@@ -48,9 +48,9 @@ func TestLoadedListsSortedEffectiveIdentities(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
wantPrompts := []domain.PromptIdentity{ wantPrompts := []domain.PromptIdentity{
{ID: " z/prompt ", Version: stringPointer("v1")}, {ID: " z/prompt "},
{ID: "a/prompt", Version: stringPointer("v1")}, {ID: "a/prompt"},
{ID: "z/prompt", Version: stringPointer("v1")}, {ID: "z/prompt"},
} }
if !reflect.DeepEqual(prompts, wantPrompts) { if !reflect.DeepEqual(prompts, wantPrompts) {
t.Fatalf("prompt identities = %#v, want %#v", prompts, wantPrompts) t.Fatalf("prompt identities = %#v, want %#v", prompts, wantPrompts)
@@ -84,7 +84,6 @@ func TestLoadedListsAreIndependent(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
prompts[0].ID = "changed prompt" prompts[0].ID = "changed prompt"
*prompts[0].Version = "changed version"
profiles, err = state.ListProfiles(context.Background()) profiles, err = state.ListProfiles(context.Background())
if err != nil { if err != nil {
@@ -101,7 +100,7 @@ func TestLoadedListsAreIndependent(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
wantPrompts := []domain.PromptIdentity{{ID: "example", Version: stringPointer("v1")}} wantPrompts := []domain.PromptIdentity{{ID: "example"}}
if !reflect.DeepEqual(prompts, wantPrompts) { if !reflect.DeepEqual(prompts, wantPrompts) {
t.Fatalf("caller mutation changed prompt inventory: %#v", prompts) t.Fatalf("caller mutation changed prompt inventory: %#v", prompts)
} }

View File

@@ -274,7 +274,7 @@ func load(main configkit.Input, underlays []configkit.Underlay) (*loaded, error)
state.backendIDs = sortedKeys(indexedBackends(&result.Config)) state.backendIDs = sortedKeys(indexedBackends(&result.Config))
state.profileIDs = sortedKeys(state.indexedProfiles) state.profileIDs = sortedKeys(state.indexedProfiles)
for _, id := range sortedKeys(state.prompts) { for _, id := range sortedKeys(state.prompts) {
state.promptIDs = append(state.promptIDs, domain.PromptIdentity{ID: id, Version: stringPointerValue(state.prompts[id].definition.Version)}) state.promptIDs = append(state.promptIDs, domain.PromptIdentity{ID: id})
} }
state.namespaces = map[string][]string{ state.namespaces = map[string][]string{
"backend": resourceNamespaces(state.backendIDs), "backend": resourceNamespaces(state.backendIDs),

View File

@@ -171,8 +171,8 @@ func TestLoadComposesLiteralKeysAndEffectivePresence(t *testing.T) {
if !exists || collectionProfile.ID != "base/namespaced" || collectionProfile.ResolvedTarget == nil || collectionProfile.ResolvedTarget.BackendID != "base/local.v1" { if !exists || collectionProfile.ID != "base/namespaced" || collectionProfile.ResolvedTarget == nil || collectionProfile.ResolvedTarget.BackendID != "base/local.v1" {
t.Fatalf("collection profile snapshot = %+v, exists %t", collectionProfile, exists) t.Fatalf("collection profile snapshot = %+v, exists %t", collectionProfile, exists)
} }
if loaded.result.Config.Collections["invoice"].Prompts["summary"].Messages[0].Content == nil || loaded.result.Config.Collections["invoice"].Prompts["summary"].Version == nil || *loaded.result.Config.Collections["invoice"].Prompts["summary"].Version != "v1.0" { if loaded.result.Config.Collections["invoice"].Prompts["summary"].Messages[0].Content == nil {
t.Fatal("literal prompt ID and version were not decoded") t.Fatal("literal prompt content was not decoded")
} }
if loaded.result.Config.Version == nil || *loaded.result.Config.Version != "1" || if loaded.result.Config.Version == nil || *loaded.result.Config.Version != "1" ||
loaded.result.Config.Collections["base"].ReleaseVersion == nil || *loaded.result.Config.Collections["base"].ReleaseVersion != "" || loaded.result.Config.Collections["base"].ReleaseVersion == nil || *loaded.result.Config.Collections["base"].ReleaseVersion != "" ||

View File

@@ -297,7 +297,6 @@ func (state *loaded) lookupPromptEntry(id string) (*promptEntry, error) {
} }
func ownPromptDefinition(definition domain.PromptDefinition) *domain.PromptDefinition { func ownPromptDefinition(definition domain.PromptDefinition) *domain.PromptDefinition {
definition.Version = stringPointerValue(definition.Version)
definition.Inputs = append([]domain.PromptInput(nil), definition.Inputs...) definition.Inputs = append([]domain.PromptInput(nil), definition.Inputs...)
definition.Templates = append([]domain.PromptMessageTemplate(nil), definition.Templates...) definition.Templates = append([]domain.PromptMessageTemplate(nil), definition.Templates...)
for index := range definition.Templates { for index := range definition.Templates {
@@ -310,7 +309,6 @@ func ownPromptDefinition(definition domain.PromptDefinition) *domain.PromptDefin
} }
func ownPromptInspection(inspection domain.PromptInspection) *domain.PromptInspection { func ownPromptInspection(inspection domain.PromptInspection) *domain.PromptInspection {
inspection.PromptVersion = stringPointerValue(inspection.PromptVersion)
inspection.Inputs = append([]domain.PromptInput(nil), inspection.Inputs...) inspection.Inputs = append([]domain.PromptInput(nil), inspection.Inputs...)
return &inspection return &inspection
} }

View File

@@ -136,7 +136,7 @@ func TestLoadCapturesNativeContentFile(t *testing.T) {
} }
} }
func TestLoadRejectsMalformedStaticSyntaxAndCapturesOptionalVersion(t *testing.T) { func TestLoadRejectsMalformedStaticSyntax(t *testing.T) {
_, err := load(mapping("bad-template", map[string]any{"prompts": map[string]any{"example": map[string]any{ _, err := load(mapping("bad-template", map[string]any{"prompts": map[string]any{"example": map[string]any{
"messages": []any{map[string]any{"role": "user", "content": "{{if}}"}}, "messages": []any{map[string]any{"role": "user", "content": "{{if}}"}},
"output": map[string]any{"format": "text", "validation_mode": "basic"}, "output": map[string]any{"format": "text", "validation_mode": "basic"},
@@ -144,119 +144,6 @@ func TestLoadRejectsMalformedStaticSyntaxAndCapturesOptionalVersion(t *testing.T
if err == nil || !strings.Contains(err.Error(), "invalid template syntax") { if err == nil || !strings.Contains(err.Error(), "invalid template syntax") {
t.Fatalf("expected construction-time syntax error, got %v", err) t.Fatalf("expected construction-time syntax error, got %v", err)
} }
state, err := load(mapping("version metadata", map[string]any{"prompts": map[string]any{"example": map[string]any{
"version": "release label",
"messages": []any{map[string]any{"role": "user", "content": "one"}},
"output": map[string]any{"format": "text", "validation_mode": "basic"},
}}}), nil)
if err != nil {
t.Fatal(err)
}
definition, inspection, err := state.prompt("example")
if err != nil || definition.Version == nil || *definition.Version != "release label" ||
inspection.PromptVersion == nil || *inspection.PromptVersion != "release label" {
t.Fatalf("optional version metadata was not retained: definition=%+v inspection=%+v err=%v", definition, inspection, err)
}
}
func TestPromptVersionLabelPresenceAndOwnership(t *testing.T) {
tests := []struct {
name string
version any
include bool
wantPresent bool
wantValue string
}{
{name: "absent"},
{name: "null", include: true},
{name: "empty", version: "", include: true, wantPresent: true},
{name: "exact text", version: " Release/v1 ", include: true, wantPresent: true, wantValue: " Release/v1 "},
}
hashes := make(map[string]string, len(tests))
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
definition := map[string]any{
"messages": []any{map[string]any{"role": "user", "content": "hello"}},
"output": map[string]any{"format": "text", "validation_mode": "basic"},
}
if test.include {
definition["version"] = test.version
}
state, err := load(mapping("prompt version label", map[string]any{
"prompts": map[string]any{"example": definition},
}), nil)
if err != nil {
t.Fatal(err)
}
captured, inspection, err := state.prompt("example")
if err != nil {
t.Fatal(err)
}
identities, err := state.ListPrompts(context.Background())
if err != nil || len(identities) != 1 {
t.Fatalf("list prompt labels: %#v, %v", identities, err)
}
check := func(name string, value *string) {
t.Helper()
if !test.wantPresent {
if value != nil {
t.Errorf("%s label = %q, want absent", name, *value)
}
return
}
if value == nil || *value != test.wantValue {
t.Errorf("%s label = %v, want %q", name, value, test.wantValue)
}
}
check("definition", captured.Version)
check("inspection", inspection.PromptVersion)
check("listing", identities[0].Version)
if captured.Version != nil && (captured.Version == inspection.PromptVersion || captured.Version == identities[0].Version || inspection.PromptVersion == identities[0].Version) {
t.Fatal("returned prompt labels share mutable pointers")
}
hashes[test.name] = inspection.PromptHash
if captured.Version != nil {
*captured.Version = "mutated definition"
}
if inspection.PromptVersion != nil {
*inspection.PromptVersion = "mutated inspection"
}
if identities[0].Version != nil {
*identities[0].Version = "mutated listing"
}
again, againInspection, err := state.prompt("example")
if err != nil {
t.Fatal(err)
}
check("captured definition after mutation", again.Version)
check("captured inspection after mutation", againInspection.PromptVersion)
})
}
if hashes["absent"] == hashes["empty"] {
t.Fatal("absent and declared-empty labels produced the same definition hash")
}
}
func TestPromptVersionNullClearsInheritedLabel(t *testing.T) {
prompt := map[string]any{
"version": "base-label",
"messages": []any{map[string]any{"role": "user", "content": "hello"}},
"output": map[string]any{"format": "text", "validation_mode": "basic"},
}
state, err := load(
mapping("clear inherited label", map[string]any{"prompts": map[string]any{"example": map[string]any{"version": nil}}}),
[]configkit.Underlay{{Inputs: []configkit.Input{mapping("base prompt", map[string]any{"prompts": map[string]any{"example": prompt}})}}},
)
if err != nil {
t.Fatal(err)
}
definition, inspection, err := state.prompt("example")
if err != nil || definition.Version != nil || inspection.PromptVersion != nil {
t.Fatalf("null overlay retained inherited label: definition=%+v inspection=%+v err=%v", definition, inspection, err)
}
} }
func TestPromptInspectionLookupMatchesSnapshotSelectionAndOwnsInputs(t *testing.T) { func TestPromptInspectionLookupMatchesSnapshotSelectionAndOwnsInputs(t *testing.T) {
@@ -272,7 +159,6 @@ func TestPromptInspectionLookupMatchesSnapshotSelectionAndOwnsInputs(t *testing.
} }
} }
selectedPrompt := makePrompt("selected") selectedPrompt := makePrompt("selected")
selectedPrompt["version"] = "v2"
state, err := load(mapping("prompt inspection lookup", map[string]any{ state, err := load(mapping("prompt inspection lookup", map[string]any{
"profiles": map[string]any{"partial": map[string]any{}}, "profiles": map[string]any{"partial": map[string]any{}},
"prompts": map[string]any{ "prompts": map[string]any{
@@ -292,8 +178,7 @@ func TestPromptInspectionLookupMatchesSnapshotSelectionAndOwnsInputs(t *testing.
if err != nil { if err != nil {
t.Fatalf("snapshot prompt ID: %v", err) t.Fatalf("snapshot prompt ID: %v", err)
} }
if inspection.PromptID != definition.ID || inspection.PromptVersion == nil || definition.Version == nil || if inspection.PromptID != definition.ID ||
*inspection.PromptVersion != *definition.Version ||
inspection.PromptHash != hash || inspection.DefaultProfileID != "partial" || inspection.PromptHash != hash || inspection.DefaultProfileID != "partial" ||
len(inspection.Inputs) != 1 || inspection.Inputs[0].Name != "document" || len(inspection.Inputs) != 1 || inspection.Inputs[0].Name != "document" ||
inspection.Inputs[0].ContentType != "text/plain" || inspection.Inputs[0].Description != "source document" { inspection.Inputs[0].ContentType != "text/plain" || inspection.Inputs[0].Description != "source document" {

View File

@@ -80,7 +80,6 @@ type RunResult struct {
RawOutput string RawOutput string
Validation ValidationResult Validation ValidationResult
PromptID string PromptID string
PromptVersion *string
PromptHash string PromptHash string
SessionID string SessionID string
RenderedPromptHash string RenderedPromptHash string
@@ -100,7 +99,6 @@ type RunResult struct {
// It must never include resolved API key values, model output, or validation data. // It must never include resolved API key values, model output, or validation data.
type PreparedRun struct { type PreparedRun struct {
PromptID string PromptID string
PromptVersion *string
PromptHash string PromptHash string
SelectedProfileID string SelectedProfileID string
SelectedBackendID string SelectedBackendID string
@@ -134,16 +132,14 @@ type Artifact struct {
Hash string Hash string
} }
// PromptIdentity identifies one configured prompt and its descriptive version label. // PromptIdentity identifies one configured prompt.
type PromptIdentity struct { type PromptIdentity struct {
ID string ID string
Version *string
} }
// PromptDefinition represents a configured prompt execution definition. // PromptDefinition represents a configured prompt execution definition.
type PromptDefinition struct { type PromptDefinition struct {
ID string `yaml:"id"` ID string `yaml:"id"`
Version *string `yaml:"version"`
DefaultProfile string `yaml:"default_profile"` DefaultProfile string `yaml:"default_profile"`
Description string `yaml:"description"` Description string `yaml:"description"`
SessionID string `yaml:"session_id" json:"session_id,omitempty"` SessionID string `yaml:"session_id" json:"session_id,omitempty"`
@@ -156,7 +152,6 @@ type PromptDefinition struct {
// PromptInspection is the resolved result of exact prompt inspection. // PromptInspection is the resolved result of exact prompt inspection.
type PromptInspection struct { type PromptInspection struct {
PromptID string PromptID string
PromptVersion *string
PromptHash string PromptHash string
DefaultProfileID string DefaultProfileID string
Inputs []PromptInput Inputs []PromptInput

View File

@@ -68,7 +68,6 @@ type ExecutionEvent struct {
RunID string RunID string
Time time.Time Time time.Time
PromptID string PromptID string
PromptVersion *string
ProfileID string ProfileID string
BackendID string BackendID string
Model string Model string

View File

@@ -48,11 +48,10 @@ type RequirementIssue struct {
// RequirementInspection contains the inventories discovered for one prompt. // RequirementInspection contains the inventories discovered for one prompt.
type RequirementInspection struct { type RequirementInspection struct {
PromptID string PromptID string
PromptVersion *string ProfileID string
ProfileID string Inputs []InputRequirement
Inputs []InputRequirement Variables []VariableRequirement
Variables []VariableRequirement Complete bool
Complete bool Issues []RequirementIssue
Issues []RequirementIssue
} }

View File

@@ -65,7 +65,6 @@ type SmokeTestTarget struct {
BackendID string BackendID string
ProfileID string ProfileID string
PromptID string PromptID string
PromptVersion *string
DefaultSourceBackendID string DefaultSourceBackendID string
SelectionSource string SelectionSource string
Endpoint string Endpoint string
@@ -180,7 +179,6 @@ func CloneSmokeTestRequest(request SmokeTestRequest) (SmokeTestRequest, error) {
func CloneSmokeTestReport(report SmokeTestReport) (SmokeTestReport, error) { func CloneSmokeTestReport(report SmokeTestReport) (SmokeTestReport, error) {
cloned := report cloned := report
cloned.Applicable = cloneBool(report.Applicable) cloned.Applicable = cloneBool(report.Applicable)
cloned.Target.PromptVersion = cloneString(report.Target.PromptVersion)
cloned.Facts = cloneSmokeTestFacts(report.Facts) cloned.Facts = cloneSmokeTestFacts(report.Facts)
cloned.Timing = cloneSmokeTestTiming(report.Timing) cloned.Timing = cloneSmokeTestTiming(report.Timing)
var err error var err error

View File

@@ -77,11 +77,9 @@ func TestCloneSmokeTestReportOwnsMutableValues(t *testing.T) {
reachable := true reachable := true
status := 200 status := 200
wait := 3 * time.Millisecond wait := 3 * time.Millisecond
promptVersion := "v1"
report := SmokeTestReport{ report := SmokeTestReport{
Applicable: &applicable, Applicable: &applicable,
Target: SmokeTestTarget{ Target: SmokeTestTarget{
PromptVersion: &promptVersion,
EffectiveSettings: ExecutionTarget{ EffectiveSettings: ExecutionTarget{
ExtraParams: map[string]any{"nested": map[string]any{"value": "original"}}, ExtraParams: map[string]any{"nested": map[string]any{"value": "original"}},
}, },
@@ -103,10 +101,9 @@ func TestCloneSmokeTestReportOwnsMutableValues(t *testing.T) {
*cloned.Attempts[0].HTTPStatus = 503 *cloned.Attempts[0].HTTPStatus = 503
*cloned.Attempts[0].Facts.EndpointReachable = false *cloned.Attempts[0].Facts.EndpointReachable = false
*cloned.Attempts[0].Timing.CapacityWait = time.Second *cloned.Attempts[0].Timing.CapacityWait = time.Second
*cloned.Target.PromptVersion = "changed"
cloned.Target.EffectiveSettings.ExtraParams["nested"].(map[string]any)["value"] = "changed" cloned.Target.EffectiveSettings.ExtraParams["nested"].(map[string]any)["value"] = "changed"
if !applicable || !reachable || status != 200 || wait != 3*time.Millisecond || promptVersion != "v1" { if !applicable || !reachable || status != 200 || wait != 3*time.Millisecond {
t.Fatal("cloned report shared optional scalar pointers") t.Fatal("cloned report shared optional scalar pointers")
} }
if got := report.Target.EffectiveSettings.ExtraParams["nested"].(map[string]any)["value"]; got != "original" { if got := report.Target.EffectiveSettings.ExtraParams["nested"].(map[string]any)["value"]; got != "original" {

View File

@@ -33,11 +33,10 @@ type Recorder struct {
// Selection contains resolved identities only. Unresolved fields stay empty. // Selection contains resolved identities only. Unresolved fields stay empty.
type Selection struct { type Selection struct {
PromptID string PromptID string
PromptVersion *string ProfileID string
ProfileID string BackendID string
BackendID string Model string
Model string
} }
// AttemptData describes one completed active-permit acquisition and optional // AttemptData describes one completed active-permit acquisition and optional
@@ -104,7 +103,6 @@ func (r *Recorder) Start() {
// UpdateSelection replaces the known resolved identities for later events. // UpdateSelection replaces the known resolved identities for later events.
func (r *Recorder) UpdateSelection(selection Selection) { func (r *Recorder) UpdateSelection(selection Selection) {
selection.PromptVersion = copyStringPointer(selection.PromptVersion)
r.selection = selection r.selection = selection
} }
@@ -180,19 +178,11 @@ func (r *Recorder) Finish(data FinishData) {
func (r *Recorder) event(kind domain.ExecutionEventKind) domain.ExecutionEvent { func (r *Recorder) event(kind domain.ExecutionEventKind) domain.ExecutionEvent {
return domain.ExecutionEvent{ return domain.ExecutionEvent{
Kind: kind, RunID: r.runID, Time: r.now(), PromptID: r.selection.PromptID, Kind: kind, RunID: r.runID, Time: r.now(), PromptID: r.selection.PromptID,
PromptVersion: copyStringPointer(r.selection.PromptVersion), ProfileID: r.selection.ProfileID, ProfileID: r.selection.ProfileID,
BackendID: r.selection.BackendID, Model: r.selection.Model, BackendID: r.selection.BackendID, Model: r.selection.Model,
} }
} }
func copyStringPointer(value *string) *string {
if value == nil {
return nil
}
copy := *value
return &copy
}
func (r *Recorder) deliver(event domain.ExecutionEvent) { func (r *Recorder) deliver(event domain.ExecutionEvent) {
if r.observer != nil { if r.observer != nil {
r.observer(event) r.observer(event)

View File

@@ -50,8 +50,7 @@ func TestRecorderAccountsDispatchedAttemptsAndReportedUsage(t *testing.T) {
var events []domain.ExecutionEvent var events []domain.ExecutionEvent
recorder := newRecorder("run-1", now, func(event domain.ExecutionEvent) { events = append(events, event) }) recorder := newRecorder("run-1", now, func(event domain.ExecutionEvent) { events = append(events, event) })
recorder.Start() recorder.Start()
version := "v1" recorder.UpdateSelection(Selection{PromptID: "prompt", ProfileID: "profile", BackendID: "backend", Model: "model"})
recorder.UpdateSelection(Selection{PromptID: "prompt", PromptVersion: &version, ProfileID: "profile", BackendID: "backend", Model: "model"})
recorder.Attempt(AttemptData{ recorder.Attempt(AttemptData{
Generation: 1, Attempt: 1, Dispatched: true, Generation: 1, Attempt: 1, Dispatched: true,
CapacityWait: 2 * time.Millisecond, GenerationDuration: 10 * time.Millisecond, CapacityWait: 2 * time.Millisecond, GenerationDuration: 10 * time.Millisecond,

View File

@@ -52,7 +52,7 @@ func BenchmarkCompiledRendering(b *testing.B) {
small := newCompiledRenderingBenchmarkCase(b, small := newCompiledRenderingBenchmarkCase(b,
"small_message", "", []string{"Summary for {{.audience}}."}, "small_message", "", []string{"Summary for {{.audience}}."},
&domain.PromptDefinition{ &domain.PromptDefinition{
ID: "compiled-render-benchmark", Version: stringPointerForTest("v1"), ID: "compiled-render-benchmark",
Templates: []domain.PromptMessageTemplate{{Role: "user", Content: "Summary for {{.audience}}."}}, Templates: []domain.PromptMessageTemplate{{Role: "user", Content: "Summary for {{.audience}}."}},
}, nil, map[string]string{"audience": "project leads"}, }, nil, map[string]string{"audience": "project leads"},
len("Summary for project leads."), len("Summary for project leads."),
@@ -68,7 +68,7 @@ func BenchmarkCompiledRendering(b *testing.B) {
} }
largeContent := `{{input "document"}}` largeContent := `{{input "document"}}`
largeDefinition := &domain.PromptDefinition{ largeDefinition := &domain.PromptDefinition{
ID: "compiled-render-benchmark", Version: stringPointerForTest("v1"), ID: "compiled-render-benchmark",
Inputs: []domain.PromptInput{{Name: "document"}}, Inputs: []domain.PromptInput{{Name: "document"}},
Templates: []domain.PromptMessageTemplate{{Role: "user", Content: largeContent}}, Templates: []domain.PromptMessageTemplate{{Role: "user", Content: largeContent}},
} }
@@ -91,7 +91,7 @@ func BenchmarkCompiledRendering(b *testing.B) {
`{{input "document"}}|{{input "document"}}`, `{{input "document"}}|{{input "document"}}`,
} }
repeatedDefinition := &domain.PromptDefinition{ repeatedDefinition := &domain.PromptDefinition{
ID: "compiled-render-benchmark", Version: stringPointerForTest("v1"), SessionID: repeatedSession, ID: "compiled-render-benchmark", SessionID: repeatedSession,
Inputs: []domain.PromptInput{{Name: "document"}}, Inputs: []domain.PromptInput{{Name: "document"}},
Templates: []domain.PromptMessageTemplate{ Templates: []domain.PromptMessageTemplate{
{Role: "system", Content: repeatedMessages[0]}, {Role: "system", Content: repeatedMessages[0]},
@@ -141,7 +141,7 @@ func BenchmarkRetainedRenderedOutput(b *testing.B) {
bodyText := string(body) bodyText := string(body)
content := `{{input "document"}}` content := `{{input "document"}}`
definition := &domain.PromptDefinition{ definition := &domain.PromptDefinition{
ID: "retained-render-benchmark", Version: stringPointerForTest("v1"), ID: "retained-render-benchmark",
Inputs: []domain.PromptInput{{Name: "document"}}, Inputs: []domain.PromptInput{{Name: "document"}},
Templates: []domain.PromptMessageTemplate{{Role: "user", Content: content}}, Templates: []domain.PromptMessageTemplate{{Role: "user", Content: content}},
} }

View File

@@ -507,7 +507,6 @@ func TestGoRendererArtifactTextLifecycle(t *testing.T) {
func TestCompiledRendererKeepsConcurrentRequestsIndependent(t *testing.T) { func TestCompiledRendererKeepsConcurrentRequestsIndependent(t *testing.T) {
const ( const (
promptID = "concurrent-render" promptID = "concurrent-render"
version = "v1"
) )
sessionTemplate, err := CompileTemplate("session", "session-{{.request}}") sessionTemplate, err := CompileTemplate("session", "session-{{.request}}")
if err != nil { if err != nil {
@@ -525,7 +524,7 @@ func TestCompiledRendererKeepsConcurrentRequestsIndependent(t *testing.T) {
}, },
}) })
definition := &domain.PromptDefinition{ definition := &domain.PromptDefinition{
ID: promptID, Version: stringPointerForTest(version), SessionID: "session-{{.request}}", ID: promptID, SessionID: "session-{{.request}}",
Inputs: []domain.PromptInput{{Name: "document"}}, Inputs: []domain.PromptInput{{Name: "document"}},
Templates: []domain.PromptMessageTemplate{{Role: "user", Content: `request={{.request}};document={{input "document"}}`}}, Templates: []domain.PromptMessageTemplate{{Role: "user", Content: `request={{.request}};document={{input "document"}}`}},
} }

View File

@@ -384,7 +384,6 @@ func AnalyzeRequirements(
result := domain.RequirementInspection{Complete: true} result := domain.RequirementInspection{Complete: true}
if definition != nil { if definition != nil {
result.PromptID = definition.ID result.PromptID = definition.ID
result.PromptVersion = copyString(definition.Version)
} }
walker := &requirementWalker{ walker := &requirementWalker{
ctx: ctx, ctx: ctx,

View File

@@ -108,7 +108,7 @@ func TestRequirementWalkerDoesNotRescanNestedUnsupportedNames(t *testing.T) {
func TestAnalyzeRequirementsCollectsDeclaredAndLiteralInputs(t *testing.T) { func TestAnalyzeRequirementsCollectsDeclaredAndLiteralInputs(t *testing.T) {
description := "retained metadata" description := "retained metadata"
definition := &domain.PromptDefinition{ID: "capture", Version: stringPointerForTest("v1")} definition := &domain.PromptDefinition{ID: "capture"}
snapshot := RequirementSnapshot{ snapshot := RequirementSnapshot{
Inputs: []InputMetadata{ Inputs: []InputMetadata{
{Name: "optional", ContentType: stringPointerForTest("text/plain"), Description: &description}, {Name: "optional", ContentType: stringPointerForTest("text/plain"), Description: &description},
@@ -123,7 +123,7 @@ func TestAnalyzeRequirementsCollectsDeclaredAndLiteralInputs(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if result.PromptID != "capture" || result.PromptVersion == nil || *result.PromptVersion != "v1" || !result.Complete || len(result.Issues) != 0 { if result.PromptID != "capture" || !result.Complete || len(result.Issues) != 0 {
t.Fatalf("unexpected result identity or completeness: %+v", result) t.Fatalf("unexpected result identity or completeness: %+v", result)
} }
wantNames := []string{"extra", "optional", "transcript", "unused"} wantNames := []string{"extra", "optional", "transcript", "unused"}

View File

@@ -128,7 +128,7 @@ func (r *Runner) RunPrepared(ctx context.Context, prepared *PreparedExecution) (
ctx = observation.WithRecorder(ctx, recorder) ctx = observation.WithRecorder(ctx, recorder)
selected := payload.prepared selected := payload.prepared
recorder.UpdateSelection(observation.Selection{PromptID: selected.PromptID, recorder.UpdateSelection(observation.Selection{PromptID: selected.PromptID,
PromptVersion: selected.PromptVersion, ProfileID: selected.SelectedProfileID, ProfileID: selected.SelectedProfileID,
BackendID: selected.SelectedBackendID, Model: selected.EffectiveModelParams.Model}) BackendID: selected.SelectedBackendID, Model: selected.EffectiveModelParams.Model})
recorder.Start() recorder.Start()
if idErr != nil { if idErr != nil {
@@ -229,7 +229,6 @@ func clonePreparedRun(source *domain.PreparedRun) (*domain.PreparedRun, error) {
} }
copied := *source copied := *source
copied.PromptVersion = copyStringPointer(source.PromptVersion)
extraParams, err := jsonvalue.CopyMap(source.EffectiveModelParams.ExtraParams) extraParams, err := jsonvalue.CopyMap(source.EffectiveModelParams.ExtraParams)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -662,7 +662,6 @@ func TestRunnerPreparedExecutionDetachesTransferredSnapshotSources(t *testing.T)
"properties": map[string]any{"value": map[string]any{"type": "string"}}, "properties": map[string]any{"value": map[string]any{"type": "string"}},
} }
definition := promptDef(domain.FormatJSON, domain.ValidationJSONSchema, 0) definition := promptDef(domain.FormatJSON, domain.ValidationJSONSchema, 0)
wantPromptVersion := *definition.Version
definition.Validation.SchemaPath = "schema.json" definition.Validation.SchemaPath = "schema.json"
control := &domain.CacheControl{Type: domain.CacheControlEphemeral, TTL: "1h"} control := &domain.CacheControl{Type: domain.CacheControlEphemeral, TTL: "1h"}
rendered := &domain.RenderedPrompt{Messages: []domain.RenderedMessage{{ rendered := &domain.RenderedPrompt{Messages: []domain.RenderedMessage{{
@@ -698,7 +697,6 @@ func TestRunnerPreparedExecutionDetachesTransferredSnapshotSources(t *testing.T)
} }
mutateExtra(profileExtras, "mutated profile source") mutateExtra(profileExtras, "mutated profile source")
mutateExtra(requestExtras, "mutated request source") mutateExtra(requestExtras, "mutated request source")
*definition.Version = "mutated definition label"
rendered.Messages[0].Content = "mutated renderer source" rendered.Messages[0].Content = "mutated renderer source"
control.TTL = "mutated renderer cache metadata" control.TTL = "mutated renderer cache metadata"
schemaDocument["properties"].(map[string]any)["value"].(map[string]any)["type"] = "integer" schemaDocument["properties"].(map[string]any)["value"].(map[string]any)["type"] = "integer"
@@ -713,21 +711,15 @@ func TestRunnerPreparedExecutionDetachesTransferredSnapshotSources(t *testing.T)
details.StructuredOutput.JSONSchema.Schema.(map[string]any)["properties"].(map[string]any)["value"].(map[string]any)["type"] != "string" { details.StructuredOutput.JSONSchema.Schema.(map[string]any)["properties"].(map[string]any)["value"].(map[string]any)["type"] != "string" {
t.Fatalf("prepared details retained a source alias: %#v", details) t.Fatalf("prepared details retained a source alias: %#v", details)
} }
if details.PromptVersion == nil || *details.PromptVersion != wantPromptVersion { details.Messages[0].Content = "mutated details"
t.Fatalf("prepared details did not preserve the captured version: %+v", details) if again := prepared.Details(); again == nil || len(again.Messages) != 1 || again.Messages[0].Content != "captured rendering" {
} t.Fatalf("details mutation escaped into the retained snapshot: %+v", again)
*details.PromptVersion = "mutated details label"
if again := prepared.Details(); again == nil || again.PromptVersion == nil || *again.PromptVersion != wantPromptVersion {
t.Fatalf("details version mutation escaped into the retained snapshot: %+v", again)
} }
result, err := runner.RunPrepared(context.Background(), prepared) result, err := runner.RunPrepared(context.Background(), prepared)
if err != nil || result == nil || !result.Validation.IsValid || result.InputHashes["transcript"] != "captured-input-hash" { if err != nil || result == nil || !result.Validation.IsValid || result.InputHashes["transcript"] != "captured-input-hash" {
t.Fatalf("run prepared snapshot=(%+v, %v)", result, err) t.Fatalf("run prepared snapshot=(%+v, %v)", result, err)
} }
if result.PromptVersion == nil || *result.PromptVersion != wantPromptVersion {
t.Fatalf("details version mutation escaped into execution metadata: %+v", result)
}
if len(llmClient.lastReq.Prompt.Messages) != 1 || llmClient.lastReq.StructuredOutput == nil || if len(llmClient.lastReq.Prompt.Messages) != 1 || llmClient.lastReq.StructuredOutput == nil ||
llmClient.lastReq.StructuredOutput.JSONSchema == nil || llmClient.lastReq.StructuredOutput.JSONSchema == nil ||
extraLabel(llmClient.lastReq.Target.ExtraParams) != wantLabel || extraLabel(llmClient.lastReq.Target.ExtraParams) != wantLabel ||
@@ -737,7 +729,6 @@ func TestRunnerPreparedExecutionDetachesTransferredSnapshotSources(t *testing.T)
t.Fatalf("execution snapshot retained a source alias: %#v", llmClient.lastReq) t.Fatalf("execution snapshot retained a source alias: %#v", llmClient.lastReq)
} }
if completedDetails := prepared.Details(); completedDetails == nil || if completedDetails := prepared.Details(); completedDetails == nil ||
completedDetails.PromptVersion == nil || *completedDetails.PromptVersion != wantPromptVersion ||
len(completedDetails.Messages) != 1 || completedDetails.Messages[0].Content != "captured rendering" || len(completedDetails.Messages) != 1 || completedDetails.Messages[0].Content != "captured rendering" ||
extraLabel(completedDetails.EffectiveModelParams.ExtraParams) != wantLabel { extraLabel(completedDetails.EffectiveModelParams.ExtraParams) != wantLabel {
t.Fatalf("completed details changed after source mutation: %#v", completedDetails) t.Fatalf("completed details changed after source mutation: %#v", completedDetails)

View File

@@ -76,7 +76,6 @@ func (r *Runner) resolvePromptInspection(ctx context.Context, promptID string) (
definition := selection.definition definition := selection.definition
return &domain.PromptInspection{ return &domain.PromptInspection{
PromptID: definition.ID, PromptID: definition.ID,
PromptVersion: copyStringPointer(definition.Version),
PromptHash: selection.hash, PromptHash: selection.hash,
DefaultProfileID: definition.DefaultProfile, DefaultProfileID: definition.DefaultProfile,
Inputs: append([]domain.PromptInput(nil), definition.Inputs...), Inputs: append([]domain.PromptInput(nil), definition.Inputs...),

View File

@@ -52,7 +52,6 @@ func (r *promptMetadataRepository) GetPromptInspection(
func TestRunnerInspectPromptResolvesOneDefinitionWithoutExecutionCollaborators(t *testing.T) { func TestRunnerInspectPromptResolvesOneDefinitionWithoutExecutionCollaborators(t *testing.T) {
definition := &domain.PromptDefinition{ definition := &domain.PromptDefinition{
ID: "normalized.prompt", ID: "normalized.prompt",
Version: stringPtr("1.2.3"),
DefaultProfile: "not-resolved", DefaultProfile: "not-resolved",
Inputs: []domain.PromptInput{ Inputs: []domain.PromptInput{
{Name: "document", Required: true, ContentType: "text/plain", Description: "Source document."}, {Name: "document", Required: true, ContentType: "text/plain", Description: "Source document."},
@@ -79,8 +78,7 @@ func TestRunnerInspectPromptResolvesOneDefinitionWithoutExecutionCollaborators(t
if repository.calls != 1 || repository.id != " prompt-id " { 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) t.Fatalf("prompt lookup=(calls=%d id=%q), want one unchanged ID lookup", repository.calls, repository.id)
} }
if inspection.PromptID != definition.ID || inspection.PromptVersion == nil || definition.Version == nil || if inspection.PromptID != definition.ID ||
*inspection.PromptVersion != *definition.Version ||
inspection.PromptHash != wantHash || inspection.PromptHash != wantHash ||
inspection.DefaultProfileID != definition.DefaultProfile || inspection.DefaultProfileID != definition.DefaultProfile ||
!reflect.DeepEqual(inspection.Inputs, definition.Inputs) || !reflect.DeepEqual(inspection.Inputs, definition.Inputs) ||
@@ -100,7 +98,7 @@ func TestRunnerInspectPromptResolvesOneDefinitionWithoutExecutionCollaborators(t
func TestRunnerInspectPromptUsesOwnedMetadataWhenRepositorySupportsIt(t *testing.T) { func TestRunnerInspectPromptUsesOwnedMetadataWhenRepositorySupportsIt(t *testing.T) {
repository := &promptMetadataRepository{inspection: domain.PromptInspection{ repository := &promptMetadataRepository{inspection: domain.PromptInspection{
PromptID: "captured.prompt", PromptVersion: stringPtr("v2"), PromptHash: "cached-prompt-hash", PromptID: "captured.prompt", PromptHash: "cached-prompt-hash",
DefaultProfileID: "partial-profile", DefaultProfileID: "partial-profile",
Inputs: []domain.PromptInput{{Name: "document", Required: true, ContentType: "text/plain", Description: "Captured."}}, Inputs: []domain.PromptInput{{Name: "document", Required: true, ContentType: "text/plain", Description: "Captured."}},
OutputContract: domain.OutputContract{Format: domain.FormatJSON, ValidationMode: domain.ValidationJSON}, OutputContract: domain.OutputContract{Format: domain.FormatJSON, ValidationMode: domain.ValidationJSON},
@@ -108,7 +106,7 @@ func TestRunnerInspectPromptUsesOwnedMetadataWhenRepositorySupportsIt(t *testing
runner := &Runner{promptDefs: repository} runner := &Runner{promptDefs: repository}
inspection, err := runner.InspectPrompt(context.Background(), " requested-id ") inspection, err := runner.InspectPrompt(context.Background(), " requested-id ")
if err != nil || repository.lookupID != " requested-id " || if err != nil || repository.lookupID != " requested-id " ||
inspection.PromptID != "captured.prompt" || inspection.PromptVersion == nil || *inspection.PromptVersion != "v2" || inspection.PromptID != "captured.prompt" ||
inspection.PromptHash != "cached-prompt-hash" || inspection.DefaultProfileID != "partial-profile" || inspection.PromptHash != "cached-prompt-hash" || inspection.DefaultProfileID != "partial-profile" ||
!reflect.DeepEqual(inspection.Inputs, repository.inspection.Inputs) || inspection.OutputContract != repository.inspection.OutputContract { !reflect.DeepEqual(inspection.Inputs, repository.inspection.Inputs) || inspection.OutputContract != repository.inspection.OutputContract {
t.Fatalf("metadata inspection=(%+v, %v), lookup=%q", inspection, err, repository.lookupID) t.Fatalf("metadata inspection=(%+v, %v), lookup=%q", inspection, err, repository.lookupID)
@@ -124,11 +122,11 @@ func TestRunnerInspectPromptUsesOwnedMetadataWhenRepositorySupportsIt(t *testing
func TestRunnerInspectPromptUsesCapturedHashWhenMetadataCapabilityIsAbsent(t *testing.T) { func TestRunnerInspectPromptUsesCapturedHashWhenMetadataCapabilityIsAbsent(t *testing.T) {
repository := &requirementInspectionPromptRepository{ repository := &requirementInspectionPromptRepository{
definition: &domain.PromptDefinition{ definition: &domain.PromptDefinition{
ID: "captured.prompt", Version: stringPtr("v1"), Inputs: []domain.PromptInput{{Name: "document"}}, ID: "captured.prompt", Inputs: []domain.PromptInput{{Name: "document"}},
}, },
} }
inspection, err := (&Runner{promptDefs: repository}).InspectPrompt(context.Background(), " requested-id ") inspection, err := (&Runner{promptDefs: repository}).InspectPrompt(context.Background(), " requested-id ")
if err != nil || inspection.PromptID != "captured.prompt" || inspection.PromptVersion == nil || *inspection.PromptVersion != "v1" || if err != nil || inspection.PromptID != "captured.prompt" ||
inspection.PromptHash != "captured-hash" || inspection.Inputs[0].Name != "document" { inspection.PromptHash != "captured-hash" || inspection.Inputs[0].Name != "document" {
t.Fatalf("captured-hash fallback inspection=(%+v, %v)", inspection, err) t.Fatalf("captured-hash fallback inspection=(%+v, %v)", inspection, err)
} }

View File

@@ -69,7 +69,7 @@ func (r *Runner) InspectRequirements(
if !ok { if !ok {
return nil, fmt.Errorf("%w: captured requirement snapshot is unavailable", ErrPromptLoad) return nil, fmt.Errorf("%w: captured requirement snapshot is unavailable", ErrPromptLoad)
} }
definition := &domain.PromptDefinition{ID: selection.PromptID, Version: copyStringPointer(selection.PromptVersion)} definition := &domain.PromptDefinition{ID: selection.PromptID}
inspection, err := prompt.AnalyzeRequirements(ctx, definition, snapshot, req.Vars, directSessionID != "") inspection, err := prompt.AnalyzeRequirements(ctx, definition, snapshot, req.Vars, directSessionID != "")
if err != nil { if err != nil {
return nil, fmt.Errorf("%w: %w", ErrPromptLoad, err) return nil, fmt.Errorf("%w: %w", ErrPromptLoad, err)

View File

@@ -88,7 +88,7 @@ func TestRunnerInspectRequirementsUsesCapturedSelectionWithoutExecutionWork(t *t
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
definition := &domain.PromptDefinition{ID: "selected", Version: stringPtr("v2"), DefaultProfile: "default-profile"} definition := &domain.PromptDefinition{ID: "selected", DefaultProfile: "default-profile"}
repository := &requirementInspectionPromptRepository{ repository := &requirementInspectionPromptRepository{
definition: definition, definition: definition,
snapshotFound: true, snapshotFound: true,
@@ -113,7 +113,7 @@ func TestRunnerInspectRequirementsUsesCapturedSelectionWithoutExecutionWork(t *t
repository.snapshotCalls, repository.snapshotID) repository.snapshotCalls, repository.snapshotID)
} }
if profiles.calls != 1 || profiles.id != "partial-profile" || inspection.PromptID != definition.ID || if profiles.calls != 1 || profiles.id != "partial-profile" || inspection.PromptID != definition.ID ||
inspection.PromptVersion == nil || *inspection.PromptVersion != *definition.Version || inspection.ProfileID != "partial-profile" || !inspection.Complete || inspection.ProfileID != "partial-profile" || !inspection.Complete ||
len(inspection.Inputs) != 1 || inspection.Inputs[0].Name != "message-input" || len(inspection.Variables) != 1 || len(inspection.Inputs) != 1 || inspection.Inputs[0].Name != "message-input" || len(inspection.Variables) != 1 ||
inspection.Variables[0].Name != "caller" || !inspection.Variables[0].Supplied { inspection.Variables[0].Name != "caller" || !inspection.Variables[0].Supplied {
t.Fatalf("unexpected requirement inspection: %+v", inspection) t.Fatalf("unexpected requirement inspection: %+v", inspection)
@@ -138,7 +138,7 @@ func TestRunnerInspectRequirementsUsesPromptMetadataAndExactRequirementSnapshot(
promptRepository := &requirementPromptMetadataRepository{ promptRepository := &requirementPromptMetadataRepository{
requirementInspectionPromptRepository: baseRepository, requirementInspectionPromptRepository: baseRepository,
inspection: domain.PromptInspection{ inspection: domain.PromptInspection{
PromptID: "captured-id", PromptVersion: stringPtr("captured-version"), PromptHash: "captured-hash", PromptID: "captured-id", PromptHash: "captured-hash",
DefaultProfileID: "default-profile", DefaultProfileID: "default-profile",
}, },
} }
@@ -155,7 +155,7 @@ func TestRunnerInspectRequirementsUsesPromptMetadataAndExactRequirementSnapshot(
if err != nil || promptRepository.lookupID != " requested-id " || if err != nil || promptRepository.lookupID != " requested-id " ||
baseRepository.snapshotID != "captured-id" || baseRepository.snapshotID != "captured-id" ||
profiles.identityID != "default-profile" || inspection.PromptID != "captured-id" || profiles.identityID != "default-profile" || inspection.PromptID != "captured-id" ||
inspection.PromptVersion == nil || *inspection.PromptVersion != "captured-version" || inspection.ProfileID != "default-profile" || inspection.ProfileID != "default-profile" ||
!inspection.Complete || len(inspection.Inputs) != 1 || inspection.Inputs[0].Name != "message-input" || !inspection.Complete || len(inspection.Inputs) != 1 || inspection.Inputs[0].Name != "message-input" ||
len(inspection.Variables) != 1 || inspection.Variables[0].Name != "caller" || !inspection.Variables[0].Supplied { len(inspection.Variables) != 1 || inspection.Variables[0].Name != "caller" || !inspection.Variables[0].Supplied {
t.Fatalf("metadata-based requirement inspection=(%+v, %v), prompt lookup=%q, snapshot=%q, profile=%q", t.Fatalf("metadata-based requirement inspection=(%+v, %v), prompt lookup=%q, snapshot=%q, profile=%q",
@@ -168,7 +168,7 @@ func TestRunnerInspectRequirementsUsesProfileIdentityCapabilityOrFallback(t *tes
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
definition := &domain.PromptDefinition{ID: "selected", Version: stringPtr("v1")} definition := &domain.PromptDefinition{ID: "selected"}
makePromptRepository := func() *requirementInspectionPromptRepository { makePromptRepository := func() *requirementInspectionPromptRepository {
return &requirementInspectionPromptRepository{ return &requirementInspectionPromptRepository{
definition: definition, snapshotFound: true, definition: definition, snapshotFound: true,
@@ -234,7 +234,7 @@ func TestRunnerInspectRequirementsUsesPromptDefaultAndIncludesSessionWhenNotBypa
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
definition := &domain.PromptDefinition{ID: "selected", Version: stringPtr("v1"), DefaultProfile: "default-profile"} definition := &domain.PromptDefinition{ID: "selected", DefaultProfile: "default-profile"}
repository := &requirementInspectionPromptRepository{ repository := &requirementInspectionPromptRepository{
definition: definition, snapshotFound: true, definition: definition, snapshotFound: true,
snapshot: prompt.RequirementSnapshot{Templates: prompt.CompiledTemplates{Messages: []*template.Template{message}, Session: session}}, snapshot: prompt.RequirementSnapshot{Templates: prompt.CompiledTemplates{Messages: []*template.Template{message}, Session: session}},
@@ -260,7 +260,7 @@ func TestRunnerInspectRequirementsReturnsIncompleteDiscoveryAsSuccess(t *testing
t.Fatal(err) t.Fatal(err)
} }
repository := &requirementInspectionPromptRepository{ repository := &requirementInspectionPromptRepository{
definition: &domain.PromptDefinition{ID: "selected", Version: stringPtr("v1"), DefaultProfile: "profile"}, definition: &domain.PromptDefinition{ID: "selected", DefaultProfile: "profile"},
snapshotFound: true, snapshotFound: true,
snapshot: prompt.RequirementSnapshot{Templates: prompt.CompiledTemplates{Messages: []*template.Template{compiled}}}, snapshot: prompt.RequirementSnapshot{Templates: prompt.CompiledTemplates{Messages: []*template.Template{compiled}}},
} }

View File

@@ -29,7 +29,7 @@ func TestPreparationCompletesResolvedTargetThroughRequestOverrides(t *testing.T)
Temperature: 0, ExtraParams: map[string]any{"configured": true}, Temperature: 0, ExtraParams: map[string]any{"configured": true},
}, TargetPresence: domain.ExecutionTargetPresence{Temperature: true}} }, TargetPresence: domain.ExecutionTargetPresence{Temperature: true}}
runner := &Runner{ runner := &Runner{
promptDefs: staticPromptRepo{def: &domain.PromptDefinition{ID: "prompt", Version: stringPtr("v1"), Validation: domain.OutputContract{ promptDefs: staticPromptRepo{def: &domain.PromptDefinition{ID: "prompt", Validation: domain.OutputContract{
Format: domain.FormatText, ValidationMode: domain.ValidationNone, Format: domain.FormatText, ValidationMode: domain.ValidationNone,
}}}, }}},
profiles: staticExecutionProfileRepo{profile: profile}, renderer: staticRenderer{}, profiles: staticExecutionProfileRepo{profile: profile}, renderer: staticRenderer{},
@@ -63,7 +63,7 @@ func TestResolvedTargetCredentialAvailability(t *testing.T) {
Endpoint: "https://provider.example/v1", Model: "model", APIKeyRequired: true, Endpoint: "https://provider.example/v1", Model: "model", APIKeyRequired: true,
}} }}
runner := &Runner{ runner := &Runner{
promptDefs: staticPromptRepo{def: &domain.PromptDefinition{ID: "prompt", Version: stringPtr("v1"), Validation: domain.OutputContract{ promptDefs: staticPromptRepo{def: &domain.PromptDefinition{ID: "prompt", Validation: domain.OutputContract{
Format: domain.FormatText, ValidationMode: domain.ValidationNone, Format: domain.FormatText, ValidationMode: domain.ValidationNone,
}}}, }}},
profiles: staticExecutionProfileRepo{profile: profile}, renderer: staticRenderer{}, profiles: staticExecutionProfileRepo{profile: profile}, renderer: staticRenderer{},

View File

@@ -252,7 +252,6 @@ func (r *Runner) executePreparedRun(
RawOutput: genResp.Content, RawOutput: genResp.Content,
Validation: validationResult, Validation: validationResult,
PromptID: prepared.PromptID, PromptID: prepared.PromptID,
PromptVersion: copyStringPointer(prepared.PromptVersion),
PromptHash: prepared.PromptHash, PromptHash: prepared.PromptHash,
SessionID: prepared.SessionID, SessionID: prepared.SessionID,
RenderedPromptHash: prepared.RenderedPromptHash, RenderedPromptHash: prepared.RenderedPromptHash,
@@ -321,7 +320,7 @@ func (r *Runner) resolvePreparation(
} }
def := promptSelection.definition def := promptSelection.definition
if recorder := observation.FromContext(ctx); recorder != nil { if recorder := observation.FromContext(ctx); recorder != nil {
recorder.UpdateSelection(observation.Selection{PromptID: def.ID, PromptVersion: copyStringPointer(def.Version)}) recorder.UpdateSelection(observation.Selection{PromptID: def.ID})
} }
promptDefinitionHash := promptSelection.hash promptDefinitionHash := promptSelection.hash
effectiveContract, err := resolveOutputContract(def, req.Validation) effectiveContract, err := resolveOutputContract(def, req.Validation)
@@ -342,7 +341,7 @@ func (r *Runner) resolvePreparation(
return nil, err return nil, err
} }
if recorder := observation.FromContext(ctx); recorder != nil { if recorder := observation.FromContext(ctx); recorder != nil {
recorder.UpdateSelection(observation.Selection{PromptID: def.ID, PromptVersion: copyStringPointer(def.Version), ProfileID: selection.id}) recorder.UpdateSelection(observation.Selection{PromptID: def.ID, ProfileID: selection.id})
} }
effectiveModel, targetPresence := resolveExecutionTarget(selection.profile, req.Execution) effectiveModel, targetPresence := resolveExecutionTarget(selection.profile, req.Execution)
@@ -355,7 +354,7 @@ func (r *Runner) resolvePreparation(
return nil, fmt.Errorf("%w: %w", ErrInvalidRequest, err) return nil, fmt.Errorf("%w: %w", ErrInvalidRequest, err)
} }
if recorder := observation.FromContext(ctx); recorder != nil { if recorder := observation.FromContext(ctx); recorder != nil {
recorder.UpdateSelection(observation.Selection{PromptID: def.ID, PromptVersion: copyStringPointer(def.Version), recorder.UpdateSelection(observation.Selection{PromptID: def.ID,
ProfileID: selection.id, BackendID: effectiveModel.BackendID, Model: effectiveModel.Model}) ProfileID: selection.id, BackendID: effectiveModel.BackendID, Model: effectiveModel.Model})
} }
@@ -481,7 +480,6 @@ func (r *Runner) completePreparationWithStructuredOutput(
effectiveModel.APIKey = "" effectiveModel.APIKey = ""
return &domain.PreparedRun{ return &domain.PreparedRun{
PromptID: state.definition.ID, PromptID: state.definition.ID,
PromptVersion: copyStringPointer(state.definition.Version),
PromptHash: state.promptDefinitionHash, PromptHash: state.promptDefinitionHash,
SelectedProfileID: state.selectedProfileID, SelectedProfileID: state.selectedProfileID,
SelectedBackendID: state.effectiveModel.BackendID, SelectedBackendID: state.effectiveModel.BackendID,
@@ -713,11 +711,3 @@ func buildOutputArtifact(content string, format domain.OutputFormat) domain.Arti
func hashPromptDefinition(def *domain.PromptDefinition) (string, error) { func hashPromptDefinition(def *domain.PromptDefinition) (string, error) {
return promptdef.HashDefinition(def) return promptdef.HashDefinition(def)
} }
func copyStringPointer(value *string) *string {
if value == nil {
return nil
}
copy := *value
return &copy
}

View File

@@ -366,7 +366,7 @@ func TestRunnerPrepareWithExplicitProfileSelection(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("expected no error, got %v", err) t.Fatalf("expected no error, got %v", err)
} }
if prepared.PromptID != "p" || prepared.PromptVersion == nil || *prepared.PromptVersion != "1" { if prepared.PromptID != "p" {
t.Fatalf("unexpected prepared prompt metadata: %+v", prepared) t.Fatalf("unexpected prepared prompt metadata: %+v", prepared)
} }
if prepared.SelectedProfileID != "exec" { if prepared.SelectedProfileID != "exec" {
@@ -1257,7 +1257,7 @@ func TestRunnerRunSuccessful(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("expected no error, got %v", err) t.Fatalf("expected no error, got %v", err)
} }
if res.PromptID != "p" || res.PromptVersion == nil || *res.PromptVersion != "1" { if res.PromptID != "p" {
t.Fatalf("unexpected prompt metadata: %+v", res) t.Fatalf("unexpected prompt metadata: %+v", res)
} }
if res.SelectedProfileID != "exec" { if res.SelectedProfileID != "exec" {
@@ -2504,7 +2504,6 @@ func TestBuildOutputArtifactDefaults(t *testing.T) {
func promptDef(format domain.OutputFormat, mode domain.ValidationMode, attempts int) *domain.PromptDefinition { func promptDef(format domain.OutputFormat, mode domain.ValidationMode, attempts int) *domain.PromptDefinition {
return &domain.PromptDefinition{ return &domain.PromptDefinition{
ID: "p", ID: "p",
Version: stringPtr("1"),
DefaultProfile: "exec", DefaultProfile: "exec",
Inputs: []domain.PromptInput{{Name: "transcript", Required: true}}, Inputs: []domain.PromptInput{{Name: "transcript", Required: true}},
Templates: []domain.PromptMessageTemplate{{Role: "user", Content: "x"}}, Templates: []domain.PromptMessageTemplate{{Role: "user", Content: "x"}},

View File

@@ -129,7 +129,6 @@ func (r *Runner) resolveSmokeTestTarget(ctx context.Context, req domain.SmokeTes
if promptInspection != nil { if promptInspection != nil {
selection.target.PromptID = promptInspection.PromptID selection.target.PromptID = promptInspection.PromptID
selection.target.PromptVersion = promptInspection.PromptVersion
} }
selection.target.Endpoint, err = resolveSmokeTestEndpoint(req.Kind, selection.target.EffectiveSettings.Endpoint, selection.backend.SmokeTests) selection.target.Endpoint, err = resolveSmokeTestEndpoint(req.Kind, selection.target.EffectiveSettings.Endpoint, selection.backend.SmokeTests)
if err != nil { if err != nil {