diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md new file mode 100644 index 0000000..88e94ae --- /dev/null +++ b/docs/roadmap/implementation.md @@ -0,0 +1,568 @@ +# Resource Inspection And Typed Sources Implementation Plan + +## Purpose And Sprint Model + +Implement the accepted [resource inspection roadmap](inspect-backend.md). That +document owns intent, scope, and product decisions; this plan owns the concrete +steps and representation choices needed to deliver them. + +Baseline: `951739e`. ConfigKit v1.1.0 composes and resolves definitions once. +Promptkit captures executable prompts and backend-completed profile targets. +`InspectPrompt` currently exposes limited metadata; `InspectProfile` exposes an +execution target. There is no `InspectBackend` or typed `PromptSource`, and +`BackendConfig` lacks `Extends`. Existing inspection values do not have the +selected generic JSON/YAML contract. + +Each numbered stage is intended for one Luna implementation prompt, in order. +This is one end-to-end sprint: intermediate stages may fail to compile or leave +callers unmigrated. Do not build compatibility shims, optional capability probes, +dual public inspection modes, or temporary representations just to keep each +stage green. Run focused checks as their affected paths become buildable; +record deferred checks and resolve them before the final stage. There are no +intermediate human-review, publication, or downstream-release gates. + +Follow [agent](../policy/agents.md), [architecture](../policy/architecture.md), +[testing](../policy/testing.md), and [documentation](../policy/documentation.md) +policies and the [configuration boundary ADR](../adr/0001-configuration-boundary.md). +Use the [development guide](../development.md) for toolchain selection and local +commits. Commit completed nonempty units and record stage completion here, +including checks run or deferred. Intermediate commits need not be releasable. + +## Selected Implementation Decisions + +### Resource Boundary And Internal Flow + +All three public inspection operations return the selected resolved resource, +before execution completion. References remain references. Imported message +text comes from the already materialized prompt, not another file read. + +Use a narrow, private resource-inspection interface on `internal/engine.Engine`, +implemented by the configuration snapshot, alongside its existing inspection +and listing collaborators. Its methods accept a context and exact full ID and +return configuration-owned internal resource views. The engine qualifies +caller IDs with the appropriate namespace and delegates. The root facade checks +engine validity, maps errors, and projects detached public values. + +Keep configuration resource views under `internal/configuration`; they contain +no ConfigKit types in their engine-facing fields. Do not add these operations +to execution-profile, generation, capacity, or transport interfaces. Remove the +now-unused runner `InspectPrompt` and `InspectProfile` entry points when wiring +is switched. Retain execution selection helpers used by preparation and smoke +tests. + +Requirement discovery still needs only the small existing prompt metadata +lookup and requirement snapshot. Keep `promptdef.Repository.GetPromptInspection` +and its narrow `domain.PromptInspection` for that purpose, with comments making +the distinction clear. Do not expand that internal value with message bodies. +The new configuration resource view is distinct from this lightweight execution +metadata. This avoids changing `InspectRequirements` into a full-resource copy. + +Index resolved profile and backend configuration records by full ID once during +capture, reusing the already built indexed maps or references into the retained +result. Do not build full parallel configuration trees or query ConfigKit's +provenance during ordinary inspection. Prompt entries already retain captured +messages, templates, and hashes; use that capture and the selected prompt's +resolved values. Small presence metadata is appropriate where decoding has +already collapsed omission into a scalar default. + +Internal views may borrow immutable captured values. Detach mutable data at the +public projection boundary, using existing trusted copy helpers for accepted +provider maps. Do not revalidate provider values merely to copy them. This is +an ownership strategy, not a new public allocation or complexity guarantee. + +### Public Result Shapes + +Keep the existing method signatures for prompt/profile inspection. Add: + +```go +func (e *Engine) InspectBackend(ctx context.Context, backendID string) (*BackendInspection, error) +``` + +Declare the result types in `resource_inspection.go` at the module root. Move +the existing public `PromptInspection` and `ProfileInspection` declarations +there rather than leaving duplicate definitions. These are facade values, not +aliases of private types. Keep execution and extension type shapes unchanged. + +The tables below specify Go fields, types, and serialized keys. Apply both +`json` and `yaml` tags with the same key. Required fields have no `omitempty`; +all pointer fields use `omitempty` and nil means absent. A non-nil pointer to +zero, false, an empty string, or an empty collection remains present. + +| Result | Go fields and types | Serialized keys | +| --- | --- | --- | +| `ProfileInspection` | `ProfileID string` | `id` | +| | `Backend, Endpoint, Model *string` | `backend`, `endpoint`, `model` | +| | `Temperature, TopP *float64` | `temperature`, `top_p` | +| | `MaxTokens, TimeoutSeconds *int` | `max_tokens`, `timeout_seconds` | +| | `ServiceTier, ReasoningEffort *string` | `service_tier`, `reasoning_effort` | +| | `APIKeyEnv *string`, `APIKeyRequired *bool` | `api_key_env`, `api_key_required` | +| | `ExtraParams *map[string]any` | `extra_params` | +| `BackendInspection` | `BackendID string`, `Endpoint string` | `id`, `endpoint` | +| | `APIKeyEnv *string` | `api_key_env` | +| | `ConcurrencyLimit, QueueCapacity *int` | `concurrency_limit`, `queue_capacity` | +| | `ExtraParams *map[string]any` | `extra_params` | +| | `SmokeTests *BackendSmokeTestConfig` | `smoke_tests` | +| `PromptInspection` | `PromptID string`, `PromptHash string` | `id`, `prompt_hash` | +| | `DefaultProfileID, Description, SessionID *string` | `default_profile`, `description`, `session_id` | +| | `Inputs *[]PromptInputInspection` | `inputs` | +| | `Messages []PromptMessageInspection` | `messages` | +| | `OutputContract PromptOutputInspection` | `output` | + +Remove `ProfileInspection.EffectiveModelParams`; do not retain a compatibility +copy of backend-completed settings. `APIKeyRequired` becomes an optional +profile resource field. Retain the familiar prompt field names `Inputs`, +`DefaultProfileID`, and `OutputContract`, but deliberately change their types +where needed for presence. + +Nested prompt values are: + +| Type | Go fields and types | Serialized keys | +| --- | --- | --- | +| `PromptInputInspection` | `Name string`, `Required *bool`, `ContentType, Description *string` | `name`, `required`, `content_type`, `description` | +| `PromptMessageInspection` | `Role string`, `Content string`, `CacheControl *PromptCacheControlInspection` | `role`, `content`, `cache_control` | +| `PromptCacheControlInspection` | `Type CacheControlType`, `TTL *string` | `type`, `ttl` | +| `PromptOutputInspection` | `Format OutputFormat`, `ValidationMode ValidationMode`, `SchemaPath *string`, `RepairAttempts *int` | `format`, `validation_mode`, `schema_path`, `repair_attempts` | + +Required strings and enum values in these nested types are always encoded. +Imported and inline message bodies both use `content`; do not report a +`content_file` field or parsed template. Content is not rendered. A supplied +empty cache TTL stays present, unlike the existing execution cache-control +value's omission behavior. Keep `PromptInputDefinition`, `OutputContract`, and +execution `CacheControl` unchanged for their existing purposes. + +Reuse `BackendSmokeTestConfig`, `ReachabilityProbeConfig`, and +`AuthenticationProbeConfig` for backend diagnostic metadata: their pointer +fields already fit the selected semantics. Add JSON/YAML tags to their fields +(`default_profile`, `reachability`, `authentication`, `endpoint`, `kind`), all +with `omitempty`. Preserve a configured empty reachability object as `{}`; +do not fill an omitted endpoint or invent a diagnostics block. This does not +make `BackendConfig` itself a serialization contract. + +The supported generic encoding paths are `encoding/json` and the existing +`go.yaml.in/yaml/v4` dependency. Ordinary `Marshal`/`Encoder` calls must suffice. +Pointer-to-collection fields avoid needing public presence flags or custom +serializers to distinguish omitted collections from explicit `{}`/`[]`. Do not +add deserialization, source round-trip, output-order, or numeric precision +guarantees. Inspect values rather than inferring source syntax from zero values. + +### Presence And Null Interpretation + +Use resolved typed pointers and nil-versus-empty collections where they retain +presence. Capture only additional information needed for scalar fields such as +input `required` and output `repair_attempts` before they become execution +defaults. Inherited values count as present. For nullable resource fields, +resolved null and omission both produce nil in resource reports. Literal nulls +inside provider maps/arrays remain untouched. + +Keep existing normalization and derived defaults recorded during the ConfigKit +resolution callback. In particular, positive backend concurrency with no queue +setting yields the already recorded queue default in inspection. Do not invent +an explicit zero concurrency value when the resolved field is absent, or add +the framework profile timeout merely because execution uses it. + +Simplify `captureExecutionProfile` to use non-nil configured values rather than +profile-specific absent/null state. Endpoint, credential source, and whole-map +null now permit backend fallback. When `api_key_required` is true and the +profile's `APIKeyEnv` pointer is nil, suppress the backend credential source +just as for omission. An explicit empty endpoint or API-key source still clears +that value. A non-nil provider map still overlays backend values, including +an explicitly empty map that does not clear defaults. Nested provider nulls +remain literal data. + +Remove the profile-only `state.profiles` presence map, `profileFields`, and +capture helpers made unused by this change. Retain helpers needed by other +metadata or validation; do not purge presence/null handling generically. +Preserve execution `ExecutionTargetPresence`, because provider control omission +and explicit zero still matter at dispatch. Do not change required-field or +non-nullable-field validation. ConfigKit's retained result and provenance are +not rewritten to erase nulls. + +### Typed Prompt Source Shapes + +Add `BackendConfig.Extends *string` and encode it exactly like the profile helper. +Add a root `prompts.go` containing these source-input types and helper: + +```go +type PromptConfig struct { + ID string + Extends, DefaultProfile, Description, SessionID *string + Inputs []PromptInputConfig + Messages []PromptMessageConfig + Output *PromptOutputConfig +} + +type PromptInputConfig struct { + Name string + Required *bool + ContentType, Description *string +} + +type PromptMessageConfig struct { + Role, Content, ContentFile *string + CacheControl *PromptCacheControlConfig +} + +type PromptCacheControlConfig struct { + Type, TTL *string +} + +type PromptOutputConfig struct { + Format, ValidationMode, SchemaPath *string + RepairAttempts *int +} + +func PromptSource(label string, prompts []PromptConfig) configkit.Source +``` + +These types are mapping-constructor inputs, not serialized result types. Match +`BackendSource`/`ProfileSource`: always write IDs/names, dereference supplied +pointers, omit nil optional fields, preserve non-nil empty slices/objects, and +return `configkit.Mapping(label, map[string]any{"prompts": records})`. Encode +`Extends` as `extends: {id: value}`. A nil top-level prompt slice supplies an +empty `prompts` sequence, matching the other source helpers. + +Do not require a complete source record in the helper: higher layers or sibling +inheritance may complete it. Engine loading owns final validation, including +invalid content/content-file combinations. Raw mappings retain explicit-null +and generic ConfigKit operations. Do not add a Promptkit-specific content root, +filesystem adapter, recursive input converter, or inheritance resolver. + +## Stage 1: Declare The Resource Result Contract + +**Scope:** Public inspection values and their nested representation only. + +1. Read `types.go`, `backends.go`, and the current inspection GoDoc in `engine.go`. + Create the public result types and tags specified above. Move only the two + existing inspection declarations; leave execution types alone. +2. Add tags to the reused backend diagnostic types. Document optional pointer + and collection semantics, caller ownership, captured content, references, + credential metadata, and the resource/execution distinction. +3. Remove outdated claims that these inspection results have no serialization + contract. Do not remove those claims from unrelated types. + +**Check:** Review every field against the tables, particularly pointer maps, +input `required`, cache TTL, and output `repair_attempts`. Compilation of old +converters and callers may wait for later stages; do not add transitional fields. + +## Stage 2: Simplify Execution's Post-Handoff Null Semantics + +**Scope:** Profile capture and its targeted configuration tests. + +1. In `internal/configuration/targets.go`, implement the pointer-based behavior + above. Continue applying backend defaults once, then the explicit profile + values, then ordinary request-time overrides through the existing path. +2. In `load.go`, remove only the now-unused profile tri-state capture machinery. + Preserve final effective validation and prompt metadata capture. +3. Update `targets_test.go` and relevant `load_test.go`/`interpretation_test.go` + cases. Compare null and omission for endpoint, API-key source, and whole + provider map; retain explicit-empty-string clearing, empty-map overlay, + nested provider nulls, and `api_key_required` behavior with both absent/null + and explicit profile sources. +4. Include real ConfigKit inheritance where a child's null displaces a parent's + endpoint/provider map: the inspected resource is unset and execution uses + the selected backend, not the displaced parent. Preserve the null in the + retained configuration inspection. Inspection assertions may be completed + after resource wiring exists. + +**Check:** Run the focused adapter tests when buildable. Retain outbound-control +presence and timeout behavior; removing configuration null distinctions must +not collapse runtime explicit zero or broaden accepted configuration shapes. + +## Stage 3: Project Resolved Backend And Profile Resources + +**Scope:** Configuration-owned views and exact-ID resource lookup. + +1. Add private-adapter result structs in `internal/configuration`, with fields + corresponding to the public profile/backend tables. Keep ConfigKit record + types and paths inside the adapter, and do not alias public root types. +2. Reuse the indexed resolved records built during `buildExecutionProfiles` + instead of discarding and recomputing those indexes for each inspection. + Values may reference the immutable retained config; avoid additional deep + retained copies of provider maps. Keep the execution registry/targets for + their current execution and smoke responsibilities. +3. Add adapter `InspectProfile(ctx, id)` and `InspectBackend(ctx, id)` lookups. + Build selected-resource views from the normalized resolved records, never + from `ExecutionProfile.ResolvedTarget` or the capacity manager. Use existing + internal not-found sentinels for absent IDs and preserve cancellation. +4. Include backend diagnostics only where configured after composition. Return + configured endpoint overrides, including inherited ones, and no derived URLs. + A missing diagnostic default profile does not prevent backend inspection. +5. Add focused adapter coverage using real ConfigKit loading: an inherited + partial profile, explicit zero/empty settings, backend defaults excluded + from that profile, and backend queue derivation and diagnostic metadata. + +**Check:** Verify resource fields against the retained resolved config and +execution fields separately against the backend-completed target. Do not turn +backend/profile references into nested reports or require execution readiness. + +## Stage 4: Capture Complete Prompt Resource Information + +**Scope:** Prompt presence and resource projection, without changing execution +or requirement-discovery representations. + +1. Extend the existing prompt metadata capture just enough to retain omission + versus explicit false for each input's `required`, and omission versus + explicit zero for `output.repair_attempts`. Use ConfigKit's effective entry + information during the existing callback, including inherited presence. + Keep non-nullable-field rejection intact; do not switch those scalars to + nullable fields as a shortcut. +2. Retain or reference the selected resolved prompt record for optional strings, + inputs-list presence, schema-path presence, and per-message cache TTL + presence. Do not create another copy of the whole configuration tree. +3. Add adapter `InspectPrompt(ctx, id)` returning its resource view. Use + captured `promptEntry.definition` message text/order and existing hash, plus + the resolved resource's presence. Do not reopen message files, render + templates, or load the referenced schema/default profile. +4. Leave `GetPromptInspection` and `domain.PromptInspection` lightweight for + `InspectRequirements`; keep requirement metadata, compiled templates, and + opaque definition hashing behavior independent of the expanded resource DTO. +5. Extend prompt adapter tests for inherited/imported captured content, + optional metadata, empty inline content, cache TTL absence versus empty, + and input/output scalar presence. Reuse existing content-origin fixtures. + +**Check:** Inspect a prompt with an unresolved template variable and an absent +default profile/schema file successfully. Schema and template syntax validation +at construction remain as before. A later content-file change does not alter +the resource report or trigger a second read. + +## Stage 5: Wire Resource Inspection Through The Engine And Facade + +**Scope:** Selection, public conversion, backend entry point, and errors. + +1. Add the three-method resource-inspection interface and captured collaborator + to `internal/engine.Engine`; initialize it from the configuration snapshot + and share it naturally through `WithNamespaces`. +2. Route internal prompt/profile inspection through this collaborator instead + of the runner, and add backend inspection. Reuse `qualifyResourceID` with + each kind's namespace. Do not qualify references stored inside definitions. +3. Replace root inspection conversion with explicit projections of the new + configuration views. Copy pointer scalars and mutable maps/slices/nested + diagnostics into caller-owned values; reuse immutable strings. Use trusted + detachment for accepted nested provider values, not a serialization round + trip or a new JSON compatibility conversion. +4. Add public `ErrBackendNotFound` and `Engine.InspectBackend`. Scope the mapping + of the registry's internal not-found sentinel to this new operation; do not + globally reclassify construction, smoke, or generation errors. Follow the + existing nil/uninitialized-engine guards and invalid-ID conventions. + Preserve cancellation causes without inventing a public backend-load category. +5. Update exact method/type GoDoc, including `Engine`'s concurrent-operation + list. All three calls return no partial result on error and expose neither + credential values nor runtime occupancy. + +**Check:** A small assembled public-API test for each method builds. Missing +backend matches `ErrBackendNotFound` and not `ErrInvalidRequest`; malformed IDs +match `ErrInvalidRequest`, invalid engines match `ErrInvalidConfig`, and +cancellation remains detectable through `errors.Is`. + +## Stage 6: Retire Superseded Inspection Paths And Migrate Existing Tests + +**Scope:** Existing consumers and test ownership, without losing execution or +requirement coverage. + +1. Remove the unused runner `InspectPrompt`/`InspectProfile` wrappers and their + wrapper-only tests. Preserve `resolvePromptInspection` for requirement + selection and profile identity/execution helpers used elsewhere. +2. Update root inspection, inheritance, namespace, bundled-configuration, and + source tests for the selected result shape. Preserve literal identity text + and exact stored-reference behavior. Dereference pointers only after + checking presence; an unset value is not a zero-valued setting. +3. Where an old `InspectProfile.EffectiveModelParams` assertion tested backend + completion or framework timeout, keep that protection on `Prepare`/execution + or the focused adapter target tests. Do not simply delete the assertion or + reproduce completed settings in the new inspection result. +4. Keep `InspectRequirements` tests using the narrow metadata/snapshot seam. + Retain protection against full definition/target lookups and source access; + do not replace that seam with the expanded resource report. +5. Migrate any in-repository examples or helper fixtures that actually consume + the changed inspection fields. Leave run/prepared-result, output validation, + appended-message, and extension-client contracts unchanged. + +**Check:** Run the affected public, configuration, use-case, and example tests +when their dependency graph is coherent. Search for stale references to +`ProfileInspection.EffectiveModelParams` and old inspection scalar assumptions; +do not replace valid execution-result fields with the same name. + +## Stage 7: Verify Generic JSON And YAML Rendering + +**Scope:** One focused public serialization contract suite for resource results. + +1. Inspect real configured resources, then encode the returned values directly + using `encoding/json` and `go.yaml.in/yaml/v4`. Consumers in the test must not + build substitute reports, register nested serializers, or switch on fields. + Use the existing YAML version; update `go.mod`/`go.sum` only as needed to + reflect its direct test import, without upgrading dependencies. +2. Decode both outputs into ordinary structures for semantic assertions. Assert + selected names/nesting and presence, not whitespace, key order, or a golden + byte snapshot. Use a small set of rich fixtures rather than one fixture per + field or duplicating configuration validation cases. +3. Cover absent versus explicit zero/false/empty strings, absent/null versus + empty collections, and provider-data nulls. Include profile provider maps, + prompt `inputs`, input `required`, output `repair_attempts`, empty message + content/cache TTL, and backend capacity/diagnostic fields. +4. Assert no `extends`, execution-completed profile fields, parsed templates, + or synthetic diagnostics/endpoints appear. A configured empty reachability + object remains present, and a recorded queue default is present even when + it was not originally written by the operator. + +**Check:** The same semantic cases pass with both ordinary encoders. If tags +alone fail to preserve a selected case, correct the result representation or +add narrowly scoped encoding support; do not move adaptation into consumers. + +## Stage 8: Verify Selection, Isolation, And Offline Boundaries + +**Scope:** Public behavior risks not already covered by the migrated suite. + +1. Extend existing namespace tests for backend inspection: scoped slashless ID, + qualified bypass, no fallback to another namespace, and full selected ID. + Include a bundled backend through the same API. Reuse existing profile/prompt + namespace coverage rather than duplicate every selection case three times. +2. Exercise independence: missing diagnostic default profiles do not prevent + backend reports; partial profiles do not require endpoints/models; prompt + reports do not resolve their default profile or schema reference. +3. Mutate representative returned pointer fields, nested diagnostics, provider + maps/arrays, and prompt input/message/cache values. Reinspection and later + preparation must retain the captured values. Include separate concurrent + inspections using caller-owned results under the race detector, reusing + existing ownership helpers where suitable. +4. Use offline boundary doubles or counting files only where needed to prove + that inspection does not render, read credentials/artifacts/schemas, or call + a provider. Preserve existing source-lifetime tests and avoid mocks of every + private call. No live diagnostic or inference requests belong in this suite. +5. Complete the resource-inspection assertions paired with Stage 2's null + inheritance case and verify that `InspectConfiguration` still shows the + retained null and provenance, separately from execution's backend fallback. + +**Check:** Each test protects a distinct public risk; consolidate overlapping +new and old cases. Run focused tests and their race-enabled versions when useful. +Do not introduce benchmark thresholds or additional release gates. + +## Stage 9: Add Typed Backend Inheritance And Prompt Sources + +**Scope:** Public mapping-constructor implementation and GoDoc. + +1. Add `Extends *string` to `BackendConfig` and encode it in `BackendSource` + using the existing profile helper pattern. Update its GoDoc accordingly. +2. Implement the source-input types and `PromptSource` specified above. Write + small explicit mapping construction for nested input, message, cache, and + output values. Preserve supplied order and nil-versus-empty collections. +3. Pass supported mapping values directly to ConfigKit so its snapshot behavior + applies. Preserve the other helpers' final-load validation and accepted-input + contracts. Do not copy through JSON/YAML or add reflection-based encoding. +4. Document nil/explicit values, sibling inheritance, deferred validation, + imported file context, and raw mapping escape hatches. Do not give these + source-input types the inspection result's serialization contract. + +**Check:** Compare each mapping field with the format reference and the source +shape table. Incomplete layered records remain expressible, and constructing +the helper itself neither accesses files nor resolves inheritance. + +## Stage 10: Verify Typed Sources Through Real Composition + +**Scope:** Focused source-helper contract tests, not a second ConfigKit suite. + +1. Extend existing backend-source tests with a real inherited child, preserving + the child's ID and endpoint/capacity overrides through `InspectBackend`. +2. Add prompt-source tests using real `NewEngine` composition. Exercise nested + input/message/output settings, sibling inheritance, source/layer completion, + explicit false/zero/empty values, nil versus empty lists, and message order. + Reuse the new resource APIs to observe resolved values and preparation where + execution behavior is the fact being tested. +3. Mutate original nested source slices, scalar pointees, and records after + creating the source. Loading should use ConfigKit's captured source values. + Keep this representative rather than reimplementing upstream snapshot tests. +4. Include a relative `content_file` from a typed source with ConfigKit's + ordinary explicit source context. Use the dependency's existing context + input setting: construct `filesystem := configkit.NewFilesystem("fixture", fsys)` + and set `configkit.Input.Filesystem` to + `&configkit.FilesystemContext{FS: &filesystem, Root: ".", BaseDir: "templates"}`. + Include an inherited relative message path. Confirm capture uses that context + without adding a new Promptkit path-setting API. +5. Confirm malformed final definitions fail at loading, not helper construction; + rely on existing generic null, inheritance-cycle, and schema validation + coverage instead of repeating every rejection for every typed helper. + +**Check:** Run focused source/inspection tests. Existing `ProfileSource` and raw +mapping workflows remain usable; this stage is not a ConfigKit upgrade or an +authorization to edit another repository. + +## Stage 11: Update Canonical Guidance And Migration Notes + +**Scope:** Documentation of the implemented APIs and intentional changes. + +1. Update `docs/consumers/pkg-promptkit.md` with the three resource views, + nullable pointer/collection usage, and minimal direct JSON/YAML rendering. + Distinguish them from `InspectConfiguration` provenance, requirement + discovery, `ValidateRequest`, and concrete-request preparation/details. +2. Document migration from `EffectiveModelParams` to the profile's resource + fields and from prompt scalar metadata to optional inspection values. + Consumers needing completed request settings use existing preparation APIs; + do not add a compatibility execution view to inspection. +3. Update `docs/formats.md`'s post-handoff profile table and map explanation. + Show a concrete null migration: a profile with null endpoint/API-key source/ + provider map now permits backend defaults; explicit empty strings still clear + endpoint/key source, and backend provider maps can be edited through ordinary + composition. Do not imply a new whole-map suppression replacement exists. +4. Document typed prompt sources and backend inheritance through the source + helpers' GoDoc and consumer guidance. Keep exact field contracts in GoDoc + and the existing format owner rather than parallel exhaustive prose schemas. +5. Reconcile `docs/internal/sources.md`, `docs/internal/overview.md`, and affected + runner guidance with configuration-owned resource inspection, retained narrow + requirement metadata, and simplified execution capture. Adjust architecture + descriptions only where implemented structure changed; preserve policy and + the accepted configuration boundary ADR. +6. Prepare the next minor release note under the existing release procedure. + At this baseline `v0.19.0` is published, so use `docs/releases/v0.20.0.md` + unless another version has been published during the sprint. Explain the + inspection and configuration compatibility changes, link canonical guidance, + and include the required licensing footer. Update the README release link. + Do not edit published release notes, tag, push, or run publication commands. +7. Supply enough migration detail for CommandKit to adopt generic reporting + without per-field adapters. Changes or publication in CommandKit itself are + consumer follow-up, not prerequisites or work authorized by this sprint. + +**Check:** Validate changed local links and terminology. Remove old claims that +profile inspection is backend-completed, resource results have no JSON contract, +or null suppresses profile backend fallbacks. Leave unrelated execution and +ConfigKit composition contracts intact. + +## Stage 12: Validate And Close The Sprint + +**Scope:** Combined verification and final cleanup of this feature only. + +1. Confirm that all three inspection operations, every selected result field, + both generic encoders, helper inheritance, and post-handoff null migration + are implemented and covered at the appropriate owning boundary. Resolve any + checks deferred by intermediate compilation failures. +2. Check that resource lookup uses captured configuration without execution + completion or a second ConfigKit interpretation; requirement discovery still + uses its narrow metadata path. Remove obsolete converters/wrappers and + private fixtures that preserve the old report behavior, without sweeping + cleanup outside this feature. +3. Format changed Go files and tidy the module only where imports changed. + Using the newest locally available Go installation under the development + guide, run the complete offline suite and vet: + + ```sh + go test -race ./... + go vet ./... + git diff --check + ``` + + Select that toolchain on `PATH`, with `GOTOOLCHAIN=local` and `GOWORK=off`. + The complete suite includes maintained example tests; do not impose another + standalone build/example/release-validation gate. No dependency or consumer + minimum upgrade is selected just to implement this feature. +4. Inspect all changes for unintended behavior and contracts. In particular, + preserve ConfigKit source ownership, literal provider nulls, existing request + overrides, output repair, provider-value support, credential handling, and + captured-state isolation. Do not add context limits, schema probes, health + promises, CLI policy, or source-round-trip guarantees. +5. Verify changed documentation links and review status/diffs under the agent + commit policy. Mark stages complete with actual validation evidence, commit + the finished unit, and report any remaining limitations accurately. Keep the + completed feature roadmap and this plan for the requested implementation + review; retirement can occur during later release preparation. + +Completion requires the full selected end state, including generic rendering +and both deliberate compatibility changes. Passing only the new backend method +or preserving the old execution-oriented profile report is not completion. diff --git a/docs/roadmap/inspect-backend.md b/docs/roadmap/inspect-backend.md index c57bb48..d08eb64 100644 --- a/docs/roadmap/inspect-backend.md +++ b/docs/roadmap/inspect-backend.md @@ -459,69 +459,30 @@ proposal to expose both declared and computed destinations is removed. This avoids an additional representation and provider-specific derivation machinery in resource inspection. -## Implementation And Verification +## Acceptance Criteria -1. Define typed results, serialization names/nesting, and consumer migration - selected in decision 4. Account for presence across prompt, profile, and - backend results. Source-input helpers, inspection results, and execution - values have distinct purposes; reuse types only where their semantics fit. -2. Implement and verify the post-handoff null change as a focused unit, separate - from inspection projection. Remove presence machinery made unnecessary by - that change while retaining omission versus explicit-value information. - Verify the changed execution behavior and document its migration example. -3. Expose expanded prompt content and resolved profile fields through existing - capture/lookup paths, before execution completion, without another composition - pass or changes to ConfigKit's retained result. Support generic encoding with - the selected omission rules and preserve explicit values. -4. Add backend inspection and the accepted public missing-backend error, - returning configured diagnostic metadata without endpoint derivation. -5. Add typed backend inheritance and the prompt source/helper types, delegating - both to the ordinary ConfigKit mapping and loading path. -6. Update GoDoc, formats, consumer/internal guidance, and release notes for the - selected behavior, inspection-result migrations, and null compatibility - change. Coordinate CommandKit's generic reporting adoption. +The companion [implementation plan](implementation.md) owns the staged work +and verification sequence. The target is complete when: -Use focused offline tests for actual boundary risks: +- Prompt, profile, and backend inspection expose the selected resolved resource + with the boundary and presence semantics above, using ordinary JSON/YAML + encoding without per-field consumer adapters. +- Inherited values, explicit zero/false/empty settings, and provider-data nulls + are represented accurately; nullable resource nulls and omission are absent. +- Profile inspection excludes backend-completed execution values, and backend + inspection reports configured diagnostics without synthesizing destinations + or requiring diagnostic readiness. +- Prompt inspection includes captured inline/imported message content and + metadata without rendering or loading related resources. +- Execution applies the selected post-handoff null behavior while preserving + explicit clearing, map overlay, and ConfigKit's retained result and provenance. +- Selection, errors, captured-state isolation, and credential handling follow + the selected contracts. Requirement discovery retains its lightweight path. +- All three resource kinds have typed source helpers, including inheritance, + using ordinary ConfigKit composition, context, and snapshot behavior. +- Canonical guidance and the next minor release note explain changed Go + inspection types, generic rendering, source helpers, and null migration. -- Directly encode each inspection result with ordinary JSON and YAML encoders, - without consumer-specific report structures. Verify semantic field names, - nesting, omitted settings, explicit zero/false/empty values, and nested - provider data. Include prompt input/output and backend capacity presence, - rather than testing only profile fields. Assert semantic output, not incidental - whitespace or mapping-key order. -- Child resources show the resolved inherited fields and overrides, not an - unresolved `extends` directive; explicit zero survives. Omitted/null nullable - settings use the same absent representation; provider-data nulls retain their - literal meaning. -- Null and omitted profile endpoint, credential-source, and provider-map fields - permit the same backend fallback. Explicit empty-string clearing and empty-map - overlay behavior remain intact. Include a ConfigKit inheritance case where - null clears a parent value before Promptkit applies backend defaults, and - verify that resource inspection does not rewrite the retained ConfigKit tree. -- 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. -- Prompt inspection exposes captured inline/imported content, metadata, and - order without rendering or adding related-resource lookup dependencies. -- Backend inspection reports configured/inherited diagnostic overrides while - leaving omitted overrides absent. It does not require diagnostic readiness. -- Resource selection, error classification, and mutable-result ownership follow - the selected contract; reuse existing namespace and ownership coverage. -- Typed backend and prompt inheritance work through real ConfigKit composition. - Prompt sources preserve nested message/input/output settings, omission and - explicit values, ordering, and source snapshot behavior. Include a representative - relative content-file case using ordinary source context. Reuse generic loading, - validation, and inheritance coverage rather than duplicating it for each helper. - -Promptkit owns the inspection serialization checks; CommandKit owns presentation -and delivery tests for the migrated resource view. Follow the -[testing policy](../policy/testing.md), combine cases where useful, and reuse -existing coverage. No new benchmark threshold or release gate is selected. - -Completion means operators can inspect the resolved selected prompt, profile, -or backend accurately through generic rendering, without per-field consumer -adapters, assembling execution settings, or navigating raw configuration paths. -All three resource kinds have typed source helpers, including inheritance -support, and consumers have migration guidance for changed inspection results -and post-handoff null semantics. -No engine-policy or prepared-request additions are part of completion. +Promptkit owns resource serialization checks; CommandKit owns presentation and +delivery. No engine-policy or prepared-request additions, benchmark threshold, +or new release gate is part of this feature.