diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index 3a81c85..ae76ee7 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -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.