Verify ownership across execution and repair

This commit is contained in:
2026-11-05 20:14:37 +00:00
parent 5dd1418953
commit b3b5ec3820
2 changed files with 114 additions and 0 deletions

View File

@@ -410,6 +410,17 @@ configured-default/runtime-override diagnostics through the public facade.
## Stage 15: Verify Cross-Path Ownership And Runtime Compatibility
**Completed:** Cross-path checks cover mutations by an injected client on both
initial and repair requests, detached results and details, concurrent details
with claim/discard, and typed, numeric, null, cyclic, unsupported, and deep
runtime provider values. Remaining validating copies serve configuration
acceptance/overlay or public override acceptance; outward projections and schema
detachment remain ownership boundaries. Go 1.27.3 `go test -race
./internal/usecase ./internal/configuration ./internal/jsonvalue . -run
'Prepared|Provider|Extra|Smoke|Profile|Schema'` passed (the filtered jsonvalue
package selected no tests); the full `go test -race ./internal/jsonvalue` passed
separately.
**Findings:** 5–8. **Scope:** focused existing public and package contract tests.
1. Reconcile the ownership inventory with the delivered call paths. Verify that

View File

@@ -307,6 +307,95 @@ func TestPreparedExecutionRepairsEmptyBasicOutput(t *testing.T) {
}
}
func TestPreparedExecutionIsolatesMutatingClientAcrossRepair(t *testing.T) {
client := &mutatingRepairClient{}
engine, err := promptkit.NewEngine(preparedContractConfig("original message", false),
promptkit.WithSchemaFS(preparedSchemaSource(), "."), promptkit.WithLLMClient(client))
if err != nil {
t.Fatal(err)
}
prepared, err := engine.PrepareExecution(context.Background(), promptkit.RunRequest{
PromptID: "prepared",
Execution: &promptkit.ExecutionTargetOverride{ExtraParams: map[string]any{
"nested": map[string]any{"value": "original"},
}},
Validation: &promptkit.OutputContract{Format: promptkit.FormatJSON, ValidationMode: promptkit.ValidationJSONSchema, SchemaPath: "schema.json", RepairAttempts: 1},
AppendedMessages: []promptkit.RenderedMessage{{Role: "user", Content: "appended", CacheControl: &promptkit.CacheControl{Type: promptkit.CacheControlEphemeral, TTL: "1h"}}},
})
if err != nil {
t.Fatal(err)
}
before := prepared.Details()
result, err := engine.RunPrepared(context.Background(), prepared)
if err != nil || result == nil || result.Validation.Status != promptkit.ValidationPassed || client.calls != 2 {
t.Fatalf("run result = %+v, error = %v, calls = %d", result, err, client.calls)
}
if !reflect.DeepEqual(before, prepared.Details()) {
t.Fatal("client mutation changed retained prepared metadata")
}
result.EffectiveModelParams.ExtraParams["nested"].(map[string]any)["value"] = "result mutation"
if prepared.Details().EffectiveModelParams.ExtraParams["nested"].(map[string]any)["value"] != "original" {
t.Fatal("result mutation changed retained prepared metadata")
}
}
type mutatingRepairClient struct{ calls int }
func (c *mutatingRepairClient) Generate(_ context.Context, request promptkit.GenerateRequest) (*promptkit.GenerateResponse, error) {
c.calls++
if len(request.Prompt.Messages) < 2 || request.Prompt.Messages[0].Content != "original message" ||
request.Prompt.Messages[1].Content != "appended" || request.Prompt.Messages[1].CacheControl == nil ||
request.Prompt.Messages[1].CacheControl.TTL != "1h" ||
request.Target.ExtraParams["nested"].(map[string]any)["value"] != "original" ||
request.StructuredOutput.JSONSchema.Schema.(map[string]any)["title"] != "original root" {
return nil, fmt.Errorf("generation %d received mutated request", c.calls)
}
request.Prompt.Messages[0].Content = "client mutation"
request.Prompt.Messages[1].CacheControl.TTL = "client mutation"
request.Target.ExtraParams["nested"].(map[string]any)["value"] = "client mutation"
request.StructuredOutput.JSONSchema.Schema.(map[string]any)["title"] = "client mutation"
if c.calls == 1 {
return &promptkit.GenerateResponse{Content: `{"value":"invalid"}`}, nil
}
return &promptkit.GenerateResponse{Content: `{"value":3}`}, nil
}
type runtimeLabels []string
type runtimeCounts map[string]int
func TestPreparedExecutionRuntimeProviderValues(t *testing.T) {
engine := newPreparedContractEngine(t, &preparedRecordingClient{response: &promptkit.GenerateResponse{Content: "ok"}}, "message")
labels := runtimeLabels{"original"}
counts := runtimeCounts{"count": 3}
request := promptkit.RunRequest{PromptID: "prepared", Execution: &promptkit.ExecutionTargetOverride{ExtraParams: map[string]any{
"labels": labels, "counts": counts, "number": json.Number("9007199254740993"), "null": nil,
}}}
prepared, err := engine.PrepareExecution(context.Background(), request)
if err != nil {
t.Fatal(err)
}
labels[0], counts["count"] = "changed", 9
details := prepared.Details().EffectiveModelParams.ExtraParams
if details["labels"].(runtimeLabels)[0] != "original" || details["counts"].(runtimeCounts)["count"] != 3 ||
details["number"] != json.Number("9007199254740993") || details["null"] != nil {
t.Fatalf("runtime values changed: %#v", details)
}
cycle := map[string]any{}
cycle["self"] = cycle
var deep any = "leaf"
for range 150 {
deep = map[string]any{"child": deep}
}
for name, invalid := range map[string]any{"cyclic": cycle, "unsupported": func() {}, "too deep": deep} {
t.Run(name, func(t *testing.T) {
_, err := engine.PrepareExecution(context.Background(), promptkit.RunRequest{PromptID: "prepared", Execution: &promptkit.ExecutionTargetOverride{ExtraParams: map[string]any{"value": invalid}}})
if !errors.Is(err, promptkit.ErrInvalidRequest) {
t.Fatalf("invalid runtime provider value error = %v", err)
}
})
}
}
func TestPreparedExecutionConcurrentClaimAllowsOneGeneration(t *testing.T) {
release := make(chan struct{})
client := &preparedRecordingClient{
@@ -383,6 +472,7 @@ func TestPreparedExecutionRunAndDiscardRaceHasOneWinner(t *testing.T) {
}
runOutcome := make(chan outcome, 1)
discardDone := make(chan struct{})
detailsDone := make(chan bool, 1)
go func() {
<-start
@@ -394,10 +484,23 @@ func TestPreparedExecutionRunAndDiscardRaceHasOneWinner(t *testing.T) {
prepared.Discard()
close(discardDone)
}()
go func() {
<-start
for range 20 {
if prepared.Details().PromptID != "prepared" {
detailsDone <- false
return
}
}
detailsDone <- true
}()
close(start)
runResult := <-runOutcome
<-discardDone
if !<-detailsDone {
t.Fatalf("attempt %d lost details during lifecycle race", i)
}
calls := len(client.snapshot())
switch {
case runResult.err == nil: