Plan the profile policy implementation
This commit is contained in:
@@ -1,337 +1,262 @@
|
||||
# Public Facade Refactor Implementation Plan
|
||||
# Profile Policy Implementation Plan
|
||||
|
||||
## Scope And Authority
|
||||
## Scope And Starting Point
|
||||
|
||||
Implement the [public facade roadmap](public-facade.md) without changing the
|
||||
consumer API or execution behavior. This plan owns implementation sequence;
|
||||
the feature roadmap owns the target state and compatibility requirements.
|
||||
The provisional [profile policy](profile-policy.md) is a separate, subsequent
|
||||
scope. Do not update catalog dependencies, introduce standard profiles, change
|
||||
profile stability promises, or prepare a release in these stages.
|
||||
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.
|
||||
|
||||
Read `AGENTS.md`, the [development guide](../development.md), and all three
|
||||
policies before starting: [architecture](../policy/architecture.md),
|
||||
[documentation](../policy/documentation.md), and [testing](../policy/testing.md).
|
||||
Use existing GoDoc and canonical consumer/format documentation to distinguish
|
||||
intentional contracts from incidental implementation. If a relocation appears
|
||||
to require a consumer-facing change, stop and report it rather than silently
|
||||
changing the contract. Existing exported declarations are not removal candidates
|
||||
merely because a guide does not mention them.
|
||||
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.
|
||||
|
||||
Each numbered stage is one implementation prompt. Complete stages in order;
|
||||
keep the repository building and maintain one active production path after
|
||||
each stage. Update affected durable documentation when its described ownership
|
||||
changes, rather than leaving inaccurate descriptions until the final stage.
|
||||
For each stage, run focused tests while developing and the complete
|
||||
[maintainer validation workflow](../development.md#maintainer-validation)
|
||||
before acceptance. Report changes, validation results, and any unresolved
|
||||
failures. Do not use live providers, credentials, sibling repositories, module
|
||||
replacements, or a Go workspace to validate the result.
|
||||
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
|
||||
|
||||
- Add `internal/engine` as the composition owner. It owns engine construction,
|
||||
defaults, source assembly, catalog loading, registry and capacity construction,
|
||||
and runner/repairer wiring. It delegates execution to `internal/usecase`;
|
||||
it does not become a second runner.
|
||||
- Keep root-defined public types, errors, options, conversions, collaborator
|
||||
adapters, and formatting. Root `Engine` holds a private `*engine.Engine`.
|
||||
The internal engine exposes only the domain-level operations needed for
|
||||
the existing facade methods. No public bridge methods or internal aliases.
|
||||
- Preserve root `Option` and its sealed `apply(*engineOptions) error` mechanism.
|
||||
Ultimately, private root `engineOptions` wraps an internal `engine.Options`
|
||||
value whose private state and setters own source construction and option
|
||||
accumulation. Root options remain closures applying in caller order; do not
|
||||
replace them with a deferred list that changes when errors or copies occur.
|
||||
- Put the memory profile repository in `internal/profile`. Existing domain,
|
||||
profile validation, and JSON-copy helpers remain the owners of their rules.
|
||||
Do not duplicate validation in the facade and repository.
|
||||
- Keep public error classification and redacted public error construction in
|
||||
the root. Internal construction returns descriptive errors; `NewEngine`
|
||||
translates construction failures to `ErrInvalidConfig` as it does today.
|
||||
Runtime errors continue through `mapPublicError` at the public boundary.
|
||||
- Keep `PreparedExecution` root-defined with its existing private use-case
|
||||
handle. Pass that internal handle through engine delegation without copying
|
||||
its execution state or creating another lifecycle owner. Private root
|
||||
references to specialized internal packages are allowed.
|
||||
- Do not impose a single internal import on the root, introduce a generic
|
||||
builder framework, add caching, broaden validation, or migrate all private
|
||||
helpers merely to reduce root line count. Straightforward public convenience
|
||||
constructors and boundary conversions may remain where they are.
|
||||
- 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: Establish The Compatibility Baseline
|
||||
## Stage 1: Prepare Both Catalog Modules For The New Contract
|
||||
|
||||
Purpose: make the compatibility review concrete before moving ownership.
|
||||
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. Read the root declarations and tests, the
|
||||
[consumer guide](../consumers/pkg-promptkit.md),
|
||||
[component overview](../internal/overview.md),
|
||||
[sources document](../internal/sources.md), and
|
||||
[runner document](../internal/runner.md). Identify existing contract coverage
|
||||
for constructor options, profile sources, injection, errors, and prepared
|
||||
execution. Read their owning internal tests before adding new coverage.
|
||||
2. Record the pre-refactor commit ID in this plan and capture an exported API
|
||||
inventory for the final comparison. Include exported declarations, named
|
||||
types, fields and tags, interface signatures, value and pointer method sets,
|
||||
constants, error variables, and serialization/formatting contracts. `go doc
|
||||
-all` is a useful starting point, not a complete method-set comparison.
|
||||
Temporary comparison output belongs outside tracked source; do not introduce
|
||||
a permanent snapshot of private structure or freeze every future API addition.
|
||||
3. Use existing tests first. Add only missing, consequential public regression
|
||||
coverage for relocation risks: source replacement versus backend accumulation,
|
||||
option application/capture timing, ownership of injected values and profiles,
|
||||
nil/zero facade behavior, and typed error translation. Keep public behavior
|
||||
tests in the external test package where practical. Do not duplicate full
|
||||
source, transport, capacity, or runner matrices.
|
||||
4. In particular, inspect the existing contracts around `WithProfiles` copying
|
||||
during option application and `WithBackend` capturing the queue-capacity
|
||||
pointer value during option creation. Preserve explicit zero versus unset.
|
||||
Keep errors from an invalid earlier option observable even if a later option
|
||||
would replace it. Do not add reflection-based typed-nil rejection or eagerly
|
||||
read lazy consumer sources as part of the refactor.
|
||||
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: the pre-refactor baseline is identified, necessary regression
|
||||
coverage passes, and no production ownership or behavior has changed. If the
|
||||
existing tests already cover these risks, do not add tests solely to fill this
|
||||
stage; record the coverage reviewed and proceed.
|
||||
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.
|
||||
|
||||
### Completion
|
||||
## Stage 2: Publish And Verify The Catalog Releases
|
||||
|
||||
- [x] Pre-refactor baseline commit: `7a858c2365e1a3625de67a46f5c488e0fe31856b`.
|
||||
- [x] Captured the exported API inventory outside the tracked repository for
|
||||
the final comparison.
|
||||
- [x] Reviewed existing public coverage for source replacement, backend
|
||||
accumulation, option error and capture timing, injected-value and profile
|
||||
ownership, nil and zero facade behavior, prepared execution, and typed error
|
||||
translation. The existing tests cover these relocation risks without a
|
||||
duplicate matrix.
|
||||
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.
|
||||
|
||||
## Stage 2: Relocate The Memory Profile Repository
|
||||
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.
|
||||
|
||||
Purpose: move a self-contained repository before changing engine assembly.
|
||||
Acceptance: both published dependencies resolve normally without sibling
|
||||
checkouts, workspaces, or replacements.
|
||||
|
||||
1. Introduce `internal/profile.NewMemoryRepository` accepting internal profile
|
||||
definitions. Move the map-backed repository and lookup implementation from
|
||||
root `profiles.go` to that package. Preserve normalized duplicate-ID detection,
|
||||
definition validation, missing-profile classification, inheritance metadata,
|
||||
and independently owned values on storage and lookup.
|
||||
2. Separate public field conversion from repository normalization as necessary.
|
||||
Root `WithProfiles` converts at application time and invokes the new internal
|
||||
constructor. Use the existing definition-normalization and JSON-copy owners
|
||||
once at the repository boundary; preserve rejection of invalid extra values
|
||||
and deep-copy guarantees without an unnecessary second validation pass.
|
||||
Audit other callers before changing the responsibilities of `toDomainProfile`.
|
||||
3. Remove the root repository implementation. Leave public `Profile` and
|
||||
`OpenAICompatibleProfile` unchanged, including the convenience constructor's
|
||||
documented copy behavior; do not strengthen that contract incidentally.
|
||||
4. Move private repository tests to `internal/profile`, adapting inputs to
|
||||
internal values. Retain representative public `WithProfiles` integration and
|
||||
conversion coverage at the root. Add only uncovered copy/validation cases.
|
||||
Update the internal source document and inventory for the new owner.
|
||||
## Stage 3: Enforce The External Catalog Namespace
|
||||
|
||||
Acceptance: `WithProfiles` uses the internal repository in the active engine;
|
||||
public behavior is unchanged and no duplicate root repository remains.
|
||||
Repository: Promptkit. Keep current v1 dependencies during this stage;
|
||||
dependency adoption remains atomic in Stage 5.
|
||||
|
||||
### Completion
|
||||
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.
|
||||
|
||||
- [x] Moved the in-memory repository, normalization, validation, and defensive
|
||||
copies into `internal/profile`.
|
||||
- [x] Kept public conversion and `WithProfiles` application timing at the root.
|
||||
- [x] Moved focused repository coverage to `internal/profile` and retained
|
||||
facade-level copy timing coverage.
|
||||
- [x] Updated the implemented component and source ownership documentation.
|
||||
Acceptance: catalogs cannot occupy the namespace; existing protections and
|
||||
consumer source behavior are unchanged.
|
||||
|
||||
## Stage 3: Move Engine Assembly And Delegation Inward
|
||||
## Stage 4: Add And Compose Promptkit-Owned Profiles
|
||||
|
||||
Purpose: establish the internal engine while leaving source-option relocation
|
||||
for the next prompt.
|
||||
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.
|
||||
|
||||
1. Add internal `Config`, `Options`, and `Engine` types. Internal `Config` carries
|
||||
the existing construction settings, not a new consumer configuration API.
|
||||
For this stage, `Options` may carry the already-prepared collaborators,
|
||||
repositories, backend definitions, and source-presence flags from the root
|
||||
option state. Do not lose distinctions between an absent source and an
|
||||
explicitly supplied empty source. Stage 4 removes this transitional mapping.
|
||||
2. Move the assembly portion of root `NewEngine`, after option application,
|
||||
into `internal/engine.New`, including maintained module imports and
|
||||
`newProfileRepository`. Preserve the existing assembly semantics:
|
||||
- prompt-source requirement and configured source defaults;
|
||||
- validated maintained catalogs and engine-local backend registry;
|
||||
- raw profile precedence: memory, ordinary configured source, application
|
||||
fallback, maintained catalog; an explicit ordinary source replaces
|
||||
`Config.ProfileDir`, and one resolver wraps the complete overlay;
|
||||
- schema default and supplied validator selection;
|
||||
- supplied or default client and artifact reader selection; and
|
||||
- one capacity manager per engine, one capacity wrapper around the selected
|
||||
client, and that same wrapped client used by runner and repairer.
|
||||
3. Give internal `Engine` domain-level forwarding methods for the existing
|
||||
prepare, run, prepared-execution, and inspection operations. Keep runner
|
||||
orchestration and prepared-handle lifecycle in `internal/usecase`. Do not
|
||||
add another queue, retry loop, mutex, source cache, or execution state machine.
|
||||
4. Change root `Engine` to hold the internal engine. Root `NewEngine` still
|
||||
applies options and maps constructor errors. Root methods still check
|
||||
nil/zero receivers, convert/validate public requests at their existing
|
||||
boundary, convert results, and translate runtime errors. Do not wrap an
|
||||
error twice or expose internal typed provider errors instead of public ones.
|
||||
5. Adapt tests that inspect private runner fields to the new owner or, where
|
||||
feasible, observable contract assertions. Reuse existing tests for prepared
|
||||
handle engine binding, shared copied-handle state, consumption/discard,
|
||||
cancellation, redaction, repair, and capacity. Add an assembly test only if
|
||||
a consequential wiring obligation is otherwise untested.
|
||||
6. Update architecture, component inventory, sources, and runner documentation
|
||||
to describe the implemented split. Remove the superseded root assembly path.
|
||||
Acceptance: both names work through existing APIs, consumer precedence remains
|
||||
effective, and no public exports or provider routing logic have been added.
|
||||
|
||||
Acceptance: all public operations route through one internal engine and the
|
||||
existing runner; maintained catalogs and component wiring are internally owned.
|
||||
Prepared-execution behavior and public error contracts remain unchanged.
|
||||
## Stage 5: Adopt Published V2 Catalogs And Replace Snapshot Tests
|
||||
|
||||
### Completion
|
||||
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.
|
||||
|
||||
- [x] Added `internal/engine` as the owner of engine assembly and runner
|
||||
delegation.
|
||||
- [x] Kept the public facade's option application, conversions, nil checks,
|
||||
prepared-execution wrapper, and error translation at the root.
|
||||
- [x] Updated architecture, component, source, and runner documentation for
|
||||
the implemented ownership split.
|
||||
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 4: Move Option State And Source Construction Inward
|
||||
## Stage 6: Publish Durable Policy And Consumer Guidance
|
||||
|
||||
Purpose: finish the ownership split without changing the public option API.
|
||||
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.
|
||||
|
||||
1. Replace the root collaborator/flag record with a private wrapper around
|
||||
`engine.Options`. Move the construction state into private fields of that
|
||||
internal type. Remove Stage 3's transitional root-to-internal state mapping.
|
||||
Internal setters correspond to the existing source, profile, backend, client,
|
||||
and artifact options; no generic option registry or callback framework.
|
||||
2. Move filesystem/`fs.FS` repository and validator construction, `fileSource`,
|
||||
source-presence flags, replacement rules, and backend accumulation into
|
||||
internal option methods. Invoke them during each root option's `apply`, not
|
||||
collectively after all options. Preserve current file checks and lazy source
|
||||
loading; do not add path restrictions or normalize actual paths beyond the
|
||||
existing contract. Preserve separate blank checks for whitespace-bearing
|
||||
valid paths.
|
||||
3. Keep public-to-internal conversion and public collaborator adapters at the
|
||||
root. Preserve closure capture and validation timing from Stage 1, including
|
||||
queue-capacity capture, profile copies, nil options, and ordinary interface
|
||||
nil checks. Internal methods consume internal values/interfaces without
|
||||
importing root types. Do not copy injected client or reader implementations.
|
||||
4. Root `NewEngine` now performs only ordered option application, configuration
|
||||
translation, internal construction, and public error translation. Review the
|
||||
remaining root imports/helpers: retain boundary work, remove dead assembly
|
||||
helpers, and do not relocate formatting or conversion for appearance alone.
|
||||
5. Move implementation-only option/source setup tests with their owner, while
|
||||
retaining public timing and error assertions at the facade. Update affected
|
||||
documentation immediately. No exact private field layout becomes a test
|
||||
requirement.
|
||||
Acceptance: durable documentation distinguishes stable literal names from
|
||||
volatile selections and agrees across repositories without weakening unrelated
|
||||
contracts.
|
||||
|
||||
Acceptance: the root no longer constructs repositories, validators, registries,
|
||||
capacity managers, catalogs, or runners. Public options still have their existing
|
||||
names, signatures, ordering, capture, and error behavior. No transitional state
|
||||
mapping or duplicate source-assembly path remains.
|
||||
## Stage 7: Final Integration Review And Release Handoff
|
||||
|
||||
### Completion
|
||||
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.
|
||||
|
||||
- [x] Wrapped the root option state around internal engine options with private
|
||||
construction state.
|
||||
- [x] Moved filesystem and file source setup, source replacement, profile
|
||||
repository construction, validator construction, and backend accumulation
|
||||
into internal option methods.
|
||||
- [x] Kept ordered public option application, boundary conversion, collaborator
|
||||
adaptation, and error translation in the root facade.
|
||||
- [x] Updated current architecture and internal ownership documentation.
|
||||
|
||||
## Stage 5: Guard The Public Boundary And Dependency Direction
|
||||
|
||||
Purpose: protect the intended architecture without freezing private layout.
|
||||
|
||||
1. Add a focused root architecture test using Go type information. Load the
|
||||
compiled root package with standard-library `go list` export data and
|
||||
`go/importer`/`go/types`; avoid a new production dependency or parsing only
|
||||
surface syntax. It must work in the ordinary offline maintainer workflow
|
||||
once normal module dependencies are available.
|
||||
2. Inspect exported declarations, public field types, function signatures,
|
||||
interface methods, and both pointer and value method sets. Follow nested
|
||||
type expressions and aliases with a visited set to avoid recursion. Reject
|
||||
references to this module's internal types in accessible public surfaces,
|
||||
public aliases to those types, and internal anonymous embedding that exposes
|
||||
implementation methods. Account for generics if encountered rather than
|
||||
silently ignoring their signatures or constraints.
|
||||
3. Permit private internal fields and the sealed `Option` method. Do not follow
|
||||
inaccessible fields as if they were public contracts or reject all aliases
|
||||
indiscriminately. Check accessible promoted methods even if the embedded
|
||||
field itself is unexported. Do not require the root to import only
|
||||
`internal/engine`, or impose rules on unrelated third-party internals.
|
||||
4. Check production package imports, using package metadata, for any dependency
|
||||
from this module's `internal/` packages to its root. Exclude external test
|
||||
packages from that restriction. Do not assert an exact internal package list.
|
||||
5. Exercise the boundary checker with a small in-memory fixture set: allowed
|
||||
private internal state and sealed option; forbidden direct/nested internal
|
||||
signature or field; forbidden internal alias and promoted method. Keep the
|
||||
test helper local and proportionate, not a reusable architecture framework.
|
||||
|
||||
Acceptance: the completed refactor passes the checks; representative violations
|
||||
fail for the intended reason, and ordinary private implementation changes remain
|
||||
possible. No ConfigKit checkout or other sibling is needed.
|
||||
|
||||
### Completion
|
||||
|
||||
- [x] Added a compiled-export-data checker for the root facade's reachable
|
||||
public type surface, including aliases, promoted methods, and generic
|
||||
constraints.
|
||||
- [x] Added package-metadata validation that production internal packages do
|
||||
not import the root facade.
|
||||
- [x] Added compact in-memory fixtures for permitted private state and sealed
|
||||
options, and for direct, nested, field, alias, and promoted-method leaks.
|
||||
- [x] Recorded the dependency-direction rule in the architecture policy.
|
||||
|
||||
## Stage 6: Complete Compatibility And Documentation Review
|
||||
|
||||
Purpose: verify the whole refactor, not just successful compilation of each move.
|
||||
|
||||
1. Compare the final exported API against the Stage 1 commit, including method
|
||||
sets, fields/tags, type ownership, interfaces, and public error identities.
|
||||
Review any difference; no API additions/removals/redesigns are authorized.
|
||||
Inspect supported serialization and formatting alongside the existing tests.
|
||||
2. Review the final root package for retained business assembly or duplicated
|
||||
repositories, and the internal engine for duplicated runner behavior. Review
|
||||
test moves for lost assertions and duplicate matrices. Existing specialized
|
||||
packages should still own their detailed behavior tests; facade tests should
|
||||
prove conversion, compatibility, and representative assembled behavior.
|
||||
3. Finish the durable documentation review: architecture owns dependency rules;
|
||||
the internal overview inventories owners; sources and runner docs explain
|
||||
their current implementation. Correct stale links and root-assembly claims.
|
||||
Keep public GoDoc authoritative and avoid adding consumer migration steps,
|
||||
format rules, or new guarantees for an internal relocation. No separate ADR
|
||||
is needed merely to restate the existing facade policy.
|
||||
4. Run the entire maintainer workflow, including race tests, vet, build, both
|
||||
offline examples, formatting, local links, and repository hygiene checks.
|
||||
Review the complete diff against the baseline. Report any environmental
|
||||
validation blocker explicitly; do not call an unrun check successful.
|
||||
5. Report completion against the feature roadmap criteria. Retain these two
|
||||
temporary documents for the maintainer's completion review; their later
|
||||
retirement follows documentation policy. Do not start the profile-policy
|
||||
work or tag a release as part of this plan.
|
||||
|
||||
Acceptance: compatibility review finds no unauthorized changes, all required
|
||||
validation passes, documentation matches the implemented architecture, and the
|
||||
refactor is ready for independent review before subsequent feature work.
|
||||
|
||||
### Completion
|
||||
|
||||
- [x] Compared the final exported GoDoc inventory with the recorded baseline;
|
||||
no exported API difference was found. Reviewed the root source diff to
|
||||
confirm that fields, tags, interfaces, method sets, error identities, and
|
||||
formatting contracts remain unchanged.
|
||||
- [x] Confirmed that root production code retains boundary conversion and error
|
||||
mapping only, while internal engine assembly delegates to the existing runner
|
||||
and specialized packages retain their focused behavior coverage.
|
||||
- [x] Reviewed architecture, component inventory, source, runner, and model
|
||||
client documentation for current ownership and local links.
|
||||
- [x] Completed the full offline maintainer validation workflow and repository
|
||||
hygiene review.
|
||||
Acceptance: ready for independent review and subsequent release preparation,
|
||||
with validation results and any blockers reported.
|
||||
|
||||
## Open Questions
|
||||
|
||||
None requiring a product decision for this scope. The refactor preserves the
|
||||
existing API and behavior; the provisional catalog policy and its release
|
||||
decisions remain outside this plan.
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user