Files
promptkit/docs/roadmap/implementation.md

27 KiB
Raw Blame History

Responsibility Simplification Implementation Plan

Scope And Execution

Implement responsibility-simplification.md from baseline c69703b, using the accepted decisions and evidence in A1-responsibility.md. Production code is unchanged from the audit baseline 1ff6d77. Findings 1–7 require changes; finding 8 requires preserving current runtime behavior. All stages below are initially pending.

This replaces the completed 33-stage audit-remediation plan. Historical links from the older audit/remediation documents refer to that earlier plan, available with git show c69703b:docs/roadmap/implementation.md, not to the stages below. Do not repeat the earlier sprint or treat its completion evidence as validation of these changes.

Execute stages in order as one end-to-end sprint. Each stage is a focused Luna prompt. Intermediate stages may leave callers/tests unmigrated or fail to compile; record deferred checks and run them once their affected paths are coherent. Do not add compatibility wrappers or duplicate implementations just to keep an intermediate commit green. No human-review or external-publication gate is needed between stages. Completion concerns the combined end state.

Read development guidance and its applicable policies, especially agents, architecture, testing, and documentation, plus ADR 0001. Use graph tools for discovery and verify actual callers before deletion. Preserve unrelated work. Follow the local commit policy and record completion/evidence for finished stages without claiming temporarily deferred checks passed.

Shared Rules

  • Keep ConfigKit composition/history outside runtime validation. Validate final configuration and genuinely new runtime inputs at their existing boundaries.
  • Preserve the public facade and substantive API/wire behavior, except removal of incidental schema-copy budgets selected in finding 7. The removed direct output-validator workflow is private, not public ValidateRequest.
  • Retain runtime supported values, concrete type/nil behavior, limits, number handling, and errors. Do not narrow runtime values to ConfigKit mapping forms.
  • Keep needed ownership copies, artifact defensive copying, prepared-handle identity/lifecycle, admission versus active permits, HTTP evidence/deadlines, and operation-owner errors. Do not expand this into another subsystem audit.
  • Use existing trusted cloning for accepted values; keep validating copying for actual acceptance. Do not add a reflection framework, schema budget, numeric converter, raw-source validator, or public internal-type alias.
  • Private names are implementation seams, not new public promises. Test selected behavior, not allocation counts, helper choreography, or incidental wording.
  • Include relevant GoDoc/internal documentation with the owning change. Stage 16 reconciles omissions, rather than authorizing stale documentation until then.
  • Select the newest locally available Go installation as documented, with GOTOOLCHAIN=local and GOWORK=off for isolated checks. The audit used Go 1.27.3. This sprint does not select a release, change dependency versions or the consumer Go minimum, or authorize pushing/tagging/publication.

Ownership Inventory For Stages 10–15

Use these decisions, checking the affected callers as they are migrated. Record any discovered mutation edge and account for it in the same boundary; do not introduce a new ownership subsystem.

Value/path Acceptance and mutation Selected ownership treatment
Configured provider values Final configuration validation and effective-target construction own acceptance; retained configuration/index state must not be mutated by runtime work. Preserve acceptance/overlay semantics. Registry/profile lookup may continue returning detached values, but their copies use trusted cloning, not repeated acceptance checks.
Runtime provider override toDomainExecutionTargetOverride, also used by smoke request conversion, validates/copies caller values. Keep that boundary and its errors. Subsequent internal selection may transfer accepted private values without another deep validation pass.
Resolved target within one operation Captured lookup returns detached values; runtime override conversion supplies owned values. Resolution changes scalar fields and selects whole provider maps, not nested content. Transfer selected private maps through preparation/inspection; avoid repeated shallow/deep copying merely between private functions. Preserve current nil/empty projection behavior.
Loaded schema The validator decodes/compiles a self-contained JSON document and retains immutable plan state. Trusted-detach the provider-facing schema without provider-value depth/node validation. Keep the frozen compiled plan and existing acceptance checks.
Prepared metadata Messages/input hashes are created during preparation; selected maps and schema belong to that operation. Retain one immutable redacted snapshot for execution and details. Clear execution-only fields without modifying metadata.
Public prepared/details/result/inspection values Root conversion crosses into caller-owned mutable state. Keep one outward deep projection at that boundary. Never expose a borrowed internal map, schema, message pointer, or slice.
Injected generation and repair The internal runner/repairer reads private settings; repair constructs a new message sequence. The root client adapter supplies a mutable public request. Keep public request detachment for every dispatch, including repairs, and existing response copying. Do not add copies to compensate for removed internal copies.
Smoke reports Selection and internal orchestration use accepted private targets; public report conversion creates caller-owned facts/settings. Keep target redaction/endpoint sanitization and final projection. Remove validation-only copies and redundant private detachment, retaining any copy needed by an actual mutator.

