Add PromptKit requirements validation command

This commit is contained in:
2026-10-12 22:16:44 +00:00
parent f5c1c69ccb
commit 686a7ba0ab
4 changed files with 264 additions and 13 deletions

View File

@@ -0,0 +1,90 @@
package ckprompt
import (
"bytes"
"context"
"io"
"reflect"
"testing"
commandkit "gitea.maximumdirect.net/eric/CommandKit"
"gitea.maximumdirect.net/eric/CommandKit/integrations/ckconfig"
promptkit "gitea.maximumdirect.net/eric/promptkit"
"go.yaml.in/yaml/v4"
)
func TestValidationCommandComposesWithRequirementsShow(t *testing.T) {
type input struct{ campaign commandkit.Supplied[string] }
type state struct{ sequence int }
campaignFlag := commandkit.ValueFlag(commandkit.FlagMeta{Name: "campaign", Usage: "Campaign selector."}, (*string)(nil), parseDefinitionString,
func(target *input, value commandkit.Supplied[string]) { target.campaign = value })
wantSelection := ckconfig.Selection{
Config: commandkit.Supplied[string]{Value: "config.yml", Set: true},
Overlay: commandkit.Supplied[string]{Value: "overlay.yml", Set: true},
}
wantInput := input{campaign: commandkit.Supplied[string]{Value: "spring", Set: true}}
var received ValidationRequest
var receivedInput input
validateCalls := 0
suite := Suite[input, state]{
NewInput: func() input { return input{} },
NewState: func() state { return state{sequence: 1} },
Selectors: []commandkit.Flag[input]{campaignFlag},
CheckInput: func(selection ckconfig.Selection, value input) error {
if selection != wantSelection || !reflect.DeepEqual(value, wantInput) {
t.Errorf("checked input = (%#v, %#v)", selection, value)
}
return nil
},
InspectRequirements: func(context.Context, RequirementsRequest, input, state) (commandkit.Acquired[*promptkit.RequirementInspection], error) {
return commandkit.Acquired[*promptkit.RequirementInspection]{Value: &promptkit.RequirementInspection{PromptID: "briefing"}}, nil
},
ValidateRequest: func(_ context.Context, request ValidationRequest, value input, gotState state) (commandkit.Acquired[struct{}], error) {
validateCalls++
received = request
receivedInput = value
if gotState.sequence != 1 {
t.Errorf("state = %#v", gotState)
}
return commandkit.Acquired[struct{}]{}, nil
},
}
app := newPromptTestApp(t, Command(suite))
var help bytes.Buffer
outcome := app.Execute(context.Background(), []string{"help", "promptkit", "requirements"}, commandkit.Streams{Out: &help, Err: io.Discard})
if outcome.Kind != commandkit.OutcomeSuccess || !bytes.Contains(help.Bytes(), []byte("show")) || !bytes.Contains(help.Bytes(), []byte("validate")) {
t.Fatalf("requirements help = (%#v, %q)", outcome, help.String())
}
var output bytes.Buffer
outcome = app.Execute(context.Background(), []string{
"promptkit", "requirements", "validate", "briefing",
"--config", "config.yml", "--overlay", "overlay.yml", "--campaign", "spring",
"--version", "v2", "--profile", "editorial", "--session-id", "session-1",
"--var", "topic=roadmap", "--input", "notes=fixtures/notes=final.txt", "--format", "yaml",
}, commandkit.Streams{Out: &output, Err: io.Discard})
if outcome.Kind != commandkit.OutcomeSuccess || outcome.Status != 0 || validateCalls != 1 {
t.Fatalf("validation outcome = (%#v, %q), calls=%d", outcome, output.String(), validateCalls)
}
if received.Selection != wantSelection || received.Request.PromptID != "briefing" || received.Request.PromptVersion != "v2" || received.Request.ProfileID != "editorial" || received.Request.SessionID != "session-1" {
t.Errorf("validation request = %#v", received)
}
if received.Request.Vars["topic"] != "roadmap" || len(received.Request.Vars) != 1 {
t.Errorf("request vars = %#v", received.Request.Vars)
}
if ref, ok := received.Request.Inputs["notes"]; !ok || ref != promptkit.File("fixtures/notes=final.txt") || len(received.Request.Inputs) != 1 {
t.Errorf("request inputs = %#v", received.Request.Inputs)
}
if !reflect.DeepEqual(receivedInput, wantInput) {
t.Errorf("provider input = %#v, want %#v", receivedInput, wantInput)
}
var report map[string]any
if err := yaml.Unmarshal(output.Bytes(), &report); err != nil {
t.Fatalf("decode validation report %q: %v", output.String(), err)
}
if len(report) != 2 || report["prompt_id"] != "briefing" || report["valid"] != true {
t.Fatalf("validation confirmation = %#v", report)
}
}