Preserve caller scope during requirement inspection

This commit is contained in:
2026-10-08 21:15:56 +00:00
parent 21815ad7c0
commit e69a847cf2
4 changed files with 150 additions and 5 deletions

View File

@@ -11,6 +11,72 @@ import (
"gitea.maximumdirect.net/eric/promptkit/internal/domain"
)
func TestAnalyzeRequirementsDoesNotHideCallerMapScopes(t *testing.T) {
for _, source := range []string{
`{{with .}}{{.audience}}{{end}}`,
`{{with $}}{{.audience}}{{end}}`,
`{{with (.)}}{{.audience}}{{end}}`,
`{{$alias := .}}{{with $alias}}{{.audience}}{{end}}`,
`{{with .}}{{index . "audience"}}{{end}}`,
`{{$alias := .}}{{index $alias "audience"}}`,
`{{$alias := .}}{{index ($alias) "audience"}}`,
`{{$alias := .}}{{$alias.audience}}`,
} {
t.Run(source, func(t *testing.T) {
compiled := compileRequirementTemplate(t, "scope", source)
vars := map[string]string{"audience": "visible"}
var rendered strings.Builder
if err := compiled.Execute(&rendered, vars); err != nil || rendered.String() != "visible" {
t.Fatalf("caller-map reference did not render: %q, %v", rendered.String(), err)
}
result, err := AnalyzeRequirements(context.Background(), &domain.PromptDefinition{}, RequirementSnapshot{
Templates: CompiledTemplates{Messages: []*template.Template{compiled}},
}, vars, false)
if err != nil {
t.Fatal(err)
}
if result.Complete {
if len(result.Variables) != 1 || result.Variables[0].Name != "audience" {
t.Fatalf("complete discovery lost the caller key: %+v", result)
}
} else if len(result.Issues) == 0 {
t.Fatalf("partial discovery did not explain its limitation: %+v", result)
}
})
}
}
func TestAnalyzeRequirementsUnknownScopesAffectOptionalEntriesOnlyWhenActive(t *testing.T) {
for _, access := range []string{`{{with $alias}}{{.audience}}{{end}}`, `{{index $alias "audience"}}`, `{{index ($alias) "audience"}}`, `{{$alias.audience}}`} {
for _, active := range []bool{false, true} {
source := `{{if false}}{{.optional}}{{end}}{{$alias := .}}` + access
if !active {
source = `{{if false}}` + source + `{{end}}`
}
compiled := compileRequirementTemplate(t, "unknown-scope", source)
result, err := AnalyzeRequirements(context.Background(), &domain.PromptDefinition{}, RequirementSnapshot{
Templates: CompiledTemplates{Messages: []*template.Template{compiled}},
}, map[string]string{"audience": "visible"}, false)
if err != nil {
t.Fatal(err)
}
wantKind := domain.RequirementOptional
if active {
wantKind = domain.RequirementConditional
}
if result.Complete == active || len(result.Variables) != 1 || result.Variables[0].Name != "optional" || result.Variables[0].Kind != wantKind {
t.Fatalf("active=%v, source=%s, result=%+v", active, source, result)
}
if active && (len(result.Issues) == 0 || result.Issues[0].Code != domain.RequirementIssueUnsupportedConstruct) {
t.Fatalf("active unknown scope lacks a structured issue: %+v", result)
}
if !active && len(result.Issues) != 0 {
t.Fatalf("skipped unknown scope introduced uncertainty: %+v", result)
}
}
}
}
func TestAnalyzeRequirementsCollectsDeclaredAndLiteralInputs(t *testing.T) {
description := "retained metadata"
definition := &domain.PromptDefinition{ID: "capture", Version: "v1"}