Stage 1: Remove Client-Level Routing Fallbacks

Completed: Client routing now uses the resolved target; constructor fixtures and integration guidance were migrated. With Go 1.27.3, go test ./internal/llm ./internal/generation ./internal/configuration ./internal/usecase ./internal/engine passed, including loaded-target coverage.

Finding: 1. Files: internal/llm/openai_compatible_client.go, client fixtures/tests, internal/engine/engine.go caller verification, docs/internal/llm.md.

  1. Delete OpenAICompatibleConfig.BaseURL/Model, stored baseURL/defaultModel, constructor endpoint normalization, and request fallback branches. Use the selected target endpoint/model directly; retain final validity checks.
  2. Remove the default-model parameter from the request builder and its caller. Preserve HTTP-client cloning/timeouts and request authentication behavior.
  3. Make the internal constructor infallible once its only failure path is gone; update engine assembly and internal callers rather than retaining an always-nil error return. Update constructor fixtures to put routing settings on request targets. Delete tests solely asserting constructor-default precedence; retain endpoint composition/rejection and supplied HTTP-client ownership cases.
  4. Retire internal configured-base fallback prose. Do not add a new default source or change backend/profile/request precedence.

Check: Relevant llm, generation, and loaded-target tests; defer compilation where fixture migration remains. No production construction supplies the removed fields.

Stage 2: Encode One Root Wire Representation

Completed: Requests now build the provider payload directly, with structured dispatch evidence derived from that payload. Go 1.27.3 go test ./internal/llm ./internal/generation passed, including mapping, presence, payload freezing, session, structured-output, and encoding-failure tests.

Finding: 2. Files: internal/llm/openai_compatible_client.go and request-mapping tests.

  1. Replace the root domain request -> openAIChatRequest -> map sequence with one direct payload builder. Remove the intermediate root struct and obsolete projection helper; retain useful nested typed wire structures.
  2. Preserve explicit numeric zero versus omission, session normalization, native schema envelopes, reserved/empty extension-key errors, and flattened provider extensions. Derive structured-output evidence from the same selected constraint, not a second independent mapping.
  3. Keep successful payload encoding once and existing encoding-failure error classification/privacy. Do not introduce JSON round trips or a custom serializer.

Check: Run go test ./internal/llm ./internal/generation; reuse request-mapping, presence, prepared-payload freezing, session, and structured-dispatch assertions.

Stage 3: Require Captured Repository Operations

Completed: Repository interfaces require captured definitions, metadata, requirements, and profile identity; the alternate lookups and hash wrapper were removed. Go 1.27.3 go build ./... passed with the real configuration snapshot. Use-case test fixture compilation is deferred to the next stage.

Finding: 3. Files: internal/promptdef/repository.go, internal/profile/repository.go, internal/usecase/{runner,prompt_inspection,profile_inspection,requirements_inspection}.go, internal/configuration/prompts.go and targets.go.

  1. Make the runner's prompt repository explicitly provide GetPromptSnapshot, GetPromptInspection, and GetRequirementSnapshot with their existing signatures. Require GetProfileIdentity alongside GetProfile on its profile repository. Reuse the existing domain/template values; no public interfaces change.
  2. Call these captured operations directly. Remove capability assertions and alternate full-definition/profile lookup/hash paths. Do not add new rejection rules for hashes or introduce runtime hashing in another helper.
  3. Preserve direct not-found versus load-error ownership, context checks, exact IDs, and metadata-only inspection. Keep captured definition detachment.
  4. Remove unused legacy repository methods and the use-case hash wrapper once callers are migrated; retain the hash implementation used by configuration.

Check: Inspect the real configuration snapshot against the new interfaces. Use-case tests may remain uncompilable until Stage 4; no transitional fallback is needed.

Stage 4: Migrate Repository Fixtures And Inspection Tests

Completed: Private repositories now supply captured lookup operations and inspection tests cover captured hashes, metadata, identities, and errors. Go 1.27.3 go test ./internal/configuration ./internal/usecase passed.

