diff --git a/docs/roadmap/resources.md b/docs/roadmap/audit/05-resources.md similarity index 90% rename from docs/roadmap/resources.md rename to docs/roadmap/audit/05-resources.md index eb5cc71..0abe625 100644 --- a/docs/roadmap/resources.md +++ b/docs/roadmap/audit/05-resources.md @@ -30,9 +30,9 @@ existing protected behavior; they do not cover all findings below. **Priority:** P2. Unbounded remote-response consumption; a finite limit would be a new policy decision, not enforcement of an existing documented byte limit. -**Code:** [runOpenRouterKey](../../internal/usecase/smoke_authentication.go:66), -[recognizedOpenRouterKeyResponse](../../internal/usecase/smoke_authentication.go:139), -and [diagnostic HTTP execution](../../internal/llm/http_evidence.go:129). +**Code:** [runOpenRouterKey](../../../internal/usecase/smoke_authentication.go:66), +[recognizedOpenRouterKeyResponse](../../../internal/usecase/smoke_authentication.go:139), +and [diagnostic HTTP execution](../../../internal/llm/http_evidence.go:129). **Circumstances:** An authentication endpoint returns HTTP 200 with a large or continuously growing body. Recognition calls unrestricted `io.ReadAll` and then @@ -63,10 +63,10 @@ artifacts, or generated output. **Priority:** P2. Potentially exponential allocation before upstream resource checks can run. -**Code:** [providerMapForMapping](../../provider_values.go:19), -[providerValueForMapping](../../provider_values.go:31), -[ProfileSource](../../profiles.go:33), and -[BackendSource](../../backends.go:100). +**Code:** [providerMapForMapping](../../../provider_values.go:19), +[providerValueForMapping](../../../provider_values.go:31), +[ProfileSource](../../../profiles.go:33), and +[BackendSource](../../../backends.go:100). **Circumstances:** A caller builds a small acyclic Go value graph containing repeated map/slice references. Each level can point twice to the same child: @@ -107,10 +107,10 @@ configuration limits to fix this pre-handoff allocation problem. **Priority:** P3. Avoidable retained-memory dependency after use/discard. -**Code:** [PreparedExecution.owner](../../internal/usecase/prepared_execution.go:24), -[Discard](../../internal/usecase/prepared_execution.go:96), -[claim](../../internal/usecase/prepared_execution.go:172), and -[payload clearing](../../internal/usecase/prepared_execution.go:188). +**Code:** [PreparedExecution.owner](../../../internal/usecase/prepared_execution.go:24), +[Discard](../../../internal/usecase/prepared_execution.go:96), +[claim](../../../internal/usecase/prepared_execution.go:172), and +[payload clearing](../../../internal/usecase/prepared_execution.go:188). **Circumstances:** A consumer retains a completed or discarded handle for its supported `Details` access, while replacing or dropping the originating engine. @@ -141,7 +141,7 @@ collaborators is implied. **Priority:** P3. Avoidable memory amplification on validation failures. -**Code:** [formatRepairDiagnostics](../../internal/usecase/repairer.go:119). +**Code:** [formatRepairDiagnostics](../../../internal/usecase/repairer.go:119). **Circumstances:** A failed schema validation produces a large diagnostic or many diagnostics and repair is enabled. The formatter normalizes every string, marshals @@ -170,9 +170,9 @@ implementation opportunity, not a claim that the existing contract promises a **Priority:** P3. Avoidable backing-buffer retention in retained metadata. -**Code:** [NormalizeSessionID](../../internal/domain/session.go:10), -[preparation](../../internal/usecase/runner.go:312), and -[prepared metadata construction](../../internal/usecase/runner.go:491). +**Code:** [NormalizeSessionID](../../../internal/domain/session.go:10), +[preparation](../../../internal/usecase/runner.go:312), and +[prepared metadata construction](../../../internal/usecase/runner.go:491). **Circumstances:** A direct or rendered session ID contains substantial leading or trailing whitespace around a short valid identifier. `strings.TrimSpace` @@ -212,4 +212,4 @@ transports/filesystems/clients remain subject to their ownership contracts; this audit proposes no blanket shutdown or disposal API. Previously recorded repeated-copying issues remain in -[the efficiency audit](audit/02-efficiency.md); they are not duplicated here. +[the efficiency audit](02-efficiency.md); they are not duplicated here. diff --git a/docs/roadmap/error-handling.md b/docs/roadmap/audit/06-error-handling.md similarity index 92% rename from docs/roadmap/error-handling.md rename to docs/roadmap/audit/06-error-handling.md index 8b6d2c4..7b6481f 100644 --- a/docs/roadmap/error-handling.md +++ b/docs/roadmap/audit/06-error-handling.md @@ -44,9 +44,9 @@ not repeated here. **Priority:** P2. Confirmed public error-classification defect. -**Code:** [publicErrorFor](../../errors.go:63), -[mapPublicError](../../errors.go:16), and -[wrapGenerationError](../../internal/usecase/runner.go:271). +**Code:** [publicErrorFor](../../../errors.go:63), +[mapPublicError](../../../errors.go:16), and +[wrapGenerationError](../../../internal/usecase/runner.go:271). **Failure condition:** An injected `LLMClient` or `ArtifactReader` returns an error obtained from another PromptKit operation. Ordinary mapped errors retain @@ -56,7 +56,7 @@ regardless of which operation the outer runner classified. **Expected:** A model-client failure matches `ErrLLMGenerate`; an artifact-reader failure matches `ErrArtifactLoad`. The injected cause remains available through -`errors.Is`, as their [public GoDoc](../../engine.go:49) specifies. Preserving +`errors.Is`, as their [public GoDoc](../../../engine.go:49) specifies. Preserving the nested cause may also preserve its public categories; it must not replace the category for the operation that just failed. @@ -89,7 +89,7 @@ and context identities. **Priority:** P2. Confirmed loss of failure provenance and cause. -**Code:** [decodeOpenAIChatResponse](../../internal/llm/openai_compatible_client.go:373). +**Code:** [decodeOpenAIChatResponse](../../../internal/llm/openai_compatible_client.go:373). **Failure condition:** A 2xx response body returns a non-EOF I/O error other than `context.Canceled` or `context.DeadlineExceeded`, either during the first decode @@ -99,7 +99,7 @@ while reading the response stream after headers were received. **Expected:** Distinguish an underlying read/transport failure from evidence of invalid JSON or trailing data. Retain the read cause through a redacting error so callers can inspect it with `errors.Is`/`errors.As`, consistent with the -[transport category](../../engine.go:65). Do not report trailing data when the +[transport category](../../../engine.go:65). Do not report trailing data when the reader failed without supplying any. This does not change the established classification of invalid/truncated JSON or introduce transport retries. @@ -114,7 +114,7 @@ rather than a transport failure. Thus the issue affects both public execution errors and factual diagnostic classification. The integration contract explicitly guarantees exact causes for -[`http.Client.Do` failures](../integrations/openai-compatible-chat.md#response-handling), +[`http.Client.Do` failures](../../integrations/openai-compatible-chat.md#response-handling), not every decoder error. The finding concerns the separate loss and misclassification of an actual body-read failure, rather than asserting a new requirement to expose JSON parser errors or provider content. @@ -133,9 +133,9 @@ private transport details. **Priority:** P2. Confirmed mismatch with the diagnostic error contract. -**Code:** [runInference](../../internal/usecase/smoke_tester.go:207), -[generation preparation](../../internal/generation/coordinator.go:96), and -[request payload validation](../../internal/llm/openai_compatible_client.go:511). +**Code:** [runInference](../../../internal/usecase/smoke_tester.go:207), +[generation preparation](../../../internal/generation/coordinator.go:96), and +[request payload validation](../../../internal/llm/openai_compatible_client.go:511). **Failure condition:** An inference diagnostic's effective settings are invalid in a way detected by built-in request construction rather than target selection. @@ -144,7 +144,7 @@ is one public example. The coordinator returns `llm.ErrInvalidRequest` before dispatch with no attempt evidence. `runInference` treats every generation error as a concluded diagnostic failure. -**Expected:** The [SmokeTest contract](../../smoke_diagnostics.go:238) says invalid +**Expected:** The [SmokeTest contract](../../../smoke_diagnostics.go:238) says invalid kinds, settings, and selections return an ordinary Go error before diagnostic work. A locally invalid request should follow that path and expose the public invalid-request category. This is distinct from a provider rejecting a validly diff --git a/docs/roadmap/audit/catalog.md b/docs/roadmap/audit/catalog.md new file mode 100644 index 0000000..6201140 --- /dev/null +++ b/docs/roadmap/audit/catalog.md @@ -0,0 +1,570 @@ +# Consolidated Pre-1.0 Audit Catalog + +Consolidated on 2026-11-04 from the 11 audit documents in this directory. +Their 41 numbered findings are represented by 34 entries below. Entries that +describe the same underlying issue share one remediation scope; missing +regression coverage for an identified defect is included with that defect. +Some broad testing findings consequently support more than one entry. + +The order reflects consequence, exposure, and the value of clarifying public +contracts before v1.0. Confirmed defects and conditional security exposure come +first, followed by contract/test gaps, resource efficiency, and maintainability. +This ordering does not upgrade the original severities or turn every cleanup +into a release gate. The source audits retain their evidence, qualifications, +and validation results. None of these entries is marked remediated by this +documentation-only consolidation. + +## 1. Update The Audited Maintainer Toolchain For Applicable Security Fixes + +**Conditional security exposure.** The audited Go 1.27.0 toolchain predates +networking fixes applicable to HTTP clients, including HTTP/2 CPU exhaustion +and conditional certificate-trust exposure. Use a patched maintainer toolchain +and repeat the focused security assessment against it. Actual downstream +exposure depends on the toolchain that builds the consumer and its transport +and trust configuration; raising PromptKit's minimum Go requirement is a +separate compatibility decision, not an implied remedy. + +Sources: [Security 1](07-security.md#1-the-audited-go-toolchain-predates-applicable-networking-security-fixes). + +## 2. Bound Authentication-Probe Response Consumption + +**Confirmed resource/security defect.** Authentication diagnostics read a +successful upstream body with unbounded `io.ReadAll`. A deadline does not bound +the bytes a fast server can supply. Introduce finite response consumption and +clean closure, with an explicit choice of byte budget and overflow reporting. +Overflow should not be interpreted as proof of rejected authentication. +Relocating the provider adapter in entry 26 would not itself fix this defect. + +Sources: [Resources 1](05-resources.md#1-authentication-diagnostics-read-an-unbounded-upstream-body), +[Security 2](07-security.md#2-authentication-probes-permit-unbounded-remote-body-memory-consumption). + +## 3. Avoid Exponential Expansion During Convenience Source Conversion + +**Confirmed resource defect.** `ProfileSource` and `BackendSource` conversion +expand repeated references before ConfigKit performs its bounded snapshot. +A small shared acyclic graph can therefore cause exponential work and +allocation. Preserve shared references during conversion, with suitable cycle +and slice-view handling, rather than duplicating ConfigKit's validation or +introducing PromptKit-side raw-source limits. Add focused shared-graph and +deferred-failure regressions for both convenience helpers. + +Sources: [Resources 2](05-resources.md#2-convenience-source-conversion-expands-shared-graphs-before-bounded-loading), +[Testing 3](08-testing.md#3-programmatic-provider-value-conversion-lacks-representative-value-cases). + +## 4. Resolve The ArtifactReader Buffer-Ownership Contract + +**Confirmed race under the documented collaborator contract.** The public +reader contract permits buffer reuse after `Read` returns, before PromptKit +can finish copying it. Concurrent preparation with a compliant custom reader +can race. Clarify ownership/lifetime per invocation and align adapters, GoDoc, +and concurrency tests. This needs a deliberate public-contract decision before +v1.0: an immediate copy alone cannot guarantee safety if the reader is allowed +to mutate the buffer immediately. No default-reader defect was established. + +Sources: [Interfaces 1](09-interfaces.md#1-artifactreader-permits-buffer-reuse-before-promptkit-can-copy-it). + +## 5. Preserve Exact Numbers In Programmatic Provider Sources + +**Confirmed data-integrity defect.** Convenience source conversion falls back +from integer parsing to `float64` without checking precision, silently changing +some accepted `json.Number` values. Preserve an exact ConfigKit-compatible +representation, or defer an unsupported-value error to ConfigKit instead of +rounding or converting the number into a string. Regression coverage should +include exact-number boundaries, nested typed collections, mutation isolation, +and deferred unsupported/cyclic-value errors for both source helpers. + +Sources: [Correctness 1](01-correctness.md#1-provider-source-helpers-silently-change-exact-json-numbers), +[Testing 3](08-testing.md#3-programmatic-provider-value-conversion-lacks-representative-value-cases). + +## 6. Make Provider-Native Schema Constraints Self-Contained + +**Confirmed implementation gap; packaging policy needs selection.** Local +validation freezes referenced schema resources, but the provider receives only +the root document and cannot resolve its local external references. Select +correct resource packaging, or an explicit local-only fallback policy, without +naively inlining recursive schemas or silently dropping native constraints. +Add a wire-level regression demonstrating a usable provider constraint, not +merely successful local compilation. Entry 21 is a separate compilation +refactor and does not solve this packaging problem. + +Sources: [Correctness 2](01-correctness.md#2-external-schema-resources-do-not-reach-the-provider-constraint), +[Testing 5](08-testing.md#5-multi-resource-schema-tests-do-not-establish-a-usable-provider-constraint). + +## 7. Preserve The Owning Operation's Public Error Category + +**Confirmed classification defect.** Public error conversion searches nested +causes in a global priority order, allowing a collaborator's sentinel to hide +the enclosing operation's category. Map the owning boundary independently +while retaining the original cause for `errors.Is`/`errors.As`. Add composed +cause regressions; simply reordering global checks can break legitimate direct +not-found versus load-failure distinctions. + +Sources: [Error handling 1](06-error-handling.md#1-nested-collaborator-errors-can-hide-the-owning-operations-public-category), +[Testing 4](08-testing.md#4-error-tests-miss-composed-causes-and-pre-dispatch-diagnostic-failures). + +## 8. Distinguish Response Stream Failures From Malformed JSON + +**Confirmed error-handling defect.** Non-context I/O failures while decoding a +successful HTTP response or checking its end are reported as malformed JSON, +losing the transport cause; complete JSON followed by a read failure can also +be misreported as trailing data. Retain and classify reader failures separately +using the existing redacted transport boundary. Preserve cancellation +precedence and genuine malformed/truncated/oversized-content handling. Cover +both read locations without adding transport retries. + +Sources: [Error handling 2](06-error-handling.md#2-successful-status-body-read-failures-are-misreported-as-malformed-json), +[Testing 4](08-testing.md#4-error-tests-miss-composed-causes-and-pre-dispatch-diagnostic-failures). + +## 9. Return Invalid Diagnostic Request Construction As A Go Error + +**Confirmed diagnostic-contract defect.** Some invalid inference settings fail +before dispatch yet produce a completed report with a nil Go error. Propagate +local request-construction failures through `ErrInvalidRequest` and add a +no-dispatch regression. Preserve intentionally completed diagnostic outcomes +for missing credentials, capacity outcomes, and unsupported or inapplicable +operations; not every no-dispatch outcome is invalid configuration. + +Sources: [Error handling 3](06-error-handling.md#3-inference-diagnostics-swallow-some-invalid-request-construction-errors), +[Testing 4](08-testing.md#4-error-tests-miss-composed-causes-and-pre-dispatch-diagnostic-failures). + +## 10. Remove Quadratic Requirement-Evidence Union Work + +**Confirmed algorithmic inefficiency.** A left-heavy recognized condition can +repeatedly copy growing missing-key evidence sets, producing quadratic work. +Use operation-local accumulation or ownership-aware merging while preserving +classification and conservative inspection coverage. Do not address this by +adding expression limits or expanding the recognized template language. Entry +23's traversal cleanup is related but is not a substitute for fixing this +specific accumulation algorithm. + +Sources: [Efficiency 1](02-efficiency.md#1-condition-evidence-unions-can-require-quadratic-work). + +## 11. Exercise RunRequest's Privacy Formatting Boundary + +**Missing protection, not a demonstrated leak.** Request formatting methods +have no execution coverage despite owning a privacy-sensitive public boundary. +Add focused tests with distinct synthetic private markers for the relevant +value/pointer formatting paths and JSON omission behavior. Assert privacy and +the documented boundary, not an incidental complete diagnostic or JSON shape. + +Sources: [Testing 1](08-testing.md#1-runrequests-privacy-formatting-contract-is-not-exercised). + +## 12. Correct Profile Inspection Credential Documentation + +**Public-contract documentation defect.** Inspection GoDoc incorrectly makes +required credentials and an environment variable mutually exclusive. Actual +behavior permits an explicit profile environment variable while suppressing +only the backend-derived default when required credentials are selected. +Correct the field/method GoDoc and consumer example, keeping the established +configuration behavior and DTO shape. + +Sources: [Interfaces 2](09-interfaces.md#2-profile-inspection-misstates-required-credential-semantics). + +## 13. Correct The Configured Provider-Map Wire Documentation + +**Integration-contract documentation defect.** The wire document says backend +and profile provider maps replace one another, but configuration recursively +overlays them; runtime replacement is a separate rule. Align the integration +summary with the canonical format reference rather than maintaining a second +conflicting precedence definition. Entry 19 concerns the efficiency of the +existing overlay, not a change to its semantics. + +Sources: [Interfaces 3](09-interfaces.md#3-the-wire-contract-incorrectly-says-configured-provider-maps-replace). + +## 14. Remove Stale Identity And Version GoDoc + +**Public-contract documentation defect.** Inspection comments still describe +trimmed profile IDs, and listing comments describe a removed prompt-version +field. Update them to the implemented literal identity and current collection +version model. Do not normalize meaningful whitespace or reintroduce a field +to match obsolete comments. + +Sources: [Interfaces 4](09-interfaces.md#4-identity-godoc-still-describes-removed-normalization-and-version-fields). + +## 15. Cover The Public Single-Schema-File Option + +**Public wiring coverage gap.** Direct filesystem-validator tests do not +exercise `WithSchemaFile` through engine construction. Add offline temporary +file cases through public preparation/validation, including option precedence +and relevant file errors. This is a supported feature, not dead code; entry +32 removes only an unused private helper result. + +Sources: [Testing 2](08-testing.md#2-the-public-single-schema-file-option-has-no-execution-coverage). + +## 16. Detach Inert Prepared Handles From The Execution Owner + +**Avoidable retention.** Used or discarded prepared handles retain their +runner, and therefore the engine's captured configuration and collaborators. +Use a narrower ownership identity or clear the unnecessary owner reference +safely. Preserve foreign-owner rejection, one-time claim, namespace-view +behavior, and available details. This is unnecessary retention when a handle +outlives its engine, not evidence of an ever-growing global leak. + +Sources: [Resources 3](05-resources.md#3-inert-prepared-handles-retain-their-entire-execution-owner). + +## 17. Bound Repair Feedback's Temporary Serialization + +**Avoidable peak allocation.** Feedback formatting serializes potentially +large diagnostic text before truncating the final message, so its existing +output bound does not bound scratch memory. Produce bounded encoded feedback +incrementally, preserving the existing output semantics and complete stored +validation diagnostics and previous candidate. A new raw-diagnostic input +limit is not implied. + +Sources: [Resources 4](05-resources.md#4-repair-feedbacks-output-bound-does-not-bound-its-temporary-serialization). + +## 18. Detach Normalized Session IDs From Large Input Strings + +**Avoidable retention.** A short trimmed session ID can retain the allocation +of a much larger padded caller string. Clone the accepted normalized value at +its ownership boundary. Preserve trimming, accepted content, code-point +validation, and resulting wire/hash content rather than adding a raw-input +size restriction. + +Sources: [Resources 5](05-resources.md#5-short-normalized-session-ids-can-pin-large-input-strings). + +## 19. Avoid Repeated Descendant Cloning During Provider Overlay + +**Construction-time inefficiency.** Recursive overlays repeatedly clone and +sort overlapping descendant maps, giving work proportional to tree size times +depth. Existing depth bounds mean this is not unbounded quadratic growth. +Clone ownership once or use a single traversal while retaining recursive-map, +null, and array semantics. Coordinate with entry 24 without assuming all JSON +walkers have interchangeable policies. + +Sources: [Efficiency 2](02-efficiency.md#2-recursive-provider-overlay-repeatedly-clones-descendant-subtrees). + +## 20. Index Filtered Listings By Namespace + +**Repeated inspection overhead.** Filtered listing currently copies and scans +the complete inventory even when few or no entries match. Capture namespace +buckets or equivalent ranges so queries operate on the relevant subset. +Preserve ordering, exact identity matching, cancellation, and caller-owned +results. A pagination API or runtime cache is not needed for this improvement. + +Sources: [Efficiency 3](02-efficiency.md#3-filtered-listings-copy-and-scan-the-complete-inventory). + +## 21. Share Schema Compilation And Declare The Runner's Real Dependency + +**Maintainability and interface clarity.** Four host-file/`fs.FS`, +direct/prepared paths repeat the schema compilation lifecycle. The runner also +declares a validator interface while requiring preparation through a runtime +assertion. Share the lifecycle behind source-specific adapters and make that +dependency explicit. Preserve malformed-output short-circuiting before schema +I/O, source containment, exact numbers, cancellation, and frozen plans. Retain +independent cross-source tests; do not force whole entry points to be identical. + +Sources: [Complexity 1](03-complexity.md#1-consolidate-schema-compilation-and-express-the-runners-actual-interface), +[Equivalence 1](10-equivalence.md#1-share-the-schema-compilation-lifecycle-across-source-and-execution-paths). + +## 22. Decompose Configuration Validation And Materialization + +**Maintainability.** Large configuration operations mix record-specific +validation, resource capture, and effective-profile construction. Extract +focused helpers with visible inputs and ownership, rather than another generic +validation framework. Preserve final-handoff validation, presence/null rules, +origins, and meaningful fail-fast/error-precedence behavior. Do not turn +incidental ordering of independent validation failures into a new guarantee. The configuration-boundary ADR remains +authoritative; this is not a proposal to inspect raw ConfigKit sources. + +Sources: [Complexity 2](03-complexity.md#2-decompose-configuration-validation-and-resource-materialization). + +## 23. Clarify Requirement Traversal And Share Branch Orchestration + +**Maintainability.** Separate recognition/evaluation from reachability and +evidence bookkeeping, particularly the repeated `if`/`with` branch protocol. +Keep their scope differences explicit and retain independent comparisons with +the actual Go renderer. Preserve conservative partial coverage and inactive +computed-name behavior. This does not justify a general template interpreter +or stronger execution-readiness promises from requirements inspection. + +Sources: [Complexity 3](03-complexity.md#3-untangle-requirement-traversal-expression-evaluation-and-evidence), +[Equivalence 3](10-equivalence.md#3-share-ifwith-requirement-branch-orchestration-not-template-execution). + +## 24. Centralize Compatible JSON Copying Without Conflating Policies + +**Maintainability and ownership clarity.** The facade maintains a separate +reflection traversal for already-normalized values despite an existing +`internal/jsonvalue` owner. Consolidate genuinely compatible structural +copying while retaining DTO projection at the facade and distinct source +encoding/runtime validation policies. Preserve concrete types, nils, exact +numbers, schema keys, and ownership. Infallible projection must not acquire +new errors, panics, or silent zero-value fallbacks. Entries 3 and 5 remain +separate source-conversion defects, not reasons to reject pre-handoff sources. + +Sources: [Complexity 4](03-complexity.md#4-clarify-ownership-and-policies-across-the-json-value-walkers), +[Equivalence 2](10-equivalence.md#2-centralize-structural-copying-of-already-normalized-json-values). + +## 25. Separate Attempt Accounting From Generation Control Flow + +**Maintainability.** Generation coordination interleaves dispatch/retry policy +with parallel return values and repeated evidence/observation projection. +Introduce a small attempt result and focused accounting helpers. Preserve +built-in versus injected-client differences, permit release before callbacks +or backoff, frozen requests, existing retry classification, private evidence, +and known/unknown usage distinctions. Do not collapse legitimately different +dispatch strategies merely to reduce lines. + +Sources: [Complexity 5](03-complexity.md#5-extract-attempt-accounting-from-generation-control-flow). + +## 26. Move OpenRouter Authentication Protocol Details Into Its Adapter + +**Architectural ownership.** Use-case code currently interprets OpenRouter's +account-response fields and provider-relative endpoint while the outbound +adapter owns HTTP execution. Place protocol construction/recognition with the +outbound integration; keep diagnostic selection, applicability, cancellation, +completion, and neutral reporting in the use case. Preserve credential/body +privacy and anonymous probing. No plugin framework, reverse dependency, or +blanket prohibition on HTTP facts is needed. Coordinate the body-bound fix +in entry 2, which is a distinct behavioral change. + +Sources: [Boundaries 2](11-boundaries.md#2-put-openrouter-authentication-protocol-details-behind-the-outbound-adapter). + +## 27. Narrow Smoke-Value Copy Helpers To Real Consumers + +**Ownership cleanup.** A request cloner has only its self-test as a caller; +the full-report cloner is used to detach only a target. Express that actual +copy operation directly and retire unused broader cloning after checking +callers. Keep facade request/report projection, active backend cloning, +provider-map errors, ownership tests, and redaction. Do not introduce shared +public/internal DTOs or an additional full-report copy. + +Sources: [Boundaries 3](11-boundaries.md#3-narrow-smoke-value-copy-helpers-to-their-actual-ownership-boundaries). + +## 28. Give Bundled Catalog Expectations One Test Owner + +**Test duplication.** Complete bundled profile/model/provider expectations are +repeated across several test layers. Keep one independently specified asset +oracle, with smaller tests for distinct loading, wire, and diagnostic behavior. +Use controlled fixtures where bundled churn is irrelevant and structural +assertions rather than formatted-map strings. Retain meaningful bundled +coverage instead of deriving every expected value from the loader under test. + +Sources: [Testing 7](08-testing.md#7-bundled-catalog-expectations-have-multiple-test-owners). + +## 29. Stop Pinning The Opaque Artifact Hash Algorithm In Tests + +**Over-specified tests.** Artifact tests and a benchmark assert a literal hash +algorithm despite the public value being opaque. Assert the documented +equality/ownership relationships and actual byte/size behavior instead; keep +benchmark setup outside its timed work. Coordinate with entry 31, but do not +turn today's hash representation into a new compatibility guarantee. + +Sources: [Testing 6](08-testing.md#6-artifact-tests-and-benchmarks-pin-an-explicitly-opaque-hash-algorithm). + +## 30. Remove Unconsumed Backend Presence Bookkeeping + +**Low-priority state cleanup.** Backend field-state maps and +`QueueCapacitySet` have no runtime reader; effective values and ConfigKit +already own queue defaulting and provenance. Remove only these unused records +and adjust tests to assert effective behavior or operator inspection. Keep +profile/input presence tracking, explicit zero capacity, and derived defaults. + +Sources: [Dead code 1](12-deadcode.md#1-remove-backend-presence-bookkeeping-with-no-runtime-consumer). + +## 31. Retire Duplicate Fields In Captured Prompt Definitions + +**Low-priority representation cleanup.** Captured definitions duplicate the +output format and carry an unused runtime message-file field after content +materialization. Use the captured output contract and text as their respective +sources of truth. Preserve real YAML `content_file` loading, origins, and the +request-override default rule. Removing serialized internal fields changes +current definition hashes: retain documented opaque equality relationships, +not an invented bit-identical encoding promise. + +Sources: [Dead code 2](12-deadcode.md#2-retire-legacy-fields-in-the-captured-prompt-representation). + +## 32. Remove Unused Private Diagnostic State And Helper Results + +**Low-priority cleanup.** A private reachability outcome echoes an endpoint +that report assembly never reads; the schema-file helper returns a directory +that its only caller discards. Remove the unused state/result while preserving +actual sanitized request/report evidence, directory calculation, file checks, +and public single-file schema support. Keep privacy tests against the values +that real execution consumes. + +Sources: [Dead code 3](12-deadcode.md#3-remove-unused-diagnostic-state-and-a-discarded-helper-result). + +## 33. Remove Orphan Internal Helpers And Their Self-Tests + +**Low-priority cleanup.** `filecatalog.RelativePath` and +`resourceNamespaceFromID` have only their own tests as callers, and the runner +test's `stringPtr` helper is entirely unused. Remove those narrow surfaces +without replacement, preserving real discovery, identity qualification, and +namespace inventory/filtering coverage. Reachability from examples alone is +not a reason to remove optional public APIs. + +Sources: [Dead code 4](12-deadcode.md#4-remove-orphan-helpers-whose-only-callers-are-their-own-tests). + +## 34. Decide Whether To Retain The Legacy Capacity Client Wrapper + +**Decision-dependent architectural cleanup.** The old capacity client wrapper +is used by tests, whereas production dispatch uses the generation coordinator. +It is also explicitly retained in current internal documentation; the dead-code +audit does not classify it as obsolete functionality. If that retention decision +is revised, exercise the production coordinator in runner tests and move any +needed one-shot capacity scaffolding into tests before retiring the wrapper. +Preserve FIFO, cancellation, independent-pool, and panic-release coverage. +This is not a second scheduling algorithm or a confirmed concurrency defect. + +Sources: [Boundaries 1](11-boundaries.md#1-retire-the-test-only-capacity-client-as-a-production-scheduling-surface), +[Dead-code retention qualification](12-deadcode.md#intentional-retention-and-related-findings). + +## Open Decisions + +Work through the decisions below in this order. These are unresolved choices, +not additional findings or approved changes to public contracts. A decision +blocks its dependent remediation, not unrelated fixes. In particular, updating +the maintainer toolchain need not wait for the consumer-minimum decision. +Implementation details and optional cleanup do not become release gates merely +by appearing in this catalog. + +### Decision 1: ArtifactReader Result Ownership And Lifetime + +**Related finding:** [4](#4-resolve-the-artifactreader-buffer-ownership-contract). + +**Question:** What ownership does a successful `Read` transfer, and when may +an injected reader mutate or reuse the returned storage? + +**Recommendation:** Transfer an independent result to PromptKit on successful +return. The reader must stop mutating the returned artifact and its body, +including through retained aliases. Fresh per-invocation storage is the simplest +implementation; immutable shared data can remain shared if no collaborator +mutates it. This removes the impossible immediate-reuse permission without +adding synchronization or a release protocol to the interface. Explain the +consumer impact as a deliberate pre-1.0 contract correction. + +**Alternative:** Permit borrowing until the enclosing preparation/execution +operation returns. This can support application-managed reuse, but a reader +cannot generally observe that lifetime and concurrent calls need independent +storage or caller coordination. If reuse immediately after `Read` returns is +required, an explicit acknowledgement/release API is another viable design; +it enables pooling at the cost of a larger interface and lifecycle change. + +**Resolve before implementation:** Select the ownership/lifetime rule and update +GoDoc, adapter assumptions, and the regression scenario together. Another +unsynchronized copy is not a remedy for the current permission. + +### Decision 2: Provider Submission Of Multi-Resource Schemas + +**Related findings:** [6](#6-make-provider-native-schema-constraints-self-contained) +and [21](#21-share-schema-compilation-and-declare-the-runners-real-dependency). + +**Question:** How should native structured output represent a schema whose +local validation depends on external resources? + +**Recommendation:** First investigate packaging the operation's captured +resource graph into a self-contained provider constraint. Check identifiers, +relative references, anchors, recursion, and supported dialects before choosing +an encoding. Prefer correct packaging when it fits a proportionate scope, +while keeping resource completeness distinct from any provider's supported +schema subset. A standalone offline validation of the actual emitted constraint +should establish the selected packaging behavior. + +**Alternative:** Offer an explicit local-only validation choice when native +submission cannot represent the resource graph. This preserves useful local +validation and avoids building a general schema transformation system, but +forgoes native generation constraints for that selected mode and needs a clear +consumer-facing selection mechanism. Silently dropping native constraints is +not equivalent to an explicit choice. + +**Resolve before implementation:** Establish packaging feasibility and select +the submission/fallback policy, including behavior for unsupported cases. +Coordinate the compilation refactor with that result; it does not itself fix +provider packaging or establish universal provider acceptance. + +### Decision 3: Authentication Response Budget And Overflow Outcome + +**Related findings:** [2](#2-bound-authentication-probe-response-consumption) +and [26](#26-move-openrouter-authentication-protocol-details-into-its-adapter). + +**Question:** What finite response budget should the authentication adapter +apply, and how should a probe report exceeding it? + +**Recommendation:** Select a conservative fixed budget for this small protocol, +check actual streamed bytes regardless of declared length, and close on overflow +without unbounded draining. Report the diagnostic failure with acceptance +unknown, retaining any independently observed HTTP facts. Agree the exact byte +count and its representation in the existing diagnostic report before coding; +the catalog does not select either implicitly. + +**Alternative:** Expose a caller-configurable budget with a finite default. +This accommodates unusual legitimate responses but expands configuration and +validation surface. It is worthwhile if a concrete consumer requirement cannot +be served by an appropriately chosen fixed budget; it is not necessary merely +to address the demonstrated unbounded read. + +**Resolve before implementation:** Choose the size, overflow classification, +and whether configurability is warranted. Keep this fix independent of adapter +relocation so architectural cleanup does not delay the resource remedy. + +### Decision 4: Exact Numbers And The Source-Conversion Boundary + +**Related findings:** [3](#3-avoid-exponential-expansion-during-convenience-source-conversion), +[5](#5-preserve-exact-numbers-in-programmatic-provider-sources), and +[24](#24-centralize-compatible-json-copying-without-conflating-policies). + +**Question:** Which exact numeric values can the convenience helpers preserve +through the current ConfigKit mapping boundary, and what happens to others? + +**Recommendation:** Preserve supported values through the complete conversion, +load, and outbound-encoding path; defer an unsupported-value error when exact +preservation is unavailable. Compare numeric meaning rather than spelling or +successful parsing alone. Address shared-graph expansion in the same adapter +with completed-conversion memoization, distinct cycle tracking, and correct +slice-view identity, preserving source capture and deferred failures. + +**Alternative:** Request upstream support for additional exact numeric/value +forms, then simplify or remove the relevant PromptKit conversion. This may +provide a cleaner long-term boundary and broader preservation, but introduces +an upstream dependency and should not postpone fixing silent rounding or +exponential expansion. Runtime JSON copying remains a separate policy. + +**Resolve before implementation:** Establish the supported numeric round-trip +cases and whether broader upstream support is needed now. Do not substitute +numeric-looking strings or introduce a second raw-source validation system. + +### Decision 5: Consumer Go Minimum After The Toolchain Update + +**Related finding:** [1](#1-update-the-audited-maintainer-toolchain-for-applicable-security-fixes). + +**Question:** Should the security fixes also change PromptKit's declared minimum +consumer Go version? + +**Recommendation:** Update the maintainer toolchain and repeat the focused +assessment promptly; initially keep the consumer minimum decision separate. +Advise affected consumers to rebuild with a patched toolchain. This recognizes +that PromptKit publishes source and that downstream build/transport choices +control the deployed exposure. + +**Alternative:** Raise the declared minimum to the selected patched release. +This makes the supported floor clearer and steers module consumers toward the +fixed toolchain, but changes compatibility and does not repair already-built +applications. Assess it under the existing release policy rather than treating +it as an automatic consequence of the scanner output. + +**Resolve before changing the minimum:** Confirm current advisory applicability, +select the patched version, and decide whether changing the supported consumer +floor is justified. No new recurring release gate is implied. + +### Decision 6: Retention Of The Legacy Capacity Client Wrapper + +**Related finding:** [34](#34-decide-whether-to-retain-the-legacy-capacity-client-wrapper). + +**Question:** Does the wrapper still justify a production surface for its +currently documented test-focused purpose? + +**Recommendation:** Retire the production wrapper after moving the runner's +integration test to the production generation coordinator. Keep direct manager +coverage and any useful one-shot scaffolding in tests. This reduces maintenance +and makes assembled scheduling tests reflect production while preserving the +actual FIFO, cancellation, independent-pool, and panic-release scenarios. + +**Alternative:** Retain it if a concrete internal use justifies the small +adapter. This avoids test migration and preserves that convenient composition, +but keeps a second assembly surface to understand and maintain. Existing +self-tests alone do not establish a future production need. + +**Resolve before removal:** Confirm the intended retention decision and test +ownership. This cleanup can be deferred without blocking the behavioral fixes; +it is not evidence of a second scheduler or a concurrency defect.