275 lines
16 KiB
Markdown
275 lines
16 KiB
Markdown
# 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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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.
|