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,
|
||||
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
|
||||
|
||||
[`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
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
**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
|
||||
canonical owners, with final verification ready for user review.
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# Effective Prompt Requirement Inspection
|
||||
|
||||
Status: Implementation planned; the feature is not implemented. The
|
||||
[implementation plan](implementation.md) owns the ordered implementation steps.
|
||||
This document owns the purpose, scope, and target end state.
|
||||
Status: Implemented (2026-10-08). The
|
||||
[implementation plan](implementation.md) records the completed work units and
|
||||
final verification. Current public API details live in GoDoc; the consumer
|
||||
guide, format reference, and internal documents link to those canonical
|
||||
contracts.
|
||||
|
||||
## Purpose
|
||||
|
||||
@@ -16,7 +18,7 @@ The originating request is [Scriptorium's feature request](scriptorium-feature-r
|
||||
Promptkit supplies application-neutral inspection; consumers own presentation,
|
||||
binding checks, and their own workflows.
|
||||
|
||||
## Current Baseline
|
||||
## Original Review Baseline
|
||||
|
||||
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
|
||||
expression or variable map.
|
||||
|
||||
## Work Needed From The Baseline
|
||||
## Implemented Outcome
|
||||
|
||||
Add request/result values and the engine method through the root facade.
|
||||
Keep selection coordination internal and place syntax discovery with the
|
||||
existing prompt-template component. Reuse captured templates and selection
|
||||
helpers rather than creating another preparation path.
|
||||
The root API selects a captured prompt and profile identity, then returns
|
||||
caller-owned input and variable inventories with conservative classifications
|
||||
and structured discovery limitations. The internal prompt walker uses captured
|
||||
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
|
||||
alongside inspection snapshots. Apply [ADR 0001](../adr/0001-configuration-boundary.md):
|
||||
interpret final effective definitions, not raw/intermediate configuration or
|
||||
history. Operator provenance remains a separate explicit API.
|
||||
|
||||
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.
|
||||
The final verification and the commit sequence are recorded in the
|
||||
[implementation plan](implementation.md). The exact public contract is owned by
|
||||
[GoDoc](../../requirements.go); consumer usage, framework-format cross-reference,
|
||||
and internal selection/source descriptions are maintained in their respective
|
||||
documents.
|
||||
|
||||
## Acceptance Outcomes
|
||||
|
||||
|
||||
@@ -36,6 +36,17 @@ func main() {
|
||||
if _, found := view.Explain(configkit.Keys("profiles", "offline-example", "model")); !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{
|
||||
PromptID: "example.prepare",
|
||||
|
||||
135
requirements.go
135
requirements.go
@@ -10,43 +10,74 @@ import (
|
||||
// RequirementInspectionRequest selects a prompt and supplies caller context
|
||||
// for requirement discovery. It requires no artifact bindings or credentials.
|
||||
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
|
||||
ProfileID string
|
||||
Vars map[string]string
|
||||
SessionID string
|
||||
// ProfileID selects the exact effective profile identity. If empty, the
|
||||
// prompt's default profile is used; the profile need not be ready for
|
||||
// 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
|
||||
// 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
|
||||
|
||||
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"
|
||||
// RequirementConditional identifies a dependency whose reachability is
|
||||
// unresolved for the supplied context.
|
||||
// RequirementConditional identifies a dependency whose reachability or
|
||||
// identity remains unresolved for the supplied context.
|
||||
RequirementConditional RequirementKind = "conditional"
|
||||
// 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"
|
||||
)
|
||||
|
||||
// InputRequirement describes a declared or template-referenced prompt input.
|
||||
type InputRequirement struct {
|
||||
Name string
|
||||
Kind RequirementKind
|
||||
Declared bool
|
||||
// Name is the exact input identifier.
|
||||
Name string
|
||||
// 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
|
||||
// Description preserves effective metadata presence independently of
|
||||
// Explanation, including an explicitly empty 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
|
||||
}
|
||||
|
||||
// VariableRequirement describes a caller-map key referenced by a prompt.
|
||||
type VariableRequirement struct {
|
||||
Name string
|
||||
Kind RequirementKind
|
||||
Supplied bool
|
||||
// Name is the exact caller-map key, not a template-local name.
|
||||
Name string
|
||||
// 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
|
||||
}
|
||||
|
||||
@@ -54,31 +85,67 @@ type VariableRequirement struct {
|
||||
type RequirementIssueCode string
|
||||
|
||||
const (
|
||||
RequirementIssueMissingVariable RequirementIssueCode = "missing_variable"
|
||||
RequirementIssueInputContent RequirementIssueCode = "input_content"
|
||||
RequirementIssueDynamicInputName RequirementIssueCode = "dynamic_input_name"
|
||||
// RequirementIssueMissingVariable means an absent caller value prevents
|
||||
// resolving a dependency decision or 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"
|
||||
)
|
||||
|
||||
// RequirementIssue describes one discovery limitation using safe summary
|
||||
// text. Descriptions are not intended as machine-readable details.
|
||||
type RequirementIssue struct {
|
||||
Code RequirementIssueCode
|
||||
InputName string
|
||||
// Code is the machine-readable limitation category.
|
||||
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
|
||||
Description string
|
||||
// Description is a safe human-readable summary, not a string to parse.
|
||||
Description string
|
||||
}
|
||||
|
||||
// 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 {
|
||||
PromptID string
|
||||
// PromptID is the selected exact prompt ID.
|
||||
PromptID string
|
||||
// PromptVersion is the selected exact prompt version.
|
||||
PromptVersion string
|
||||
ProfileID string
|
||||
Inputs []InputRequirement
|
||||
Variables []VariableRequirement
|
||||
Complete bool
|
||||
Issues []RequirementIssue
|
||||
// ProfileID is the selected profile identity; it does not indicate
|
||||
// execution readiness.
|
||||
ProfileID string
|
||||
// Inputs contains declared inputs and recognizable template references,
|
||||
// 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
|
||||
@@ -89,6 +156,14 @@ type RequirementInspection struct {
|
||||
// captured session template. Vars are copied before analysis, and returned
|
||||
// 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,
|
||||
// validation, capacity, observation, provider, or execution work. Complete
|
||||
// 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
|
||||
// ErrProfileRequired. Missing prompt/profile IDs match ErrPromptNotFound 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(
|
||||
ctx context.Context,
|
||||
req RequirementInspectionRequest,
|
||||
|
||||
Reference in New Issue
Block a user