Record accepted namespace scope and filtering decisions

This commit is contained in:
2026-10-13 22:47:21 +00:00
parent cf997c2034
commit 1516631a30

View File

@@ -1,8 +1,10 @@
# Namespaces And Scoped Resource Lookup # Namespaces And Scoped Resource Lookup
Status: feature roadmap; not implemented. The reserved-slash naming convention Status: feature roadmap; not implemented. The reserved-slash naming convention,
and reference-resolution rules are accepted target behavior. The public scope reference-resolution rules, and decisions 1–3 (scope shape, validation, and
API, discovery surface, and migration details remain open as identified below. integrated discovery filtering) are accepted target behavior. Decision 4,
catalog migration, remains open. Exact Go names and option types remain delivery
details within the accepted semantics.
## Purpose ## Purpose
@@ -81,11 +83,11 @@ those outside the new grammar require migration. This intentional format break
is accepted in favor of unambiguous resolution; the migration work is described is accepted in favor of unambiguous resolution; the migration work is described
below. below.
## Proposed Consumer Scope ## Accepted Consumer Scope
Prefer a lightweight, immutable view over an existing engine. The following Provide a lightweight, immutable view over an existing engine with independent
sketch illustrates the consumer experience only; it does not settle a method prompt, profile, and backend scopes. The following sketch illustrates the
name, return type, error behavior, or final signature: accepted shape; method/type names and final signatures remain provisional:
```go ```go
weather, err := engine.WithNamespaces(Namespaces{ weather, err := engine.WithNamespaces(Namespaces{
@@ -95,8 +97,8 @@ weather, err := engine.WithNamespaces(Namespaces{
// Handle err, then use local prompt and profile names through weather. // Handle err, then use local prompt and profile names through weather.
``` ```
This sketch follows the recommendation in open decision 1; these declarations This sketch follows [decision 1](#1-public-scope-shape-accepted); these
do not exist yet. declarations do not exist yet.
The view would share the engine's captured configuration, clients, and execution The view would share the engine's captured configuration, clients, and execution
machinery. Selecting a namespace would not rebuild the engine or duplicate its machinery. Selecting a namespace would not rebuild the engine or duplicate its
@@ -146,29 +148,20 @@ applying a scope. No escape syntax for unqualified IDs is introduced here.
### Separate Resource Scopes ### Separate Resource Scopes
A consumer may want prompt shorthand under `weatherreporter` and profile A consumer can select prompt shorthand under `weatherreporter` and profile
shorthand under `openrouter` in the same request. Evaluate independently shorthand under `openrouter` in the same request. Each resource type has an
selectable prompt, profile, and backend scopes instead of assuming one namespace independent scope, as defined in [decision 1](#1-public-scope-shape-accepted).
must apply to every field. A prompt's configured default profile needs no caller A prompt's configured default profile needs no caller profile scope because
profile scope because the stored reference is already exact. the stored reference is already exact. Scope syntax and existence handling are
defined in [decision 2](#2-scope-validation-accepted).
Independent scopes are recommended where the consumer needs shorthand, but the
scope options and the meaning of a convenience `InNamespace` operation are
still open. Define which scopes apply to unqualified names in each request
field; qualified references always bypass them. Include any directly supplied
backend selection in this decision.
## Discovery And Collection Organization ## Discovery And Collection Organization
Namespace-aware discovery is supporting work: consumers should be able to Namespace enumeration and filtering are integrated into PromptKit's listing
identify available namespaces and list their resources without each application APIs. Consumers select a filter and receive matching full resource identities;
inventing parsing and filtering rules. Keep this proportionate to the primary they do not need to fetch all resources and filter them themselves. Defaults,
scoped-lookup feature. explicit filter overrides, and result semantics are defined in
[decision 3](#3-discovery-accepted).
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.
Derive namespace membership from the qualified identifier's namespace component: Derive namespace membership from the qualified identifier's namespace component:
`weather` must not include `weatherreporter/...`. Nested slash-separated `weather` must not include `weatherreporter/...`. Nested slash-separated
@@ -232,19 +225,19 @@ if a concrete consumer need emerges.
## Delivery Outline ## Delivery Outline
1. Settle the open API decisions below and audit existing identifier usage 1. Resolve decision 4 and audit existing identifier usage against the accepted
against the accepted grammar. Record explicit mappings and coordinated grammar. Record explicit mappings and coordinated migration work. Finalize
migration work. Go names and option types that express the accepted decisions 1–3.
2. Implement the smallest public scope surface with shared name qualification 2. Implement the smallest public scope surface with shared name qualification
and existing engine collaborators. Cover supported operations consistently. and existing engine collaborators. Cover supported operations consistently.
3. Add the selected discovery behavior and representative consumer examples. 3. Add integrated namespace filtering and representative consumer examples.
4. Verify compatibility and scoped resolution through focused offline tests, 4. Verify compatibility and scoped resolution through focused offline tests,
following the [testing policy](../policy/testing.md). Update GoDoc, the following the [testing policy](../policy/testing.md). Update GoDoc, the
format reference, consumer guide, and relevant internal documentation as format reference, consumer guide, and relevant internal documentation as
behavior lands; retire this roadmap when its work is complete. behavior lands; retire this roadmap when its work is complete.
Acceptance cases for the settled rules, with scope/discovery details subject to Acceptance cases for the settled rules; migration-specific cases follow the
the selected API contract: eventual decision 4:
- Two prompt scopes resolve the same local name to their respective prompts; - 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. a missing name never resolves from the other scope or an unqualified entry.
@@ -259,21 +252,32 @@ the selected API contract:
stored default references and omitted selections retain their meaning. stored default references and omitted selections retain their meaning.
- Scoped views coexist concurrently and share backend capacity with ordinary - Scoped views coexist concurrently and share backend capacity with ordinary
calls on the underlying engine. calls on the underlying engine.
- Scope creation rejects invalid syntax, accepts well-formed absent namespaces,
and treats empty scope fields as no scope. Missing resources fail at lookup;
qualified references remain usable even when the default namespace is absent.
- Listing without an explicit filter uses the resource's view scope, or lists
all resources when no scope is selected. Explicit named, unqualified-only,
and all-namespaces filters override that default for the current listing only.
- A valid namespace with no matches produces an empty listing. Namespace
filtering respects resource type and exact namespace boundaries.
- Existing exact-ID calls using valid IDs, intentional overlays, and prompt - Existing exact-ID calls using valid IDs, intentional overlays, and prompt
versions retain their behavior. Migrated catalog references resolve to their versions retain their behavior. Migrated catalog references resolve to their
intended resources without collisions. intended resources without collisions.
- Listings and reported identities support the chosen local/full-ID round trip. - Listings preserve full IDs and separate prompt versions. Qualified results
round-trip through either engine or view; unqualified results round-trip
through the engine without a corresponding scope.
- Representative validation, inspection, execution, and smoke-test paths use - Representative validation, inspection, execution, and smoke-test paths use
the same qualification rules without duplicating every test at every layer. the same qualification rules without duplicating every test at every layer.
## Open Decisions And Recommendations ## Decisions And Remaining Recommendation
Each recommendation below is a proposal for the next decision, not an accepted Decisions 1–3 are accepted; their alternatives are retained as considered but
contract. Alternatives preserve the settled naming and resolution rules. not selected. Decision 4 remains open, with its recommendation and alternative
unchanged for further discussion.
### 1. Public Scope Shape ### 1. Public Scope Shape (Accepted)
**Recommended: an immutable view with independent resource scopes.** Provide one **Accepted: an immutable view with independent resource scopes.** Provide one
engine operation that accepts a small value with prompt, profile, and backend engine operation that accepts a small value with prompt, profile, and backend
namespace fields and returns a scoped view or an error. The illustrative namespace fields and returns a scoped view or an error. The illustrative
`WithNamespaces` and `Namespaces` names above are provisional. Empty fields mean `WithNamespaces` and `Namespaces` names above are provisional. Empty fields mean
@@ -295,27 +299,28 @@ 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 exactly which resource types it affects. A convenience operation can follow if
that repetition is a demonstrated burden. that repetition is a demonstrated burden.
**Alternative: one namespace per immutable view, applied to all resource **Considered alternative, not selected: one namespace per immutable view,
types.** A one-string operation would scope every unqualified prompt, profile, applied to all resource types.** A one-string operation would scope every
and backend selection; callers would use qualified references for resources in unqualified prompt, profile, and backend selection; callers would use qualified
other namespaces. This is smaller and reads naturally for self-contained 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 application collections. It is less convenient when prompts and profiles
habitually come from different namespaces, because profile overrides would habitually come from different namespaces, because profile overrides would
repeatedly need qualification. Prefer it if consumers primarily use prompts' repeatedly need qualification. Prefer it if consumers primarily use prompts'
configured defaults and rarely select profiles themselves. configured defaults and rarely select profiles themselves.
**Alternative: explicit scope values supplied per operation.** Add scope to **Considered alternative, not selected: explicit scope values supplied per
request values and appropriate inspection/listing options instead of returning operation.** Add scope to request values and appropriate inspection/listing
a view. This makes every invocation self-contained and suits applications that 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 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 sites and API shapes, and consumers would need their own reusable wrapper to
achieve the requested select-once experience. The immutable view is therefore achieve the requested select-once experience. The immutable view is therefore
the better default for the use case discussed so far. the better default for the use case discussed so far.
### 2. Scope Validation ### 2. Scope Validation (Accepted)
**Recommended: validate syntax when creating the view; resolve existence when **Accepted: validate syntax when creating the view; resolve existence when
an operation selects a resource.** In the recommended scope value, the empty an operation selects a resource.** In the scope value, the empty
string means no scope. Reject a nonempty namespace containing `/` or consisting string means no scope. Reject a nonempty namespace containing `/` or consisting
only of whitespace. Otherwise preserve its exact spelling, with no trimming, only of whitespace. Otherwise preserve its exact spelling, with no trimming,
case folding, or additional character whitelist. This distinguishes omission case folding, or additional character whitelist. This distinguishes omission
@@ -334,9 +339,9 @@ successful scope construction as validation of a prompt or execution profile.
The tradeoff is that a misspelled but syntactically valid namespace is detected The tradeoff is that a misspelled but syntactically valid namespace is detected
only when listed or used, rather than during view construction. only when listed or used, rather than during view construction.
**Alternative: require each selected namespace to have resources of its **Considered alternative, not selected: require each selected namespace to have
corresponding type when creating the view.** For an immutable assembled engine, resources of its corresponding type when creating the view.** For an immutable
this can catch spelling mistakes immediately and gives startup checks useful assembled engine, this can catch spelling mistakes immediately and gives startup checks useful
feedback without attempting execution. However, it rejects empty optional feedback without attempting execution. However, it rejects empty optional
collections and a view intended to use qualified references outside its default collections and a view intended to use qualified references outside its default
namespace. A namespace having one member also does not establish that the namespace. A namespace having one member also does not establish that the
@@ -344,36 +349,54 @@ particular required prompt/profile exists. Prefer this approach only if eager
inventory validation is itself an intended consumer contract; it should not be inventory validation is itself an intended consumer contract; it should not be
an accidental consequence of implementing scope creation. an accidental consequence of implementing scope creation.
### 3. Discovery ### 3. Discovery (Accepted)
**Recommended: namespace enumeration and resource listings that retain full **Accepted: integrated namespace filtering and full-identity results.**
IDs.** Enumerate the distinct named namespaces present in final effective Enumerate the distinct named namespaces present in final effective
prompts, profiles, and backends. Allow filtering that enumeration by resource prompts, profiles, and backends. Allow filtering that enumeration by resource
type so a prompt picker need not show profile-only namespaces. Provide scoped type so a prompt picker need not show profile-only namespaces. Provide scoped
listings for the supported resource types, adding a backend inventory surface listings for the supported resource types, adding a backend inventory surface
as part of this work if needed. Keep the existing unscoped listing signatures as part of this work if needed. Namespace filtering is an explicit option in
and their all-resource behavior. the library listing API, not a consumer-side filtering helper. Preserve existing
unfiltered engine calls and their result contracts; the exact Go option shape
remains to be specified.
A scoped listing filters by the selected scope for that resource type and | Selection | Listing behavior |
returns full IDs, retaining prompt versions as separate identity fields. | --- | --- |
Without a scope, it lists all resources of that type. Unqualified resources | No explicit filter on the engine | All namespaces, including unqualified resources |
remain in unscoped listings; provide an explicit unqualified-only listing filter | No explicit filter on a scoped view | The selected scope for that resource type; all resources of that type if no scope is selected |
so callers can distinguish that group from all namespaces. Do not invent a | Explicit named namespace | Resources in exactly that namespace |
named namespace such as `default` for those IDs. Namespace enumeration excludes | Explicit unqualified-only filter | Resources whose IDs have no namespace |
that unnamed group. Use deterministic ordering consistent with existing listing | Explicit all-namespaces filter | All resources of that type, including unqualified resources |
contracts.
Full IDs can be passed unchanged to either scoped or unscoped operations, which An explicit filter replaces the view's default for the current listing; it
avoids double qualification and preserves identity in logs and user interfaces. does not intersect with that default or mutate the view. A named namespace
A small public name-splitting helper can supply namespace/local components for filter uses the namespace syntax rules in decision 2. A well-formed namespace
display without requiring applications to duplicate parsing rules. This keeps with no matching resources returns an empty listing. Represent default, named,
existing identity shapes useful and avoids introducing collection metadata just unqualified-only, and all-namespaces selections distinctly in the API; do not
to support filtering. The tradeoff is that consumers wanting separate display overload an empty string to mean several of them.
fields perform that explicit decomposition.
**Alternative: add a richer inventory API returning full ID, namespace, local Return full IDs, retaining prompt versions as separate identity fields. Do not
name, resource type, and prompt version where applicable.** Preserve existing invent a named namespace such as `default` for unqualified resources. Namespace
list methods and expose the structured form separately. This is attractive for enumeration excludes that unnamed group. Use deterministic ordering consistent
with existing listing contracts.
Qualified result IDs can be passed unchanged to either scoped or unscoped
operations. Unqualified IDs remain literal unqualified identities: when an
explicit all-namespaces or unqualified-only filter exposes one through a scoped
view, use the original engine or a view without that resource scope to select
it exactly. A listing filter does not change subsequent execution scope. This
preserves the accepted lookup rules without introducing an escape syntax.
Integrated filtering gives consumers a direct way to discover the desired
resources, while full identities keep logs and subsequent selections
unambiguous. Namespace/local-name display decomposition is separate from
filtering; a public splitting helper is not required by this decision.
**Considered alternative, not selected: 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, Scriptorium-style library browsers: grouping and display require no parsing,
and one inventory operation can cover all resource kinds. It creates another and one inventory operation can cover all resource kinds. It creates another
public representation and overlaps existing listing APIs, so its value should public representation and overlaps existing listing APIs, so its value should
@@ -381,7 +404,7 @@ justify that maintenance. Prefer it if downstream clients routinely need a
combined catalog view rather than a resource picker or namespace filter. In combined catalog view rather than a resource picker or namespace filter. In
either approach, the full ID remains the authoritative selection value. either approach, the full ID remains the authoritative selection value.
### 4. Catalog Migration ### 4. Catalog Migration (Open)
**Recommended: coordinate the grammar change with adoption of provider **Recommended: coordinate the grammar change with adoption of provider
namespaces for ordinary maintained catalog profiles.** Use provider namespaces namespaces for ordinary maintained catalog profiles.** Use provider namespaces
@@ -427,7 +450,6 @@ it if the audit reveals that broad catalog renaming would impose substantial
downstream disruption relative to current demand. downstream disruption relative to current demand.
The delimiter, two-component qualified grammar, syntax-based resolution, and The delimiter, two-component qualified grammar, syntax-based resolution, and
acceptance of the required breaking migration are settled. Resolve the remaining decisions 1–3 are settled. The need for a breaking migration is accepted, but
API and delivery choices around that foundation: consumers select a scope once decision 4's migration strategy, exact mappings, and release coordination remain
and use local or explicitly qualified names predictably within an assembled open for further discussion.
library.