Prepare the v0.10.0 release
This commit is contained in:
@@ -33,7 +33,7 @@ boundary and constraints that framework work must preserve.
|
||||
|
||||
## Release Guidance
|
||||
|
||||
Consumers preparing for the unreleased `v0.10.0` profile-policy transition
|
||||
Consumers upgrading to the `v0.10.0` profile-policy transition
|
||||
should read the [v0.10.0 transition guide](docs/releases/v0.10.0.md).
|
||||
|
||||
Consumers upgrading from `v0.8.0` to `v0.9.0` should read the
|
||||
|
||||
@@ -264,7 +264,7 @@ only the setting it owns:
|
||||
```go
|
||||
promptkit.WithProfiles(promptkit.Profile{
|
||||
ID: "weather-light",
|
||||
BaseProfileID: "deepseek-4-flash",
|
||||
BaseProfileID: "promptkit-openrouter-standard",
|
||||
ReasoningEffort: "high",
|
||||
})
|
||||
```
|
||||
|
||||
@@ -346,7 +346,7 @@ cross-version guarantee for these names.
|
||||
The external profile inventory is defined by the selected catalog modules, not
|
||||
duplicated here. Browse the exact data selected by this Promptkit version:
|
||||
|
||||
- [OpenRouter catalog v2.20260922.0 profiles](https://gitea.maximumdirect.net/eric/promptkit-backend-openrouter/src/tag/v2.20260922.0/catalog/profiles)
|
||||
- [OpenRouter catalog v2.20260922.1 profiles](https://gitea.maximumdirect.net/eric/promptkit-backend-openrouter/src/tag/v2.20260922.1/catalog/profiles)
|
||||
- [Rakestrawhome catalog v2.20260922.0 profiles](https://gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome/src/tag/v2.20260922.0/catalog/profiles)
|
||||
|
||||
External profile entries are volatile across catalog releases. The
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
# Promptkit v0.10.0 (Unreleased)
|
||||
# Promptkit v0.10.0
|
||||
|
||||
This supplemental transition guide describes the planned `v0.10.0` catalog
|
||||
profile-policy change. It is not a release record and does not claim that the
|
||||
version has been published. The annotated tag, when created, remains the
|
||||
authoritative release record.
|
||||
This supplemental guide summarizes the `v0.10.0` changes and migration needs.
|
||||
The annotated tag remains the authoritative release record.
|
||||
|
||||
## Transition Summary
|
||||
|
||||
@@ -12,6 +10,13 @@ modules whose external profile data can change between catalog releases. It
|
||||
also introduces the maintained literal names
|
||||
`promptkit-openrouter-standard` and `promptkit-openrouter-auto`.
|
||||
|
||||
The public package now delegates assembly to an internal engine while retaining
|
||||
the existing Go API. This refactor requires no consumer code changes.
|
||||
|
||||
This release selects OpenRouter `v2.20260922.1` and Rakestrawhome
|
||||
`v2.20260922.0`; their exact inventories are linked from the
|
||||
[format reference](../formats.md#external-profile-inventories).
|
||||
|
||||
The maintained names provide continuity only within the catalog versions
|
||||
selected and tested by a Promptkit release and when consumers do not override
|
||||
the name or its base. Their current selections may change. External catalog
|
||||
@@ -26,6 +31,12 @@ catalog profile's volatility, or define a complete application-owned profile
|
||||
when the application must control its target and settings. An alias that
|
||||
inherits from an external base is not a frozen copy.
|
||||
|
||||
In particular, the selected OpenRouter catalog removes `deepseek-3-2`,
|
||||
`deepseek-4-flash`, and `deepseek-4-pro`. Consumers using those IDs must choose
|
||||
an available profile or supply their own complete definition; the new
|
||||
`deepseek-flash-latest` and `deepseek-pro-latest` profiles are not automatic
|
||||
aliases and need not preserve the previous settings.
|
||||
|
||||
See the [release policy](../release.md#catalog-profile-compatibility) for the
|
||||
compatibility boundary, the [format reference](../formats.md#built-in-profile-catalog)
|
||||
for current Promptkit-owned definitions and selected external inventories, and
|
||||
|
||||
@@ -1,284 +0,0 @@
|
||||
# Profile Policy Implementation Plan
|
||||
|
||||
## Scope And Starting Point
|
||||
|
||||
Implement the [profile-policy roadmap](profile-policy.md): volatile external
|
||||
profile catalogs, dated `/v2` catalog modules, and two Promptkit-owned stable
|
||||
profile names. This replaces the completed public-facade implementation plan.
|
||||
The facade refactor and its review remediation are complete; composition work
|
||||
belongs in `internal/engine`, not the public package.
|
||||
|
||||
The feature roadmap still labels its policy provisional. Before executing
|
||||
Stage 1, confirm maintainer acceptance of this plan and update that roadmap's
|
||||
status to accepted for implementation, linking here for sequencing. Remove
|
||||
superseded procedural language there without changing its intended end state.
|
||||
Until implementation lands, existing durable contracts remain authoritative.
|
||||
|
||||
Execute stages in numerical order, one coding-agent prompt per stage. Stage 2
|
||||
is a release handoff requiring explicit publication authority. This plan does
|
||||
not itself authorize releases or pushes. Do not carry forward completion marks
|
||||
or API snapshots from the previous implementation plan.
|
||||
|
||||
Read `AGENTS.md`, [development](../development.md), all policies under
|
||||
`docs/policy/`, [formats](../formats.md), [internal sources](../internal/sources.md),
|
||||
and [release procedure](../release.md). Read each catalog repository's own
|
||||
instructions and release procedure before editing it. Preserve unrelated
|
||||
changes. For every implementation stage, run focused tests and the affected
|
||||
repository's complete validation workflow before acceptance. Report results
|
||||
and blockers; do not treat an unrun check as successful.
|
||||
|
||||
## Implementation Decisions
|
||||
|
||||
- Both catalog modules move to `/v2` paths and `v2.YYYYMMDD.N` releases. Use the
|
||||
actual UTC publication date and the next unused revision starting at zero;
|
||||
no placeholder tag or preliminary `v2.0.0` is needed. Modules release
|
||||
independently. Preserve published tags and their historical contracts.
|
||||
- Only external profile data becomes volatile. Go APIs, manifest/format
|
||||
semantics, backend IDs and definitions, and Promptkit runtime behavior remain
|
||||
outside the exception. Promptkit adds no live model or endpoint checks.
|
||||
Catalog owners remain responsible for upstream mapping accuracy.
|
||||
- The only profile-specific continuity guarantees are the literal names
|
||||
`promptkit-openrouter-standard` and `promptkit-openrouter-auto`, within the
|
||||
selected-and-tested dependency scope and absent consumer overrides. Models,
|
||||
backends, routing, defaults, and other selection characteristics are not
|
||||
permanent promises. Do not add notice or approval gates for later selections.
|
||||
- Initially, standard inherits `gemini-flash-latest`; auto directly selects
|
||||
backend `openrouter` and model `openrouter/auto`. Add no generation overrides,
|
||||
connection metadata, implicit default selection, public API, or fallback loop.
|
||||
- Construct the two raw definitions as internal Go values through
|
||||
`profile.NewMemoryRepository`, owned by a focused `internal/engine` helper.
|
||||
Two definitions do not justify another embedded asset tree or package.
|
||||
- Compose raw sources in this order: consumer memory, ordinary consumer source,
|
||||
consumer fallback source, Promptkit-owned profiles, external catalogs. Keep
|
||||
one runtime resolver over the complete hierarchy. Separately validate the
|
||||
maintained-only composition at construction without freezing its resolved
|
||||
values into the runtime source.
|
||||
- Reject the exact `promptkit-` prefix on normalized external catalog IDs in
|
||||
`internal/catalog.Load`. Do not impose that reservation on consumer sources,
|
||||
fold case beyond existing ID rules, or alter generic repositories.
|
||||
- Replace the old external-catalog extraction snapshot with structural and
|
||||
maintained-name tests. Do not create another full-profile inventory snapshot:
|
||||
module versions/checksums identify selected data, while repeated snapshots
|
||||
recreate catalog churn. Preserve backend-contract coverage separately.
|
||||
- The transition targets a new Promptkit minor release, currently `v0.10.0`.
|
||||
Later catalog-only updates and maintained-selection adjustments may ship as
|
||||
patches if other contracts remain intact. Promptkit retains semantic versioning.
|
||||
|
||||
## Stage 1: Prepare Both Catalog Modules For The New Contract
|
||||
|
||||
**Completed:** 2026-09-22
|
||||
|
||||
Repositories: `../promptkit-backend-openrouter` and
|
||||
`../promptkit-backend-rakestrawhome`. Their small data-only packages make this
|
||||
one bounded prompt; keep changes in their respective repositories.
|
||||
|
||||
1. Inspect both worktrees, module files, tags, assets, tests, README files, and
|
||||
`docs/release.md`. Preserve maintainer changes. The current OpenRouter
|
||||
checkout already contains a profile refresh; retain it rather than reverting
|
||||
to Promptkit's selected v1 catalog. Additional model curation is out of scope.
|
||||
2. Change each module declaration to its existing path plus `/v2`, and update
|
||||
self-imports and examples. Preserve package names, `FS()`, `Root`, embedded
|
||||
layout, manifest schema, and backend definitions. Do not introduce a
|
||||
dependency on Promptkit or duplicate its runtime validation.
|
||||
3. Revise compatibility documentation: profiles may be added, removed, renamed,
|
||||
or modified without deprecation or notice; backend definitions, public Go
|
||||
API, and schema compatibility do not gain that exception. Describe dated
|
||||
versions and explain that dates do not certify live availability. Do not
|
||||
pretend a README change retroactively changes the v1 contract.
|
||||
4. Update each release procedure for `/v2`, dated tags, immutable versions,
|
||||
independent release dates, and normal module-resolution checks. Retain its
|
||||
existing validation and annotated source-tag publication requirements.
|
||||
5. Keep proportionate data-package tests for the exported filesystem and asset
|
||||
shape. No network calls, credentials, provider SDKs, runtime dependencies,
|
||||
or cross-version profile-continuity assertions. Run both full workflows.
|
||||
|
||||
Acceptance: both source trees are ready for dated v2 releases; their asset APIs
|
||||
and backend manifests are unchanged apart from module identity. Report the
|
||||
candidate commits and validation. Do not publish without authority.
|
||||
|
||||
## Stage 2: Publish And Verify The Catalog Releases
|
||||
|
||||
**Completed:** 2026-09-22
|
||||
|
||||
**Publication record:**
|
||||
|
||||
- OpenRouter: `gitea.maximumdirect.net/eric/promptkit-backend-openrouter/v2`
|
||||
`v2.20260922.0` from `ad0b16f77035d8acbe38a6ae1e278eaf7eeb0dc8`.
|
||||
- Rakestrawhome:
|
||||
`gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome/v2`
|
||||
`v2.20260922.0` from `d664696142bf7c2d93db2a6b2e07f3deb55f2226`.
|
||||
|
||||
This is a maintainer-authorized publication stage, not a coding workaround for
|
||||
unavailable dependencies. If authority or remote access is missing, report the
|
||||
handoff and stop before adopting unpublished dependencies.
|
||||
|
||||
1. Follow each catalog's updated release procedure. Select an unused
|
||||
`v2.YYYYMMDD.N` tag using the publication date, validate the clean candidate,
|
||||
publish its source commit and only the selected annotated tag, and verify
|
||||
the remote tag and peeled commit. Never move a published tag.
|
||||
2. From a temporary module outside these repositories, resolve each exact
|
||||
`/v2@version` with `GOWORK=off`, without replacements or vendoring. Verify
|
||||
module identity and version. Downloads are not inference-provider probes
|
||||
and are separate from offline test execution.
|
||||
3. Record the two actual module versions and source commits in execution notes
|
||||
in this plan for Stage 5. They need not share dates or revision numbers.
|
||||
|
||||
Acceptance: both published dependencies resolve normally without sibling
|
||||
checkouts, workspaces, or replacements.
|
||||
|
||||
## Stage 3: Enforce The External Catalog Namespace
|
||||
|
||||
**Completed:** 2026-09-22
|
||||
|
||||
Repository: Promptkit. Keep current v1 dependencies during this stage;
|
||||
dependency adoption remains atomic in Stage 5.
|
||||
|
||||
1. In `internal/catalog.Load`, reject normalized profile IDs starting with
|
||||
`promptkit-` while inspecting eager-loaded catalog metadata. Use the existing
|
||||
descriptive catalog-construction error style with source context. Public
|
||||
construction continues to classify failures as `ErrInvalidConfig`.
|
||||
2. Preserve catalog-local inheritance, owning-backend validation, duplicate
|
||||
detection, secret/connection-field rules, strict decoding, and value checks.
|
||||
Do not relax these because profiles are volatile or add upstream validation.
|
||||
3. Extend synthetic catalog tests with a reserved maintained name and an
|
||||
otherwise unused `promptkit-` name. Confirm ordinary IDs still load. Keep
|
||||
the rule out of generic parsing so consumer definitions can use the prefix.
|
||||
4. Update internal source documentation for the implemented catalog-only
|
||||
reservation. Do not yet claim the maintained profiles exist.
|
||||
|
||||
Acceptance: catalogs cannot occupy the namespace; existing protections and
|
||||
consumer source behavior are unchanged.
|
||||
|
||||
## Stage 4: Add And Compose Promptkit-Owned Profiles
|
||||
|
||||
**Completed:** 2026-09-22
|
||||
|
||||
1. Add a maintained-profile helper in `internal/engine` with the two raw
|
||||
definitions specified above. Build its memory repository, overlay it above
|
||||
the raw external catalog repository, and supply that raw composition to the
|
||||
existing consumer-source assembly.
|
||||
2. During construction, resolve each Promptkit-owned definition through a
|
||||
maintained-only resolver and check that its effective backend exists in the
|
||||
maintained backend set. Reuse existing resolver and backend lookup owners;
|
||||
do not implement another inheritance walker or target-policy validator.
|
||||
External profiles retain catalog-local validation in `catalog.Load`.
|
||||
Together these checks cover the maintained set without consumer definitions
|
||||
or network access.
|
||||
3. If a maintained definition fails to resolve, fail construction through the
|
||||
existing `ErrInvalidConfig` boundary. Consumer overrides must not mask broken
|
||||
bundled definitions. Keep raw definitions for runtime resolution so consumer
|
||||
overrides of a maintained profile or its base still work. No resolved-profile
|
||||
cache or global mutable repository is needed.
|
||||
4. Use minimal synthetic composition tests for inherited selection, direct
|
||||
selection, missing-base failure, and invalid backend reference. Expected
|
||||
selections should follow the supplied definitions, not become permanent
|
||||
literal model promises.
|
||||
5. Add representative public inspection/preparation coverage proving both
|
||||
literal names resolve, consumers can replace maintained profiles or their
|
||||
bases, and default-profile selection is unchanged. Reuse source-precedence
|
||||
and prepared-execution coverage rather than duplicating full matrices.
|
||||
6. Update formats with the two current definitions, opt-in selection, and
|
||||
precedence. Update internal ownership and source-validation documentation.
|
||||
Scope intermediate compatibility claims to policy actually adopted so far.
|
||||
|
||||
Acceptance: both names work through existing APIs, consumer precedence remains
|
||||
effective, and no public exports or provider routing logic have been added.
|
||||
|
||||
## Stage 5: Adopt Published V2 Catalogs And Replace Snapshot Tests
|
||||
|
||||
**Completed:** 2026-09-22
|
||||
|
||||
1. Update catalog imports in production and tests to `/v2`. Select the exact
|
||||
Stage 2 versions through normal Go tooling, tidy module metadata, and review
|
||||
`go.mod`/`go.sum`. No `latest`, unpublished revisions, unrelated upgrades,
|
||||
or local replacements. Remove unused v1 requirements.
|
||||
2. Replace `TestLoadPublishedCatalogsMatchCompatibilityFixture` with an offline
|
||||
integration test loading both selected catalogs for structural acceptance.
|
||||
Remove snapshot-only helpers and `testdata/builtin-catalog-v1.json` once no
|
||||
callers remain. Retain malformed-input tests and backend metadata contract
|
||||
coverage; add focused backend assertions if deleting the snapshot removes
|
||||
their only protection. Backend definitions are not volatile profile data.
|
||||
3. Run maintained-profile tests against the new modules. Verify standard's base
|
||||
exists locally; if absent, change the maintained selection in this same
|
||||
dependency update and document the current definition. This is not a new
|
||||
permanent selection-approval gate. The inspected catalog currently contains
|
||||
`gemini-flash-latest`, so no replacement is planned.
|
||||
4. Convert tests that use removed external profiles for unrelated runtime
|
||||
behavior to consumer-owned fixtures. Keep small real-catalog integration
|
||||
coverage without coupling every runtime test to external inventories.
|
||||
5. Review the catalog diff for local compatibility consequences, not provider
|
||||
health. Do not restore removed IDs or add migration aliases just to preserve
|
||||
the old snapshot. Confirm backend manifests and public/runtime contracts
|
||||
did not change as a side effect.
|
||||
|
||||
Acceptance: Promptkit passes its full workflow using published v2 dependencies;
|
||||
tests protect structural validity and maintained names without promising an
|
||||
external inventory across releases.
|
||||
|
||||
## Stage 6: Publish Durable Policy And Consumer Guidance
|
||||
|
||||
**Completed:** 2026-09-22
|
||||
|
||||
1. Update `docs/release.md`, the release-policy owner: narrow external-profile
|
||||
exception, two-name continuity scope, initial minor transition, and later
|
||||
patch eligibility. Replace its blanket catalog-update instruction to claim
|
||||
no consumer migration is needed: removals may require consumer action.
|
||||
Preserve ordinary compatibility and release records; do not require model
|
||||
change announcements or additional selection gates.
|
||||
2. Replace the exhaustive external profile table in `docs/formats.md` with links
|
||||
to inventories at the selected catalog versions. Keep the small Promptkit
|
||||
inventory here, label selections current rather than permanent, and link to
|
||||
release policy for cross-version guarantees.
|
||||
3. Explain consumer choices in the consumer guide: use a maintained name,
|
||||
accept a volatile external profile, or define a complete application-owned
|
||||
profile. Inheritance still follows base changes and can fail if the base
|
||||
disappears; an application alias is not a frozen copy.
|
||||
4. Explain selected-and-tested dependency scope and the resolved module graph:
|
||||
independently upgrading a transitive catalog can break an inherited base.
|
||||
Pinned data does not preserve upstream availability; running binaries neither
|
||||
download updates nor automatically replace withdrawn models.
|
||||
5. Update architecture, internal source/overview, and contributor documentation
|
||||
only where ownership or workflow changed. Avoid duplicate inventories and
|
||||
exact contracts. No live endpoint/model-list check belongs in adoption,
|
||||
tests, or release validation.
|
||||
6. Prepare `docs/releases/v0.10.0.md` as supplemental transition guidance linking
|
||||
canonical policy/formats and describing potential profile migration. Add a
|
||||
README link labeled unreleased until publication. Do not claim release
|
||||
completion or require individual model-change notices.
|
||||
|
||||
Acceptance: durable documentation distinguishes stable literal names from
|
||||
volatile selections and agrees across repositories without weakening unrelated
|
||||
contracts.
|
||||
|
||||
## Stage 7: Final Integration Review And Release Handoff
|
||||
|
||||
**Completed:** 2026-09-22
|
||||
|
||||
1. Run the complete Promptkit maintainer workflow: ordinary/race tests, vet,
|
||||
build, both offline examples, formatting, local links, and hygiene. Verify
|
||||
normal module resolution independent of sibling checkouts.
|
||||
2. Compare public declarations against the completed facade baseline: no new
|
||||
API, internal type leak, default-selection change, or consumer restriction
|
||||
is intended. Confirm existing error, injection, override, inheritance, repair,
|
||||
prepared-execution, and capacity tests still pass.
|
||||
3. Check recorded dependency versions, maintained-name resolution without
|
||||
consumer help, consumer overrides, and absence of cross-version external
|
||||
inventory promises in tests or documentation.
|
||||
4. Review for stronger promises than authorized: permanent backend/routing
|
||||
implied by a profile name, change announcements, deprecation periods, or
|
||||
live-service checks. Remove accidental guarantees rather than adding gates.
|
||||
5. Report completion and the minor-release candidate. Retire completed roadmaps
|
||||
only when requested or approved during release preparation. Promptkit
|
||||
publication follows its release procedure under separate authority; do not
|
||||
tag or push it merely because this stage passes.
|
||||
|
||||
Acceptance: ready for independent review and subsequent release preparation,
|
||||
with validation results and any blockers reported.
|
||||
|
||||
## Open Questions
|
||||
|
||||
No unresolved product or architecture decision is needed for this proposed
|
||||
implementation. Maintainer acceptance of the still-provisional policy and
|
||||
authority to publish catalog releases are execution prerequisites, not assumed
|
||||
permissions. Exact version strings are selected at publication using the
|
||||
agreed date convention and recorded before Promptkit adoption.
|
||||
@@ -1,359 +0,0 @@
|
||||
# Built-In Profile Compatibility Policy
|
||||
|
||||
## Status
|
||||
|
||||
Accepted for implementation on 2026-09-22. The implementation sequence and
|
||||
completion status are maintained in the
|
||||
[profile-policy implementation plan](implementation.md). Current code, GoDoc,
|
||||
durable documentation, published module contracts, and release tags remain
|
||||
authoritative until each corresponding implementation change lands.
|
||||
|
||||
## Prerequisite And Sequencing
|
||||
|
||||
Implementation of this roadmap must begin only after the
|
||||
[public facade refactor](public-facade.md) is complete and its compatibility
|
||||
and validation criteria have passed. The refactor preserves existing behavior;
|
||||
this subsequent work introduces the deliberate profile-policy changes.
|
||||
|
||||
Profile-source composition, maintained-profile construction, and catalog
|
||||
dependency assembly must use the internal owners established by that refactor.
|
||||
Both scopes may ship in `v0.10.0`, but they remain separately reviewable changes.
|
||||
This prerequisite has been satisfied. The remaining work proceeds through the
|
||||
[profile-policy implementation plan](implementation.md).
|
||||
|
||||
## Purpose
|
||||
|
||||
Define a truthful compatibility and release boundary for Promptkit's
|
||||
maintained built-in profiles. The intended direction is to permit exceptionally
|
||||
rapid catalog updates without weakening Promptkit's stability commitments for
|
||||
its engine, public Go API, configuration semantics, backend registry, or other
|
||||
non-profile behavior.
|
||||
|
||||
Model catalogs change faster than the Promptkit runtime. Providers control
|
||||
their own model catalogs and service lifecycles. Promptkit cannot
|
||||
reasonably guarantee that a maintained profile's upstream model or endpoint
|
||||
will remain available, and retaining obsolete profiles can be actively
|
||||
misleading when their targets no longer provide the expected service.
|
||||
|
||||
The release model should treat external catalog profiles as volatile data,
|
||||
while providing a small set of Promptkit-owned aliases with stable IDs for
|
||||
applications that prefer a maintained general-purpose selection.
|
||||
|
||||
## Proposed Compatibility Boundary
|
||||
|
||||
The provisional policy would exclude external catalog profile data from
|
||||
Promptkit's cross-version compatibility surface. A catalog or Promptkit
|
||||
release could, without deprecation or advance notice:
|
||||
|
||||
- add or remove an external catalog profile;
|
||||
- rename a profile, represented as removing one ID and adding another;
|
||||
- change the upstream model selected by a profile;
|
||||
- change profile defaults such as reasoning effort, timeout, service tier,
|
||||
sampling controls, token limits, or extra parameters; and
|
||||
- correct or otherwise revise profile metadata in response to upstream
|
||||
behavior.
|
||||
|
||||
Promptkit would make no cross-version promise about the continued presence,
|
||||
identity, settings, suitability, or upstream availability of an external
|
||||
catalog profile. The separately defined Promptkit-owned alias IDs would have
|
||||
the continuity guarantee below. Promptkit would make no claim that an upstream
|
||||
provider will continue to serve a cataloged model or endpoint for the lifetime
|
||||
of a Promptkit or catalog release.
|
||||
|
||||
This volatility exception should apply only to external catalog profile
|
||||
data. It should not silently weaken the ordinary compatibility rules for:
|
||||
|
||||
- Promptkit's exported Go API and GoDoc contracts;
|
||||
- prompt, profile, and schema format semantics;
|
||||
- request preparation, execution, validation, repair, cancellation, error,
|
||||
credential, ownership, and concurrency behavior;
|
||||
- public built-in backend IDs and registry behavior;
|
||||
- the external catalog packages' exported Go API;
|
||||
- the catalog manifest and asset schema understood by Promptkit; or
|
||||
- consumer-defined profiles and backends.
|
||||
|
||||
Backend definitions, including endpoint, credential-environment, and capacity
|
||||
metadata, remain outside the profile-volatility exception and subject to the
|
||||
ordinary compatibility policy.
|
||||
|
||||
## Proposed Stable Promptkit Profiles
|
||||
|
||||
Promptkit would maintain a small, explicitly documented set of built-in
|
||||
profiles using existing profile definitions and inheritance:
|
||||
|
||||
| Stable profile ID | Initial definition | Initial purpose |
|
||||
| --- | --- | --- |
|
||||
| `promptkit-openrouter-standard` | Inherits from external catalog profile `gemini-flash-latest`. | A maintained selection for general-purpose text generation. |
|
||||
| `promptkit-openrouter-auto` | Selects backend `openrouter` and model `openrouter/auto`. | Delegates model selection to OpenRouter's automatic routing. |
|
||||
|
||||
These definitions and purposes describe the initial selections only and are
|
||||
not continuing model-selection promises.
|
||||
|
||||
The auto profile can initially be a direct profile definition; it does not
|
||||
require a second catalog alias or a new public API. It inherits connection and credential
|
||||
metadata from the OpenRouter backend and need not add generation overrides.
|
||||
Promptkit forwards `openrouter/auto` as the model identifier through its ordinary
|
||||
client. OpenRouter owns the routing decision, eligible models, and resulting
|
||||
provider behavior. Promptkit adds no model-selection algorithm or fallback
|
||||
loop. Its ordinary local validation does not check the upstream availability
|
||||
of `openrouter/auto`.
|
||||
|
||||
Both profiles receive the stable-ID guarantee below. References to aliases
|
||||
describe inherited definitions where applicable; the same namespace,
|
||||
precedence, and structural-validation requirements cover direct definitions.
|
||||
Only these two profiles are in scope. This roadmap imposes no additional
|
||||
approval process for future profiles.
|
||||
|
||||
The only profile-specific continuity promise is that the literal names
|
||||
`promptkit-openrouter-standard` and `promptkit-openrouter-auto` remain
|
||||
available, subject to the supported dependency and consumer-override scope
|
||||
below. Their actual models may change at any time, for any reason, without
|
||||
notice to anyone. No deprecation, approval, or change-announcement gate applies
|
||||
to model selection. The names do not promise a permanent model, provider,
|
||||
routing strategy, or set of defaults. Both initially use OpenRouter, but the
|
||||
profile names themselves are the only continuity guarantee.
|
||||
|
||||
In particular, `promptkit-openrouter-auto` is not required to retain
|
||||
`openrouter/auto` or automatic routing indefinitely. Neither profile guarantees
|
||||
unchanged output, cost, latency, capabilities, or upstream availability. While
|
||||
using upstream automatic routing, the selected model can vary between requests
|
||||
even with unchanged Promptkit and catalog versions.
|
||||
|
||||
Catalog dependency updates must preserve local resolution of the two maintained
|
||||
profile names. If a referenced catalog profile disappears or is renamed,
|
||||
adjust the affected alias together with the dependency update and ship both in
|
||||
the same Promptkit release. If the catalog retains the referenced ID but
|
||||
changes its model, inheritance picks up the change automatically; no separate
|
||||
model-selection approval is required. Ordinary code review and structural
|
||||
validation apply. Upstream deprecation, retirement, and mapping accuracy remain
|
||||
the catalog library's responsibility and do not create a Promptkit monitoring
|
||||
or upstream-verification obligation.
|
||||
|
||||
Release validation must prove that every maintained alias resolves against
|
||||
the selected catalog versions. This continuity guarantee applies to the
|
||||
versions selected and tested by Promptkit and assumes consumers have not
|
||||
overridden the alias or its base with their own definitions. Independently
|
||||
upgrading a transitive catalog can remove an alias's base without updating
|
||||
Promptkit; that untested combination is outside the guarantee.
|
||||
|
||||
Aliases would retain the ordinary profile precedence and inheritance
|
||||
semantics. They would introduce no new public API or automatic model failover.
|
||||
An already deployed application would retain its compiled alias and catalog
|
||||
data until upgraded; an upstream withdrawal would not change its selection
|
||||
automatically.
|
||||
|
||||
Adding these profiles does not change existing default-profile selection.
|
||||
Consumers opt into them through the existing profile-selection mechanisms.
|
||||
|
||||
### Ownership, Precedence, And Composition
|
||||
|
||||
The maintained alias definitions belong to a small Promptkit-owned profile
|
||||
source. Profile precedence is consumer sources in their existing order, then
|
||||
Promptkit-owned aliases, then external catalog profiles. Consumers may override
|
||||
an alias or its base using the ordinary profile mechanisms.
|
||||
|
||||
Reserve the `promptkit-` profile-ID prefix against definitions in external
|
||||
catalogs. Reject such catalog definitions even if they do not yet collide with
|
||||
an existing alias. This namespace rule does not prohibit consumer overrides.
|
||||
|
||||
Retain existing catalog-local inheritance and backend-ownership validation,
|
||||
and verify that the combined maintained profiles resolve without relying on
|
||||
consumer overrides. Do not assert a permanent model or routing selection based
|
||||
on a profile name. Runtime inheritance must continue to observe the complete
|
||||
source hierarchy, including consumer overrides of aliases and their bases.
|
||||
Reuse the existing resolver; exact private assembly and validation sequencing
|
||||
belongs in the implementation plan. Do not introduce a second inheritance
|
||||
implementation or freeze alias values in a way that bypasses consumer overrides.
|
||||
|
||||
## Local Validation And Existing Safeguards
|
||||
|
||||
Profile volatility does not remove existing structural validation or library
|
||||
safeguards. Preserve the following implemented responsibilities without making
|
||||
them additional profile-availability or permanent implementation promises:
|
||||
|
||||
- catalog assets are immutable build inputs rather than runtime downloads;
|
||||
- manifests and profiles satisfy the supported schemas;
|
||||
- IDs are unique and profiles select their owning backend;
|
||||
- external catalogs do not define IDs in the reserved `promptkit-` namespace;
|
||||
- secret-bearing fields and prohibited connection metadata are rejected;
|
||||
- profile values are normalized, copied, resolved, and overlaid through the
|
||||
existing Promptkit architecture;
|
||||
- the selected catalogs pass Promptkit's integration suite before a Promptkit
|
||||
release adopts them; and
|
||||
- the module graph and checksums provide a reproducible identity for the data
|
||||
that was tested.
|
||||
|
||||
These checks establish local integrity for selected data, together with the
|
||||
maintained-profile resolution requirement above. They do not establish external
|
||||
catalog profile continuity across versions or live upstream availability.
|
||||
|
||||
Promptkit's checks cover local syntax and structural semantics: supported
|
||||
fields, duplicate IDs, namespace conflicts, inheritance resolution, backend
|
||||
references, endpoint URL format, and existing security and value constraints.
|
||||
They expressly exclude attempts to verify that an endpoint exists, a model ID
|
||||
is recognized upstream, or a provider serves that model. Catalog libraries own
|
||||
the accuracy of upstream model and endpoint mappings. Promptkit must not add
|
||||
network probes, model-list lookups, or paid inference checks to catalog adoption
|
||||
or release validation. Ordinary execution continues to report upstream errors
|
||||
through the existing generation-error contract.
|
||||
|
||||
## Provisional Release Model
|
||||
|
||||
The first release adopting this policy should be a new Promptkit minor release
|
||||
because it changes a previously documented consumer expectation and may remove
|
||||
profile IDs on which deployed configuration depends. `v0.10.0` is the current
|
||||
candidate.
|
||||
|
||||
The OpenRouter catalog's published `v1.0.0` contract promised stable profile
|
||||
IDs and advance handling before removal. A later README cannot retroactively
|
||||
weaken that promise. The current recommendation is therefore to establish the
|
||||
new boundary in `promptkit-backend-openrouter` major version 2, using the dated
|
||||
release convention below, even if its exported Go declarations and manifest
|
||||
schema do not change.
|
||||
|
||||
After that boundary is established, maintained catalog releases could publish
|
||||
profile additions, deletions, and modifications rapidly under their documented
|
||||
volatile-data policy. Promptkit could select a reviewed catalog update without
|
||||
treating profile churn as a compatibility break in its otherwise stable core.
|
||||
Later catalog updates and corresponding alias adjustments may ship in a
|
||||
Promptkit patch release, such as `v0.10.1` after `v0.10.0`, provided unrelated
|
||||
compatibility contracts remain intact. Profile churn alone does not require
|
||||
`v0.11.0` or another minor release.
|
||||
|
||||
Promptkit's integration validation covers the catalog versions it selected
|
||||
and tested. It does not guarantee upstream correctness for those versions.
|
||||
Go module version selection may cause an advanced consumer's build
|
||||
to select a newer compatible catalog module than Promptkit's own requirement;
|
||||
the resolved module graph, rather than Promptkit's `go.mod` alone, determines
|
||||
the actual embedded data.
|
||||
|
||||
Release notes may identify selected catalog updates and summarize changes for
|
||||
convenience, but no notice of model-selection changes is required, in advance
|
||||
or afterward. Ordinary release records and validation still apply; they must
|
||||
not introduce a profile-change announcement gate.
|
||||
|
||||
### Proposed Date-Based Catalog Versions
|
||||
|
||||
The proposed catalog version convention is `vMAJOR.YYYYMMDD.N`. This is a
|
||||
calendar-based convention encoded in Go-compatible semantic-version syntax:
|
||||
|
||||
- `MAJOR` identifies the compatibility generation of the exported Go package
|
||||
and catalog asset format. Profile additions, deletions, renames, and setting
|
||||
changes do not require a major-version increase under the proposed policy.
|
||||
- `YYYYMMDD` is the release publication date in UTC. It occupies the numeric
|
||||
minor-version component and communicates snapshot freshness, not the scale
|
||||
or compatibility of a profile change.
|
||||
- `N` starts at zero for each UTC date and increments for every additional
|
||||
release that day, regardless of the kind of profile change. It occupies the
|
||||
numeric patch-version component and carries no profile-continuity promise.
|
||||
|
||||
For example, `v2.20260922.0` and `v2.20260922.1` would be successive releases
|
||||
on September 22, 2026, followed by `v2.20260923.0` on the next day. These are
|
||||
illustrative dates, not scheduled releases. Use the actual publication date;
|
||||
published versions remain immutable, and corrections receive new versions.
|
||||
Within a major generation, these versions sort chronologically under Go's
|
||||
ordinary module-version ordering.
|
||||
|
||||
Go requires a matching major-version suffix in module paths for version 2 and
|
||||
later. The OpenRouter transition would therefore use
|
||||
`gitea.maximumdirect.net/eric/promptkit-backend-openrouter/v2` in the catalog's
|
||||
module declaration and Promptkit's imports and dependency requirement. A first
|
||||
release on the example date would be `v2.20260922.0`; a preliminary `v2.0.0`
|
||||
release is not required. Promptkit consumers would continue importing
|
||||
Promptkit through its existing module path. See the
|
||||
[Go module version rules](https://go.dev/ref/mod#versions) and
|
||||
[major-version suffix rules](https://go.dev/ref/mod#major-version-suffixes).
|
||||
|
||||
Both maintained catalog libraries, OpenRouter and Rakestrawhome, would
|
||||
transition to this policy and dated major-version-2 convention as part of this
|
||||
work, with matching `/v2` module paths. Thereafter each would release
|
||||
independently; releases need not share dates or revision numbers.
|
||||
Promptkit itself would retain its existing version-number
|
||||
convention and explicitly select and test individual catalog versions.
|
||||
|
||||
This proposal replaces the earlier idea of classifying catalog refreshes as
|
||||
ordinary minor releases and metadata corrections as patches. The date records
|
||||
when a snapshot was published; release notes may summarize what changed.
|
||||
Neither establishes live upstream availability or cross-version profile
|
||||
continuity. The convention remains provisional along with this roadmap.
|
||||
|
||||
## Consumer Guidance
|
||||
|
||||
The eventual durable documentation should make the tradeoff explicit:
|
||||
|
||||
- external catalog profiles optimize for convenient access to a maintained
|
||||
current model catalog;
|
||||
- selecting or inheriting directly from an external catalog profile accepts
|
||||
its volatility;
|
||||
- selecting either `promptkit-openrouter-standard` or
|
||||
`promptkit-openrouter-auto` guarantees only continued availability of that
|
||||
literal profile name within the supported dependency scope; models and
|
||||
settings may change for any reason without notice;
|
||||
- `promptkit-openrouter-auto` initially delegates model selection to OpenRouter;
|
||||
its initial routing behavior is not a permanent contract, and upstream
|
||||
routing can change independently of a library upgrade;
|
||||
- pinning the complete resolved Go module graph preserves the exact catalog
|
||||
assets used by that build, but cannot preserve live upstream availability;
|
||||
- applications that require their own fixed model selection or settings should
|
||||
define a complete application-owned profile with an explicit backend, model,
|
||||
and defaults; and
|
||||
- an application-owned alias that inherits from an external catalog profile
|
||||
isolates application configuration from the catalog ID only while that base
|
||||
exists; it deliberately continues to inherit changes to the base profile.
|
||||
|
||||
Promptkit should not promise automatic migration or replacement aliases for
|
||||
every removed external catalog ID, deprecation windows for catalog profiles,
|
||||
or runtime fallback from a removed or unavailable model. Its small maintained
|
||||
alias set provides continuity through coordinated library releases.
|
||||
|
||||
## Expected Documentation And Repository Changes
|
||||
|
||||
If accepted, implementation would likely require coordinated changes in
|
||||
Promptkit and each maintained catalog repository:
|
||||
|
||||
- revise catalog compatibility and release documentation to distinguish the
|
||||
stable Go/schema boundary from volatile profile data and document the
|
||||
`vMAJOR.YYYYMMDD.N` convention;
|
||||
- update Promptkit's release policy with a narrowly scoped built-in-profile
|
||||
volatility exception for external catalogs and an explicit continuity
|
||||
guarantee for Promptkit-owned alias IDs, while retaining its other pre-`v1`
|
||||
compatibility rules;
|
||||
- add `promptkit-openrouter-standard` through existing profile inheritance and
|
||||
`promptkit-openrouter-auto` as a direct `openrouter/auto` profile; document
|
||||
their distinct purposes and opt-in selection;
|
||||
- require coordinated catalog and alias updates, with release checks proving
|
||||
every maintained alias resolves against the selected catalog versions;
|
||||
- update the architecture, format, source, development, and consumer
|
||||
documentation at their existing ownership boundaries;
|
||||
- keep exact external profile inventories in the catalog repositories, linking
|
||||
to the selected versions from Promptkit rather than duplicating their tables;
|
||||
keep Promptkit's small alias inventory and runtime semantics in its own
|
||||
canonical documentation;
|
||||
- revise tests and compatibility-fixture terminology so they protect local
|
||||
structural validity and maintained-profile resolution, without asserting
|
||||
cross-version stability of external profiles; retain an exact selected-version
|
||||
snapshot only where its review value justifies its maintenance cost;
|
||||
- publish both revised catalog contracts as dated major-version-2 releases
|
||||
with matching `/v2` module paths;
|
||||
- update Promptkit's catalog imports and requirement, current selected-profile
|
||||
documentation, and release guidance; and
|
||||
- publish the policy transition and its consumer impact in the eventual
|
||||
Promptkit minor release note and annotated tag.
|
||||
|
||||
Implementation is sequenced and tracked in the
|
||||
[profile-policy implementation plan](implementation.md).
|
||||
|
||||
## Non-Goals
|
||||
|
||||
This proposal does not introduce:
|
||||
|
||||
- runtime catalog downloads, discovery, or mutable global registration;
|
||||
- any upstream endpoint or model-existence verification by Promptkit, or
|
||||
guarantees based on current provider health;
|
||||
- automatic replacement aliases or migration tables for every removed catalog
|
||||
profile, or runtime fallback models;
|
||||
- weakened validation of catalog structure or content;
|
||||
- weaker compatibility for Promptkit's public engine or consumer-defined
|
||||
configuration; or
|
||||
- a general exception allowing arbitrary dependency updates to break stable
|
||||
Promptkit behavior.
|
||||
@@ -1,217 +0,0 @@
|
||||
# Public Facade Refactor
|
||||
|
||||
## Status
|
||||
|
||||
Accepted direction; implementation has not begun. This feature roadmap defines
|
||||
the intended end state and compatibility requirements. The companion
|
||||
[implementation plan](implementation.md) defines the work sequence. Current
|
||||
GoDoc and durable documentation remain authoritative until implementation lands.
|
||||
|
||||
## Purpose
|
||||
|
||||
Make Promptkit's root package a deliberately maintained consumer facade while
|
||||
placing engine implementation and assembly behind Go's `internal/` boundary.
|
||||
Consumers should depend only on intentional public contracts, and maintainers
|
||||
should be able to refactor internal behavior without changing those contracts.
|
||||
|
||||
The aim is a clearer ownership boundary, not the smallest possible root package
|
||||
or a reduction in consumer capabilities. Private root functions are already
|
||||
inaccessible to consumers; relocating them improves separation but does not by
|
||||
itself control the exported API. The refactor must also protect public type
|
||||
ownership, signatures, fields, and method sets against accidental exposure of
|
||||
implementation details.
|
||||
|
||||
## Current Position
|
||||
|
||||
Promptkit already places execution, repair, capacity management, rendering,
|
||||
source loading, transport, and validation in specialized internal packages.
|
||||
Its [architecture policy](../policy/architecture.md) already identifies the
|
||||
root package as the supported public facade.
|
||||
|
||||
The remaining root implementation includes engine construction and collaborator
|
||||
assembly, source selection, profile overlay construction, filesystem source
|
||||
setup, and an in-memory profile repository. These responsibilities can move
|
||||
inward while the root retains public declarations and explicit adapters.
|
||||
|
||||
ConfigKit's completed facade refactor is a design reference: root-owned public
|
||||
types wrap private engine state and expose explicitly selected methods. Its
|
||||
implementation should inform this work without introducing a dependency on
|
||||
ConfigKit or copying mechanisms that Promptkit does not need.
|
||||
|
||||
## Target End State
|
||||
|
||||
### Root-Owned Public Contract
|
||||
|
||||
The root `promptkit` package remains the consumer import path and owns:
|
||||
|
||||
- public named types, interfaces, constants, and error identities;
|
||||
- public configuration, request, result, inspection, and profile values;
|
||||
- constructors, options, and deliberate forwarding methods;
|
||||
- opaque public handles backed by private internal state;
|
||||
- public GoDoc and supported serialization and formatting behavior; and
|
||||
- explicit value conversion, injected-collaborator adaptation, and public
|
||||
error translation where they cross the facade boundary.
|
||||
|
||||
Public types must remain root-defined. Do not alias them to internal types,
|
||||
anonymously embed internal implementations to promote methods, expose internal
|
||||
types in public fields or signatures, or add public bridge methods for wiring.
|
||||
Private fields may refer to internal implementations.
|
||||
|
||||
Straightforward convenience constructors and boundary code may remain in the
|
||||
root. A forwarding layer or additional record type should have a concrete
|
||||
ownership or compatibility purpose; moving every helper is not an objective.
|
||||
|
||||
### Internal Engine Assembly
|
||||
|
||||
A cohesive internal assembly owner constructs an operational engine from
|
||||
internal configuration and supplied collaborators. `internal/engine` is the
|
||||
proposed home; exact private package and helper layout belongs in the
|
||||
implementation plan. Its responsibilities
|
||||
include source selection and defaults, maintained catalog loading, profile
|
||||
overlay assembly, backend registration assembly, capacity-manager construction,
|
||||
default client and validator selection, and runner/repairer wiring.
|
||||
|
||||
The public `Engine` delegates through private state to internal implementation.
|
||||
Root options express consumer choices and translate public values; internal
|
||||
construction owns how those choices assemble components. Preserve established
|
||||
contracts for option capture, application, validation, and source access.
|
||||
Incidental private ordering is not a new compatibility requirement.
|
||||
|
||||
Build on the existing specialized internal responsibilities. Internal assembly
|
||||
is the composition owner, not a replacement for the runner,
|
||||
catalog adapter, profile repositories, transport, or domain packages. It should
|
||||
not duplicate execution orchestration already owned by `internal/usecase`.
|
||||
|
||||
Move the in-memory profile repository behind the internal boundary;
|
||||
`internal/profile` is its natural home. Reuse existing definition validation and
|
||||
copying owners. Other root implementation
|
||||
helpers should move to their cohesive existing owner or to internal assembly
|
||||
as appropriate. Avoid generic registries, service locators, or a new extension
|
||||
framework for this relocation.
|
||||
|
||||
Dependency direction remains root facade to internal components. Internal
|
||||
production packages must not import the root package. The root can use internal
|
||||
domain values and narrow collaborator interfaces for explicit conversions;
|
||||
this proposal does not require all root imports to pass through a single
|
||||
internal package or require duplicate forwarding APIs to achieve that shape.
|
||||
|
||||
## Compatibility Requirements
|
||||
|
||||
This is a behavior-preserving refactor covering the actual exported surface,
|
||||
including methods and fields. An exported declaration is
|
||||
accessible even when it is absent from the consumer guide. Do not infer that
|
||||
an apparently low-level declaration is safe to remove: injected model clients
|
||||
and other intentional extension contracts may rely on it.
|
||||
|
||||
Preserve existing public names, signatures, named-type identity, method sets,
|
||||
interface satisfaction, exported struct fields, and supported value behavior.
|
||||
Any discovered API removal or redesign requires a separate explicit decision
|
||||
and consumer migration rationale; the minor release is not blanket permission
|
||||
to remove accessible declarations.
|
||||
|
||||
The refactor must preserve, in particular:
|
||||
|
||||
- established option order, replacement and accumulation rules, nil behavior,
|
||||
validation timing, and capture/copy contracts;
|
||||
- profile-source precedence, lazy consumer source reads, inheritance, and
|
||||
maintained-catalog validation;
|
||||
- public error identities and typed errors through `errors.Is` and `errors.As`,
|
||||
including cancellation propagation and sensitive-detail redaction;
|
||||
- public JSON representations, formatting, and defensive-copy guarantees;
|
||||
- injected client and artifact-reader contracts, including caller ownership
|
||||
of collaborator values;
|
||||
- preparation and inspection semantics, hash relationships, request overrides,
|
||||
appended messages, output validation, and bounded repair;
|
||||
- prepared-execution engine binding, shared lifecycle when handles are copied,
|
||||
single-use execution, discard behavior, and credential retention; and
|
||||
- engine-local concurrency, admission, cancellation, usage accounting, and
|
||||
transport behavior.
|
||||
|
||||
Preserve intentional contracts without elevating incidental private layout,
|
||||
helper names, operation ordering, diagnostic wording, or opaque hash encodings
|
||||
into new promises. The baseline inventory identifies accessible API; it is
|
||||
not authority to turn every observed implementation behavior into a contract.
|
||||
|
||||
## Verification And Test Ownership
|
||||
|
||||
Follow the [testing policy](../policy/testing.md). Existing external-package
|
||||
contract tests and maintained offline examples should continue to exercise the
|
||||
same consumer API. Tests coupled to private layout may be adapted or
|
||||
consolidated under the testing policy without changing their contract-level
|
||||
expectations.
|
||||
|
||||
Move implementation tests with their owning behavior when package relocation
|
||||
requires it. Keep focused source, profile, runner, capacity, and transport
|
||||
coverage at the existing internal owners. Root tests should focus on public
|
||||
compatibility, boundary conversion, error adaptation, and representative
|
||||
assembled workflows. Do not duplicate internal test matrices at the facade or
|
||||
add one test per trivial forwarding method.
|
||||
|
||||
Add a focused public-boundary check that detects internal types escaping
|
||||
through exported types, signatures, fields, or promoted methods, and rejects
|
||||
public aliases to internal implementations. Use Go's type information where
|
||||
needed to inspect the actual exported method sets. The check must permit
|
||||
private internal state and the established sealed option mechanism. Protect
|
||||
the no-internal-production-imports-of-root dependency rule without freezing an
|
||||
incidental file layout or exact internal package inventory.
|
||||
|
||||
Compatibility evidence includes an unchanged exported surface and behavioral
|
||||
coverage of consequential boundary risks: option timing, conversion ownership,
|
||||
typed errors, and prepared-execution lifecycle. Acceptance requires the complete
|
||||
[maintainer validation workflow](../development.md#maintainer-validation),
|
||||
including race checks and both offline examples. No live provider calls or
|
||||
sibling repository are required for validation.
|
||||
|
||||
## Relationship To The Profile Policy Work
|
||||
|
||||
This refactor and the [profile-policy proposal](profile-policy.md) are separate
|
||||
scopes that may ship together in the planned `v0.10.0` release. Establish the
|
||||
facade boundary with current behavior preserved before implementing the
|
||||
catalog-policy and standard-profile changes. Their assembly logic can then
|
||||
land in its intended internal owner.
|
||||
|
||||
This roadmap does not itself change catalog versions, introduce standard
|
||||
profiles, or adopt the provisional profile compatibility policy. Release
|
||||
guidance should distinguish the internal refactor from the deliberate consumer
|
||||
policy changes accompanying it. A completed facade refactor should require no
|
||||
consumer migration on its own.
|
||||
|
||||
## Documentation End State
|
||||
|
||||
Update the [architecture policy](../policy/architecture.md) to describe the
|
||||
implemented facade and assembly boundary, and the
|
||||
[component overview](../internal/overview.md) to identify the new owner and
|
||||
relocated responsibilities. Update affected internal source and runner
|
||||
documentation and links when implementation moves.
|
||||
|
||||
Go declarations and GoDoc remain the canonical public contract. Consumer and
|
||||
format documentation should not acquire new requirements from a private
|
||||
relocation. Record the durable facade decision in an ADR if needed to preserve
|
||||
its rationale; ConfigKit is a reference, not an ongoing normative dependency.
|
||||
Remove this temporary roadmap after completion and durable documentation
|
||||
updates according to the [documentation policy](../policy/documentation.md).
|
||||
|
||||
## Completion Criteria
|
||||
|
||||
- The root exposes deliberate, root-owned consumer contracts and explicit
|
||||
adapters without leaking internal types or promoted implementation methods.
|
||||
- Internal assembly and repositories own the relocated implementation, with
|
||||
one production path and no parallel legacy engine.
|
||||
- Specialized internal components retain clear ownership and do not import
|
||||
the public facade.
|
||||
- Public API comparison and behavioral tests establish compatibility,
|
||||
including ownership, errors, option timing, and prepared execution.
|
||||
- Boundary checks protect accidental API exposure without preventing ordinary
|
||||
internal refactoring or consumer extension.
|
||||
- Required validation passes, documentation matches the implemented state,
|
||||
and consumers require no migration for this refactor.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Public API expansion, removal, or redesign.
|
||||
- Changes to provider behavior, formats, defaults, or execution semantics.
|
||||
- Replacing the existing specialized packages with one large engine package.
|
||||
- A dependency on ConfigKit or a reusable facade-generation framework.
|
||||
- A minimum root-package line count, exhaustive wrapper tests, or a blanket
|
||||
prohibition on private boundary logic in the root.
|
||||
- Implementing the separate profile-policy roadmap during this refactor.
|
||||
@@ -1,86 +0,0 @@
|
||||
# Public Facade Review Remediation
|
||||
|
||||
## Scope
|
||||
|
||||
Review of implementation commits after baseline `7a858c2` through `06251e3`,
|
||||
against the [feature roadmap](public-facade.md) and
|
||||
[implementation plan](implementation.md).
|
||||
|
||||
The production ownership split is in place. No production behavior regression
|
||||
or public API change was identified in the reviewed diff. One required
|
||||
architecture-test gap was identified and has now been addressed; it did not
|
||||
establish an existing public type leak in Promptkit.
|
||||
|
||||
## Finding 1: Complete Reachable Public Type Inspection (P2)
|
||||
|
||||
Status: addressed.
|
||||
|
||||
Location: [public boundary checker](../../public_boundary_test.go),
|
||||
`publicSurfaceViolations`, in its named/alias and method-set traversal.
|
||||
|
||||
The original checker inspected method sets only for exported package-scope type
|
||||
names. It did not inspect methods on an unexported root type reached through an
|
||||
exported function or field. Such methods are still callable by consumers. It
|
||||
also walked generic parameter constraints but not instantiated type arguments;
|
||||
an internal argument can escape without appearing in the underlying fields.
|
||||
|
||||
Both examples below were type-checked through the existing fixture helper and
|
||||
incorrectly produced zero violations:
|
||||
|
||||
```go
|
||||
// Example 1: a caller can invoke New().Leak().
|
||||
type result struct{}
|
||||
func (result) Leak() hidden.Value { return hidden.Value{} }
|
||||
func New() result { return result{} }
|
||||
```
|
||||
|
||||
```go
|
||||
// Example 2: an internal type appears in an exported result signature even
|
||||
// though Box has no field using its type parameter.
|
||||
type Box[T any] struct{}
|
||||
func New() Box[hidden.Value] { return Box[hidden.Value]{} }
|
||||
```
|
||||
|
||||
Here `hidden` is the fixture's own-module internal package. These are separate
|
||||
fixture packages, not additions to Promptkit's API. Temporary diagnostic tests
|
||||
confirmed both false negatives and were removed after review.
|
||||
|
||||
### Resolution
|
||||
|
||||
The recursive named-type traversal now checks reachable root types' value and
|
||||
pointer method sets, using instantiated selections for their signatures. Named
|
||||
types and aliases have their concrete type arguments inspected before their
|
||||
underlying representation is considered. The separate package-scope method
|
||||
loop was removed. Regression fixtures cover returned private types, private
|
||||
field types with public pointer methods, generic arguments, aliases that erase
|
||||
their arguments, and allowed public arguments with recursive method signatures.
|
||||
|
||||
### Acceptance Criteria
|
||||
|
||||
Extend the existing recursive traversal rather than adding a second checker:
|
||||
|
||||
- Inspect accessible methods of reachable root named types, including
|
||||
unexported types, with the existing cycle protection and promoted-method
|
||||
checks. Cover pointer and value method sets where applicable.
|
||||
- Inspect concrete generic type arguments on named types and aliases before
|
||||
losing them through unaliasing or skipping an external named type's internals.
|
||||
Continue checking constraints. Do not recursively police unrelated dependency
|
||||
implementation details.
|
||||
- Add the two reproductions to the compact fixture table and exercise an
|
||||
allowed public type argument as a control. Preserve acceptance of private
|
||||
internal fields and sealed options. Avoid duplicated method traversal.
|
||||
|
||||
Acceptance: both examples are rejected, legitimate private state still passes,
|
||||
and the full maintainer workflow succeeds. No production API changes are needed.
|
||||
|
||||
## Review Validation
|
||||
|
||||
The existing full maintainer workflow passed: ordinary and race tests, vet,
|
||||
build, both offline examples, formatting, Markdown links, and repository
|
||||
hygiene. The targeted diagnostic tests failed as expected, demonstrating the
|
||||
checker gap rather than a runtime failure. No production or permanent test
|
||||
files were changed during this review.
|
||||
|
||||
After remediation, the focused checker tests and full maintainer workflow also
|
||||
passed. The changes are confined to the architecture test and this review log;
|
||||
production code and public contracts remain unchanged.
|
||||
2
go.mod
2
go.mod
@@ -3,7 +3,7 @@ module gitea.maximumdirect.net/eric/promptkit
|
||||
go 1.25.5
|
||||
|
||||
require (
|
||||
gitea.maximumdirect.net/eric/promptkit-backend-openrouter/v2 v2.20260922.0
|
||||
gitea.maximumdirect.net/eric/promptkit-backend-openrouter/v2 v2.20260922.1
|
||||
gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome/v2 v2.20260922.0
|
||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
|
||||
4
go.sum
4
go.sum
@@ -1,5 +1,5 @@
|
||||
gitea.maximumdirect.net/eric/promptkit-backend-openrouter/v2 v2.20260922.0 h1:uxvVFOylxXrzcg0jJLXcRBIj73BGNjvnsRuMoOeoYKw=
|
||||
gitea.maximumdirect.net/eric/promptkit-backend-openrouter/v2 v2.20260922.0/go.mod h1:a3VBbh9oaGXD6ruxhtwHj+AWW6DY/SSyby1QtMmYSUo=
|
||||
gitea.maximumdirect.net/eric/promptkit-backend-openrouter/v2 v2.20260922.1 h1:S2/Q/JDE+m8Ca3pDhAjVbfYrdlEhs9blj0STgNopHo0=
|
||||
gitea.maximumdirect.net/eric/promptkit-backend-openrouter/v2 v2.20260922.1/go.mod h1:a3VBbh9oaGXD6ruxhtwHj+AWW6DY/SSyby1QtMmYSUo=
|
||||
gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome/v2 v2.20260922.0 h1:Y0EXc3eh12eKW2NrOviVqdk3oBo6UUjopt1YAa1B3Oc=
|
||||
gitea.maximumdirect.net/eric/promptkit-backend-rakestrawhome/v2 v2.20260922.0/go.mod h1:mtgD1E0SGm0e/I8Ffhz+AYX7GN7RKUWJXehNFIKHs4Y=
|
||||
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
|
||||
|
||||
@@ -18,7 +18,7 @@ func TestProfileInheritanceBuiltInAliasWorkflow(t *testing.T) {
|
||||
SchemaDir: frameworkSchemaDir,
|
||||
}, promptkit.WithProfiles(promptkit.Profile{
|
||||
ID: "weather-light",
|
||||
BaseProfileID: "deepseek-4-flash",
|
||||
BaseProfileID: "promptkit-openrouter-standard",
|
||||
ReasoningEffort: "high",
|
||||
TimeoutSeconds: 120,
|
||||
}))
|
||||
@@ -26,7 +26,7 @@ func TestProfileInheritanceBuiltInAliasWorkflow(t *testing.T) {
|
||||
t.Fatalf("construct alias engine: %v", err)
|
||||
}
|
||||
|
||||
base, err := engine.InspectProfile(context.Background(), "deepseek-4-flash")
|
||||
base, err := engine.InspectProfile(context.Background(), "promptkit-openrouter-standard")
|
||||
if err != nil {
|
||||
t.Fatalf("inspect base: %v", err)
|
||||
}
|
||||
@@ -84,7 +84,7 @@ func TestProfileInheritanceYAMLAliasOfBuiltIn(t *testing.T) {
|
||||
engine, err := promptkit.NewEngine(promptkit.Config{},
|
||||
promptkit.WithPromptFS(fstest.MapFS{}, "."),
|
||||
promptkit.WithProfileFS(fstest.MapFS{
|
||||
"alias.yaml": &fstest.MapFile{Data: []byte("id: yaml-alias\nbase_profile: deepseek-4-flash\n")},
|
||||
"alias.yaml": &fstest.MapFile{Data: []byte("id: yaml-alias\nbase_profile: promptkit-openrouter-standard\n")},
|
||||
}, "."),
|
||||
)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user