diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md new file mode 100644 index 0000000..8519ec8 --- /dev/null +++ b/docs/roadmap/implementation.md @@ -0,0 +1,272 @@ +# Rakestrawhome Built-In Backend Implementation Plan + +## Purpose + +Implement the target state defined in the +[Rakestrawhome built-in backend roadmap](rakestrawhome-backend.md): make the +maintainer's OpenAI-compatible inference service a reserved built-in backend, +publish its first built-in model profile, and document the resulting consumer +surface. + +This is an execution plan, not an additional source of feature policy. When a +detail in this plan requires interpretation, preserve the decisions and scope +boundaries in the feature roadmap and the ownership rules under +[`docs/policy/`](../policy/). + +## Fixed Decisions + +- The internal and wire-facing backend ID is `rakestrawhome`; its exported root + constant is `BackendRakestrawHome`. +- Its base endpoint is `https://inference.ai.rakestrawhome.com/v1`. The existing + OpenAI-compatible client composes the final request URL as + `https://inference.ai.rakestrawhome.com/v1/chat/completions`. +- Its API-key environment variable is + `RAKESTRAWHOME_INFERENCE_API_KEY`. +- Each engine permits four active generation calls for this backend. The + existing default bounded waiting capacity of 1024 applies. +- The embedded profile ID is `rakestrawhome-gemma-4-31b`, its backend is + `rakestrawhome`, and its model is `google/gemma-4-31b-it`. +- The new profile contains no optional generation settings. The existing + OpenRouter `gemma-4-31b` profile remains unchanged. +- Built-in registration is inert: engine construction does not read a + credential or contact the service. Existing selection-time credential, + endpoint-override, profile-precedence, and error behavior remains in force. +- Consumer backend additions cannot replace either built-in ID. Consumer + profile sources may continue to override an embedded profile by profile ID. +- Verification is deterministic and offline. Do not add a live service test, + provider-specific client, duplicate concurrency stress matrix, or duplicate + endpoint-composition matrix. + +## Execution Rules + +- Implement the stages in numerical order. Treat each stage as one bounded + coding-agent prompt, and complete its focused and regression verification + before beginning the next stage. +- At the start of each stage, review the feature roadmap and the policy files + relevant to that stage. Follow the task-specific reading guide in + [`docs/development.md`](../development.md). +- Preserve unrelated working-tree changes. Do not commit, tag, push, or modify + release documentation unless a separate instruction authorizes it. +- Keep tests at their narrowest owner. Extend existing tests where they already + own the contract instead of creating parallel test matrices. +- Update current-state documentation only in Stage 3, after the implemented + behavior exists. + +## Stage 1: Generalize Built-In Backend Registration + +### Objective + +Add the exact Rakestrawhome definition to the immutable backend registry and +expose its reserved ID through the public facade without changing the generic +backend, capacity, or client mechanisms. + +### Implementation + +1. In `internal/backend/registry.go`, add the stable exported internal ID + `RakestrawHomeID = "rakestrawhome"` and private constants for: + - endpoint `https://inference.ai.rakestrawhome.com/v1`; + - API-key environment variable `RAKESTRAWHOME_INFERENCE_API_KEY`; and + - concurrency limit `4`. +2. Replace the inline OpenRouter construction in `NewRegistry` with a private + `builtInBackends() []domain.Backend` factory that returns fresh definitions + for OpenRouter and Rakestrawhome on every call. Do not use a mutable package- + level slice or map. The Rakestrawhome definition must leave + `QueueCapacitySet` false so the existing normalization path assigns the + shared default queue capacity of 1024. +3. Have `NewRegistry` allocate from `len(builtIns) + len(additions)`, process + built-ins before consumer additions, and pass every definition through the + existing `normalizeBackend` and duplicate-ID logic. Preserve defensive-copy + behavior and all validation and error contracts. +4. In the root `backends.go`, expose + `BackendRakestrawHome = backend.RakestrawHomeID`. Update the `Backend` and + `WithBackend` GoDoc so their reservation language applies to all built-ins, + not only OpenRouter. Do not expose endpoint, credential, or capacity + constants in the root package. +5. Make no changes to `NewEngine`, the capacity manager, or the OpenAI- + compatible client. They must consume the new definition through their + existing registry and policy interfaces. + +### Tests + +1. In `internal/backend/registry_test.go`, generalize the exact built-in test + to assert both definitions. For Rakestrawhome, assert the exact ID, base + endpoint, API-key environment-variable name, concurrency limit `4`, + normalized queue capacity `1024`, `QueueCapacitySet == true`, and absence of + extra parameters. Preserve the corresponding exact OpenRouter assertions. +2. Assert that `CapacityPolicies` contains exactly both built-in policies in a + registry with no additions, including the exact concurrency and queue + values. Retain lookup-isolation coverage rather than exposing registry- + owned data to mutation. +3. Update addition-related expected counts to include two built-ins. Ensure the + custom-addition mutation test still proves registry isolation and does not + accidentally replace either built-in. +4. Table-drive the existing built-in collision coverage over whitespace- + normalized `openrouter` and `rakestrawhome` additions. Each must return the + existing duplicate-ID configuration error. +5. At the root public-contract owner, extend the existing reserved-backend + registration test to cover both `BackendOpenRouter` and + `BackendRakestrawHome`. Do not duplicate the internal registry's full + validation matrix. + +### Verification + +Run the focused backend and root tests first, then the ordinary regression +suite: + +```sh +go test ./internal/backend +go test . +go test ./... +``` + +The stage is complete when both exact built-ins are published through the same +immutable registry path, both IDs are reserved, and existing custom-backend and +OpenRouter behavior remains green. + +## Stage 2: Add the Built-In Profile and Prove Assembly + +### Objective + +Embed the minimal Gemma profile, generalize built-in catalog assumptions from +one backend to the maintained built-in set, and prove ordinary engine assembly +without adding provider-specific execution logic. + +### Implementation + +1. Add `internal/profile/builtin/assets/google/rakestrawhome-gemma-4-31b.yml` + with exactly these semantic fields and no optional settings: + + ```yaml + id: rakestrawhome-gemma-4-31b + backend: rakestrawhome + model: google/gemma-4-31b-it + ``` + + Keep the asset under `google` because the existing directory hierarchy + groups profiles by model provider; the profile ID and `backend` field carry + the inference-backend distinction. +2. Do not change the embedded repository implementation: its existing recursive + `assets/**/*.yml` pattern must discover the new asset. Do not alter + `internal/profile/builtin/assets/google/gemma-4-31b.yml`. +3. In the built-in repository tests, replace the assumption that every asset + selects OpenRouter with an explicit allowed built-in set containing + `backend.OpenRouterID` and `backend.RakestrawHomeID`. Continue to reject a + blank or duplicate profile ID, an unapproved backend ID, raw `api_key`, + `endpoint`, or `api_key_env` fields, and any asset that fails ordinary + repository parsing and validation. +4. Add a focused assertion that loading `rakestrawhome-gemma-4-31b` returns the + exact backend and model and leaves every optional generation setting, + timeout, service tier, endpoint, credential field, and extra-parameter map + absent or at its zero value. This protects the deliberate native-default + policy rather than merely proving that the YAML parses. +5. Generalize the existing root test that prepares a built-in profile without + a profile directory into a small table covering its current OpenRouter case + and the new Rakestrawhome case. Supply a synthetic credential with + `t.Setenv`; call preparation only; and assert the selected profile ID, + backend ID, base endpoint, credential environment-variable name, and model. + Capacity policy has no public inspection seam and is intentionally covered + by the registry and existing generic capacity-contract owners instead. + +### Test Boundaries + +- Rely on the registry test for the literal Rakestrawhome capacity values and + on the existing generic capacity-contract tests for semaphore and queue + behavior. Do not add another four-way goroutine test. +- Rely on the exact registered base endpoint plus the existing generic client + endpoint-composition test. Do not make a live request or add a second copy of + the transport matrix. +- Preserve existing profile-source precedence tests. The new asset uses the + same repository and resolution path, so do not duplicate the complete + precedence matrix. + +### Verification + +Run the focused catalog and root tests, then the ordinary regression suite: + +```sh +go test ./internal/profile/builtin +go test . +go test ./... +``` + +The stage is complete when the new ID resolves through the embedded catalog and +ordinary engine assembly, contains no unintended request defaults, and does +not alter the existing OpenRouter Gemma profile. + +## Stage 3: Update Canonical Documentation and Complete Validation + +### Objective + +Bring each canonical documentation owner into line with the implemented public +and internal state, give manual registrants an explicit migration path, and +run the complete maintainer workflow. + +### Documentation + +1. Update `docs/policy/architecture.md` and `docs/internal/overview.md` so the + backend registry is described as owning multiple maintained built-ins rather + than a single inline OpenRouter definition. Keep architectural policy at the + ownership level; do not turn it into a catalog of duplicated literal values. +2. Update `docs/internal/sources.md` to remove the assertion that every + built-in profile selects OpenRouter. Explain that embedded profiles inherit + connection and credential metadata from whichever maintained built-in + backend they select. +3. Update `docs/formats.md` as the canonical owner of backend definitions and + the embedded profile catalog: + - list OpenRouter and Rakestrawhome with their exact stable IDs, endpoints, + API-key environment variables, concurrency limits, and default queue + capacity; + - add a `Backend` column to the built-in profile table so a mixed-backend + catalog is unambiguous; and + - add `rakestrawhome-gemma-4-31b` with backend `rakestrawhome` and model + `google/gemma-4-31b-it`, while preserving every existing catalog row. +4. Update `docs/consumers/pkg-promptkit.md` with the shortest supported use of + the built-in profile and `BackendRakestrawHome`. State that consumers set + `RAKESTRAWHOME_INFERENCE_API_KEY`, do not register the built-in manually, + and must remove an existing `WithBackend` registration under the exact + `rakestrawhome` ID to avoid the intentional duplicate-ID error. Preserve the + documented direct credential and runtime endpoint overrides. +5. Ensure root GoDoc added in Stage 1 documents the exported constant and the + plural built-in reservation rule. Leave + `docs/integrations/openai-compatible-chat.md` as the canonical owner of + generic endpoint composition and wire behavior; change it only if it + contains an inaccurate single-built-in statement. Do not duplicate its + transport details in consumer guidance. +6. Do not add release notes in this feature pass. Release documentation and + tagging are separate maintainer actions. + +### Final Verification + +Run the complete offline workflow in +[`docs/development.md#maintainer-validation`](../development.md#maintainer-validation), +including: + +```sh +go test ./... +go test -race ./... +go vet ./... +go build ./... +go run ./examples/go-library/prepare +go run ./examples/go-library/run +``` + +Also perform the documented Go-formatting, local Markdown-link, and repository- +hygiene checks. Review the examples' deterministic output as instructed. No +command may require a real Rakestrawhome credential or contact either provider. + +Finally, inspect the diff against the feature roadmap and confirm all of the +following: + +- only the new public constant and embedded profile ID enlarge the consumer + surface; +- OpenRouter's definition and existing `gemma-4-31b` profile are unchanged; +- both built-in backend IDs are reserved and consumer-added IDs remain + extensible; +- no API key value, mutable global registry, provider-specific transport, live + test, or hidden generation default was introduced; and +- current-state documentation and GoDoc agree with the implemented behavior. + +## Open Questions + +None. The feature roadmap and this plan fix every implementation-relevant +choice required for the three stages. diff --git a/docs/roadmap/rakestrawhome-backend.md b/docs/roadmap/rakestrawhome-backend.md new file mode 100644 index 0000000..a85ef22 --- /dev/null +++ b/docs/roadmap/rakestrawhome-backend.md @@ -0,0 +1,164 @@ +# Rakestrawhome Built-In Inference Backend + +## Purpose + +Promptkit should provide the maintainer's Rakestrawhome inference service as a +second built-in OpenAI-compatible backend, alongside OpenRouter. This removes +the repeated backend and profile registration currently required in every +downstream application that uses the service. + +The feature is intentionally a built-in registration rather than another +convenience constructor. Engines should receive the same immutable backend +definition, credential convention, concurrency policy, and initial model +profile without consumer assembly code. + +## Target End State + +Every newly constructed engine contains two reserved built-in backend IDs: + +- `openrouter`, with its existing definition and behavior unchanged; and +- `rakestrawhome`, configured with the OpenAI-compatible base endpoint + `https://inference.ai.rakestrawhome.com/v1`, API-key environment variable + `RAKESTRAWHOME_INFERENCE_API_KEY`, and a concurrency limit of four active + model-generation calls per engine. + +The Rakestrawhome backend uses Promptkit's existing default bounded waiting +capacity of 1024. The capacity manager therefore permits no more than four +simultaneous generation calls for this backend while retaining the existing +high, bounded backlog policy. Ordinary backend, profile, runtime endpoint, +credential, and request-setting precedence remains unchanged. + +Promptkit also embeds this profile: + +```yaml +id: rakestrawhome-gemma-4-31b +backend: rakestrawhome +model: google/gemma-4-31b-it +``` + +The profile deliberately omits optional generation controls so the inference +service and model apply their native defaults. It does not repeat the backend +endpoint or credential environment-variable name. The existing +`gemma-4-31b` OpenRouter profile and its current model spelling and settings +remain unchanged. + +Consumers can select `rakestrawhome-gemma-4-31b` anywhere an ordinary profile +ID is accepted. Higher-precedence in-memory, configured, or application +fallback profile sources may continue to replace the embedded profile by ID. +Consumers can refer to the built-in backend through a new exported constant, +`BackendRakestrawHome`, while the exact backend definition remains internal. + +## Backend Registry End State + +Built-in registry construction owns a small maintained collection rather than +an inline OpenRouter special case. Both built-ins enter the same normalization, +validation, immutable storage, defensive-copy, and capacity-policy paths. + +The internal backend package owns stable IDs and connection and capacity +policy. The root facade exposes only the stable Rakestrawhome ID through +`BackendRakestrawHome`. Public uniqueness and reservation rules apply equally +to every built-in. + +Consumer additions must remain unable to replace either reserved built-in ID. +Registrations under all other valid IDs retain their current behavior. Engine +construction must not contact the Rakestrawhome endpoint, read the API-key +environment variable, or require credentials merely because the backend is +registered. Credential resolution occurs only when a selected execution target +uses it, under the existing precedence and error contracts. + +The built-in OpenAI-compatible client will append `chat/completions` to the +registered base path, producing +`https://inference.ai.rakestrawhome.com/v1/chat/completions`. No provider- +specific transport implementation is required. + +## Built-In Profile Catalog End State + +The Rakestrawhome Gemma profile is an embedded YAML asset in the existing +built-in profile repository. No additional repository layer or provider- +specific profile loader exists. + +Catalog validation permits the maintained built-in backend IDs and establishes +that: + +- every embedded profile has a unique, nonblank ID; +- every embedded profile selects an approved built-in backend; +- no embedded profile contains a raw API key or repeats an endpoint or API-key + environment-variable name owned by its backend; and +- the new profile resolves to the exact intended backend and model through the + ordinary repository and engine assembly. + +Retain the existing source precedence: consumer profile sources may override +the new built-in profile, but a malformed authoritative override remains an +error rather than silently falling through. + +## Public Compatibility And Migration + +This feature adds one public constant and one embedded profile ID. It does not +remove or change an existing public declaration or profile. + +The backend ID `rakestrawhome` becomes reserved. A downstream application that +currently registers that ID manually must remove its `WithBackend` +registration when adopting this feature; otherwise construction will correctly +report a duplicate built-in ID. It may also remove any equivalent manually +supplied profile and select `rakestrawhome-gemma-4-31b` directly. A consumer +profile with the same profile ID remains a supported higher-precedence +override rather than a registry collision. + +Direct API-key and runtime endpoint overrides continue to work. Promptkit must +never embed, inspect, log, or document an actual credential value; only the +environment-variable name belongs in the built-in definition. + +## Documentation End State + +Canonical current-state documentation: + +- describes the backend registry as containing multiple built-ins in the + architecture policy and internal component overview; +- describes both built-in backend definitions and the mixed-backend profile + catalog in the framework format reference and internal source overview; +- lists `rakestrawhome-gemma-4-31b` in the built-in profile catalog; +- documents `BackendRakestrawHome`, the removal of redundant downstream + registration, the credential variable, and the four-call concurrency policy + in public GoDoc and consumer guidance; and +- retains the OpenAI-compatible integration document as the canonical owner of + endpoint composition and outbound wire behavior. + +## Acceptance Criteria + +The completed feature is protected at the narrowest stable owners: + +- registry tests should cover both exact built-in definitions, default queue + normalization, capacity-policy publication, lookup ownership, and duplicate + rejection for both reserved IDs; +- built-in profile tests should validate the generalized catalog invariants and + exact Rakestrawhome profile; +- a representative root integration test proves that selecting the new + profile resolves the expected backend ID, endpoint, model, and credential + environment-variable name without making a live network request or + requiring a real credential; +- the registry's exact capacity-policy tests and the existing generic engine + capacity tests together protect the engine-local four-call limit without a + duplicate provider-specific concurrency matrix; and +- existing OpenRouter, custom-backend, profile-precedence, endpoint-override, + credential, capacity, and injected-client tests should remain green without + duplicating their full behavioral matrices for the new built-in. + +## Non-Goals + +This feature does not add: + +- provider discovery, health checking, model enumeration, or live integration + tests; +- automatic fallback, retry, or routing between OpenRouter and Rakestrawhome; +- global mutable registry state or consumer replacement of built-in IDs; +- a second model-client protocol or non-OpenAI-compatible transport; +- provider-specific generation defaults that have not been deliberately + selected; or +- any embedded API-key value. + +## Open Questions + +None. The backend ID, public constant direction, endpoint base path, +credential environment-variable name, concurrency and queue policy, profile +ID, model name, optional-setting policy, compatibility behavior, and scope +boundaries are fixed by this roadmap.