diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index 7733a52..dafc4b7 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -1,523 +1,290 @@ -# Implementation Plan: PromptKit v0.12.0 Adoption +# Implementation Plan: ReleaseKit Adoption -**Last updated:** 2026-10-04 -**Status:** Complete; Stages 1–9 completed. +**Last updated:** 2026-10-07 +**Status:** Ready for implementation; no stages completed. **Audience:** Luna coding agent. ## Scope and Execution -Implement the accepted target in the [PromptKit roadmap](promptkit.md). That -document owns feature intent and policy choices; this plan owns the ordered -implementation work. The planning baseline is Audita commit -`b31955fc97adec707b4e5f9a1b0c43c4cbc66750`: ConfigKit v0.5.0 is adopted, -PromptKit is v0.11.2, and the finalized roadmap includes the selected-profile, -operator-override, example-layout, and major-release clarifications. +Implement the target in the [ReleaseKit roadmap](releasekit.md), following +[ADR 0001](../adr/0001-releasekit.md). The roadmap owns intent and policy +choices; this document owns execution. The planning baseline is Audita commit +`418da456d75a68d3bb5a43ab823c5b2b434b90cc`: v3.0.0 is released, the ADR is +accepted, and release tooling still uses the custom scripts and delivery plugin. -This replaces the completed ConfigKit plan at this path. Its -[completed implementation record](https://gitea.maximumdirect.net/eric/audita/src/commit/b31955fc97adec707b4e5f9a1b0c43c4cbc66750/docs/roadmap/implementation.md) -remains available for readers following the ConfigKit completion roadmap. +This replaces the completed PromptKit plan. Its +[completion record](https://gitea.maximumdirect.net/eric/audita/src/commit/418da456d75a68d3bb5a43ab823c5b2b434b90cc/docs/roadmap/implementation.md) +remains available for historical adoption references. -Execute Stage 1 through Stage 9 in order. Each is sized as one bounded Luna -implementation prompt. Commit completed units with short, plain English messages -under the [agent policy](../policy/agents.md); no approval round is needed between -stages. Record actual checks and any remaining expected migration failures. -Stages 1 and 2 change formats before Stage 3 changes their consumer. Intermediate -commits need not be runnable or release-ready. Do not add temporary readers, -compatibility shims, fallback engines for execution, or scaffolding to make them -so. Later stages complete the same migration rather than separate product modes. +Execute Stage 1 through Stage 5 in order. Each is a bounded Luna implementation +unit. Commit completed units with plain English messages under the +[agent policy](../policy/agents.md), recording the relevant checks. Intermediate +commits need not be release-ready; complete the migration directly without +compatibility wrappers for the old release arguments or temporary release modes. -Start with [development guidance](../development.md) and the applicable agent, -[architecture](../policy/architecture.md), [testing](../policy/testing.md), -[documentation](../policy/documentation.md), and [OSS](../policy/oss.md) -policies. Use graph-first discovery. Read the current -[configuration](../config.md), [LLM runtime](../internal/llm-runtime.md), -[prompt registry](../internal/prompts.md), and -[LLM integration](../integrations/openai-compatible-llm.md) contracts for the -established behavior this migration preserves. +Start with [development guidance](../development.md), use graph-first discovery, +and follow the applicable [architecture](../policy/architecture.md), +[testing](../policy/testing.md), [documentation](../policy/documentation.md), +[release](../policy/release.md), and [OSS](../policy/oss.md) policies. Preserve +transcript processing and its current configuration, reporting, and LLM behavior. -Target the released PromptKit v0.12.0 at commit -`4b8169da286917fde7875425bb32b799b12c6af3`, ConfigKit v0.5.0, and both -maintained `/v3` catalogs at `v3.20260930.0`. Read the pinned -[format reference](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.12.0/docs/formats.md) -and [migration guide](https://gitea.maximumdirect.net/eric/promptkit/src/tag/v0.12.0/docs/consumers/pkg-promptkit.md#migrate-from-the-previous-configuration-api). -The sibling checkout is reference material, not a dependency replacement. +Use ReleaseKit v0.1.0, commit +`5e60fe3113c69f95c42fbbe32a8ca4b51f5b83c1`. The sibling checkout is reference +material. Its pinned [configuration](https://gitea.maximumdirect.net/eric/ReleaseKit/src/tag/v0.1.0/docs/config.md), +[CLI](https://gitea.maximumdirect.net/eric/ReleaseKit/src/tag/v0.1.0/docs/cli.md), +[build](https://gitea.maximumdirect.net/eric/ReleaseKit/src/tag/v0.1.0/docs/consumers/build.md), +and [delivery](https://gitea.maximumdirect.net/eric/ReleaseKit/src/tag/v0.1.0/docs/consumers/delivery.md) +contracts own generic mechanics. Keep Go 1.25.5 and unrelated dependency +selections. Use released modules without a production local replacement. ### Selected Implementation Decisions -- Keep Go 1.25.5, application `version: 2`, current flags, role selection, - application overlays, and main-file-relative path rules. Retain the - `profiles_dir` name and default; broaden its accepted documents as agreed. -- Use PromptKit's catalog and owned defaults, then caller underlays for embedded - Audita prompts and operator directory inputs, then `Sources.Main` for - application backend settings. Directory inputs compose strictly within their - group; discovery order supplies no field precedence. Keep imports disabled. -- Use one ConfigKit mapping for the final application source. For each - application backend, supply its endpoint, `concurrency_limit`, - `queue_capacity`, and explicit `api_key_env: null`. The null suppresses - lower-tier credential lookup. Leave other supported provider fields available - to native layering. Do not put resolved credential values in this mapping. -- Keep selected-role registration, endpoint-match, competing-credential, and - required-key checks. Add explicit nonblank effective model and endpoint checks - for both selected roles. Valid unselected partial profiles remain permitted. -- Preserve the adapter's complete per-call schemas, configured repairs/retries, - operation context, shared variables, observation, and prepare/check/run flow. - Operator messages can omit shared-variable references; do not append the - shared text unconditionally or require particular message counts or roles - beyond PromptKit's own format rules. -- Use captured source inspection for consumed host configuration and message - paths. Keep source-relative resource resolution with PromptKit and ConfigKit; - Audita projects paths for its existing output collision checks. -- Replace the old profile-reload test expectation with snapshot behavior. - Successful construction uses only final effective definitions. A failed - construction may make an embedded-only diagnostic construction to distinguish - asset defects from operator errors; it never executes or substitutes for the - requested configuration. -- Maintained example roots are `examples/profiles/local/` and - `examples/profiles/service/`. Service testing profiles stay in the service - root. Keep the literal `temperature: 0` in examples as an explicit outbound - setting, and use native presence semantics without a compatibility translator. +- Audita imports `ReleaseKit/buildinfo` for runtime version information. The + upstream executable owns release orchestration; no application release engine + or private linker variable is needed. +- `releasekit.json` owns product facts. Local tooling builds the executable from + the module graph; CI pins the same v0.1.0 release explicitly. +- Keep `scripts/release.sh` as a thin entry point with native ReleaseKit + arguments, such as `publish VERSION` and `check VERSION`. Compile its tool into + ignored `bin/releasekit` and invoke it with `exec` to preserve native statuses. +- Main-first preparation, annotated tags, the offline standard suite, Linux + builds, and the native version smoke check are accepted. On a nonselected + host, the shared builder may compile a temporary native executable and require + its check to succeed. Keep only Linux amd64 and arm64 delivery targets. +- CI uses managed `ci-deliver` and the existing `GITEA_RELEASE_TOKEN` secret, + exposed to the command as `RELEASEKIT_GITEA_TOKEN`. Retained prebuilt artifacts + remain an upstream recovery option rather than a second ordinary CI sequence. +- Additional profile checks are omitted. Do not repeat the standard suite, + maintain a local Git/publication guard layer, or copy upstream delivery logic. + Focus tests on Audita wiring and reuse existing protection for common mechanics. -This unit is an intentional major-release migration. Exact version selection, -release notes, tag/push, and publication timing remain release preparation under -the [release policy](../policy/release.md). Guided recovery, new report formats, -hot reload, extra configuration commands, and scheduling changes remain outside -this plan. Tests should protect changed integration behavior and established -contracts, not reproduce the libraries' entire validation matrices. +This implementation sprint does not choose an Audita release version, write a +new versioned release note, tag, push to the authoritative repository, contact +Gitea with delivery credentials, or wait for CI. Deployment observations belong +to the first adopting release and its separate delivery status. No extra release +gates or platform guarantees are introduced by these adoption checks. -## Stage 1 — Convert Embedded Prompt Definitions +## Stage 1 — Add the Dependency and Version Command -**Primary files:** The seven YAML files under -`internal/prompts/assets/prompts/`. +**Primary files:** `go.mod`, `go.sum`, `internal/cli/run.go`, and focused tests in +`internal/cli`. -1. Wrap each existing definition beneath `prompts`, its exact current ID, and - the string version `v1`. Remove the old inner `id` and `version` fields. - Keep filenames and Audita registry identifiers unchanged; filenames are - asset locations rather than PromptKit identities. -2. Preserve messages, block-scalar text, variable references, task examples, - output settings, and schema paths. Preserve the applicable references to - `HardeningPolicy`, `ProposalContract`, and `ValidationContract`. Do not edit - shared fragments, response schemas, or domain policies to accommodate the - new container format. -3. Review each before/after definition structurally, including YAML indentation - inside block scalars. Do not introduce default profile selections or new - repair counts. The adapter continues to own the runtime output contract. - -**Verification and completion:** Check all seven migrated identities and -version keys against `RegisteredMetadata`, and run `git diff --check`. Registry -preparation tests become runnable with the new constructor in Stage 3. Commit -the asset conversion; do not introduce an old-format reader to test it here. - -**Completion marker:** Stage 1 complete. All seven registered prompt assets -use keyed prompt/version mappings; parsed definitions were structurally checked -against their prior content, and `git diff --check` passed. - -## Stage 2 — Migrate Operator Profiles, Example Roots, and YAML Fixtures - -**Primary files:** `examples/profiles/`, the three maintained configuration -examples, and profile-producing test fixtures in -`internal/framework/llm/{runtime_inspection,adapter,adapter_capacity}_test.go`, -`internal/framework/proposal_generation/adapter_integration_test.go`, -`internal/framework/validators/llm_integration_test.go`, -`internal/framework/runner/cancellation_test.go`, and -`cmd/audita/main_integration_test.go`. - -1. Move local proposal/validation examples beneath `profiles/local/`; move the - four service proposal/validation and testing files beneath - `profiles/service/`. Convert each to `profiles: {: }` in readable - YAML. Keep IDs, models, positive timeouts, and controls, including explicit - zero temperature. No example needs a real credential or live model. -2. Set `profiles_dir: profiles/local` in `examples/minimal-config.yml` and - `examples/configkit-inheritance.yml`; set `profiles_dir: profiles/service` - in `examples/production-config.yml`. Preserve the testing overlay's role IDs - and the existing ConfigKit inheritance example. Select the leaf root, since - recursive discovery at their common parent would still load both groups. -3. Convert profile YAML emitted by the listed fixtures to keyed definitions. - Search for remaining old profile construction strings and removed - `base_profile` syntax, and migrate any genuine profile fixture found. - Do not rewrite transcript/proposal `id` fields or domain schema fixtures. - Keep test source names independent of profile IDs where already exercised. -4. Keep negative tests negative for their selected behavioral reason. Give - cases clean temporary layouts or replace their contribution completely - rather than leaving an unrelated invalid definition behind for later cases. - Eager validation now reads unselected final definitions too. Do not remove - such definitions merely to simulate the old lazy loader where the test is - intended to exercise eager validation. - -**Verification and completion:** Review the six profiles, explicit root -selections, and changed fixture text; run `git diff --check` and format touched -Go test files. These formats become consumable in Stage 3. Commit this unit. -Current documentation links and recipes are updated together in Stage 8. - -**Completion marker:** Stage 2 complete. Six maintained profile documents are -keyed and split into separately selected local/service roots; the listed Go -fixtures use keyed definitions. Touched Go files were formatted and -`git diff --check` passed. Runtime tests are deferred until Stage 3 replaces -the current consumer, as the plan allows intermediate commits not to run. - -## Stage 3 — Adopt the Released Source API and Selected-Role Checks - -**Primary files:** `go.mod`, `go.sum`, -`internal/framework/llm/runtime.go`, and `internal/prompts/registry_test.go`. - -1. Upgrade with `go get gitea.maximumdirect.net/eric/promptkit@v0.12.0` and - reconcile the module files. Verify ConfigKit stays v0.5.0, the catalog - dependencies become `/v3` at `v3.20260930.0`, and obsolete `/v2` requirements - are removed when unused. Retain the Go minimum and unrelated selections; - introduce no local replacements. -2. Resolve `profiles_dir` exactly as the current runtime does. Obtain embedded - inputs with `pk.FilesystemInputs` and operator inputs with `pk.DirectoryInputs`. - An unavailable selected root is an operator error; an empty directory can - contribute no definitions. Do not require one profile per file, IDs matching - filenames, or profile-only top-level content. -3. Construct the agreed `pk.ConfigurationSources`: two ordered caller underlays - for embedded and operator groups, and one highest-priority application - `ck.Input` whose source is the mapping specified above. Retain - `pk.WithSchemaFS`, the supplied HTTP client, and configured transient retries. - Remove old prompt/profile/backend registration options. -4. Inspect registered prompt ID/version selections, then both selected roles. - Reject a selected role whose effective model or endpoint is empty or - whitespace-only. Retain backend registration, normalized endpoint equality, - nonblank effective `APIKeyEnv` rejection, and required-credential checks. - Preserve literal IDs; do not trim/re-key identities or require all profiles - to be complete. Populate the same role inspection map for both clients. -5. Migrate the registry test engine to `FilesystemInputs` and a programmatic - `ProfileSource` fixture in its own tier, retaining its schema filesystem. - A complete endpoint/model fixture without an application backend is valid - for this direct library test; Audita's selected-role guard belongs in its - runtime tests. Keep the embedded prompt preparation assertions scoped to - embedded prompts. -6. Remove the old `profileSourceFS` wrapper once unused. Source accounting is - completed in Stage 5. Preserve the adapter boundary; change other production - callers only to resolve actual API incompatibilities. Search for remaining - uses of removed source options and old `pk.Profile`/`pk.Backend` values. - Run `go mod tidy` after migrating construction callers and review its diff. - -**Verification and completion:** Run `go test ./internal/prompts` and the -existing offline profile assembly, unsafe-selection, and absolute-directory -tests in `internal/framework/llm`. Run `git diff --check` and review the module -diff. The obsolete file-reload assertion is intentionally replaced in Stage 6; -do not restore reload behavior to make that assertion pass. Commit the runtime -API migration. - -**Completion marker:** Stage 3 complete. Runtime construction now uses the -released PromptKit source API with the selected application mapping; module -selections match PromptKit v0.12.0 and both `/v3` catalogs at -`v3.20260930.0`. `go mod tidy`, prompt registry tests, offline profile -assembly, unsafe-selection, absolute-directory tests, and `git diff --check` -passed. Captured source accounting remains in Stage 5. - -## Stage 4 — Preserve Startup Failure Classification and Validate Assembly - -**Primary files:** `internal/framework/llm/runtime.go`, -`internal/framework/llm/runtime_inspection_test.go`, and configuration-command -tests in `internal/cli`. Update `internal/cli/run.go` only where the changed -startup path needs existing exit behavior preserved. - -1. Treat embedded discovery failures as `AssetError`; treat operator-directory - discovery failures as configuration input errors. Preserve wrapped causes - for `errors.Is`/`errors.As` and retain configured-secret redaction at CLI - boundaries. Caller cancellation remains a runtime exit, not an operator - mistake, and should not trigger further diagnostic loading. -2. PromptKit wraps both definition-loading and template/content failures in - `ErrInvalidConfig`; some materialization errors have no public source/path - type. Do not classify by parsing error strings or by that sentinel alone. - On final engine-construction failure, perform an embedded-only diagnostic - construction with the same embedded prompt/schema sources and library - defaults, excluding operator inputs and application backend mappings. If - that also fails, surface an `AssetError` with the asset cause; otherwise - return the original final-construction error as an operator/configuration - error. The diagnostic engine does no provider work and is never retained - for execution. Keep a small unexported assembly seam accepting an embedded - filesystem so tests can exercise asset failures without modifying shipped - files or creating a global test hook. -3. Do not run this diagnostic construction as a successful-path preflight. - A valid final snapshot remains accepted even if an operator contribution - repairs an otherwise invalid lower-tier prompt. Verify that property with - the same small assembly test seam. This avoids strengthening upstream - final-value validation into mandatory validation of displaced definitions. -4. Cover incomplete selected profiles using omitted, empty, and null model - contributions and a cleared selected endpoint. Exercise proposal and - validation selection, including omission-derived validation selection, with - a rejecting HTTP transport. Confirm valid unselected partial profiles are - accepted; malformed unselected definitions, undefined backend references, - and conflicting directory contributions still fail under native rules. -5. Add focused boundary coverage that invalid operator YAML/template/resource - input produces configuration exit `2`, and test the asset classification - directly at the runtime seam. Reuse existing CLI handling of `AssetError` - for exit `1`; no damaged-binary subprocess fixture is needed. Cover the - shared `NewRuntime` validation route and preserve cancellation exit `1` in - configuration commands if the new error path would otherwise classify it - as `2`. Avoid exact complete diagnostic wording assertions. - -**Verification and completion:** Run targeted startup/inspection tests and -`go test ./internal/cli`; check whitespace and commit. Preserve the original -failure cause where available rather than flattening it to a generic error. - -**Completion marker:** Stage 4 complete. Embedded discovery and construction -failures are distinguished from operator inputs through an embedded-only -diagnostic construction; cancellation skips that diagnostic. Selected-profile -completeness and native directory validation are covered, and both config -commands preserve exit 1 for cancellation/assets and exit 2 for invalid -operator YAML, templates, and resources. Targeted runtime tests, -`go test ./internal/cli`, and `git diff --check` passed. - -## Stage 5 — Protect Consumed Configuration and Message Files - -**Primary files:** `internal/framework/llm/runtime.go` or a focused source-path -helper in that package, `internal/cli/process.go`, runtime source-accounting -tests, and `cmd/audita/main_integration_test.go`. - -1. Rename the internal `Runtime.ProfilePaths` field to `SourcePaths` and update - its process caller. It now covers consumed host YAML and message resources, - rather than profiles alone. Populate it from the successfully captured final - engine; do not expose source metadata as a new public output. -2. Call `InspectConfiguration`. Index `Sources()` by source ID, and collect - paths with `Kind == ck.SourceKindFile`; embedded filesystem and synthetic - sources are not host paths. All loaded host YAML counts, including unused - definitions and files whose contributions were later overlaid. Deduplicate - paths and sort for a stable internal projection. -3. For message resources, enumerate `Metadata().HistoricalPaths()` and retain - effective, nonnull paths shaped as - `/prompts///messages//content_file`. Use `Lookup` and the - effective field's origin, not an inherited destination's guessed source. - PromptKit successfully captures these fields only with a unique usable - source context. Obtain the effective scalar from `Explain(path).Effective` - and decode that scalar YAML into a string with the existing YAML dependency. - This decodes captured inspection data; it is not a second configuration - loader. When the contributing source is a host file, join the untrimmed - resource name against that source file's directory and add it to the ledger. - Ignore displaced references and non-host resources. Do not reread operator - YAML, infer IDs from filenames, or reimplement resource-root validation. -4. Pass `SourcePaths` through existing `diagnostics.PrepareOutput` protection. - Leave canonicalization, symlink/hardlink checks, permitted in-place transcript - handling, and output initialization with their current owner. Do not protect - every unrelated file in the selected directory or add filesystem mutation - guarantees beyond the existing collision contract. -5. Extend `TestSubprocessProfileSources` and a focused runtime case to cover an - arbitrarily named YAML contribution, a consumed source-relative message - file, and conflicting transcript/report destinations. Use a non-YAML message - filename, such as `instruction.md`, so directory discovery does not mistake - plain prompt text for a configuration document. Include an inherited message - reference from a different directory and a prompt ID/version with a JSON - Pointer escape character so source provenance and literal keys determine - the path. Check rejection before provider dispatch and unchanged input bytes. - Preserve acceptance of an unused alternate output filename; do not turn the - whole directory into a forbidden output location. - -**Verification and completion:** Run focused source-ledger tests and subprocess -collision cases, plus `git diff --check`, then commit. Check that resource -accounting uses the frozen snapshot and never changes the engine's source or -resource-resolution behavior to facilitate tracking. - -**Completion marker:** Stage 5 complete. `Runtime.SourcePaths` now projects -host YAML and effective source-relative message files from PromptKit's captured -configuration inspection, using field provenance for inherited references. -Process output protection consumes that ledger. Focused source-accounting and -subprocess collision tests passed, including unchanged input bytes, no provider -dispatch, JSON Pointer-escaped keys, and acceptance of an unused alternate -output; `git diff --check` passed. - -## Stage 6 — Verify Operator Prompt Overrides and Captured Execution - -**Primary files:** `internal/framework/llm/adapter_test.go` and focused runtime -tests. Change `adapter.go` only for an actual integration defect. - -1. Add a native keyed operator contribution overriding messages for an active - prompt/version. Use the real runtime and controlled HTTP responses to prove - the operator text reaches both the prepared snapshot and dispatched request. - One case deliberately omits shared-variable references and still succeeds; - do not require Audita to inject their text. A reference-bearing case renders - the adapter-supplied value and retains existing protection against caller - variables replacing the reserved shared variables. -2. Override the prompt's definition-level output contract with another valid - upstream contract. Prove that Audita's per-call JSON schema and configured - repair budget still govern execution: a structurally invalid response is - repaired or exhausted as the controlled budget dictates. Domain validators - remain downstream. Reuse existing validator/proposal integration coverage - for their rules rather than weakening them to fit an operator prompt. -3. Replace the reload portion of - `TestPreparedAdapterRejectsTargetDriftAndPreparationErrors`. After successful - construction, change a profile or message file and verify the existing - runtime still uses its captured settings/text. Construct a new runtime to - observe a valid edit or reject a newly mismatched endpoint. Keep the missing - prompt preparation failure case. -4. Retain a focused test of the prepared-target check independently of reload: - deliberately change the test runtime's application backend endpoint after - construction and verify the inconsistency is blocked before dispatch. This - tests the existing guard, not a supported live mutation/reload feature. - Continue executing the same prepared handle whose details were inspected; - do not add another preparation or an application-side retry loop. - -**Verification and completion:** Run the prompt override, snapshot, and -prepared-adapter tests. Compare semantic messages and selected targets, not old -hash values or exact YAML formatting. Check whitespace and commit. - -**Completion marker:** Stage 6 complete. Native operator messages reach both -the prepared snapshot and provider request, with and without shared-variable -references. The adapter's per-call schema and repair budget remain effective -under a valid operator output-contract override. Existing runtimes retain -captured prompt/profile values after source edits, and a new runtime observes -valid edits; the target guard and preparation failure remain covered. The -`internal/framework/llm` tests and `git diff --check` passed. - -## Stage 7 — Verify Native Profiles, Backend Authority, and Resilience - -**Primary files:** Runtime inspection and adapter tests, -`internal/framework/llm/adapter_capacity_test.go`, and existing framework/CLI -integration tests where their established behavior is affected. - -1. Add a compact native profile inheritance fixture with literal keyed IDs - unrelated to filenames, multiple definitions in one file, a partial parent, - and a complete selected child. Verify inherited controls survive a child - model change and child overrides win. Reuse the metadata-facing literal-key - coverage from Stage 5 rather than repeating it in profile tests. -2. Use controlled HTTP request bodies to distinguish explicit zero temperature - from omission and inherited-control suppression by null. Check a - representative recursively overlaid provider parameter and null clearing; - do not promise that all providers accept every valid configured zero. - Reuse existing deadline/cancellation coverage for unchanged outer deadlines; - explicit zero profile timeout must not disable the operation context. -3. Verify an operator backend contribution can add supported provider fields, - while a conflicting endpoint/concurrency/queue/environment contribution - cannot displace the final application fields. Preserve an explicit profile - environment lookup as a selected-role error rather than hiding it with an - adapter override. Include an application backend using a catalog ID to show - it is allowed and its catalog credential lookup is suppressed. Use synthetic - environment values and local HTTP fixtures, not provider catalog endpoints. -4. Reuse `TestRolesShareBackendCapacityAndReleaseAfterCancellation` and - `TestDistinctBackendsHaveIndependentCapacity`; verify the final mapped - limits, including zero queue capacity, still coordinate both roles and - remain backend-local. Strengthen a fixture with conflicting lower-tier - capacity only where needed to prove the new mapping wins. Keep existing - synchronization; do not infer admission with sleeps or add another limiter. -5. Preserve offline selected-profile inspection and value-free application - explanations. Check configured secrets, endpoint strings, arbitrary provider - fields, and prompt text remain outside the current safe profile summary. - Do not replace it with a full upstream dump. Its numeric projection is not - proof that an omitted provider setting is sent; wire presence belongs to - the HTTP coverage above. -6. Run the existing transient retry, structural repair, attempt-count, - observation, partial-validation, and all-model-failure subprocess cases - after fixture migration. Preserve their error/recovery/debug classifications, - cancellation, and continued output. Fix proven integration regressions; - do not rewrite domain outcomes or reduce budgets to obtain a passing suite. +1. Add `gitea.maximumdirect.net/eric/ReleaseKit@v0.1.0` with `go get`. Import its + public `buildinfo` package in the CLI and run `go mod tidy` after the import + is present. Review the dependency diff for unrelated upgrades or replacements. +2. Add `version` dispatch to the existing CLI. With no arguments, print + `audita ` followed by `buildinfo.Version()` and a newline to stdout, returning + zero. Run this route independently of application configuration and runtime + assembly. Use the existing output streams and standard-library parsing style. +3. Add the command to root help. Support `help version` and the usual + `version -h`/`version --help` help behavior with stdout and status zero. + Unexpected positional arguments or unknown flags use the existing usage-error + status two. No new version flags are needed at the root level. +4. Add compact CLI coverage for successful version output, help, and malformed + invocation. Derive the expected version from the public accessor rather than + hardcoding `dev`. Exercise the version route from a temporary working directory + without application setup and verify stderr stays empty on success. Preserve + existing commands and help behavior. **Verification and completion:** Run -`go test ./internal/framework/llm ./internal/framework/proposal_generation ./internal/framework/validators ./internal/framework/runner ./internal/cli ./cmd/audita` -and `git diff --check`. Review whether each new test addresses a distinct changed -boundary. Commit the native-profile and runtime verification unit. +`go test ./internal/cli ./cmd/audita`, build the application to ignored +`bin/audita`, and run its `version` command. Run `git diff --check`, review the +module diff, and commit. Real release-version injection is verified in Stage 5; +no test should hardcode an upstream private linker symbol. -**Completion marker:** Stage 7 complete. Native profile inheritance, control -presence, provider-map overlays, application backend authority, selected -credential rejection, catalog-ID handling, shared backend capacity, and safe -inspection behavior are covered. The six targeted packages passed, along with -focused wire, timeout, capacity, credential, and safe-view tests; `git diff ---check` passed. +## Stage 2 — Introduce the Product Profile and Thin Local Wrapper -## Stage 8 — Document the Migration and Update Attribution +**Primary files:** new `releasekit.json`, `scripts/release.sh`, and +`scripts/release_test.go`. -**Primary files:** `docs/config.md`, `docs/internal/llm-runtime.md`, -`docs/internal/prompts.md`, `docs/integrations/openai-compatible-llm.md`, -`docs/operations.md`, `docs/internal/cli-config.md`, `README.md`, and -`docs/oss/attribution.md`. +1. Write a JSON profile with these exact product settings: -1. Update the configuration contract for unified `profiles_dir` content, exact - keyed identities, directory composition, agreed tier precedence, profile - inheritance/presence, selected-role completeness, eager validation of all - final definitions, selected-root failures, and construction-time capture. - Replace the obsolete statement that PromptKit profiles do not gain ConfigKit - inheritance. Retain application overlays, defaults, and credential ownership. -2. Include concise migration instructions in the profile section: wrap old - profile fields beneath `profiles/`, remove inner `id`, change - `base_profile` to `extends`, review explicit values/nulls, and select roots - whose final definitions have valid backend references. Show a small keyed - inheritance/override snippet and link complete maintained examples. Explain - explicit zero temperature versus omitted or null controls and link upstream - for the full field table. State that this ships as an Audita major migration; - do not invent an exact release version or automatic file conversion. -3. Document intentional prompt overrides and optional shared-variable references. - Supplying shared variables does not inject omitted text, while per-call - schemas and domain validators remain enforced. Internal prompt documentation - distinguishes shipped asset instructions from operator-effective messages; - no prompt-quality rewrite or new global prompt-policy requirement is added. -4. Describe layered runtime assembly, source accounting, snapshot use, and - startup classification in their internal owner. Update the pinned PromptKit - consumer link in the LLM integration contract. Expand operations' loaded - source description to include consumed operator message files; keep physical - output/collision rules with operations and diagnostics. -5. Repair example navigation for separate local/service roots, especially the - README's local-profile link. Update validation recipes to use the maintained - config files' explicit roots and keep the service testing overlay workflow. - Review other affected links without rewriting historical release notes. -6. Update the PromptKit and both catalog attribution entries to selected versions - and exact commit-pinned source/notice URLs. Resolve catalog tag commits from - the selected module origins or authoritative upstream refs, not annotated - tag object IDs. Check the releases' COPYRIGHT/LICENSE files and retain the - applicable unchanged local LGPL/GPL and MIT texts. Keep the existing House - Format; no new license selection, policy rewrite, or attribution inventory - is needed. Review `go.mod`/`go.sum` against those entries. + | Field | Value | + | --- | --- | + | `product` | `Audita` | + | `remote` | `origin` | + | `build.main_package` | `./cmd/audita` | + | `build.binary_name` | `audita` | + | `build.targets` | `linux/amd64`, `linux/arm64` | + | `delivery.base_url` | `https://gitea.maximumdirect.net` | + | `delivery.owner` | `eric` | + | `delivery.repository` | `audita` | + | `delivery.token_env` | `RELEASEKIT_GITEA_TOKEN` | -**Verification and completion:** Check affected local links/anchors, format -examples against the implemented loader, verify source revisions/notices, and -run `git diff --check`. Commit the documentation and attribution unit. - -**Completion marker:** Stage 8 complete. Configuration, runtime, prompt, -integration, operations, contributor, and README guidance now reflects native -PromptKit layering, migration, presence, snapshot, and separate example-root -behavior. Attribution matches PromptKit v0.12.0 and both v3 catalog module -origins and notices. Local links/anchors and `git diff --check` passed. - -## Stage 9 — Validate the Integrated End State and Close the Plan - -**Primary files:** This plan and the feature roadmap; correct an implementation -file only if the final checks reveal an actual gap. - -1. Verify the full roadmap acceptance criteria against the landed code and the - distinct tests from these stages. Review for unintended requirements: - profile-only filtering, mandatory shared text in operator messages, - filename-derived IDs, complete unselected profiles, catalog ID bans, - successful-path asset preflights, compatibility readers, and new output - guarantees are not part of the accepted target. -2. Run `go build -o ./bin/audita ./cmd/audita` and `go test ./...`. Keep the - generated binary out of commits. Reuse successful checks on unchanged - content; rerun checks affected by any corrective code changes. -3. Validate the maintained examples offline using the built binary: + Omit `checks`. Store no token value and use the upstream profile format + directly; Audita does not need another profile parser in production. +2. Replace the wrapper body with straightforward Bash using `set -euo pipefail`: + select the repository directory relative to the script, create `bin/`, build + the selected CLI, and execute it with the original argument vector. The + build command is: ```sh - ./bin/audita config validate --config examples/minimal-config.yml - ./bin/audita config validate --config examples/configkit-inheritance.yml - AUDITA_SERVICE_KEY=synthetic-example ./bin/audita config validate --config examples/production-config.yml - AUDITA_SERVICE_KEY=synthetic-example ./bin/audita config validate --config examples/production-config.yml --overlay testing - ./bin/audita config print-effective --config examples/minimal-config.yml --view profiles - ./bin/audita config print-effective --config examples/configkit-inheritance.yml --view explain + GOWORK=off GOTOOLCHAIN=local go build -mod=readonly \ + -o ./bin/releasekit gitea.maximumdirect.net/eric/ReleaseKit/cmd/releasekit ``` - Confirm local/service roots and testing selections work without provider - dispatch. Check safe views exclude resolved secrets and preserve the - established explanation fields. Do not call a model to validate examples. -4. Check the selected dependency graph, attribution, affected links, and final - diff. Run `git diff --check`. Confirm only the released modules are used and - no obsolete `/v2` catalog or removed construction API remains in active code. - Historical release documents and historical roadmap links may retain old - versions as accurate records. -5. Mark this plan and the feature roadmap complete only after the full target - passes. Record the tested implementation revision and checks accurately; - distinguish a subsequent documentation-only completion commit. Commit the - completion documentation and report remaining work, if any. Do not select - a release number, publish, tag, push, poll CI, or add permanent release gates. + Finish with `exec ./bin/releasekit "$@"`. Preserve argument boundaries and + build failures. Existing `bin/` ignore rules suffice. Let ReleaseKit parse + its commands and report errors; remove all local note, version, Git, test, + build-target, and publication mechanics from the wrapper. +3. Replace `TestReleaseWorkflow`'s old fourteen-scenario matrix. Use a temporary + layout with the real wrapper and a stub at the Go/tool boundary to verify + repository selection, forwarded native arguments (including an argument with + spaces), and returned tool status. Include uncertain publication status three + and a failed bootstrap that never executes the tool. The stub writes a small + executable at the requested output path; assert effects and arguments without + tying tests to harmless build-flag ordering or a particular shell layout. +4. Add a focused check of the committed JSON profile's product/build/delivery + facts and absence of additional checks or credential values. Standard JSON + decoding in test code is sufficient. Keep this coverage alongside wrapper + tests; compare target membership rather than incidental list order. Avoid + reproducing upstream profile validation or remote guard tests. +5. Keep `scripts/build-release.sh` until Stage 3 removes its CI caller. The new + wrapper already uses ReleaseKit's selected build specification. -**Completion marker:** Stage 9 complete. The tested implementation revision is -`5525fe8`; the preceding documentation migration commit is `9bcf183`, and this -roadmap closure is documentation-only. At `9bcf183`, the application built, -`go test ./...` passed, all six maintained example commands passed offline, -`go mod verify` passed, the selected module graph contained PromptKit v0.12.0 -and both `/v3` catalogs at `v3.20260930.0` with no `/v2` catalogs, and -`git diff --check` passed. The active Go/module scan found no removed PromptKit -construction options. +**Verification and completion:** Run `go test ./scripts`, then +`bash scripts/release.sh version` to verify real tool bootstrap and execution. +This prints the tool's version, not Audita's. Check ignored build output and +`git diff --check`, then commit. No publication or delivery invocation against +an external service is needed. -**End state:** Native PromptKit configuration and catalogs are adopted, -operator overrides and captured resources work through the real runtime, -application backend/domain ownership and resilience remain effective, and -maintained examples and migration documentation match the implementation. -No implementation-blocking decisions remain; exact major-release numbering -and publication timing remain outside this implementation unit. +## Stage 3 — Migrate Woodpecker Delivery and Retire the Builder + +**Primary files:** `.woodpecker/release.yml` and deletion of +`scripts/build-release.sh`. + +1. Adapt the maintained upstream + [tag-delivery template](https://gitea.maximumdirect.net/eric/ReleaseKit/src/tag/v0.1.0/examples/woodpecker/tag-delivery.yml). + Use its matrix and single `deliver` step with `GO_IMAGE: golang:1.25.5` and + `RELEASEKIT_VERSION: v0.1.0`. Select tag events under `refs/tags/v*`. +2. Map the command environment variable `RELEASEKIT_GITEA_TOKEN` from the + existing Woodpecker secret `GITEA_RELEASE_TOKEN`. Use the existing credential; + no new secret name or credential provisioning is selected by this migration. +3. Use the template's command, preserving Woodpecker interpolation escaping: + + ```sh + go run gitea.maximumdirect.net/eric/ReleaseKit/cmd/releasekit@${RELEASEKIT_VERSION} ci-deliver \ + --repo "$${CI_WORKSPACE}" \ + --commit "$${CI_COMMIT_SHA}" \ + "$${CI_COMMIT_TAG}" + ``` + + ReleaseKit owns fetch/checkout verification, dependency preparation, builds, + note-page creation, manifests, and uploads. Remove the separate build step, + release plugin, wildcard asset settings, and local checksum configuration. + Managed delivery gets its targets and destination from `releasekit.json`. +4. Delete `scripts/build-release.sh` after confirming its active caller is gone. + Search remaining script/CI references and remove only obsolete active + invocations. Historical release records retain their original descriptions. +5. Review the parsed workflow against the template: selected image/pin, tag + trigger, token mapping, and event arguments. Use the existing YAML dependency + or available tooling for local syntax inspection. Confirm the tool pin matches + the selected module. This is adoption validation; it does not require a new + permanent workflow-text snapshot test or a running Woodpecker instance. + +**Verification and completion:** Run `go test ./scripts`, review the workflow +and profile together, and run `git diff --check`. Commit the delivery migration. +The existing Go image must provide compatible Go and Git; real runner execution +is observed during subsequent delivery, independently of source completion. + +## Stage 4 — Align Policy, Documentation, and Attribution + +**Primary files:** `docs/release.md`, `docs/policy/release.md`, `docs/cli.md`, +`docs/internal/cli-config.md`, `docs/adr/README.md`, and +`docs/oss/attribution.md`. Update other current references only where affected. + +1. Rewrite the runbook around dependency preparation, a committed candidate, + `git push origin main`, and `bash scripts/release.sh publish VERSION`. + Explain that remote `main` must identify the captured candidate exactly. + `bash scripts/release.sh check VERSION` is an optional local diagnostic, + never a required pre-publication step. Document preparation with + `GOWORK=off GOTOOLCHAIN=local go mod download`; if it changes module files, + those changes belong in the candidate before publication. +2. Describe annotated notes-derived tags, native publication statuses, and + recovery against the captured authoritative endpoint. State that the tool + retains a local tag after push failure. An exact-object recovery can confirm + success; an unreadable result remains unknown. Link to pinned upstream + recovery guidance instead of implementing or repeating its full algorithm. + Remove the old atomic-push prerequisite and procedure. +3. Describe the shared tagged-source delivery command, the existing secret + mapping, Linux artifacts, note body/footer, and separate delivery status. + Explain content-aware retries and retained-artifact recovery by linking to + upstream. Remove references to the retired builder/plugin and the assertion + that Audita has no version command. Keep the release script's bootstrap + preparation distinct from its offline candidate validation. +4. In the release policy, retain upstream wording wherever it already permits + the selected approach. Add a concise project-specific native-host check + provision under supported platforms/candidate validation: Linux delivery + targets remain required, macOS development remains best effort, and running + publication on a nonselected host requires ReleaseKit's temporary native + version check to succeed. Qualify the existing statement that macOS failures + never block release accordingly. Mac access and native tests on every target + remain unnecessary. Date the local policy update and preserve its upstream + source attribution. Avoid unrelated policy changes or additional gates. +5. Document `audita version`, its stdout/help/usage behavior, and public version + fallback in `docs/cli.md`. Add a short implementation/change-recipe note in + `docs/internal/cli-config.md` linking to that contract and the accepted ADR. + Update the ADR index to list ADR 0001; its current assertion that no ADR exists + is obsolete. Preserve the accepted ADR's content. +6. Add a House Format ReleaseKit entry with selected module v0.1.0, + `Copyright (C) 2026 Eric Rakestraw`, and `LGPL-3.0-or-later`. Link existing + `licenses/LGPL-3.0.txt` and `licenses/GPL-3.0.txt`, and the upstream COPYRIGHT + and source at commit `5e60fe3113c69f95c42fbbe32a8ca4b51f5b83c1`. Check the + selected module's notices. Keep the application grant and unchanged license + texts intact; no policy-template material is copied in this feature. +7. Repair current navigation affected by replacing this implementation plan. + Completed PromptKit/ConfigKit roadmap references that intend to identify + their former plan should link to the corresponding historical completion + records, not this ReleaseKit plan. Preserve published release notes and tags. + The next release note is deferred to release preparation. + +**Verification and completion:** Check commands against the new wrapper/CLI, +local links and anchors, pinned upstream references, source attribution, and +`git diff --check`. Use the prior successful code checks for unchanged code. +Commit the documentation unit. + +## Stage 5 — Verify Adoption and Close the Plan + +**Primary files:** This plan and the ReleaseKit feature roadmap; fix an +implementation file only if the final checks expose a real integration defect. + +1. Audit the roadmap acceptance criteria against the landed files. Confirm the + runtime uses the public version accessor, the profile selects only the two + Linux targets, pins agree, the wrapper owns no common release mechanics, and + the old builder and repeated publication tests have been retired. +2. Prepare dependencies if necessary, then run `go test ./...` and + `go build -o ./bin/audita ./cmd/audita`. Run the normal binary's `version` + command without application setup. These tests remain offline; preparation + may use the module network separately. +3. On the committed implementation, verify the real shared builder once using + temporary output outside the repository: + + ```sh + releasekit_check_dir=$(mktemp -d) + bash scripts/release.sh build --output "$releasekit_check_dir" v0.0.0 + ``` + + `v0.0.0` is solely a build-test identifier, not an Audita release selection. + `build` requires no release note or remote publication. Confirm both + `audita-v0.0.0-linux-amd64` and `audita-v0.0.0-linux-arm64` are produced; + ReleaseKit's own mandatory native smoke check must report success. It checks + `audita v0.0.0` with a newline on a host-runnable executable, building a + temporary native executable itself when needed. Do not execute a foreign + architecture binary. Remove the temporary output afterward. The CLI's private + build receipt is an upstream artifact and should not enter Git. +4. Review the dependency/attribution diff, wrapper/profile wiring evidence, + workflow syntax and pin, and current documentation. Run `git diff --check` + and confirm no generated output, credentials, or unrelated work is staged. + Fix proven defects and rerun only affected checks. No real tag publication, + hosted upload, paid inference, extra platform matrix, or CI polling is needed + to establish this implementation's completion. +5. Mark the plan and feature roadmap complete after these requirements pass. + Record the tested implementation revision and checks; distinguish a later + documentation-only closure commit. Summarize the local infrastructure removed + and any remaining deployment observations accurately. Commit the closure. + The first adopting release and live delivery remain separate authorized work. + +**End state:** Audita supplies a product profile, native version command, thin +local entry point, and shared CI invocation. ReleaseKit owns the common release +mechanics and their tests. Documentation and attribution match the integration. +No implementation-blocking open questions remain. diff --git a/docs/roadmap/releasekit.md b/docs/roadmap/releasekit.md index 70a821d..7c2b615 100644 --- a/docs/roadmap/releasekit.md +++ b/docs/roadmap/releasekit.md @@ -176,5 +176,6 @@ does not become a source-release completion gate. The accepted ADR settles the architectural choice and standard workflow trade-offs. No significant feature decisions remain open. The next Audita -version and publication timing belong to release preparation; this roadmap -does not publish a release or prescribe implementation stages. +version and publication timing belong to release preparation. The +[implementation plan](implementation.md) owns the ordered execution steps and +their verification; this roadmap owns the desired end state and adoption intent.