Finding: 3. Scope: private repository fixtures in use-case tests and affected configuration tests.

  1. Update small repository fixtures to supply captured hashes, metadata, and requirement snapshots through Stage 3's operations. Prefer real in-memory configuration where useful, rather than rebuilding configuration resolution.
  2. Replace the missing-metadata-capability fallback case with captured-hash and narrow-inspection behavior. Preserve useful tests for missing resources, lookup errors, cancellation, independent returned metadata, and namespaces.
  3. Remove fixture methods/helpers that solely support deleted alternatives. Keep convenient no-repair runner construction and controlled external doubles.

Check: Focused configuration/use-case prompt, profile, and requirement inspection tests. Renderer-related failures may be deferred through Stage 6.

Stage 5: Keep Only Captured Rendering

Completed: Rendering now requires captured templates and no longer parses messages or sessions per call. Go 1.27.3 go build ./... passed; renderer and use-case test migrations and their checks are deferred to the next stage.

Finding: 3. Files: internal/prompt/go_renderer.go, template helpers, engine assembly.

  1. Remove NewGoRenderer and the nil-template lookup mode. Keep NewCompiledRenderer consuming the existing TemplateLookup.
  2. Remove per-call parsing branches and the uncompiled session-rendering helper. Keep construction-time compilation, missing captured-template errors, per-call template cloning/function binding, and direct-session suppression.
  3. Preserve input requirements, roles/cache-control behavior, message order, artifact text resolution, cancellation, and rendered/session hash inputs. Do not expand recognized template syntax or add a template cache.

Check: Engine assembly already provides captured templates. Test callers are deliberately migrated in Stage 6 rather than accommodated in production.

Stage 6: Move Renderer Tests Onto Captured Templates

Finding: 3. Scope: prompt rendering tests/benchmarks and their use-case/configuration callers.

  1. Use CompileTemplate and a small TemplateLookup fixture, or a loaded configuration snapshot, to provide message/session parses. Keep parsing outside benchmark timing where measuring execution rather than capture.
  2. Preserve syntax-error protection at compilation/capture, runtime missing variable/input cases, direct/rendered session behavior, artifact-text lifecycle, cancellation, and independent requirement-versus-rendering comparisons.
  3. Do not recreate the deleted parser mode inside a renderer fixture. Share only simple fixture setup; avoid a general test configuration framework.

Check: Run go test ./internal/prompt ./internal/configuration ./internal/usecase. Revisit deferred Stage 3–5 checks; carry any still-blocked checks forward to final validation without adding transitional code or an intermediate gate.

Stage 7: Use Prepared Plans For Both Smoke Output Checks

Finding: 4. Files: internal/usecase/smoke_inference_case.go and diagnostic tests.

  1. Replace the smoke case's jsonValidator validate.Validator with a validate.PreparedValidation JSON-only plan, prepared through the existing validator. Keep the distinct compiled schema plan and provider schema.
  2. Invoke JSON-only validation first and schema validation only after syntax passes. Preserve nil/false/true facts, cancellation precedence, scalar JSON syntax, construction errors, privacy, and current diagnostic completion rules.
  3. Do not move json.Valid into orchestration or add a composite validation API. JSON-only plan creation performs no schema loading/compilation.

Check: Focused smoke tests for malformed JSON, valid nonmatching schema, matching schema, cancellation, and native schema dispatch. Reuse existing coverage.

Stage 8: Remove Standalone Direct Output Validation

Finding: 4. Files: internal/validate/validator.go, standard_validator.go.

  1. Remove the standalone Validator interface and concrete host/FS Validate(ctx, artifact, contract) methods after Stage 7's migration.
  2. Delete the direct on-demand schema callbacks. Keep ValidationPreparer, PreparedValidation, shared instance-mode validation, and prepared schema execution. Simplify callback plumbing tied only to the removed workflow without writing a new validation mechanism.
  3. Preserve host and fs.FS root-source handling, eager plan compilation, synchronous context boundaries, self-containment/portability checks, numeric decoding, and frozen plans. Keep nil-validator/no-op behavior in the runner.

Check: Production no longer calls a direct validator. Old test calls may temporarily fail to compile; migrate them in Stage 9, not through a wrapper.

Stage 9: Migrate Validator Tests To Prepared Execution

Finding: 4. Scope: internal/validate tests, particularly standard-validator and cancellation cases.

  1. Express meaningful direct-validation cases as plan preparation followed by plan validation. Keep malformed instance outcomes separate from preparation failures, rather than retaining decode-before-schema-I/O as an expectation.
  2. Retain independent host/FS path and containment coverage, source mutation/removal freezing, references/unused declarations/portability, JSON precision, basic/JSON modes, and cancellation around reading/compilation/execution where already selected.
  3. Delete redundant direct/prepared duplicates and mocks of the retired interface. In-progress synchronous dependency work is still not detached on cancellation.

