diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index 81f30f8..10d39d6 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -9,10 +9,11 @@ ReleaseKit adoption plan; that plan remains available in Git history. - Baseline: `7827ca043b5de84a18199ac8f4b3056691aacbb5`. There is no effective requirement-inspection API yet. `InspectPrompt` reports declarations; `Prepare` needs artifacts. The configured engine captures compiled templates. -- The stages use the roadmap's recommended practical analysis core and - active-context inventory. The previously open scope choices and alternatives - are recorded under Open Questions; do not silently substitute broader analysis - or an all-reference inventory. +- The agreed scope is the practical analysis core, with statically identifiable + inactive undeclared input references included as optional inventory entries + and explained as inactive. Distinguish this inventory from applicable + dependencies; it does not require evaluating skipped expressions or adopting + broader Go-template interpretation. - Start with [development](../development.md), then read the [agent](../policy/agents.md), [architecture](../policy/architecture.md), [testing](../policy/testing.md), and [documentation](../policy/documentation.md) @@ -65,6 +66,7 @@ type InputRequirement struct { Declared bool ContentType *string Description *string + Explanation string } type VariableRequirement struct { @@ -114,11 +116,17 @@ establish that an input/variable is absent. - Always report declarations. A declared required input stays required. Active template accesses can promote an optional declaration to required. - Undeclared references on known inactive paths are omitted. + Include statically identifiable undeclared references on known inactive paths + as optional entries with an inactive-use explanation. - An entry is required when its use is established for the context, conditional when a possible use depends on unresolved analysis, and optional when no applicable use needs it and unresolved effects do not undermine that conclusion. An established required use dominates conditional/optional uses. +- `Explanation` is a safe human-readable summary of inactive-only use, separate + from declared `Description`. Its wording is not a machine-readable contract. + Do not add an uncertainty issue for known inactivity. Required or conditional + uses elsewhere override inactive-only classification and explanation. + Caller variables used solely on known inactive paths are not requirements. - Aggregate inputs and variables by exact execution name. Do not trim request variable keys or discovered helper names. Configuration normalization remains with the existing configuration adapter. @@ -144,6 +152,10 @@ establish that an input/variable is absent. whether they are satisfied. `{{.audience}} {{input "note"}}` can yield complete discovery with a missing required `audience` and known required `note`. Reading the body of `note` is unnecessary to identify that dependency. +An empty complete input set, or a complete inventory containing only optional +entries, establishes that no artifact bindings are needed. Nonempty inventory +alone does not establish that artifacts are needed; incomplete discovery does +not establish their absence. Unknown values carry their cause internally. Emit issues and mark incomplete when uncertainty affects a dependency decision/name, or an opaque construct @@ -153,13 +165,16 @@ An unknown branch containing only text need not make discovery incomplete. For an unresolved branch, analyze both paths once and combine access summaries: a name definitely needed on both paths can stay required; names possible on only some paths are conditional. Merge branch-local unresolved issues. -Compare requirement summaries, not rendered content, and do not enumerate -combinations of independent conditions. Conservative incompleteness is valid +Compare applicable requirement summaries, not inactive inventory or rendered +content, and do not enumerate combinations of independent conditions. +Conservative incompleteness is valid where the core cannot prove an exact set; do not claim completeness there. Unresolved dynamic names/opaque input effects must not leave otherwise optional -declarations falsely definitive. Mark affected declared optional inputs -conditional; an unrestricted unknown input name can affect all such declarations. +input entries falsely definitive. Mark affected optional entries conditional, +including previously inactive-only undeclared entries; an unrestricted unknown +input name can affect all such entries. Clear inactive-only explanations where +possible active uses undermine them. An unknown-name issue also describes potential undiscovered undeclared names. Known required declarations remain required. @@ -187,6 +202,18 @@ A numeric literal or unsupported pure output expression is not itself a caller requirement. Discover its evaluated arguments where that is safe; its value can remain unknown until a later dependency decision needs it. Known short-circuit paths must not collect dependencies from skipped operands or branches. +They can contribute optional inactive inventory as described below, without +collecting skipped caller-variable requirements or uncertainty. + +For a known inactive path, use a non-evaluating syntax walk to collect literal +`input` names, including equivalent parenthesized/piped literal forms. Walk +skipped branch bodies and short-circuit operands without reading caller values, +mutating local environments, or invoking templates/functions. Unresolved +dynamic names and unsupported expressions in these skipped paths do not make +discovery incomplete. Never-invoked definitions and a directly bypassed session +template remain outside this inventory. Track inactive-only occurrences +separately from definite/possible uses so aggregation can classify a shared +name correctly. Use a small private known/unknown value model. Branch joins retain identical known values and can retain finite possible string names from direct @@ -249,7 +276,9 @@ discoverable through an internal analyzer. `input "name"` calls, deduplicate names, and aggregate required accesses. Analyze the session first when applicable and messages in their existing order. 4. Add aggregation/finalization helpers for classification, independent metadata, - ordering, safe issue construction, and `Complete`. Do not produce prompt text. + ordering, safe explanations/issue construction, and `Complete`. Keep + inactive-only occurrence information separate from applicable accesses for + Stage 5. Do not produce prompt text. 5. Until later stages implement control flow, return conservative incomplete results for constructs that can hide dependencies. Temporary partial coverage is internal implementation status, not a new public promise. @@ -304,6 +333,8 @@ with Go templates. 3. Once a preceding operand leaves access uncertain, treat later potentially evaluated operands conditionally rather than definitely accessed or skipped. Preserve unknown causes for later dependency decisions. + Stage 5 adds optional inventory for definitely skipped helper expressions; + these are not applicable input or variable dependencies. 4. Keep unsupported/incompatible evaluation as an internal unknown value with a safe category. Do not leak values through errors or convert it into a new construction/request rejection. @@ -316,27 +347,36 @@ comparisons, multi-operand `eq`, and `and`/`or` skips containing helper calls or missing variables. Compare representative supported expressions with the existing Go renderer. Run `go test ./internal/prompt`; commit. -## Stage 5 — Analyze Known Branches And Lexical Scope +## Stage 5 — Analyze Known Branches, Scope, And Inactive Inventory **Outcome:** Supplied context resolves ordinary `if`/`with` dependencies; -known inactive uses are omitted. +statically identifiable inactive input references remain optional inventory. **Work:** 1. Add `if`/`else` and `with` traversal for known predicate values. - Analyze only the selected path. + Evaluate only the selected path for applicable dependencies. 2. Preserve root `$`, `with` dot changes, pipeline-declared symbols, block shadowing, and assignments to outer symbols. Follow Go's lexical lifetimes. 3. Never reinterpret `.field` against a known string dot as a root-map lookup. Unsupported field operations have unknown values, not invented variables. -4. Retain declarations regardless of branch activity; omit undeclared helper - and variable accesses solely on a known inactive path. -5. Keep uncertain predicates using the temporary conservative handling until +4. Add the non-evaluating inactive syntax walk specified above. Include literal + helper names from skipped branches and short-circuit operands as optional + entries with a safe inactive-use explanation. Preserve declarations and + aggregate other uses of the same name; required/conditional uses dominate. +5. Do not evaluate skipped predicates, resolve skipped dynamic names, mutate + branch environments, or collect skipped caller-variable requirements/issues. + Do not inspect uncalled definitions or a bypassed session template. +6. Keep uncertain predicates using the temporary conservative handling until Stage 6; do not guess their truth from placeholders. **Verify:** Both known branches, nested `if`/`with`, root access from changed dot, declarations versus assignments/shadowing, and inactive helpers/missing variables. Include declared-required and declared-optional inputs in these cases. +Test inactive undeclared literal and equivalent parenthesized/piped names, +inactive explanations, active reuse overriding inactivity, and skipped dynamic +or unsupported expressions causing no uncertainty. Verify that a complete +all-optional inventory requires no artifacts. Run `go test ./internal/prompt`; commit. ## Stage 6 — Join Unresolved Paths And Finalize Completeness @@ -354,7 +394,8 @@ results without inventing definitive classifications. or a declared required input still dominates. 3. Emit uncertainty only when it affects discovered requirements. An unresolved text-only branch can still have a complete requirement set; no output rendering - is needed to establish that. + is needed to establish that. Inactive inventory entries alone do not change + applicable dependency summaries or introduce incompleteness. 4. Support input-body-caused unknown conditions without reading the body: the predicate's known helper name is required; dependent branches are partial. 5. Handle out-of-core controls/calls conservatively. Inspect identifiable @@ -372,7 +413,7 @@ returning incomplete rather than errors. Run `go test ./internal/prompt`; commit ## Stage 7 — Finish Dynamic Names And Conservative Inventory Aggregation **Outcome:** Direct variable/alias names resolve exactly; unresolved names -preserve known candidates and correctly affect declaration classifications. +preserve known candidates and correctly affect optional inventory classifications. **Work:** @@ -385,17 +426,20 @@ preserve known candidates and correctly affect declaration classifications. 3. Emit dynamic-name issues together with useful missing-variable, input-content, unsupported, or expression-unresolved categories from the underlying value. Do not echo values beyond a resolved/known possible binding identifier. -4. Make potentially targeted declared optional inputs conditional: candidate-only - uncertainty affects matching declarations; unrestricted/opaque input effects - can affect all optional declarations. Leave known required inputs required. +4. Make potentially targeted optional input entries conditional: candidate-only + uncertainty affects matching entries; unrestricted/opaque input effects + can affect all optional entries, including inactive undeclared inventory. + Remove inactive-only explanations when possible active uses undermine them. + Leave known required inputs required. 5. Finalize deduplication, lexical ordering, metadata propagation, variable - `Supplied` flags, and completeness. No placeholder `"*"` input name, - invented variable default, payload read, or binding-validation API. + `Supplied` flags, inactive-use explanations, and completeness. No placeholder + `"*"` input name, invented variable default, payload read, or binding-validation API. **Verify:** Exact dynamic names, empty supplied values versus missing values, aliases selected by known branches, finite names from unknown assignments, unrestricted names, repeated uses across messages/session, and optional -declaration uncertainty. Verify results contain no unrelated variable values. +declaration/inactive inventory uncertainty. Verify results contain no unrelated +variable values or skipped-variable requirements. Run `go test ./internal/prompt`; commit. ## Stage 8 — Wire Selection And The Public Engine Facade @@ -425,6 +469,8 @@ credentials, schema preparation, or execution collaborators. selected identities and forward through `internal/engine`. 6. Add the public values/method in root `requirements.go`, conversion helpers, GoDoc, and normal `mapPublicError` translation. Copy mutable values as above. + Document inactive inventory and `Explanation` separately from declaration + metadata and structured uncertainty; do not promise diagnostic wording. Nil engine matches `ErrInvalidConfig`; operational errors return no partial result. Successful incomplete discovery returns a result and nil error. 7. Preserve existing public error categories for absent prompt/profile, @@ -452,17 +498,22 @@ duplicating the analyzer's detailed case matrix. 2. Prove exact `transcript` discovery, undeclared literal inputs, required and optional declarations in inactive branches, context-selected names, and session-only requirements removed by a direct session ID. + Include optional inactive undeclared entries with explanations, active reuse + overriding inactivity, and bypassed session names absent from the inventory. 3. Cover complete-but-unsatisfied variable requirements, conditional/unknown dependencies, and empty complete versus empty incomplete input sets. + Cover complete all-optional inventories and no caller requirements from + solely inactive variable accesses. 4. Preserve classifiable errors for selection/cancellation. Test inspection against a valid partial profile and an explicit direct-key-required profile without an API key; missing runtime schemas and future artifact files must not prevent inspection. Inject fail-if-called artifact/model/validator collaborators where supported to prove the relevant absence of execution. -5. Use a small parity table: known-context inspector requirements must agree - with `Prepare`/the renderer's input and variable semantics when actual - synthetic artifacts are later supplied. Do not use execution failure order - as the definition of all discovered requirements. +5. Use a small parity table: known-context applicable inspector requirements + must agree with `Prepare`/the renderer's input and variable semantics when + actual synthetic artifacts are later supplied. Do not use execution failure + order as the definition of all discovered requirements. + Do not compare optional inventory entries to actual renderer helper accesses. 6. Test source capture using a file-backed message changed/deleted after engine construction. New inspection uses the captured content, like existing runs. 7. Mutate returned metadata/slices and repeat inspection; run representative @@ -471,6 +522,7 @@ duplicating the analyzer's detailed case matrix. 8. Verify safe diagnostics/result formatting with marker values: unrelated variable values, direct session value, template text, and credential values are absent; input identifiers and declared descriptions are allowed. + Include inactive explanations in the disclosure checks. 9. Keep analyzer tests as the owner of detailed expression/branch semantics; root tests own public values, errors, ownership, and assembled behavior. @@ -491,6 +543,8 @@ and the complete feature is ready for review, not automatically published. 2. Add task-oriented consumer guidance comparing the three inspection methods and preparation. Demonstrate required `transcript`, missing variables, and explicit incomplete discovery without a Promptkit JSON format. + Explain optional inactive inventory and reading requirement classifications + rather than treating every input entry as a binding to prepare. 3. Update relevant format cross-references, internal source/runner/component documents, and development reading guidance. Do not duplicate the exact public contract outside GoDoc or describe unsupported constructs as invalid. @@ -526,42 +580,10 @@ and the complete feature is ready for review, not automatically published. remains a structured successful partial result, not guessed absence or error. - Missing values, conditional requirements, metadata absence, and session bypass are distinguishable without leaking unrelated content. +- Inactive undeclared references appear as optional entries with explanations; + they do not introduce skipped-variable requirements or uncertainty. Complete + all-optional inventories remain distinguishable from incomplete discovery. - Public classification and ownership tests pass; no provider/resource preflight, arbitrary limit, application wire schema, or new template-validity rule was added. - Canonical documentation and maintained examples reflect the implemented discovery boundary. Successful checks for the final snapshot are reported. - -## Open Questions - -### Confirm The Practical-Core Scope - -The roadmap still records this as open. This plan uses the recommended core, -made precise in the table above, and treats other dependency-relevant constructs -as incomplete without affecting their execution validity. - -**Recommendation:** Use that practical core for this feature. It addresses the -consumer scenarios and gives maintainable, testable completeness while avoiding -a full interpreter. Extend coverage later when concrete prompts justify it. - -**Alternative:** Include ranges, invoked named templates, numeric comparison, -and more built-in value pipelines in this implementation. That improves complete -discovery for more prompts, but needs additional independent stages and more -semantic parity coverage. It still cannot resolve artifact-content-dependent -decisions before artifacts exist. - -### Confirm The Inactive-Reference Inventory - -This plan uses the roadmap recommendation: declarations are always reported, -while undeclared references solely on known inactive paths are omitted. - -**Recommendation:** Keep that effective-context inventory. It avoids confusing -potential future prompt uses with bindings the current context needs. - -**Alternative:** Include statically identifiable inactive undeclared references -as optional entries with an inactive-use explanation. That is useful for broader -operator exploration, but expands result/issue semantics and requires tests and -documentation distinguishing inventory from applicable dependencies. - -These questions concern the two previously open scope choices, not a new -publication or human sign-off gate. The stages above consistently implement the -recommended baseline; revise that baseline if a different option is selected. diff --git a/docs/roadmap/inspection.md b/docs/roadmap/inspection.md index b111080..2250abf 100644 --- a/docs/roadmap/inspection.md +++ b/docs/roadmap/inspection.md @@ -2,9 +2,8 @@ Status: Implementation planned; the feature is not implemented. The [implementation plan](implementation.md) owns the ordered migration steps and -uses the recommended scope below. Open Decisions still records the alternative -scope choices for confirmation. This document owns the target end state and -migration scope. +implements the agreed analysis scope and inventory below. This document owns +the target end state and migration scope. ## Purpose @@ -80,6 +79,10 @@ The result contains: 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. @@ -94,9 +97,15 @@ 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. -An unresolved dynamic name can refer to a declared optional input. Its absence -from recognized active uses alone does not establish that it is definitely -optional; classification and uncertainty must account for that possibility. +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 @@ -108,7 +117,10 @@ 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; -an empty incomplete set does not establish that fact. +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 @@ -121,6 +133,7 @@ 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 @@ -136,8 +149,8 @@ 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 initial analysis coverage and inactive-reference inventory are the Open -Decisions below. They do not change execution or expand the template language. +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 @@ -209,24 +222,29 @@ not own its contract. The implementation plan owns implementation sequencing. 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. -- No-input completeness is distinguishable from empty partial discovery. +- 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. -## Open Decisions +## Selected Analysis Scope And Inventory ### Initial Template Analysis Coverage -**Recommendation:** Implement a documented practical core: literal input calls, +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 @@ -236,24 +254,20 @@ 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. -**Alternative:** Support substantially broader Go-template evaluation now, -including loops, named templates, and more built-in pipelines. It would produce -complete results for more existing prompts, but increases semantic machinery, -maintenance, and parity-testing costs. It still cannot determine decisions based -on unavailable artifact contents. Prefer it if concrete consumer examples show -that the practical core would frequently return unhelpful partial results. - ### Inactive Undeclared Reference Inventory -**Recommendation:** Always include declarations, plus template-discovered names -needed on active or unresolved paths. Omit undeclared names used solely in a -branch known to be inactive. Conditional names on unresolved paths remain -explicitly conditional. This keeps the result focused on the effective caller -requirements and avoids presenting irrelevant bindings as work to prepare. +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. -**Alternative:** Also list statically identifiable undeclared references on -known inactive paths, marking them optional with an inactive-use explanation. -This gives operators a broader inventory for exploring prompt behavior, but -adds irrelevant names and requires consumers to distinguish that inventory -from applicable dependencies. Either choice must preserve declared optional -metadata and must not classify a known inactive use as required. +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.