diff --git a/docs/config.md b/docs/config.md index 7920740..9d93c46 100644 --- a/docs/config.md +++ b/docs/config.md @@ -46,7 +46,7 @@ other than **version** is optional. | Field | Type | Default | Rules | | --- | --- | --- | --- | | **version** | integer | none | Required; must be 4. | -| **promptkit** | object | none | Profile source configuration. | +| **promptkit** | object | none | Profile source and optional local-backend configuration. | | **pipelines** | map | empty | Maps pipeline IDs to pipeline definitions. | | **concurrency** | object | see below | Global LLM and extraction limits. | | **output** | object | see below | Published output settings. | @@ -71,27 +71,58 @@ per-user root. An explicit empty output or debug directory is invalid. ## PromptKit Profiles -The optional **promptkit** object selects one source of profile definitions: +The optional **promptkit** object selects one source of profile definitions and +may register one conventional local OpenAI-compatible backend: ~~~yaml version: 4 + promptkit: - profile_dir: /path/to/profiles - # profile_file: /path/to/profiles.yml + profile_dir: ./profiles + # profile_file: ./profiles.yml + local_backend: + endpoint: http://localhost:8000/v1 + concurrency_limit: 2 ~~~ | Field | Type | Rules | | --- | --- | --- | | **profile_dir** | string | Non-empty directory containing profile files. | | **profile_file** | string | Non-empty profile file. | +| **local_backend** | object | Optional registration for the conventional PromptKit backend ID **local**. | +| **local_backend.endpoint** | string | Required when **local_backend** is present; absolute HTTP or HTTPS URL with a host. | +| **local_backend.concurrency_limit** | integer | Optional non-negative limit; defaults to 0. | Set at most one of these fields. Profile IDs used by a binding must be available from the selected PromptKit profile source when the pipeline is resolved. -Keep credentials out of this file: configure a profile to read its credential -from an environment variable, then set that environment variable only in the -run environment. PromptKit owns the profile-file format; see the -[PromptKit upstream boundary](integrations/pkg-promptkit.md) for the pinned -package and canonical format reference. +The optional local registration may coexist with either profile source or with +PromptKit's built-in profiles. + +When **local_backend** is present, its endpoint is trimmed and must use HTTP or +HTTPS case-insensitively, be absolute, and have a non-empty host. URL paths are +allowed. User information, queries, and fragments are rejected. A zero +**concurrency_limit** leaves the local backend unrestricted inside PromptKit; +a positive value limits simultaneous local generations. The application-wide +**concurrency.total_llm** limit still applies in both cases. Neither local +backend field has an environment override. Omitting **local_backend** registers +nothing and preserves existing built-in and endpoint-only profile behavior. + +A file-backed PromptKit profile selects the registration by its case-sensitive +backend ID: + +~~~yaml +id: local-summary +backend: local +model: example-model +~~~ + +Keep credentials out of the local-backend object. A PromptKit profile may name +its credential environment variable through `api_key_env`; set that variable +only in the run environment. PromptKit owns the +[pinned profile-file format](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.3.0/docs/formats.md). +The [PromptKit upstream boundary](integrations/pkg-promptkit.md) identifies the +supported package API, and [Operations](operations.md#operational-limits) +describes the effective concurrency layers. ## Migrating Version 3 Configuration diff --git a/docs/integrations/pkg-promptkit.md b/docs/integrations/pkg-promptkit.md index 23647d0..21193b3 100644 --- a/docs/integrations/pkg-promptkit.md +++ b/docs/integrations/pkg-promptkit.md @@ -1,11 +1,11 @@ # PromptKit Integration Notarius pins -[`gitea.maximumdirect.net/eric/promptkit` v0.2.0](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.2.0) +[`gitea.maximumdirect.net/eric/promptkit` v0.3.0](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.3.0) as its in-process prompt engine. The upstream -[Go package consumer guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.2.0/docs/consumers/pkg-promptkit.md) +[Go package consumer guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.3.0/docs/consumers/pkg-promptkit.md) owns the public engine API, and the upstream -[format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.2.0/docs/formats.md) +[format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.3.0/docs/formats.md) owns prompt, profile, and schema file contracts. ## Supported Boundary @@ -18,10 +18,16 @@ Notarius relies on the root `promptkit` package to: a direct session ID, prompt identity, and profile selection; - return rendered debug material, validated structured output, selected profile, backend, effective model metadata, and token usage; +- register the optional conventional `local` backend through `BackendLocal`, + `LocalBackend`, and `WithBackend`; - distinguish structured-output validation failure from execution failure; and - identify a missing explicit profile through `ErrProfileNotFound` and backend admission exhaustion through `ErrCapacityExceeded`. +The pinned +[`BackendLocal`, `LocalBackend`, and `WithBackend` API](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.3.0/backends.go) +owns the registration and backend-capacity contract. + Notarius does not use PromptKit's optional `ArtifactReader`. It materializes source and reference content itself and supplies owned inline artifacts at the adapter boundary. It also retains responsibility for pipeline retries, @@ -38,8 +44,9 @@ Notarius records PromptKit's selected backend ID and effective reasoning setting as optional run-manifest provenance. Endpoint-only profiles have no backend ID. Debug prompt material also retains the selected backend ID and PromptKit's stable lower-case `effective_model_params` JSON, which may include -`backend_id`. Notarius production configuration does not expose user-defined -PromptKit backend registration. +`backend_id`. Notarius production configuration exposes one optional +conventional `local` registration. It does not expose a general user-defined +PromptKit backend registry. Endpoint-only profiles remain supported unchanged. Notarius retains its application-wide scheduled client around the PromptKit adapter. PromptKit may apply a narrower limit for the selected backend; @@ -55,7 +62,8 @@ module assets, maps its transport-neutral completion contract, prepares and executes requests, validates output, records provenance, captures debug material, redacts errors, and preserves timeout ownership. [Configuration](../config.md#promptkit-profiles) defines how a Notarius -configuration selects one PromptKit profile source. +configuration selects one PromptKit profile source and optionally registers +the conventional local backend. PromptKit API or format changes outside this boundary are not implicitly supported. Updating the pinned version requires reviewing the adapter and diff --git a/docs/internal/configuration.md b/docs/internal/configuration.md index 097a048..eb955d4 100644 --- a/docs/internal/configuration.md +++ b/docs/internal/configuration.md @@ -39,14 +39,20 @@ This establishes the public precedence order without giving environment input a second file schema. Loading and application reject malformed YAML, unsupported file versions, unknown fields, invalid values, and identifiers that are empty or collide after whitespace normalization. The file application also makes the -effective extraction-worker default follow the effective LLM limit. +effective extraction-worker default follow the effective LLM limit. A present +PromptKit local-backend object requires and trims its endpoint, defaults its +omitted concurrency limit to zero, and is copied so the parsed file model +cannot alias the populated **Config**. **Config.Validate** checks configuration-only invariants before resolution. It rejects incompatible profile sources, invalid state-surface values, unsupported concurrency settings, malformed bindings and references, invalid retries, and -invalid pipeline, step, or lane structure. Its errors retain the closest known -pipeline, lane, and binding context. It deliberately does not require modules -to be registered: that requires a catalog and belongs to resolution. +invalid pipeline, step, or lane structure. PromptKit local-backend validation +accepts only an absolute HTTP or HTTPS endpoint with a host and no user +information, query, or fragment, and rejects a negative local concurrency +limit. Its errors retain the closest known pipeline, lane, and binding context. +It deliberately does not require modules to be registered: that requires a +catalog and belongs to resolution. The exact user-selectable values and validation rules are defined in [Configuration](../config.md). Keep additions to the file model, an @@ -71,7 +77,8 @@ options, and returns the fixed ordered pipeline shape. The resulting changes, a clone of the input configuration, and the resolved pipeline. Callers may therefore retain or modify their input slices and maps without changing the resolved result, and later consumers cannot mutate the original -configuration through the effective value. +configuration through the effective value. This ownership includes the nested +PromptKit local-backend value. Resolution failures stop before module construction and source parsing. They include an error path for an unconfigured pipeline, missing module, missing @@ -94,9 +101,12 @@ Configuration summaries must use **Redacted**, **RedactedSummaryPayload**, or Those methods copy every binding and nested option container, replace values whose key is credential-shaped with **[REDACTED]**, and omit materialized reference content while retaining safe binding and reference provenance. The -payload must not alias the source configuration or resolved pipeline. This -redaction is deliberately narrow: it protects configuration summaries and does -not authorize recording arbitrary environment values or provider requests. +payload must not alias the source configuration or resolved pipeline. +PromptKit's local endpoint and concurrency limit are preserved as non-secret +configuration metadata in the independently owned summary; the object contains +no credential value. This redaction is deliberately narrow: it protects +configuration summaries and does not authorize recording arbitrary environment +values or provider requests. ## Invariants To Preserve diff --git a/docs/internal/llm.md b/docs/internal/llm.md index 72c7dde..1af5b62 100644 --- a/docs/internal/llm.md +++ b/docs/internal/llm.md @@ -56,6 +56,13 @@ distinct and deterministically ordered. Endpoint-only profiles retain an empty backend ID, which the published JSON omits. Successful completion responses and recorded profile manifests identify the adapter provider as `promptkit`. +The CLI's preparation-only engine and the production adapter use the same +conversion helper to register the optional conventional `local` backend. +Preflight therefore resolves the same backend membership as runtime without +performing generation. When the registration is absent, a profile selecting +`backend: local` fails preparation instead of falling back to a built-in or +endpoint-only target. + Before execution, the adapter also contributes a non-secret checkpoint fingerprint for the effective PromptKit profile source. It combines the identity of PromptKit's compiled-in profile catalog with a deterministic digest @@ -65,7 +72,11 @@ paths. It covers both explicit binding profiles and prompt-selected defaults, so changing a model or other profile setting cannot reuse checkpoints created under the prior profile source. This cache identity is independent of durable profile provenance: run manifests continue to list only profiles actually -observed during LLM calls. +observed during LLM calls. When the local backend is registered, a second +fingerprint hashes its trimmed endpoint behind a stable marker. Changing that +semantic execution target invalidates checkpoint reuse. The raw endpoint is not +stored in checkpoint identity, and the local concurrency limit is excluded +because it changes scheduling rather than execution semantics. ## Shared Provider-Call Limit @@ -85,8 +96,10 @@ PromptKit applies a second, independent admission limit when the selected profile names a limited backend. It sits beneath the Notarius scheduled client, so it may narrow but cannot expand the application-wide limit. Built-in OpenRouter profiles select PromptKit's reserved backend and its upstream -capacity policy. Endpoint-only profiles do not select a PromptKit backend and -remain limited only by the Notarius scheduler. +capacity policy. A positive configured local-backend limit bounds active local +generations inside PromptKit; zero leaves that backend unlimited there. +Endpoint-only profiles do not select a PromptKit backend and remain limited +only by the Notarius scheduler. ## Prompt And Schema Assets diff --git a/docs/operations.md b/docs/operations.md index 4709378..ba740f9 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -118,8 +118,10 @@ disabled. Without **--resume**, a recording-enabled run executes normally and does not load checkpoint state. Compatibility includes the resolved pipeline, input, selected lanes, runtime overrides, reference provenance, LLM-profile provenance, the effective PromptKit profile-source fingerprint, and -prepared-component fingerprints. Changing profile content causes a cold miss -even when its profile ID is unchanged. A changed identity produces a cold miss; +prepared-component fingerprints. When a local PromptKit backend is configured, +compatibility also includes a non-secret fingerprint of its endpoint. Changing +profile content or the local endpoint causes a cold miss; changing only the +local concurrency limit does not. A changed identity produces a cold miss; Notarius does not migrate, rewrite, or delete older checkpoint directories. Reasoning-effort inheritance, replacement, and explicit clearing are distinct runtime identities, so checkpoints created under one state are not reused by @@ -217,7 +219,7 @@ Provider execution settings and the generation timeout come from the selected PromptKit profile. The invocation-only **--reasoning-effort** and **--clear-reasoning-effort** controls may replace or clear that profile setting for all LLM-backed calls in one run without changing the profile. PromptKit -v0.2.0 does not add a provider retry loop. Notarius binding retries rerun the +v0.3.0 does not add a provider retry loop. Notarius binding retries rerun the complete module operation and validation chain as defined by [module bindings](config.md#module-bindings-and-validators). @@ -234,13 +236,19 @@ and validators. PromptKit may impose a narrower admission limit for the selected backend. The effective active-generation bound is the intersection of both limits and can therefore be lower than **total_llm**. Built-in OpenRouter profiles use PromptKit's upstream backend limit; endpoint-only profiles have no -PromptKit backend limit and remain bounded by Notarius. +PromptKit backend limit and remain bounded by Notarius. For the configured +local backend, a zero **concurrency_limit** leaves only the Notarius scheduler +as a call limit. A positive value makes the effective active local-generation +bound the smaller of **total_llm** and that local limit. -When a PromptKit backend has admitted all active and queued work, a new call -fails as capacity exhaustion before generation. The adapter does not retry it. -The calling stage's configured retry policy applies normally, and the run fails -if those attempts are exhausted. Caller cancellation remains authoritative. -Configuration contracts are documented under +For a positive local limit, PromptKit owns its default waiting capacity and +admission behavior. When a PromptKit backend has admitted all active and queued +work, a new call fails as capacity exhaustion before generation. The adapter +maps that failure to Notarius's existing provider-neutral capacity error and +does not retry it. The calling stage's configured retry policy applies +normally, and the run fails if those attempts are exhausted. Caller +cancellation remains authoritative. Configuration contracts are documented +under [PromptKit profiles](config.md#promptkit-profiles) and [concurrency](config.md#concurrency-output-cache-and-debug). Extract-worker limits and actual provider-call limits are independent. Notarius writes local filesystem state only; remote storage, archival, and retention automation are