Check: Run go test ./internal/validate ./internal/usecase and relevant root schema/smoke tests. Resolve Stage 8's deferred checks.

Stage 10: Remove Copier-Derived Schema Budgets

Finding: 7. Files: internal/usecase/runner.go, prepared_execution.go, schema/preparation tests.

  1. Replace schema-document validation/copying in structuredOutputFromValidationPlan and prepared metadata cloning with trusted detachment of the decoded schema. Preserve nil-plan/missing-document failures and the existing frozen schema boundary.
  2. Remove cloneJSONValue if no longer needed; do not substitute another limited walker, JSON-number conversion, or new schema-resource check.
  3. Replace the fake-plan excessive-depth rejection expectation with selected acceptance/isolation behavior. Include a representative real loaded schema exceeding the old copier depth or node budget in annotation data, which the compiler accepts; verify preparation and outward detachment. Generate large fixtures in test setup, not as bulky checked-in files.
  4. Preserve invalid/external-schema rejection and runtime provider-value budgets. Do not turn the regression into a promise of arbitrary depth or provider support.

Check: Focused prepared/schema-file tests plus internal/validate and internal/jsonvalue tests establish that only schema-copy acceptance changed.

Stage 11: Detach Captured Backend And Profile Values Without Revalidation

Finding: 5; preserve 8. Files: internal/domain/smoke_diagnostics.go, internal/backend/registry.go, internal/configuration/targets.go, associated tests.

  1. Apply the ownership inventory: final validation/effective construction remains responsible for configured acceptance; later lookup does not repeat it.
  2. Make CloneBackend an infallible trusted deep clone, retaining smoke metadata detachment. Remove copy-only errors from effective registry construction and update its callers; GetBackend still reports genuine not-found errors.
  3. Keep GetProfile returning a detached target/map using trusted cloning, retaining context/not-found failures and presence semantics. Keep required construction ownership separation from the retained ConfigKit result.
  4. Leave configured overlay/acceptance semantics intact in this stage; assembling a new effective map is not the same as copying a captured lookup result. Do not remove final validateExtraParams or runtime override validation.

Check: Backend/configuration tests cover mutation isolation, composed targets, null/empty values, and construction errors without pinning deleted copy-error branches.

Stage 12: Transfer Accepted Provider Maps Through Internal Resolution

Finding: 5; preserve 8. Files: internal/usecase/runner.go, profile_inspection.go, smoke_selection.go, related ownership tests.

  1. With detached lookup values from Stage 11, pass selected maps through private target resolution rather than copying them again. Runtime replacement maps already belong to the converted request; scalar overrides need not mutate them.
  2. Remove the extra validating map copy in profile inspection. Retain credential redaction and the root facade's independent public projection.
  3. Remove redundant copyExtraParams uses in target/override/smoke selection and the helper if unused. Preserve existing nil/empty outcomes, including inheritance for an empty runtime map; do not let sharing alter public JSON shapes.
  4. Keep the facade's toDomainExecutionTargetOverride validation/deep copy and actual client/result detachment. Do not expose internal request sharing as a new mutable consumer interface.

Check: Focused target precedence, profile inspection, runtime override, smoke selection, and mutation-isolation tests. Retain typed/numeric runtime cases.

Stage 13: Share One Immutable Prepared Metadata Snapshot

Findings: 5–6. Files: internal/usecase/prepared_execution.go, prepared_execution.go, convert.go, lifecycle/ownership tests.

  1. Remove payload cleanup's write into prepared metadata. Keep clearing private credential, observer, retry, validation, and execution payload references under the existing lifecycle. Owner identity and claim/discard synchronization stay.
  2. Retain the prepared operation's one redacted metadata snapshot for both internal execution and details. Remove the extra provider-map clone and separate deep details snapshot created by PrepareExecution.
  3. Make the internal details accessor return that immutable private snapshot; its root caller performs the sole outward fromDomainPreparedRun copy. Update private comments/tests to distinguish borrowed internal metadata from mutable public details. Do not expose an internal type in a public signature.
  4. Delete clonePreparedRun and hidden copy-error-to-nil fallback once unused. Preserve nil/zero public handle behavior, details after use/discard, source freezing, and private direct-key lifetime. Execution and repair must not mutate shared metadata, including nested maps, cache controls, or schema values.

Check: Race-enabled prepared lifecycle, concurrent claim/discard, engine/view binding, independent details, mutation, credential, and repair tests. Public Run results also remain detached from metadata retained by the handle.

