Document prompt requirement inspection
This commit is contained in:
@@ -154,6 +154,50 @@ rendered messages, and use prepared execution when that work must remain tied
|
|||||||
to later execution. The method's [GoDoc](../../engine.go) owns exact fields,
|
to later execution. The method's [GoDoc](../../engine.go) owns exact fields,
|
||||||
hash, ownership, and error semantics.
|
hash, ownership, and error semantics.
|
||||||
|
|
||||||
|
## Inspect Requirements Before Preparation
|
||||||
|
|
||||||
|
Use [`Engine.InspectRequirements`](../../requirements.go) when the application
|
||||||
|
needs the prompt's recognizable input and caller-variable dependencies for a
|
||||||
|
particular context before it has input artifacts. Unlike `InspectPrompt`, it
|
||||||
|
also walks captured template syntax and selects a profile identity; unlike
|
||||||
|
`Prepare`, it does not load artifacts or render messages.
|
||||||
|
|
||||||
|
```go
|
||||||
|
requirements, err := engine.InspectRequirements(ctx, promptkit.RequirementInspectionRequest{
|
||||||
|
PromptID: "meeting.summary",
|
||||||
|
Vars: map[string]string{"audience": "project leads"},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, input := range requirements.Inputs {
|
||||||
|
if input.Kind == promptkit.RequirementRequired {
|
||||||
|
// Plan to bind this input before preparation.
|
||||||
|
}
|
||||||
|
if input.Kind == promptkit.RequirementOptional && input.Explanation != "" {
|
||||||
|
// A recognizable reference may occur only on a known skipped path.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, variable := range requirements.Variables {
|
||||||
|
if variable.Kind == promptkit.RequirementRequired && !variable.Supplied {
|
||||||
|
// The key is required even though this inspection did not receive it.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !requirements.Complete {
|
||||||
|
// Preserve the partial inventory and account for its discovery issues.
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Optional entries can include recognizable inputs and variables found only in
|
||||||
|
inactive branches. A missing required variable is reported separately from
|
||||||
|
discovery completeness: missing a value used only for direct text substitution
|
||||||
|
does not by itself make the inventory incomplete. Conversely, an unresolved
|
||||||
|
dependency-bearing branch can make discovery incomplete while retaining known
|
||||||
|
conditional entries. Do not treat an empty partial inventory as proof that no
|
||||||
|
input bindings are needed. See the method's [GoDoc](../../requirements.go) for
|
||||||
|
the exact classifications, supported syntax, ownership, and error contract.
|
||||||
|
|
||||||
## Prepare Without Model Execution
|
## Prepare Without Model Execution
|
||||||
|
|
||||||
[`Engine.Prepare`](../../engine.go) resolves the selected prompt and profile,
|
[`Engine.Prepare`](../../engine.go) resolves the selected prompt and profile,
|
||||||
|
|||||||
@@ -124,6 +124,12 @@ Optional `session_id` uses the same template variables and input helper. Its
|
|||||||
rendered value is trimmed, omitted if empty, and limited to 256 Unicode code
|
rendered value is trimmed, omitted if empty, and limited to 256 Unicode code
|
||||||
points. A nonblank direct request session ID bypasses the template.
|
points. A nonblank direct request session ID bypasses the template.
|
||||||
|
|
||||||
|
`InspectRequirements` can enumerate recognizable dependencies from captured
|
||||||
|
templates before artifact content is available. Its conservative syntax
|
||||||
|
coverage does not change template validity or rendering; see the [consumer
|
||||||
|
guide](consumers/pkg-promptkit.md#inspect-requirements-before-preparation) and
|
||||||
|
the method's [GoDoc](../requirements.go) for that inspection boundary.
|
||||||
|
|
||||||
### Cache Control
|
### Cache Control
|
||||||
|
|
||||||
Optional `cache_control` has required `type: ephemeral` and optional `ttl`,
|
Optional `cache_control` has required `type: ephemeral` and optional `ttl`,
|
||||||
|
|||||||
@@ -416,6 +416,13 @@ suite solely for this unit; commit.
|
|||||||
|
|
||||||
## Stage 7 — Document And Verify The Assembled Feature
|
## Stage 7 — Document And Verify The Assembled Feature
|
||||||
|
|
||||||
|
**Status: Complete (2026-10-08).** GoDoc, consumer guidance, framework-format
|
||||||
|
cross-references, and the maintained preparation example now describe the
|
||||||
|
implemented discovery boundary. Final offline verification passed:
|
||||||
|
`go test -race -vet=off -mod=readonly -count=1 ./...`,
|
||||||
|
`go vet -mod=readonly ./...`, and `python3 scripts/check-examples.py`, with
|
||||||
|
`GOTOOLCHAIN=local GOWORK=off GOPROXY=off GONOPROXY=none GOSUMDB=off`.
|
||||||
|
|
||||||
**Outcome:** Implemented semantics and analysis limits are documented in their
|
**Outcome:** Implemented semantics and analysis limits are documented in their
|
||||||
canonical owners, with final verification ready for user review.
|
canonical owners, with final verification ready for user review.
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
# Effective Prompt Requirement Inspection
|
# Effective Prompt Requirement Inspection
|
||||||
|
|
||||||
Status: Implementation planned; the feature is not implemented. The
|
Status: Implemented (2026-10-08). The
|
||||||
[implementation plan](implementation.md) owns the ordered implementation steps.
|
[implementation plan](implementation.md) records the completed work units and
|
||||||
This document owns the purpose, scope, and target end state.
|
final verification. Current public API details live in GoDoc; the consumer
|
||||||
|
guide, format reference, and internal documents link to those canonical
|
||||||
|
contracts.
|
||||||
|
|
||||||
## Purpose
|
## Purpose
|
||||||
|
|
||||||
@@ -16,7 +18,7 @@ The originating request is [Scriptorium's feature request](scriptorium-feature-r
|
|||||||
Promptkit supplies application-neutral inspection; consumers own presentation,
|
Promptkit supplies application-neutral inspection; consumers own presentation,
|
||||||
binding checks, and their own workflows.
|
binding checks, and their own workflows.
|
||||||
|
|
||||||
## Current Baseline
|
## Original Review Baseline
|
||||||
|
|
||||||
At review baseline `b595dca`:
|
At review baseline `b595dca`:
|
||||||
|
|
||||||
@@ -183,28 +185,19 @@ metadata. A directly resolved input identifier may equal a supplied variable
|
|||||||
value; reporting that binding name is necessary, without echoing its originating
|
value; reporting that binding name is necessary, without echoing its originating
|
||||||
expression or variable map.
|
expression or variable map.
|
||||||
|
|
||||||
## Work Needed From The Baseline
|
## Implemented Outcome
|
||||||
|
|
||||||
Add request/result values and the engine method through the root facade.
|
The root API selects a captured prompt and profile identity, then returns
|
||||||
Keep selection coordination internal and place syntax discovery with the
|
caller-owned input and variable inventories with conservative classifications
|
||||||
existing prompt-template component. Reuse captured templates and selection
|
and structured discovery limitations. The internal prompt walker uses captured
|
||||||
helpers rather than creating another preparation path.
|
template syntax and effective metadata; inspection does not enter artifact,
|
||||||
|
schema, credential, rendering, provider, or execution preparation.
|
||||||
|
|
||||||
Capture required metadata presence at the final ConfigKit handoff and retain it
|
The final verification and the commit sequence are recorded in the
|
||||||
alongside inspection snapshots. Apply [ADR 0001](../adr/0001-configuration-boundary.md):
|
[implementation plan](implementation.md). The exact public contract is owned by
|
||||||
interpret final effective definitions, not raw/intermediate configuration or
|
[GoDoc](../../requirements.go); consumer usage, framework-format cross-reference,
|
||||||
history. Operator provenance remains a separate explicit API.
|
and internal selection/source descriptions are maintained in their respective
|
||||||
|
documents.
|
||||||
Implement a small syntax walker, simple context tests, classification
|
|
||||||
aggregation, and safe limitation reporting. Keep request-specific state separate
|
|
||||||
from captured definitions. Focus tests on representative enumeration,
|
|
||||||
classifications, scope mistakes, selection, capture/ownership, and absence of
|
|
||||||
execution effects, under the [testing policy](../policy/testing.md). Do not test
|
|
||||||
a general interpreter or repeat ConfigKit's source-loading matrix.
|
|
||||||
|
|
||||||
When implementation lands, update GoDoc, the consumer guide, relevant format
|
|
||||||
cross-references, internal documents, and a maintained example. Canonical owners
|
|
||||||
document the implemented boundary; release notes summarize rather than own it.
|
|
||||||
|
|
||||||
## Acceptance Outcomes
|
## Acceptance Outcomes
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,17 @@ func main() {
|
|||||||
if _, found := view.Explain(configkit.Keys("profiles", "offline-example", "model")); !found {
|
if _, found := view.Explain(configkit.Keys("profiles", "offline-example", "model")); !found {
|
||||||
exit(fmt.Errorf("configured profile model was not found"))
|
exit(fmt.Errorf("configured profile model was not found"))
|
||||||
}
|
}
|
||||||
|
requirements, err := engine.InspectRequirements(context.Background(), promptkit.RequirementInspectionRequest{
|
||||||
|
PromptID: "example.prepare",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
exit(err)
|
||||||
|
}
|
||||||
|
if !requirements.Complete || len(requirements.Inputs) != 1 ||
|
||||||
|
requirements.Inputs[0].Name != "note" ||
|
||||||
|
requirements.Inputs[0].Kind != promptkit.RequirementRequired {
|
||||||
|
exit(fmt.Errorf("required note input was not discovered before preparation"))
|
||||||
|
}
|
||||||
|
|
||||||
prepared, err := engine.Prepare(context.Background(), promptkit.RunRequest{
|
prepared, err := engine.Prepare(context.Background(), promptkit.RunRequest{
|
||||||
PromptID: "example.prepare",
|
PromptID: "example.prepare",
|
||||||
|
|||||||
135
requirements.go
135
requirements.go
@@ -10,43 +10,74 @@ import (
|
|||||||
// RequirementInspectionRequest selects a prompt and supplies caller context
|
// RequirementInspectionRequest selects a prompt and supplies caller context
|
||||||
// for requirement discovery. It requires no artifact bindings or credentials.
|
// for requirement discovery. It requires no artifact bindings or credentials.
|
||||||
type RequirementInspectionRequest struct {
|
type RequirementInspectionRequest struct {
|
||||||
PromptID string
|
// PromptID is the exact, case-sensitive configured prompt ID.
|
||||||
|
PromptID string
|
||||||
|
// PromptVersion selects an exact version. An empty value uses the prompt
|
||||||
|
// selection rule that requires exactly one configured version.
|
||||||
PromptVersion string
|
PromptVersion string
|
||||||
ProfileID string
|
// ProfileID selects the exact effective profile identity. If empty, the
|
||||||
Vars map[string]string
|
// prompt's default profile is used; the profile need not be ready for
|
||||||
SessionID string
|
// execution.
|
||||||
|
ProfileID string
|
||||||
|
// Vars supplies string values for caller-variable lookups and simple
|
||||||
|
// conditions. Presence is determined by exact map key, including an empty
|
||||||
|
// value; values are not returned in the inspection.
|
||||||
|
Vars map[string]string
|
||||||
|
// SessionID, when nonblank after the normal session-ID normalization,
|
||||||
|
// bypasses the prompt's session template during discovery.
|
||||||
|
SessionID string
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequirementKind describes how a selected prompt may depend on an input or
|
// RequirementKind describes how a selected prompt may depend on an input or
|
||||||
// caller variable for the supplied context.
|
// caller variable for the supplied context. It is independent of whether a
|
||||||
|
// caller-variable value is present.
|
||||||
type RequirementKind string
|
type RequirementKind string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// RequirementRequired identifies a declaration or definite access.
|
// RequirementRequired identifies an input declared required or a dependency
|
||||||
|
// reached by a recognized definite access.
|
||||||
RequirementRequired RequirementKind = "required"
|
RequirementRequired RequirementKind = "required"
|
||||||
// RequirementConditional identifies a dependency whose reachability is
|
// RequirementConditional identifies a dependency whose reachability or
|
||||||
// unresolved for the supplied context.
|
// identity remains unresolved for the supplied context.
|
||||||
RequirementConditional RequirementKind = "conditional"
|
RequirementConditional RequirementKind = "conditional"
|
||||||
// RequirementOptional identifies a dependency known not to be required,
|
// RequirementOptional identifies a dependency known not to be required,
|
||||||
// including a reference used only on a known skipped path.
|
// including a nonrequired declaration, optional lookup, or reference used
|
||||||
|
// only on a known skipped path.
|
||||||
RequirementOptional RequirementKind = "optional"
|
RequirementOptional RequirementKind = "optional"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InputRequirement describes a declared or template-referenced prompt input.
|
// InputRequirement describes a declared or template-referenced prompt input.
|
||||||
type InputRequirement struct {
|
type InputRequirement struct {
|
||||||
Name string
|
// Name is the exact input identifier.
|
||||||
Kind RequirementKind
|
Name string
|
||||||
Declared bool
|
// Kind is the strongest classification established for this name.
|
||||||
|
Kind RequirementKind
|
||||||
|
// Declared reports whether the name appears in the effective input
|
||||||
|
// declarations; helper-only references have Declared false.
|
||||||
|
Declared bool
|
||||||
|
// ContentType preserves effective metadata presence: nil means absent or
|
||||||
|
// null, while a non-nil pointer may refer to an empty string.
|
||||||
ContentType *string
|
ContentType *string
|
||||||
|
// Description preserves effective metadata presence independently of
|
||||||
|
// Explanation, including an explicitly empty string.
|
||||||
Description *string
|
Description *string
|
||||||
|
// Explanation is safe human-readable context, such as why a reference is
|
||||||
|
// optional because it occurs only on a known skipped path. It is not a
|
||||||
|
// machine-readable contract.
|
||||||
Explanation string
|
Explanation string
|
||||||
}
|
}
|
||||||
|
|
||||||
// VariableRequirement describes a caller-map key referenced by a prompt.
|
// VariableRequirement describes a caller-map key referenced by a prompt.
|
||||||
type VariableRequirement struct {
|
type VariableRequirement struct {
|
||||||
Name string
|
// Name is the exact caller-map key, not a template-local name.
|
||||||
Kind RequirementKind
|
Name string
|
||||||
Supplied bool
|
// Kind is the strongest classification established for this key.
|
||||||
|
Kind RequirementKind
|
||||||
|
// Supplied reports exact-key presence in the request Vars map. An empty
|
||||||
|
// string is supplied; the value itself is not returned.
|
||||||
|
Supplied bool
|
||||||
|
// Explanation is safe human-readable context and is not a machine-readable
|
||||||
|
// contract.
|
||||||
Explanation string
|
Explanation string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,31 +85,67 @@ type VariableRequirement struct {
|
|||||||
type RequirementIssueCode string
|
type RequirementIssueCode string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RequirementIssueMissingVariable RequirementIssueCode = "missing_variable"
|
// RequirementIssueMissingVariable means an absent caller value prevents
|
||||||
RequirementIssueInputContent RequirementIssueCode = "input_content"
|
// resolving a dependency decision or input name.
|
||||||
RequirementIssueDynamicInputName RequirementIssueCode = "dynamic_input_name"
|
RequirementIssueMissingVariable RequirementIssueCode = "missing_variable"
|
||||||
|
// RequirementIssueInputContent means unavailable input content affects
|
||||||
|
// dependency discovery.
|
||||||
|
RequirementIssueInputContent RequirementIssueCode = "input_content"
|
||||||
|
// RequirementIssueDynamicInputName means a referenced input name cannot be
|
||||||
|
// determined for the supplied context.
|
||||||
|
RequirementIssueDynamicInputName RequirementIssueCode = "dynamic_input_name"
|
||||||
|
// RequirementIssueUnsupportedConstruct means a dependency-relevant
|
||||||
|
// expression or scope is outside the supported discovery analysis.
|
||||||
RequirementIssueUnsupportedConstruct RequirementIssueCode = "unsupported_construct"
|
RequirementIssueUnsupportedConstruct RequirementIssueCode = "unsupported_construct"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RequirementIssue describes one discovery limitation using safe summary
|
// RequirementIssue describes one discovery limitation using safe summary
|
||||||
// text. Descriptions are not intended as machine-readable details.
|
// text. Descriptions are not intended as machine-readable details.
|
||||||
type RequirementIssue struct {
|
type RequirementIssue struct {
|
||||||
Code RequirementIssueCode
|
// Code is the machine-readable limitation category.
|
||||||
InputName string
|
Code RequirementIssueCode
|
||||||
|
// InputName identifies an affected input when one is known; empty means no
|
||||||
|
// particular input was identified.
|
||||||
|
InputName string
|
||||||
|
// VariableName identifies an affected caller key when one is known; empty
|
||||||
|
// means no particular key was identified.
|
||||||
VariableName string
|
VariableName string
|
||||||
Description string
|
// Description is a safe human-readable summary, not a string to parse.
|
||||||
|
Description string
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequirementInspection contains discovered dependencies for one selected
|
// RequirementInspection contains discovered dependencies for one selected
|
||||||
// prompt context. Complete describes discovery, not renderability or readiness.
|
// prompt context. Input and variable entries are sorted by exact name. Issues
|
||||||
|
// are deduplicated by code and associated names, then sorted by that tuple.
|
||||||
|
// Their descriptions and entry explanations are safe summaries, not
|
||||||
|
// machine-readable details.
|
||||||
|
//
|
||||||
|
// Complete describes the supported analysis's discovery coverage, not whether
|
||||||
|
// requirements are supplied, templates will render, artifacts or schemas are
|
||||||
|
// valid, or execution is ready. A complete result can still contain required
|
||||||
|
// inputs or missing required variables. Valid templates using dependency-
|
||||||
|
// relevant constructs outside the deliberately small recognition scope may
|
||||||
|
// produce useful partial inventories with Complete false; this is not a
|
||||||
|
// template-definition error or an authoring prohibition.
|
||||||
type RequirementInspection struct {
|
type RequirementInspection struct {
|
||||||
PromptID string
|
// PromptID is the selected exact prompt ID.
|
||||||
|
PromptID string
|
||||||
|
// PromptVersion is the selected exact prompt version.
|
||||||
PromptVersion string
|
PromptVersion string
|
||||||
ProfileID string
|
// ProfileID is the selected profile identity; it does not indicate
|
||||||
Inputs []InputRequirement
|
// execution readiness.
|
||||||
Variables []VariableRequirement
|
ProfileID string
|
||||||
Complete bool
|
// Inputs contains declared inputs and recognizable template references,
|
||||||
Issues []RequirementIssue
|
// including entries known to be optional.
|
||||||
|
Inputs []InputRequirement
|
||||||
|
// Variables contains recognizable caller-map keys, including keys used
|
||||||
|
// only on known skipped paths.
|
||||||
|
Variables []VariableRequirement
|
||||||
|
// Complete reports discovery coverage, not requirement satisfaction or
|
||||||
|
// execution readiness.
|
||||||
|
Complete bool
|
||||||
|
// Issues contains deduplicated, structured discovery limitations.
|
||||||
|
Issues []RequirementIssue
|
||||||
}
|
}
|
||||||
|
|
||||||
// InspectRequirements discovers inputs and caller variables for one selected
|
// InspectRequirements discovers inputs and caller variables for one selected
|
||||||
@@ -89,6 +156,14 @@ type RequirementInspection struct {
|
|||||||
// captured session template. Vars are copied before analysis, and returned
|
// captured session template. Vars are copied before analysis, and returned
|
||||||
// slices and metadata pointers belong to the caller.
|
// slices and metadata pointers belong to the caller.
|
||||||
//
|
//
|
||||||
|
// Discovery recognizes literal input names, direct caller-map keys, literal-
|
||||||
|
// key root-map lookups, simple caller-derived input names, and if/with
|
||||||
|
// conditions based on direct values, literals, negation, or two-string
|
||||||
|
// equality/inequality. It classifies recognizable references on known skipped
|
||||||
|
// paths as optional. Other dependency-relevant expressions or scopes may leave
|
||||||
|
// a useful partial result with Complete false. The returned inventories do
|
||||||
|
// not reject otherwise valid templates or prohibit their use.
|
||||||
|
//
|
||||||
// This method does not perform artifact, schema, credential, rendering,
|
// This method does not perform artifact, schema, credential, rendering,
|
||||||
// validation, capacity, observation, provider, or execution work. Complete
|
// validation, capacity, observation, provider, or execution work. Complete
|
||||||
// describes dependency discovery, not whether every dependency is supplied or
|
// describes dependency discovery, not whether every dependency is supplied or
|
||||||
@@ -98,7 +173,9 @@ type RequirementInspection struct {
|
|||||||
// selection match ErrInvalidRequest; an absent profile selection also matches
|
// selection match ErrInvalidRequest; an absent profile selection also matches
|
||||||
// ErrProfileRequired. Missing prompt/profile IDs match ErrPromptNotFound or
|
// ErrProfileRequired. Missing prompt/profile IDs match ErrPromptNotFound or
|
||||||
// ErrProfileNotFound. Other selection/snapshot failures match ErrPromptLoad or
|
// ErrProfileNotFound. Other selection/snapshot failures match ErrPromptLoad or
|
||||||
// ErrProfileLoad. A nil Engine matches ErrInvalidConfig.
|
// ErrProfileLoad. When cancellation prevents lookup or analysis, no inspection
|
||||||
|
// is returned and the context error remains discoverable with errors.Is. A nil
|
||||||
|
// Engine matches ErrInvalidConfig.
|
||||||
func (e *Engine) InspectRequirements(
|
func (e *Engine) InspectRequirements(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
req RequirementInspectionRequest,
|
req RequirementInspectionRequest,
|
||||||
|
|||||||
Reference in New Issue
Block a user