diff --git a/docs/roadmap/inspect-backend.md b/docs/roadmap/inspect-backend.md index 6416e95..44aa2a8 100644 --- a/docs/roadmap/inspect-backend.md +++ b/docs/roadmap/inspect-backend.md @@ -10,7 +10,8 @@ The direction is accepted for planning; implementation has not begun. Selected work includes fuller prompt inspection, profile inspection of the resolved profile itself, a new `InspectBackend`, `BackendConfig.Extends`, and typed prompt construction through `PromptConfig`/`PromptSource`. Execution-policy reporting -and prepared-request enhancements have been removed from this roadmap. Decisions below record the accepted boundary and remaining choices. +and prepared-request enhancements have been removed from this roadmap. The +decisions below record the accepted scope and representation approach. ## Resource-Inspection Boundary @@ -71,11 +72,12 @@ guidelines, not prohibitions on a small helper or type when it serves the API. **Selected presentation:** Omit absent optional settings. Preserve explicit values, including zero. Absence is not displayed as zero or `unspecified`. -An explicit null retained in the resolved resource is a configured value, not -an absent key; preserve that distinction where it affects resource semantics. +Treat null like omission where they have the same meaning after ConfigKit +resolution. Preserve their distinction only where it changes resource behavior; +the mere presence of a null key is not enough to justify another public state. The previous draft's rule to omit suppressed outbound controls belonged to an -execution report and does not define resource inspection. Representation of -presence/null in public results is open decision 4. +execution report and does not define resource inspection. Accepted decision 4 +selects typed results with this limited preservation of null semantics. Inspection reports effective resource values rather than original YAML layout, comments, or the history of each inherited field. `InspectConfiguration` remains @@ -123,8 +125,8 @@ presence from an execution target. Execution target presence and prepared metadata describe a later resolution stage and are not substitutes for profile configuration presence. Use the existing configuration capture path to expose the needed information without -introducing a second configuration interpreter. The precise result shape and -migration from `EffectiveModelParams` are open decision 4. +introducing a second configuration interpreter. Follow accepted decision 4 for +typed results and migration from `EffectiveModelParams`. This roadmap changes no `Prepare`, `PreparedRun`, `PrepareExecution`, or `PreparedExecution.Details` contract. Execution continues to apply backend @@ -173,8 +175,9 @@ A particular connected layout is a consumer choice, not a new Promptkit API. Coordinate CommandKit adoption of the changed profile result and richer prompt and backend views. In particular, migrate any formatter that currently expects `EffectiveModelParams`. The profile semantic change must be documented as such, -not presented as merely adding more fields. Select the Go/serialization migration -in decision 4 and follow the existing release policy for compatibility changes. +not presented as merely adding more fields. Document the Go/serialization +migration for the typed result selected in decision 4 and follow the existing +release policy for compatibility changes. Existing preparation APIs remain available for separate concrete-request uses; this roadmap adds neither preview commands nor execution-policy report fields. @@ -242,8 +245,9 @@ source round-tripping are not selected deliverables. ## Decisions -Decisions 1, 2, 3, and 5 are accepted. Only decision 4 remains open. Numbering is -retained for continuity with the discussion; implementation is pending. +All five decisions below are resolved. Numbering is retained for continuity with +the discussion; implementation is pending. The follow-up review of field-specific +null semantics in decision 4 does not select a configuration behavior change. ### 1. How Should An Unknown Backend Be Classified? @@ -308,29 +312,46 @@ is unnecessary; raw mappings continue to serve those cases. ### 4. How Should Resolved Resource Results And Presence Be Represented? -The chosen meaning of inspection is settled; the public Go shape and migration -from the existing backend-completed profile result are not. +**Status:** Accepted; implementation pending. -**Recommendation:** Use a resource-oriented typed profile result, reusing suitable -public nested values and representing absent/explicit-zero/explicit-null values -where needed. Prefer a deliberate, documented change to `ProfileInspection` over -retaining a second execution-settings view just for compatibility. Choose the -smallest presence representation supported by captured configuration; do not -reuse `ExecutionTargetPresence` as if it represented the uncompleted profile. -Apply the same resource semantics to prompt/backend result additions without -requiring a generic resource framework. +**Decision (Option A):** Use resource-oriented typed inspection results, reusing +suitable public nested values. Change `ProfileInspection` deliberately to report +the resolved profile rather than retaining a second execution-settings view for +compatibility. Apply the same resource semantics to prompt/backend additions. -**Alternative:** Expose resolved resource fields as a caller-owned mapping, -possibly alongside typed identity and prompt metadata. That naturally represents -missing keys and null and can reduce per-field projection work, but gives up Go -field discoverability and requires careful definition of the mapping's values -and compatibility. Compare that cost with the typed representation rather than -assuming another complete family of public configuration types is necessary. +Represent absent settings and explicit values, including zero, false, and empty +strings where valid. Preserve an omitted/null distinction only when it has a +meaningful effect after ConfigKit has finished resolution. Otherwise, treat null +as absent in the resource result. Clearing a parent's value during ConfigKit +inheritance is not, by itself, a reason to retain a third state afterward. +Use the smallest field-specific representation needed; a universal three-state +wrapper or generic resource framework is not selected. Execution-target presence +does not represent the uncompleted profile and must not substitute for it. -Decide the migration for existing `EffectiveModelParams` consumers and any -serialization changes explicitly. CommandKit can own its report formatting; -new JSON contracts or custom serializers are not automatically required. Neither -option authorizes leaking internal package types or mutable captured state. +The current cases needing this distinction are profile `endpoint`, `api_key_env`, +and whole-map `extra_params`: they control whether later backend completion may +provide a value. Arbitrary nulls inside provider data remain provider data. +The [format reference](../formats.md#defaults-and-overrides) owns those semantics. +Their continuing value is a separate follow-up discussion; accepting typed +inspection does not endorse every existing null rule as permanently necessary +or authorize changing configuration behavior in this work. + +**Rationale:** Typed results provide discoverable Go fields without making +consumers interpret a generic configuration mapping. Limiting additional +presence handling to meaningful cases avoids carrying source syntax and +inheritance history into every field. Existing implementation machinery is not +itself justification for a public distinction. + +**Alternative considered:** A caller-owned resource mapping naturally represents +missing keys and null and can reduce per-field projection work, but sacrifices +typed discoverability and introduces a broader mapping-value contract. It is not +selected as the primary resource-inspection result; `InspectConfiguration` +remains available for explicit configuration/provenance inspection. + +Document migration for existing `EffectiveModelParams` consumers and any +serialization changes with the final Go types. CommandKit owns report formatting; +new JSON contracts or custom serializers are not automatically required. Do not +leak internal package types or mutable captured state. ### 5. Backend Diagnostics Show Configured Values, Not Derived Destinations @@ -345,12 +366,13 @@ in resource inspection. ## Implementation And Verification -1. Resolve result representation/migration in decision 4. Source-input helper - types and inspection results have distinct purposes; select their shapes - accordingly. +1. Define the typed results and migration selected in decision 4. Source-input + helper types and inspection results have distinct purposes; select their + shapes accordingly, with additional null handling only where meaningful. 2. Expose expanded prompt content and resolved profile fields through existing capture/lookup paths, before execution completion. Preserve configured - presence/null distinctions without another composition pass. + presence/null distinctions only where meaningful, without another composition + pass. 3. Add backend inspection and the accepted public missing-backend error, returning configured diagnostic metadata without endpoint derivation. 4. Add typed backend inheritance and the prompt source/helper types, delegating @@ -362,7 +384,9 @@ Use focused offline tests for actual boundary risks: - Child resources show the resolved inherited fields and overrides, not an unresolved `extends` directive; explicit zero survives and absent fields - remain distinguishable from configured null where meaningful. + remain distinguishable from configured null where meaningful. Equivalent + omitted/null settings use the same absent representation; provider-data nulls + retain their literal meaning. - Profile inspection excludes settings supplied only by a referenced backend, framework execution defaults, or a request. Existing execution still applies those settings through its ordinary resolution path.