Finalize the ConfigKit and PromptKit implementation plan

This commit is contained in:
2026-09-24 01:23:32 +00:00
parent 116648fa78
commit 1ad2119283
5 changed files with 642 additions and 659 deletions

View File

@@ -1,306 +1,527 @@
# Implementation Plan: Testing Overlays and Migration Handoff
# Implementation Plan: Adopt ConfigKit and PromptKit
**Last updated:** 2026-09-24
**Status:** Complete (2026-09-24). All six stages below are finished. This plan implements the next
unit in the [prototype roadmap](library-boundary.md#next-unit-testing-overlays-and-production-migration-plan),
not the production ConfigKit or PromptKit migrations.
**Status:** Ready for implementation. All stages below are pending. This replaces
the completed testing-overlay prototype plan; its results remain in the
[boundary findings](library-boundary-findings.md#selected-overlay-extension-2026-09-24).
**Production handoff revision:** The completed prototype stages remain recorded
below. The current [production plan](configkit.md#ordered-production-migration-handoff)
targets both libraries in one refactor; intermediate commits need not build or run.
It supersedes the earlier interim-runtime design. No temporary adapter,
compatibility shim, or processing gate is required.
## Scope and Working Instructions
Execute Stage 1 through Stage 6 in order. Each stage is sized as a separate coding
prompt for a gpt-5.6-terra agent and ends with a reviewable result. When assigned
one stage, finish that stage and report the next stage; when assigned the entire
plan, continue through all stages. Do not restart completed work: inspect current
files, recorded results, and Git state before deciding what remains.
Implement the final configuration and execution model in the
[combined feature roadmap](library-adoption.md) and [configuration roadmap](configkit.md).
The [selected boundary](library-boundary-findings.md#configuration-and-profile-contract),
[migration inventory](library-boundary-findings.md#migration-inventory), and
[failure mapping](library-boundary-findings.md#execution-and-failure-mapping)
are the detailed behavioral inputs. Do not repeat the prototype or reopen settled
choices without a concrete contradiction in the pinned libraries.
Before each stage, follow `AGENTS.md`, [development guidance](../development.md),
and the [agent policy](../policy/agents.md). Preserve unrelated changes. Use the
knowledge graph for code discovery; examples may be excluded from its index, in
which case inspect the known prototype files directly. Follow the repository's
testing and documentation policies. Complete relevant checks and make a plain
English local commit for each coherent stage under the standing commit policy.
No push, tag, release, or upstream-library edit is included.
This plan is for a gpt-5.6-terra coding agent. Execute Stage 1 through Stage 12 in
order. Each stage is one bounded implementation prompt. When assigned the whole
plan, continue between stages without a permission round. When assigned one stage,
finish that stage's scope and report the next stage. Mark completed stages with a
short result and actual validation evidence; do not call a pending integration
check passed.
Update each stage's status line with its result and verification evidence when
finished; keep detailed design/results in their owning roadmap documents. Do not
mark a stage complete while required checks are failing. Fix in-scope failures;
record any genuine upstream gap and its effect on later stages before continuing
work that depends on it. Routine implementation choices do not need fresh approval.
Read `AGENTS.md`, [development guidance](../development.md), and all documents under
`docs/policy/`. Use graph-first code discovery. Follow the
[agent](../policy/agents.md), [architecture](../policy/architecture.md),
[testing](../policy/testing.md), [documentation](../policy/documentation.md), and
[release](../policy/release.md) policies. The intentional dependency, configuration,
and scheduler changes here supersede the corresponding old implementation choices;
update canonical descriptions as the new behavior lands.
The [ConfigKit roadmap](configkit.md#selected-overlays-for-testing) owns the overlay
contract. The [boundary findings](library-boundary-findings.md) own existing choices
and evidence. Preserve the original v0.3.1 results as historical. ConfigKit v0.4.0
renames selected configuration profiles to overlays; do not rename PromptKit's
`profiles/`, `profiles_dir`, or execution-profile fields.
The stages divide one refactor, not supported intermediate releases. Intermediate
commits may fail to build or run. Do not write temporary adapters, compatibility
shims, duplicate execution paths, stubs returning invented successes, or an interim
processing gate. Remove superseded code when replacing it. Run focused checks
where the affected packages are testable; record checks deferred because later
stages must reconnect callers. Such a completed stage is still work in progress
on the overall refactor. Commit coherent stages with plain-English messages under
the standing policy. Do not spend a stage making an intermediate application work.
All implementation in this plan stays under `examples/library-adoption/`, plus
relevant roadmap/README updates. Keep the root Go module, production CLI/runtime,
correction algorithms, and upstream libraries unchanged. Use the existing built-in
PromptKit HTTP path with a controlled transport, synthetic credentials, and no live
provider calls. Keep imports and secret-directory bootstrap disabled. This work
does not introduce general environment overlays or backwards compatibility.
Keep tests deterministic, offline, and credential-independent. Reuse prototype
scenarios at their production boundary rather than copy the nested application or
retest all library internals. Preserve domain tests unless the selected contract
actually changes. Update each affected canonical reference alongside its owning
stage; Stage 11 finishes the cross-document migration guide and examples.
Unless explicitly stated otherwise, shell commands below run from
`examples/library-adoption/`. Use an installed Go 1.25.5 or newer. Acquire dependencies
with `GOWORK=off go mod download all` when needed; then use the offline command
prefix below. Root `go test ./...` does not cover this nested module.
No upstream edits, paid calls, push, tag, publication, retention-policy change,
timestamp fix, or unrelated pipeline redesign is included. Release compliance
and publication remain a later release unit. Completion here means both libraries
are adopted, obsolete machinery is removed, and the final application is verified.
## Stage 1: Upgrade the Prototype Dependency
## Implementation Decisions
**Status:** Complete (2026-09-24). **Depends on:** nothing. ConfigKit v0.4.0 pinned;
the nested offline tests and demonstration passed with the expected 1/4/0/2 result.
These decisions close the remaining application-design details; background and
user-facing policy belong to the feature roadmaps.
Read the prototype README, `go.mod`, `go.sum`, and the current ConfigKit roadmap.
Confirm the working tree and run the existing nested-module tests once as a
baseline. Upgrade ConfigKit to the published v0.4.0 release using module tooling;
leave PromptKit and Audita dependency versions unchanged. Review any indirect
module changes and retain only changes needed by this upgrade. Do not add local
replacements or an active Go workspace.
- Pin the published modules used by the verified prototype: ConfigKit v0.4.0 and
PromptKit v0.11.0. Set the root minimum to Go 1.25.5. Keep yaml.v3 while glossary
parsing uses it. No sibling replacements or dependency on Audita's own old release.
- Keep application loading in `internal/core/config`, embedded prompt definitions
in `internal/prompts`, schemas in `internal/framework/responseschema`, and the
PromptKit integration in `internal/framework/llm`. Use one engine per process
invocation, shared by both role-bound clients; neither modules nor validators
construct engines. The CLI composes these pieces. Avoid a generic service layer.
- Retain the `CompleteStructured(ctx, request, out)` boundary, using Audita-owned
prompt ID/version, string variables, schema identity, and diagnostic context.
Replace the old rendered-message/model request fields. Model/profile/credential
selection belongs to the role-bound adapter, not individual callers. Consolidate
the equivalent validator types onto the framework contract where needed, without
an import cycle. No PromptKit types in correction algorithms or ledger records.
- Store PromptKit definitions for all nine existing prompt IDs with their existing
`v1` selection. Replace the custom `hardening` template function with an
application-supplied `HardeningPolicy` string variable sourced from the one
embedded hardening fragment. The adapter supplies that reserved variable after
caller variables. PromptKit renders all messages; do not retain an Audita template
engine or introduce generated prompt files requiring a second build step.
- Use one shared configuration-input parser for `process`, `config validate`, and
`config print-effective`. All three accept `--config`, `--overlay`, and the
retained setting overrides in the inventory, including the two profile flags.
Only `process` accepts transcript/glossary/output/report paths. Only explicitly
visited setting flags become ConfigKit overrides. Do not add retry/capacity/key
flags beyond the agreed inventory.
- `config validate` requires an explicit nonempty config path. The other two
commands use the selected discovery order. All validate the resolved settings
and both selected profiles without provider calls, including an empty module
pipeline. Help succeeds before file discovery or secret/profile loading.
- `config print-effective` adds `--view settings|profiles|explain`, defaulting to
`settings`. Settings uses ConfigKit `WriteEffective` YAML. Profiles emits a safe
Audita-owned YAML summary for the proposal and validation roles. Explain emits
a YAML sequence of field path, source, and derivation records from ConfigKit's
recorded resolution, with no resolved secret values. Unknown views are usage
errors. This avoids mixing multiple formats into the default output or adding
another command tree. Profiles includes selected ID, backend, model, temperature,
max tokens, top-p, per-attempt timeout, service tier, and reasoning effort when
present; omit arbitrary extra provider parameters and credentials. It is a
selected-controls summary, not a dump of every profile input.
- Keep CLI exit classes 0/1/2 and transcript/report stream behavior. Invalid user
settings/profiles are configuration errors (2); broken embedded assets and
runtime/provider failures are runtime errors (1). Serialization/write failures
remain runtime errors. Do not classify malformed HTTP envelopes as repairable
model output.
- Publish process reports as `audita-process-report` schema `v2`. Preserve existing
domain fields and ledger ordering, add a top-level `llm_summary`, and replace
obsolete scheduler utilization fields as specified in Stage 10. Transcript
encoder versions stay unchanged. No legacy report mode is needed.
No source changes were needed in the earlier isolated review. If a change is now
necessary, investigate and record the concrete reason instead of assuming that
ConfigKit execution overlays and PromptKit profiles share an API.
## Stage 1: Replace the Configuration Model and Loader
Verification:
**Status:** Pending. **Depends on:** the completed prototype only.
**Owns:** root `go.mod`/`go.sum`, `internal/core/config`, and config tests.
```sh
GOTOOLCHAIN=local GOWORK=off GOPROXY=off GOSUMDB=off go test ./...
GOTOOLCHAIN=local GOWORK=off GOPROXY=off GOSUMDB=off go run .
```
1. Pin both modules and the Go minimum above. Align build/CI toolchain declarations
with that minimum; preserve the existing platform set and release gates.
2. Replace version-1 YAML/env merge and duration coercion with one ConfigKit
definition covering every retained field in the migration inventory. Use the
prototype's types/lifecycle as evidence, then add the full domain configuration.
Remove legacy environment loaders and alias resolution; do not keep two loaders.
3. Implement defaults, presence-aware backend defaults, final validation-profile
inheritance, and recorded derivations. Keep `chunking.target_sections` optional,
explicit empty module lists empty, and module order/repeats intact. Validate
domain constraints after overlay and explicit override resolution. Preserve
numeric normalization seconds; operation timeout is a duration string.
4. Use typed optional secret references. Resolve every surviving reference, including
unselected backends; missing/empty references fail, replacement resolves only the
replacement, and null permits unauthenticated use. Enable selected overlays;
leave imports and secret-directory bootstrap disabled.
5. Expose the ConfigKit result to CLI composition for effective output and provenance;
convert retained settings into existing domain inputs without transporting the
library result through correction code. Update `docs/config.md`'s implemented
loader/schema description, clearly marking unfinished CLI integration if needed.
Acceptance: the manifest and sums pin v0.4.0, tests pass, and the demonstration
still yields one accepted correction, four attempts, zero transient retries, and
two structural repairs. Update the README/findings to distinguish the new pin from
historical v0.3.1 evidence. Do not claim overlay integration yet.
**Acceptance and validation:** focused config tests cover strict version/fields,
selected defaults, omission/null/zero, final role inheritance, empty/repeated
modules, overlay/override precedence, secret replacement/null/missing, and retained
cross-field rules. Old schema fails with migration guidance. General environment
variables have no implicit effect. Run `go test ./internal/core/config` when this
package is independently buildable; record caller compile failures for later stages.
Do not duplicate ConfigKit's exhaustive YAML/merge tests.
## Stage 2: Add Overlay Loading and Configuration Fixtures
## Stage 2: Replace CLI Configuration Selection and Overrides
**Status:** Complete (2026-09-24). **Depends on:** Stage 1. On-disk overlay and
profile fixtures, precedence, inheritance, rejection, and runtime assembly tests
pass in the nested module (`go test ./...`).
**Status:** Pending. **Depends on:** Stage 1.
**Owns:** `internal/cli/run.go`, `process_flags.go`, configuration command parsing,
and corresponding CLI/subprocess tests.
Start with `config.go`, `config_test.go`, `config.yaml`, and `profiles/`. Extend
`loadConfig` with an explicit overlay-selection argument or a small invocation
options value. Pass it to ConfigKit `Options.Overlay`; selection does not belong
in the persistent `Config` struct. Update existing callers to request no overlay
without changing their behavior. Avoid a parallel merge implementation.
1. Implement the shared configuration-input parser described above. Preserve the
existing supported positional-argument arrangement for `process`, required
glossary, output/report behavior, and root/subcommand help. Remove obsolete
LLM/model/key/timeout/retry/concurrency flags and aliases outright.
2. Select exactly one file: explicit `--config`, then
`/usr/local/etc/audita/config.yml`, then `/etc/audita/config.yml`. Missing system
candidates are skipped; selected inaccessible files and explicit empty/missing
paths fail. With no file, report a configuration error; do not select a provider.
Remove `AUDITA_CONFIG`. Test discovery using an injected path list/filesystem
seam rather than modifying the host's system configuration.
3. Pass invocation overlay selection to ConfigKit and only supplied setting flags
to its overrides. `--modules ''` must clear the pipeline; explicit numeric zero
reaches validation rather than being treated as absent. Relative profile bases
derive from the selected main file, never the overlay directory.
4. Wire the parsed result into the final process/config command entry points.
Profile-dependent command completion belongs to Stage 4; do not emulate the old
runtime to make the process command work now. Update `docs/cli.md` for the final
input contract as parsing lands.
Add these prototype fixtures:
**Acceptance and validation:** parser/loading tests prove help without usable
configuration, discovery/error cases, explicit-only overrides, retained domain
flags, removed flag rejection, and ignored legacy environment values. Table-drive
shared cases; retain representative subprocess checks rather than triplicate every
parser test across commands. Config commands reject positional arguments and
process-only flags. Defer assembled command checks until Stage 8 if imports still
prevent compilation.
- `overlays/testing.yml`, selecting `proposal-testing` and `assessment-testing`
through the existing two `llm` role fields. Do not put `version`, model settings,
or ConfigKit directives in this overlay.
- Complete PromptKit profiles under `profiles/` with those IDs and distinct
synthetic model IDs, such as `synthetic-grammar-testing` and
`synthetic-review-testing`. Both use the existing `offline` backend and keep the
current positive repair policy and finite shared capacity.
## Stage 3: Migrate Embedded Prompt Assets and Call Contracts
Preserve base `config.yaml` as the no-overlay fixture, including its explicitly
selected assessment profile. This makes the risk of accidentally leaving the
validation role on its base model observable. Profile paths remain relative to
main configuration according to the selected application contract, not relative
to the overlay file.
**Status:** Pending. **Depends on:** Stage 1; execute after Stage 2.
**Owns:** `internal/prompts`, `internal/framework/responseschema`,
`internal/framework/contracts`, validator contract aliases, and prompt tests.
Add focused configuration tests proving:
1. Convert all four module and five validator prompts listed in
[the prompt registry](../internal/prompts.md) to PromptKit definitions. Preserve
instructions, variables, glossary/description context, prompt IDs, and the two
existing JSON response schemas. Embed assets once and expose their filesystem
to the runtime. Do not copy the prototype's duplicate schema directory.
2. Keep output contracts JSON Schema based, but supply the full effective output
contract and repair count on each runtime request. Do not create separate
operator-facing repair defaults per prompt. Use the hardening variable decision
above to retain a single hardening source.
3. Change the structured-call request to prompt identity, variables, response schema
identity, and diagnostic context. Keep decoded output and typed Audita metadata
as the return boundary. Include role/module instance/section/batch/validator
context where available for attribution; do not derive identities from messages.
4. Replace the old parser/renderer and hash assumptions. Keep small metadata and
schema lookup helpers where Audita needs them. Update the prompt reference.
- Omitted selection, empty selection, and `default` select the base configuration;
`testing` selects both new profiles.
- Explicit ConfigKit overrides win over overlay values. Only supplied flags will
become overrides in Stage 3; parser defaults must not enter this layer.
- With validation selection absent from both base and overlay, validation inherits
the final proposal selection, including an explicit override. An existing
explicit base validation selection remains explicit unless replaced by overlay
or CLI. Empty/null validation values retain the established rejection behavior.
- Runtime profile assembly resolves both selected profiles to the shared backend.
**Acceptance and validation:** a table covering all nine definitions prepares
representative variable sets through PromptKit with controlled profile fixtures;
checks include hardening, section/glossary/description data, missing variables,
correct schema association, and rendered content preserving the previous task
instructions. Use reviewed expectations, not a retained legacy renderer or old
Audita module dependency. Existing schema/domain tests remain meaningful. Callers
are deliberately migrated in Stages 6–7.
Use temporary on-disk layouts for overlay tests so ConfigKit owns file discovery.
Existing byte-source tests can remain for cases that do not select an overlay;
if a byte source needs an overlay, supply ConfigKit's supported filesystem context
rather than relying on the process working directory.
## Stage 4: Assemble Profiles and Finish Offline Inspection
Acceptance: the new fixtures load and assemble correctly, the focused precedence/
inheritance tests pass, and `go test ./...` in the nested module still passes.
Do not yet claim that the testing models reached the HTTP transport.
**Status:** Pending. **Depends on:** Stages 1–3.
**Owns:** engine/profile assembly in `internal/framework/llm`, CLI config commands,
and inspection tests.
## Stage 3: Demonstrate and Verify Model Switching
1. Construct one PromptKit engine with the embedded assets, complete profile files,
and registered application backends. Reuse the prototype's supported filesystem,
backend, retry-config, and inspection APIs. Accept an HTTP client at the external
boundary for tests; production uses the library transport.
2. Resolve `profiles_dir` against the main config file. Inspect both selected roles,
require a registered backend, reject endpoint-only bypass and profile credential
lookup, and compare endpoints after trimming surrounding whitespace and trailing
slashes, as in the prototype. Do not invent profile inheritance/catalog wiring
or reject unrelated unselected profile content beyond library behavior.
3. Complete `config validate` and the three effective-output views. Settings,
profiles, and explanations share the same load/assembly path used by process.
Keep the `config is valid` success message. Redact configured secret values in
any surfaced library error; do not stringify raw configuration/profile objects.
4. Add the internal safe-view helpers later used for snapshots. Document the view
interface and its limits in `docs/cli.md` and `docs/config.md`.
**Status:** Complete (2026-09-24). **Depends on:** Stage 2. Nested tests inspect
outbound base/testing/override model IDs, including repairs; all three documented
offline demonstrations passed with one accepted correction and 4/0/2 attempts,
retries, and repairs.
**Acceptance and validation:** offline command tests prove all views and validation
agree for base/testing/explicit-profile selections; main-file-relative and absolute
profile paths work; missing profiles, backend mismatch, competing credentials,
missing surviving secrets, and invalid views fail with the selected exit class.
Use a transport that fails the test if called. Inspect outputs/errors for synthetic
secret absence and overlay/CLI provenance, including inherited validation selection.
Start with `main.go`, `offline.go`, `runtime.go`, and `workflow_test.go`. Add minimal
standard-library argument handling to the prototype executable:
## Stage 5: Implement the Final PromptKit Structured-Call Adapter
- `--overlay <name>` selects the ConfigKit overlay.
- `--proposal-profile <id>` and `--validation-profile <id>` produce ConfigKit
overrides only when explicitly supplied.
- Keep the existing fixture-based invocation from the prototype directory. There
is no need to reproduce production file discovery or its subcommand tree here.
**Status:** Pending. **Depends on:** Stages 3–4.
**Owns:** `internal/framework/llm`, the typed failure boundary in
`internal/framework/structuredoutput`, and adapter tests.
Use a small testable entry function if needed to check flag handling without
repeated subprocess builds. Preserve ordinary flag error handling. Keep execution
on the synthetic transport for every supported demonstration invocation; do not
add a live-network mode. Extend that transport to recognize the testing models and
preserve the initial-invalid-output/repair behavior for each role.
1. Implement role-bound clients over the shared engine. Start the operation context
and Audita logical-call record before preparation; inherit earlier caller deadlines.
Select the role profile and backend secret, supply reserved hardening variables,
and pass an explicit full schema/repair contract. Use `PrepareExecution`, its
`Details`, then `RunPrepared` so diagnostic messages/hashes describe the actual
execution snapshot. Defer handle discard; do not call `Prepare` and then `Run`
with an independently reloaded profile. Before dispatch, verify the prepared
target still matches the role's registered backend/endpoint and has no competing
credential lookup. A changed target fails safely rather than sending a backend
key to a different target. This is the final diagnostic/security boundary, not
an intermediate adapter.
2. Check both the returned error and `result.Validation.IsValid`: exhausted repair
can return a result with failed validation and no error. Decode only validated
JSON into the requested Audita output. Use the selected failure table:
exhausted output repair becomes the Audita malformed-output classification; provider/transport/protocol/retry/admission/deadline failures
remain runtime failures. Preserve typed causes for classification and safe
messages for users. Explicit zero retries must not become retries-exhausted.
3. Preserve prepared messages/hashes and available final content and profile/model
metadata through Audita-owned types. Provide a per-call observer hook and logical
start/finish record bound to Audita diagnostic context for Stage 9; do not
create another retry loop, scheduler, provider envelope parser, or schema engine.
4. Remove the old OpenAI-compatible client and its role config resolution. Retain
only applicable redaction and diagnostics helpers. Update the LLM integration
reference to delegate wire/retry mechanics to the pinned library.
Add a compact safe selection summary to demonstration output: requested overlay
and effective profile, backend, and model for each role, alongside the existing
domain outcome and attempt/retry/repair totals. It must reflect the assembled
configuration rather than echoing flag values. Inspection APIs and tests in the
next stage suffice; do not create production config commands in this prototype.
**Acceptance and validation:** controlled HTTP tests cover successful decode,
positive repair and exhaustion for both schema types, 429/5xx retry recovery,
explicit zero, exhausted positive budget, transport/malformed-envelope failure,
combined retry-plus-repair bounds, preparation failure without dispatch, exact
prepared request metadata, target-change rejection, and operation cancellation
during a long retry wait. Assert classifications and meaningful counts, not timing-sensitive sleeps
or complete error strings. Reuse the prototype sequences; no need to reproduce
PromptKit's entire status-code matrix.
Test through the assembled path and inspect actual outbound HTTP request bodies:
## Stage 6: Migrate All Proposal Callers
- No overlay sends the base proposal and assessment models.
- `testing` sends the testing proposal and assessment models, including repair
requests, and still produces one accepted correction with two repairs.
- An explicitly supplied role-profile flag overrides that role's testing selection;
the other role retains its overlay selection. An omitted flag preserves overlay
selection. Match reported selections to observed outbound model IDs.
**Status:** Pending. **Depends on:** Stage 5.
**Owns:** `internal/modules`, `internal/framework/proposal_generation`, and their tests.
Use distinct models per role for these demonstration cases. Do not expand the fake
provider into a general simulation framework. Reuse existing prompt/schema/domain
helpers and existing capacity/observation coverage.
1. Switch glossary, homophones, spoken_word, and grammar proposal construction to
prompt IDs and variables. Preserve section/glossary encoding, context trimming,
replacement policy, confidence filtering, and applicability checks.
2. Feed repaired structured output into the existing domain path. Exhausted
structural repair produces the existing section warning and no proposals;
runtime failures propagate. Schema-valid but inapplicable proposals do not
trigger semantic retries or additional repairs.
3. Update fake clients and module prompt tests to the final request contract.
Delete duplicate message rendering and obsolete transport/schema checks; retain
domain protection and prompt variable coverage. Update module internals docs.
Acceptance: nested-module tests pass and these invocations visibly show the expected
selections and successful domain result:
**Acceptance and validation:** all four modules have an exercised variable/schema
mapping; existing domain suites retain their assertions. Representative controlled
adapter coverage proves repaired proposals reach domain checks and that a low-
confidence/inapplicable proposal remains rejected. Preserve section/proposal
ordering. Run the module and proposal-generation suites as imports become buildable.
```sh
GOTOOLCHAIN=local GOWORK=off GOPROXY=off GOSUMDB=off go run .
GOTOOLCHAIN=local GOWORK=off GOPROXY=off GOSUMDB=off go run . --overlay testing
GOTOOLCHAIN=local GOWORK=off GOPROXY=off GOSUMDB=off go run . --overlay testing --proposal-profile proposal
```
## Stage 7: Migrate LLM Validators Without Changing Domain Decisions
Update the prototype README with these implemented commands and fixture layout.
State that synthetic testing IDs demonstrate operator-selectable routing, not
measured price, speed, or model quality.
**Status:** Pending. **Depends on:** Stage 6.
**Owns:** `internal/framework/validators`, validation prompt builders/batching,
and validator tests.
## Stage 4: Verify Failure, Credential, and Inspection Boundaries
1. Migrate spoken_form_plausibility, meaning_reversal_review, editorial_review,
grammar_review, and spoken_word_review to prompt IDs/variables and the common
structured boundary. Keep deterministic validators independent of PromptKit.
2. Preserve batching by `validation.max_prompt_tokens`, proposal preview, stable
proposal indexes, exact decision cardinality, and unknown/duplicate index checks.
Keep the current domain token-estimation method; do not add a second template
renderer or treat this budget as a provider output-token limit.
3. Apply the failure mapping: exhausted repairs reject/warn the batch; schema-valid
bad cardinality or negative assessments reject without semantic retry. Provider,
malformed HTTP, deadline, and admission failures propagate as runtime errors.
Update any old tests treating malformed provider envelopes as warning-only.
4. Remove redundant validator client/model configuration types and keep execution
class distinctions. Update validator reference/internal documentation.
**Status:** Complete (2026-09-24). **Depends on:** Stage 3. Focused offline tests
cover ConfigKit overlay errors, backend validation, credential replacement and
null handling, provenance, inspection, and redaction. Nested `go test -race ./...`
and `go vet ./...` passed on linux/amd64 with Go 1.26.8.
**Acceptance and validation:** preserve existing batching no-drop/no-duplicate,
domain reason, glossary protection, and cardinality tests. Cover all five prompt
mappings, positive repair before domain validation, exhausted repair, and runtime
failure propagation through a representative validator. Run validator tests;
full runner behavior is Stage 8.
Extend focused tests in the prototype; keep them offline and independent of host
configuration and credentials. Exercise the consumer's assembled loader/runtime
rather than duplicating ConfigKit's exhaustive parser or merge tests.
## Stage 8: Connect the Runner and Remove the Old Scheduling Hierarchy
Required evidence:
**Status:** Pending. **Depends on:** Stages 2 and 4–7.
**Owns:** CLI process assembly, `internal/framework/runner`, old scheduler contracts,
and runner/CLI integration tests.
- Missing and invalid overlay selections fail with ConfigKit classifications.
Representative attempts to replace the schema version or introduce ConfigKit
directives fail. Do not create application fallbacks for those failures.
- An overlay can change an ordinary non-profile setting, such as a backend limit,
and the effective setting still undergoes application validation. This proves
overlays have not been accidentally restricted to profile selection.
- A replaced credential reference resolves only its surviving replacement; an
unresolved displaced reference does not make the load fail. A surviving missing
or empty secret reference still fails. Explicit null retains unauthenticated
backend semantics. Use synthetic environment names and values under test control.
- Switching role profiles alone does not remove other credential references still
present in configuration. Document this distinction and test the relevant case;
do not bypass ConfigKit validation for unselected backends as an incidental fix.
- `WriteEffective` and relevant explanation/metadata APIs identify overlay origin;
a CLI replacement identifies CLI origin. Inspect selected PromptKit profiles from
that same loaded result and verify model/backend agreement with runtime selection.
- Synthetic credential values do not appear in effective configuration, explanations,
profile inspection, observations, or surfaced errors exercised by these scenarios.
Confirm the controlled transport receives the effective synthetic credential.
1. Pass the shared engine's two role clients into the runner. Remove global and
role schedulers, scheduler interfaces/fields, legacy concurrency configuration,
and measured scheduler wrappers. PromptKit backend admission is the only LLM
service-capacity mechanism. Do not remove unrelated deterministic work or alter
module sequencing merely because the scheduler disappears.
2. Preserve concurrent section work, deterministic collection/indexing, ordered
module application, validator execution classes, and cancellation of remaining
work on runtime failure. Capacity rejection fails the run as selected; do not
silently retry or add another queue to conceal it.
3. Wire final loaded domain settings, role clients, and diagnostics context into
normal processing. No old-runtime branch or interim gate remains. Keep existing
transcript encoding, output channels, partial domain results, and artifact
retention behavior. Ensure terminal failures cannot emit a purportedly complete
corrected transcript.
4. Update architecture policy for shared library dependencies and engine-local
backend admission; preserve the existing ownership, determinism, and redaction
invariants. Update pipeline/runtime internal guidance.
Maintain the existing retry/repair/capacity tests. Add only the overlay-specific
integration coverage needed to protect this boundary; do not repeat the complete
scheduler matrix for each fixture.
**Acceptance and validation:** controlled concurrent requests from both roles to
one backend never exceed its configured cap, including retries and repairs;
separate backend identities have independent capacity. Queued cancellation,
deadline and zero-wait-capacity rejection do not leak capacity; later work can
succeed. Existing deterministic runner/domain tests pass after deleting scheduler-
implementation assertions where the affected packages compile. Exercise a real
CLI-to-local-HTTP workflow with both roles when reporting dependencies permit;
otherwise record that check for Stage 12. Do not restore old utilization fields
or add placeholders merely to make this intermediate commit build.
Verification:
## Stage 9: Collect Execution Observations Safely
```sh
GOTOOLCHAIN=local GOWORK=off GOPROXY=off GOSUMDB=off go test -race ./...
GOTOOLCHAIN=local GOWORK=off GOPROXY=off GOSUMDB=off go vet ./...
```
**Status:** Pending. **Depends on:** Stage 8.
**Owns:** Audita-owned execution record types and collector in the LLM boundary,
runner attribution, and concurrency/observation tests.
Acceptance: all cases above have passing behavioral evidence, the existing suite
remains green, and concurrent observation collection remains race-free. Record
actual gaps instead of silently relaxing tests or claiming complete integration.
1. Translate PromptKit events into small Audita-owned records at the observer
boundary. Use the prototype's short mutex-protected collection pattern; callbacks
do no filesystem I/O, provider calls, or waiting on their own run. Freeze/copy
snapshots after active work has joined.
2. Bind observations to logical call, role (`proposal` or `validation`), module
instance, section, validator and batch where applicable, then retain library
run/backend/profile and attempt/generation identity. Keep provider attempts distinct from logical calls.
3. Record dispatch, queue/generation/retry/wall durations, outcome/failure category,
HTTP status, retry exhaustion, attempts/retries/repairs, and usage value/known/
complete per field. Use terminal events once for provider totals; never add
attempt usage on top. `PrepareExecution` emits no events and `RunPrepared` timing
excludes preparation. Audita's surrounding call record therefore owns the logical
count and wall time, including preparation failures; do not invent library events.
A failure before dispatch has zero attempts and known-zero complete usage.
Preserve completed observations on nil-result failures and mark usage incomplete
when dispatched attempts lack measurements. Across calls, sum known values,
set known if any contributing dispatched usage is known, and set complete only
when all contributing dispatched usage is complete, independently per field.
An aggregate with no dispatched attempts is known-zero and complete.
4. Keep non-LLM runner wall/validator timing. Remove instrumentation that counts
scheduler permits as calls. Do not infer queue peaks, exact active concurrency,
billing totals, or timing fields the released event API does not provide.
## Stage 5: Record Overlay Findings and Executable Instructions
**Acceptance and validation:** adapter/collector tests prove known zero differs
from unknown, partial usage survives failed repairs, undispatched admissions are
not HTTP attempts, terminal totals are not doubled, and parallel callbacks retain
attribution safely. Run targeted race tests for the affected LLM/runner packages.
No raw provider messages, URLs, keys, prompts, or payloads enter observation records.
**Status:** Complete (2026-09-24). **Depends on:** Stage 4. Dated v0.4.0 evidence,
test coverage, commands, limitations, README guidance, and roadmap links updated;
affected links and `git diff --check` verified.
## Stage 10: Update Reports and Diagnostic Artifacts
This stage changes documentation, not production code. Read the new tests/results,
then update the existing owners rather than creating another parallel design:
**Status:** Pending. **Depends on:** Stage 9.
**Owns:** `internal/core/reporting`, `internal/core/diagnostics`,
`internal/framework/processreport`, runtime diagnostic writers, and CLI artifact wiring.
- Append a dated v0.4.0/overlay result section to `library-boundary-findings.md`.
Record commands, toolchain/platform, outcomes, test-to-requirement coverage,
limitations, and any unresolved gaps. Keep original v0.3.1 evidence identifiable.
- Update the prototype README to match the actual executable and fixtures; check
every documented command. Explain the separate ConfigKit overlay and PromptKit
profile directories and the credential behavior proved in Stage 4.
- Record the overlay implementation as verified in `library-boundary.md` and link
the new evidence from `library-adoption.md`. The next unit still has its Stage 6
planning deliverable outstanding; keep production migration pending.
1. Bump the process report version to `v2`; keep the existing transcript/ledger
structures. Add `llm_summary` with `logical_calls`, `provider_attempts`,
`transient_retries`, `structural_repairs`, and `usage`. A logical call counts
once even when it fails before dispatch. Usage has `prompt`, `completion`,
`total`, `cached`, and `cache_write`, each `{value, known, complete}`.
Omit the whole summary only when execution observations are unavailable; a
successfully initialized run with no LLM calls has known-zero complete totals.
2. Replace obsolete utilization concurrency/pool fields with `backends`, keyed by
backend ID, containing configured `concurrency`/`queue_capacity` and the same
execution summary plus `capacity_wait_ms`, `generation_ms`, `retry_delay_ms`,
and `logical_wall_ms`. Sum library terminal timings once per call for capacity,
generation, and retry time; use Audita's whole-call elapsed time for logical wall
time. Attribute pre-dispatch failures to the already selected role backend.
Durations can overlap and must not be presented as a decomposition of elapsed
process time. Preserve domain module/validator timing and run wall time.
Existing role/module call counts now count logical calls; remove their obsolete
scheduler-wait and transport-execution fields rather than assign misleading new
meanings. Remove estimated active-concurrency fields throughout utilization.
3. Write `llm-execution.json` as `{calls: [...], events: [...]}` in the run directory.
Calls contain Audita logical identity, attribution, elapsed milliseconds, final
classification, summary, and available prompt/profile/model metadata. Events
contain the safe Stage 9 records, including attempt and terminal records, joined
by call ID. A preparation failure has a call record and no fabricated events.
Use millisecond integer durations in serialized records; absent attempt/section/
batch identity is omitted, not encoded as a misleading zero. Add optional
`llm_execution_path` and `selected_profiles_path` to diagnostic path metadata.
Write `selected-profiles.yaml` from the safe view and use ConfigKit YAML for
the effective snapshot (`effective-config.redacted.yaml`). Keep invocation
overlay selection and recorded origins in safe invocation/config diagnostics.
Adjust centralized filename constants and readers together; do not emit old and
new snapshots in parallel.
4. Preserve redacted request/response/error diagnostic content from prepared
details and available final results, including prompt definition/rendered hashes
and selected profile/model. Do not promise legacy hash equality or complete
provider payloads for every retry. Use the separate observation artifact for retry/repair
attempts. Redact all resolved backend secrets, including unselected ones, at
every serialization/error boundary; observation records remain payload-free.
5. Update output-file, operations, and diagnostics/reporting contracts. Preserve
failure report/ledger behavior and the distinction between primary execution
failures and secondary diagnostic write errors. Do not change retention policy.
Acceptance: the README commands are reproducible, the new overlay evidence is
clearly separated from historical results, and each Stage 2–4 requirement maps
to a passing test or observed demonstration result. Verify affected links and
`git diff --check`. Do not repeat unchanged code checks solely for this commit.
**Acceptance and validation:** report/diagnostic tests check v2 mapping, summary
semantics, per-backend grouping, safe serialization, nil-result partial failures,
and existing deterministic ledger order. A CLI failure fixture echoes a synthetic
secret in a provider error; stdout/stderr/report and retained artifacts must not
leak it. Inspect known-zero and unavailable summaries structurally, not by complete
JSON golden dumps. Reuse Stage 9 evidence rather than retest every event sequence.
## Stage 6: Prepare the Production Migration Plan and Close the Unit
## Stage 11: Finish Examples, Migration Guidance, and Removal
**Status:** Complete (2026-09-24). **Depends on:** Stage 5. The ordered ConfigKit
production handoff records bounded packages, runtime integration, tests,
dependencies, and acceptance criteria. Prototype evidence and scope audit passed;
links and `git diff --check` verified.
**Status:** Pending. **Depends on:** Stages 1–10.
**Owns:** maintained examples, affected canonical documentation, obsolete code/tests,
prototype removal, and final dependency cleanup.
Expand `configkit.md` into a concrete, ordered production migration plan using
the existing inventory and verified overlay evidence. Follow the development
reading guide for configuration/CLI and LLM runtime work; use graph-first discovery
to verify affected production components and their tests. This is a planning stage:
do not implement the production migration or overwrite this execution plan with
new production stages. Keep future work packages explicitly pending.
1. Replace maintained config examples with schema 2, complete PromptKit profile
files, and `overlays/testing.yml` selecting both roles. Use one shared backend
where roles share a service; provide secret-reference and unauthenticated local
examples without real secrets. Explain that operators choose real models and
testing cost/quality is not guaranteed. Validate examples offline with controlled
synthetic environment values; no service is required for profile inspection.
2. Write `docs/migrations/v2.md` as the one migration guide. Cover every old file/
flag/environment item in the inventory, durations, explicit empties/null,
credentials, profiles/overlays, inspection views, finite capacity, retry/repair/
deadline semantics, and changed report/diagnostic shapes. Do not add conversion
tooling or compatibility aliases. Link current contracts for complete references.
3. Finish README prerequisites/examples and canonical CLI/config, integration,
internal component, and architecture references. Audit build/CI toolchain images
for Go 1.25.5 or newer; keep only required Linux amd64/arm64 targets and best-effort
macOS arm64. Do not rewrite immutable historical release notes.
4. Remove `examples/library-adoption` once its unique useful scenarios live in
production tests. Remove the nested dependency on old Audita and duplicate
assets/fixtures. Update historical roadmap links to recorded evidence or Git
history rather than leaving broken links to deleted files.
5. Remove superseded loaders, client, renderers, schedulers, aliases, and tests
asserting retired behavior. Tidy/verify the root dependency graph and confirm
no local replacements. Keep yaml.v3 if glossary parsing still uses it. Mark the
retry-count follow-up in `runtime-behavior.md` resolved without including its
unrelated retention/timestamp proposals.
The production handoff must specify bounded work packages, dependencies, affected
components, tests, and acceptance criteria for:
**Acceptance and validation:** maintained examples validate and all guide links
resolve. Search for old CLI/env inputs, loader/client/scheduler names and prototype
references; remaining mentions must be intentional migration/history material.
Review deleted tests for lost domain/concurrency/redaction protection. Run affected
example/config/subprocess checks and `git diff --check`; final full-suite execution
belongs to Stage 12.
- The full version-2 configuration definition: existing domain fields, defaults,
presence/null/zero behavior, role inheritance, overlays, secrets, and validation.
- File discovery and invocation parsing; `--overlay` behavior shared by process,
config validation, and effective inspection; explicit-setting override mapping;
removal of legacy environment overlays, aliases, and direct-key flags.
- Profile loading/inspection and configuration snapshots, including relative-path
bases, secret redaction, provenance, and clear separation of ConfigKit settings
from PromptKit execution controls.
- Direct integration of the final configuration with PromptKit execution. Specify
the final behavior and tests for each setting; do not preserve the old runtime
through temporary adapters or add interim processing gates.
- Removal of superseded configuration machinery, retained domain checks, maintained
examples, canonical documentation updates, and the combined migration guide.
- Removal of superseded LLM machinery and release follow-up. Preserve
the agreed ordering and defer release compliance/publication to the final unit.
## Stage 12: Verify the Combined Application and Close the Refactor
Resolve final integration decisions against the evidence. Record genuine open
questions without creating scaffolding to support intermediate commits.
**Status:** Pending. **Depends on:** Stages 1–11.
**Owns:** final integration tests, final defect fixes within this scope, and status/evidence.
Final audit: map every acceptance criterion in the prototype extension to actual
files and command results. Verify new relative links/anchors, run `git diff --check`,
and review that no root runtime/dependency or upstream files changed. Reuse passing
checks for unchanged code; rerun the affected tests if this stage changes code or
fixtures to correct a finding. A root build/test run is not a substitute for the
nested-module checks, and this documentation stage adds no release gate.
1. Complete representative production subprocess workflows against controlled HTTP:
base selection, testing overlay, explicit profile override, and a retained
domain override. Observe actual outbound models for both roles, an accepted
correction after repair, a warning-only domain/repair rejection, and a runtime
failure with safe partial diagnostics. Cover an empty module pipeline and a
repeated-module sequence without duplicating all adapter scenarios.
2. Run root `go test ./...`, `go build -o ./bin/audita ./cmd/audita`, and focused race
checks for the final concurrent adapter/runner/collector changes. Verify both
Linux targets compile using `bash scripts/build-release.sh v2.0.0 <temp-dir>`;
this names local build outputs and creates no tag or publication. No native Mac, paid-provider, or CI-completion gate.
If the supported minimum toolchain was not exercised earlier, verify the root
suite with installed Go 1.25.5; do not silently claim this from a newer compiler.
3. Fix actual failures and rerun affected checks; repeat the full suite when those
fixes materially change assembled behavior. Do not rerun unchanged tests solely
to mark multiple planning steps complete. Verify maintained documentation links,
examples, and whitespace once for the final content.
4. Record concise final evidence and known limits here, mark the production feature
roadmaps implemented, and commit the completed refactor. Both libraries must
own their selected responsibilities, processing must work, and no temporary
or legacy compatibility machinery may remain.
5. Hand off release preparation separately: proposed Audita v2.0.0, one migration
guide, actual pinned production dependency/license inventory, and the remaining
LGPL notice/source/rebuild-distribution review. Do not claim license compliance
from prototype tests or publish a release. The later release unit uses the
existing minimal automated procedure and ends on a successful source/tag push,
without waiting for CI.
Mark this prototype-extension/planning unit complete in `library-boundary.md` only
after the audit passes, and link the production handoff from `library-adoption.md`.
Production implementation remains pending.
**Acceptance:** the final production application and required Linux builds pass;
configuration selection, both LLM roles, domain outcomes, cancellation/capacity,
secret handling, reports and retained artifacts match the selected contract.
Recorded checks describe what actually ran. The workspace is committed and clean.
Release-specific compliance and publication are explicitly still pending.
Acceptance: a reviewer can reproduce base/testing/override selection offline,
trace each new claim to evidence, and hand the production ConfigKit work to a coding
agent in bounded units. Commit the completed documentation, report remaining
limitations and working-tree state, and stop at the end of this plan.
## Open Questions
None block this implementation plan. Configuration, inspection, runtime boundaries,
report representation, and stage ownership are selected above. Release distribution
compliance remains outside this implementation sprint and must be resolved against
the final production dependency graph before publishing binaries; it is not a
reason to build compatibility scaffolding or delay the refactor.