From cf997c20348097ff51d8822ce6836cc84a598534 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Tue, 13 Oct 2026 21:33:21 +0000 Subject: [PATCH] Explain namespace design recommendations and alternatives --- docs/roadmap/namespaces.md | 182 +++++++++++++++++++++++++++++++++---- 1 file changed, 166 insertions(+), 16 deletions(-) diff --git a/docs/roadmap/namespaces.md b/docs/roadmap/namespaces.md index 14b8bcc..98464d8 100644 --- a/docs/roadmap/namespaces.md +++ b/docs/roadmap/namespaces.md @@ -88,10 +88,16 @@ sketch illustrates the consumer experience only; it does not settle a method name, return type, error behavior, or final signature: ```go -weather := engine.InNamespace("weatherreporter") -// Operations through weather can select the local prompt "summarize.alerts". +weather, err := engine.WithNamespaces(Namespaces{ + Prompt: "weatherreporter", + Profile: "openrouter", +}) +// Handle err, then use local prompt and profile names through weather. ``` +This sketch follows the recommendation in open decision 1; these declarations +do not exist yet. + The view would share the engine's captured configuration, clients, and execution machinery. Selecting a namespace would not rebuild the engine or duplicate its backend capacity accounting. Consumers could use different views concurrently @@ -260,21 +266,165 @@ the selected API contract: - Representative validation, inspection, execution, and smoke-test paths use the same qualification rules without duplicating every test at every layer. -## Open Decisions +## Open Decisions And Recommendations -1. **Public scope shape:** immutable view, scope options, or another small - surface? Which resource scopes can be selected independently, and what does - a one-namespace convenience operation mean? -2. **Scope validation:** how does the scope API represent no scope, report an - invalid namespace selection, and handle a well-formed but currently absent - namespace? Apply the accepted separator rules, distinguish syntax from - existence, and preserve omitted-ID defaults. Do not add case folding or other - character restrictions without a separate decision. -3. **Discovery:** which listing/filtering operations are needed, how are legacy - IDs grouped, and how are local and full identities represented? -4. **Catalog migration:** what exact old-to-new mappings and coordinated release - plan will implement the accepted breaking change, and which otherwise valid - IDs should additionally adopt provider/application namespaces? +Each recommendation below is a proposal for the next decision, not an accepted +contract. Alternatives preserve the settled naming and resolution rules. + +### 1. Public Scope Shape + +**Recommended: an immutable view with independent resource scopes.** Provide one +engine operation that accepts a small value with prompt, profile, and backend +namespace fields and returns a scoped view or an error. The illustrative +`WithNamespaces` and `Namespaces` names above are provisional. Empty fields mean +no scope for that resource type. The view captures the value and delegates to +the same engine; it does not expose a mutable namespace setting. Apply the +prompt field to caller-supplied prompt IDs, the profile field to profile IDs, +and the backend field to backend IDs wherever those selections are supported. +Qualified references bypass the corresponding field. + +This directly serves the select-once workflow and the common mixed case of an +application prompt namespace with a provider profile namespace. It also keeps +scope out of stored configuration and makes concurrent use independent of call +order. The cost is an additional facade surface whose supported operations must +remain consistent with the engine. Keep qualification shared rather than +duplicating selection logic in each wrapper. + +Initially omit an ambiguous one-string `InNamespace` shorthand. Repeating the +same namespace in several fields happens once when creating a view and states +exactly which resource types it affects. A convenience operation can follow if +that repetition is a demonstrated burden. + +**Alternative: one namespace per immutable view, applied to all resource +types.** A one-string operation would scope every unqualified prompt, profile, +and backend selection; callers would use qualified references for resources in +other namespaces. This is smaller and reads naturally for self-contained +application collections. It is less convenient when prompts and profiles +habitually come from different namespaces, because profile overrides would +repeatedly need qualification. Prefer it if consumers primarily use prompts' +configured defaults and rarely select profiles themselves. + +**Alternative: explicit scope values supplied per operation.** Add scope to +request values and appropriate inspection/listing options instead of returning +a view. This makes every invocation self-contained and suits applications that +choose a different scope for every request. It spreads scope through more call +sites and API shapes, and consumers would need their own reusable wrapper to +achieve the requested select-once experience. The immutable view is therefore +the better default for the use case discussed so far. + +### 2. Scope Validation + +**Recommended: validate syntax when creating the view; resolve existence when +an operation selects a resource.** In the recommended scope value, the empty +string means no scope. Reject a nonempty namespace containing `/` or consisting +only of whitespace. Otherwise preserve its exact spelling, with no trimming, +case folding, or additional character whitelist. This distinguishes omission +from an unusable namespace without inventing normalization rules. Report invalid +scope construction through PromptKit's existing public error conventions. + +Allow a well-formed namespace even when it has no current members. Its scoped +listing would be empty, and selection of a missing local resource would produce +the ordinary lookup error. Qualified selections would remain usable regardless +of the view's default scope. An empty optional request ID continues to mean +omission under that operation's existing contract; it is never qualified. + +This keeps scope as a naming context and supports uniform application setup +across installations with different library contents. It also avoids treating +successful scope construction as validation of a prompt or execution profile. +The tradeoff is that a misspelled but syntactically valid namespace is detected +only when listed or used, rather than during view construction. + +**Alternative: require each selected namespace to have resources of its +corresponding type when creating the view.** For an immutable assembled engine, +this can catch spelling mistakes immediately and gives startup checks useful +feedback without attempting execution. However, it rejects empty optional +collections and a view intended to use qualified references outside its default +namespace. A namespace having one member also does not establish that the +particular required prompt/profile exists. Prefer this approach only if eager +inventory validation is itself an intended consumer contract; it should not be +an accidental consequence of implementing scope creation. + +### 3. Discovery + +**Recommended: namespace enumeration and resource listings that retain full +IDs.** Enumerate the distinct named namespaces present in final effective +prompts, profiles, and backends. Allow filtering that enumeration by resource +type so a prompt picker need not show profile-only namespaces. Provide scoped +listings for the supported resource types, adding a backend inventory surface +as part of this work if needed. Keep the existing unscoped listing signatures +and their all-resource behavior. + +A scoped listing filters by the selected scope for that resource type and +returns full IDs, retaining prompt versions as separate identity fields. +Without a scope, it lists all resources of that type. Unqualified resources +remain in unscoped listings; provide an explicit unqualified-only listing filter +so callers can distinguish that group from all namespaces. Do not invent a +named namespace such as `default` for those IDs. Namespace enumeration excludes +that unnamed group. Use deterministic ordering consistent with existing listing +contracts. + +Full IDs can be passed unchanged to either scoped or unscoped operations, which +avoids double qualification and preserves identity in logs and user interfaces. +A small public name-splitting helper can supply namespace/local components for +display without requiring applications to duplicate parsing rules. This keeps +existing identity shapes useful and avoids introducing collection metadata just +to support filtering. The tradeoff is that consumers wanting separate display +fields perform that explicit decomposition. + +**Alternative: add a richer inventory API returning full ID, namespace, local +name, resource type, and prompt version where applicable.** Preserve existing +list methods and expose the structured form separately. This is attractive for +Scriptorium-style library browsers: grouping and display require no parsing, +and one inventory operation can cover all resource kinds. It creates another +public representation and overlaps existing listing APIs, so its value should +justify that maintenance. Prefer it if downstream clients routinely need a +combined catalog view rather than a resource picker or namespace filter. In +either approach, the full ID remains the authoritative selection value. + +### 4. Catalog Migration + +**Recommended: coordinate the grammar change with adoption of provider +namespaces for ordinary maintained catalog profiles.** Use provider namespaces +such as `openrouter` and `rakestrawhome`, with descriptive slash-free local +profile names. Use `google.gemma-4-31b-it` for the illustrative model-based +profile name; profiles with distinct execution settings need distinct local +names even when they select the same model. Assign every renamed profile an +explicit old-to-new mapping after auditing the catalog, including valid old IDs +that currently encode a provider prefix differently. Do not infer mappings by +blind punctuation replacement. + +Retain the two unqualified built-in profile names explicitly guaranteed by the +release policy. Keep existing valid backend IDs unless there is a concrete +collision or organizational reason to rename them; provider-qualified profiles +can reference those exact backend IDs without duplicating backend identity or +capacity accounting. Application-owned prompt libraries choose their own +namespace and migration mappings rather than being silently rewritten by +PromptKit. + +Prepare catalog data, affected references, consumer migration instructions, and +the PromptKit grammar change as coordinated work. Select compatible catalog +revisions for the PromptKit release and follow each repository's release rules. +Choose a PromptKit version permitted to break the format contract: a minor +release before v1, or a major release at/after v1, under the current release +policy. Exact versions and actual old-to-new mappings require the catalog audit; +this recommendation does not claim those mappings have already been established. + +This makes the initial feature useful with maintained provider catalogs and +concentrates consumer migration into one planned transition. Retaining the +explicitly supported unqualified profile names preserves their selected +contract. The cost is a broader coordinated change than grammar enforcement +alone, including renames of otherwise valid ordinary profile IDs. + +**Alternative: migrate only IDs that violate the new grammar, and defer broader +catalog naming changes.** Keep all other exact IDs, including valid one-slash +IDs whose first component would now be their namespace. Ship scope support and +let new libraries adopt provider/application namespaces incrementally. This +reduces immediate consumer changes and makes the format update easier to review +and release independently. It leaves existing catalogs with inconsistent +grouping, may expose model-vendor rather than provider namespaces, and can +require another migration to realize the intended provider shorthand. Prefer +it if the audit reveals that broad catalog renaming would impose substantial +downstream disruption relative to current demand. The delimiter, two-component qualified grammar, syntax-based resolution, and acceptance of the required breaking migration are settled. Resolve the remaining