245 lines
13 KiB
Markdown
245 lines
13 KiB
Markdown
# 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.
|