Stage 14: Simplify Smoke Target And Public Report Detachment

Finding: 5. Files: internal/usecase/smoke_tester.go, smoke_diagnostics.go, smoke conversion/ownership tests.

  1. Keep accepted targets private and read-only through diagnostic orchestration; remove their validation-only provider-map copy in smokeReportTarget where no mutable ownership handoff occurs. Keep endpoint sanitization, credential redaction, and genuine endpoint errors.
  2. Use the existing trusted public execution-target projection in fromDomainSmokeTestReport, rather than another CopyMap. Make report conversion infallible and update facade callers, removing only the impossible report-copy error path. Other operational/configuration errors remain.
  3. Retain detached report facts, attempts, pointer fields, and nested provider values. Delete the internal invalid-provider-map conversion-error test that sustains revalidation of fabricated unaccepted reports; retain its meaningful public acceptance/ownership protection at the real boundary.

Check: Smoke conversion isolation, privacy, partial/canceled reports, and configured-default/runtime-override diagnostics through the public facade.

Stage 15: Verify Cross-Path Ownership And Runtime Compatibility

Findings: 5–8. Scope: focused existing public and package contract tests.

  1. Reconcile the ownership inventory with the delivered call paths. Verify that prepared details/results, profile inspection, smoke reports, and injected initial/repair requests cannot mutate retained engine/handle state. Extend a representative existing test only where these changes leave a meaningful gap.
  2. Keep valid typed/named runtime containers, numbers, nil/empty forms, map replacement, and current invalid/cyclic/over-budget rejection at acceptance. Distinguish those provider budgets from removed schema budgets.
  3. Exercise a mutating injected client across initial and repair calls and concurrent details/claim/discard where existing coverage supplies the seam. Keep the built-in HTTP payload freeze and existing artifact defensive copy.
  4. Review remaining copy/validation callers for purpose. Remove overlooked repeated acceptance work on the selected paths, not all copies indiscriminately. Do not preserve private copy-failure tests as new public requirements.

Check: Run targeted race-enabled root/use-case/configuration/jsonvalue tests. Record results and any reconciled ownership edge; no benchmark framework or exact allocation threshold is needed.

Stage 16: Reconcile Canonical Documentation And Retire Obsolete Descriptions

Findings: 1–8. Scope: GoDoc, docs/internal/{overview,llm,runner,sources}.md, relevant consumer/format guidance, feature roadmap completion status.

  1. Remove descriptions of client routing defaults, uncaptured renderer/repository fallbacks, standalone direct output validation, duplicate prepared metadata, and prepared-schema copier limits. Describe the delivered ownership paths.
  2. Record broadened schema acceptance only where consumer/format guidance needs it. Keep the self-contained-schema rule, runtime provider budgets, and existing number handling; add no resource/provider/performance promises.
  3. Keep exact public contracts in GoDoc, formats/wire behavior with their owning references, and private mechanics in internal docs. Update affected comments throughout, not just the package inventory.
  4. Update the feature roadmap with delivered outcomes and pending final checks; do not mislabel the audit's original tests as replacement validation. Leave unrelated completed-roadmap retirement and release notes to their own work.

Check: Documentation links and whitespace, plus searches for the retired names/claims to separate historical audit evidence from stale current guidance.

Stage 17: Validate And Close The Sprint

Scope: combined final state, all findings and deferred checks.

  1. Resolve remaining deferred compilation/tests; format changed Go files. Run go test -race ./... and go vet ./... using the selected local toolchain. The suite includes maintained examples; separate ordinary/full build/example runs are not additional required checks for the same unchanged candidate.
  2. Check documentation links, git diff --check, full intended/staged diff, and repository status. Exclude secrets, generated artifacts, local workspace files/replacements, and unrelated changes. No release publication check is needed.
  3. Confirm removal of client defaults, duplicate root wire representation, optional lookup fallbacks, uncaptured rendering, direct-validator lifecycle, redundant copy-validation paths, duplicate prepared metadata, and schema-copy budgets. Verify that remaining copies implement real ownership boundaries.
  4. Record final evidence and completion for findings 1–7 and preservation of 8 in the feature roadmap/plan. A deferred check or unimplemented selected change is not completion. Preserve actual scope if a new blocker appears and surface it rather than substituting a compatibility layer or narrowing the feature.
  5. Commit the completed work under repository policy and report the result and any remaining unrelated workspace changes. Do not push, tag, or publish.

End state: The selected roadmap is implemented with fewer private workflows, representations, and redundant traversals; public behavior and ownership remain intact except for the explicitly removed incidental schema restriction.