2026-10-11 01:46:54 +00:00
package ckprompt
import (
"bytes"
"context"
"errors"
"io"
2026-10-12 17:05:33 +00:00
"reflect"
2026-10-17 18:39:38 +00:00
"strconv"
2026-10-11 01:46:54 +00:00
"strings"
"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"
)
2026-10-19 17:23:32 +00:00
func newPromptTestApp ( t * testing . T , declarations ... commandkit . Declaration ) * commandkit . App {
2026-10-11 01:46:54 +00:00
t . Helper ( )
2026-10-19 17:23:32 +00:00
app , err := commandkit . New ( commandkit . Identity { Name : "example" } , declarations ... )
2026-10-11 01:46:54 +00:00
if err != nil {
t . Fatal ( err )
}
return app
}
2026-10-17 18:39:38 +00:00
func testStringPointer ( value string ) * string { return & value }
2026-10-11 01:46:54 +00:00
func TestCommandBuildsIndependentOptionalTrees ( t * testing . T ) {
promptOnly := newPromptTestApp ( t , Command ( Suite [ struct { } , struct { } ] { InspectPrompt : func ( context . Context , PromptRequest , struct { } , struct { } ) ( commandkit . Acquired [ * promptkit . PromptInspection ] , error ) {
return commandkit . Acquired [ * promptkit . PromptInspection ] { } , errors . New ( "unused" )
} } ) )
var output bytes . Buffer
outcome := promptOnly . Execute ( context . Background ( ) , [ ] string { "help" , "promptkit" , "show" } , commandkit . Streams { Out : & output , Err : io . Discard } )
2026-10-12 17:05:33 +00:00
if outcome . Kind != commandkit . OutcomeSuccess || ! strings . Contains ( output . String ( ) , "\n prompt " ) || strings . Contains ( output . String ( ) , "\n profile " ) || strings . Contains ( output . String ( ) , "requirements" ) || strings . Contains ( output . String ( ) , "config" ) {
2026-10-11 01:46:54 +00:00
t . Fatalf ( "prompt-only help = (%#v, %q)" , outcome , output . String ( ) )
}
profileOnly := newPromptTestApp ( t , Command ( Suite [ struct { } , struct { } ] { InspectProfile : func ( context . Context , ProfileRequest , struct { } , struct { } ) ( commandkit . Acquired [ * promptkit . ProfileInspection ] , error ) {
return commandkit . Acquired [ * promptkit . ProfileInspection ] { } , errors . New ( "unused" )
} } ) )
output . Reset ( )
outcome = profileOnly . Execute ( context . Background ( ) , [ ] string { "help" , "promptkit" , "show" } , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeSuccess || ! strings . Contains ( output . String ( ) , "\n profile " ) || strings . Contains ( output . String ( ) , "\n prompt " ) {
t . Fatalf ( "profile-only help = (%#v, %q)" , outcome , output . String ( ) )
}
both := Command ( Suite [ struct { } , struct { } ] {
InspectPrompt : func ( context . Context , PromptRequest , struct { } , struct { } ) ( commandkit . Acquired [ * promptkit . PromptInspection ] , error ) {
return commandkit . Acquired [ * promptkit . PromptInspection ] { } , nil
} ,
InspectProfile : func ( context . Context , ProfileRequest , struct { } , struct { } ) ( commandkit . Acquired [ * promptkit . ProfileInspection ] , error ) {
return commandkit . Acquired [ * promptkit . ProfileInspection ] { } , nil
} ,
2026-10-12 17:05:33 +00:00
InspectRequirements : func ( context . Context , RequirementsRequest , struct { } , struct { } ) ( commandkit . Acquired [ * promptkit . RequirementInspection ] , error ) {
return commandkit . Acquired [ * promptkit . RequirementInspection ] { } , nil
} ,
2026-10-17 18:44:10 +00:00
ListPrompts : func ( context . Context , CatalogRequest , struct { } , struct { } ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
2026-10-12 17:05:33 +00:00
return commandkit . Acquired [ [ ] promptkit . PromptIdentity ] { } , nil
} ,
2026-10-17 18:44:10 +00:00
ListProfiles : func ( context . Context , CatalogRequest , struct { } , struct { } ) ( commandkit . Acquired [ [ ] string ] , error ) {
2026-10-12 17:05:33 +00:00
return commandkit . Acquired [ [ ] string ] { } , nil
} ,
2026-10-11 01:46:54 +00:00
} )
2026-10-12 17:05:33 +00:00
all := newPromptTestApp ( t , both )
output . Reset ( )
outcome = all . Execute ( context . Background ( ) , [ ] string { "help" , "promptkit" } , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeSuccess || ! strings . Contains ( output . String ( ) , "show" ) || ! strings . Contains ( output . String ( ) , "list" ) || ! strings . Contains ( output . String ( ) , "requirements" ) {
t . Fatalf ( "all-capability tree = (%#v, %q)" , outcome , output . String ( ) )
2026-10-11 01:46:54 +00:00
}
app := newPromptTestApp ( t , Command ( Suite [ struct { } , struct { } ] { Selectors : [ ] commandkit . Flag [ struct { } ] { { } } } ) )
output . Reset ( )
outcome = app . Execute ( context . Background ( ) , [ ] string { "help" } , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeSuccess || strings . Contains ( output . String ( ) , "promptkit" ) {
t . Fatalf ( "empty suite installed a namespace: (%#v, %q)" , outcome , output . String ( ) )
}
invalid := FromEngine [ int , int ] ( nil )
2026-10-17 18:46:47 +00:00
invalid . ListPrompts , invalid . ListProfiles , invalid . ListBackends = nil , nil , nil
invalid . ListNamespaces , invalid . ListCollections = nil , nil
2026-10-11 01:46:54 +00:00
invalid . InspectPrompt , invalid . InspectProfile = nil , nil
2026-10-12 17:05:33 +00:00
invalid . InspectRequirements = nil
2026-10-11 01:46:54 +00:00
if err := newPromptTestApp ( t ) . Register ( Command ( invalid ) ) ; err == nil || ! strings . Contains ( err . Error ( ) , "PromptKit engine loader is nil" ) {
t . Fatalf ( "empty invalid adapter lost its construction issue: %v" , err )
}
}
2026-10-12 17:05:33 +00:00
func TestRequirementsCommandCapturesContextAndVariableAssignments ( t * testing . T ) {
type input struct { campaign commandkit . Supplied [ string ] }
type state struct { call int }
campaignFlag := commandkit . ValueFlag ( commandkit . FlagMeta { Name : "campaign" , Usage : "Application campaign." } , ( * string ) ( nil ) , parseDefinitionString ,
func ( target * input , value commandkit . Supplied [ string ] ) { target . campaign = value } )
newInputCalls , checkInputCalls , newStateCalls , providerCalls := 0 , 0 , 0 , 0
var received RequirementsRequest
var receivedInput input
var receivedState state
suite := Suite [ input , state ] {
NewInput : func ( ) input {
newInputCalls ++
return input { }
} ,
NewState : func ( ) state {
newStateCalls ++
return state { call : newStateCalls }
} ,
Selectors : [ ] commandkit . Flag [ input ] { campaignFlag } ,
CheckInput : func ( selection ckconfig . Selection , value input ) error {
checkInputCalls ++
if checkInputCalls == 1 {
if ! selection . Config . Set || selection . Config . Value != "" || ! selection . Overlay . Set || selection . Overlay . Value != "" {
t . Errorf ( "checked selection = %#v" , selection )
}
if ! value . campaign . Set || value . campaign . Value != "spring" {
t . Errorf ( "checked campaign = %#v" , value . campaign )
}
} else if selection . Config . Set || selection . Overlay . Set || value . campaign . Set {
t . Errorf ( "second checked input retained prior invocation values: selection=%#v input=%#v" , selection , value )
}
return nil
} ,
InspectRequirements : func ( _ context . Context , request RequirementsRequest , value input , gotState state ) ( commandkit . Acquired [ * promptkit . RequirementInspection ] , error ) {
providerCalls ++
received , receivedInput , receivedState = request , value , gotState
return commandkit . Acquired [ * promptkit . RequirementInspection ] { Value : & promptkit . RequirementInspection {
2026-10-17 18:39:38 +00:00
PromptID : request . Inspection . PromptID , ProfileID : request . Inspection . ProfileID , Complete : true ,
2026-10-12 17:05:33 +00:00
} } , nil
} ,
}
app := newPromptTestApp ( t , Command ( suite ) )
streams := commandkit . Streams { Out : io . Discard , Err : io . Discard }
var help bytes . Buffer
streams . Out = & help
helpOutcome := app . Execute ( context . Background ( ) , [ ] string { "help" , "promptkit" , "requirements" , "show" } , streams )
if helpOutcome . Kind != commandkit . OutcomeSuccess || ! strings . Contains ( help . String ( ) , "id" ) {
t . Fatalf ( "requirements-only help = (%#v, %q)" , helpOutcome , help . String ( ) )
}
var familyHelp bytes . Buffer
familyOutcome := app . Execute ( context . Background ( ) , [ ] string { "help" , "promptkit" } , commandkit . Streams { Out : & familyHelp , Err : io . Discard } )
if familyOutcome . Kind != commandkit . OutcomeSuccess || ! strings . Contains ( familyHelp . String ( ) , "requirements" ) || strings . Contains ( familyHelp . String ( ) , "\n show " ) || strings . Contains ( familyHelp . String ( ) , "\n list " ) {
t . Fatalf ( "requirements-only family help = (%#v, %q)" , familyOutcome , familyHelp . String ( ) )
}
2026-10-17 18:39:38 +00:00
for _ , flag := range [ ] string { "--config" , "--overlay" , "--profile" , "--session-id" , "--var" , "--format" , "--campaign" } {
2026-10-12 17:05:33 +00:00
if ! strings . Contains ( help . String ( ) , flag ) {
t . Errorf ( "requirements help omits %s: %q" , flag , help . String ( ) )
}
}
if strings . Contains ( help . String ( ) , "--scope" ) || newInputCalls != 0 || checkInputCalls != 0 || newStateCalls != 0 || providerCalls != 0 {
t . Fatalf ( "help selected a scope or invoked application code: output=%q factories/checks/providers=%d/%d/%d/%d" , help . String ( ) , newInputCalls , checkInputCalls , newStateCalls , providerCalls )
}
var output bytes . Buffer
args := [ ] string {
"promptkit" , "requirements" , "show" , "briefing" , "--campaign" , "spring" ,
"--config" , "before.yml" , "--config=" , "--overlay" , "base.yml" , "--overlay=" ,
2026-10-17 18:39:38 +00:00
"--profile" , "first" , "--profile" , "editorial" ,
2026-10-12 17:05:33 +00:00
"--session-id" , "old-session" , "--session-id" , "session-42" , "--format" , "text" , "--format" , "yaml" ,
"--var" , "note=hello, world" , "--var" , "empty=" , "--var" , "token=a=b" , "--var" , "=value" ,
"--var" , "mode=brief" , "--var" , "mode=full" ,
}
outcome := app . Execute ( context . Background ( ) , args , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeSuccess || outcome . Status != 0 {
t . Fatalf ( "requirements invocation = %#v, output=%q" , outcome , output . String ( ) )
}
if newInputCalls != 1 || checkInputCalls != 1 || newStateCalls != 1 || providerCalls != 1 {
t . Fatalf ( "first invocation calls = input/check/state/provider %d/%d/%d/%d" , newInputCalls , checkInputCalls , newStateCalls , providerCalls )
}
if ! received . Selection . Config . Set || received . Selection . Config . Value != "" || ! received . Selection . Overlay . Set || received . Selection . Overlay . Value != "" {
t . Fatalf ( "configuration selection = %#v" , received . Selection )
}
wantVariables := map [ string ] string { "note" : "hello, world" , "empty" : "" , "token" : "a=b" , "" : "value" , "mode" : "full" }
2026-10-17 18:39:38 +00:00
if received . Inspection . PromptID != "briefing" || received . Inspection . ProfileID != "editorial" || received . Inspection . SessionID != "session-42" || ! reflect . DeepEqual ( received . Inspection . Vars , wantVariables ) {
2026-10-12 17:05:33 +00:00
t . Fatalf ( "native request = %#v, want vars %#v" , received . Inspection , wantVariables )
}
if ! receivedInput . campaign . Set || receivedInput . campaign . Value != "spring" || receivedState . call != 1 {
t . Fatalf ( "provider input/state = %#v/%#v" , receivedInput , receivedState )
}
var report map [ string ] any
if err := yaml . Unmarshal ( output . Bytes ( ) , & report ) ; err != nil || report [ "prompt_id" ] != "briefing" || report [ "complete" ] != true {
t . Fatalf ( "default requirements YAML = %#v (decode error %v), output=%q" , report , err , output . String ( ) )
}
output . Reset ( )
outcome = app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "requirements" , "show" , "briefing" } , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeSuccess || newInputCalls != 2 || checkInputCalls != 2 || newStateCalls != 2 || providerCalls != 2 {
t . Fatalf ( "second invocation = %#v, calls=%d/%d/%d/%d" , outcome , newInputCalls , checkInputCalls , newStateCalls , providerCalls )
}
2026-10-17 18:39:38 +00:00
if len ( received . Inspection . Vars ) != 0 || received . Inspection . ProfileID != "" || received . Inspection . SessionID != "" {
2026-10-12 17:05:33 +00:00
t . Fatalf ( "second invocation retained native values: %#v" , received . Inspection )
}
2026-10-12 17:45:35 +00:00
var defaultReport map [ string ] any
if err := yaml . Unmarshal ( output . Bytes ( ) , & defaultReport ) ; err != nil || defaultReport [ "prompt_id" ] != "briefing" {
t . Fatalf ( "omitted format did not produce the selected prompt's YAML report: %#v (decode error %v), output=%q" , defaultReport , err , output . String ( ) )
2026-10-12 17:05:33 +00:00
}
}
func TestRequirementsCommandUsageFailuresPrecedeApplicationPreparation ( t * testing . T ) {
for _ , test := range [ ] struct {
name string
args [ ] string
} {
{ name : "missing operand" , args : [ ] string { "promptkit" , "requirements" , "show" } } ,
{ name : "extra operand" , args : [ ] string { "promptkit" , "requirements" , "show" , "briefing" , "extra" } } ,
{ name : "unsupported format" , args : [ ] string { "promptkit" , "requirements" , "show" , "briefing" , "--format" , "text" } } ,
{ name : "malformed variable followed by valid assignment" , args : [ ] string { "promptkit" , "requirements" , "show" , "briefing" , "--var" , "broken" , "--var" , "mode=full" } } ,
{ name : "no built-in scope" , args : [ ] string { "promptkit" , "requirements" , "show" , "briefing" , "--scope" , "all" } } ,
{ name : "malformed variable on help" , args : [ ] string { "help" , "promptkit" , "requirements" , "show" , "--var" , "broken" } } ,
} {
t . Run ( test . name , func ( t * testing . T ) {
newInputCalls , checkInputCalls , newStateCalls , providerCalls := 0 , 0 , 0 , 0
suite := Suite [ struct { } , struct { } ] {
NewInput : func ( ) struct { } { newInputCalls ++ ; return struct { } { } } ,
CheckInput : func ( ckconfig . Selection , struct { } ) error {
checkInputCalls ++
return nil
} ,
NewState : func ( ) struct { } { newStateCalls ++ ; return struct { } { } } ,
InspectRequirements : func ( context . Context , RequirementsRequest , struct { } , struct { } ) ( commandkit . Acquired [ * promptkit . RequirementInspection ] , error ) {
providerCalls ++
return commandkit . Acquired [ * promptkit . RequirementInspection ] { Value : & promptkit . RequirementInspection { } } , nil
} ,
}
var output bytes . Buffer
outcome := newPromptTestApp ( t , Command ( suite ) ) . Execute ( context . Background ( ) , test . args , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeUsage || outcome . Status != 2 || newInputCalls != 0 || checkInputCalls != 0 || newStateCalls != 0 || providerCalls != 0 {
t . Fatalf ( "usage failure = %#v, factories/checks/providers=%d/%d/%d/%d output=%q" , outcome , newInputCalls , checkInputCalls , newStateCalls , providerCalls , output . String ( ) )
}
} )
}
}
2026-10-12 02:17:54 +00:00
func TestCatalogCommandTreesAreIndependentAndOmitShow ( t * testing . T ) {
prompts := Command ( Suite [ struct { } , struct { } ] {
2026-10-17 18:44:10 +00:00
ListPrompts : func ( context . Context , CatalogRequest , struct { } , struct { } ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
2026-10-12 02:17:54 +00:00
return commandkit . Acquired [ [ ] promptkit . PromptIdentity ] { } , nil
} ,
} )
profiles := Command ( Suite [ struct { } , struct { } ] {
2026-10-17 18:44:10 +00:00
ListProfiles : func ( context . Context , CatalogRequest , struct { } , struct { } ) ( commandkit . Acquired [ [ ] string ] , error ) {
2026-10-12 02:17:54 +00:00
return commandkit . Acquired [ [ ] string ] { } , nil
} ,
} )
for _ , test := range [ ] struct {
name string
cmd commandkit . Command
want string
omit string
} {
{ name : "prompts" , cmd : prompts , want : "prompts" , omit : "profiles" } ,
{ name : "profiles" , cmd : profiles , want : "profiles" , omit : "prompts" } ,
} {
t . Run ( test . name , func ( t * testing . T ) {
app := newPromptTestApp ( t , test . cmd )
var output bytes . Buffer
outcome := app . Execute ( context . Background ( ) , [ ] string { "help" , "promptkit" , "list" } , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeSuccess || ! strings . Contains ( output . String ( ) , "list" ) || ! strings . Contains ( output . String ( ) , test . want ) || strings . Contains ( output . String ( ) , test . omit ) || strings . Contains ( output . String ( ) , "show" ) {
t . Fatalf ( "catalog-only help = (%#v, %q)" , outcome , output . String ( ) )
}
} )
}
2026-10-12 02:24:25 +00:00
mixed := Command ( Suite [ struct { } , struct { } ] {
InspectPrompt : func ( context . Context , PromptRequest , struct { } , struct { } ) ( commandkit . Acquired [ * promptkit . PromptInspection ] , error ) {
return commandkit . Acquired [ * promptkit . PromptInspection ] { } , nil
} ,
2026-10-17 18:44:10 +00:00
ListPrompts : func ( context . Context , CatalogRequest , struct { } , struct { } ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
2026-10-12 02:24:25 +00:00
return commandkit . Acquired [ [ ] promptkit . PromptIdentity ] { } , nil
} ,
} )
output := new ( bytes . Buffer )
outcome := newPromptTestApp ( t , mixed ) . Execute ( context . Background ( ) , [ ] string { "help" , "promptkit" } , commandkit . Streams { Out : output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeSuccess || ! strings . Contains ( output . String ( ) , "show" ) || ! strings . Contains ( output . String ( ) , "list" ) {
t . Fatalf ( "mixed catalog/show help = (%#v, %q)" , outcome , output . String ( ) )
}
2026-10-12 02:17:54 +00:00
}
2026-10-17 18:46:47 +00:00
func TestAdditionalCatalogsInstallIndependentlyAndCaptureCallbacks ( t * testing . T ) {
for _ , name := range [ ] string { "backends" , "namespaces" , "collections" } {
t . Run ( name , func ( t * testing . T ) {
calls := 0
var namespaceRequest NamespaceRequest
suite := Suite [ struct { } , struct { } ] { }
args := [ ] string { "promptkit" , "list" , name }
switch name {
case "backends" :
suite . ListBackends = func ( context . Context , CatalogRequest , struct { } , struct { } ) ( commandkit . Acquired [ [ ] string ] , error ) {
calls ++
return commandkit . Acquired [ [ ] string ] { Value : [ ] string { "local" } } , nil
}
case "namespaces" :
suite . ListNamespaces = func ( _ context . Context , request NamespaceRequest , _ , _ struct { } ) ( commandkit . Acquired [ [ ] string ] , error ) {
calls ++
namespaceRequest = request
return commandkit . Acquired [ [ ] string ] { Value : [ ] string { "team" } } , nil
}
case "collections" :
suite . ListCollections = func ( context . Context , ckconfig . Selection , struct { } , struct { } ) ( commandkit . Acquired [ [ ] promptkit . CollectionInfo ] , error ) {
calls ++
return commandkit . Acquired [ [ ] promptkit . CollectionInfo ] { Value : [ ] promptkit . CollectionInfo { } } , nil
}
}
app := newPromptTestApp ( t , Command ( suite ) )
switch name {
case "backends" :
suite . ListBackends = nil
case "namespaces" :
suite . ListNamespaces = nil
case "collections" :
suite . ListCollections = nil
}
var help bytes . Buffer
outcome := app . Execute ( context . Background ( ) , [ ] string { "help" , "promptkit" , "list" } , commandkit . Streams { Out : & help , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeSuccess || ! strings . Contains ( help . String ( ) , "\n " + name + " " ) || calls != 0 {
t . Fatalf ( "independent list help = (%#v, %q), calls=%d" , outcome , help . String ( ) , calls )
}
var unavailableArgs [ ] string
switch name {
case "namespaces" :
unavailableArgs = append ( append ( [ ] string ( nil ) , args ... ) , "--namespace" , "team" )
case "collections" :
unavailableArgs = append ( append ( [ ] string ( nil ) , args ... ) , "--kind" , "prompt" )
}
if len ( unavailableArgs ) != 0 {
if got := app . Execute ( context . Background ( ) , unavailableArgs , commandkit . Streams { Out : io . Discard , Err : io . Discard } ) ; got . Kind != commandkit . OutcomeUsage || calls != 0 {
t . Fatalf ( "unavailable %s filter = %#v, calls=%d" , name , got , calls )
}
}
if got := app . Execute ( context . Background ( ) , args , commandkit . Streams { Out : io . Discard , Err : io . Discard } ) ; got . Kind != commandkit . OutcomeSuccess || calls != 1 {
t . Fatalf ( "captured %s callback = (%#v, calls=%d)" , name , got , calls )
}
if name == "namespaces" && ( namespaceRequest . Selection . Config . Set || len ( namespaceRequest . Kinds ) != 0 ) {
t . Fatalf ( "omitted namespace selection = %#v" , namespaceRequest )
}
} )
}
}
2026-10-17 18:45:39 +00:00
func TestDiscoveryCommandsForwardFiltersAndRenderCollections ( t * testing . T ) {
var promptRequest , profileRequest , backendRequest CatalogRequest
var namespaceRequest NamespaceRequest
var collectionSelection ckconfig . Selection
providers := 0
suite := Suite [ struct { } , struct { } ] {
ListPrompts : func ( _ context . Context , request CatalogRequest , _ , _ struct { } ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
providers ++
promptRequest = request
return commandkit . Acquired [ [ ] promptkit . PromptIdentity ] { Value : [ ] promptkit . PromptIdentity { { ID : "team/briefing" , Version : testStringPointer ( "" ) } } } , nil
} ,
ListProfiles : func ( _ context . Context , request CatalogRequest , _ , _ struct { } ) ( commandkit . Acquired [ [ ] string ] , error ) {
providers ++
profileRequest = request
return commandkit . Acquired [ [ ] string ] { Value : [ ] string { "default" } } , nil
} ,
ListBackends : func ( _ context . Context , request CatalogRequest , _ , _ struct { } ) ( commandkit . Acquired [ [ ] string ] , error ) {
providers ++
backendRequest = request
return commandkit . Acquired [ [ ] string ] { Value : [ ] string { "local" } } , nil
} ,
ListNamespaces : func ( _ context . Context , request NamespaceRequest , _ , _ struct { } ) ( commandkit . Acquired [ [ ] string ] , error ) {
providers ++
namespaceRequest = request
return commandkit . Acquired [ [ ] string ] { Value : [ ] string { "team" , "root" } } , nil
} ,
ListCollections : func ( _ context . Context , selection ckconfig . Selection , _ , _ struct { } ) ( commandkit . Acquired [ [ ] promptkit . CollectionInfo ] , error ) {
providers ++
collectionSelection = selection
return commandkit . Acquired [ [ ] promptkit . CollectionInfo ] { Value : [ ] promptkit . CollectionInfo {
{ Namespace : "team" , ReleaseVersion : testStringPointer ( "v1" ) } ,
{ Namespace : "empty-version" , ReleaseVersion : testStringPointer ( "" ) } ,
{ Namespace : "unversioned" } ,
} } , nil
} ,
}
app := newPromptTestApp ( t , Command ( suite ) )
run := func ( args ... string ) ( commandkit . Outcome , string ) {
t . Helper ( )
var output bytes . Buffer
outcome := app . Execute ( context . Background ( ) , args , commandkit . Streams { Out : & output , Err : io . Discard } )
return outcome , output . String ( )
}
outcome , output := run ( "promptkit" , "list" , "prompts" , "--namespace" , "first" , "--namespace" , "team" , "--all-namespaces=false" , "--config" , "selected.yml" )
if outcome . Kind != commandkit . OutcomeSuccess || promptRequest . Filter != ( promptkit . NamespaceFilter { Mode : promptkit . NamespaceNamed , Name : "team" } ) || ! promptRequest . Selection . Config . Set || promptRequest . Selection . Config . Value != "selected.yml" {
t . Fatalf ( "prompt list outcome/request = (%#v, %#v), output=%q" , outcome , promptRequest , output )
}
var promptRows [ ] map [ string ] any
if err := yaml . Unmarshal ( [ ] byte ( output ) , & promptRows ) ; err != nil || len ( promptRows ) != 1 || promptRows [ 0 ] [ "id" ] != "team/briefing" || promptRows [ 0 ] [ "version" ] != "" {
t . Fatalf ( "prompt catalog YAML = %#v, error=%v, output=%q" , promptRows , err , output )
}
outcome , _ = run ( "promptkit" , "list" , "profiles" , "--namespace" , "" )
if outcome . Kind != commandkit . OutcomeSuccess || profileRequest . Filter . Mode != promptkit . NamespaceUnqualified || profileRequest . Filter . Name != "" {
t . Fatalf ( "profile list outcome/filter = (%#v, %#v)" , outcome , profileRequest . Filter )
}
2026-10-17 18:46:47 +00:00
outcome , _ = run ( "promptkit" , "list" , "backends" , "--all-namespaces=false" )
if outcome . Kind != commandkit . OutcomeSuccess || backendRequest . Filter . Mode != promptkit . NamespaceDefault {
t . Fatalf ( "explicit false backend filter = (%#v, %#v)" , outcome , backendRequest . Filter )
}
2026-10-17 18:45:39 +00:00
outcome , _ = run ( "promptkit" , "list" , "backends" , "--all-namespaces" )
if outcome . Kind != commandkit . OutcomeSuccess || backendRequest . Filter . Mode != promptkit . NamespaceAll {
t . Fatalf ( "backend list outcome/filter = (%#v, %#v)" , outcome , backendRequest . Filter )
}
outcome , output = run ( "promptkit" , "list" , "namespaces" , "--kind" , "prompt" , "--kind" , "backend" )
if outcome . Kind != commandkit . OutcomeSuccess || ! reflect . DeepEqual ( namespaceRequest . Kinds , [ ] promptkit . ResourceKind { promptkit . ResourcePrompt , promptkit . ResourceBackend } ) {
t . Fatalf ( "namespace list outcome/kinds = (%#v, %#v)" , outcome , namespaceRequest . Kinds )
}
var namespaces [ ] string
if err := yaml . Unmarshal ( [ ] byte ( output ) , & namespaces ) ; err != nil || ! reflect . DeepEqual ( namespaces , [ ] string { "team" , "root" } ) {
t . Fatalf ( "namespace YAML = %#v, error=%v, output=%q" , namespaces , err , output )
}
outcome , output = run ( "promptkit" , "list" , "collections" , "--config" , "collections.yml" )
if outcome . Kind != commandkit . OutcomeSuccess || ! collectionSelection . Config . Set || collectionSelection . Config . Value != "collections.yml" {
t . Fatalf ( "collection list outcome/selection = (%#v, %#v)" , outcome , collectionSelection )
}
var collections [ ] map [ string ] any
if err := yaml . Unmarshal ( [ ] byte ( output ) , & collections ) ; err != nil || len ( collections ) != 3 || collections [ 0 ] [ "namespace" ] != "team" || collections [ 0 ] [ "version" ] != "v1" || collections [ 1 ] [ "version" ] != "" || collections [ 2 ] [ "version" ] != nil {
t . Fatalf ( "collection YAML = %#v, error=%v, output=%q" , collections , err , output )
}
beforeConflict := providers
outcome , _ = run ( "promptkit" , "list" , "backends" , "--namespace" , "team" , "--all-namespaces" )
if outcome . Kind != commandkit . OutcomeUsage || providers != beforeConflict {
t . Fatalf ( "conflicting namespace filters = %#v, provider calls %d -> %d" , outcome , beforeConflict , providers )
}
2026-10-17 18:46:47 +00:00
if providers != 6 {
t . Fatalf ( "catalog providers called = %d, want six" , providers )
2026-10-17 18:45:39 +00:00
}
}
2026-10-12 02:17:54 +00:00
func TestCatalogListUsesPreparedInputAndPreflightsFormat ( t * testing . T ) {
type input struct { campaign commandkit . Supplied [ string ] }
type state struct { token int }
flag := commandkit . ValueFlag ( commandkit . FlagMeta { Name : "campaign" } , ( * string ) ( nil ) ,
func ( value string ) ( string , error ) { return value , nil } ,
func ( target * input , value commandkit . Supplied [ string ] ) { target . campaign = value } )
newInputCalls , newStateCalls , providerCalls := 0 , 0 , 0
var received input
var receivedSelection ckconfig . Selection
var receivedState state
suite := Suite [ input , state ] {
NewInput : func ( ) input { newInputCalls ++ ; return input { } } ,
NewState : func ( ) state { newStateCalls ++ ; return state { token : newStateCalls } } ,
Selectors : [ ] commandkit . Flag [ input ] { flag } ,
CheckInput : func ( selection ckconfig . Selection , value input ) error {
if ! value . campaign . Set || value . campaign . Value != "spring" {
t . Errorf ( "checked campaign = %#v" , value . campaign )
}
if ! selection . Config . Set || selection . Config . Value != "" || ! selection . Overlay . Set || selection . Overlay . Value != "base.yml" {
t . Errorf ( "checked selection = %#v" , selection )
}
return nil
} ,
2026-10-17 18:44:10 +00:00
ListPrompts : func ( _ context . Context , request CatalogRequest , value input , gotState state ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
2026-10-12 02:17:54 +00:00
providerCalls ++
2026-10-17 18:44:10 +00:00
received , receivedSelection , receivedState = value , request . Selection , gotState
2026-10-17 18:39:38 +00:00
return commandkit . Acquired [ [ ] promptkit . PromptIdentity ] { Value : [ ] promptkit . PromptIdentity { { ID : "briefing" , Version : testStringPointer ( "1" ) } } } , nil
2026-10-12 02:17:54 +00:00
} ,
}
app := newPromptTestApp ( t , Command ( suite ) )
var output bytes . Buffer
invalid := app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "list" , "prompts" , "--format" , "text" } , commandkit . Streams { Out : & output , Err : io . Discard } )
if invalid . Kind != commandkit . OutcomeUsage || newInputCalls != 0 || newStateCalls != 0 || providerCalls != 0 || output . Len ( ) != 0 {
t . Fatalf ( "invalid format preflight = %#v, factories/providers=%d/%d/%d output=%q" , invalid , newInputCalls , newStateCalls , providerCalls , output . String ( ) )
}
outcome := app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "list" , "prompts" , "--config" , "" , "--overlay" , "base.yml" , "--campaign" , "spring" } , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeSuccess || newInputCalls != 1 || newStateCalls != 1 || providerCalls != 1 {
t . Fatalf ( "catalog invocation = %#v, factories/providers=%d/%d/%d output=%q" , outcome , newInputCalls , newStateCalls , providerCalls , output . String ( ) )
}
2026-10-12 02:24:25 +00:00
if ! received . campaign . Set || received . campaign . Value != "spring" || ! receivedSelection . Config . Set || receivedSelection . Config . Value != "" || ! receivedSelection . Overlay . Set || receivedSelection . Overlay . Value != "base.yml" || receivedState . token != 1 {
2026-10-12 02:17:54 +00:00
t . Fatalf ( "provider values = input %#v selection %#v state %#v" , received , receivedSelection , receivedState )
}
}
2026-10-12 02:24:25 +00:00
func TestCatalogLifecycleCapturesSelectorsAndRefreshesInvocationValues ( t * testing . T ) {
type input struct {
campaign commandkit . Supplied [ string ]
shadow commandkit . Supplied [ string ]
enabled commandkit . Supplied [ bool ]
limit commandkit . Supplied [ int ]
labels commandkit . Supplied [ [ ] string ]
}
type state struct { run int }
conversions , newInputs , newStates , checks , providers := 0 , 0 , 0 , 0 , 0
reject := false
flag := commandkit . ValueFlag ( commandkit . FlagMeta { Name : "campaign" } , ( * string ) ( nil ) , func ( value string ) ( string , error ) {
conversions ++
return value , nil
} , func ( target * input , value commandkit . Supplied [ string ] ) { target . campaign = value } )
lookalike := commandkit . ValueFlag ( commandkit . FlagMeta { Name : "campaign" } , ( * string ) ( nil ) ,
func ( value string ) ( string , error ) { return value , nil } ,
func ( target * input , value commandkit . Supplied [ string ] ) { target . shadow = value } )
enabled := commandkit . BoolFlag ( commandkit . FlagMeta { Name : "enabled" } , true , func ( target * input , value commandkit . Supplied [ bool ] ) { target . enabled = value } )
limit := commandkit . ValueFlag ( commandkit . FlagMeta { Name : "limit" } , ( * int ) ( nil ) , func ( value string ) ( int , error ) {
if value != "0" {
return 0 , errors . New ( "test accepts only zero" )
}
return 0 , nil
} , func ( target * input , value commandkit . Supplied [ int ] ) { target . limit = value } )
labels := commandkit . RepeatFlag ( commandkit . FlagMeta { Name : "label" } , [ ] string ( nil ) , func ( value string ) ( string , error ) { return value , nil } ,
func ( target * input , value commandkit . Supplied [ [ ] string ] ) { target . labels = value } )
selectors := [ ] commandkit . Flag [ input ] { flag , enabled , limit , labels }
suite := Suite [ input , * state ] {
NewInput : func ( ) input { newInputs ++ ; return input { } } ,
NewState : func ( ) * state {
newStates ++
if checks != newStates {
t . Errorf ( "state initialized after %d checks; state count %d" , checks , newStates )
}
return & state { run : newStates }
} ,
Selectors : selectors ,
CheckInput : func ( selection ckconfig . Selection , got input ) error {
checks ++
if reject {
return errors . New ( "catalog input rejected" )
}
if checks == 1 {
if ! selection . Config . Set || selection . Config . Value != "" || ! selection . Overlay . Set || selection . Overlay . Value != "" || ! got . campaign . Set || got . campaign . Value != "" || got . shadow . Set || ! got . enabled . Set || got . enabled . Value || ! got . limit . Set || got . limit . Value != 0 || ! got . labels . Set || len ( got . labels . Value ) != 2 || got . labels . Value [ 0 ] != "late" || got . labels . Value [ 1 ] != "early" {
return errors . New ( "supplied catalog values were not preserved" )
}
} else if selection . Config . Set || selection . Overlay . Set || got . campaign . Set || got . shadow . Set || got . enabled . Set || got . limit . Set || got . labels . Set {
return errors . New ( "catalog values leaked between invocations" )
}
return nil
} ,
2026-10-17 18:44:10 +00:00
ListPrompts : func ( _ context . Context , request CatalogRequest , got input , gotState * state ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
2026-10-12 02:24:25 +00:00
providers ++
if gotState == nil || gotState . run != providers {
t . Errorf ( "provider state = %#v at invocation %d" , gotState , providers )
}
2026-10-17 18:44:10 +00:00
if providers == 1 && ( ! request . Selection . Config . Set || request . Selection . Config . Value != "" || ! request . Selection . Overlay . Set || request . Selection . Overlay . Value != "" || ! got . campaign . Set || ! got . enabled . Set || ! got . limit . Set || ! got . labels . Set ) {
t . Errorf ( "first provider values = selection %#v input %#v" , request . Selection , got )
2026-10-12 02:24:25 +00:00
}
return commandkit . Acquired [ [ ] promptkit . PromptIdentity ] { Value : [ ] promptkit . PromptIdentity { } } , nil
} ,
}
declaration := Command ( suite )
if conversions + newInputs + newStates + checks + providers != 0 {
t . Fatal ( "command construction invoked suite callbacks" )
}
selectors [ 0 ] = lookalike
app := newPromptTestApp ( t , declaration )
if conversions + newInputs + newStates + checks + providers != 0 {
t . Fatal ( "installation invoked suite callbacks" )
}
var output bytes . Buffer
for _ , args := range [ ] [ ] string { { "help" , "promptkit" , "list" , "prompts" } , { "version" } } {
outcome := app . Execute ( context . Background ( ) , args , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeSuccess {
t . Fatalf ( "non-invoking command %v = %#v" , args , outcome )
}
}
output . Reset ( )
outcome := app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "list" , "prompts" , "--campaign" , "spring" , "--help" } , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeSuccess || conversions != 1 || newInputs + newStates + checks + providers != 0 {
t . Fatalf ( "help with supplied flag = %#v conversions=%d callbacks=%d/%d/%d/%d output=%q" , outcome , conversions , newInputs , newStates , providers , checks , output . String ( ) )
}
output . Reset ( )
outcome = app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "list" , "prompts" , "--campaign" , "" , "--enabled=false" , "--limit" , "0" , "--label" , "late" , "--label=early" , "--config" , "" , "--overlay" , "" } , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeSuccess || conversions != 2 || newInputs != 1 || newStates != 1 || checks != 1 || providers != 1 {
t . Fatalf ( "supplied catalog invocation = %#v counts convert/input/state/check/provider=%d/%d/%d/%d/%d output=%q" , outcome , conversions , newInputs , newStates , checks , providers , output . String ( ) )
}
output . Reset ( )
outcome = app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "list" , "prompts" } , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeSuccess || newInputs != 2 || newStates != 2 || checks != 2 || providers != 2 {
t . Fatalf ( "fresh catalog invocation = %#v counts input/state/check/provider=%d/%d/%d/%d" , outcome , newInputs , newStates , checks , providers )
}
reject = true
outcome = app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "list" , "prompts" } , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeUsage || newInputs != 3 || newStates != 2 || checks != 3 || providers != 2 {
t . Fatalf ( "rejected input reached state/provider: %#v counts input/state/check/provider=%d/%d/%d/%d" , outcome , newInputs , newStates , checks , providers )
}
}
func TestCatalogNilFactoriesSupplyZeroValues ( t * testing . T ) {
app := newPromptTestApp ( t , Command ( Suite [ * struct { } , * struct { } ] {
2026-10-17 18:44:10 +00:00
ListPrompts : func ( _ context . Context , request CatalogRequest , input , state * struct { } ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
if input != nil || state != nil || request . Selection . Config . Set || request . Selection . Overlay . Set {
t . Errorf ( "nil-factory values = selection %#v input %#v state %#v" , request . Selection , input , state )
2026-10-12 02:24:25 +00:00
}
return commandkit . Acquired [ [ ] promptkit . PromptIdentity ] { } , nil
} ,
} ) )
outcome := app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "list" , "prompts" } , commandkit . Streams { Out : io . Discard , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeSuccess {
t . Fatalf ( "nil-factory catalog outcome = %#v" , outcome )
}
}
func TestCatalogCommandsRenderNativeValuesAndEmptySequences ( t * testing . T ) {
prompts := [ ] promptkit . PromptIdentity {
2026-10-17 18:39:38 +00:00
{ ID : "later" , Version : testStringPointer ( "1.10" ) } ,
{ ID : "001" , Version : testStringPointer ( " 03 " ) } ,
{ ID : "a: true" , Version : testStringPointer ( "yes" ) } ,
{ ID : "without-version" } ,
2026-10-12 02:24:25 +00:00
}
profiles := [ ] string { "later" , "001" , "a: true" , "later" }
suite := Suite [ struct { } , struct { } ] {
2026-10-17 18:44:10 +00:00
ListPrompts : func ( context . Context , CatalogRequest , struct { } , struct { } ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
2026-10-12 02:24:25 +00:00
return commandkit . Acquired [ [ ] promptkit . PromptIdentity ] { Value : prompts } , nil
} ,
2026-10-17 18:44:10 +00:00
ListProfiles : func ( context . Context , CatalogRequest , struct { } , struct { } ) ( commandkit . Acquired [ [ ] string ] , error ) {
2026-10-12 02:24:25 +00:00
return commandkit . Acquired [ [ ] string ] { Value : profiles } , nil
} ,
}
app := newPromptTestApp ( t , Command ( suite ) )
var output bytes . Buffer
outcome := app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "list" , "prompts" } , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeSuccess {
t . Fatalf ( "default prompt YAML outcome = %#v" , outcome )
}
var promptEntries [ ] map [ string ] any
if err := yaml . Unmarshal ( output . Bytes ( ) , & promptEntries ) ; err != nil {
t . Fatalf ( "decode prompt command output %q: %v" , output . String ( ) , err )
}
if len ( promptEntries ) != len ( prompts ) {
t . Fatalf ( "prompt output is not the native sequence: %#v" , promptEntries )
}
for index , entry := range promptEntries {
id , idOK := entry [ "id" ] . ( string )
2026-10-17 18:39:38 +00:00
if ! idOK || id != prompts [ index ] . ID {
t . Errorf ( "prompt entry %d = %#v, want ID %q" , index , entry , prompts [ index ] . ID )
}
version , versionExists := entry [ "version" ]
if prompts [ index ] . Version == nil {
if versionExists || len ( entry ) != 1 {
t . Errorf ( "prompt entry %d emitted absent version: %#v" , index , entry )
}
} else if ! versionExists || version != * prompts [ index ] . Version || len ( entry ) != 2 {
t . Errorf ( "prompt entry %d version = %#v, want %q" , index , version , * prompts [ index ] . Version )
2026-10-12 02:24:25 +00:00
}
}
output . Reset ( )
outcome = app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "list" , "profiles" , "--format" , "yaml" } , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeSuccess {
t . Fatalf ( "explicit profile YAML outcome = %#v" , outcome )
}
var profileEntries [ ] any
if err := yaml . Unmarshal ( output . Bytes ( ) , & profileEntries ) ; err != nil {
t . Fatalf ( "decode profile command output %q: %v" , output . String ( ) , err )
}
if len ( profileEntries ) != len ( profiles ) {
t . Fatalf ( "profile output is not the native sequence: %#v" , profileEntries )
}
for index , entry := range profileEntries {
value , ok := entry . ( string )
if ! ok || value != profiles [ index ] {
t . Errorf ( "profile entry %d = %#v, want string %q" , index , entry , profiles [ index ] )
}
}
promptEmptyCalls , profileEmptyCalls := 0 , 0
emptyApp := newPromptTestApp ( t , Command ( Suite [ struct { } , struct { } ] {
2026-10-17 18:44:10 +00:00
ListPrompts : func ( context . Context , CatalogRequest , struct { } , struct { } ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
2026-10-12 02:24:25 +00:00
promptEmptyCalls ++
if promptEmptyCalls % 2 == 0 {
return commandkit . Acquired [ [ ] promptkit . PromptIdentity ] { Value : [ ] promptkit . PromptIdentity { } } , nil
}
return commandkit . Acquired [ [ ] promptkit . PromptIdentity ] { Value : nil } , nil
} ,
2026-10-17 18:44:10 +00:00
ListProfiles : func ( context . Context , CatalogRequest , struct { } , struct { } ) ( commandkit . Acquired [ [ ] string ] , error ) {
2026-10-12 02:24:25 +00:00
profileEmptyCalls ++
if profileEmptyCalls % 2 == 0 {
return commandkit . Acquired [ [ ] string ] { Value : [ ] string { } } , nil
}
return commandkit . Acquired [ [ ] string ] { Value : nil } , nil
} ,
} ) )
for _ , resource := range [ ] string { "prompts" , "profiles" } {
for _ , inventory := range [ ] string { "nil" , "allocated" } {
output . Reset ( )
outcome := emptyApp . Execute ( context . Background ( ) , [ ] string { "promptkit" , "list" , resource } , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeSuccess || strings . TrimSpace ( output . String ( ) ) != "[]" {
t . Errorf ( "%s %s catalog = %#v, %q" , inventory , resource , outcome , output . String ( ) )
}
}
}
}
func TestCatalogRejectsOperandsAndUnavailableSelectors ( t * testing . T ) {
calls := 0
2026-10-17 18:44:10 +00:00
app := newPromptTestApp ( t , Command ( Suite [ struct { } , struct { } ] { ListPrompts : func ( context . Context , CatalogRequest , struct { } , struct { } ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
2026-10-12 02:24:25 +00:00
calls ++
return commandkit . Acquired [ [ ] promptkit . PromptIdentity ] { } , nil
} } ) )
for _ , args := range [ ] [ ] string {
{ "promptkit" , "list" , "prompts" , "unexpected" } ,
{ "promptkit" , "list" , "prompts" , "--version" , "2" } ,
{ "promptkit" , "list" , "prompts" , "--scope" , "app" } ,
} {
outcome := app . Execute ( context . Background ( ) , args , commandkit . Streams { Out : io . Discard , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeUsage || calls != 0 {
t . Errorf ( "unsupported catalog arguments %v = %#v after %d provider calls" , args , outcome , calls )
}
}
}
func TestCatalogFailuresRetainDiagnosticsAndDeliveryState ( t * testing . T ) {
diagnostic := commandkit . Diagnostic { Severity : commandkit . SeverityWarning , Write : func ( writer io . Writer ) error {
_ , err := io . WriteString ( writer , "catalog warning\n" )
return err
} }
hasCatalogWarning := func ( diagnostics [ ] commandkit . Diagnostic ) bool {
for _ , got := range diagnostics {
if got . Severity != diagnostic . Severity || got . Write == nil {
continue
}
var output bytes . Buffer
if got . Write ( & output ) == nil && output . String ( ) == "catalog warning\n" {
return true
}
}
return false
}
providerErr := errors . New ( "catalog provider failed" )
2026-10-17 18:44:10 +00:00
app := newPromptTestApp ( t , Command ( Suite [ struct { } , struct { } ] { ListPrompts : func ( context . Context , CatalogRequest , struct { } , struct { } ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
2026-10-12 02:24:25 +00:00
return commandkit . Acquired [ [ ] promptkit . PromptIdentity ] { Diagnostics : [ ] commandkit . Diagnostic { diagnostic } } , providerErr
} } ) )
outcome := app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "list" , "prompts" } , commandkit . Streams { Out : io . Discard , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeOperational || ! errors . Is ( outcome . Cause , providerErr ) || ! hasCatalogWarning ( outcome . Diagnostics ) {
t . Fatalf ( "provider failure outcome = %#v" , outcome )
}
ctx , cancel := context . WithCancel ( context . Background ( ) )
2026-10-17 18:44:10 +00:00
canceled := newPromptTestApp ( t , Command ( Suite [ struct { } , struct { } ] { ListPrompts : func ( context . Context , CatalogRequest , struct { } , struct { } ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
2026-10-12 02:24:25 +00:00
cancel ( )
2026-10-17 18:39:38 +00:00
return commandkit . Acquired [ [ ] promptkit . PromptIdentity ] { Value : [ ] promptkit . PromptIdentity { { ID : "briefing" , Version : testStringPointer ( "1" ) } } , Diagnostics : [ ] commandkit . Diagnostic { diagnostic } } , nil
2026-10-12 02:24:25 +00:00
} } ) )
var output bytes . Buffer
outcome = canceled . Execute ( ctx , [ ] string { "promptkit" , "list" , "prompts" } , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeOperational || ! errors . Is ( outcome . Cause , context . Canceled ) || ! hasCatalogWarning ( outcome . Diagnostics ) || output . Len ( ) != 0 {
t . Fatalf ( "post-provider cancellation outcome = %#v output=%q" , outcome , output . String ( ) )
}
writeErr := errors . New ( "catalog report writer failed" )
for _ , test := range [ ] struct {
name string
writer io . Writer
want error
} {
{ name : "writer error" , writer : partialReportWriter { err : writeErr } , want : writeErr } ,
{ name : "short write" , writer : partialReportWriter { } , want : io . ErrShortWrite } ,
} {
t . Run ( test . name , func ( t * testing . T ) {
2026-10-17 18:44:10 +00:00
writerApp := newPromptTestApp ( t , Command ( Suite [ struct { } , struct { } ] { ListPrompts : func ( context . Context , CatalogRequest , struct { } , struct { } ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
2026-10-17 18:39:38 +00:00
return commandkit . Acquired [ [ ] promptkit . PromptIdentity ] { Value : [ ] promptkit . PromptIdentity { { ID : "briefing" , Version : testStringPointer ( "1" ) } } , Diagnostics : [ ] commandkit . Diagnostic { diagnostic } } , nil
2026-10-12 02:24:25 +00:00
} } ) )
outcome := writerApp . Execute ( context . Background ( ) , [ ] string { "promptkit" , "list" , "prompts" } , commandkit . Streams { Out : test . writer , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeOperational || ! errors . Is ( outcome . DeliveryError , test . want ) || ! errors . Is ( outcome . Cause , test . want ) || ! outcome . ReportIncomplete || ! hasCatalogWarning ( outcome . Diagnostics ) {
t . Fatalf ( "catalog delivery outcome = %#v" , outcome )
}
} )
}
}
2026-10-11 01:46:54 +00:00
func TestCommandUsesInstalledNamespaceCollisionChecks ( t * testing . T ) {
command := Command ( Suite [ struct { } , struct { } ] { InspectPrompt : func ( context . Context , PromptRequest , struct { } , struct { } ) ( commandkit . Acquired [ * promptkit . PromptInspection ] , error ) {
return commandkit . Acquired [ * promptkit . PromptInspection ] { } , nil
} } )
other := commandkit . Group ( "promptkit" , "Another command tree." , commandkit . NewCommand ( commandkit . CommandSpec [ struct { } ] { Name : "child" , Summary : "A child." } ) )
first , err := commandkit . New ( commandkit . Identity { Name : "example" } , other )
if err != nil {
t . Fatal ( err )
}
if err := first . Register ( command ) ; err == nil {
t . Fatal ( "PromptKit tree installed over an existing namespace" )
}
second , err := commandkit . New ( commandkit . Identity { Name : "example" } , command )
if err != nil {
t . Fatal ( err )
}
if err := second . Register ( other ) ; err == nil {
t . Fatal ( "later command tree installed over the PromptKit namespace" )
}
}
func TestCommandValidatesOnlyGeneratedCapturedBindings ( t * testing . T ) {
unused := Command ( Suite [ struct { } , struct { } ] { Selectors : [ ] commandkit . Flag [ struct { } ] { { } } } )
if err := newPromptTestApp ( t ) . Register ( unused ) ; err != nil {
t . Fatalf ( "unused malformed selector affected empty suite: %v" , err )
}
generated := Command ( Suite [ struct { } , struct { } ] { Selectors : [ ] commandkit . Flag [ struct { } ] { { } } , InspectProfile : func ( context . Context , ProfileRequest , struct { } , struct { } ) ( commandkit . Acquired [ * promptkit . ProfileInspection ] , error ) {
return commandkit . Acquired [ * promptkit . ProfileInspection ] { } , nil
} } )
if err := newPromptTestApp ( t ) . Register ( generated ) ; err == nil {
t . Fatal ( "generated command accepted an invalid captured selector" )
}
}
func TestDefinitionInputAndStateLifetimesFollowChecks ( t * testing . T ) {
type inspectInput struct { Campaign commandkit . Supplied [ string ] }
type runState struct { }
conversions := 0
flag := commandkit . ValueFlag [ * inspectInput , string ] ( commandkit . FlagMeta { Name : "campaign" , Required : true } , ( * string ) ( nil ) , func ( value string ) ( string , error ) {
conversions ++
return value , nil
} , func ( input * * inspectInput , value commandkit . Supplied [ string ] ) { ( * input ) . Campaign = value } )
newInputs , newStates , checks , callbacks := 0 , 0 , 0 , 0
rejectInput := false
var checked * inspectInput
var wantContext context . Context
suite := Suite [ * inspectInput , * runState ] {
NewInput : func ( ) * inspectInput { newInputs ++ ; return & inspectInput { } } ,
NewState : func ( ) * runState {
newStates ++
if checks != 1 {
t . Errorf ( "state initialized after %d input checks" , checks )
}
return & runState { }
} ,
Selectors : [ ] commandkit . Flag [ * inspectInput ] { flag } ,
CheckInput : func ( selection ckconfig . Selection , input * inspectInput ) error {
checks ++
checked = input
if rejectInput {
return errors . New ( "rejected definition input" )
}
if ! selection . Config . Set || selection . Config . Value != "base.yml" || ! selection . Overlay . Set || selection . Overlay . Value != "local.yml" || ! input . Campaign . Set || input . Campaign . Value != "spring" {
return errors . New ( "definition input was incomplete" )
}
return nil
} ,
InspectPrompt : func ( ctx context . Context , request PromptRequest , input * inspectInput , state * runState ) ( commandkit . Acquired [ * promptkit . PromptInspection ] , error ) {
callbacks ++
2026-10-17 18:39:38 +00:00
if ctx != wantContext || input != checked || request . ID != "briefing" || state == nil {
2026-10-11 01:46:54 +00:00
t . Errorf ( "prompt callback arguments = ctx=%v request=%#v input=%p state=%p" , ctx , request , input , state )
}
2026-10-17 18:39:38 +00:00
return commandkit . Acquired [ * promptkit . PromptInspection ] { Value : & promptkit . PromptInspection { PromptID : request . ID } } , nil
2026-10-11 01:46:54 +00:00
} ,
}
app := newPromptTestApp ( t , Command ( suite ) )
wantContext = context . WithValue ( context . Background ( ) , struct { } { } , "context" )
var output bytes . Buffer
2026-10-17 18:39:38 +00:00
outcome := app . Execute ( wantContext , [ ] string { "promptkit" , "show" , "prompt" , "briefing" , "--campaign" , "spring" , "--config" , "base.yml" , "--overlay" , "local.yml" } , commandkit . Streams { Out : & output , Err : io . Discard } )
2026-10-11 01:46:54 +00:00
if outcome . Kind != commandkit . OutcomeSuccess || newInputs != 1 || newStates != 1 || checks != 1 || callbacks != 1 || conversions != 1 {
t . Fatalf ( "execution outcome=%#v counts conversion/input/state/check/callback=%d/%d/%d/%d/%d report=%q" , outcome , conversions , newInputs , newStates , checks , callbacks , output . String ( ) )
}
rejectInput = true
output . Reset ( )
2026-10-17 18:39:38 +00:00
outcome = app . Execute ( wantContext , [ ] string { "promptkit" , "show" , "prompt" , "briefing" , "--campaign" , "spring" , "--config" , "base.yml" , "--overlay" , "local.yml" } , commandkit . Streams { Out : & output , Err : io . Discard } )
2026-10-11 01:46:54 +00:00
if outcome . Kind != commandkit . OutcomeUsage || newInputs != 2 || newStates != 1 || checks != 2 || callbacks != 1 || conversions != 2 {
t . Fatalf ( "rejected input reached state/callback: outcome=%#v counts=%d/%d/%d/%d/%d" , outcome , conversions , newInputs , newStates , checks , callbacks )
}
}
func TestDefinitionReportsRetainNativeFieldsAndSafeCredentialReferences ( t * testing . T ) {
t . Setenv ( "PROMPTKIT_ADAPTER_TEST_KEY" , "credential-value-must-not-appear" )
engine := adapterEngine ( t )
loadCalls := 0
suite := FromEngine ( func ( context . Context , ckconfig . Selection , struct { } , struct { } ) ( * promptkit . Engine , error ) {
loadCalls ++
return engine , nil
} )
app := newPromptTestApp ( t , Command ( suite ) )
var output bytes . Buffer
2026-10-17 18:39:38 +00:00
outcome := app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "show" , "prompt" , "briefing" , "--format" , "yaml" } , commandkit . Streams { Out : & output , Err : io . Discard } )
2026-10-11 01:46:54 +00:00
if outcome . Kind != commandkit . OutcomeSuccess || loadCalls != 1 {
t . Fatalf ( "prompt report outcome=%#v load calls=%d report=%s" , outcome , loadCalls , output . String ( ) )
}
var prompt map [ string ] any
if err := yaml . Unmarshal ( output . Bytes ( ) , & prompt ) ; err != nil {
t . Fatal ( err )
}
inputs := prompt [ "inputs" ] . ( [ ] any )
if len ( inputs ) != 2 || inputs [ 0 ] . ( map [ string ] any ) [ "name" ] != "topic" || inputs [ 1 ] . ( map [ string ] any ) [ "name" ] != "audience" || prompt [ "prompt_hash" ] == "" {
t . Fatalf ( "prompt fields/order = %#v" , prompt )
}
contract := prompt [ "output_contract" ] . ( map [ string ] any )
if contract [ "repair_attempts" ] != 0 {
t . Fatalf ( "zero-valued contract field was lost: %#v" , contract )
}
output . Reset ( )
outcome = app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "show" , "prompt" , "briefing" } , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeSuccess || loadCalls != 2 || ! strings . Contains ( output . String ( ) , "Prompt version: \"1\"" ) || ! strings . Contains ( output . String ( ) , ` - name: "topic" ` ) {
t . Fatalf ( "default text prompt report = (%#v, calls=%d, %s)" , outcome , loadCalls , output . String ( ) )
}
output . Reset ( )
outcome = app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "show" , "profile" , "default" , "--format" , "yaml" } , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeSuccess || loadCalls != 3 {
t . Fatalf ( "profile report outcome=%#v calls=%d report=%s" , outcome , loadCalls , output . String ( ) )
}
var profile map [ string ] any
if err := yaml . Unmarshal ( output . Bytes ( ) , & profile ) ; err != nil {
t . Fatal ( err )
}
params := profile [ "effective_model_params" ] . ( map [ string ] any )
if params [ "api_key_env" ] != "PROMPTKIT_ADAPTER_TEST_KEY" || params [ "temperature" ] != 0 || params [ "max_tokens" ] != 0 || strings . Contains ( output . String ( ) , "credential-value-must-not-appear" ) {
t . Fatalf ( "credential or zero model fields = %#v / %s" , params , output . String ( ) )
}
extra := params [ "extra_params" ] . ( map [ string ] any )
nested := extra [ "nested" ] . ( map [ string ] any )
sequence := extra [ "sequence" ] . ( [ ] any )
if extra [ "token" ] != "caller-owned-value" || nested [ "null_value" ] != nil || nested [ "visible" ] != true || len ( sequence ) != 3 || sequence [ 1 ] != nil || sequence [ 2 ] != 3 {
t . Fatalf ( "nested ExtraParams changed: %#v" , extra )
}
output . Reset ( )
outcome = app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "show" , "profile" , "default" } , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeSuccess || loadCalls != 4 || ! strings . Contains ( output . String ( ) , "API key required: false" ) || ! strings . Contains ( output . String ( ) , ` api_key_env: "PROMPTKIT_ADAPTER_TEST_KEY" ` ) {
t . Fatalf ( "default text profile report = (%#v, calls=%d, %s)" , outcome , loadCalls , output . String ( ) )
}
output . Reset ( )
outcome = app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "show" , "profile" , "requires-key" , "--format" , "yaml" } , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeSuccess || ! strings . Contains ( output . String ( ) , "api_key_required: true" ) {
t . Fatalf ( "credential requirement report = (%#v, %s)" , outcome , output . String ( ) )
}
output . Reset ( )
outcome = app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "show" , "prompt" , "empty" , "--format" , "yaml" } , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeSuccess || ! strings . Contains ( output . String ( ) , "inputs: []" ) {
t . Fatalf ( "empty prompt input list = (%#v, %s)" , outcome , output . String ( ) )
}
}
2026-10-17 18:39:38 +00:00
func TestOptionalPromptVersionsPreserveAbsenceAndEmptyValues ( t * testing . T ) {
empty := ""
label := "release-1"
for _ , test := range [ ] struct {
name string
version * string
present bool
want string
} {
{ name : "absent" } ,
{ name : "present empty" , version : & empty , present : true , want : "" } ,
{ name : "nonempty" , version : & label , present : true , want : "release-1" } ,
} {
t . Run ( test . name , func ( t * testing . T ) {
prompt := promptReportFromInspection ( & promptkit . PromptInspection { PromptID : "briefing" , PromptVersion : test . version } )
promptBytes , err := encodePromptYAMLBytes ( prompt )
if err != nil {
t . Fatal ( err )
}
var promptReport map [ string ] any
if err := yaml . Unmarshal ( promptBytes , & promptReport ) ; err != nil {
t . Fatal ( err )
}
assertOptionalVersion ( t , promptReport , test . present , test . want )
text := formatPromptText ( prompt )
if test . present && ! strings . Contains ( text , "Prompt version: " + strconv . Quote ( test . want ) + "\n" ) {
t . Errorf ( "text omitted present version %q: %q" , test . want , text )
}
if ! test . present && strings . Contains ( text , "Prompt version:" ) {
t . Errorf ( "text emitted absent version: %q" , text )
}
requirementsBytes , err := encodePromptYAMLBytes ( requirementsReportFromInspection ( & promptkit . RequirementInspection { PromptID : "briefing" , PromptVersion : test . version } ) )
if err != nil {
t . Fatal ( err )
}
var requirementsReport map [ string ] any
if err := yaml . Unmarshal ( requirementsBytes , & requirementsReport ) ; err != nil {
t . Fatal ( err )
}
assertOptionalVersion ( t , requirementsReport , test . present , test . want )
catalogBytes , err := encodePromptCatalog ( [ ] promptkit . PromptIdentity { { ID : "briefing" , Version : test . version } } )
if err != nil {
t . Fatal ( err )
}
var catalog [ ] map [ string ] any
if err := yaml . Unmarshal ( catalogBytes , & catalog ) ; err != nil {
t . Fatal ( err )
}
if len ( catalog ) != 1 || catalog [ 0 ] [ "id" ] != "briefing" {
t . Fatalf ( "catalog = %#v" , catalog )
}
assertOptionalVersion ( t , catalog [ 0 ] , test . present , test . want )
} )
}
}
func assertOptionalVersion ( t * testing . T , report map [ string ] any , present bool , want string ) {
t . Helper ( )
version , found := report [ "version" ]
if found != present {
t . Fatalf ( "version presence = %t in %#v, want %t" , found , report , present )
}
if present && version != want {
t . Errorf ( "version = %#v, want %q" , version , want )
}
}
2026-10-11 01:46:54 +00:00
func TestNativeLookupErrorsAndBlankIDsReachCallbacks ( t * testing . T ) {
nativeErr := errors . New ( "native lookup failure" )
calls := 0
diagnostic := commandkit . MessageDiagnostic ( commandkit . SeverityWarning , "lookup context" )
app := newPromptTestApp ( t , Command ( Suite [ struct { } , struct { } ] { InspectPrompt : func ( _ context . Context , request PromptRequest , _ struct { } , _ struct { } ) ( commandkit . Acquired [ * promptkit . PromptInspection ] , error ) {
calls ++
if request . ID != "" {
t . Errorf ( "blank ID was rewritten to %q" , request . ID )
}
return commandkit . Acquired [ * promptkit . PromptInspection ] { Diagnostics : [ ] commandkit . Diagnostic { diagnostic } } , nativeErr
} } ) )
var output , diagnosticOutput bytes . Buffer
outcome := app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "show" , "prompt" } , commandkit . Streams { Out : & output , Err : & diagnosticOutput } )
if outcome . Kind != commandkit . OutcomeUsage || calls != 0 || output . Len ( ) != 0 {
t . Fatalf ( "missing ID was not a usage failure: (%#v, calls=%d, out=%q)" , outcome , calls , output . String ( ) )
}
output . Reset ( )
diagnosticOutput . Reset ( )
outcome = app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "show" , "prompt" , "" } , commandkit . Streams { Out : & output , Err : & diagnosticOutput } )
if outcome . Kind != commandkit . OutcomeOperational || ! errors . Is ( outcome . Cause , nativeErr ) || calls != 1 || output . Len ( ) != 0 || ! strings . Contains ( diagnosticOutput . String ( ) , "lookup context" ) {
t . Fatalf ( "native lookup failure = (%#v, calls=%d, out=%q, err=%q)" , outcome , calls , output . String ( ) , diagnosticOutput . String ( ) )
}
}
2026-10-17 18:39:38 +00:00
func TestNamedPromptInspectionRejectsRemovedVersionFlag ( t * testing . T ) {
calls := 0
app := newPromptTestApp ( t , Command ( Suite [ struct { } , struct { } ] { InspectPrompt : func ( _ context . Context , request PromptRequest , _ , _ struct { } ) ( commandkit . Acquired [ * promptkit . PromptInspection ] , error ) {
calls ++
return commandkit . Acquired [ * promptkit . PromptInspection ] { Value : & promptkit . PromptInspection { PromptID : request . ID } } , nil
} } ) )
outcome := app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "show" , "prompt" , "briefing" , "--version" , "1" } , commandkit . Streams { Out : io . Discard , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeUsage || calls != 0 {
t . Fatalf ( "removed version flag outcome = %#v, provider calls=%d" , outcome , calls )
}
}
2026-10-11 01:46:54 +00:00
func TestCancelledInspectionDoesNotRender ( t * testing . T ) {
ctx , cancel := context . WithCancel ( context . Background ( ) )
called := 0
app := newPromptTestApp ( t , Command ( Suite [ struct { } , struct { } ] { InspectProfile : func ( context . Context , ProfileRequest , struct { } , struct { } ) ( commandkit . Acquired [ * promptkit . ProfileInspection ] , error ) {
called ++
cancel ( )
return commandkit . Acquired [ * promptkit . ProfileInspection ] { Value : & promptkit . ProfileInspection { ProfileID : "default" } } , nil
} } ) )
var output bytes . Buffer
outcome := app . Execute ( ctx , [ ] string { "promptkit" , "show" , "profile" , "default" } , commandkit . Streams { Out : & output , Err : io . Discard } )
if ! errors . Is ( outcome . Cause , context . Canceled ) || outcome . Kind != commandkit . OutcomeOperational || called != 1 || output . Len ( ) != 0 {
t . Fatalf ( "cancelled inspection = (%#v, called=%d, output=%q)" , outcome , called , output . String ( ) )
}
}
func TestDefinitionFormatPreflightAndReportDeliveryFailure ( t * testing . T ) {
calls := 0
app := newPromptTestApp ( t , Command ( Suite [ struct { } , struct { } ] { InspectProfile : func ( context . Context , ProfileRequest , struct { } , struct { } ) ( commandkit . Acquired [ * promptkit . ProfileInspection ] , error ) {
calls ++
return commandkit . Acquired [ * promptkit . ProfileInspection ] { Value : & promptkit . ProfileInspection { ProfileID : "default" } } , nil
} } ) )
var output bytes . Buffer
outcome := app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "show" , "profile" , "default" , "--format" , "json" } , commandkit . Streams { Out : & output , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeUsage || calls != 0 || output . Len ( ) != 0 {
t . Fatalf ( "bad format was not rejected before callback: outcome=%#v calls=%d output=%q" , outcome , calls , output . String ( ) )
}
writeErr := errors . New ( "report writer failed" )
outcome = app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "show" , "profile" , "default" } , commandkit . Streams { Out : partialReportWriter { err : writeErr } , Err : io . Discard } )
if outcome . Kind != commandkit . OutcomeOperational || ! errors . Is ( outcome . Cause , writeErr ) || outcome . DeliveryError != writeErr || ! outcome . ReportIncomplete || calls != 1 {
t . Fatalf ( "report delivery outcome = %#v calls=%d" , outcome , calls )
}
}
type partialReportWriter struct { err error }
func ( writer partialReportWriter ) Write ( content [ ] byte ) ( int , error ) {
if len ( content ) == 0 {
return 0 , writer . err
}
return 1 , writer . err
}
var _ io . Writer = partialReportWriter { }
func TestProfileTextUsesCredentialNamesAndExplicitEmptyExtraParams ( t * testing . T ) {
report := profileReportFromInspection ( & promptkit . ProfileInspection { ProfileID : "default" , EffectiveModelParams : promptkit . ExecutionTarget { APIKeyEnv : "APP_KEY" , ExtraParams : nil } } )
text , err := formatProfileText ( report )
if err != nil || ! strings . Contains ( text , "api_key_env: \"APP_KEY\"" ) || ! strings . Contains ( text , "extra_params:\n {}\n" ) || ! strings . Contains ( text , "API key required: false" ) {
t . Fatalf ( "profile text = (%q, %v)" , text , err )
}
if strings . Contains ( text , "APP_KEY_VALUE" ) {
t . Fatalf ( "report contains a credential value: %q" , text )
}
}
2026-10-12 02:12:47 +00:00
func TestPromptCatalogYAMLPreservesSchemaStringsAndOrder ( t * testing . T ) {
want := [ ] promptkit . PromptIdentity {
2026-10-17 18:39:38 +00:00
{ ID : " briefing " , Version : testStringPointer ( " 03 " ) } ,
{ ID : "001" , Version : testStringPointer ( "1.10" ) } ,
{ ID : " briefing " , Version : testStringPointer ( " 03 " ) } ,
2026-10-12 02:12:47 +00:00
}
output , err := encodePromptCatalog ( want )
if err != nil {
t . Fatal ( err )
}
var decoded [ ] map [ string ] any
if err := yaml . Unmarshal ( output , & decoded ) ; err != nil {
t . Fatalf ( "decode prompt catalog %q: %v" , output , err )
}
if len ( decoded ) != len ( want ) {
t . Fatalf ( "catalog entry count = %d, want %d: %q" , len ( decoded ) , len ( want ) , output )
}
for index , entry := range decoded {
if len ( entry ) != 2 {
t . Errorf ( "entry %d fields = %#v, want only id and version" , index , entry )
}
id , idOK := entry [ "id" ] . ( string )
version , versionOK := entry [ "version" ] . ( string )
2026-10-17 18:39:38 +00:00
if ! idOK || ! versionOK || id != want [ index ] . ID || want [ index ] . Version == nil || version != * want [ index ] . Version {
t . Errorf ( "entry %d = %#v, want id/version %q/%#v" , index , entry , want [ index ] . ID , want [ index ] . Version )
2026-10-12 02:12:47 +00:00
}
}
}
func TestCatalogYAMLEncodersRenderNilAndEmptyInventoriesAsSequences ( t * testing . T ) {
for _ , test := range [ ] struct {
name string
data func ( ) ( [ ] byte , error )
} {
{ name : "nil prompts" , data : func ( ) ( [ ] byte , error ) { return encodePromptCatalog ( nil ) } } ,
{ name : "empty prompts" , data : func ( ) ( [ ] byte , error ) { return encodePromptCatalog ( make ( [ ] promptkit . PromptIdentity , 0 ) ) } } ,
{ name : "nil profiles" , data : func ( ) ( [ ] byte , error ) { return encodeProfileCatalog ( nil ) } } ,
{ name : "empty profiles" , data : func ( ) ( [ ] byte , error ) { return encodeProfileCatalog ( make ( [ ] string , 0 ) ) } } ,
} {
t . Run ( test . name , func ( t * testing . T ) {
output , err := test . data ( )
if err != nil {
t . Fatal ( err )
}
if strings . TrimSpace ( string ( output ) ) != "[]" {
t . Fatalf ( "empty catalog YAML = %q, want empty sequence" , output )
}
} )
}
}
func TestProfileCatalogYAMLPreservesStringValuesAndOrder ( t * testing . T ) {
want := [ ] string { " default " , "001" , "same" , "same" }
output , err := encodeProfileCatalog ( want )
if err != nil {
t . Fatal ( err )
}
var decoded [ ] any
if err := yaml . Unmarshal ( output , & decoded ) ; err != nil {
t . Fatalf ( "decode profile catalog %q: %v" , output , err )
}
if len ( decoded ) != len ( want ) {
t . Fatalf ( "catalog entry count = %d, want %d: %q" , len ( decoded ) , len ( want ) , output )
}
for index , item := range decoded {
value , ok := item . ( string )
if ! ok || value != want [ index ] {
t . Errorf ( "profile %d = %#v, want string %q" , index , item , want [ index ] )
}
}
}
2026-10-12 16:57:23 +00:00
func TestRequirementsReportRendersEmptyInventoriesAndFalseValues ( t * testing . T ) {
output , err := encodePromptYAMLBytes ( requirementsReportFromInspection ( & promptkit . RequirementInspection { } ) )
if err != nil {
t . Fatal ( err )
}
var report map [ string ] any
if err := yaml . Unmarshal ( output , & report ) ; err != nil {
t . Fatalf ( "decode requirements report %q: %v" , output , err )
}
2026-10-17 18:39:38 +00:00
for _ , key := range [ ] string { "prompt_id" , "profile_id" , "complete" , "inputs" , "variables" , "issues" } {
2026-10-12 16:57:23 +00:00
if _ , ok := report [ key ] ; ! ok {
t . Errorf ( "requirements report is missing %q: %q" , key , output )
}
}
2026-10-17 18:39:38 +00:00
if _ , ok := report [ "version" ] ; ok {
t . Errorf ( "absent prompt version was emitted: %q" , output )
}
2026-10-12 16:57:23 +00:00
if report [ "complete" ] != false {
t . Errorf ( "complete = %#v, want false" , report [ "complete" ] )
}
for _ , key := range [ ] string { "inputs" , "variables" , "issues" } {
items , ok := report [ key ] . ( [ ] any )
if ! ok || len ( items ) != 0 {
t . Errorf ( "%s = %#v, want an empty sequence" , key , report [ key ] )
}
}
2026-10-17 18:39:38 +00:00
for _ , key := range [ ] string { "prompt_id" , "profile_id" } {
2026-10-12 16:57:23 +00:00
if report [ key ] != "" {
t . Errorf ( "%s = %#v, want an explicitly present empty string" , key , report [ key ] )
}
}
}
func TestRequirementsReportPreservesNativeFieldsAndMetadata ( t * testing . T ) {
empty := ""
contentType := "true"
inspection := & promptkit . RequirementInspection {
PromptID : "true" ,
2026-10-17 18:39:38 +00:00
PromptVersion : testStringPointer ( "001" ) ,
2026-10-12 16:57:23 +00:00
ProfileID : "null" ,
Complete : true ,
Inputs : [ ] promptkit . InputRequirement {
{ Name : "true" , Kind : promptkit . RequirementKind ( "123" ) , Declared : false , Description : & empty } ,
{ Name : "001" , Kind : promptkit . RequirementKind ( "future_kind" ) , Declared : true , ContentType : & contentType , Explanation : "false" } ,
} ,
Variables : [ ] promptkit . VariableRequirement {
{ Name : "false" , Kind : promptkit . RequirementKind ( "on" ) , Supplied : false } ,
{ Name : "001" , Kind : promptkit . RequirementKind ( "future_kind" ) , Supplied : true , Explanation : "true" } ,
} ,
Issues : [ ] promptkit . RequirementIssue { {
Code : promptkit . RequirementIssueCode ( "123" ) ,
InputName : "" ,
VariableName : "false" ,
Description : "" ,
} } ,
}
for _ , complete := range [ ] bool { true , false } {
t . Run ( map [ bool ] string { true : "complete" , false : "partial" } [ complete ] , func ( t * testing . T ) {
inspection . Complete = complete
output , err := encodePromptYAMLBytes ( requirementsReportFromInspection ( inspection ) )
if err != nil {
t . Fatal ( err )
}
var report map [ string ] any
if err := yaml . Unmarshal ( output , & report ) ; err != nil {
t . Fatalf ( "decode requirements report %q: %v" , output , err )
}
2026-10-17 18:39:38 +00:00
if report [ "complete" ] != complete || report [ "prompt_id" ] != "true" || report [ "version" ] != "001" || report [ "profile_id" ] != "null" {
2026-10-12 16:57:23 +00:00
t . Fatalf ( "selected context or completeness = %#v" , report )
}
inputs , ok := report [ "inputs" ] . ( [ ] any )
if ! ok || len ( inputs ) != 2 {
t . Fatalf ( "inputs = %#v" , report [ "inputs" ] )
}
firstInput , ok := inputs [ 0 ] . ( map [ string ] any )
if ! ok || len ( firstInput ) != 6 || firstInput [ "name" ] != "true" || firstInput [ "kind" ] != "123" || firstInput [ "declared" ] != false || firstInput [ "content_type" ] != nil || firstInput [ "description" ] != "" || firstInput [ "explanation" ] != "" {
t . Fatalf ( "first input = %#v" , inputs [ 0 ] )
}
secondInput , ok := inputs [ 1 ] . ( map [ string ] any )
if ! ok || len ( secondInput ) != 6 || secondInput [ "name" ] != "001" || secondInput [ "kind" ] != "future_kind" || secondInput [ "declared" ] != true || secondInput [ "content_type" ] != "true" || secondInput [ "description" ] != nil || secondInput [ "explanation" ] != "false" {
t . Fatalf ( "second input = %#v" , inputs [ 1 ] )
}
variables , ok := report [ "variables" ] . ( [ ] any )
if ! ok || len ( variables ) != 2 {
t . Fatalf ( "variables = %#v" , report [ "variables" ] )
}
firstVariable , ok := variables [ 0 ] . ( map [ string ] any )
if ! ok || len ( firstVariable ) != 4 || firstVariable [ "name" ] != "false" || firstVariable [ "kind" ] != "on" || firstVariable [ "supplied" ] != false || firstVariable [ "explanation" ] != "" {
t . Fatalf ( "first variable = %#v" , variables [ 0 ] )
}
secondVariable , ok := variables [ 1 ] . ( map [ string ] any )
if ! ok || len ( secondVariable ) != 4 || secondVariable [ "name" ] != "001" || secondVariable [ "kind" ] != "future_kind" || secondVariable [ "supplied" ] != true || secondVariable [ "explanation" ] != "true" {
t . Fatalf ( "second variable = %#v" , variables [ 1 ] )
}
issues , ok := report [ "issues" ] . ( [ ] any )
if ! ok || len ( issues ) != 1 {
t . Fatalf ( "issues = %#v" , report [ "issues" ] )
}
issue , ok := issues [ 0 ] . ( map [ string ] any )
if ! ok || len ( issue ) != 4 || issue [ "code" ] != "123" || issue [ "input_name" ] != "" || issue [ "variable_name" ] != "false" || issue [ "description" ] != "" {
t . Fatalf ( "issue = %#v" , issues [ 0 ] )
}
} )
}
}