2026-10-11 01:46:54 +00:00
package ckprompt
import (
"bytes"
"context"
"errors"
"io"
"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"
)
func newPromptTestApp ( t * testing . T , commands ... commandkit . Command ) * commandkit . App {
t . Helper ( )
app , err := commandkit . New ( commandkit . Identity { Name : "example" } , commands ... )
if err != nil {
t . Fatal ( err )
}
return app
}
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 } )
if outcome . Kind != commandkit . OutcomeSuccess || ! strings . Contains ( output . String ( ) , "\n prompt " ) || strings . Contains ( output . String ( ) , "\n profile " ) || strings . Contains ( output . String ( ) , "config" ) {
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
} ,
} )
if err := newPromptTestApp ( t ) . Register ( both ) ; err != nil {
t . Fatalf ( "both-capability tree failed to register: %v" , err )
}
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-12 02:17:54 +00:00
invalid . ListPrompts , invalid . ListProfiles = nil , nil
2026-10-11 01:46:54 +00:00
invalid . InspectPrompt , invalid . InspectProfile = nil , nil
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 02:17:54 +00:00
func TestCatalogCommandTreesAreIndependentAndOmitShow ( t * testing . T ) {
prompts := Command ( Suite [ struct { } , struct { } ] {
ListPrompts : func ( context . Context , ckconfig . Selection , struct { } , struct { } ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
return commandkit . Acquired [ [ ] promptkit . PromptIdentity ] { } , nil
} ,
} )
profiles := Command ( Suite [ struct { } , struct { } ] {
ListProfiles : func ( context . Context , ckconfig . Selection , struct { } , struct { } ) ( commandkit . Acquired [ [ ] string ] , error ) {
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
} ,
ListPrompts : func ( context . Context , ckconfig . Selection , struct { } , struct { } ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
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
}
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
} ,
ListPrompts : func ( _ context . Context , selection ckconfig . Selection , value input , gotState state ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
providerCalls ++
received , receivedSelection , receivedState = value , selection , gotState
return commandkit . Acquired [ [ ] promptkit . PromptIdentity ] { Value : [ ] promptkit . PromptIdentity { { ID : "briefing" , Version : "1" } } } , nil
} ,
}
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
} ,
ListPrompts : func ( _ context . Context , selection ckconfig . Selection , got input , gotState * state ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
providers ++
if gotState == nil || gotState . run != providers {
t . Errorf ( "provider state = %#v at invocation %d" , gotState , providers )
}
if providers == 1 && ( ! selection . Config . Set || selection . Config . Value != "" || ! selection . Overlay . Set || selection . Overlay . Value != "" || ! got . campaign . Set || ! got . enabled . Set || ! got . limit . Set || ! got . labels . Set ) {
t . Errorf ( "first provider values = selection %#v input %#v" , selection , got )
}
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 { } ] {
ListPrompts : func ( _ context . Context , selection ckconfig . Selection , input , state * struct { } ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
if input != nil || state != nil || selection . Config . Set || selection . Overlay . Set {
t . Errorf ( "nil-factory values = selection %#v input %#v state %#v" , selection , input , state )
}
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 {
{ ID : "later" , Version : "1.10" } ,
{ ID : "001" , Version : " 03 " } ,
{ ID : "a: true" , Version : "yes" } ,
}
profiles := [ ] string { "later" , "001" , "a: true" , "later" }
suite := Suite [ struct { } , struct { } ] {
ListPrompts : func ( context . Context , ckconfig . Selection , struct { } , struct { } ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
return commandkit . Acquired [ [ ] promptkit . PromptIdentity ] { Value : prompts } , nil
} ,
ListProfiles : func ( context . Context , ckconfig . Selection , struct { } , struct { } ) ( commandkit . Acquired [ [ ] string ] , error ) {
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 )
version , versionOK := entry [ "version" ] . ( string )
if len ( entry ) != 2 || ! idOK || ! versionOK || id != prompts [ index ] . ID || version != prompts [ index ] . Version {
t . Errorf ( "prompt entry %d = %#v, want string id/version %q/%q" , index , entry , prompts [ index ] . ID , prompts [ index ] . Version )
}
}
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 { } ] {
ListPrompts : func ( context . Context , ckconfig . Selection , struct { } , struct { } ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
promptEmptyCalls ++
if promptEmptyCalls % 2 == 0 {
return commandkit . Acquired [ [ ] promptkit . PromptIdentity ] { Value : [ ] promptkit . PromptIdentity { } } , nil
}
return commandkit . Acquired [ [ ] promptkit . PromptIdentity ] { Value : nil } , nil
} ,
ListProfiles : func ( context . Context , ckconfig . Selection , struct { } , struct { } ) ( commandkit . Acquired [ [ ] string ] , error ) {
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
app := newPromptTestApp ( t , Command ( Suite [ struct { } , struct { } ] { ListPrompts : func ( context . Context , ckconfig . Selection , struct { } , struct { } ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
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" )
app := newPromptTestApp ( t , Command ( Suite [ struct { } , struct { } ] { ListPrompts : func ( context . Context , ckconfig . Selection , struct { } , struct { } ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
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 ( ) )
canceled := newPromptTestApp ( t , Command ( Suite [ struct { } , struct { } ] { ListPrompts : func ( context . Context , ckconfig . Selection , struct { } , struct { } ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
cancel ( )
return commandkit . Acquired [ [ ] promptkit . PromptIdentity ] { Value : [ ] promptkit . PromptIdentity { { ID : "briefing" , Version : "1" } } , Diagnostics : [ ] commandkit . Diagnostic { diagnostic } } , nil
} } ) )
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 ) {
writerApp := newPromptTestApp ( t , Command ( Suite [ struct { } , struct { } ] { ListPrompts : func ( context . Context , ckconfig . Selection , struct { } , struct { } ) ( commandkit . Acquired [ [ ] promptkit . PromptIdentity ] , error ) {
return commandkit . Acquired [ [ ] promptkit . PromptIdentity ] { Value : [ ] promptkit . PromptIdentity { { ID : "briefing" , Version : "1" } } , Diagnostics : [ ] commandkit . Diagnostic { diagnostic } } , nil
} } ) )
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 ++
if ctx != wantContext || input != checked || request . ID != "briefing" || ! request . Version . Set || request . Version . Value != "2" || state == nil {
t . Errorf ( "prompt callback arguments = ctx=%v request=%#v input=%p state=%p" , ctx , request , input , state )
}
return commandkit . Acquired [ * promptkit . PromptInspection ] { Value : & promptkit . PromptInspection { PromptID : request . ID , PromptVersion : request . Version . Value } } , nil
} ,
}
app := newPromptTestApp ( t , Command ( suite ) )
wantContext = context . WithValue ( context . Background ( ) , struct { } { } , "context" )
var output bytes . Buffer
outcome := app . Execute ( wantContext , [ ] string { "promptkit" , "show" , "prompt" , "briefing" , "--campaign" , "spring" , "--config" , "base.yml" , "--overlay" , "local.yml" , "--version" , "2" } , commandkit . Streams { Out : & output , Err : io . Discard } )
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 ( )
outcome = app . Execute ( wantContext , [ ] string { "promptkit" , "show" , "prompt" , "briefing" , "--campaign" , "spring" , "--config" , "base.yml" , "--overlay" , "local.yml" , "--version" , "2" } , commandkit . Streams { Out : & output , Err : io . Discard } )
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
outcome := app . Execute ( context . Background ( ) , [ ] string { "promptkit" , "show" , "prompt" , "briefing" , "--version" , "1" , "--format" , "yaml" } , commandkit . Streams { Out : & output , Err : io . Discard } )
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 ( ) )
}
}
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 ( ) )
}
}
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 {
{ ID : " briefing " , Version : " 03 " } ,
{ ID : "001" , Version : "1.10" } ,
{ ID : " briefing " , Version : " 03 " } ,
}
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 )
if ! idOK || ! versionOK || id != want [ index ] . ID || version != want [ index ] . Version {
t . Errorf ( "entry %d = %#v, want id/version %q/%q as strings" , index , entry , want [ index ] . ID , want [ index ] . Version )
}
}
}
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 ] )
}
}
}