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
Status: feature roadmap; not implemented. The reserved-slash naming convention
and reference-resolution rules are accepted target behavior. The public scope
API, discovery surface, and migration details remain open as identified below.
Status: feature roadmap; not implemented. The reserved-slash naming convention,
reference-resolution rules, and decisions 1–3 (scope shape, validation, and
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
@@ -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
below.
## Proposed Consumer Scope
## Accepted 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:
Provide a lightweight, immutable view over an existing engine with independent
prompt, profile, and backend scopes. The following sketch illustrates the
accepted shape; method/type names and final signatures remain provisional:
```go
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.
```
This sketch follows the recommendation in open decision 1; these declarations
do not exist yet.
This sketch follows [decision 1](#1-public-scope-shape-accepted); 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
@@ -146,29 +148,20 @@ applying a scope. No escape syntax for unqualified IDs is introduced here.
### 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. 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.
A consumer can select prompt shorthand under `weatherreporter` and profile
shorthand under `openrouter` in the same request. Each resource type has an
independent scope, as defined in [decision 1](#1-public-scope-shape-accepted).
A prompt's configured default profile needs no caller profile scope because
the stored reference is already exact. Scope syntax and existence handling are
defined in [decision 2](#2-scope-validation-accepted).
## 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.
Namespace enumeration and filtering are integrated into PromptKit's listing
APIs. Consumers select a filter and receive matching full resource identities;
they do not need to fetch all resources and filter them themselves. Defaults,
explicit filter overrides, and result semantics are defined in
[decision 3](#3-discovery-accepted).
Derive namespace membership from the qualified identifier's namespace component:
`weather` must not include `weatherreporter/...`. Nested slash-separated
@@ -232,19 +225,19 @@ if a concrete consumer need emerges.
## Delivery Outline
1. Settle the open API decisions below and audit existing identifier usage
against the accepted grammar. Record explicit mappings and coordinated
migration work.
1. Resolve decision 4 and audit existing identifier usage against the accepted
grammar. Record explicit mappings and coordinated migration work. Finalize
Go names and option types that express the accepted decisions 1–3.
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.
3. Add integrated namespace filtering 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.
Acceptance cases for the settled rules, with scope/discovery details subject to
the selected API contract:
Acceptance cases for the settled rules; migration-specific cases follow the
eventual decision 4:
- 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.
@@ -259,21 +252,32 @@ the selected API contract:
stored default references and omitted selections retain their meaning.
- Scoped views coexist concurrently and share backend capacity with ordinary
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
versions retain their behavior. Migrated catalog references resolve to their
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
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
contract. Alternatives preserve the settled naming and resolution rules.
Decisions 1–3 are accepted; their alternatives are retained as considered but
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
namespace fields and returns a scoped view or an error. The illustrative
`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
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
**Considered alternative, not selected: 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
**Considered alternative, not selected: 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
### 2. Scope Validation (Accepted)
**Recommended: validate syntax when creating the view; resolve existence when
an operation selects a resource.** In the recommended scope value, the empty
**Accepted: validate syntax when creating the view; resolve existence when
an operation selects a resource.** In the 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
@@ -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
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
**Considered alternative, not selected: 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
@@ -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
an accidental consequence of implementing scope creation.
### 3. Discovery
### 3. Discovery (Accepted)
**Recommended: namespace enumeration and resource listings that retain full
IDs.** Enumerate the distinct named namespaces present in final effective
**Accepted: integrated namespace filtering and full-identity results.**
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.
as part of this work if needed. Namespace filtering is an explicit option in
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
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.
| Selection | Listing behavior |
| --- | --- |
| No explicit filter on the engine | All namespaces, including unqualified resources |
| No explicit filter on a scoped view | The selected scope for that resource type; all resources of that type if no scope is selected |
| Explicit named namespace | Resources in exactly that namespace |
| Explicit unqualified-only filter | Resources whose IDs have no namespace |
| Explicit all-namespaces filter | All resources of that type, including unqualified resources |
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.
An explicit filter replaces the view's default for the current listing; it
does not intersect with that default or mutate the view. A named namespace
filter uses the namespace syntax rules in decision 2. A well-formed namespace
with no matching resources returns an empty listing. Represent default, named,
unqualified-only, and all-namespaces selections distinctly in the API; do not
overload an empty string to mean several of them.
**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
Return full IDs, retaining prompt versions as separate identity fields. Do not
invent a named namespace such as `default` for unqualified resources. Namespace
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,
and one inventory operation can cover all resource kinds. It creates another
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
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
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.
The delimiter, two-component qualified grammar, syntax-based resolution, and
acceptance of the required breaking migration are settled. Resolve the remaining
API and delivery choices around that foundation: consumers select a scope once
and use local or explicitly qualified names predictably within an assembled
library.
decisions 1–3 are settled. The need for a breaking migration is accepted, but
decision 4's migration strategy, exact mappings, and release coordination remain
open for further discussion.