649 lines
24 KiB
Markdown
649 lines
24 KiB
Markdown
# PromptKit v0.3.0 Upgrade And Local Backend Adoption
|
|
|
|
## Status
|
|
|
|
Planned.
|
|
|
|
This roadmap is an implementation specification for upgrading Notarius from
|
|
`gitea.maximumdirect.net/eric/promptkit` v0.2.0 to v0.3.0 and adopting the new
|
|
conventional local-backend helper. Implement the stages in order. Each stage
|
|
must leave its focused tests passing before the next stage begins.
|
|
|
|
The upstream release is additive. Existing endpoint-only profiles, custom
|
|
engine options used by tests, and the built-in OpenRouter backend remain
|
|
supported. The implementation must preserve those paths.
|
|
|
|
## Outcome
|
|
|
|
After all stages:
|
|
|
|
- Notarius pins PromptKit v0.3.0.
|
|
- Version 4 Notarius configuration may register one optional conventional
|
|
PromptKit `local` backend.
|
|
- A PromptKit-owned file profile may select that registration with
|
|
`backend: local`.
|
|
- The registration supplies one shared endpoint and an optional PromptKit
|
|
concurrency limit to every profile that selects it.
|
|
- CLI profile preflight and the production LLM client construct equivalent
|
|
PromptKit backend registrations.
|
|
- Run manifests and debug material continue to expose PromptKit's selected
|
|
backend ID through the existing provenance paths.
|
|
- Checkpoint identity changes when the pinned PromptKit release or configured
|
|
local endpoint changes, but not when only the local concurrency limit
|
|
changes.
|
|
- Existing configurations and endpoint-only profiles behave as before.
|
|
|
|
## Upstream Contracts
|
|
|
|
Use the v0.3.0 tag, rather than the moving `main` branch, as the implementation
|
|
contract:
|
|
|
|
- release guide:
|
|
`https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.3.0/docs/releases/v0.3.0.md`
|
|
- Go consumer guide:
|
|
`https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.3.0/docs/consumers/pkg-promptkit.md`
|
|
- profile format:
|
|
`https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.3.0/docs/formats.md`
|
|
- backend API and GoDoc:
|
|
`https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.3.0/backends.go`
|
|
|
|
The new API used by this work is:
|
|
|
|
```go
|
|
promptkit.WithBackend(
|
|
promptkit.LocalBackend(endpoint, concurrencyLimit),
|
|
)
|
|
```
|
|
|
|
`LocalBackend` creates an ordinary engine-scoped backend whose ID is
|
|
`promptkit.BackendLocal`, currently the case-sensitive string `local`. It does
|
|
not register itself, read environment variables, select a model, or add
|
|
credentials. A positive concurrency limit uses PromptKit's default waiting
|
|
capacity; zero leaves the backend unlimited inside PromptKit.
|
|
|
|
## Decisions
|
|
|
|
### Public configuration
|
|
|
|
Keep `SupportedFileConfigVersion` at 4. The new field is optional and additive:
|
|
|
|
```yaml
|
|
version: 4
|
|
|
|
promptkit:
|
|
profile_dir: ./profiles
|
|
# profile_file: ./profiles.yml
|
|
local_backend:
|
|
endpoint: http://localhost:8000/v1
|
|
concurrency_limit: 2
|
|
```
|
|
|
|
The selected PromptKit profile remains in the external PromptKit profile
|
|
source:
|
|
|
|
```yaml
|
|
id: local-summary
|
|
backend: local
|
|
model: example-model
|
|
```
|
|
|
|
`promptkit.local_backend` has these semantics:
|
|
|
|
- The entire object is optional.
|
|
- When the object is present, `endpoint` is required.
|
|
- File loading trims `endpoint`; an explicitly blank value is invalid.
|
|
- The effective endpoint must be an absolute HTTP or HTTPS URL with a host.
|
|
User information, query strings, and fragments are invalid. URL paths are
|
|
allowed.
|
|
- `concurrency_limit` is optional and defaults to zero.
|
|
- A negative concurrency limit is invalid.
|
|
- Zero means no PromptKit-local concurrency restriction. The existing
|
|
application-wide `concurrency.total_llm` scheduler remains in force.
|
|
- A positive value limits simultaneous generations for profiles selecting
|
|
`backend: local`. PromptKit owns its default queue capacity and admission
|
|
behavior.
|
|
- The local backend may coexist with either `profile_dir`, `profile_file`, or
|
|
built-in profiles. The existing mutual exclusion between `profile_dir` and
|
|
`profile_file` remains unchanged.
|
|
- No environment override is added for either local-backend field.
|
|
- The object contains no credential. A profile may continue to name its own
|
|
`api_key_env` according to the PromptKit profile format.
|
|
|
|
Use pointer presence for the nested object in both the file model and effective
|
|
configuration. This distinguishes an absent registration from a configured
|
|
registration whose concurrency limit is zero.
|
|
|
|
Add these effective configuration values in `internal/core/config/config.go`:
|
|
|
|
```go
|
|
type PromptKitConfig struct {
|
|
ProfileDir string `json:"profile_dir,omitempty"`
|
|
ProfileFile string `json:"profile_file,omitempty"`
|
|
LocalBackend *PromptKitLocalBackendConfig `json:"local_backend,omitempty"`
|
|
}
|
|
|
|
type PromptKitLocalBackendConfig struct {
|
|
Endpoint string `json:"endpoint"`
|
|
ConcurrencyLimit int `json:"concurrency_limit"`
|
|
}
|
|
```
|
|
|
|
Add a corresponding YAML file model in
|
|
`internal/core/config/file_config.go`. Use pointer fields inside the file model
|
|
where necessary to distinguish omission from an explicitly empty value:
|
|
|
|
```go
|
|
type FilePromptKitConfig struct {
|
|
ProfileDir *string `yaml:"profile_dir,omitempty"`
|
|
ProfileFile *string `yaml:"profile_file,omitempty"`
|
|
LocalBackend *FilePromptKitLocalBackendConfig `yaml:"local_backend,omitempty"`
|
|
}
|
|
|
|
type FilePromptKitLocalBackendConfig struct {
|
|
Endpoint *string `yaml:"endpoint,omitempty"`
|
|
ConcurrencyLimit *int `yaml:"concurrency_limit,omitempty"`
|
|
}
|
|
```
|
|
|
|
The existing YAML decoder's `KnownFields(true)` behavior must reject unknown
|
|
fields within `local_backend`.
|
|
|
|
### Ownership and redaction
|
|
|
|
`internal/core/config` owns parsing, normalization, structural validation,
|
|
copying, and the user-facing configuration contract. It must not import
|
|
PromptKit merely to validate the URL.
|
|
|
|
The nested effective configuration pointer must be deep-copied by
|
|
`cloneConfig`. `Config.Redacted` and effective-config summaries already begin
|
|
from that clone and should preserve the endpoint and concurrency limit. Treat
|
|
the endpoint as non-secret configuration metadata, like the existing profile
|
|
source path. Do not add any credential value to this object.
|
|
|
|
The framework LLM adapter owns conversion to `promptkit.LocalBackend` and
|
|
PromptKit engine construction. The CLI composition root maps the core
|
|
configuration type to the adapter type; the framework package must not import
|
|
`internal/core/config`.
|
|
|
|
### Adapter representation and shared option construction
|
|
|
|
Add an adapter-owned value in `internal/framework/llm`:
|
|
|
|
```go
|
|
type PromptKitLocalBackendConfig struct {
|
|
Endpoint string
|
|
ConcurrencyLimit int
|
|
}
|
|
```
|
|
|
|
Add an optional `LocalBackend *PromptKitLocalBackendConfig` field to
|
|
`PromptKitClientConfig`. `NewPromptKitClient` must:
|
|
|
|
- defensively copy the pointed-to value;
|
|
- add a `promptkit.WithBackend(promptkit.LocalBackend(...))` option when it is
|
|
present;
|
|
- add no backend option when it is absent; and
|
|
- retain the trimmed endpoint needed for checkpoint fingerprinting.
|
|
|
|
Provide this small exported helper in `internal/framework/llm`:
|
|
|
|
```go
|
|
func PromptKitLocalBackendOption(cfg PromptKitLocalBackendConfig) promptkit.Option
|
|
```
|
|
|
|
It converts the adapter local-backend value directly to
|
|
`promptkit.WithBackend(promptkit.LocalBackend(...))`. Both
|
|
`NewPromptKitClient` and the CLI's preparation-only profile validation engine
|
|
must call this helper. The helper must be a direct conversion with no defaults
|
|
or hidden environment behavior. Its purpose is to prevent preflight and
|
|
runtime registration from drifting.
|
|
|
|
The production CLI construction in `internal/cli/catalog.go` maps
|
|
`config.PromptKit.LocalBackend` into the adapter-owned value. The profile
|
|
validation path in `internal/cli/promptkit_profiles.go` performs the same
|
|
mapping and appends the shared option to its preparation-only engine.
|
|
|
|
Do not remove or reinterpret `PromptKitClientConfig.EngineOptions`. It remains
|
|
the test and internal extension seam, and those options continue to be appended
|
|
after asset and profile-source options. Ensure the local backend registration
|
|
is added exactly once.
|
|
|
|
### Scheduling and capacity
|
|
|
|
Do not change the existing Notarius scheduled client. It remains the outer,
|
|
application-wide FIFO limit. PromptKit's local backend limit remains an inner
|
|
per-engine, per-backend limit:
|
|
|
|
```text
|
|
Notarius total LLM scheduler
|
|
-> PromptKit local backend admission
|
|
-> local OpenAI-compatible endpoint
|
|
```
|
|
|
|
When the local limit is positive, the maximum active calls against the local
|
|
endpoint is effectively the smaller of `concurrency.total_llm` and
|
|
`promptkit.local_backend.concurrency_limit`. When the local limit is zero, only
|
|
the Notarius scheduler limits calls.
|
|
|
|
Do not add another retry or translate errors in a new location.
|
|
`PromptKitClient.CompleteStructured` already maps
|
|
`promptkit.ErrCapacityExceeded` to `contracts.ErrLLMCapacityExceeded`, and the
|
|
pipeline remains responsible for retry decisions.
|
|
|
|
### Checkpoint identity
|
|
|
|
Keep the existing `promptkit_profile_source` fingerprint and change its
|
|
compiled-in release marker from:
|
|
|
|
```text
|
|
promptkit:v0.2.0:builtin-profiles
|
|
```
|
|
|
|
to:
|
|
|
|
```text
|
|
promptkit:v0.3.0:builtin-profiles
|
|
```
|
|
|
|
With the current length-prefixed hashing algorithm, the no-external-profile
|
|
fingerprint becomes:
|
|
|
|
```text
|
|
sha256:5218b1dec48f5fdd46836826e0b25906c33efbdf943c5f18085b8d82467e0276
|
|
```
|
|
|
|
Add a second fingerprint only when a local backend is configured:
|
|
|
|
- name: `promptkit_local_backend_target`
|
|
- value: a SHA-256 digest over two length-prefixed parts:
|
|
1. the stable marker `notarius:promptkit-local-backend:v1`;
|
|
2. the trimmed endpoint.
|
|
|
|
Reuse the existing length-prefix helper so concatenated inputs are
|
|
unambiguous. Do not put the raw endpoint in checkpoint identity.
|
|
|
|
Do not include `concurrency_limit` in this fingerprint. The endpoint selects
|
|
the semantic execution target; the concurrency limit changes scheduling and
|
|
admission only. Return fingerprints in deterministic order: profile source
|
|
first, optional local backend target second.
|
|
|
|
No manifest schema change is needed. Successful calls already record
|
|
PromptKit's selected backend ID, so profiles using the new registration will
|
|
produce the existing optional `backend_id: "local"` provenance. Do not add the
|
|
endpoint to run manifests.
|
|
|
|
### Scope exclusions
|
|
|
|
Do not add:
|
|
|
|
- arbitrary user-defined backend IDs;
|
|
- more than one configured local endpoint;
|
|
- backend-wide API-key fields;
|
|
- backend-wide extra request parameters;
|
|
- configurable PromptKit queue capacity;
|
|
- automatic local endpoint discovery;
|
|
- environment-variable overrides for local-backend configuration;
|
|
- an implicit local backend when the object is absent;
|
|
- a default model or an in-memory local profile;
|
|
- CLI flags for local backend settings;
|
|
- changes to existing maintained example configurations;
|
|
- a configuration version bump;
|
|
- a new ADR.
|
|
|
|
Those capabilities require the full PromptKit `Backend` interface or a broader
|
|
product decision and are outside this release adoption.
|
|
|
|
## Stage 1: Pin PromptKit v0.3.0
|
|
|
|
### Changes
|
|
|
|
1. Run:
|
|
|
|
```sh
|
|
go get gitea.maximumdirect.net/eric/promptkit@v0.3.0
|
|
go mod tidy
|
|
```
|
|
|
|
2. Confirm `go.mod` directly requires exactly v0.3.0 and `go.sum` contains the
|
|
v0.3.0 module and Go module checksums with no v0.2.0 PromptKit entries.
|
|
3. Update `promptKitBuiltinProfileCatalogID` in
|
|
`internal/framework/llm/promptkit_profile_fingerprint.go`.
|
|
4. Update the exact built-in fingerprint expectation in
|
|
`internal/framework/llm/promptkit_client_test.go` to the value specified
|
|
above.
|
|
5. Do not use the new local-backend API in this stage.
|
|
|
|
### Verification
|
|
|
|
Run:
|
|
|
|
```sh
|
|
go test ./internal/framework/llm
|
|
go test ./...
|
|
go vet ./...
|
|
go build ./cmd/notarius
|
|
```
|
|
|
|
### Completion criteria
|
|
|
|
- The repository builds against PromptKit v0.3.0 without compatibility
|
|
shims.
|
|
- All pre-existing behavior passes unchanged.
|
|
- Checkpoints created under the v0.2.0 release identity are not considered
|
|
identical to v0.3.0 checkpoints.
|
|
|
|
## Stage 2: Add The Version 4 Configuration Contract
|
|
|
|
### Changes
|
|
|
|
1. Add the effective and file-model types described in the decisions above.
|
|
2. In `Config.ApplyFileConfig`:
|
|
- recognize an absent object without changing defaults;
|
|
- require a present object to contain a nonblank endpoint;
|
|
- trim the endpoint before storing it;
|
|
- default an omitted concurrency limit to zero;
|
|
- allocate a new effective nested value so the parsed file model cannot
|
|
alias the resulting `Config`.
|
|
3. Extend `validatePromptKit`:
|
|
- preserve profile directory/file mutual exclusion;
|
|
- reject an effective local backend with a blank endpoint;
|
|
- parse the trimmed endpoint with `net/url`;
|
|
- accept `http` or `https` case-insensitively;
|
|
- require `URL.IsAbs()` and a nonempty `URL.Hostname()`;
|
|
- reject URL user information;
|
|
- reject both a nonempty `URL.RawQuery` and `URL.ForceQuery`;
|
|
- reject any endpoint text containing `#`, including an empty trailing
|
|
fragment;
|
|
- allow URL paths;
|
|
- reject a negative concurrency limit.
|
|
4. Extend `cloneConfig` to deep-copy `PromptKit.LocalBackend`.
|
|
5. Make no environment-override changes.
|
|
|
|
Use contextual errors rooted at the public field names, for example:
|
|
|
|
```text
|
|
promptkit.local_backend.endpoint must not be empty when set
|
|
promptkit.local_backend.endpoint must be an absolute HTTP or HTTPS URL with a host and no user information, query, or fragment
|
|
promptkit.local_backend.concurrency_limit must not be negative
|
|
```
|
|
|
|
Exact wrapping may follow existing configuration conventions, but tests should
|
|
assert stable field context rather than whole error strings.
|
|
|
|
### Tests
|
|
|
|
Extend the current configuration contract suites rather than creating a
|
|
parallel test framework:
|
|
|
|
- `internal/core/config/file_config_contract_test.go`
|
|
- decodes the documented object;
|
|
- trims the endpoint;
|
|
- defaults omitted concurrency to zero;
|
|
- preserves an explicit positive concurrency value;
|
|
- rejects a missing or explicitly blank endpoint;
|
|
- rejects an unknown nested field;
|
|
- confirms cloning and `Redacted` preserve values without pointer aliasing;
|
|
- confirms runtime JSON uses `local_backend`, `endpoint`, and
|
|
`concurrency_limit`.
|
|
- `internal/core/config/validation_contract_test.go`
|
|
- accepts representative HTTP and HTTPS endpoints, including a path;
|
|
- rejects relative URLs, unsupported schemes, missing hosts, user
|
|
information, queries, fragments, and negative concurrency;
|
|
- confirms the object may coexist with either valid profile-source choice.
|
|
- `internal/core/config/effective_config_contract_test.go`
|
|
- confirms resolution preserves an independently owned local-backend value;
|
|
- mutating either the input or resolved copy must not mutate the other.
|
|
|
|
Avoid tests for `net/url` itself. Cover only the public categories in the
|
|
configuration contract.
|
|
|
|
### Verification
|
|
|
|
Run:
|
|
|
|
```sh
|
|
go test ./internal/core/config
|
|
go test ./...
|
|
```
|
|
|
|
### Completion criteria
|
|
|
|
- Old version 4 files load exactly as before.
|
|
- The new object is strict, validated, normalized, independently owned, and
|
|
visible through the existing safe configuration summaries.
|
|
- No runtime behavior uses the new values yet.
|
|
|
|
## Stage 3: Register The Local Backend In Preflight And Runtime
|
|
|
|
### Changes
|
|
|
|
1. Add the adapter-owned configuration value and shared PromptKit option
|
|
helper described above.
|
|
2. Extend `PromptKitClientConfig` and `NewPromptKitClient` to register the
|
|
configured backend before calling `promptkit.NewEngine`.
|
|
3. In `internal/cli/catalog.go`, map the core configuration into
|
|
`PromptKitClientConfig.LocalBackend`.
|
|
4. In `internal/cli/promptkit_profiles.go`, add the identical registration to
|
|
the preparation-only engine.
|
|
5. Preserve option ordering and existing profile-source behavior:
|
|
- mounted prompt/schema assets;
|
|
- optional profile file;
|
|
- optional local backend registration;
|
|
- caller-supplied `EngineOptions`.
|
|
6. Do not change request mapping, response decoding, selected-backend
|
|
recording, scheduler construction, or capacity-error translation.
|
|
|
|
The preflight engine must prepare a file-backed profile selecting
|
|
`backend: local` without making a provider call. If the profile selects
|
|
`local` but `promptkit.local_backend` is absent, preserve PromptKit's
|
|
profile-load failure with the existing Notarius profile-validation context; do
|
|
not silently fall back to an endpoint-only or OpenRouter profile.
|
|
|
|
### Tests
|
|
|
|
Add or extend focused behavioral tests:
|
|
|
|
- In `internal/framework/llm/promptkit_client_test.go`, configure a profile
|
|
selecting `backend: local` and prove that:
|
|
- client construction succeeds when the registration is supplied;
|
|
- a structured call reaches an `httptest.Server` at the configured endpoint;
|
|
- the returned response and recorded manifest use backend ID `local`;
|
|
- omitting the registration causes preparation/execution to fail before any
|
|
provider request.
|
|
- Add `internal/cli/promptkit_profiles_test.go` if no existing CLI test gives a
|
|
narrow home for preflight behavior:
|
|
- configured local registration permits explicit-profile validation;
|
|
- absent registration rejects the same profile with profile and backend
|
|
context;
|
|
- validation remains preparation-only and does not contact the endpoint.
|
|
- Extend an existing production composition test in
|
|
`internal/cli/production_contract_test.go` to ensure the effective
|
|
configuration reaches the production client path. Exercise the constructed
|
|
client far enough to select the local-backed profile; construction alone is
|
|
insufficient because backend membership is resolved during preparation.
|
|
|
|
Use temporary profile files and `httptest.Server`. Tests must remain offline,
|
|
deterministic, and credential-free.
|
|
|
|
Do not duplicate PromptKit's constructor-shape tests or comprehensively retest
|
|
its backend queue. Notarius owns correct configuration handoff, equivalent
|
|
preflight/runtime construction, existing provenance, and error-boundary
|
|
behavior.
|
|
|
|
### Verification
|
|
|
|
Run:
|
|
|
|
```sh
|
|
go test ./internal/framework/llm ./internal/cli
|
|
go test ./...
|
|
```
|
|
|
|
### Completion criteria
|
|
|
|
- A configured `backend: local` profile passes CLI preflight and uses the
|
|
configured endpoint at runtime.
|
|
- The same profile fails clearly when the backend is not registered.
|
|
- Endpoint-only profiles and built-in profiles continue to work.
|
|
- Existing manifest/debug backend provenance records `local` without schema
|
|
changes.
|
|
- Application-wide and PromptKit-local scheduling remain layered as designed.
|
|
|
|
## Stage 4: Add Local Backend Checkpoint Identity
|
|
|
|
### Changes
|
|
|
|
1. Store a defensive copy of the configured local endpoint on
|
|
`PromptKitClient`.
|
|
2. Add the optional `promptkit_local_backend_target` fingerprint using the
|
|
exact algorithm and marker specified above.
|
|
3. Extend `LLMCheckpointFingerprints` to return:
|
|
- the existing profile-source fingerprint in all cases;
|
|
- the local-target fingerprint second when configured.
|
|
4. Preserve defensive-copy behavior on the returned fingerprint slice.
|
|
5. Do not add concurrency, queue behavior, raw endpoint text, or credentials
|
|
to checkpoint identity.
|
|
|
|
Keep this logic with the existing PromptKit profile fingerprint implementation
|
|
or in an adjacent focused file under `internal/framework/llm`; do not move
|
|
checkpoint policy into the CLI or core configuration package.
|
|
|
|
### Tests
|
|
|
|
Extend `internal/framework/llm/promptkit_client_test.go` to prove:
|
|
|
|
- no local backend returns only the profile-source fingerprint;
|
|
- a configured local backend returns exactly two fingerprints in the required
|
|
order;
|
|
- changing only the endpoint changes the local-target fingerprint;
|
|
- changing only `concurrency_limit` leaves every fingerprint unchanged;
|
|
- neither fingerprint exposes the raw endpoint;
|
|
- mutating a returned slice does not affect a later result.
|
|
|
|
The existing scheduled-client fingerprint delegation test is sufficient
|
|
unless it assumes exactly one fingerprint. If it does, update it to verify
|
|
transparent delegation of multiple values without specializing it to
|
|
PromptKit.
|
|
|
|
### Verification
|
|
|
|
Run:
|
|
|
|
```sh
|
|
go test ./internal/framework/llm ./internal/cli
|
|
go test ./...
|
|
```
|
|
|
|
### Completion criteria
|
|
|
|
- Checkpoint reuse is invalidated by a changed PromptKit release, profile
|
|
source, or local endpoint.
|
|
- A concurrency-only operational change does not invalidate semantic
|
|
checkpoints.
|
|
- Fingerprints remain deterministic, non-secret, and available through the
|
|
scheduled-client wrapper.
|
|
|
|
## Stage 5: Publish Current Behavior And Complete Validation
|
|
|
|
Documentation outside `docs/roadmap` must describe only the implemented result,
|
|
so perform these updates after Stages 1 through 4 work.
|
|
|
|
### Documentation changes
|
|
|
|
1. `docs/integrations/pkg-promptkit.md`
|
|
- change the pin and upstream links from v0.2.0 to v0.3.0;
|
|
- add `BackendLocal`, `LocalBackend`, and `WithBackend` to the supported
|
|
boundary;
|
|
- replace the statement that production exposes no user-defined backend
|
|
registration with the narrower truth: Notarius exposes one optional
|
|
conventional `local` registration and no general backend registry;
|
|
- retain endpoint-only profile compatibility and existing ownership
|
|
boundaries.
|
|
2. `docs/config.md`
|
|
- add the exact YAML example from this roadmap;
|
|
- document the nested fields and validation rules;
|
|
- explain that a PromptKit profile selects it with `backend: local`;
|
|
- link profile-format details to the pinned PromptKit reference;
|
|
- state that omission leaves current behavior unchanged.
|
|
3. `docs/internal/configuration.md`
|
|
- mention the independently owned nested PromptKit backend configuration
|
|
and its validation boundary.
|
|
4. `docs/internal/llm.md`
|
|
- document equivalent registration in preflight and production engines;
|
|
- describe the two scheduling layers;
|
|
- describe the optional endpoint fingerprint and why concurrency is
|
|
excluded;
|
|
- retain the existing capacity-error and provenance ownership.
|
|
5. `docs/operations.md`
|
|
- explain the effective local concurrency relationship;
|
|
- state that a zero local limit leaves only the application scheduler;
|
|
- state that PromptKit owns the positive-limit waiting capacity and emits
|
|
the already-mapped capacity failure when admission is exhausted.
|
|
|
|
Do not add a complete local configuration under `examples/`. Existing examples
|
|
are maintained provider-neutral workflows and should not gain a dependency on
|
|
a local inference server. The concise `docs/config.md` fragments are the
|
|
canonical user guidance for this optional integration.
|
|
|
|
Review `README.md`, `docs/cli.md`, the JSON output contract, and architecture
|
|
policy for contradictions. Do not edit them unless the implemented behavior
|
|
made a statement inaccurate. No CLI syntax, output schema, or architectural
|
|
boundary changes are intended.
|
|
|
|
### Full verification
|
|
|
|
Run the upstream-requested ordinary and race-enabled tests plus the repository
|
|
checks:
|
|
|
|
```sh
|
|
go test ./...
|
|
go test -race ./...
|
|
go vet ./...
|
|
go build ./cmd/notarius
|
|
```
|
|
|
|
Also inspect the final diff and confirm:
|
|
|
|
- only intended module checksums changed;
|
|
- all upstream documentation links use the v0.3.0 tag;
|
|
- no raw credential or environment value was added;
|
|
- no endpoint was added to run-manifest output;
|
|
- old endpoint-only profile fixtures remain present;
|
|
- current-behavior documentation no longer says Notarius cannot register any
|
|
production backend;
|
|
- this roadmap's completed work is reflected in canonical documentation.
|
|
|
|
### Completion criteria
|
|
|
|
- All focused, repository-wide, race, vet, and build checks pass.
|
|
- The public configuration, internal behavior, integration boundary, and
|
|
operational guidance agree.
|
|
- The upgrade remains backward compatible for existing Notarius
|
|
configurations and PromptKit profiles.
|
|
- The only newly supported backend configuration is the explicit conventional
|
|
`local` registration defined by this roadmap.
|
|
|
|
## Final Acceptance Scenarios
|
|
|
|
An implementation is complete only when all scenarios below hold:
|
|
|
|
1. A current version 4 configuration with no `local_backend` loads and runs
|
|
without behavioral changes.
|
|
2. An endpoint-only PromptKit profile continues to run and omits backend ID
|
|
exactly as before.
|
|
3. A built-in OpenRouter profile continues to resolve through PromptKit's
|
|
built-in backend.
|
|
4. A file profile containing `backend: local` passes `config validate` when
|
|
the Notarius local backend is configured.
|
|
5. The same profile fails before provider execution when the registration is
|
|
absent.
|
|
6. A successful local-backed call reaches the configured endpoint and records
|
|
backend ID `local` through existing response, debug, and manifest fields.
|
|
7. The Notarius scheduler remains the application-wide ceiling, and a positive
|
|
local limit may narrow concurrency for local-backed profiles.
|
|
8. Existing capacity rejection mapping and pipeline retry ownership remain
|
|
unchanged.
|
|
9. Changing the local endpoint prevents checkpoint reuse; changing only its
|
|
concurrency limit does not.
|
|
10. Configuration summaries own their nested values and contain no credential.
|