Document the v0.2.0 upgrade path
This commit is contained in:
@@ -31,6 +31,11 @@ Contributors should start with the [development guide](docs/development.md).
|
|||||||
The [architecture policy](docs/policy/architecture.md) defines the library
|
The [architecture policy](docs/policy/architecture.md) defines the library
|
||||||
boundary and constraints that framework work must preserve.
|
boundary and constraints that framework work must preserve.
|
||||||
|
|
||||||
|
## Release Guidance
|
||||||
|
|
||||||
|
Consumers moving from `v0.1.0` to `v0.2.0` should read the
|
||||||
|
[v0.2.0 changelog and migration guide](docs/releases/v0.2.0.md).
|
||||||
|
|
||||||
## Related Project
|
## Related Project
|
||||||
|
|
||||||
[Scriptorium](https://gitea.maximumdirect.net/eric/scriptorium) is the CLI and
|
[Scriptorium](https://gitea.maximumdirect.net/eric/scriptorium) is the CLI and
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ mechanisms, not secret values.
|
|||||||
| Framework file formats | `docs/formats.md` | Prompt-definition and profile YAML fields, schema references, defaults, validation modes, built-in profiles, credentials, and file-to-request precedence. | Exported Go declarations, outbound wire behavior, internal parsing mechanics, and application configuration. |
|
| Framework file formats | `docs/formats.md` | Prompt-definition and profile YAML fields, schema references, defaults, validation modes, built-in profiles, credentials, and file-to-request precedence. | Exported Go declarations, outbound wire behavior, internal parsing mechanics, and application configuration. |
|
||||||
| Consumer guidance | `docs/consumers/`, when consumer workflows require dedicated guidance | Task-oriented use of implemented public APIs, minimal examples, and consumer responsibilities. | Exact exported declarations and internal mechanics. |
|
| Consumer guidance | `docs/consumers/`, when consumer workflows require dedicated guidance | Task-oriented use of implemented public APIs, minimal examples, and consumer responsibilities. | Exact exported declarations and internal mechanics. |
|
||||||
| Durable integration contracts | `docs/integrations/`, when integrations exist | External formats and protocols, compatibility behavior, and upstream or downstream responsibilities. | Internal transformations and public Go declarations. |
|
| Durable integration contracts | `docs/integrations/`, when integrations exist | External formats and protocols, compatibility behavior, and upstream or downstream responsibilities. | Internal transformations and public Go declarations. |
|
||||||
|
| Supplemental release guidance | None. `docs/releases/` may be used when a release benefits from a changelog or migration guide. | No canonical content. These files may briefly summarize release-specific changes, compatibility, and consumer migration paths, and may be corrected, consolidated, archived, or removed when no longer useful. | Public API and behavior contracts, formats, integrations, architecture, release procedure, and the authoritative annotated-tag release record. |
|
||||||
| Implemented component inventory | `docs/internal/overview.md` | Current packages and components, their implemented responsibilities, and links to focused internal documents. | Normative architecture, contributor workflow, external contracts, and proposed components. |
|
| Implemented component inventory | `docs/internal/overview.md` | Current packages and components, their implemented responsibilities, and links to focused internal documents. | Normative architecture, contributor workflow, external contracts, and proposed components. |
|
||||||
| Internal subsystem behavior | Other files under `docs/internal/`, when a subsystem needs durable detail | Implementation flow, internal collaborators and state transitions, package-local guarantees and failures, and relevant tests. | Global architecture invariants, public API definitions, and future package plans. |
|
| Internal subsystem behavior | Other files under `docs/internal/`, when a subsystem needs durable detail | Implementation flow, internal collaborators and state transitions, package-local guarantees and failures, and relevant tests. | Global architecture invariants, public API definitions, and future package plans. |
|
||||||
| Architectural decision history | `docs/adr/`, when repository-local decisions require records | Significant decisions, context, alternatives, rationale, consequences, and supersession history. | Current behavior reference, implementation status, and task sequencing. |
|
| Architectural decision history | `docs/adr/`, when repository-local decisions require records | Significant decisions, context, alternatives, rationale, consequences, and supersession history. | Current behavior reference, implementation status, and task sequencing. |
|
||||||
@@ -85,9 +86,9 @@ mechanisms, not secret values.
|
|||||||
| Complete copyable artifacts | `examples/` | Valid inputs, Go programs, and other files intended to be copied or run. | Field-by-field reference, exact API declarations, and prose explanation. |
|
| Complete copyable artifacts | `examples/` | Valid inputs, Go programs, and other files intended to be copied or run. | Field-by-field reference, exact API declarations, and prose explanation. |
|
||||||
|
|
||||||
Conditional owners do not require placeholder files or directories. Create a
|
Conditional owners do not require placeholder files or directories. Create a
|
||||||
consumer, integration, subsystem, ADR, roadmap, or example document only when
|
consumer, integration, release, subsystem, ADR, roadmap, or example document
|
||||||
the corresponding implemented interface, decision, planned effort, or
|
only when the corresponding implemented interface, release, decision, planned
|
||||||
maintained artifact exists.
|
effort, or maintained artifact exists.
|
||||||
|
|
||||||
## Boundary Rules
|
## Boundary Rules
|
||||||
|
|
||||||
@@ -109,6 +110,23 @@ but must link to its canonical definition rather than restate it.
|
|||||||
The [framework format reference](../formats.md) owns exact prompt, profile, and
|
The [framework format reference](../formats.md) owns exact prompt, profile, and
|
||||||
schema-file contracts. Integration documents own external wire formats.
|
schema-file contracts. Integration documents own external wire formats.
|
||||||
|
|
||||||
|
### Supplemental Release Guidance
|
||||||
|
|
||||||
|
Files under `docs/releases/` may provide changelog-style summaries and
|
||||||
|
migration guidance for a particular release. They are navigation and
|
||||||
|
orientation aids, not canonical owners of public APIs, behavior, formats,
|
||||||
|
integrations, architecture, release procedure, or other durable facts. When a
|
||||||
|
reader needs detail beyond a short release-specific note, the release document
|
||||||
|
must link to the applicable canonical documentation rather than reproduce its
|
||||||
|
contract.
|
||||||
|
|
||||||
|
The annotated tag message required by the
|
||||||
|
[release procedure](../release.md#write-the-release-note) remains the
|
||||||
|
authoritative release record. Supplemental release documents may be corrected,
|
||||||
|
consolidated, archived, or removed at any time when they are no longer useful,
|
||||||
|
provided maintained documentation does not depend on them and the annotated
|
||||||
|
tag record remains intact.
|
||||||
|
|
||||||
### Security Topics
|
### Security Topics
|
||||||
|
|
||||||
This policy owns what documentation and examples may contain. Architecture owns
|
This policy owns what documentation and examples may contain. Architecture owns
|
||||||
@@ -160,6 +178,10 @@ durable owners, update incoming links, and archive or remove the roadmap
|
|||||||
according to repository practice. Do not preserve completed roadmaps as a
|
according to repository practice. Do not preserve completed roadmaps as a
|
||||||
second current-state reference.
|
second current-state reference.
|
||||||
|
|
||||||
|
Supplemental release documents may likewise be removed without preserving a
|
||||||
|
replacement. Before removal, update maintained incoming links so current
|
||||||
|
documentation does not depend on an optional historical guide.
|
||||||
|
|
||||||
Before completing documentation work:
|
Before completing documentation work:
|
||||||
|
|
||||||
- verify affected behavior and examples;
|
- verify affected behavior and examples;
|
||||||
|
|||||||
243
docs/releases/v0.2.0.md
Normal file
243
docs/releases/v0.2.0.md
Normal file
@@ -0,0 +1,243 @@
|
|||||||
|
# Promptkit v0.2.0
|
||||||
|
|
||||||
|
This supplemental changelog and migration guide summarizes the consumer-facing
|
||||||
|
changes from `v0.1.0` to `v0.2.0`. The annotated `v0.2.0` tag is the
|
||||||
|
authoritative release record. Exact current contracts belong to the linked
|
||||||
|
GoDoc and durable documentation.
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
`v0.2.0` adds three major capabilities:
|
||||||
|
|
||||||
|
- an engine-scoped registry for reusable OpenAI-compatible backend
|
||||||
|
definitions;
|
||||||
|
- bounded, backend-specific run admission and model-generation concurrency;
|
||||||
|
and
|
||||||
|
- direct per-run session IDs and tri-state reasoning-effort overrides.
|
||||||
|
|
||||||
|
Existing endpoint-only profiles remain supported. Consumers can adopt backend
|
||||||
|
registration and runtime overrides incrementally rather than rewriting all
|
||||||
|
profiles during the upgrade.
|
||||||
|
|
||||||
|
## Compatibility At A Glance
|
||||||
|
|
||||||
|
Promptkit remains pre-`v1`, and this minor release includes source-level and
|
||||||
|
behavioral changes that deserve review.
|
||||||
|
|
||||||
|
| Area | `v0.1.0` consumer impact |
|
||||||
|
| --- | --- |
|
||||||
|
| Endpoint-only profiles | Continue to work without migration. |
|
||||||
|
| Built-in profiles | Continue to use OpenRouter and `OPENROUTER_API_KEY`; they now select the built-in `openrouter` backend. |
|
||||||
|
| Custom backends | Registration is optional. Existing profiles may keep their endpoint and credential configuration. |
|
||||||
|
| Reasoning overrides | String assignments must migrate to the new pointer field. |
|
||||||
|
| `RunRequest.Metadata` | Removed; delete assignments to this field. |
|
||||||
|
| OpenRouter concurrency | Now limited to 16 active generations with waiting capacity of 1024 per engine. |
|
||||||
|
| Public JSON | `v0.2.0` formalizes supported JSON representations; consumers relying on `v0.1.0` encodings should review the notes below. |
|
||||||
|
| Unkeyed public struct literals | May require updates because fields were added. Keyed literals are recommended. |
|
||||||
|
|
||||||
|
## Upgrade
|
||||||
|
|
||||||
|
After the `v0.2.0` tag is published, update the module dependency with:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
go get gitea.maximumdirect.net/eric/promptkit@v0.2.0
|
||||||
|
go mod tidy
|
||||||
|
```
|
||||||
|
|
||||||
|
Run the consuming project's ordinary tests and race-enabled tests after the
|
||||||
|
upgrade, especially if it calls one engine concurrently or persists Promptkit
|
||||||
|
JSON values.
|
||||||
|
|
||||||
|
## Backend Registry
|
||||||
|
|
||||||
|
Consumers may now register reusable OpenAI-compatible backend definitions with
|
||||||
|
`WithBackend`, then select them by ID from file-backed or in-memory profiles.
|
||||||
|
A backend can supply its endpoint, API-key environment-variable name,
|
||||||
|
request-wide extra parameters, and optional capacity policy.
|
||||||
|
|
||||||
|
Registrations are immutable and belong to one engine. Consumer registrations
|
||||||
|
can add new IDs but cannot replace Promptkit's reserved `openrouter` backend.
|
||||||
|
Profiles that select a backend may still override its endpoint without losing
|
||||||
|
the backend's routing or capacity identity.
|
||||||
|
|
||||||
|
An existing endpoint-only in-memory profile remains valid:
|
||||||
|
|
||||||
|
```go
|
||||||
|
promptkit.Profile{
|
||||||
|
ID: "local",
|
||||||
|
Endpoint: "http://localhost:8000/v1",
|
||||||
|
Model: "example-model",
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Adopting the registry is optional and can be done when several profiles should
|
||||||
|
share connection or capacity settings:
|
||||||
|
|
||||||
|
```go
|
||||||
|
engine, err := promptkit.NewEngine(
|
||||||
|
promptkit.Config{PromptDir: "prompts"},
|
||||||
|
promptkit.WithBackend(promptkit.Backend{
|
||||||
|
ID: "local",
|
||||||
|
Endpoint: "http://localhost:8000/v1",
|
||||||
|
APIKeyEnv: "LOCAL_LLM_API_KEY",
|
||||||
|
}),
|
||||||
|
promptkit.WithProfiles(promptkit.Profile{
|
||||||
|
ID: "local-summary",
|
||||||
|
BackendID: "local",
|
||||||
|
Model: "example-model",
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
See the
|
||||||
|
[custom-backend consumer guide](../consumers/pkg-promptkit.md#register-a-custom-backend)
|
||||||
|
for task-oriented usage. The
|
||||||
|
[`Backend` and `WithBackend` GoDoc](../../backends.go) owns exact registration,
|
||||||
|
validation, copying, defaulting, and uniqueness semantics. The
|
||||||
|
[framework format reference](../formats.md) owns the profile `backend` field
|
||||||
|
and execution precedence.
|
||||||
|
|
||||||
|
## Backend-Specific Concurrency
|
||||||
|
|
||||||
|
Each registered backend may now define:
|
||||||
|
|
||||||
|
- an active model-generation limit; and
|
||||||
|
- a bounded number of additional admitted `Run` calls.
|
||||||
|
|
||||||
|
Promptkit owns scheduling for both its built-in model client and an injected
|
||||||
|
`LLMClient`. `Run` remains synchronous: an admitted caller waits for its
|
||||||
|
ordinary result, while a call beyond the bounded admission capacity returns
|
||||||
|
`ErrCapacityExceeded`. Capacity is engine-local and keyed by backend ID.
|
||||||
|
Endpoint-only profiles and custom backends without a configured limit remain
|
||||||
|
unlimited.
|
||||||
|
|
||||||
|
The built-in OpenRouter backend now permits 16 active generations and 1024
|
||||||
|
additional admitted calls per engine. Applications that can exceed this bound
|
||||||
|
should handle capacity exhaustion separately from provider and request
|
||||||
|
failures:
|
||||||
|
|
||||||
|
```go
|
||||||
|
result, err := engine.Run(ctx, request)
|
||||||
|
if errors.Is(err, promptkit.ErrCapacityExceeded) {
|
||||||
|
// Apply application-specific overload or retry policy.
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Promptkit does not prescribe retries or map this error to an HTTP status. See
|
||||||
|
the
|
||||||
|
[concurrency consumer guidance](../consumers/pkg-promptkit.md#limit-backend-concurrency)
|
||||||
|
and the [`Backend` GoDoc](../../backends.go) for the canonical configuration
|
||||||
|
contract. Runtime behavior and public error identities belong to the
|
||||||
|
[`Engine.Run` GoDoc](../../engine.go).
|
||||||
|
|
||||||
|
## Per-Run Session IDs
|
||||||
|
|
||||||
|
`RunRequest.SessionID` can now supply a consumer-managed correlation ID for one
|
||||||
|
`Prepare` or `Run` invocation. A nonblank direct value overrides the prompt's
|
||||||
|
session template and is exposed in prepared values, results, injected-client
|
||||||
|
requests, and provider observability. Session IDs should therefore be stable,
|
||||||
|
non-secret values.
|
||||||
|
|
||||||
|
```go
|
||||||
|
result, err := engine.Run(ctx, promptkit.RunRequest{
|
||||||
|
PromptID: "meeting.summary",
|
||||||
|
SessionID: "conversation-42",
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
The built-in OpenAI-compatible client sends a nonempty effective session as the
|
||||||
|
top-level `session_id` request-body field, not as an `x-session-id` header. See
|
||||||
|
the
|
||||||
|
[session and reasoning consumer guide](../consumers/pkg-promptkit.md#set-a-per-run-session-and-reasoning),
|
||||||
|
the [`RunRequest` GoDoc](../../types.go), and the
|
||||||
|
[OpenAI-compatible request contract](../integrations/openai-compatible-chat.md#request-body)
|
||||||
|
for exact normalization, length, exposure, and wire behavior.
|
||||||
|
|
||||||
|
## Per-Run Reasoning Effort
|
||||||
|
|
||||||
|
`ExecutionTargetOverride.ReasoningEffort` changed from `string` to `*string` so
|
||||||
|
one request can distinguish inheritance, replacement, and explicit clearing.
|
||||||
|
|
||||||
|
Update a `v0.1.0` override like this:
|
||||||
|
|
||||||
|
```go
|
||||||
|
// v0.1.0
|
||||||
|
Execution: &promptkit.ExecutionTargetOverride{
|
||||||
|
ReasoningEffort: "high",
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
to:
|
||||||
|
|
||||||
|
```go
|
||||||
|
// v0.2.0
|
||||||
|
reasoning := "high"
|
||||||
|
Execution: &promptkit.ExecutionTargetOverride{
|
||||||
|
ReasoningEffort: &reasoning,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The three states are:
|
||||||
|
|
||||||
|
- `nil` inherits the selected profile's value;
|
||||||
|
- a pointer to a nonblank string replaces it for that invocation; and
|
||||||
|
- a pointer to an empty or whitespace-only string clears it for that
|
||||||
|
invocation.
|
||||||
|
|
||||||
|
This allows consumers to consolidate profiles that differed only by reasoning
|
||||||
|
effort. The [`ExecutionTargetOverride` GoDoc](../../types.go) owns the exact
|
||||||
|
override contract.
|
||||||
|
|
||||||
|
## Other Migration Notes
|
||||||
|
|
||||||
|
### Remove `RunRequest.Metadata`
|
||||||
|
|
||||||
|
`RunRequest.Metadata` is no longer part of the public request. Remove any
|
||||||
|
assignment to that field. Use application-owned state keyed by `RunResult.RunID`
|
||||||
|
or a direct `SessionID` when correlation is needed; these identifiers have
|
||||||
|
different purposes, so choose according to the application's lifecycle.
|
||||||
|
|
||||||
|
### Review Persisted JSON
|
||||||
|
|
||||||
|
`v0.2.0` defines stable JSON representations for the public result, artifact,
|
||||||
|
execution, validation, and model-client values listed in the
|
||||||
|
[package documentation](../../doc.go). Consumers that treated `v0.1.0`
|
||||||
|
reflection-derived encodings as stable should update fixtures and stored-data
|
||||||
|
adapters.
|
||||||
|
|
||||||
|
In particular:
|
||||||
|
|
||||||
|
- `RunResult` encodes elapsed time as integer milliseconds in `duration_ms`
|
||||||
|
instead of encoding `time.Duration` under `duration`;
|
||||||
|
- result JSON can include the new `session_id` and `selected_backend_id`
|
||||||
|
fields;
|
||||||
|
- execution-target JSON can include `backend_id`; and
|
||||||
|
- artifact and target-presence fields now use their documented lower-case
|
||||||
|
names.
|
||||||
|
|
||||||
|
The `v0.2.0` `RunResult` decoder reads `duration_ms`; it does not translate a
|
||||||
|
persisted `v0.1.0` `duration` field. Transform old payloads before decoding
|
||||||
|
when preserving their elapsed duration matters.
|
||||||
|
|
||||||
|
### Prefer Keyed Struct Literals
|
||||||
|
|
||||||
|
New fields were added to several public structs. Replace positional composite
|
||||||
|
literals with keyed literals so future additive fields do not cause another
|
||||||
|
source migration.
|
||||||
|
|
||||||
|
## Migration Checklist
|
||||||
|
|
||||||
|
- Update the module dependency and run the consumer's tests.
|
||||||
|
- Change reasoning overrides from strings to pointers.
|
||||||
|
- Remove uses of `RunRequest.Metadata`.
|
||||||
|
- Review unkeyed Promptkit struct literals.
|
||||||
|
- Decide whether shared endpoints should move into registered backends.
|
||||||
|
- If using built-in OpenRouter profiles at high concurrency, handle
|
||||||
|
`ErrCapacityExceeded` and review the new engine-local bound.
|
||||||
|
- Review stored JSON, fixtures, and downstream decoders.
|
||||||
|
- Optionally replace profile-specific session or reasoning variants with
|
||||||
|
per-run overrides.
|
||||||
|
|
||||||
|
For complete consumer workflows, use the
|
||||||
|
[package consumer guide](../consumers/pkg-promptkit.md) and maintained
|
||||||
|
[offline execution example](../../examples/go-library/run/main.go).
|
||||||
Reference in New Issue
Block a user