From 75891b65617303d3fc7e5bf607f02ad25b41fe85 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Tue, 13 Oct 2026 21:25:57 +0000 Subject: [PATCH] Document namespace and scoped lookup roadmap --- docs/roadmap/namespaces.md | 244 +++++++++++++++++++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 docs/roadmap/namespaces.md diff --git a/docs/roadmap/namespaces.md b/docs/roadmap/namespaces.md new file mode 100644 index 0000000..b734065 --- /dev/null +++ b/docs/roadmap/namespaces.md @@ -0,0 +1,244 @@ +# Namespaces And Scoped Resource Lookup + +Status: proposed feature roadmap; not implemented. The consumer need is +established, but the API shape and naming rules below remain proposals unless +identified as existing behavior. + +## Purpose + +Let consumers select a namespace once and use convenient local names within +that namespace across PromptKit operations. An assembled engine may contain +multiple application prompt libraries and provider profile catalogs with +overlapping local names. Resolution must remain unambiguous. + +The motivating cases are: + +- WeatherReporter and another application both define `summarize.alerts`. + Each consumer selects its application namespace and uses the local name. +- OpenRouter and RakestrawHome both provide the model identified in the + discussion as `google/gemma-4-31b-it`. Consumers distinguish the execution + profiles by provider namespace while retaining convenient local naming. + +Model names here illustrate identity and resolution, not provider availability +or a promise of maintained catalog entries. + +The primary need is organization and convenient lookup within assembled +libraries. Ansible collections are a conceptual reference for qualified names; +package distribution and relocatable collection imports are not required for +this feature. + +## Existing Foundation + +The [format reference](../formats.md) defines prompt, profile, and backend keys +as exact literal IDs. Punctuation is already allowed, and references are not +trimmed or re-keyed. Merely adopting prefixed IDs therefore does not provide +the requested scoped lookup behavior. + +Existing prompt and profile listings expose assembled identities. The +[consumer guide](../consumers/pkg-promptkit.md) describes current operations; +their Go declarations and GoDoc remain authoritative until this feature lands. + +[ADR 0001](../adr/0001-configuration-boundary.md) assigns source loading, +composition, and inheritance to ConfigKit. This proposal adds interpretation +of consumer-supplied resource names against the final effective configuration, +without a second source-composition pass. + +## Proposed Identity Convention + +Use `namespace/local-name` as the qualified identifier. The first slash is the +namespace boundary; the rest of the local name is literal and may contain dots +or additional slashes. This is the recommended convention, not a settled +format change. + +| Resource | Namespace | Local name | Qualified ID | +| --- | --- | --- | --- | +| Prompt | `weatherreporter` | `summarize.alerts` | `weatherreporter/summarize.alerts` | +| Prompt | `homewatch` | `summarize.alerts` | `homewatch/summarize.alerts` | +| Profile | `openrouter` | `google/gemma-4-31b-it` | `openrouter/google/gemma-4-31b-it` | +| Profile | `rakestrawhome` | `google/gemma-4-31b-it` | `rakestrawhome/google/gemma-4-31b-it` | + +Prompt, profile, and backend identities remain separate resource types. The +same namespace can contain all three, and resources in it may come from +multiple configuration sources. A namespace does not imply a directory, +package, provider model identifier, or security boundary. + +A profile ID identifies execution settings. Its configured model value is +still the identifier passed to the provider; qualifying the profile ID does +not modify that value. Different profiles may select the same model with +different settings. Prompt versions also remain separate from namespaces and +continue to use the existing selection rules. + +Retain existing exact IDs, including unqualified and dotted names. Before +formalizing namespace discovery, audit slash-containing IDs in maintained +catalogs and representative consumer configurations: interpreting their first +component as a namespace may affect grouping even when exact lookup is unchanged. + +## Proposed Consumer Scope + +Prefer a lightweight, immutable view over an existing engine. The following +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". +``` + +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 +without changing a shared current-namespace setting. + +The proposed resolution rules are: + +1. A supplied local name is qualified using the selected scope for its resource + type, then looked up exactly. +2. A missing scoped resource does not trigger a search in other namespaces or + among unqualified IDs. Loading another collection cannot redirect lookup. +3. An operation without a selected scope retains existing exact-ID behavior. +4. Scope applies to caller-supplied resource names. Stored references, including + prompt default profiles, profile backends, inheritance references, and backend + smoke-test default profiles, retain their existing exact meaning. They are + not rebound to the invoking consumer's namespace. +5. Omitted optional IDs retain their existing selection/default behavior; an + omission is not converted into a namespace prefix or a lookup for an empty + local name. +6. Where outputs, inspection, errors, or diagnostic reports identify a selected + resource, preserve its resolved full identity. Any exposed local name should + be distinguishable from that identity. + +Keep qualification consistent across execution, preparation, request validation, +prompt/profile inspection, and applicable smoke-test selections. Namespace +selection must not change request override precedence, prompt version selection, +or provider model strings. + +### Local Names Versus Exact IDs + +The presence of a slash cannot distinguish local and qualified references: +`google/gemma-4-31b-it` is a legitimate local profile name under `openrouter`. +Do not decide whether to qualify a name by checking whether the unqualified +candidate happens to exist; that would make resolution depend on loaded content. + +The recommended initial approach is that a scoped resource field consistently +accepts a local name, while the original engine remains available for exact IDs. +Under that approach, even a string that looks qualified is treated as local +when passed through the corresponding scope. An explicit per-reference exact-ID +mechanism is an alternative if mixed local and qualified selections in one +request justify it. Settle this before defining the public API. + +### Separate Resource Scopes + +A consumer may want prompt shorthand under `weatherreporter` and profile +shorthand under `openrouter` in the same request. Evaluate independently +selectable prompt, profile, and backend scopes instead of assuming one namespace +must apply to every field. A prompt's configured default profile needs no caller +profile scope because the stored reference is already exact. + +Independent scopes are recommended where the consumer needs shorthand, but the +scope options and the meaning of a convenience `InNamespace` operation are +still open. Do not silently apply a prompt scope to an otherwise exact profile +override. Include any directly supplied backend selection in this decision. + +## Discovery And Collection Organization + +Namespace-aware discovery is supporting work: consumers should be able to +identify available namespaces and list their resources without each application +inventing parsing and filtering rules. Keep this proportionate to the primary +scoped-lookup feature. + +Decide whether scoped listing returns full identities, local names alongside +full identities, or another explicit shape. A caller must be able to tell how +to pass a listed name back to a scoped operation without double qualification. +Retain the existing unscoped listing contracts. + +If namespace membership is derived from the recommended prefix convention, +match the complete namespace boundary: `weather` must not include +`weatherreporter/...`. Additional slashes within the local name do not imply +recursive namespace traversal. + +The initial proposal does not require a collection manifest. Titles, +descriptions, and other collection metadata can be considered if consumers +need more than identity and grouping. + +## Composition And Compatibility + +Qualified identities reduce accidental collisions between independently +authored libraries. Definitions with the same exact qualified identity still +follow the existing ConfigKit overlay and inheritance rules; namespaces do not +create a separate collision policy. + +Leave source composition and configuration inspection with ConfigKit. Do not +introduce implicit qualification of definition keys, mounting under caller-chosen +prefixes, or rewriting of stored references as part of consumer scope. Those +would be separate configuration-design work. + +Existing unscoped engine calls and catalog identifiers must continue to work. +Adoption of the new convention by maintained catalogs needs an explicit +migration decision. Renaming a profile or backend can affect configured +references; duplicating a backend under another ID can also separate capacity +accounting. Do not treat blanket aliases or duplicate catalog entries as a +cost-free compatibility mechanism. + +The [architecture policy](../policy/architecture.md) continues to assign CLI +syntax, flags, and application policy to consumers such as Scriptorium. PromptKit +would supply reusable scope and resolution semantics. + +## Work Not Included In The Initial Proposal + +- Package installation, collection registries, and dependency resolution. +- Caller-selected collection mount points or import alias rewriting. +- Implicit namespace search paths or fallback to whichever resource exists. +- Namespace-based access control or filesystem isolation. +- Changes to model names, inference behavior, or configuration precedence. + +These boundaries limit the initial proposal; they do not prohibit future work +if a concrete consumer need emerges. + +## Delivery Outline + +1. Settle the open naming and API decisions below and audit existing identifier + usage. Record any catalog migration as explicit coordinated work. +2. Implement the smallest public scope surface with shared name qualification + and existing engine collaborators. Cover supported operations consistently. +3. Add the selected discovery behavior and representative consumer examples. +4. Verify compatibility and scoped resolution through focused offline tests, + following the [testing policy](../policy/testing.md). Update GoDoc, the + format reference, consumer guide, and relevant internal documentation as + behavior lands; retire this roadmap when its work is complete. + +Suggested acceptance cases, subject to the selected API contract: + +- Two prompt scopes resolve the same local name to their respective prompts; + a missing name never resolves from the other scope or an unqualified entry. +- Two provider profile scopes preserve a slash-containing local name and select + different profiles without changing the configured provider model value. +- Prompt shorthand and a profile override use their intended scopes, while + stored default references and omitted selections retain their meaning. +- Scoped views coexist concurrently and share backend capacity with ordinary + calls on the underlying engine. +- Existing exact-ID calls, intentional overlays, and prompt versions retain + their behavior. +- Listings and reported identities support the chosen local/full-ID round trip. +- Representative validation, inspection, execution, and smoke-test paths use + the same qualification rules without duplicating every test at every layer. + +## Open Decisions + +1. **Naming convention:** adopt the first-slash boundary, or select another + separator? What namespace syntax is needed without narrowing existing IDs? +2. **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? +3. **Exact access within scoped requests:** use the original engine for exact + selections, or provide an explicit per-reference distinction? +4. **Scope validation:** when should an empty, malformed, or currently absent + namespace produce an error? Distinguish syntax from resource existence and + do not accidentally change omitted-ID defaults. +5. **Discovery:** which listing/filtering operations are needed, how are legacy + IDs grouped, and how are local and full identities represented? +6. **Catalog adoption:** which maintained IDs, if any, should change, and what + compatibility and release plan would accompany those changes? + +Resolve these choices before treating the proposed mechanics as implementation +requirements. The central requirement is already clear: consumers select a +scope once and use local names predictably within an assembled library.