diff --git a/docs/consumers/pkg-promptkit.md b/docs/consumers/pkg-promptkit.md index 2f55f8c..a0ac9f8 100644 --- a/docs/consumers/pkg-promptkit.md +++ b/docs/consumers/pkg-promptkit.md @@ -377,6 +377,11 @@ When a limited backend has admitted all active and waiting calls, handle ```go result, err := engine.Run(ctx, request) if errors.Is(err, promptkit.ErrCapacityExceeded) { + var capacityErr *promptkit.CapacityError + if errors.As(err, &capacityErr) { + // Record capacityErr.BackendID using application-owned diagnostics. + } + // Apply application policy: shed work, report overload, or retry later. } ``` @@ -384,8 +389,9 @@ if errors.Is(err, promptkit.ErrCapacityExceeded) { A rejected call returns no partial result and does not invoke the model client. Promptkit does not prescribe retries or map this error to an HTTP status; those choices remain with the consuming application. The -[`Engine.Run` and error GoDoc](../../engine.go) owns exact error and -cancellation identities. +[`CapacityError` GoDoc](../../capacity_error.go) owns the exact typed-error +contract, while the [`Engine.Run` and error GoDoc](../../engine.go) owns broad +error and cancellation identities. ## Application Boundary diff --git a/docs/internal/capacity.md b/docs/internal/capacity.md index 27b588a..9101bad 100644 --- a/docs/internal/capacity.md +++ b/docs/internal/capacity.md @@ -38,10 +38,10 @@ output contract, but before schema loading, artifact loading, or rendering. rechecks credential availability, and then asks the manager to admit the frozen backend before generation. -Admission is immediate: a limited pool either reserves a slot or returns the -internal `ErrCapacityExceeded` identity. The root facade maps that identity to -the public error without treating it as an invalid request or generation -failure. +Admission is immediate: a limited pool either reserves a slot or returns only +the internal `ErrCapacityExceeded` identity. The runner attaches the selected +backend identity at its use-case boundary, and the root facade translates that +typed value without treating it as an invalid request or generation failure. The total admitted bound is the active-generation limit plus its configured waiting capacity. The returned release function is idempotent. The runner diff --git a/docs/internal/overview.md b/docs/internal/overview.md index b475fe0..7800458 100644 --- a/docs/internal/overview.md +++ b/docs/internal/overview.md @@ -11,7 +11,7 @@ contributor workflow and validation. | Component | Implemented responsibility | References | | --- | --- | --- | -| Root `promptkit` package | Provides the supported engine facade, source, backend-registration, and injection options, public request, result, prompt-inspection, and profile-inspection values, opaque prepared-execution handles, profile construction, extension interfaces, value conversion, redacted formatting, public error mapping, and engine-local assembly. | [Package GoDoc](../../doc.go), [prepared execution](../../prepared_execution.go), [backend API](../../backends.go), [engine assembly](../../engine.go) | +| Root `promptkit` package | Provides the supported engine facade, source, backend-registration, and injection options, public request, result, prompt-inspection, and profile-inspection values, opaque prepared-execution handles, profile construction, extension interfaces, value conversion, redacted formatting, typed capacity errors, public error mapping, and engine-local assembly. | [Package GoDoc](../../doc.go), [prepared execution](../../prepared_execution.go), [backend API](../../backends.go), [engine assembly](../../engine.go) | | `examples/go-library/prepare` | Demonstrates an offline downstream consumer using a prompt file, in-memory profile, inline input, and `Prepare`. It is not a public library package. | [Example program](../../examples/go-library/prepare/main.go) | | `examples/go-library/run` | Demonstrates an offline downstream consumer using a prompt file, in-memory profile, inline input, an injected deterministic model client, and `Run`. It is not a public library package. | [Example program](../../examples/go-library/run/main.go) | | `internal/backend` | Constructs each engine's immutable registry from the built-in OpenRouter definition and consumer additions, validates and defensively copies definitions through the shared JSON-value package, and consumes the LLM-owned OpenAI-compatible reserved request-field rule. | [Backend registry](../../internal/backend/registry.go) | diff --git a/docs/internal/runner.md b/docs/internal/runner.md index 5257bdf..722eb45 100644 --- a/docs/internal/runner.md +++ b/docs/internal/runner.md @@ -152,15 +152,17 @@ validation failures. Wrapping preserves the package identities mapped by the public facade and retains collaborator identities where they are part of the internal contract. -Admission capacity exhaustion retains the internal capacity identity and adds -the selected backend ID as context. It is not recategorized as an invalid -request or generation failure, and no partial result is returned. A context -already done at admission retains its context identity directly. Cancellation -while waiting for an active generation permit prevents client invocation when -it wins the grant race; the model-client boundary then preserves the context -error through the generation-failure category. Deferred release restores the -admission lease on preparation, generation, validation, repair, and -cancellation failures. +Admission capacity exhaustion retains the internal capacity identity. At the +use-case boundary, the runner attaches the selected backend ID in an internal +typed error, and the root facade copies that value into the public +[`CapacityError`](../../capacity_error.go) without parsing diagnostic text. It +is not recategorized as an invalid request or generation failure, and no +partial result is returned. A context already done at admission retains its +context identity directly. Cancellation while waiting for an active generation +permit prevents client invocation when it wins the grant race; the model-client +boundary then preserves the context error through the generation-failure +category. Deferred release restores the admission lease on preparation, +generation, validation, repair, and cancellation failures. Other context cancellation propagates through the invoked collaborator and is classified by the owning operation. diff --git a/docs/roadmap/capacity-errors.md b/docs/roadmap/capacity-errors.md index a78f61f..cc3d15e 100644 --- a/docs/roadmap/capacity-errors.md +++ b/docs/roadmap/capacity-errors.md @@ -1,6 +1,6 @@ # Structured Capacity Errors -**Status:** Accepted. +**Status:** Complete. ## Purpose diff --git a/docs/roadmap/future.md b/docs/roadmap/future.md index c3771ad..f0d5f95 100644 --- a/docs/roadmap/future.md +++ b/docs/roadmap/future.md @@ -33,9 +33,7 @@ consumers. ## Ideas -Structured capacity errors have been selected for active planning in the -[focused feature roadmap](capacity-errors.md). No other ideas currently await -selection. +No ideas currently await selection. ## Entry Format diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index 4e5ddfb..4d73b80 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -1,6 +1,6 @@ # Structured Capacity Errors Implementation Plan -**Status:** Ready for implementation. +**Status:** Complete. ## Purpose diff --git a/docs/roadmap/notarius-promptkit-wishlist.md b/docs/roadmap/notarius-promptkit-wishlist.md index a0e89e3..4aa3e46 100644 --- a/docs/roadmap/notarius-promptkit-wishlist.md +++ b/docs/roadmap/notarius-promptkit-wishlist.md @@ -205,8 +205,8 @@ resolution. ## Priority 4: Structured Capacity Errors -**Disposition:** Accepted into the -[structured capacity errors](capacity-errors.md) feature roadmap. +**Disposition:** Implemented behavior. See the consumer guide's +[Handle Errors](../consumers/pkg-promptkit.md#handle-errors) section. ### Downstream need @@ -215,46 +215,16 @@ provider-neutral application error. When multiple backends are active, operators would benefit from knowing which backend rejected admission without parsing an error string or exposing endpoint details. -### Current integration +### Implemented behavior -PromptKit provides the useful `ErrCapacityExceeded` sentinel. Notarius can -classify the failure reliably, but it retains only a sanitized diagnostic -string as additional context. - -### Requested capability - -Add a typed error that continues to match `ErrCapacityExceeded`: - -```go -type CapacityError struct { - BackendID string -} - -func (e *CapacityError) Is(target error) bool { - return target == ErrCapacityExceeded -} -``` - -The exact implementation may use `Unwrap` or another idiomatic mechanism. The -important properties are compatibility with `errors.Is` and discoverability -through `errors.As`. - -### Design considerations - -- Include the stable backend ID. -- Do not expose the backend endpoint, credential environment, credential - value, request content, or other sensitive configuration. -- Consider including the configured concurrency and queue limits if they are - useful and safe, but backend identity alone provides most of the downstream - value. -- Add a retry delay only if PromptKit can provide a meaningful value. A full - queue does not necessarily imply a reliable `Retry-After` duration. -- Keep retry and backoff policy with the consuming application. PromptKit - should classify the admission failure rather than silently retry it. +PromptKit now retains the broad capacity classification while allowing +Notarius to obtain the selected backend ID without parsing diagnostic text. +The consumer guide owns the application workflow, including retry and backoff +policy. ### Value to Notarius -This would improve operational diagnostics and future metrics while preserving +This improves operational diagnostics and future metrics while preserving the provider-neutral error boundary used by Notarius. ## Capabilities PromptKit Already Provides Well @@ -311,7 +281,8 @@ Notarius would be: 1. Add atomic execution that returns prepared details and the completed result. 2. Add a semantic execution-target digest, preferably alongside profile inspection. -3. Add a typed capacity error carrying backend identity. +3. Use the implemented typed capacity error where backend admission diagnostics + are needed. The first addresses a concrete execution workaround. The second would improve checkpoint correctness and reduce coupling. The third is operational polish. diff --git a/docs/roadmap/weatherreporter-promptkit-wishlist.md b/docs/roadmap/weatherreporter-promptkit-wishlist.md index 1bb0789..c21c840 100644 --- a/docs/roadmap/weatherreporter-promptkit-wishlist.md +++ b/docs/roadmap/weatherreporter-promptkit-wishlist.md @@ -282,18 +282,16 @@ the existing sentinel remain available. ### Structured Capacity Errors -**Disposition:** Accepted into the -[structured capacity errors](capacity-errors.md) feature roadmap. +**Disposition:** Implemented behavior. See the consumer guide's +[Handle Errors](../consumers/pkg-promptkit.md#handle-errors) section. -The typed capacity error proposed by the -[Notarius wishlist](notarius-promptkit-wishlist.md#priority-4-structured-capacity-errors) -would improve Weatherreporter diagnostics by exposing the stable backend ID -without parsing error text. +PromptKit now exposes the stable backend ID for capacity rejection without +requiring Weatherreporter to parse error text. Weatherreporter currently generates batch reports sequentially and constructs one engine per invocation, so engine-local capacity exhaustion is unlikely in -the initial design. The feature would become more valuable if report -generation later becomes concurrent or PromptKit engines become longer-lived. +the initial design. The typed error becomes more valuable if report generation +later becomes concurrent or PromptKit engines become longer-lived. It should not block adoption. ### Semantic Execution-Target Fingerprints @@ -364,8 +362,8 @@ Weatherreporter would be: 2. Consider eager source validation after evaluating whether the two exact inspection APIs are sufficient. 3. Add structured generation errors. -4. Add structured capacity errors and semantic execution-target fingerprints - as lower-priority operational improvements. +4. Use structured capacity errors and consider semantic execution-target + fingerprints as lower-priority operational improvements. The first item removes the only material integration workaround. Prompt and profile inspection improve fail-fast validation. The remaining items improve