Files
promptkit/docs/roadmap/inspection.md

274 lines
16 KiB
Markdown

# Effective Prompt Requirement Inspection
Status: Implementation planned; the feature is not implemented. The
[implementation plan](implementation.md) owns the ordered migration steps and
implements the agreed analysis scope and inventory below. This document owns
the target end state and migration scope.
## Purpose
Let consumers discover a selected prompt's caller requirements before its input
artifacts exist. Scriptorium can expose that information to operators and to
Narratio, which can compare its planned bindings with Promptkit's exact input
names before undertaking expensive pipeline work.
The originating request is `docs/roadmap/scriptorium-feature-request.md`.
The capability is application-neutral: Promptkit describes prompt requirements;
consumers interpret them for their own configuration, presentation, and workflow.
## Current Baseline
At review baseline `b595dca`:
- [InspectPrompt](../consumers/pkg-promptkit.md#inspect-a-prompt-before-preparation)
selects a captured prompt and reports declared inputs and output metadata.
It does not analyze templates or resolve the execution profile.
- [InspectProfile](../consumers/pkg-promptkit.md#inspect-a-profile-before-prompt-work)
reports one captured profile's effective target separately.
- [Prepare](../consumers/pkg-promptkit.md#prepare-without-model-execution)
selects the execution context, checks target requirements, loads artifacts
and applicable schemas, and renders messages. It needs actual input data.
- The configuration adapter captures final effective definitions, message
contents, and compiled message/session templates during engine construction.
Runtime rendering uses Go templates, string-valued caller variables, and the
`input` helper. Declared required inputs are checked independently of template
branches; active helper calls also require their named inputs.
- Declared input metadata currently uses string fields for content type and
description. The new result needs to identify a declaration and distinguish
available metadata from absent metadata, including effective presence where
necessary; current empty strings alone do not establish source-field presence.
The [format reference](../formats.md#messages-and-templates),
[internal source document](../internal/sources.md), and existing GoDoc own the
implemented semantics. No existing operation provides artifact-free,
context-sensitive requirement discovery.
## Target Public Operation
Add a separate read-only engine operation, planned as
`Engine.InspectRequirements`, with a dedicated request and result. Preserve
`InspectPrompt`, `InspectProfile`, preparation, and execution contracts.
The request supplies a prompt ID, optional version, optional profile selector,
supplied template variables, and an optional direct session ID. It needs no
artifact references or contents, output path, API key, or execution settings
unrelated to discovery.
Selection follows equivalent execution semantics: exact identities, omitted
version ambiguity, request profile or prompt default, and direct session-ID
normalization and bypass. Return selected prompt ID/version and effective
profile ID. Profile selection establishes identity, not generation readiness;
profiles that depend on later execution overrides need not be completed here.
Use the configured engine's captured definitions. Source discovery and layering
remain consumer choices. Results describe that captured context, not a promise
about a later engine or later execution with changed variables.
## Result And Requirement Meanings
Expose public Go values with documented classifications and predictable ordering.
Exact symbol and field spelling belongs in the implementation plan
and GoDoc. No Promptkit JSON wire schema is part of this feature.
The result contains:
- Selected prompt and profile identities.
- Known input names, preserving execution identity, with required, optional,
or conditional classification for the supplied context.
- Declaration information, descriptions, and content-type metadata where
available. A template-discovered undeclared input must not look like a
declared input with known metadata. Report existing media-type metadata,
not an invented input schema or inferred format constraint.
- An inactive-use explanation for statically identifiable undeclared inputs
referenced only on known inactive paths. These are optional inventory entries,
not bindings the current context needs. Keep this explanation separate from
declared descriptions.
- Variable requirements separately from artifact inputs, with requirement
classification and whether supplied values satisfy the known requirement.
Report presence and actual supported semantics, not the supplied values.
- A discovery-completeness indicator and structured uncertainty reasons, with
safe explanations and relevant identifiers where available.
Required means the caller must supply the input for this context. A declared
required input stays required even if no active template references it. A
declared optional input becomes required when an active template use needs it.
Optional means it is known not to be required for this context; conditional
means its requirement depends on unresolved context. Do not use optional to
hide uncertainty. Known required declarations retain that classification even
when other requirements are conditional or undiscoverable.
Include statically identifiable undeclared references on known inactive paths
as optional entries with an inactive-use explanation. A required or conditional
use elsewhere takes precedence over that inactive-only classification and
explanation. Inactivity itself is not discovery uncertainty.
An unresolved dynamic name can refer to an otherwise optional input entry. Its
absence from recognized active uses alone does not establish that it is
definitely optional; classification and uncertainty must account for that
possibility.
Known input names should be deduplicated across declarations, messages, and
session templates. Aggregate uses without discarding an established required
use. Conditions need not expose raw expressions; machine-readable reason
categories and safe summaries are sufficient for basic consumer handling.
Completeness describes discovery, not readiness or satisfaction. For example,
a missing variable used only to insert text can be a known unsatisfied
requirement while the complete input set is still discoverable. If that
variable selects an input name or branch, its absence can also make discovery
incomplete. An empty complete input set means no artifact bindings are needed;
a complete inventory containing only optional entries also needs no artifact
bindings. An empty incomplete set does not establish that fact. Consumers must
distinguish the inventory from applicable requirements, rather than treating
every reported name as a needed binding.
## Context-Sensitive Discovery Boundary
Analyze parsed templates rather than searching raw text or rendering with
placeholder artifacts. Use supplied variable values where they determine
branches and input names, following execution's presence, truthiness, scope,
and evaluation semantics. An empty string is not an absent variable, and a
nonempty string must not be reinterpreted as a Boolean merely from its spelling.
Include dependencies from messages and the applicable session-ID template.
A direct nonblank session ID bypasses that template, removing only requirements
introduced solely by it; declarations and message uses remain relevant.
The bypassed session template is also excluded from the inactive inventory.
Literal `input` references are discoverable without reading bodies, including
undeclared references. Artifact content being unavailable does not by itself
make discovery incomplete: it does so when the content affects which further
requirements apply. Variable-derived names are discoverable when supported
analysis can determine the exact name from the supplied context.
When missing variables, content-dependent decisions, unresolved names, or
analysis limitations prevent determination, preserve known requirements and
return successful incomplete discovery. Structured reasons should distinguish
these situations without requiring diagnostic-text matching. Unsupported
analysis is not a new prompt-validity rule. Completeness is asserted only when
the supported analysis establishes the requirement set; it does not promise
universal analysis of every valid Go template.
The selected practical analysis core and inactive inventory are described below.
They do not change execution or expand the template language.
## Effects, Errors, And Disclosure
Inspection uses captured prompt resources and needs no future artifact files,
credential lookup, model access, capacity admission, or execution artifact
creation. It does not prepare an output-validation schema or validate future
input bytes. Necessary configuration/resource failures can still prevent engine
construction or inspection; this is not a general resource preflight.
Use existing public selection/error identities wherever applicable, including
invalid requests, missing prompt/profile selections, and ambiguous versions.
Preserve ordinary context cancellation behavior. Discovery uncertainty is a
result state, distinct from an operational or selection error. Expose any
additional necessary classifications through the public facade, not diagnostic
text parsing or internal types.
Results and safe diagnostics exclude credential values, artifact payloads,
raw/rendered prompt content, and unrelated supplied variable values. Selected
identities, input/variable names, and declared descriptions are intentional
operator metadata. A resolved dynamic input identifier may equal a supplied
variable value; reporting that identifier is necessary to describe the binding.
Keep the disclosure exception limited to its role as an identifier, without
echoing the variable map or the expression that produced it. Scriptorium owns
the presentation and disclosure of this metadata to its callers.
A complete result describes requirements, not successful rendering or generation,
future artifact validity, or provider availability. Incomplete results remain
useful without authorizing consumers to treat unknown dependencies as absent.
## Work Needed From The Baseline
Add public request/result values and the engine method through the existing
facade. Put selection coordination and analysis in internal components with
cohesive ownership. Reuse existing prompt/profile selection, session override,
and template parsing semantics rather than introducing a second preparation
path or a general-purpose template interpreter.
Make the captured templates and effective declaration metadata available to
internal inspection. Retain any required metadata presence at the ConfigKit
handoff. Apply [ADR 0001](../adr/0001-configuration-boundary.md): inspection
interprets final effective definitions, not raw sources, configuration history,
or intermediate artifacts. Operator provenance remains a separate explicit API.
Implement requirement aggregation, context-sensitive analysis, and safe public
uncertainty/error conversion. Keep request-specific analysis separate from
shared captured state. Prefer direct traversals and indexed aggregation; avoid
enumerating every possible branch combination or repeated full-template scans.
Predictable result ordering does not require a stronger complexity guarantee
or a new global cache.
Add focused analyzer tests and public-facade contract coverage under the
[testing policy](../policy/testing.md). Use real captured definitions and
templates, synthetic variables, and explicit unavailable artifacts. Compare
complete discovery with representative execution semantics. Test incomplete
results separately from errors and verify disclosure boundaries and absence
of artifact reads/provider calls. Do not retest ConfigKit's loading matrix.
When implementation lands, update GoDoc, the consumer guide, relevant format
cross-references, and the internal component/source documents. Describe the
analysis boundary and examples of complete, unsatisfied, and incomplete results
in their canonical owners. Release notes explain the new capability; they do
not own its contract. The implementation plan owns implementation sequencing.
## Acceptance Outcomes
- A required `transcript` is reported exactly, allowing a consumer to detect a
planned binding under the wrong name before the transcript exists.
- Literal undeclared helper references are discoverable without making their
absence from declarations a new definition error.
- Declared required inputs remain required in inactive branches; optional
declarations remain optional where no applicable use makes them required.
- Statically identifiable inactive undeclared references are optional entries
with an inactive-use explanation; active and unresolved uses of the same name
take precedence. These entries do not introduce variable requirements or
incompleteness solely from skipped expressions.
- Supported variable-dependent branches and names agree with execution;
unresolved content/name/analysis cases retain known entries and uncertainty.
- Version/profile/default selection and session-template bypass agree with
execution without credential or generation-readiness checks.
- Variables are reported separately, with absent and empty supplied values
interpreted according to the existing template semantics.
- Artifact-free complete results, including all-optional inventories, are
distinguishable from empty partial discovery.
- Errors remain publicly classifiable; results and safe diagnostics disclose
identifiers and declared metadata without unrelated content or secret values.
- Existing inspection and execution APIs retain their contracts. Pipeline
planning, binding validation, CLI/HTTP exposure, presentation, JSON schemas,
graph rendering, batch interfaces, and provider preflight remain downstream.
## Selected Analysis Scope And Inventory
### Initial Template Analysis Coverage
Implement a documented practical core: literal input calls,
direct caller-variable access, ordinary `if`/`with` control flow, and simple
variable-derived names and comparisons where their values are determinable.
Account for template variable scope and short-circuit behavior for supported
expressions. Additional constructs can be supported where straightforward;
otherwise report incompleteness when they affect requirement discovery. The
implementation plan specifies the exact expression families for this baseline.
This covers the representative consumer needs while keeping completeness
honest and avoiding a second general-purpose interpreter.
### Inactive Undeclared Reference Inventory
Always include declarations and discovered active or unresolved dependencies.
Also include statically identifiable undeclared references on known inactive
paths as optional entries with an inactive-use explanation. This broader
inventory helps operators explore prompt behavior while preserving the
distinction between inventory and applicable dependencies.
Collect inactive names from syntax without evaluating skipped expressions.
The initial scope covers literal helper names and equivalent parenthesized or
piped literal forms. Skipped dynamic names need not be resolved, and skipped
variable accesses do not become caller requirements or uncertainty reasons.
Include known skipped branches and short-circuit operands, without expanding
analysis to never-invoked template definitions or a bypassed session template.
Preserve declared optional metadata and required declarations; when another
use makes a name required or conditional, its inactive occurrence does not
override that classification or imply that the name is inactive-only.