Prepare the v0.9.0 release
This commit is contained in:
@@ -33,7 +33,10 @@ boundary and constraints that framework work must preserve.
|
||||
|
||||
## Release Guidance
|
||||
|
||||
Consumers upgrading from `v0.7.0` to `v0.8.0` should read the
|
||||
Consumers upgrading from `v0.8.0` to `v0.9.0` should read the
|
||||
[v0.9.0 changelog and migration guide](docs/releases/v0.9.0.md).
|
||||
|
||||
Consumers upgrading from `v0.7.0` to `v0.8.0` can consult the
|
||||
[v0.8.0 changelog and migration guide](docs/releases/v0.8.0.md).
|
||||
|
||||
Earlier adopters can consult the
|
||||
|
||||
125
docs/releases/v0.9.0.md
Normal file
125
docs/releases/v0.9.0.md
Normal file
@@ -0,0 +1,125 @@
|
||||
# Promptkit v0.9.0
|
||||
|
||||
This supplemental changelog and migration guide summarizes the consumer-facing
|
||||
changes from `v0.8.0` to `v0.9.0`. The annotated `v0.9.0` tag is the
|
||||
authoritative release record. Exact current contracts belong to the linked
|
||||
GoDoc and durable documentation.
|
||||
|
||||
## Summary
|
||||
|
||||
`v0.9.0` adds stateless request-message composition and separates maintained
|
||||
provider data from Promptkit's core implementation:
|
||||
|
||||
- callers can append already-rendered messages to a configured prompt for
|
||||
application-owned conversations and semantic correction workflows;
|
||||
- the public package now publishes constants for the four supported text-chat
|
||||
roles, and prompt definitions use the same normalized role vocabulary; and
|
||||
- the OpenRouter and Rakestrawhome backend/profile catalogs now come from two
|
||||
independently versioned Go module dependencies.
|
||||
|
||||
## Compatibility
|
||||
|
||||
This release adds one field and four constants to the public API and removes no
|
||||
public declarations. Existing keyed `RunRequest` literals that omit
|
||||
`AppendedMessages` retain their behavior. Adding the field changes the struct
|
||||
shape, so consumers using positional `RunRequest` literals must convert them
|
||||
to keyed literals.
|
||||
|
||||
Message roles in prompt definitions are now trimmed, lowercased, and required
|
||||
to be `developer`, `system`, `user`, or `assistant`. Definitions using another
|
||||
role that earlier releases accepted as an arbitrary nonblank string now fail
|
||||
prompt loading. In particular, the text-only message contract does not support
|
||||
`tool` or the deprecated `function` role. Otherwise valid roles with different
|
||||
case or surrounding whitespace are normalized rather than rejected.
|
||||
|
||||
The catalog extraction preserves Promptkit's public API, built-in backend and
|
||||
profile IDs, configuration, precedence, credential handling, and capacity
|
||||
behavior. Consumers do not import or register either catalog themselves, and
|
||||
no configuration migration is required. Promptkit now selects two
|
||||
independently versioned data dependencies and guarantees only the catalog
|
||||
versions selected and tested by this Promptkit release.
|
||||
|
||||
## Upgrade
|
||||
|
||||
Update the module dependency with:
|
||||
|
||||
```sh
|
||||
go get gitea.maximumdirect.net/eric/promptkit@v0.9.0
|
||||
go mod tidy
|
||||
```
|
||||
|
||||
Convert any positional `RunRequest` literals to keyed literals. Review prompt
|
||||
definitions for unsupported roles, then run the consuming project's ordinary
|
||||
and race-enabled tests.
|
||||
|
||||
## Appended Request Messages
|
||||
|
||||
`RunRequest.AppendedMessages` accepts caller-owned `RenderedMessage` values
|
||||
that Promptkit validates, copies, and appends after every rendered
|
||||
prompt-definition message in caller order. Promptkit does not template this
|
||||
content, retain conversation state between calls, impose a retry policy, or
|
||||
apply a message-count, byte-size, token, or context-window limit. Upstream
|
||||
rejections continue through the ordinary generation-error boundary.
|
||||
|
||||
This primitive supports application-owned conversation continuations and
|
||||
domain-aware correction loops while preserving Promptkit's existing
|
||||
preparation, hashing, prepared-execution, structural repair, backend-capacity,
|
||||
credential, and cancellation behavior. Appended content can include sensitive
|
||||
model output or application feedback; prepared values expose the complete
|
||||
effective messages by design, while default request formatting reports only
|
||||
the appended-message count.
|
||||
|
||||
See the
|
||||
[consumer appended-message example](../consumers/pkg-promptkit.md#append-already-rendered-messages),
|
||||
the [`RunRequest`, `RenderedMessage`, and `CacheControl` GoDoc](../../types.go),
|
||||
and the [OpenAI-compatible request contract](../integrations/openai-compatible-chat.md#request-body)
|
||||
for current behavior.
|
||||
|
||||
## Supported Message Roles
|
||||
|
||||
The new `RoleDeveloper`, `RoleSystem`, `RoleUser`, and `RoleAssistant`
|
||||
constants identify the complete role vocabulary accepted by Promptkit's
|
||||
text-chat message model. The same validation and normalization now apply to
|
||||
prompt-definition messages and request-supplied appended messages. Promptkit
|
||||
does not translate between roles; provider- or model-specific rejection of an
|
||||
otherwise supported role remains an upstream generation error.
|
||||
|
||||
See the [message format reference](../formats.md#messages-and-templates) for
|
||||
the canonical prompt-definition contract.
|
||||
|
||||
## Independently Versioned Backend Catalogs
|
||||
|
||||
Promptkit imports immutable catalog data for its maintained OpenRouter and
|
||||
Rakestrawhome backends and profiles. Engine construction validates and
|
||||
assembles both catalogs behind the existing built-in registry and profile
|
||||
precedence rules. Promptkit no longer keeps duplicate embedded profile assets
|
||||
or hard-coded definitions for those maintained backends.
|
||||
|
||||
The module versions in Promptkit's `go.mod` identify the catalog releases
|
||||
tested with this release. The [built-in backend and profile format
|
||||
reference](../formats.md#built-in-backends) remains the canonical consumer
|
||||
contract, while the [internal source documentation](../internal/sources.md#profiles-and-built-ins)
|
||||
describes the dependency boundary.
|
||||
|
||||
## Public API Changes
|
||||
|
||||
The release adds:
|
||||
|
||||
- `RunRequest.AppendedMessages`;
|
||||
- `RoleDeveloper`;
|
||||
- `RoleSystem`;
|
||||
- `RoleUser`; and
|
||||
- `RoleAssistant`.
|
||||
|
||||
No public declaration was removed.
|
||||
|
||||
## Consumer Action
|
||||
|
||||
- Convert positional `RunRequest` literals to keyed literals.
|
||||
- Replace unsupported prompt-definition roles with an appropriate supported
|
||||
role, or keep richer tool-call protocols in an application-owned client.
|
||||
- Treat appended messages and prepared effective messages according to the
|
||||
application's sensitive-data policy.
|
||||
- Do not add direct catalog imports or registration calls; existing Promptkit
|
||||
construction and configuration remain correct.
|
||||
- Run consumer ordinary and race-enabled tests after updating the module.
|
||||
@@ -1,434 +0,0 @@
|
||||
# Appended Request Messages
|
||||
|
||||
## Status
|
||||
|
||||
Accepted for future implementation. This roadmap records a concrete downstream
|
||||
requirement from Notarius and the Promptkit-native design selected for it. It
|
||||
describes future behavior only; the current public API and canonical
|
||||
documentation remain authoritative until the feature is implemented.
|
||||
|
||||
## Purpose
|
||||
|
||||
Allow a Go consumer to execute an ordinary configured prompt with an explicit
|
||||
sequence of already-rendered chat messages appended after the
|
||||
prompt-definition messages. The capability should preserve Promptkit's normal
|
||||
preparation, inspection, hashing, validation, structured-output repair,
|
||||
capacity, cancellation, credential, error, and debug boundaries.
|
||||
|
||||
The immediate consumer is Notarius, which needs to resubmit the same configured
|
||||
prompt after semantic validation rejects an LLM-produced stage candidate, then
|
||||
append:
|
||||
|
||||
1. an `assistant` message containing the exact defective response; and
|
||||
2. a `user` message containing bounded application-owned feedback and a request
|
||||
for one corrected replacement response.
|
||||
|
||||
Promptkit should provide the safe message-composition mechanism. Notarius
|
||||
should continue to own semantic validation, stage retry budgets, correction
|
||||
wording, terminal policy, and the decision to start another completion.
|
||||
|
||||
## Consumer Need
|
||||
|
||||
Promptkit v0.8 can perform bounded structural repair inside one `Run` or
|
||||
`RunPrepared` operation. Its repairer correctly starts from the complete
|
||||
original rendered prompt, appends the latest candidate as an assistant turn,
|
||||
and adds a corrective user turn. That loop is intentionally driven by
|
||||
Promptkit's own structural validators.
|
||||
|
||||
Notarius has a distinct outer workflow:
|
||||
|
||||
1. Promptkit returns a structurally valid response.
|
||||
2. Notarius materializes a typed stage candidate.
|
||||
3. One or more application validators evaluate domain semantics.
|
||||
4. If the candidate is rejected and a Notarius stage attempt remains, Notarius
|
||||
makes a new Promptkit request with application-owned corrective turns
|
||||
appended after the ordinary configured prompt.
|
||||
|
||||
Each `Run`, `Prepare`, or `PrepareExecution` remains an independent operation
|
||||
that resolves current sources and inputs. Promptkit does not retain or reuse a
|
||||
base prompt across calls, so the ordinary prefix is identical across attempts
|
||||
only when the selected definitions, inputs, variables, and other preparation
|
||||
inputs remain identical. A consumer that requires a pre-execution equality
|
||||
check can prepare each attempt and compare its opaque rendered-prompt hash
|
||||
before calling `RunPrepared`. A reusable prepared conversation or frozen
|
||||
cross-run prompt is outside this feature.
|
||||
|
||||
Today a `RunRequest` can select and parameterize a prompt definition, but it
|
||||
cannot append downstream-owned messages. Registering a second prompt manifest
|
||||
for every correction-capable operation would duplicate prompt identity,
|
||||
profile defaults, input declarations, output contracts, and message assets.
|
||||
Calling an injected model client directly would bypass Promptkit preparation,
|
||||
capacity, structured output, repair, error adaptation, and provenance. Neither
|
||||
workaround is a suitable long-term consumer contract.
|
||||
|
||||
## Target Public API
|
||||
|
||||
Add an append-only field to `RunRequest`:
|
||||
|
||||
```go
|
||||
type RunRequest struct {
|
||||
// Existing fields omitted.
|
||||
|
||||
AppendedMessages []RenderedMessage
|
||||
}
|
||||
```
|
||||
|
||||
Retain `RenderedMessage.Role` as a string for source compatibility and expose
|
||||
the untyped string constants `RoleDeveloper`, `RoleSystem`, `RoleUser`, and
|
||||
`RoleAssistant`. Their values are `developer`, `system`, `user`, and
|
||||
`assistant`, respectively. The supported values and their semantics are part
|
||||
of the public contract.
|
||||
|
||||
`AppendedMessages` contains fully rendered message values. Promptkit normalizes
|
||||
and validates their roles as described below, but does not interpret their
|
||||
content as Go templates, resolve input references inside it, or load it from
|
||||
files. Nil and empty slices are equivalent.
|
||||
|
||||
Reusing `RenderedMessage` is preferred because it is already Promptkit's
|
||||
public, stable representation of a provider-bound chat message and includes
|
||||
the supported cache-control metadata. Its GoDoc should be generalized from a
|
||||
definition-supplied message to an already-rendered chat message. A new
|
||||
request-only message type would duplicate the same role, content, and cache
|
||||
control contract without adding useful type safety.
|
||||
|
||||
The exact exported declarations and semantics, once implemented, belong in
|
||||
GoDoc. The name `AppendedMessages` is intentional: placement is part of the
|
||||
contract, whereas names such as `AdditionalMessages` leave ordering
|
||||
ambiguous.
|
||||
|
||||
## Composition Semantics
|
||||
|
||||
For `Prepare`, `PrepareExecution`, and `Run`, Promptkit should:
|
||||
|
||||
1. perform ordinary prompt selection, input loading, variable processing, and
|
||||
prompt rendering;
|
||||
2. preserve every ordinary rendered message after its role has passed the
|
||||
shared canonical normalization, including content, cache-control value,
|
||||
order, and bytes, without rerendering or rewriting content;
|
||||
3. normalize and validate request-supplied roles, then defensively copy and
|
||||
append `RunRequest.AppendedMessages` in caller-supplied order; and
|
||||
4. treat the combined sequence as the effective rendered prompt for every
|
||||
later preparation and execution boundary.
|
||||
|
||||
The request-supplied messages always follow all prompt-definition messages.
|
||||
They cannot prepend, insert, replace, or delete definition messages. This
|
||||
narrow contract protects a stable prompt prefix for provider-side prompt
|
||||
caching and keeps prompt definitions as the canonical owner of ordinary
|
||||
prompt content.
|
||||
|
||||
Promptkit must not synthesize separators or normalize message content. Content,
|
||||
including empty or whitespace-only content, remains byte-for-byte caller data;
|
||||
whether a provider accepts it is provider policy. The effective session ID,
|
||||
selected profile, model settings, output contract, structured-output
|
||||
constraint, and input hashes retain their ordinary resolution rules.
|
||||
|
||||
`InspectPrompt` remains definition inspection and therefore does not accept or
|
||||
report request-supplied appended messages.
|
||||
|
||||
## Preparation, Hashing, And Inspection
|
||||
|
||||
Appended messages must participate in the same immutable preparation boundary
|
||||
as ordinary rendered messages:
|
||||
|
||||
- `PreparedRun.Messages` contains the complete combined sequence;
|
||||
- `PreparedExecution.Details().Messages` contains an independent defensive
|
||||
copy of that sequence;
|
||||
- `Run` and `RunPrepared` send exactly that sequence to the selected model
|
||||
client;
|
||||
- `RenderedPromptHash` covers the effective session ID and complete combined
|
||||
sequence, including appended-message cache-control metadata;
|
||||
- `PromptHash` continues to identify only the selected prompt definition and
|
||||
therefore does not change merely because appended messages differ; and
|
||||
- input hashes continue to describe only named artifacts.
|
||||
|
||||
Two requests with identical prompt selection, inputs, variables, session, and
|
||||
appended messages should prepare equivalent message sequences and rendered
|
||||
prompt hashes. Changing any normalized appended role, content, order, or
|
||||
cache-control value should change the rendered prompt hash. The hash encoding
|
||||
must frame sessions, messages, and fields unambiguously rather than relying on
|
||||
separators that could also occur in caller-controlled content.
|
||||
|
||||
Prepared execution must freeze appended messages at preparation time. Caller
|
||||
mutation after `PrepareExecution` returns must not affect its details or later
|
||||
execution, and mutation of a value returned by `Details` must not affect the
|
||||
opaque executable snapshot.
|
||||
|
||||
## Interaction With Structured-Output Repair
|
||||
|
||||
The combined message sequence is the complete original prompt for one
|
||||
Promptkit operation. If Promptkit's structural validator rejects a generated
|
||||
candidate and a repair attempt is available, the existing repair workflow
|
||||
should begin from a fresh copy of that combined sequence and then append its
|
||||
own candidate and correction messages.
|
||||
|
||||
For the Notarius use case, the ordering may therefore be:
|
||||
|
||||
1. ordinary configured prompt messages;
|
||||
2. Notarius's previous assistant response;
|
||||
3. Notarius's semantic-correction user message;
|
||||
4. Promptkit's latest structurally defective assistant response, if any; and
|
||||
5. Promptkit's structural-repair user message, if needed.
|
||||
|
||||
This is not a recursive retry policy. Promptkit still owns only its configured
|
||||
structural-repair budget within the current operation. It does not interpret
|
||||
the purpose of consumer-supplied messages, invoke application validators, or
|
||||
start a later Notarius stage attempt.
|
||||
|
||||
All initial and repair generation calls must continue through the ordinary
|
||||
prepared-execution, capacity, client, cancellation, credential, structured
|
||||
output, usage, and error-adaptation paths.
|
||||
|
||||
## Message Validation And Provider Boundaries
|
||||
|
||||
Promptkit should validate appended messages before publishing a prepared value
|
||||
or starting model generation. Validation should be shared by `Prepare`,
|
||||
`PrepareExecution`, and `Run` and should reject:
|
||||
|
||||
- invalid UTF-8 in role or content;
|
||||
- a role that, after normalization, is not `developer`, `system`, `user`, or
|
||||
`assistant`; or
|
||||
- invalid cache-control metadata.
|
||||
|
||||
Role normalization is intentionally limited to trimming surrounding whitespace
|
||||
and converting the result to lowercase. Promptkit performs no aliasing or
|
||||
semantic role translation. In particular, it must not translate `developer`
|
||||
to `system` or the reverse. `system` is generally the more portable choice
|
||||
across heterogeneous OpenAI-compatible backends; `developer` remains supported
|
||||
for providers and models that implement the newer instruction hierarchy. A
|
||||
backend or model that rejects an otherwise supported role reports that through
|
||||
the ordinary provider error path.
|
||||
|
||||
The same four-role vocabulary and normalization apply to prompt-definition
|
||||
messages. This deliberately tightens the existing prompt format, which
|
||||
currently accepts any nonblank role. `tool` is not supported because
|
||||
Promptkit's text-only message value cannot express its required `tool_call_id`;
|
||||
the deprecated `function` role likewise requires a name that the value cannot
|
||||
represent. Those roles should be considered only as part of a deliberate
|
||||
future tool-call message design.
|
||||
|
||||
Promptkit does not impose appended-message count, per-message size, aggregate
|
||||
size, estimated-token, or context-window limits, and it must not truncate
|
||||
caller content. Those limits are backend-, model-, and application-specific.
|
||||
Provider rejection for context length, role support, empty content, or any
|
||||
other provider rule should cross the existing generation-error boundary with
|
||||
its supported status and provider-detail information intact.
|
||||
|
||||
Invalid appended messages are invalid requests and should preserve the public
|
||||
`ErrInvalidRequest` identity. Error text should identify the failing appended
|
||||
message index and violated property without echoing its role or content. An
|
||||
invalid role in a prompt definition remains a source-owned prompt-definition
|
||||
failure through its ordinary public error category.
|
||||
|
||||
## Ownership, Privacy, And Formatting
|
||||
|
||||
`RunRequest.AppendedMessages` is caller-owned. Promptkit must defensively copy
|
||||
the slice and nested cache-control values before retaining them. Internal
|
||||
domain conversion, prepared-run cloning, public result conversion, and
|
||||
prepared-execution details must preserve the same non-aliasing guarantees as
|
||||
ordinary rendered messages.
|
||||
|
||||
Appended content can contain model output, source excerpts, or application
|
||||
validation feedback and must be treated as sensitive prompt content:
|
||||
|
||||
- `RunRequest.String` and `RunRequest.GoString` should report only an appended
|
||||
message count, not roles or content;
|
||||
- errors must not reproduce appended content;
|
||||
- no credential or secret value may be inferred, copied, or added to hashes
|
||||
beyond the existing prompt-content behavior;
|
||||
- prepared values continue to expose complete rendered messages by design and
|
||||
remain subject to the consumer's data-handling policy; and
|
||||
- Promptkit should not add logging, persistence, or a durable retry transcript
|
||||
for appended messages.
|
||||
|
||||
The field does not need a stable `RunRequest` JSON contract because
|
||||
`RunRequest` has none today. The stable JSON representation of prepared values
|
||||
must continue to include the final `Messages` sequence through its existing
|
||||
contract.
|
||||
|
||||
## Application-Neutral Boundary
|
||||
|
||||
This feature is a generic prompt-composition primitive. Promptkit should not
|
||||
add concepts such as semantic validator, rejection, stage, pipeline,
|
||||
correction reason code, or terminal validation policy to its public API.
|
||||
|
||||
The following remain downstream responsibilities:
|
||||
|
||||
- deciding whether a new request is warranted;
|
||||
- choosing and enforcing the outer retry budget;
|
||||
- retaining the exact earlier candidate;
|
||||
- constructing, bounding, and redacting application feedback;
|
||||
- determining which message roles and sequence express that workflow;
|
||||
- keeping preparation inputs stable when an identical prefix is required, or
|
||||
checking prepared hashes before execution;
|
||||
- aggregating semantic validation findings;
|
||||
- recording application provenance; and
|
||||
- deciding whether exhausted retries fail, reject, warn, or continue.
|
||||
|
||||
Promptkit owns only safe composition and execution of the effective request.
|
||||
|
||||
## Documentation End State
|
||||
|
||||
In the target state, the capability is described by the following canonical
|
||||
owners:
|
||||
|
||||
- root GoDoc for `RunRequest`, `RenderedMessage`, `PreparedRun`, and relevant
|
||||
engine operations, including the role constants and normalization contract;
|
||||
- the [framework format reference](../formats.md) for the tightened role
|
||||
vocabulary and normalization shared by prompt-definition messages;
|
||||
- the [Go consumer guide](../consumers/pkg-promptkit.md) with one concise
|
||||
appended-message example and a warning that values are already rendered and
|
||||
potentially sensitive;
|
||||
- the [internal runner document](../internal/runner.md) for validation,
|
||||
composition, hashing, preparation, and structural-repair interaction;
|
||||
- the [internal source document](../internal/sources.md) for
|
||||
prompt-definition role normalization and source-owned failures;
|
||||
- the [internal model-client document](../internal/llm.md) only if its
|
||||
effective-message input contract needs clarification;
|
||||
- the [architecture policy](../policy/architecture.md) only if implementation
|
||||
establishes a durable request-composition invariant not already covered by
|
||||
the public-facade and application-neutral-boundary rules;
|
||||
- the
|
||||
[OpenAI-compatible integration contract](../integrations/openai-compatible-chat.md)
|
||||
for supported provider-bound roles and provider rejection; and
|
||||
- release guidance for the new minor version, including migration guidance for
|
||||
consumers with nonstandard prompt-definition roles.
|
||||
|
||||
The Go-only appended-message field does not belong in `docs/formats.md`.
|
||||
However, the prompt-definition role contract does change and must be updated in
|
||||
that canonical format reference. Profile and schema formats do not change.
|
||||
|
||||
## Verification Expectations
|
||||
|
||||
Tests protect the public composition and ownership contract rather than
|
||||
private helper layout or exact diagnostic prose. Focused coverage establishes:
|
||||
|
||||
- nil and empty appended slices preserve current behavior;
|
||||
- ordinary rendered messages remain an exact prefix and appended messages
|
||||
retain caller order;
|
||||
- supported roles in both sources normalize by trimming and lowercasing, while
|
||||
unsupported, `tool`, and `function` roles are rejected at the owning
|
||||
boundary;
|
||||
- message content, including empty and whitespace-only content, is preserved
|
||||
exactly and receives no Promptkit-owned count or size restriction;
|
||||
- `Prepare`, `PrepareExecution`, and `Run` agree on the combined sequence and
|
||||
rendered prompt hash;
|
||||
- `RunPrepared` uses its frozen appended-message snapshot after caller
|
||||
mutation;
|
||||
- `Details` and public conversions return independent copies;
|
||||
- changing a normalized appended role, content, order, or cache control changes
|
||||
the
|
||||
rendered prompt hash without changing `PromptHash`;
|
||||
- invalid appended roles, UTF-8, and cache controls fail as invalid requests
|
||||
before model generation without echoing sensitive content;
|
||||
- provider rejection of an otherwise structurally valid combined sequence
|
||||
retains the ordinary generation-error contract;
|
||||
- the initial model call receives the combined sequence;
|
||||
- structural repair reconstructs the complete combined sequence before adding
|
||||
Promptkit's repair turns;
|
||||
- usage, capacity, cancellation, credentials, structured output, and error
|
||||
identity retain their existing behavior; and
|
||||
- `String` and `GoString` expose only a count for appended messages.
|
||||
|
||||
One external-package contract test and focused internal runner tests should
|
||||
own most of this matrix. Extend the maintained offline run example only if it
|
||||
materially improves consumer understanding; do not turn the example into a
|
||||
retry framework or duplicate the contract tests.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- A consumer can append already-rendered messages through `RunRequest` without
|
||||
defining a second prompt manifest or bypassing `Engine`.
|
||||
- Normalized ordinary prompt messages remain an unchanged, ordered prefix.
|
||||
- The final sequence is prepared, hashed, reported in prepared details, frozen,
|
||||
executed, and repaired consistently across all engine workflows.
|
||||
- Roles are normalized to and validated against the supported four-role
|
||||
vocabulary at both prompt-definition and appended-message boundaries.
|
||||
- Appended values are structurally validated, defensively copied, and excluded
|
||||
from ordinary request formatting and error text without Promptkit-owned
|
||||
count, size, token, or context-window limits.
|
||||
- Promptkit structural repair treats the combined sequence as its original
|
||||
prompt and retains all existing execution safeguards.
|
||||
- Promptkit introduces no application-specific retry, validation, pipeline, or
|
||||
terminal-policy concepts.
|
||||
- Existing consumers that omit appended messages and use supported roles retain
|
||||
current behavior; nonstandard prompt-definition roles are intentionally
|
||||
rejected under the tightened minor-version contract.
|
||||
- Canonical GoDoc and consumer/internal documentation describe the implemented
|
||||
contract, and the complete maintainer validation workflow passes.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- A Promptkit-owned semantic validation framework.
|
||||
- A generic outer retry orchestrator.
|
||||
- Automatic interpretation or formatting of downstream validation errors.
|
||||
- Prepending, inserting, replacing, or deleting configured prompt messages.
|
||||
- Treating appended content as a template or file reference.
|
||||
- Accumulating conversation state across `Run` calls.
|
||||
- Freezing or reusing a base prompt across independent operations.
|
||||
- A durable session or retry transcript store.
|
||||
- PromptKit-owned message-count, byte-size, token, or context-window limits.
|
||||
- Tool calls, tool results, deprecated function messages, or arbitrary custom
|
||||
message roles.
|
||||
- Provider-specific branching for Notarius.
|
||||
- Changes to profile or schema file formats.
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
### Paired Initial And Correction Prompt Definitions
|
||||
|
||||
A downstream application could register a second prompt definition that
|
||||
duplicates the initial manifest and adds candidate and correction inputs. This
|
||||
requires no Promptkit API change, but it duplicates prompt metadata and creates
|
||||
drift across prompt versions, profile defaults, output contracts, assets, and
|
||||
hashes. It also makes a generic request-composition need module-specific.
|
||||
|
||||
### A Purpose-Specific Repair Request
|
||||
|
||||
Promptkit could expose an API accepting `PreviousOutput` and
|
||||
`ValidationErrors`, mirroring its internal structural repair request. This
|
||||
would initially fit Notarius, but it would make Promptkit interpret downstream
|
||||
policy and would conflate application semantic retries with Promptkit
|
||||
structural repair. A generic append-only message contract is smaller and more
|
||||
reusable.
|
||||
|
||||
### Direct Execution Of A Mutated Prepared Prompt
|
||||
|
||||
Promptkit could expose mutable prepared messages or accept a complete caller-
|
||||
constructed prompt for execution. That would weaken definition ownership,
|
||||
prepared-execution immutability, hashing, validation, and provenance, and would
|
||||
make it easy to bypass source and preparation guarantees. The requested API
|
||||
should compose messages before immutable preparation instead.
|
||||
|
||||
### Direct Use Of The Model Client
|
||||
|
||||
Notarius could invoke an injected Promptkit-compatible model client directly.
|
||||
That bypasses the engine's profile resolution, backend admission, structured
|
||||
output, repair, error mapping, and prepared-execution contracts. It is not an
|
||||
acceptable downstream integration path.
|
||||
|
||||
### A Semantic-Validation Callback
|
||||
|
||||
Promptkit could accept an application callback that validates each candidate
|
||||
and drives another generation inside one `Run`. That could retain one frozen
|
||||
prompt and aggregate usage automatically, but it would make Promptkit own
|
||||
callback lifecycle, semantic diagnostics, application retry policy, and the
|
||||
boundary between typed domain values and raw model output. Keeping semantic
|
||||
validation and its outer loop downstream leaves the public API smaller and the
|
||||
library application-neutral.
|
||||
|
||||
### A Reusable Prepared Conversation
|
||||
|
||||
Promptkit could expose a reusable handle whose frozen base prompt accepts new
|
||||
turns across multiple executions. That would guarantee a byte-identical prefix
|
||||
and could support longer-lived chatbot workflows, but it would require a much
|
||||
larger lifecycle, credential-retention, concurrency, source-freshness, and
|
||||
history-ownership contract. The stateless append-only request primitive meets
|
||||
the demonstrated need without precommitting to those policies.
|
||||
|
||||
### Complete Caller-Supplied Or Mutable Message Sequences
|
||||
|
||||
Promptkit could let a consumer replace, insert, or delete configured messages,
|
||||
or execute an entirely caller-constructed sequence. That would weaken prompt
|
||||
definition ownership, hashing, provenance, and the prepared-execution
|
||||
boundary. Append-only composition provides the needed flexibility while
|
||||
preserving configured messages as the canonical prefix.
|
||||
@@ -1,238 +0,0 @@
|
||||
# External Backend Catalogs
|
||||
|
||||
## Status
|
||||
|
||||
Accepted for future implementation. This roadmap defines the intended end
|
||||
state for extracting Promptkit's maintained built-in backend and profile data
|
||||
into independently versioned Go modules. It describes future behavior only;
|
||||
the current implementation and canonical documentation remain authoritative
|
||||
until the extraction is complete.
|
||||
|
||||
## Purpose
|
||||
|
||||
Move the rapidly changing built-in backend and model-profile catalogs out of
|
||||
the Promptkit repository without changing how consumers configure or use
|
||||
Promptkit.
|
||||
|
||||
Provider model catalogs change much more frequently than Promptkit's engine,
|
||||
public API, and internal execution architecture. Independent catalog modules
|
||||
allow model additions, deprecations, and metadata corrections to be developed,
|
||||
tested, reviewed, and released without placing that content churn in the core
|
||||
repository's history. Promptkit can adopt tested catalog releases through
|
||||
ordinary Go module version updates.
|
||||
|
||||
This extraction is an ownership and release-boundary improvement. It does not
|
||||
eliminate all Promptkit maintenance: Promptkit must still pin and test the
|
||||
catalog versions that it supplies by default, and adopting a newer default
|
||||
catalog ordinarily requires a Promptkit dependency update and release.
|
||||
|
||||
## Target End State
|
||||
|
||||
The OpenRouter and Rakestrawhome catalogs reside in separate, independently
|
||||
versioned Go repositories and modules. Each module owns exactly one built-in
|
||||
backend definition and every built-in profile maintained for that backend.
|
||||
|
||||
Promptkit imports both modules and assembles their contents as its built-in
|
||||
catalog. Downstream consumers continue to receive the same built-in backends
|
||||
and profiles automatically when they construct an engine. They do not need to
|
||||
import a catalog module, call a registration function, or change existing
|
||||
configuration.
|
||||
|
||||
Promptkit no longer contains duplicate embedded copies of the extracted
|
||||
profile assets or hard-coded copies of the extracted backend definitions.
|
||||
Promptkit continues to own:
|
||||
|
||||
- the public backend constants and their exact string values;
|
||||
- catalog decoding, normalization, and validation;
|
||||
- conversion into Promptkit's internal domain values;
|
||||
- built-in and consumer-source precedence;
|
||||
- engine assembly, capacity management, credentials, and execution; and
|
||||
- the canonical consumer documentation for the built-ins supplied by each
|
||||
Promptkit release.
|
||||
|
||||
The catalog modules supply immutable data. They do not own Promptkit runtime
|
||||
behavior or become general-purpose provider SDKs.
|
||||
|
||||
## External Catalog Modules
|
||||
|
||||
Maintain one repository and Go module for OpenRouter and one for the
|
||||
Rakestrawhome inference backend. Repository and module names make both the
|
||||
Promptkit relationship and owning backend unambiguous. Every catalog version
|
||||
selected by Promptkit must be available from the same build environment used
|
||||
to test and release Promptkit.
|
||||
|
||||
Each module should contain:
|
||||
|
||||
- a versioned backend manifest containing the backend ID, OpenAI-compatible
|
||||
base endpoint, API-key environment-variable name, concurrency policy, queue
|
||||
capacity, and any backend-wide extra parameters;
|
||||
- the backend's existing profile YAML assets, retaining their current IDs and
|
||||
behavior;
|
||||
- a minimal public package that exposes the embedded, read-only catalog as an
|
||||
`fs.FS` together with the stable root needed to read it;
|
||||
- focused package documentation describing the asset contract and release
|
||||
responsibility;
|
||||
- validation tests appropriate to data that the module can validate without
|
||||
importing Promptkit; and
|
||||
- an independent semantic version and release history.
|
||||
|
||||
The exported Go surface should remain limited to access to immutable embedded
|
||||
assets. The modules should use only the Go standard library at runtime. They
|
||||
must not import Promptkit, duplicate Promptkit's domain types, perform global
|
||||
registration in `init`, expose mutable registries, read process environment,
|
||||
or contain credentials.
|
||||
|
||||
The backend manifest format should include an explicit schema version.
|
||||
Promptkit should strictly reject unsupported versions, unknown fields,
|
||||
malformed values, and files outside the catalog contract. A structured
|
||||
standard-library format such as JSON is preferred for the backend manifest;
|
||||
the existing profile YAML format remains unchanged and continues to be parsed
|
||||
by Promptkit.
|
||||
|
||||
## Promptkit Integration
|
||||
|
||||
Add an internal catalog adapter that accepts an external catalog's `fs.FS` and
|
||||
root, decodes its backend manifest, exposes its profile assets through the
|
||||
existing profile repository boundary, and converts validated data into the
|
||||
existing internal domain types.
|
||||
|
||||
Engine construction should explicitly assemble the imported catalogs. Catalog
|
||||
packages must not register themselves through package initialization or other
|
||||
process-global mutable state. The internal backend registry should receive the
|
||||
assembled built-ins separately from engine-scoped consumer additions so that
|
||||
the distinction between maintained and consumer-owned IDs remains clear.
|
||||
|
||||
The assembled catalog must be validated before use. Validation should cover at
|
||||
least:
|
||||
|
||||
- a supported catalog-manifest schema version;
|
||||
- all existing backend invariants, including endpoint, environment-variable,
|
||||
concurrency, queue-capacity, and extra-parameter rules;
|
||||
- duplicate backend IDs across imported catalogs;
|
||||
- duplicate profile IDs within or across imported catalogs;
|
||||
- profile references to the backend owned by their catalog;
|
||||
- profile-format and inheritance validity under Promptkit's existing rules;
|
||||
and
|
||||
- absence of raw API keys or other secret material.
|
||||
|
||||
Invalid maintained catalog data should fail engine construction through the
|
||||
existing configuration-error boundary with enough source context for a
|
||||
maintainer to identify the catalog, while avoiding content or credential
|
||||
leakage.
|
||||
|
||||
Imported profile repositories remain the lowest-precedence profile source.
|
||||
Configured, fallback, and in-memory consumer sources retain their existing
|
||||
precedence and override behavior. Consumer backend registration continues to
|
||||
accept only new IDs and cannot replace a maintained built-in.
|
||||
|
||||
## Compatibility Requirements
|
||||
|
||||
The extraction must preserve consumer-visible behavior. In particular:
|
||||
|
||||
- `BackendOpenRouter` and `BackendRakestrawHome` retain their current names and
|
||||
values in the root Promptkit package;
|
||||
- every current built-in profile retains its ID, model, backend, settings,
|
||||
output behavior, and inheritance behavior;
|
||||
- each backend retains its endpoint, API-key environment variable,
|
||||
concurrency limit, queue capacity, and extra parameters;
|
||||
- built-ins remain available without additional consumer options;
|
||||
- consumer-defined backend and profile behavior remains unchanged;
|
||||
- preparation, execution, errors, capacity, and credential handling remain
|
||||
Promptkit responsibilities; and
|
||||
- no new catalog implementation types appear in Promptkit's public API.
|
||||
|
||||
Promptkit should record the complete pre-extraction built-in catalog in a
|
||||
reviewable compatibility fixture or equivalent test-owned snapshot before
|
||||
switching data sources. Integration tests must prove that the imported
|
||||
catalogs reproduce it exactly and that source precedence and reserved-ID
|
||||
behavior remain unchanged.
|
||||
|
||||
## Migration Safety Requirements
|
||||
|
||||
The migration must not publish a Promptkit state with either zero runtime
|
||||
owners or two overlaid runtime owners for maintained catalog data. Every
|
||||
external module version selected in `go.mod` must already be published and
|
||||
resolvable through ordinary Go module tooling. The frozen pre-extraction
|
||||
compatibility baseline remains test-owned migration evidence rather than a
|
||||
runtime fallback.
|
||||
|
||||
At cutover, Promptkit must use only the imported modules for runtime catalog
|
||||
assembly and must remove its embedded profiles and hard-coded backend
|
||||
definitions in the same accepted source state. That source state must pass the
|
||||
ordinary and race-enabled test suites, static analysis, builds, maintained
|
||||
examples, compatibility checks, and repository-hygiene validation. The final
|
||||
tree has one authoritative runtime data owner for each built-in catalog.
|
||||
|
||||
## Catalog Version And Release Policy
|
||||
|
||||
Promptkit's `go.mod` should pin catalog versions that have passed Promptkit's
|
||||
full integration suite. Catalog dependencies should not use local replacement
|
||||
directives or require a committed Go workspace. The complete module graph and
|
||||
checksums remain the reproducible identity of a consumer build.
|
||||
|
||||
Catalog repositories should adopt an explicit compatibility policy before
|
||||
their first release:
|
||||
|
||||
- adding a new profile is ordinarily backward compatible;
|
||||
- stable profile IDs should not silently be reassigned to unrelated models;
|
||||
- metadata corrections should preserve the documented meaning of an ID;
|
||||
- removals should account for consumer reliance and upstream model
|
||||
deprecation, with notice or an appropriate catalog version boundary when
|
||||
practicable; and
|
||||
- manifest-schema changes must remain compatible with the Promptkit versions
|
||||
that consume that module version.
|
||||
|
||||
Go module version selection may allow an advanced consumer to select a newer
|
||||
compatible transitive catalog release. Promptkit guarantees only the versions
|
||||
it pins and tests. This possibility must not require a new Promptkit API or
|
||||
weaken the catalog compatibility policy.
|
||||
|
||||
## Documentation And Release Impact
|
||||
|
||||
When the extraction lands, update current-state documentation to reflect that
|
||||
Promptkit imports rather than embeds its maintained catalog data. The framework
|
||||
format reference remains the canonical consumer owner of built-in backend and
|
||||
profile behavior. Internal architecture and component documentation should
|
||||
describe the external asset boundary without duplicating the catalog's
|
||||
contents.
|
||||
|
||||
The Promptkit release adopting the modules should include a short consumer
|
||||
release note explaining the new dependency boundary and confirming that no
|
||||
configuration migration is required. Catalog repository documentation should
|
||||
link consumers back to Promptkit for runtime behavior and configuration rather
|
||||
than becoming a parallel Promptkit manual.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
This feature does not:
|
||||
|
||||
- change Promptkit's root public API or require consumers to import catalogs;
|
||||
- add runtime plugin discovery, network catalog downloads, or dynamic module
|
||||
loading;
|
||||
- allow a consumer to replace a maintained backend ID;
|
||||
- move backend execution, transport, credential, or concurrency logic out of
|
||||
Promptkit;
|
||||
- define a general public catalog-authoring SDK;
|
||||
- automatically select untested catalog releases at runtime;
|
||||
- guarantee that an upstream provider continues to serve every cataloged
|
||||
model; or
|
||||
- extract consumer-defined backends or profiles from their owning
|
||||
applications.
|
||||
|
||||
## Completion Criteria
|
||||
|
||||
The feature is complete when:
|
||||
|
||||
- both external catalog repositories have released usable, tested modules;
|
||||
- Promptkit imports and explicitly assembles both catalogs through a private
|
||||
adapter;
|
||||
- compatibility tests prove parity with every previously built-in backend and
|
||||
profile;
|
||||
- ordinary consumer construction and configuration require no changes;
|
||||
- consumer overlays and reserved backend IDs retain their behavior;
|
||||
- Promptkit contains no duplicate embedded catalog assets or hard-coded
|
||||
definitions for the extracted backends;
|
||||
- all required Promptkit validation succeeds without a workspace, replacement
|
||||
directive, real credential, or provider network call; and
|
||||
- current-state and release documentation accurately describe the resulting
|
||||
dependency boundary.
|
||||
@@ -1,661 +0,0 @@
|
||||
# External Backend Catalogs Implementation Plan
|
||||
|
||||
## Purpose
|
||||
|
||||
This document is the ordered implementation plan for the target state in
|
||||
[external-backend-catalogs.md](external-backend-catalogs.md). It is written for
|
||||
a coding agent implementing one stage per prompt, in order. The feature
|
||||
roadmap owns the intended end state, compatibility policy, migration safety
|
||||
requirements, and non-goals; this document owns sequencing and concrete
|
||||
implementation decisions.
|
||||
|
||||
The work spans these three sibling repositories:
|
||||
|
||||
- `/home/eric/Workspace/promptkit` with module path
|
||||
`gitea.maximumdirect.net/eric/promptkit`;
|
||||
- `/home/eric/Workspace/promptkit-backend-openrouter` with module path
|
||||
`gitea.maximumdirect.net/eric/promptkit-backend-openrouter`; and
|
||||
- `/home/eric/Workspace/promptkit-backend-rakestrawhome` with module path
|
||||
`gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome`.
|
||||
|
||||
## Cross-Stage Constraints
|
||||
|
||||
Apply these constraints throughout every stage:
|
||||
|
||||
- Read and follow each repository's `AGENTS.md` and contributor documentation
|
||||
before changing it. In Promptkit, always follow
|
||||
[docs/development.md](../development.md),
|
||||
[docs/policy/architecture.md](../policy/architecture.md),
|
||||
[docs/policy/documentation.md](../policy/documentation.md), and
|
||||
[docs/policy/testing.md](../policy/testing.md).
|
||||
- Implement exactly one stage per prompt. Start a stage only after every prior
|
||||
stage's completion criteria are satisfied and committed. Preserve unrelated
|
||||
work in all three worktrees and commit only the stage's intended files.
|
||||
- Keep Promptkit an importable Go library. Do not add a command, service,
|
||||
runtime catalog download, global registration, mutable registry, or public
|
||||
Promptkit catalog API.
|
||||
- Keep `BackendOpenRouter` and `BackendRakestrawHome`, their exact values, and
|
||||
all current consumer construction and source-precedence behavior unchanged.
|
||||
- Keep the external modules data-only. Their non-test package code may import
|
||||
only `embed` and `io/fs`; it must not import Promptkit, read environment
|
||||
variables, perform network calls, or expose mutable assets.
|
||||
- Use no committed `go.work`, `go.work.sum`, vendor tree, or `replace`
|
||||
directive. Temporary local workspaces may be used only for exploratory
|
||||
development and must be disabled for acceptance. Every dependency and
|
||||
release check must succeed with `GOWORK=off` through ordinary module
|
||||
resolution.
|
||||
- Keep all default tests deterministic, offline, and credential-free. Remote
|
||||
publication and module-resolution checks are release gates, not test-suite
|
||||
behavior.
|
||||
- Treat copying the Promptkit-maintained catalog assets into the LGPL-3.0
|
||||
external repositories as an intentional copyright-holder relicensing
|
||||
decision. Preserve source provenance and record that decision in both
|
||||
catalog READMEs; do not imply that an ordinary dependency extraction alone
|
||||
changes an asset's license.
|
||||
- Update the canonical current-state documentation in the same commit that
|
||||
introduces or changes the behavior it describes. In particular, do not
|
||||
defer an implemented-package inventory or source-boundary update to a later
|
||||
stage merely because the feature has not reached runtime cutover.
|
||||
- Treat catalog content and compatibility as high-risk data-integrity work.
|
||||
Test strict decoding, duplicates, source ownership, immutable copies,
|
||||
precedence, and exact pre-extraction parity at their narrowest owners; do
|
||||
not repeat the same malformed-input matrix through the public facade.
|
||||
- Never include catalog file contents, extra-parameter values, environment
|
||||
values, or candidate secret values in new diagnostics. Errors may identify
|
||||
the catalog display name and repository-relative asset path.
|
||||
- Do not publish or move a tag that already exists. If a planned external
|
||||
module tag exists locally or remotely, verify that it identifies the exact
|
||||
intended release commit; otherwise stop and report the conflict.
|
||||
- Do not create a Promptkit release tag as part of these stages. The external
|
||||
modules must be released because Promptkit needs resolvable versions, but
|
||||
Promptkit release publication remains governed by
|
||||
[docs/release.md](../release.md) after the feature is accepted.
|
||||
|
||||
## Shared Catalog Asset Contract
|
||||
|
||||
Stages 2 through 6 must use this exact contract in both external modules and
|
||||
Promptkit's private adapter:
|
||||
|
||||
- The module root package is named `openrouter` or `rakestrawhome`, matching
|
||||
the backend. It exports only:
|
||||
|
||||
```go
|
||||
const Root = "catalog"
|
||||
func FS() fs.FS
|
||||
```
|
||||
|
||||
`FS` returns the package's embedded filesystem as an `fs.FS`; callers cannot
|
||||
replace or mutate the embedded value. Both declarations require accurate
|
||||
GoDoc.
|
||||
- The embedded tree contains `catalog/backend.json` and one or more profile
|
||||
files below `catalog/profiles/`. Directories are allowed below `profiles`;
|
||||
every nondirectory entry there must be a regular `.yml` file. No other file,
|
||||
symlink, or special entry is part of the embedded tree.
|
||||
- `backend.json` is one strict JSON object with these required fields and no
|
||||
others:
|
||||
|
||||
```json
|
||||
{
|
||||
"schema_version": 1,
|
||||
"id": "openrouter",
|
||||
"endpoint": "https://openrouter.ai/api/v1",
|
||||
"api_key_env": "OPENROUTER_API_KEY",
|
||||
"concurrency_limit": 16,
|
||||
"queue_capacity": 1024,
|
||||
"extra_params": null
|
||||
}
|
||||
```
|
||||
|
||||
The Rakestrawhome manifest changes `id` to `rakestrawhome`, `endpoint` to
|
||||
`https://inference.ai.rakestrawhome.com/v1`, `api_key_env` to
|
||||
`RAKESTRAWHOME_INFERENCE_API_KEY`, and `concurrency_limit` to `4`; it keeps
|
||||
`schema_version: 1`, `queue_capacity: 1024`, and `extra_params: null`.
|
||||
`extra_params` may be a JSON object in later compatible catalog releases,
|
||||
but it remains `null` for the compatibility baseline.
|
||||
- Schema version `1` requires an integer version, a nonblank ID, endpoint, and
|
||||
environment-variable name, a positive integer concurrency limit, a
|
||||
nonnegative integer queue capacity whose sum with the concurrency limit fits
|
||||
in `int`, and `extra_params` equal to `null` or an object. Promptkit also
|
||||
applies all existing endpoint, environment-name, reserved-field, and bounded
|
||||
JSON-value validation.
|
||||
- OpenRouter owns every existing built-in profile except
|
||||
`rakestrawhome-gemma-4-31b`; Rakestrawhome owns exactly that profile at the
|
||||
initial release. Copy the YAML bytes without changing IDs or behavior.
|
||||
- Each catalog is self-contained: every `base_profile` must resolve inside the
|
||||
same module. A locally resolved profile must select the manifest's backend
|
||||
ID. Raw catalog profiles must not provide `endpoint`, `api_key_env`, or a raw
|
||||
API key; connection and credential-source metadata comes from the manifest.
|
||||
- Strict source decoding and the bounded JSON-value rules are the primary
|
||||
secret-safety controls. In addition, recursively reject case-insensitive
|
||||
catalog `extra_params` keys named `api_key`, `apikey`, `authorization`,
|
||||
`credential`, `credentials`, `password`, `secret`, `token`, or
|
||||
`access_token`. `api_key_env` is the sole permitted credential-related
|
||||
catalog field. Do not use value-pattern heuristics as a substitute for
|
||||
structural validation; retain Promptkit's repository credential scan as a
|
||||
separate acceptance check.
|
||||
- Both external modules start at `v1.0.0`. The two-function/constant asset
|
||||
surface and manifest schema are intentionally stable; normal profile-data
|
||||
changes use later semantic versions according to each module's compatibility
|
||||
policy.
|
||||
|
||||
## Stage 1: Freeze The Pre-Extraction Compatibility Baseline
|
||||
|
||||
**Status:** Complete
|
||||
|
||||
### Repository
|
||||
|
||||
`/home/eric/Workspace/promptkit`
|
||||
|
||||
### Objective
|
||||
|
||||
Record the complete current built-in catalog before any data is copied or any
|
||||
runtime assembly changes. This stage must leave Promptkit using its existing
|
||||
hard-coded backend definitions and embedded profile repository.
|
||||
|
||||
### Implementation
|
||||
|
||||
1. Add `testdata/builtin-catalog-v1.json` as a reviewable, permanently frozen
|
||||
compatibility fixture. Represent both normalized backend definitions and
|
||||
every raw built-in profile. Include all fields whose zero, empty, nil, or
|
||||
explicit state affects behavior, including `queue_capacity_set`,
|
||||
`base_profile`, backend, endpoint, model, execution settings,
|
||||
`api_key_env`, `api_key_required`, and `extra_params`. Sort backends by ID
|
||||
and profiles by ID so diffs are deterministic.
|
||||
2. Add a focused compatibility test under `internal/profile/builtin` that
|
||||
reads the fixture, obtains normalized built-ins from
|
||||
`internal/backend.Registry`, discovers every current embedded profile, and
|
||||
compares complete semantic values. Compare both directions so a missing or
|
||||
extra backend/profile fails. Reuse the package's existing asset discovery
|
||||
and profile repository rather than adding production enumeration APIs in
|
||||
this stage.
|
||||
3. Do not provide an automatic golden-file update path. The snapshot describes
|
||||
the migration baseline and must change only by deliberate review of the
|
||||
fixture itself.
|
||||
|
||||
### Tests And Validation
|
||||
|
||||
1. Run the focused `internal/backend` and `internal/profile/builtin` tests.
|
||||
2. Run `go test ./...` and `go test -race ./...`.
|
||||
3. Inspect the fixture diff against the current YAML and backend constants,
|
||||
confirm that it contains no credential value, and run the Promptkit
|
||||
credential scan from the development guide.
|
||||
|
||||
### Completion Criteria
|
||||
|
||||
- One deterministic fixture accounts for both current backends and every
|
||||
current raw built-in profile.
|
||||
- The fixture test fails for added, removed, or semantically changed catalog
|
||||
data.
|
||||
- Promptkit runtime construction and production code are unchanged.
|
||||
|
||||
## Stage 2: Build And Release The OpenRouter Catalog Module
|
||||
|
||||
**Status:** Complete
|
||||
|
||||
### Repository
|
||||
|
||||
`/home/eric/Workspace/promptkit-backend-openrouter`
|
||||
|
||||
### Objective
|
||||
|
||||
Create the independently testable OpenRouter data module, publish its source
|
||||
commit, and release immutable tag `v1.0.0` before Promptkit depends on it.
|
||||
|
||||
### Implementation
|
||||
|
||||
1. Initialize `go.mod` with module path
|
||||
`gitea.maximumdirect.net/eric/promptkit-backend-openrouter` and Go version
|
||||
`1.25.5`. Name the root package `openrouter`.
|
||||
2. Add `catalog/backend.json` using the exact OpenRouter manifest from the
|
||||
shared contract. Copy every current OpenRouter-owned YAML asset from
|
||||
`promptkit/internal/profile/builtin/assets/` into
|
||||
`catalog/profiles/<provider>/` without editing its bytes. Record in the
|
||||
README that the Promptkit-maintained source assets are intentionally being
|
||||
distributed under this repository's LGPL-3.0 terms with authorization from
|
||||
their copyright holder, and identify Promptkit as their source provenance.
|
||||
3. Add the private embedded filesystem and the exact `Root`/`FS` public
|
||||
surface. Embed only `catalog`, return the embedded filesystem by value
|
||||
behind `fs.FS`, and add package GoDoc explaining that the module supplies
|
||||
immutable Promptkit catalog assets rather than runtime provider behavior.
|
||||
4. Replace the placeholder README with concise ownership, consumption,
|
||||
compatibility, and validation guidance. State that Promptkit owns parsing,
|
||||
runtime behavior, credentials, and consumer documentation; catalog releases
|
||||
own OpenRouter manifest/profile data. Document the roadmap's ID stability,
|
||||
additive profile, correction, deprecation/removal, and manifest-schema
|
||||
compatibility policy.
|
||||
5. Add `docs/release.md` with a source-only semantic-tag procedure. Require a
|
||||
clean synchronized `main`, no workspace/replacement/vendor tree, complete
|
||||
validation, an annotated tag, publication of only the selected tag, remote
|
||||
tag verification, and resolution from a temporary module with `GOWORK=off`.
|
||||
6. Add focused tests that use the exported `FS` and `Root` and verify the exact
|
||||
embedded layout, strict manifest shape and owner ID, at least one profile,
|
||||
unique trimmed profile IDs, backend selection equal to `openrouter`, no
|
||||
connection fields or raw API key in profiles, and no forbidden secret key
|
||||
in nested extra parameters. A test-only `gopkg.in/yaml.v3` dependency is
|
||||
permitted for robust YAML-node inspection; confirm that the non-test root
|
||||
package's dependency graph remains standard-library-only.
|
||||
7. Run `go mod tidy`, commit the module with a short plain-English message,
|
||||
push `main`, create annotated tag `v1.0.0`, push only that tag, and perform
|
||||
the documented remote and temporary-module resolution checks. Never use a
|
||||
local replacement to satisfy the resolution check.
|
||||
|
||||
### Tests And Validation
|
||||
|
||||
- Run `go test ./...`, `go test -race ./...`, `go vet ./...`, and
|
||||
`go build ./...` with `GOWORK=off`.
|
||||
- Require `gofmt -l` to report no tracked Go files and run `git diff --check`
|
||||
before committing.
|
||||
- Confirm `GOWORK=off go list -deps .` contains no non-standard-library
|
||||
runtime package and scan tracked content for credentials.
|
||||
- After publication, resolve
|
||||
`gitea.maximumdirect.net/eric/promptkit-backend-openrouter@v1.0.0` from a
|
||||
temporary module and verify the returned version.
|
||||
|
||||
### Completion Criteria
|
||||
|
||||
- The OpenRouter module contains its manifest and the complete copied profile
|
||||
set behind the exact immutable asset API.
|
||||
- Its validation is offline and its runtime package is standard-library-only.
|
||||
- `main` and annotated tag `v1.0.0` are published and independently resolvable.
|
||||
|
||||
## Stage 3: Build And Release The Rakestrawhome Catalog Module
|
||||
|
||||
**Status:** Complete
|
||||
|
||||
### Repository
|
||||
|
||||
`/home/eric/Workspace/promptkit-backend-rakestrawhome`
|
||||
|
||||
### Objective
|
||||
|
||||
Create and publish the matching Rakestrawhome data module without coupling its
|
||||
release history or package implementation to the OpenRouter module.
|
||||
|
||||
### Implementation
|
||||
|
||||
1. Repeat the module, package, immutable asset API, package documentation,
|
||||
README policy, and `docs/release.md` structure from Stage 2, using module
|
||||
path `gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome`, package
|
||||
name `rakestrawhome`, and Go version `1.25.5`.
|
||||
2. Add the exact Rakestrawhome manifest from the shared contract. Copy only
|
||||
`google/rakestrawhome-gemma-4-31b.yml` into
|
||||
`catalog/profiles/google/`, without editing its bytes. Apply the same
|
||||
explicit LGPL-3.0 relicensing and Promptkit source-provenance statement as
|
||||
Stage 2.
|
||||
3. Apply the same focused asset tests, changing the expected backend to
|
||||
`rakestrawhome` and the initial profile set to the single owned profile.
|
||||
Keep the module independent: do not import or share code with either
|
||||
Promptkit or the OpenRouter module.
|
||||
4. Run the same validation and release sequence as Stage 2, commit and push
|
||||
`main`, publish annotated tag `v1.0.0`, and verify ordinary module
|
||||
resolution without a workspace or replacement.
|
||||
|
||||
### Tests And Validation
|
||||
|
||||
Use the complete Stage 2 validation list with the Rakestrawhome module path.
|
||||
Inspect the copied profile against Promptkit's Stage 1 fixture before release.
|
||||
|
||||
### Completion Criteria
|
||||
|
||||
- The Rakestrawhome module contains exactly its owned backend and profile data
|
||||
behind the same stable asset contract.
|
||||
- Its tests, build, runtime dependency check, credential scan, and remote
|
||||
resolution all pass.
|
||||
- `main` and annotated tag `v1.0.0` are published and independently resolvable.
|
||||
|
||||
## Stage 4: Add Eager Immutable Profile Loading To Promptkit
|
||||
|
||||
**Status:** Complete
|
||||
|
||||
### Repository
|
||||
|
||||
`/home/eric/Workspace/promptkit`
|
||||
|
||||
### Objective
|
||||
|
||||
Add the reusable profile-package primitive needed to validate an immutable
|
||||
external catalog completely at engine construction, without changing the lazy
|
||||
point-in-time semantics of consumer-configured profile sources.
|
||||
|
||||
### Implementation
|
||||
|
||||
1. In `internal/profile`, add:
|
||||
|
||||
```go
|
||||
type LoadedProfileMetadata struct {
|
||||
ID string
|
||||
Path string
|
||||
ExplicitFields []string
|
||||
}
|
||||
|
||||
func LoadFSRepository(
|
||||
ctx context.Context,
|
||||
fsys fs.FS,
|
||||
root string,
|
||||
) (Repository, []LoadedProfileMetadata, error)
|
||||
```
|
||||
|
||||
It must discover sorted YAML paths through `internal/filecatalog`, read each
|
||||
file once, require exactly one document, strictly decode the existing
|
||||
profile schema, reject raw API keys, normalize and validate each raw
|
||||
definition through the existing owners, and reject duplicate trimmed IDs.
|
||||
Return an immutable in-memory raw repository plus a newly allocated metadata
|
||||
slice sorted by normalized profile ID. Each metadata entry contains that ID,
|
||||
the safe root-relative source path, and a newly allocated sorted list of the
|
||||
exact top-level YAML field names present in the source document. An empty
|
||||
source returns an empty repository and metadata slice; the catalog adapter,
|
||||
not this generic primitive, decides whether emptiness is invalid. All three
|
||||
fields, the type, and the function are internal to the Promptkit module but
|
||||
require accurate GoDoc because they cross internal package boundaries.
|
||||
2. Refactor existing private decode/metadata logic only as needed so eager and
|
||||
point lookup share strict decoding, source-path context, raw-key rejection,
|
||||
normalization, and defensive JSON-value copying. Do not change
|
||||
`NewFSRepository`: configured and fallback consumer sources must retain
|
||||
fresh point-in-time reads and their current error-preserving fallback
|
||||
semantics. Derive `ExplicitFields` during the same source read and through
|
||||
the existing YAML-node metadata path; do not make the later catalog adapter
|
||||
reread or independently parse profile YAML.
|
||||
3. The returned repository must honor context cancellation before lookup,
|
||||
return `ErrProfileNotFound` for absence, and publish a fresh profile value
|
||||
with a deeply copied `ExtraParams` tree on every successful lookup. Do not
|
||||
pre-resolve `base_profile`; the raw repository must remain suitable for the
|
||||
existing outer resolving repository and consumer shadowing rules.
|
||||
4. Update `docs/internal/sources.md` in the same commit to describe the eager
|
||||
immutable loader as an implemented internal profile boundary. Make clear
|
||||
that configured consumer sources remain lazy and that engine assembly still
|
||||
uses the existing embedded built-ins at this stage.
|
||||
|
||||
### Tests And Validation
|
||||
|
||||
1. Add focused profile-package tests for sorted metadata, exact explicit-field
|
||||
presence including explicitly empty values, safe relative paths, strict
|
||||
malformed-input rejection, duplicate IDs, raw API-key rejection, empty
|
||||
input, cancellation, and defensive copies of metadata and profile values.
|
||||
Reuse representative existing fixtures and avoid repeating the entire
|
||||
profile rule matrix already owned by point lookup.
|
||||
2. Add a parity test showing that eager and ordinary FS repositories publish
|
||||
the same raw semantic value for representative standalone and derived
|
||||
profiles.
|
||||
3. Run `go test ./internal/profile`, `go test -race ./internal/profile`, and
|
||||
`go test ./...`.
|
||||
|
||||
### Completion Criteria
|
||||
|
||||
- Promptkit can eagerly load and validate all raw profiles from an `fs.FS`
|
||||
without creating a second YAML contract implementation.
|
||||
- Returned metadata and profile values are caller-independent, and the
|
||||
metadata preserves the distinction between an absent field and an explicitly
|
||||
empty field.
|
||||
- Existing configured, fallback, in-memory, and built-in runtime behavior is
|
||||
unchanged.
|
||||
- The internal source document accurately distinguishes eager immutable loads
|
||||
from existing point-in-time consumer source lookup.
|
||||
|
||||
## Stage 5: Add And Verify The Private Catalog Adapter
|
||||
|
||||
**Status:** Complete
|
||||
|
||||
### Repository
|
||||
|
||||
`/home/eric/Workspace/promptkit`
|
||||
|
||||
### Objective
|
||||
|
||||
Import the two published module versions and validate them through one private
|
||||
Promptkit adapter while retaining the existing embedded/hard-coded runtime
|
||||
source as the active implementation.
|
||||
|
||||
### Implementation
|
||||
|
||||
1. Add direct requirements at `v1.0.0` for both external module paths and run
|
||||
`go mod tidy` with `GOWORK=off`. Do not add a replacement or workspace.
|
||||
2. Add `internal/catalog` with this internal contract:
|
||||
|
||||
```go
|
||||
type Source struct {
|
||||
Name string
|
||||
ExpectedBackendID string
|
||||
FS fs.FS
|
||||
Root string
|
||||
}
|
||||
|
||||
type Set struct {
|
||||
Backends []domain.Backend
|
||||
Profiles profile.Repository
|
||||
}
|
||||
|
||||
func Load(sources ...Source) (Set, error)
|
||||
```
|
||||
|
||||
`Name` is a safe maintainer-facing label used in errors; reject blank or
|
||||
duplicate names. Require nonnil filesystems, valid non-root asset roots,
|
||||
nonblank expected IDs, and at least one source. Return caller-independent
|
||||
backend values and one raw immutable composite profile repository.
|
||||
3. Strictly enforce the shared asset layout and manifest schema. Use
|
||||
`json.Decoder.DisallowUnknownFields`, require exactly one JSON value, use
|
||||
presence-aware raw fields so missing required fields differ from zero or
|
||||
`null`, reject unsupported schema versions, and check the manifest ID
|
||||
against `ExpectedBackendID`. When constructing `domain.Backend`, set
|
||||
`QueueCapacitySet` to `true` because schema version 1 requires an explicit
|
||||
`queue_capacity`; this ensures normalization preserves later compatible
|
||||
releases that intentionally select a non-default capacity.
|
||||
4. Rename the existing private backend normalizer to the internal exported
|
||||
`backend.NormalizeDefinition` and have both `Registry` and the catalog
|
||||
adapter call it. This remains inside Go's `internal` boundary and is not a
|
||||
Promptkit public API. Do not duplicate endpoint, environment-name,
|
||||
capacity, reserved-field, or bounded JSON-value policy in the adapter.
|
||||
5. For each source, call `profile.LoadFSRepository` on `<root>/profiles`.
|
||||
Reject an empty profile set. Use the returned explicit-field metadata to
|
||||
reject `endpoint` or `api_key_env` whenever the key is present, including
|
||||
when its YAML value is explicitly empty; do not infer source presence from
|
||||
the decoded profile's zero values. Validate every raw profile's nested extra
|
||||
parameters for forbidden secret keys. Resolve every metadata ID through a
|
||||
source-local `profile.NewResolvingRepository`; this both proves inheritance
|
||||
is self-contained and verifies that the final backend ID equals the manifest
|
||||
owner.
|
||||
6. Reject duplicate backend IDs and duplicate raw profile IDs across sources.
|
||||
Compose the already validated raw repositories in source order only after
|
||||
duplicate checks pass. Do not pre-resolve the returned composite: the root
|
||||
engine must later place consumer sources above it and apply one outer
|
||||
resolver to preserve base-profile shadowing semantics.
|
||||
7. Keep errors bounded and redacted. Wrap failures with the safe source name
|
||||
and relative path where available, but never include raw JSON/YAML values or
|
||||
extra-parameter content.
|
||||
8. Add an integration test that imports the released `openrouter` and
|
||||
`rakestrawhome` packages, supplies their `FS()`/`Root` values with expected
|
||||
backend IDs, loads the set, and compares it exactly with
|
||||
`testdata/builtin-catalog-v1.json`. Keep the Stage 1 test against the old
|
||||
source too; at this point both tests must pass while only the old source
|
||||
participates in engine construction.
|
||||
9. Update `docs/policy/architecture.md`, `docs/internal/overview.md`, and
|
||||
`docs/internal/sources.md` in the same commit. Describe `internal/catalog`
|
||||
as an implemented private validation/adapter boundary and the external
|
||||
modules as imported immutable test-verified sources, while stating
|
||||
accurately that root engine assembly still uses the original built-in
|
||||
runtime source until cutover.
|
||||
|
||||
### Tests And Validation
|
||||
|
||||
1. At `internal/catalog`, use `testing/fstest.MapFS` tables for nil/invalid
|
||||
sources, layout violations, strict/trailing/missing/unsupported manifests,
|
||||
backend normalization failures, empty profiles, malformed profiles,
|
||||
cross-source duplicates, missing/cyclic/cross-catalog bases, owner mismatch,
|
||||
prohibited connection fields, secret-like nested keys, defensive copies,
|
||||
and redacted source-aware errors.
|
||||
2. Keep exhaustive YAML rules in `internal/profile` and backend invariants in
|
||||
`internal/backend`; adapter tests must prove delegation and assembly, not
|
||||
duplicate those packages' full matrices.
|
||||
3. Run focused tests for `internal/profile`, `internal/backend`, and
|
||||
`internal/catalog`, followed by `go test ./...`, `go test -race ./...`,
|
||||
`go vet ./...`, and `go build ./...`.
|
||||
4. With `GOWORK=off`, verify `go list -m all` selects exactly `v1.0.0` for both
|
||||
catalogs and `go mod verify` succeeds.
|
||||
|
||||
### Completion Criteria
|
||||
|
||||
- Both released external catalogs load through one strict private adapter and
|
||||
exactly match the frozen baseline.
|
||||
- Every maintained profile is eagerly validated locally and across the
|
||||
assembled set before publication.
|
||||
- Promptkit still executes exclusively from its original built-in data source.
|
||||
- The current-state architecture and internal inventory describe this
|
||||
transitional implemented boundary without claiming that cutover is complete.
|
||||
|
||||
## Stage 6: Cut Promptkit Over To The External Catalogs
|
||||
|
||||
**Status:** Complete
|
||||
|
||||
### Repository
|
||||
|
||||
`/home/eric/Workspace/promptkit`
|
||||
|
||||
### Objective
|
||||
|
||||
Make the validated external modules Promptkit's sole runtime owners for the
|
||||
maintained backends and profiles, then remove every duplicate production copy
|
||||
from Promptkit in the same committed cutover.
|
||||
|
||||
### Implementation
|
||||
|
||||
1. In root engine assembly, import the two external packages with unambiguous
|
||||
aliases and construct `catalog.Source` values in deterministic OpenRouter,
|
||||
Rakestrawhome order. Use safe display names plus
|
||||
`backend.OpenRouterID`/`backend.RakestrawHomeID` as the expected IDs.
|
||||
2. Load the maintained `catalog.Set` during `NewEngine` after options and the
|
||||
required prompt source have been validated, but before constructing the
|
||||
backend registry, capacity manager, or runner. Map any load failure to
|
||||
`ErrInvalidConfig` with the prefix `failed to load maintained catalogs` and
|
||||
preserve redacted catalog/path context. Add no new public error identity.
|
||||
3. Change `backend.NewRegistry` to accept maintained definitions and consumer
|
||||
additions as separate slices. Normalize and copy both through the same
|
||||
path, insert maintained definitions first, and reject every duplicate
|
||||
across or within the two groups. This preserves the rule that a consumer
|
||||
cannot replace a maintained ID without retaining hard-coded maintained
|
||||
definitions inside the registry package.
|
||||
4. Change `newProfileRepository` to accept the maintained raw repository as
|
||||
its lowest-precedence source. Preserve this exact overlay order: in-memory,
|
||||
ordinary configured file/FS/directory, application fallback, maintained
|
||||
external catalog. Continue to wrap the complete raw overlay in exactly one
|
||||
`profile.NewResolvingRepository`.
|
||||
5. Delete `internal/profile/builtin`, including its embedded YAML assets, and
|
||||
delete `builtInBackends` plus the OpenRouter/Rakestrawhome endpoint,
|
||||
environment, and concurrency constants from `internal/backend`. Retain the
|
||||
internal backend ID constants because the root public constants still
|
||||
alias them, and retain the generic default queue-capacity policy used for
|
||||
consumer registrations.
|
||||
6. Move the Stage 1 compatibility assertion to `internal/catalog` and make it
|
||||
compare only the external loaded set to the frozen fixture. Remove tests
|
||||
whose sole purpose was the deleted duplicate source; retain or relocate
|
||||
distinct compatibility, reserved-ID, profile completeness, and native
|
||||
Rakestrawhome behavior coverage.
|
||||
7. Update registry and engine tests for explicit maintained definitions. Add
|
||||
only focused assembled-engine coverage needed to prove that ordinary
|
||||
construction includes both catalogs, consumer backend IDs cannot replace
|
||||
either maintained ID, consumer profiles still override catalog profiles,
|
||||
inherited base lookup still observes the complete precedence chain, and
|
||||
capacity/credential/endpoint behavior matches the compatibility fixture.
|
||||
Reuse existing public contract tests wherever they already protect these
|
||||
outcomes.
|
||||
8. Confirm with repository search and `go list -deps` that no production Go
|
||||
file embeds the old assets or hard-codes the extracted endpoints,
|
||||
environment-variable names, concurrency values, or profile model catalog.
|
||||
The frozen test fixture and canonical consumer documentation are the only
|
||||
permitted Promptkit copies of compatibility data.
|
||||
9. Update `docs/policy/architecture.md`, `docs/internal/overview.md`, and
|
||||
`docs/internal/sources.md` in the cutover commit: remove the transitional
|
||||
old-runtime description, remove `internal/profile/builtin`, and describe
|
||||
explicit root assembly plus eager maintained-catalog validation and the
|
||||
unchanged outer consumer overlay/resolution boundary.
|
||||
10. Update `docs/formats.md` where its current wording says the catalog is
|
||||
embedded or hard-coded. It remains the canonical consumer owner of the
|
||||
built-ins supplied by a Promptkit release, so retain the exact backend and
|
||||
profile tables after confirming them against the compatibility fixture.
|
||||
Do not duplicate pinned module versions there; `go.mod` owns them.
|
||||
|
||||
### Tests And Validation
|
||||
|
||||
- Run focused backend, catalog, profile, root engine, capacity, and public
|
||||
contract tests.
|
||||
- Run the complete Promptkit maintainer workflow from
|
||||
[docs/development.md](../development.md#maintainer-validation), including
|
||||
ordinary/race tests, vet, build, both offline examples, Go formatting,
|
||||
Markdown links, workspace/replacement/vendor guards, whitespace checks,
|
||||
ignored-file review, credential scan, and full diff/status inspection.
|
||||
- Run the complete workflow with `GOWORK=off` and no provider credentials.
|
||||
|
||||
### Completion Criteria
|
||||
|
||||
- Every new engine validates and uses both external catalogs automatically.
|
||||
- Public constants, effective backend/profile values, source precedence,
|
||||
inheritance, capacity, credentials, and consumer additions match the frozen
|
||||
baseline and existing contracts.
|
||||
- Promptkit has one runtime data owner: no embedded profile catalog or
|
||||
hard-coded extracted backend definition remains.
|
||||
|
||||
## Stage 7: Update Current-State And Release Documentation
|
||||
|
||||
**Status:** Complete
|
||||
|
||||
### Repository
|
||||
|
||||
`/home/eric/Workspace/promptkit`
|
||||
|
||||
### Objective
|
||||
|
||||
Make durable documentation describe the implemented dependency boundary,
|
||||
provide concise consumer-facing release guidance, and perform final acceptance
|
||||
across all three clean repositories.
|
||||
|
||||
### Implementation
|
||||
|
||||
1. Review the current-state changes made in Stages 4 through 6 against the
|
||||
final implementation. Correct any stale transitional language and ensure
|
||||
`docs/policy/architecture.md`, `docs/internal/overview.md`,
|
||||
`docs/internal/sources.md`, and `docs/formats.md` link to canonical owners
|
||||
instead of duplicating the manifest or complete catalog.
|
||||
2. Update `docs/development.md` with a task-specific reading-guide row for
|
||||
external catalog or maintained built-in changes. Route contributors to the
|
||||
internal source document, the format reference, testing policy, both module
|
||||
repositories, and each module's release procedure.
|
||||
3. Do not add a versionless supplemental release document during feature
|
||||
implementation. Record for the later Promptkit release-preparation pass that
|
||||
its versioned `docs/releases/vMAJOR.MINOR.PATCH.md` document should state
|
||||
that the release adds two independently versioned data dependencies,
|
||||
preserves the public API and configuration, requires no consumer migration,
|
||||
and guarantees only the catalog versions selected and tested by that
|
||||
Promptkit release. That document must link to canonical current-state
|
||||
documentation rather than restating its contracts.
|
||||
4. Update each external repository README only if the final implemented paths
|
||||
or links changed during integration. Do not turn either README into a
|
||||
parallel Promptkit consumer manual.
|
||||
5. Mark every stage in this plan complete only after its committed state and
|
||||
validation evidence exist. Leave Promptkit release tagging to the normal
|
||||
release procedure; the future annotated Promptkit tag message must include
|
||||
the dependency-boundary summary and the absence of consumer migration.
|
||||
|
||||
### Tests And Validation
|
||||
|
||||
1. Run the full Promptkit maintainer workflow, including the local Markdown
|
||||
link validator, with `GOWORK=off`.
|
||||
2. In each external module, run its full test/race/vet/build, formatting,
|
||||
hygiene, credential, and ordinary module-resolution checks.
|
||||
3. From a temporary module, download both external `v1.0.0` versions and the
|
||||
current Promptkit commit's module dependencies without a workspace or
|
||||
replacement. Promptkit itself need not be tagged in this stage.
|
||||
4. Inspect all three worktrees and their committed diffs. Require each to be
|
||||
clean and confirm that Promptkit's `go.mod`/`go.sum` identify the published
|
||||
catalog versions.
|
||||
|
||||
### Completion Criteria
|
||||
|
||||
- Durable current-state documents accurately describe the external asset
|
||||
boundary without duplicating implementation-plan detail.
|
||||
- The later versioned release-document requirements are explicit without
|
||||
creating a release note before a Promptkit version has been selected.
|
||||
- All completion criteria in the feature roadmap hold, all three repositories
|
||||
are clean, and the complete offline validation passes without credentials,
|
||||
a workspace, a replacement, or provider network access.
|
||||
|
||||
## Open Questions
|
||||
|
||||
None. The implementation decisions required by this roadmap are fixed above.
|
||||
Reference in New Issue
Block a user