Remove completed roadmaps and implementation plans

This commit is contained in:
2026-11-10 20:52:52 +00:00
parent 791deca3cd
commit 8946a82407
8 changed files with 0 additions and 3486 deletions

View File

@@ -1,389 +0,0 @@
# CommandKit Adoption Outline
**Updated:** 2026-11-10
**Status:** Adoption target and design decisions resolved; the upstream release
gate is satisfied and implementation is complete. The
[master roadmap](library-adoption.md) owns shared direction and exact dependency
revisions; the [implementation plan](implementation.md) owns sequencing. See the
[ConfigKit](configkit.md) and [PromptKit](promptkit.md) outlines for their contracts.
## Baseline and Target
Before this work, Audita used application-owned CLI parsing, inspection commands, and
reporting, described in the [CLI contract](../cli.md). Adopt CommandKit core v0.6.0
with ckconfig and ckprompt v0.7.0 as the standard operator interface. Use supported
command declarations, typed inputs, supplied-value tracking, help/version,
reporting, and formatting. Audita handlers retain transcript processing and
artifact responsibilities.
The upstream [core release](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/1613ff95cab60581de5d86f6e9e2a3cc091a44a0/docs/releases/v0.6.0.md),
[ckconfig release](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/64f6453b8453f914f272d427bb4ae6f59deacd2b/integrations/ckconfig/docs/releases/v0.7.0.md),
[ckprompt release](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/f369d6a78253b6e6fcb1e023fb2e9c3af1d20ff0/integrations/ckprompt/docs/releases/v0.7.0.md),
and [consumer guide](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/f369d6a78253b6e6fcb1e023fb2e9c3af1d20ff0/docs/consumers/guide.md)
define the selected set. Core uses Cobra/pflag and declares Go 1.26.0; the matched
integrations require Go 1.27. They select ConfigKit v1.2.0 and PromptKit v0.21.0.
The integration updates preserve their public adapters; wire processing and all
inspection commands to the shared loaders and recorded application context
described in the ConfigKit and PromptKit outlines.
## Adoption Gate: Released Debug Binding and Reporting Mode Access
**Satisfied by core v0.6.0 and the selected v0.7.0 integrations.**
Upstream publication, public APIs,
released integration dependencies, and the required behavior were verified in the
[review below](#upstream-review-shared-debug-input-and-reporting-mode).
Both required capabilities are available:
- A `BoolFlag` named `debug` attaches to the shared reporting option and supplies
its parsed boolean independently of the reporting mode for artifact capture.
- `Invocation.ReportingMode()` exposes the resolved reporting mode for quiet
transcript-destination validation.
The [master dependency selection](library-adoption.md#baseline-and-selected-dependency-set)
records exact published versions and source revisions. No unreleased dependency,
local replacement, private-state inspection, or duplicate argument parsing is
needed. Audita integration and its acceptance tests remain implementation work;
the released capabilities remove the upstream availability blocker.
## Agreed Operator Experience
- Install the full ckprompt inspection surface: prompt/profile/backend views,
resource and namespace/collection inventories, contextual requirement
inspection, and captured engine configuration through its config scope.
Native reports and namespace selection must remain available; a curated Audita
subset is not a substitute.
- Apply the [resolved profile-summary decision](promptkit.md#profile-inspection-and-summary--resolved):
retire the curated profiles view, use standard configuration/resource inspection
and request preview, and add no replacement custom role summary at this stage.
- Adopt standard ckconfig viewing, validation, sources, path discovery,
explanation, and comparison. Use native evidence and common text/YAML/JSON
rendering. Do not recreate removed provider-specific explanation writers.
- Use standard command names and reporting flags. CommandKit owns `--debug`;
its parsed boolean also enables Audita artifact capture for processing runs,
independently of the resolved reporting mode, as resolved below.
- Keep domain transcript serialization and ordinary report files under Audita's
output contracts. Generic report formatting need not transform transcript JSON.
Preserve meaningful partial success: a work-unit model error is not automatically
a failed CLI invocation or a reporter warning.
- Preserve safe library redaction without restricting standard inspection to
today's curated fields. Loading for help/version must not trigger credentials,
provider calls, or domain processing.
## Debug Reporting and Artifact Capture — Resolved
Use one `--debug` flag for detailed diagnostics: standard CommandKit debug
reporting plus retained Audita diagnostic artifacts during processing. Do not
introduce `--debug-artifacts`, duplicate the reserved flag, or add a second parser.
Artifact capture follows the parsed `--debug` boolean independently of the
resolved reporting mode. In particular, `--debug --quiet` suppresses ordinary CLI
output while retaining diagnostic artifacts; `--debug --verbose` also retains
them. CommandKit continues to own CLI visibility and mode ordering.
Use the native boolean semantics: omission disables capture, `--debug` enables
it, `--debug=false` disables it, and the last debug occurrence wins. Quiet and
verbose flags do not rewrite this value. Aliases refer to the same input; tokens
consumed as other flag values or following `--` do not count as debug flags.
Inspection commands keep standard debug reporting without creating processing
artifacts. Help and migration guidance must explain that supplying `--debug` for
processing also writes diagnostic files, including when quiet suppresses output.
Report artifact locations through CommandKit's normal visibility rules; artifact
creation does not require an always-visible message in quiet mode. Retain Audita's
artifact redaction and lifecycle responsibilities. There is no separate capture
switch in this design.
Use CommandKit's released optional `BoolFlag` binding named `debug`, with a false
default, to initialize capture from its typed boolean value. The
resolved-mode accessor serves destination validation and reporting decisions;
capture follows the bound value independently. The upstream review below records
the matching released contract.
## Quiet Mode and the Completion Summary — Resolved
Adopt CommandKit's standard visibility rules. Emit the completion summary and
created report/debug locations as informational diagnostics through the shared
reporter, using deferred information when final ordering requires it. Show them
in verbose and debug modes; suppress them in ordinary and quiet modes. Keep
diagnostics separate from transcript stdout and announce completion only after
processing and enabled required outputs have succeeded.
| Output | Ordinary | Verbose/debug | Quiet |
| --- | --- | --- | --- |
| Transcript on stdout, when selected | Shown | Shown | Rejected before processing |
| Completion summary and created artifact locations | Hidden | Shown | Hidden |
| Requested transcript and ordinary report files | Written | Written | Written |
| Fatal error explanation | Shown | Shown | Shown |
Debug capture follows the independent boolean decision above in every reporting
mode. Quiet does not cancel processing or suppress file writes. Recoverable
model-operation failures retain their domain meaning and ordinary report records;
do not promote them to fatal errors or warnings merely to make them visible.
This deliberately retires the always-visible completion summary. Help and
hard-cutover guidance must explain that operators wanting immediate counts and
locations should select verbose/debug reporting. If ordinary reports are disabled,
those modes are needed to see the completion counts. Operators wanting a transcript
while quiet is effective must select an explicit destination, as resolved below.
## Quiet Processing Requires a Transcript Destination — Resolved
Reject a processing invocation when its resolved reporting mode is quiet and its
selected transcript destination is stdout. Require an explicit non-stdout output
destination, such as `--output corrected.json`. Deliberate disposal remains
available through `--output /dev/null`; do not introduce a `--force` bypass.
An empty output value that selects stdout does not satisfy the requirement.
Audita's primary product is the corrected transcript. Reports and debug evidence
do not substitute for delivering it, so their enablement does not exempt a run
from this check. The domain-specific restriction prevents incurring processing
costs while accidentally discarding that product. It leaves CommandKit's standard
quiet semantics intact and does not apply to inspection commands.
Use CommandKit's public resolved-mode accessor and Audita's selected destination.
Return a usage failure with a visible explanation before creating output or debug
artifacts or starting model calls. For example: "Quiet processing requires an
output destination; use --output FILE, or --output /dev/null to discard the
transcript deliberately." Do not scan arguments or infer mode from output.
Shell redirection does not satisfy the requirement because CommandKit still
suppresses stdout transcript delivery.
Check effective mode after native ordering, boolean values, and aliases:
`--quiet --verbose` permits stdout, whereas `--verbose --quiet` requires an
explicit destination. `--debug --quiet` also requires one; debug capture remains
independent once the invocation passes this check.
## Output-Failure Behavior — Resolved
Require successful delivery of the transcript and enabled ordinary reports.
Debug artifacts remain optional even when capture was explicitly requested.
Adopt CommandKit's native handling of CLI output and diagnostic write failures.
| Output | Failure behavior |
| --- | --- |
| Transcript file or stdout | Fail the invocation. |
| Enabled ordinary reports | Fail the invocation if any required report cannot be written. |
| Debug directory or individual debug artifacts | Continue processing and submit a redacted warning through CommandKit. |
| CommandKit output and diagnostic streams | Preserve the native outcome and delivery-error behavior. |
Ordinary reports describe incomplete work, recoverable model failures, and
repairs. When enabled, delivering that account is part of completing the run.
Debug artifacts provide supplemental investigative detail; their loss alone does
not invalidate a delivered transcript and reports. Do not add a debug strictness
option.
Detect required-destination problems before model work wherever practical through
the [output preparation below](#output-resource-preparation-during-preflight--resolved).
If a required output fails later, retain successfully written files, fail the
invocation, and attempt to finalize the remaining reports with the failure
recorded. A report failure after transcript publication must not erase that
transcript or repeat model calls. Preserve the original processing failure when
secondary reporting or cleanup also fails. Emit the completion summary only
after processing and all enabled required outputs have succeeded, including
required final writes, closes, and file replacements.
Use the existing redaction and resolved visibility rules for debug warnings.
In particular, `--debug --quiet` still attempts capture but suppresses warnings
about missing optional artifacts; required-output failures retain the normal
fatal-error explanation. A separate failure while writing a warning can still
make the invocation fail under CommandKit's native
[output-failure contract](https://forge.maximumdirect.net/base-layer/commandkit/src/tag/v0.6.0/docs/cli.md#output-failures).
Keep that outcome under upstream ownership rather than overriding it to make
diagnostic stream failures nonfatal.
## Output Resource Preparation During Preflight — Resolved
Prepare output resources as part of Audita's expressly named
`internal/framework/preflight` phase, after ConfigKit handoff and before model
calls. Follow the [preflight package boundary](glossary-stages.md#empty-collections-and-audita-preflight--resolved).
Complete configuration, invocation, and domain-readiness checks for the entire
pipeline first, including the quiet-destination rule and active destination
collision checks. Only then prepare output resources, and begin execution after
required preparation succeeds. Disabled report and debug destinations remain
inactive.
- For a regular transcript destination, create and open a temporary file in its
destination directory before processing. Preserve the existing destination
until processing and writing succeed, then replace it. This also preserves
input when the transcript intentionally replaces its own source; preparation
must not truncate the final path.
- Initialize enabled ordinary reports before processing, using the existing
`in_progress` report lifecycle and per-file replacement. An initialization
failure stops the invocation before model work.
- When debug capture is enabled, create its directory and initial artifacts
early. Create later artifacts as needed instead of opening every possible
artifact in advance. Debug preparation failures follow the nonfatal artifact
rule above.
- Use CommandKit's supplied writer for transcript stdout. Defer opening pipe and
device destinations until output delivery; in particular, opening a named pipe
during preflight could block waiting for its reader. Do not replace these
destinations with regular temporary files.
The preflight package coordinates preparation through the output-session
component. Reuse and adapt that component to own prepared handles, cleanup, and
final publication; keep filesystem machinery out of individual readiness checks.
Close owned handles and remove unpublished temporary files on failure or
cancellation, while retaining published outputs and retained diagnostic evidence.
The caller retains ownership of supplied standard streams.
Opening resources early establishes readiness at that point; later writes,
closes, and replacements can still fail. Apply the output-failure rules throughout
execution and finalization. Preserve per-file publication without adding a
transaction across the transcript and reports.
## Request Preview, Validation, and Smoke Commands — Resolved
Include standard ckprompt request preview, request validation, and the complete
smoke-command surface in the next major release. Enable the upstream adapters
and retain native commands, flags, reports, and outcomes. Smoke commands remain
explicit operator-invoked operations, separate from application startup and
automated release checks.
Use the standard request inputs directly where they suffice. Where Audita adds
role/profile selection, shared instructions, response schemas, or domain inputs,
reuse its processing request-construction helpers in the relevant adapters.
Preserve native operator overrides and keep generic requests usable without
Audita processing context. Request preview and validation operate on supplied
inputs; representative validator candidates can come from maintained fixtures
without running proposal inference as part of request construction.
All three capabilities are required adoption scope. Address concrete integration
blockers upstream rather than silently omitting standard capabilities.
For standard CommandKit commands passed through by Audita, provide a concise
link to the upstream documentation for the adopted version. Upstream owns their
command reference and behavior explanations. Do not duplicate that documentation,
add local provider-call/cost warnings, or add caveats or workarounds for perceived
limitations of the standard capabilities. Audita documentation covers only its
own selectors, request construction, domain inputs, and application-specific
behavior. Apply this documentation boundary to the whole standard command suite.
## Integration Boundaries
The native `app` and PromptKit configuration scopes are distinct. Both sides of
native comparison use their own selected inputs. Scope validation follows native
scope behavior; process preflight checks what execution needs. The same
engine-loading path and
[automatic source contract](promptkit.md#automatic-prompt-sources--resolved)
serve processing and all standard PromptKit commands. ReleaseKit supplies the
application version; CommandKit owns standard flags, formats, help, completion,
and outcomes, including native comparison status 3.
Audita supplies typed process inputs, domain request construction, preflight,
and output-session coordination. [Glossary readiness](glossary-stages.md#empty-collections-and-audita-preflight--resolved)
is part of that shared phase. Standard inspection remains independent of
processing inputs. Canonical Audita documentation owns application-specific
behavior and the hard cutover; standard commands link to the adopted upstream
reference. Exact selected dependencies and notices belong in attribution.
## Acceptance and Upstream Requests
Check the complete standard inspection/configuration inventory and native
formats through the assembled CLI, including failed-load evidence, redaction,
source selection, and missing/partial resources. Check help/version without
configuration and supplied-value handling through domain settings. Exercise
stdout transcript isolation, file output, quiet/verbose/debug behavior, completion
summary placement, cancellation, partial success, and output failures.
Verify that automatic prompt replacements and their origins agree between
processing, resource/configuration inspection, and request preview. Apply the
shared loader's source selection to validation and smoke commands as well, using
controlled provider boundaries for smoke acceptance. Inspection must retain the
same source behavior without requiring processing inputs or starting preflight.
Verify that the completion summary and created artifact locations appear only
in verbose/debug diagnostics, never in transcript stdout. Reject quiet processing
with a stdout destination; requested file outputs remain enabled in valid quiet
runs. Fatal error explanations remain visible in every mode, and a required-output
failure must not produce a successful completion summary. Cover ordinary reporting disabled as
well as enabled, and document the loss of the former default summary.
Cover required-output preparation failure before model calls, late write/close/
replacement failures, and report failure after a transcript has been published.
Verify retention of published output, preservation of the original processing
failure when reporting also fails, and attempts to finalize available reports.
Exercise optional debug-directory and artifact failures, including suppressed
warnings in quiet mode, and the native CommandKit outcome when a diagnostic
write itself fails. Keep these checks focused on Audita's integration and output
responsibilities rather than duplicating upstream reporter tests.
Verify that readiness failures occur before output resources are created.
Check that preparing regular transcript output preserves existing content,
including an in-place transcript, and that failure or cancellation closes owned
resources and removes unpublished temporary files. Cover enabled report
initialization, inactive disabled destinations, and debug artifacts created as
needed. Confirm that preflight does not open pipe/device destinations and that
supplied standard streams remain caller-owned.
Cover omitted and empty output selections in effective quiet mode, including
with reports or debug capture enabled: reject before model calls and artifact
creation. Accept valid explicit file and discard destinations. Exercise native
mode ordering, explicit false, and aliases so the check follows the resolved
mode. Keep quiet inspection valid and help/version free of processing setup.
Verify the independent capture and visibility decisions through CommandKit's
parser for processing commands with a valid explicit transcript destination:
| Arguments after the command path | Reporting mode | Capture artifacts |
| --- | --- | --- |
| None | Ordinary | No |
| `--debug` | Debug | Yes |
| `--debug --quiet` | Quiet | Yes |
| `--quiet --debug` | Debug | Yes |
| `--debug --verbose` | Verbose | Yes |
| `--debug --debug=false` | Ordinary | No |
| `--debug=false --debug` | Debug | Yes |
| `--debug --quiet --debug=false` | Quiet | No |
Check aliases, explicit false values, and option-looking operands or values
through native parsing. Inspection must not create processing artifacts even
with debug enabled. Check artifact-location reporting subject to normal
visibility and help text explaining capture under quiet mode.
Verify preview, validation, and every standard smoke operation through the
assembled CLI using fixtures and controlled providers. Focus on Audita's command
registration, engine loading, input forwarding, shared request construction, and
native report/outcome handoff. Keep integration coverage proportionate rather
than duplicating upstream capability tests.
Tagged core and integration suites passed during review, but do not establish
these Audita behaviors. Use offline tests and controlled providers.
CommandKit and integrations are early-stage. Freely propose upstream improvements
where reporting, declaration, or integration APIs are problematic or incomplete.
The reporting request is fulfilled by the released capabilities described below.
The resolved summary and destination decisions use standard reporting behavior;
they do not require an ordinary-mode summary channel or an exception to quiet
suppression. Record further concrete integration gaps as they arise and prefer
shared upstream improvements over a permanent local output layer.
### Upstream Review: Shared Debug Input and Reporting Mode
On 2026-11-09, verified published upstream tags for core, ckconfig, and ckprompt
v0.6.0, the then-selected release set. Reviewed the core
source changes and external public-API tests. Compared with the previous reviewed
integration releases, ckconfig and ckprompt change dependency pins and release
notes without changing integration implementation.
The released [binding contract](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/1613ff95cab60581de5d86f6e9e2a3cc091a44a0/binding.go)
and [invocation API](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/1613ff95cab60581de5d86f6e9e2a3cc091a44a0/identity.go)
support the selected design. The shared binding preserves supplied-value tracking,
explicit false, repeated occurrences, and aliases. Application defaults affect
the bound input, not reporting-mode selection; Audita selects a false default.
`Invocation.ReportingMode()` reports the selection independently of delivery
success and remains available after finalization. `--debug --quiet` therefore
retains a true capture input while the reporting mode is quiet.
Using Go 1.27.3, all three tagged module suites passed with `GOWORK=off` and
released dependencies. An isolated consumer importing all three published v0.6.0
modules, without local replacements, passed 33 cases spanning the roadmap's
capture/mode combinations, aliases, and quiet-destination policy. The resolved
graph selected the intended ConfigKit v1.1.0 and PromptKit v0.20.0 dependencies.
On 2026-11-10, the newly selected ckconfig and ckprompt v0.7.0 tagged suites
also passed independently with released dependencies. Their changes update
dependency pins and release documentation without changing adapter implementation.
The new graph selects ConfigKit v1.2.0, PromptKit v0.21.0, and core v0.6.0.
These checks establish the upstream gate; they do not replace Audita's assembled
integration acceptance. No additional upstream request was identified.

View File

@@ -1,187 +0,0 @@
# ConfigKit Adoption Outline
**Updated:** 2026-11-10
**Status:** Target decisions resolved and implementation complete. The
[master roadmap](library-adoption.md) owns shared policy and dependency selection;
the [implementation plan](implementation.md) owns sequencing.
## Baseline and Target
Before this work, Audita used ConfigKit v0.7.1 through its former import path. Its
[configuration contract](../config.md) describes application file discovery,
overlays, defaults, inheritance, secret references, and explicit CLI settings.
Adopt ConfigKit v1.2.0 and its stable public API as the configuration foundation.
Use its native loading, discovery, presence, composition, resolution, diagnostics,
and inspection mechanisms. Audita supplies domain types and validation; retain
custom loading behavior only for a demonstrated domain requirement. Standard
operator access is implemented through the [CommandKit outline](commandkit.md).
The main upstream references are the
[v1 API migration](https://forge.maximumdirect.net/base-layer/configkit/src/commit/c1c7e87f2cdf77a0cbf3327831ac05578e756b9e/docs/releases/v1.0.0.md),
[v1.2 release](https://forge.maximumdirect.net/base-layer/configkit/src/commit/c1c7e87f2cdf77a0cbf3327831ac05578e756b9e/docs/releases/v1.2.0.md),
and [configuration contract](https://forge.maximumdirect.net/base-layer/configkit/src/commit/c1c7e87f2cdf77a0cbf3327831ac05578e756b9e/docs/config.md).
## Agreed Direction and Migration Work
### Application Schema Version — Resolved
Use `version: 3` for Audita's application configuration in the next major
release, with a hard cutover. The new contract includes the selected native
PromptKit ownership boundaries and the final stage-specific glossary design.
Finalize that combined schema before release so operators migrate once.
Reject obsolete application schema versions with migration guidance. Do not
retain version-2 loading, automatic conversion, or dual-schema compatibility.
Update application defaults, examples, and schema validation together when the
new schema is implemented. The no-main-file behavior below remains supported;
embedded defaults must supply the current application version.
This is Audita's application schema version, independent of library releases and
ConfigKit or PromptKit source headers. It does not require a version header on
every imported fragment. Hard-cutover guidance must explain the actual field and
ownership changes, including glossary-stage configuration, rather than merely
instructing operators to change the version number.
### Discovery Locations and Import Selection — Resolved
For Audita's main application configuration, an explicit `--config` selects
exactly that file. A missing, inaccessible, or invalid explicit file is an error;
do not fall back to discovery.
Without an explicit file, search in this order using ConfigKit's native presets
and filename rules with application name `audita`:
1. `WorkingDirectory` for project-local configuration.
2. `UserConfigDirectory` for personal configuration.
3. `UnixSystemDirectories` for system configuration.
Select the first matching file. Do not merge every discovered file or continue
searching after a selected file fails to load. Additional composition is explicit
through native imports and overlays. Recommend explicit configuration paths for
automation so its selection does not depend on the working directory.
Enable native imports for operator configuration sources, retaining upstream
defaults and declaration-level controls. Imports compose peer documents, not
higher-priority override layers. Missing optional imports may be absent;
operators use `required: true` for essential inputs. Invalid declarations,
unreadable selected files, and composition conflicts retain native errors.
The PromptKit outline owns [automatic prompt sources](promptkit.md#automatic-prompt-sources--resolved).
Those imports compose in a separate engine underlay, using the selected
application main's recorded context under the shared rule below. Keep application
and PromptKit schemas separate while sharing native loading mechanisms.
### Companion Resource Base and Overlays — Resolved
Use the selected main application configuration file's directory as the lookup
base for automatic glossary and prompt companions and named overlays. This applies
to both explicit `--config` and native discovery. Follow ConfigKit's resolved
context: host symlinks use the canonical target directory; a wider containment
root does not move the lookup base. Transitive imports retain their declaring
file's native context, and embedded inputs retain their own filesystem namespace.
For application-owned glossary import declarations, use a non-file underlay
`Input` with `Imports: true` and `MainRelative: configkit.MainRelative()`.
ConfigKit binds it during the single `LoadLayered` call. PromptKit's separate
loader uses the application result's recorded main context, as specified in its
[automatic source contract](promptkit.md#automatic-prompt-sources--resolved).
Do not duplicate main discovery or perform a preliminary full configuration load.
Select native `overlays/<name>.yml` beside the main file. Let `LoadLayered` derive
its overlay context; do not supply an invocation-directory `OverlayFilesystem`
or `OverlayFallback`. No overlay selection loads no overlay; an active selection
requires a usable context and the named file. Aggregate `overlays.yml` is deferred
upstream and is outside this adoption. ConfigKit v1.2.0 satisfies the upstream
API requirement for this decision.
### No Configuration File Found — Resolved
Use ConfigKit's optional-search behavior when automatic discovery finds no file:
continue with embedded defaults, underlays, and explicit CLI settings, then
validate what the requested command needs. Require sufficient configuration for
the operation, not the existence of a main configuration file.
Resource inspection can work without a main file. Processing can run when its
required selections and inputs are otherwise supplied through supported
mechanisms. Report missing command-specific settings clearly; do not invent an
implicit model or profile selection to make incomplete execution settings pass.
Inspection must accurately show that no main file was selected.
When no main context exists, skip automatic optional glossary and prompt
companion imports; retain embedded defaults and explicitly supplied settings.
Do not install a working-directory fallback or infer a base from unsuccessful
search candidates. Use ConfigKit's native absent-base behavior for the glossary
underlay and omit automatic operator prompt inputs in the separate engine load.
An explicitly selected overlay without a usable context fails. Preserve genuine
absent-main evidence rather than manufacturing a placeholder source. Explicit
file errors and failures loading a selected discovered file remain terminal.
### Target Boundaries
The application uses the `go.maximumdirect.net/configkit` module and native
recorded resolution, discovery, source diagnostics, and safe effective output.
Source composition and inheritance precede typed decoding and explicit CLI
assignment; application resolution and validation follow. CLI assignments do
not repair earlier decoding failures, change inheritance relationships, or
propagate parent edits through resolved children. Native source provenance uses
`main` in place of `base`. Genuine source-root controls use `config:`.
PromptKit [owns backend and credential resources](promptkit.md#backend-and-credential-ownership--resolved).
Audita's v3 schema has no separate backend or LLM credential registry. Native
[automatic resource sources](promptkit.md#automatic-prompt-sources--resolved)
use the application main context while retaining their separate schema and tiers.
The v3 schema includes the glossary roadmap's [scope and inheritance model](glossary-stages.md#configuration-scope--resolved),
[typed handoff](glossary-stages.md#list-inputs-and-configuration-handoff--resolved),
and [optional stage identity](glossary-stages.md#stage-identity-and-attribution--resolved).
Glossary definitions use native composition, [default underlay sources](glossary-stages.md#default-sources-and-explicit-configuration--resolved),
and [collection-scoped identity](glossary-stages.md#entry-identity--resolved).
Pipeline stages remain an ordinary ordered list, including repetitions and
explicit empty-pipeline behavior. The application supplies domain resolution
rules within the native lifecycle, with no second runtime defaulting pass.
## Documentation and Acceptance
Update [configuration](../config.md), relevant [CLI](../cli.md) behavior,
[change recipes](../internal/cli-config.md), maintained examples, migration
guidance, and attribution as the corresponding behavior lands. Public docs
remain descriptions of implemented behavior until then.
Acceptance should demonstrate native file selection, source composition,
overlays, explicit false/zero/empty values, derived settings, and secret handling
through real ConfigKit loading. Cover the changed inheritance/assignment order,
source errors, useful failure evidence, and secret-safe inspection. Reuse upstream
coverage for generic grammar rather than copying its test matrix. Verify the
standard ckconfig surface through the assembled CLI and run the full application
suite at the coordinated migration boundary.
Check explicit-file selection without fallback, native working/user/system
search precedence, and terminal errors for a selected invalid file. Verify
optional and required imports and peer-composition errors through Audita's
integration. Verify that discovery exhaustion permits inspection and sufficiently
configured processing, while incomplete processing reports its missing inputs.
Cover absent-main provenance and filesystem context for selected overlays or
relative resources without weakening explicit-file error behavior.
Verify that explicit and discovered mains outside the working directory anchor
companions and overlays beside the selected file. Cover a broader containment
root, native source evidence, and absent-main skipping without a working-directory
fallback. Verify PromptKit receives the same application context while retaining
its separate schema and precedence, through processing and inspection alike.
Verify acceptance of the final version-3 schema and rejection of obsolete
application versions. Check that no-main-file loading uses version-3 defaults,
and that maintained examples and migration guidance cover the final library
ownership and glossary-stage changes without a legacy compatibility path.
The earlier passing configuration suite is useful baseline evidence, not proof
that operators see unchanged semantics. Native semantics and clear migration are
the target; preserving incidental old output or validation order is not.
## Upstream Requests
The main-relative companion/overlay request is fulfilled by ConfigKit v1.2.0.
No further ConfigKit change request is currently identified. Prefer adapting
Audita to its stable supported API. Record any necessary exception with a concrete domain
requirement and the smallest integration boundary that satisfies it.

View File

@@ -78,12 +78,3 @@ semantics. It must address meaning preservation and the effects on segment
identity, timestamps, fixed chunks, subsequent stages, recombination, and output
consumers. Do not infer authorization to remove a segment from an empty string
or introduce segment-removal machinery as part of span-deletion consistency.
## Library Inspection and Configuration Comparison
Standard library inspection and configuration comparison have moved into the
accepted [native library adoption roadmap](library-adoption.md). The
[CommandKit outline](commandkit.md) owns the operator surface, including the
full ckprompt inspection set. These capabilities are no longer deferred pending
an additional operator need; consistency across the application suite is the
selected reason for adoption. The domain features above remain separate work.

View File

@@ -1,962 +0,0 @@
# Stage-Specific Glossary Inputs
**Updated:** 2026-11-10
**Status:** Accepted feature scope, ownership, and stage-selection semantics for
the next Audita major release, including named collections and recursive import
placement, optional default sources, collection-scoped entry IDs, extensible
entry content fields, and optional stage IDs. Active glossary vocabulary takes
precedence over overlapping protection. Empty collections are permitted, with
Audita preflight rejecting empty glossary stages. Design decisions are resolved;
implementation is complete. The
[master roadmap](library-adoption.md) owns release completion; the
[implementation plan](implementation.md) owns sequencing.
## Baseline and Target
The current [CLI](../cli.md) accepts one glossary input for a processing run.
The [pipeline configuration](../config.md) supports repeated glossary stages,
but does not select different glossary inputs for each occurrence. Glossary
files currently have a separate [YAML input contract](../integrations/transcript-glossary-files.md#glossary-collections).
Make glossaries and glossary collections reusable, composable configuration
assets loaded and composed by ConfigKit. Allow ordered stages to select different resolved
vocabulary within one processing run: for example, a focused party pass, a
focused spell pass, and grammar cleanup using both. Each stage processes the
transcript resulting from earlier stages. Operators need not maintain one
manually combined glossary or run Audita separately for each pass.
The major-release policy permits a hard cutover. The current single-glossary
CLI, standalone parser, and file schema do not constrain the target design.
Finalize the glossary representation with the agreed
[version-3 application schema](configkit.md#application-schema-version--resolved)
so operators migrate once. Collection placement and named selection are selected;
default import sources, their tier, entry identity, and content fields are also
selected. Runtime ordering, deduplication, and active-vocabulary exemptions are
selected below; other validation business logic is retained. List clearing and
the configuration handoff boundary are resolved, as are optional stage identity
and attribution. Empty collections and preflight readiness checks are resolved
below.
## Glossary Configuration Ownership — Resolved
Glossaries are configuration. ConfigKit owns their source loading, parsing,
composition, inheritance, collection operations, strict typed decoding, and
configuration provenance. Audita supplies the Go schema, collection identity
registrations where applicable, and configuration-contract validation through
supported public APIs. Use native imports and layering rather than an Audita YAML
loader or private glossary merge engine.
ConfigKit owns the entire configuration-resolution lifecycle up to handoff,
including explicit CLI assignment, presence tracking, defaults, and stage
inheritance. Audita supplies its domain-specific resolution rules through
ConfigKit's supported application lifecycle. Complete those rules before handing
off fully resolved configuration; do not add a second resolution pass in Audita's
processing code.
Before transcript processing, hand off fully resolved, typed Go glossary
configuration and stage selections to Audita. Schema and configuration-consistency
checks use the supported ConfigKit validation lifecycle. Audita then runs an
explicit preflight phase for execution-readiness business logic, including the
nonempty glossary-stage check below. A valid configuration does not by itself
establish that a processing run has useful work. Audita's processing code must not
reopen glossary documents or parse arbitrary YAML after this handoff. Remove the separate
glossary decoding/composition path when the new contract lands.
All configuration-source path and resolution behavior remains upstream-owned,
including glossary documents, imports, overlays, and source resource contexts.
Retain native source attribution through application resolution. A glossary
filename is a configuration source, not an application-data file for a second
post-handoff loader. Choose the source arrangement through ConfigKit's public
composition APIs; a string in an application field does not automatically cause
ConfigKit to load another document. Use the selected import placement and
application-supplied underlay below.
### Named Collections and Recursive Imports — Resolved
Define `glossary_collections` as a typed mapping of collection names to collection
objects. Each object contains an `entries` collection. Root and stage `glossaries`
and `protected_terms` are ordered lists selecting those names, not filenames.
An omitted stage selection inherits the root selection; an explicit list replaces
it, and `[]` selects none. Report unknown collection names during configuration
validation. Selection order determines runtime traversal, not source precedence.
Mount glossary inputs at `glossary_collections`, with each imported file
declaring its collection name. The default underlay below supplies native file
and recursive directory imports, keeping the main configuration focused on
selection and stages:
```yaml
version: 3
glossaries: [party, spells]
pipeline:
stages:
- module: glossary
glossaries: [party]
- module: glossary
glossaries: [spells]
- module: grammar
```
An imported `party.yml` declares the collection directly, without repeating the
application's `glossary_collections` wrapper:
```yaml
party:
entries:
- id: merrin
name: Merrin
category: character
description: The party's wizard.
player: Alex
class: wizard
level: 5
```
The entry follows the [selected content contract](#entry-content-fields--resolved).
Its additional campaign fields remain available for other consumers.
Keep collection identity in document keys. ConfigKit does not infer keys from
filenames or subdirectories; all matches of the declaration receive the same
destination. Moving a file within the imported tree therefore need not change
stage selections. A file can define multiple collections, and multiple sources
can contribute to one collection under native composition and identity rules.
Repeated membership and runtime entry ordering follow the resolved runtime
vocabulary rules below.
Use native mapping placement, discovery, composition, and provenance. Do not add
a directory walker, filename-to-key conversion, or YAML preprocessing in Audita.
Imports in the same tier are strict peers; their discovery order does not create
an override priority. Intentional overrides use upstream layering semantics.
### Entry Identity — Resolved
Represent each collection's `entries` as an ordered identified list. Each entry
has an explicit, stable, nonempty string `id`, unique within that collection.
Its configuration identity is the pair of collection name and entry ID. Keep
identity independent of the displayed term, category, and descriptive text so
those fields can change without changing the record being addressed.
Register `id` through ConfigKit's application sequence-identity API at every
`glossary_collections.<collection>.entries` destination, using a native mapping
wildcard registration. Authors do not need to repeat identity declarations in
every file. ConfigKit owns duplicate-identity checks, inheritance lookup, and
cross-layer matching, including final typed-result identity validation. Audita's
domain validation requires nonempty string IDs; comparisons use ConfigKit's
native exact matching, without case folding or a custom normalization scheme.
Recommend readable IDs such as `shield` or `mordenkainens-magnificent-mansion`;
do not require generated UUIDs or impose a slug syntax. The same ID may occur in
different collections and identifies distinct configuration records there. Two
entries with different IDs may also share a displayed name. Neither matching
IDs across collections nor matching text implicitly establishes semantic
identity. Runtime protection may still deduplicate their recognized spellings.
A higher-priority definition targets an existing record by retaining its ID in
the same collection. Apply native collection operations: duplicate identities
among strict peers fail, while upsert at a precedence boundary replaces the
whole matching record. Do not treat an identified list as a mapping that merges
individual fields of matching records. The selected ordinary stage-selection
lists remain separate from these definition collections.
### Entry Content Fields — Resolved
Require `id`, `name`, and `category` as nonempty strings. The collection-scoped
identity contract above governs `id`; `name` is the canonical term, and `category`
is free-form text rather than an Audita-defined enumeration.
Support these optional fields:
| Field | Contract |
| --- | --- |
| `description` | String providing contextual guidance; omission or an empty string requires no filler text. |
| `aliases` | List of nonempty strings representing alternate names or spellings. |
| `plural` | Nonempty string when supplied, providing an explicit plural form. |
Allow and preserve additional ordinary entry fields, including nested mappings,
lists, and scalar values. A campaign's party roster can therefore also carry
player names, classes, levels, affiliations, or data for other applications.
Preservation applies to the effective result of native composition; it does not
change whole-record replacement semantics.
Use typed Go fields for the Audita contract and ConfigKit's native inline
string-keyed map of dynamic values for unmatched fields. Its
[schema binding rules](https://forge.maximumdirect.net/base-layer/configkit/src/commit/c1c7e87f2cdf77a0cbf3327831ac05578e756b9e/docs/config.md#advanced-type-and-field-rules)
cover decoding and inspection without a custom decoder. Keep additional data in
the resolved Go configuration and native inspection. ConfigKit still owns its
reserved syntax and supported value shapes; extensibility does not mean
accepting arbitrary YAML. Audita validates its known fields without imposing
campaign-specific rules on additional fields. A misspelled optional field may
therefore be retained as additional data; do not add a separate typo-detection
mechanism.
Build the rich LLM projection deliberately from Audita's known glossary fields,
including `description` when present. Do not automatically forward additional
fields to the LLM. Derive protected vocabulary from names, aliases, and plurals;
unrelated metadata does not contribute vocabulary. These consumer projections
leave the complete resolved entry intact.
### Default Sources and Explicit Configuration — Resolved
Audita supplies one glossary underlay with two optional native imports:
```yaml
config:
imports:
- path: glossary.yml
required: false
destination: [glossary_collections]
- dir: glossary
required: false
recursive: true
pattern: ["*.yml", "*.yaml"]
destination: [glossary_collections]
```
Both locations follow the selected main application configuration file's
resolved directory under the shared [resource-base rule](configkit.md#companion-resource-base-and-overlays--resolved).
Supply the declarations in a non-file underlay with imports enabled and
`MainRelative: configkit.MainRelative()`. ConfigKit binds the context during the
application load. With no usable main context, skip these optional imports and
retain independent defaults; do not supply a working-directory fallback. Keep
embedded contexts independent and do not add a local discovery pass or walker.
Load both sources when present; this is composition, not first-match discovery.
Missing optional sources contribute nothing. Present sources retain ConfigKit's
normal parse, access, and composition errors; absence does not remove the domain
requirement for a glossary-correction stage to select usable vocabulary.
The file and directory contributions compose as strict peers in the same
underlay tier. Neither overrides the other by declaration or discovery order.
Main configuration and its imports have higher priority and can supplement or
replace definitions according to native mapping and collection policies. An
identified-list upsert replaces the whole matched record; details depend on the
selected entry identity and native collection policy.
Operators can put small inline collections in `glossary.yml`, organize larger
libraries below `glossary/`, or use both. Nested imports retain native relative
path and destination inheritance. A nested import from mounted `glossary.yml`
inherits the `glossary_collections` destination unless it explicitly extends it.
Do not repeat that destination unnecessarily in a manifest.
With both defaults enabled, use the file for inline collections or imports of
other sources, rather than a manifest that also imports the files discovered
under `glossary/`. Repeated inclusion within the tier retains ConfigKit's native
error; Audita does not silently deduplicate the import graph.
Explicit main-file imports supplement the underlay's sources; they do not cancel
its import declarations. In particular, main-file `config.imports: []` does not
disable default loading. An underlay does not set a universal destination for
unrelated explicit imports. Changing or disabling default discovery, if added
later, would require a load-time choice before ConfigKit processes the underlay;
ordinary resolved application values cannot retroactively change those imports.
### Shared Libraries and Campaign Vocabulary — Resolved
As a campaign maintainer, I can compose a reusable, versioned D&D glossary
library with campaign-specific vocabulary without editing the shared definitions.
I can select different combinations for focused correction passes while
protecting the selected vocabulary throughout the pipeline.
Use stable, descriptive collection names independent of filenames. For example:
| Shared collections | Campaign collections |
| --- | --- |
| `dnd5e.spells` | `campaign.party` |
| `forgotten_realms.places` | `campaign.npcs` |
| `dnd5e.creatures` | `campaign.places` |
These are literal mapping keys. Dots are a naming convention, not nested lookup
or another reference language; this convention does not restrict other valid
collection names. A shared document declares the same key wherever it is used.
One practical project layout is:
```text
campaign/
audita.yml
glossary.yml
glossary/
shared/
dnd5e/
spells.yml
creatures.yml
forgotten-realms/
places.yml
campaign/
party.yml
npcs.yml
places.yml
```
Run from the campaign directory to use the default sources. `glossary.yml` can
contain small inline collections; the default recursive directory import discovers
the shared and campaign subtrees through ConfigKit. A vendored library release
or pinned checkout inside the configuration tree lets each
campaign adopt shared updates deliberately and independently. Library distribution
and revision management remain outside Audita; it consumes local configuration
sources through native imports. This layout fits the native import-root model
without adding cross-directory discovery conventions.
Importing collections makes them available; selections determine their use.
For example, the campaign can select the following vocabulary and focused passes:
```yaml
glossaries:
- dnd5e.spells
- forgotten_realms.places
- campaign.party
- campaign.npcs
- campaign.places
pipeline:
stages:
- module: glossary
glossaries: [campaign.party, campaign.npcs]
- module: glossary
glossaries: [dnd5e.spells]
- module: glossary
glossaries: [forgotten_realms.places, campaign.places]
- module: grammar
```
With `protected_terms` omitted, root protection derives from that selection.
Each glossary stage exempts its active vocabulary; grammar protects the complete
selection. An available but unselected collection such as `dnd5e.creatures` does
not automatically enter prompt inputs or protected vocabulary. Imported sources
still undergo normal ConfigKit composition and validation.
Add new campaign vocabulary in campaign collections and select it alongside the
shared collections. Intentional adaptations of shared definitions use native
ConfigKit inheritance or explicit layering, without changing the shared source.
Use the selected collection-scoped entry identity when adapting definitions;
directory order must never silently choose which definition wins.
### Derived Runtime Representations — Resolved
Keep the resolved configuration intact. Audita derives separate runtime views
for its consumers, preserving traceability to configured entries and selections:
| Consumer | Derived representation |
| --- | --- |
| Glossary module LLM | Rich entries projected from known glossary fields, including names, categories, descriptions, aliases, and plurals when present. |
| Protected-term validator | Deduplicated recognized vocabulary prepared for deterministic matching. |
| Glossary-stage protection | Selected protected vocabulary minus the active glossary vocabulary. |
| Diagnostics and inspection | Resolved definitions and selections with their configuration origins, distinguished from derived runtime views. |
ConfigKit's identity and composition rules govern which configuration records
coexist or replace one another. Runtime vocabulary deduplication governs whether
multiple valid records contribute the same recognized spelling. Do not use the
latter to suppress configuration conflicts or rewrite the resolved definitions.
Rich prompt data need not lose distinct definitions merely because their text
matches in the protection view. Audita owns matching, transcript-specific
validation, and the selected stage-specific transformations. Apply the runtime
vocabulary rules below, including the active-vocabulary exemption, while retaining
other validation business logic.
### Runtime Vocabulary and Ordering — Resolved
Retain distinct resolved entries in rich LLM input, even when names or other
content match. Two entries named Shield may describe a spell and an item; both
can supply useful context. Matching text does not merge configuration identities.
Include each selected entry once, identified by `(collection name, id)`. Traverse
collections in selection order and entries in their resolved ConfigKit order.
Keep the first occurrence when selection repeats an entry. Separate records
remain separate even when their content is identical. These rules govern runtime
projections without rewriting the configured selections or definitions.
Deduplicate recognized spellings in protected vocabulary using the existing
matcher rules. Repeated membership must not multiply protection requirements.
Retain the association between each spelling and all contributing entries so
vocabulary deduplication does not discard identity information.
For a glossary stage, active glossary vocabulary takes precedence over protection
from every selected collection. Remove each active recognized spelling from the
stage's effective protected vocabulary even when a distinct, non-active entry
also contributes that spelling. Apply the existing matching rules to names,
aliases, and supported plurals. The glossary stage must be free to manipulate its
active vocabulary without protected-term rules blocking those changes.
For example, if the active spell collection and a protected item collection both
contain Shield, that spelling is exempt during the spell pass. Other protected
spellings remain protected; sharing one spelling does not exempt every spelling
of the non-active entry. Configured entries and their associations remain intact.
The exemption is local to that stage, and other validators continue to apply.
Preserve other existing matching and identity-dependent validation business
logic, including protected-name repetition handling. Integrate the reduced
vocabulary without reintroducing protection for exempt active spellings through
another contributing entry or a downstream protected-term check.
## Empty Collections and Audita Preflight — Resolved
Permit glossary collections with no entries. They remain valid configuration
assets, whether imported for reuse, inspected, or selected alongside populated
collections. A nonempty list of selected collection names does not establish
that a stage has entries to process.
Use an explicit Audita preflight phase after ConfigKit hands off the fully
resolved configuration and before pipeline execution begins. Preflight evaluates
execution-readiness business rules against that resolved data. It does not load
sources, resolve configuration, restore defaults, or change stage inheritance.
Keep the nonempty glossary-stage check in Audita preflight rather than ConfigKit's
configuration-validation callbacks.
The shared `internal/framework/preflight` package owns this phase.
Accept fully resolved configuration and the domain inputs needed for
readiness checks through ordinary Go functions and concrete inputs. Return
errors identifying the affected stage and reason; CLI presentation remains with
the caller. Keep the package small and independent of CLI and provider transport.
It must not reload or modify configuration or make provider calls. ConfigKit
retains configuration resolution, and correction validators retain evaluation of
proposed transcript changes. Future execution-readiness checks belong here when
they fit this responsibility; no generic check-registration framework is needed.
Complete invocation and domain-readiness checks before preparing output
resources, then begin execution after required preparation succeeds. Preflight
coordinates preparation through the output-session component, which owns file
handles, cleanup, and final publication. The CommandKit outline owns the
[output preparation contract](commandkit.md#output-resource-preparation-during-preflight--resolved)
and [output-failure rules](commandkit.md#output-failure-behavior--resolved).
This extends readiness preparation after handoff without adding configuration
resolution or duplicating filesystem machinery in the glossary checks.
Preflight checks every configured glossary-correction stage. Its combined selected
collections must supply at least one entry. Empty selections, null selections,
and nonempty selections whose collections collectively contain no entries fail
this check. A mixture of empty and populated collections passes when the combined
input contains an entry. An empty protection selection remains valid and supplies
no protected vocabulary.
Complete preflight for the entire pipeline before executing any stage or making
processing model calls, so an empty later glossary stage cannot fail only after
earlier stages have incurred work. Reject it before output resource preparation.
Report a clear readiness error identifying the stage by position, module, and
optional ID, with its selected collections.
Do not silently skip the stage. This is a processing preflight phase, not another
operator-configured pipeline module; ordinary configuration/resource inspection
can still inspect valid empty collections.
## Root Defaults and Stage Overrides — Resolved
Define global stage defaults at the configuration root. Represent the pipeline
as an ordered `pipeline.stages` list of objects, each selecting a `module` and
optionally overriding stage settings. Resolve every stage independently against
the root settings. Omitted stage settings inherit; explicit stage values override.
Preserve meaningful false, zero, and empty values under each setting's validation
rules rather than treating them as omission. A stage override does not alter
root settings or defaults seen by later stages.
`glossaries` and `protected_terms` select named definitions from the resolved
`glossary_collections` mapping. Keep file organization in the import declarations
and collection names in stage settings. This is domain selection over typed data,
not a general variable-substitution language.
For the party/spells use case, the root selects both collections, the first
stage selects party vocabulary, the second selects spell vocabulary, and grammar
inherits both. All stages inherit the root protection selection by default;
glossary stages exempt their active vocabulary as described below. Transcript
changes carry forward; configuration overrides do not. Each consumer receives
the appropriate view of its stage's effective settings.
Invocation-wide concerns such as configuration discovery, output destinations,
and reporting mode remain global. Preserve stage order, repeated modules, and
explicit empty-pipeline behavior. Use native ConfigKit presence and provenance;
Audita owns the domain meaning of stage scope.
### Stage Identity and Attribution — Resolved
Support an optional operator-chosen `id` on each stage for reports and diagnostics:
```yaml
pipeline:
stages:
- id: party-pass
module: glossary
glossaries: [party]
- id: spell-pass
module: glossary
glossaries: [spells]
- module: grammar
```
When supplied, an ID must be a nonempty string unique within the pipeline.
Compare IDs exactly and case-sensitively; no slug syntax or generated identifier
is required. Unnamed stages remain valid. Validate supplied IDs through ConfigKit's
supported lifecycle before handoff so runtime consumers receive resolved IDs
without generating or resolving configuration themselves.
Retain execution position and module identity alongside the optional ID. Reports
and diagnostics use the supplied ID when present and otherwise identify the stage
by position and module. An operator-chosen ID remains meaningful when stages are
reordered; position continues to describe execution order within a run. Preserve
ordered execution and repeated modules.
Inspection exposes effective glossary and protection selections and their
ConfigKit source origins for both named and unnamed stages. Stage naming does
not replace configuration provenance. These IDs serve reporting and diagnostics;
they do not introduce targeted-stage CLI overrides or change pipeline composition
semantics.
## Configuration Scope — Resolved
Settings governing an individual stage's requests, acceptance, or model-operation
budget support root defaults and stage overrides. Settings governing preprocessing,
the invocation's shared resources, or its final outputs remain global. Classify
by the setting's meaning and consumer lifecycle, not by where current code stores
it. The inventory below records the selected scopes; version-3 field
representation must preserve these decisions.
| Setting | Scope and rationale |
| --- | --- |
| `glossaries` selection | Stage: resolved glossary collections supplying correction and context vocabulary. |
| `protected_terms` selection | Stage: independently selected glossary collections supplying protected vocabulary; defaults from root `glossaries` before stage inheritance. |
| Glossary definitions and collection composition | Global: typed definitions composed through ConfigKit; runtime views are derived per consumer. |
| Applicable confidence threshold | Stage: acceptance of that stage's proposals. |
| Proposal and validation profile selection | Stage: models and generation settings appropriate to each role. |
| `context.description` | Stage: prompt context shared by proposals and validators. |
| `validation.max_prompt_tokens` | Stage: batching budget for that stage's validators. |
| `llm.operation_timeout` | Stage: deadline for each logical model operation. |
| `llm.repair_attempts` | Stage: structural-repair budget for its requests. |
| `llm.transient_retries` | Stage: native transient-retry budget for its requests. |
| All `normalization.*` settings | Global: establish transcript segments before stage execution. |
| All `chunking.*` settings | Global: establish common section boundaries and identities across stages. |
| Transcript input, output destination, and `output.schema` | Global: input and final product of the whole run. |
| Reporting, debug capture, and artifact directories | Global: invocation reporting and retained evidence. |
| Configuration discovery, imports, and resource-source locations | Global: construct the configuration and catalog shared by stages. |
| Backend definitions, credentials, concurrency, and queue capacity | Global native PromptKit resources and shared backend admission. |
| Pipeline ordering and application schema version | Global: define the overall processing configuration. |
Stages may select different profiles and thereby different configured models or
backends. Model parameters remain in native PromptKit profiles rather than a
duplicated Audita settings system. Apply stage request budgets through native
request controls and operation contexts while retaining the shared engine and
backend admission. Do not rebuild or mutate shared backend configuration for
each stage. Per-stage validation batching does not change transcript chunking;
per-stage rechunking would be a separate feature decision.
### Glossary Selection and Protected Vocabulary — Resolved
Select correction/context vocabulary and protection vocabulary independently
at root and stage scopes. A glossary stage without an override uses the entire
root glossary selection; an explicit stage selection supports a focused pass.
An explicit protection selection is complete, not an additive set of extra
vocabulary. Do not implicitly union it with correction inputs or collections
selected by other stages.
The named mapping, ordered name selections, entry identity, repeated membership,
and rich-input order are selected above. Configuration composition
must follow ConfigKit's contracts rather than a local rule to concatenate
independently parsed files.
Resolve these settings through ConfigKit before deriving runtime views:
1. Load and compose glossary configuration and apply explicit CLI assignments
through ConfigKit.
2. If root `protected_terms` is omitted, derive it from a copy of the effective
root `glossaries`. Preserve any explicit root protection selection, including
`[]` or `null`.
3. Independently inherit the effective root `glossaries` and `protected_terms`
into each stage wherever that stage omits the corresponding setting. A stage
override replaces only its own selected list; explicit `[]` or `null` suppresses
inheritance for that setting.
4. After the configuration handoff, derive runtime views. For a glossary module
stage, construct its effective protected vocabulary by subtracting its active
glossary terms from its selected protected terms.
Non-glossary stages use their selected protection vocabulary without this
subtraction.
Protection therefore defaults at the root before stage inheritance. It does not
fall back to a focused stage's glossary list. In the party/spells scenario, no
operator protection configuration is needed:
| Stage | Glossary input | Protection selection | Effective protected vocabulary |
| --- | --- | --- | --- |
| Party glossary pass | Party | Party + spells | Spells |
| Spell glossary pass | Spells | Party + spells | Party |
| Grammar | Party + spells | Party + spells | Party + spells |
The table assumes distinct party and spell vocabulary. The subtraction applies
after resolving both stage selections, including explicit protection overrides.
It operates on recognized terms using the protection matcher's rules, including
names, aliases, and supported plural forms, rather than subtracting configuration
source files or collection names. Active spellings are exempt even when they
also belong to non-active protected entries, as resolved in the runtime vocabulary
contract above. Explicit protection selections do not override this exemption.
Keep the configured protection selection intact and construct the reduced
vocabulary separately for that stage. Do not mutate root settings, loaded
glossary entries, or another stage's protection. A glossary stage selecting all
of its protected vocabulary as active input has no glossary-derived protection
from those terms; its other validators still assess proposed corrections.
A stage can supply a narrower or different `protected_terms` list. Explicit
`protected_terms: []` disables glossary-derived protection for that stage without
clearing its correction/context inputs or disabling other validators. Explicit
`glossaries: []` clears correction/context inputs without changing the protection
selection.
Audita preflight requires a glossary-correction stage's effective selection to
supply at least one entry; other stages may operate without glossary context
where supported. A glossary selected only by a stage is not automatically added
to root protection.
Use the active-term exemption for glossary correction and retain the existing
module-appropriate allowance for spoken-word cleanup. Carry both selections
through execution and validation rather than passing a single combined glossary
to every consumer.
### Validation-Profile Fallback — Resolved
Combine root and stage selections, including explicit clearing, before deriving
the validation-profile fallback. If no validation selection remains, use the
stage's effective proposal profile. An explicit root validation profile is
inherited unless the stage replaces or clears it. Preserve presence so a value
previously derived at the root is not mistaken for an explicit choice.
| Root selection | Stage selection | Effective validation profile |
| --- | --- | --- |
| Proposal A; validation omitted | Proposal B; validation omitted | B |
| Proposal A; validation V | Proposal B; validation omitted | V |
| Proposal A; validation V | Proposal B; validation null | B |
| Proposal A; validation null | Proposal B; validation omitted | B |
| Proposal A; validation V or omitted | Validation W | W |
| Proposal A; validation omitted | Both omitted | A |
Clearing the validation-profile selection does not disable validation. This rule
does not invent a proposal selection when none is available; a stage requiring
model execution must have a valid effective proposal profile.
### Compound Values and Explicit Clearing — Resolved
Resolve eligible settings field by field. A partial settings group overrides
only its supplied children; an empty mapping such as `llm: {}` contributes no
overrides. For example, a stage setting `llm.repair_attempts: 0` inherits the
root proposal profile and operation timeout while explicitly selecting no repairs.
Omitted fields inherit root settings, with derived defaults applied at the scope
specified for each setting. Root protection defaulting precedes stage inheritance;
validation-profile fallback follows the combination of root and stage selections.
False, zero, and empty values remain explicit and follow per-field validation:
zero repairs is valid, while a zero operation timeout is invalid.
| Explicit input | Meaning |
| --- | --- |
| `context.description: ""` | Clear the inherited description. |
| `glossaries: []` or `glossaries: null` | Clear correction/context inputs; a glossary-correction stage then lacks its required input. |
| `protected_terms: []` or `protected_terms: null` | Disable glossary-derived protection without changing correction/context inputs. |
| `llm.validation_profile: null` | Clear the inherited selection, then use the effective proposal profile. |
| `llm.validation_profile: ""` | Error: use null to clear the selection deliberately. |
| Empty or null proposal profile | Invalid for a stage requiring model execution. |
| `llm: null` | Error: a settings group cannot be cleared as a whole. |
Declare genuinely optional selectors nullable and preserve omission versus
explicit null through resolution. Null is not a universal reset operation;
settings groups are not nullable. For glossary and protection selection lists,
apply the resolved null-as-empty contract below. This concerns stage selections,
not ConfigKit-owned definition collections.
Reject a glossary-correction stage's missing or empty effective input in Audita
preflight after configuration handoff and before execution. Other stages may
operate without glossary context where their operation supports it, independently
of their protection selection.
Lists replace the entire inherited list where list-valued stage settings apply;
`[]` and `null` explicitly select no entries. Do not append or union implicitly.
Preserve the owning library's semantics for library-owned resources and
identified collections. These scope rules do not introduce a custom merge
language or change ConfigKit source composition.
### List Inputs and Configuration Handoff — Resolved
Use ConfigKit's native nullable-list decoding and explicit-presence tracking for
`glossaries` and `protected_terms`. Omission can trigger the agreed root defaults
or stage inheritance within ConfigKit's application-resolution lifecycle;
explicit `null` and `[]` both suppress that defaulting or inheritance. Resolve
all effective selections before handoff.
Once Audita receives the fully resolved configuration, treat a null selection
as equivalent to an empty set. Do not restore defaults, inherit another value,
or run a second configuration-resolution pass because a received list is nil.
Nonempty selections retain their agreed ordering. ConfigKit may preserve the
input distinction between `null` and `[]` in provenance and inspection without
that distinction affecting processing; no normalization of the resolved
configuration is required solely to erase it.
An empty effective protection selection contributes no protected vocabulary.
An empty effective glossary input makes a glossary-correction stage unready to
execute, whether it originated from null, an empty list, absent configuration,
or selected collections with no entries. Enforce that business rule in Audita
preflight after handoff; ConfigKit may successfully resolve those configurations.
Use standard CommandKit/parser conventions for CLI list inputs and ConfigKit's
native override API for explicit root assignments. Pass the completed parser
selection as one override for its root field; let ConfigKit apply it and resolve
the resulting configuration. Exact flag spelling is an implementation detail
within that boundary. Do not introduce custom clearing syntax or merge machinery.
Explicit stage selections remain authoritative under the resolved precedence
rules. Use `[]` as the usual configuration example for clearing while accepting
native null values.
### CLI Overrides and Stage Precedence — Resolved
Ordinary CLI setting flags override the corresponding root settings through
ConfigKit's native CLI override API. Resolve stage inheritance afterward:
omitted stage fields inherit the effective root values, while explicit stage
values and clearing remain authoritative for that stage. Apply validation-profile
fallback after combining these selections. This preserves deliberate differences
between stages while allowing invocation-specific changes to their defaults.
For the party/spells scenario, a CLI assignment changing the root glossary
selection changes grammar's inherited input and, with root `protected_terms`
omitted, the derived protection inherited by all three stages. The explicit party
and spell correction selections stay unchanged.
An explicit root protection list is not changed by a root glossary assignment;
an explicit stage protection list, `[]`, or `null` remains authoritative for that
stage.
Apply this precedence consistently to all stage-capable settings. Submit only
explicitly supplied CLI values to ConfigKit; preserve false, zero, and empty
values under their per-field rules rather than allowing parser defaults to
override configuration.
Keep CLI functionality within ConfigKit's native capabilities. ConfigKit v1.2.0
does not support sequence-index paths in its CLI override API, so targeted-stage
CLI overrides are not part of this plan. Operators supply stage-specific values
in configuration files. Do not implement a parallel override system, custom
merge machinery, or a workaround for addressing stage-list entries. Any future
targeted-stage CLI support should depend on suitable native ConfigKit support.
The resolved stage-identity contract concerns reporting and diagnostics; stage IDs
do not imply CLI targeting. Audita's domain-specific inheritance and fallback
rules remain within ConfigKit's supported application-resolution lifecycle.
### ConfigKit Support
Use the selected ConfigKit v1.2.0 public lifecycle for this work. Its
[typed decoding contract](https://forge.maximumdirect.net/base-layer/configkit/src/commit/c1c7e87f2cdf77a0cbf3327831ac05578e756b9e/docs/config.md#defaults-and-typed-decoding)
already preserves explicit false, zero, empty, and permitted null values,
recurses through partial mappings, and replaces ordinary sequences. Represent
nullable selectors with nullable typed fields and settings groups with
non-nullable structs. Use native decoding and validation rather than a parallel
parser or generic deep-merge implementation.
Use the native [collection and inheritance contracts](https://forge.maximumdirect.net/base-layer/configkit/src/commit/c1c7e87f2cdf77a0cbf3327831ac05578e756b9e/docs/config.md#strict-document-composition)
for glossary definitions. For identified lists, register identity constraints in
Audita's ConfigKit definition so native final validation also covers values from
defaults, CLI, and recorded resolution. YAML-only declarations do not provide
that final-result guarantee. Apply the selected collection-scoped `id` identity
through `SequenceIdentityMatching` with literal mapping keys and an
any-mapping-key segment for the collection name.
Compose sources in the scope where cross-source identity and inheritance are
intended to apply. Loading files separately and concatenating afterward does not
provide those upstream guarantees. Strict peers reject duplicate identities,
including identical records; higher layers follow native collection operations,
and upsert replaces a whole matching record. Empty identified collections follow
their native mode (`[]` does not clear an append/upsert collection). These rules
are distinct from Audita's whole-list replacement of ordinary stage selections.
Do not extend native inheritance beyond its supported sibling scope or treat
inherited entries as abstract templates exempt from normal validation.
Root-to-stage inheritance remains an Audita application rule: ConfigKit does not
automatically copy root fields into new sequence elements. Implement that rule
in `Definition.Resolve`, using `Resolution.IsExplicit` for presence and
`Resolution.EntryInfo` for the fixed pre-resolution metadata. Use
`configkit.Default` for omitted stage fields and record root-field dependencies.
Do not treat a derived root validation fallback as an explicit selection.
Implement root protection defaulting in the same `Definition.Resolve` callback:
use `configkit.Default` for root `protected_terms`, copying effective root
`glossaries` and recording that path as its dependency. Then default each omitted
stage protection list from the effective root protection list, even when that
root value was derived. Preserve source context through both steps and avoid
shared mutable list storage. Explicit empty lists and nulls must suppress
defaulting.
Leave `protected_terms` absent from the bundled configuration underlay. ConfigKit
does not express this live list-to-list dependency as a declarative underlay
reference: native `extends` concerns sibling mappings and runs before CLI
assignment. Use the public recorded-resolution lifecycle, which sees final CLI
assignments, rather than static duplicated lists or custom reference machinery.
An explicitly null validation selection needs deliberate application fallback:
`configkit.Default` correctly leaves explicit null alone. Apply the chosen
fallback and use `Resolution.RecordDerivedDefault` to record the assignment and
its effective proposal-profile dependency, retaining the original explicitness
and history. Follow the native
[recorded-resolution contract](https://forge.maximumdirect.net/base-layer/configkit/src/commit/c1c7e87f2cdf77a0cbf3327831ac05578e756b9e/docs/config.md#recorded-application-resolution)
for all derived mutations, and use `Definition.Validate` for configuration-contract
checks on effective settings. The execution-readiness check for an empty glossary
stage belongs to Audita preflight after handoff. Keep stage values independent
when copying compound values.
The selected defaulting rules use existing public APIs. Verify the final glossary
composition and selection design against the native API before implementation;
do not compensate for a mismatch with a private configuration system.
### Durable Decision Record
Completion requires durable documentation before retiring this roadmap. Record
the glossary-configuration ownership boundary, typed handoff, and Audita preflight
responsibility, including its coordination with the output-session lifecycle, in
an ADR under the [documentation policy](../policy/documentation.md#architecture-decision-records).
This is an architectural ownership decision; routine scope and clearing choices
do not each require an ADR. The roadmap owns implementation status and sequencing.
Put enduring scope classification and ownership rules in the
[architecture policy](../policy/architecture.md) and the implemented collection,
selection, defaulting, and clearing contracts in the
[configuration reference](../config.md). Update the glossary input contract and
consumer internals as the redesign lands, removing obsolete standalone-parser
instructions. Document the distinction between configuration identity and derived
runtime vocabulary without copying the native ConfigKit reference into Audita.
When the package lands, add `internal/framework/preflight` to the
[internal overview](../internal/overview.md) and describe its invocation boundary
in the [pipeline internals](../internal/pipeline.md).
Update the [configuration change guide](../internal/cli-config.md) to require
classifying each new setting by consumer lifecycle, specifying its inheritance
and presence behavior, and documenting its scope in the configuration reference.
New settings should follow the established stage/global distinction; deliberate
exceptions need a domain rationale. Link to the durable policy rather than copy
the field inventory into multiple developer documents. This documentation work
is part of feature acceptance, not an optional follow-up.
## Integrated Target
The glossary feature uses the adopted ConfigKit and CommandKit conventions and
the shared preflight/output-session boundary. It replaces the standalone glossary
input and parsing path with typed, composed configuration. Runtime consumers
receive derived per-stage views from that handoff; reports identify the stage
and configuration inspection explains its effective selections and origins.
Consumed glossary sources participate in output-collision protection. Maintained
examples and hard-cutover guidance describe the new configuration contract.
## Acceptance Direction
Include a shared-library scenario with two campaigns consuming the same reusable
library and maintaining different local party, NPC, and place collections.
Verify independent selections and focused stages, inherited protection and
active-term exemptions, and provenance identifying shared versus campaign
definitions. Demonstrate an intentional adaptation through the selected native
inheritance/layering contract without modifying the shared source or the other
campaign's configuration. Cover an imported but unselected collection remaining
absent from prompt/protection views. Maintained examples should show deliberate
library revision adoption without introducing package-management code in Audita.
Use distinct party and spell fixtures with controlled model responses to show
that each stage receives its intended correction and protection selections,
that overrides do not leak into other stages, and that the second stage sees
the first stage's accepted transcript changes. Verify meaningful errors for
invalid selections or inputs, and retain the selected domain validation and
partial-success behavior. Exact test cases follow the design; live provider
calls are unnecessary.
Verify root fallback, per-stage override isolation, and explicit-value presence
for the selected stage settings. Include the grammar stage after the overridden
glossary stage to establish that it inherits both root glossary inputs. Verify
that all three stages inherit root protection derived from those inputs despite
the focused correction selections. Cover explicit root and stage protection
lists, independent empty-list clearing, a glossary stage with no override using
both inputs, and a collection selected only on a stage not entering root protection.
Verify that modules and validators receive their respective effective selections
and recorded source origins. Cover repeated modules and an empty stage list.
Verify named, unnamed, and mixed pipelines, rejecting empty or non-string supplied
IDs and duplicate IDs through configuration validation. Cover exact case-sensitive
comparison without imposing slug syntax. Verify IDs remain associated with their
stages after reordering while reported positions reflect the new order. Reports
and diagnostics retain module and position, with optional IDs when supplied;
inspection exposes effective selections and source origins for every stage.
Confirm stage IDs do not change pipeline composition or add CLI targeting.
Cover default-source loading with only `glossary.yml`, only `glossary/`, both,
and neither present. Verify resolution beside explicit and discovered main files
outside the working directory. With no main context, verify optional imports are
skipped without a working-directory fallback. Preserve normal errors for invalid
present sources and preflight rejection of unusable glossary stages. Verify
strict-peer conflicts within the underlay, higher-priority main
configuration additions/replacements under the selected native policies, nested
import destination inheritance, and repeated inclusion within the default tier.
Confirm that an empty main-file import list does not cancel the underlay imports.
Exercise recursive directory imports with nested files, both YAML extensions,
explicit collection names, and native placement/source attribution. Verify that
file relocation within the imported tree preserves collection selection, and
unknown collection names fail configuration validation. Cover multiple collections
in one file and contributions from multiple files under the selected identity
rules. Do not derive collection keys from filenames or discovery order.
Verify that missing, null, or empty entry IDs fail, and duplicate IDs in a
collection's strict peer sources retain native errors. Cover native matching of
IDs across layers, including whole-record upsert, and final-result validation.
Allow the same ID in different collections and the same displayed name on distinct
records. Verify that changing a term or description while retaining its ID targets
the same collection record, and that runtime spelling deduplication does not
collapse distinct configuration identities. Cover exact case-sensitive ID matching.
Verify required name/category validation and the optional description, aliases,
and plural contracts, including invalid types and empty values where prohibited.
Cover additional scalar, nested mapping, and list fields surviving native loading
and inspection; extension data must not mask invalid known fields. Verify that
unrelated extra fields affect neither the LLM projection nor protected vocabulary.
Exercise native glossary composition, inheritance, collection identity checks,
and supported explicit layering with reusable party/spells fixtures. Cover source
origins and configuration validation failures during loading, then business-rule
failures during Audita preflight before processing.
Test configured discovery/no-main-file behavior through the supported load path;
do not add a secondary glossary-file resolver. Verify that inheritance and
application derivations retain traceability to their configuration inputs.
Verify that distinct valid definitions can contribute to a deduplicated runtime
vocabulary without rewriting rich configured entries. Check that rich LLM input
contains the selected descriptive fields, and that deriving or using any runtime
view leaves configuration and other consumers' views unchanged. Verify the
selected rules for repeated membership and entry ordering: first occurrence of
each `(collection name, id)` wins, while separate records with matching names or
content remain distinct. Verify that deduplicated spellings retain all contributing
entry associations and do not multiply protection requirements. Preserve existing
ambiguous-alias and protected-name repetition behavior outside the selected
active-vocabulary exemption when adapting consumers to these views.
Exercise the selected request and validation overrides through stage consumers,
including independent budgets without changing shared backend admission or the
initial transcript sections. Cover all validation-profile fallback cases above
and preserve the distinction between explicit and derived values in inspection.
Cover partial and empty settings groups, explicit zero and false, nullable
selectors, empty-list replacement, and invalid empty strings or group nulls.
For glossary and protection selections, cover omitted, null, empty, and nonempty
root and stage inputs through ConfigKit resolution. Confirm explicit null and
empty lists suppress defaulting and inheritance while inspection preserves native
provenance. Verify equivalent null/empty behavior in runtime consumers, with no
post-handoff default restoration or configuration resolution. Both forms must
fail Audita preflight when they leave a glossary-correction stage without input.
Verify ConfigKit can hand off empty collections and empty effective selections
and that ordinary inspection remains available. Cover a selected empty collection,
several collectively empty collections, and mixed empty/populated collections.
Include an empty glossary stage late in the pipeline and verify preflight fails
before output resources are created, any stage executes, or processing model
calls occur. Check useful stage and collection attribution in the readiness
error, and no silent stage skipping.
Exercise the preflight package directly with resolved inputs and through the
processing entry point. Verify it leaves configuration unchanged and returns
readiness errors without provider calls or CLI presentation responsibilities.
Exercise CLI list assignment through the standard parser and ConfigKit override
path, including explicit empty selections and unchanged explicit stage settings.
Verify that clearing a validation selection follows the effective proposal
profile without disabling validation, and that clearing a required glossary
fails preflight before execution. Check recorded dependencies and retained
clear-input history as well as effective values. Verify that explicit CLI flags change root
defaults and inherited stage values while preserving explicit stage settings
and clearing. Cover profile fallback after CLI assignment, explicit false/zero/
empty CLI values where valid, and the absence of overrides from parser defaults.
Cover root protection defaulting after CLI assignment, explicit root protection
surviving glossary overrides, and recorded root-to-stage protection dependencies.
Verify module-appropriate protection using terminology from both collections, including
legitimate corrections and cleanup; retain regression coverage for existing
validation behavior outside the selected active-vocabulary exemption.
For glossary stages, verify that active terms are exempt while remaining selected
terms stay protected, including when protection was explicitly configured.
Cover names, aliases, supported plurals, and vocabulary shared across collections.
Verify a spelling contributed by both an active entry and a distinct non-active
protected entry remains exempt regardless of collection order or explicit
protection selection. Check that protected-term validation does not block changes
to that active spelling, while unrelated spellings of the non-active entry remain
protected. Preserve other validators and later stages' independent protection.
Verify the all-active case produces an empty effective protected vocabulary
without disabling other validators. Confirm that a later non-glossary stage
still protects its full selection and that inspection distinguishes configured
protection inputs from the glossary stage's effective protected vocabulary.
Confirm that the durable policy, configuration contracts, and contributor
guidance are in place before declaring this feature complete.

View File

@@ -1,657 +0,0 @@
# Next Major Release Implementation Plan
**Updated:** 2026-11-10
**Status:** Ready for the implementation sprint. This document assigns work;
it does not describe implemented behavior or authorize a release.
Execute the numbered stages in order, one focused assignment per Luna prompt.
Read the named roadmap sections and relevant current contracts before editing.
Use [development guidance](../development.md) and the applicable policies,
especially [agent discipline](../policy/agents.md), [architecture](../policy/architecture.md),
[testing](../policy/testing.md), [documentation](../policy/documentation.md),
[attribution](../policy/oss.md), and [release](../policy/release.md).
The [master roadmap](library-adoption.md) owns the target, selected revisions,
and release requirements. Its child roadmaps own configuration, LLM, CLI, and
glossary behavior. Start from the current implementation: old-path ConfigKit
v0.7.1, PromptKit v0.14.0, ReleaseKit v0.4.1, a standard-library CLI, and one
separately parsed glossary per run. The target is a single hard cutover. Define
final interfaces as work reaches them. Unconverted callers and tests may fail
between stages; do not add transitional parsers, aliases, adapters between
old/new library types, or build-only stubs. Do not make each stage pass the full
suite or require an intermediate release or commit merely to continue. Record
remaining dependent edits at each handoff; run focused checks when their owning
path is available and complete validation at Stage 15.
Follow the selected library behavior where the roadmaps delegate ownership.
Do not turn a useful implementation choice into a new public guarantee or test
requirement. Keep the transcript processing and validator policies outside the
changes expressly selected here. Use existing upstream APIs; if a concrete gap
prevents an agreed result, record the smallest reproducer and affected contract
before proposing an upstream request or local alternative. That is not a new
approval gate for routine work. Use controlled providers for tests. Keep
unrelated [deferred features](future.md) outside the sprint.
## Stage 1: Establish the toolchain and ReleaseKit integration
**Completed.** The existing ConfigKit and PromptKit callers still use their old
module identities; their migration and removal of transitive old dependencies
remain in the following assignments. Final assembled release validation remains
in Stage 15.
Read the [selected modules](library-adoption.md#baseline-and-selected-dependency-set)
and [ReleaseKit contract](library-adoption.md#releasekit-adoption-work). Work in
`go.mod`, `go.sum`, `scripts/release.sh`, `.woodpecker/release.yml`,
`releasekit.json`, and the version wiring in `internal/cli`.
1. Set the source minimum to Go 1.27.0. Use Go 1.27.3 for the validated release
toolchain, matching the review. Select its published Bookworm image for
Woodpecker; if unavailable, choose an available Go 1.27 patch and use it
consistently in the image, runbook, validation, and runtime attribution.
Include the C compiler and cgo prerequisites for the selected race check.
2. Select the exact versions from the master roadmap: ConfigKit v1.2.0,
PromptKit v0.21.0, CommandKit core v0.6.0, ckconfig/ckprompt v0.7.0,
and ReleaseKit v0.9.0, all under `go.maximumdirect.net`.
Move the ReleaseKit runtime `buildinfo`
import and tool registration together. Move ConfigKit/PromptKit consumers in
Stages 2–4. Retire old requirements after their imports disappear; defer
final `go mod tidy` until all real consumers are wired. Prepare dependencies
with `GOWORK=off` and the selected local toolchain. Do not change Audita's
own module major suffix independently of selecting its actual release tag.
3. Adapt the v0.9.0 launcher and tag-delivery recipe linked by the master.
Invoke the full `go.maximumdirect.net/releasekit/cmd/releasekit` tool path
with host GOOS/GOARCH. Preserve tagged-source bootstrap outside the worktree,
Woodpecker variable escaping, annotated-tag peeling, event commit verification,
and `ci-deliver --prepared` with the verified commit. Preserve the actual
remote, product, secret mapping, and Linux amd64/arm64 targets; add
`delivery.forge: "gitea"`. Do not reintroduce comparison with the raw tag SHA.
4. Select the master's native validator settings exactly. Remove generic local
bootstrap/launcher tests covered upstream; retain Audita-specific checks for
product, targets, destination, and version injection. Source publication is
one `publish` after the candidate is pushed to main; `check` is diagnostic.
Keep recovery native and delivery asynchronous. No actual publication here.
Handoff: selected module/tool and workflow wiring, with any not-yet-migrated Go
callers identified. The assembled version and release checks belong to Stage 15.
## Stage 2: Define the v3 application schema and native loader
**Completed.** The native configuration result retains main source and context
evidence. Prompt loading, request clients, command routing, glossary composition,
resolved stage defaults, and processing callers still require the migrations
assigned below; existing unconverted callers and tests may not compile. Final
examples and assembled validation remain assigned later in this plan.
Read the [ConfigKit outline](configkit.md) and glossary
[scope inventory](glossary-stages.md#configuration-scope--resolved). Own
`internal/core/config` and the application-loading portion of
`internal/cli/config_input.go`. Do not implement glossary projection or stage
execution in this stage.
1. Migrate to `go.maximumdirect.net/configkit` and its recorded resolution API.
Build one typed `LoadLayered` path returning the native result (or native
load error), using `File` for an explicitly supplied path and optional
`SearchConfig` with `Searches(WorkingDirectory(), UserConfigDirectory(),
UnixSystemDirectories())` otherwise. Use application name `audita`. An
explicit empty/invalid selection fails; a selected file's failure does not
resume search. Enable imports on operator sources. Leave the actual main
absent on exhaustion and use result source evidence, not guessed paths.
2. Use typed defaults with application version 3 and the main-only version
rule. Reject supplied obsolete, null, or invalid versions with migration
guidance; when no header is supplied, decode against v3 defaults and schema.
Do not require headers on fragments or construct a pretend main source.
Follow the resolved [companion resource base](configkit.md#companion-resource-base-and-overlays--resolved).
Let ConfigKit derive the selected overlay context from the main; leave
`OverlayFilesystem` and `OverlayFallback` unset. Native selection uses
`overlays/<name>.yml` beside the main, with no aggregate `overlays.yml`.
Return recorded main source/context evidence for Stage 3's prompt loader;
no main context means optional companions are skipped, with no CWD fallback.
Use field-named literals for the expanded ConfigKit input/options types.
3. Define the final shape now: global preprocessing/chunking, output,
reporting, and diagnostic-directory settings; root defaults for eligible
stage settings; ordered `pipeline.stages` with `module`, optional `id`,
and stage overrides. Use the existing `thresholds.<module>` root defaults
with a stage-local `confidence_threshold`. Keep field-level `llm`,
`validation`, and `context` groups, and nullable selectors/list values where
the glossary roadmap allows clearing. Use native metadata to distinguish
absent from explicit null or empty. Keep the current default ordered module
sequence expressed as stage records and the existing numeric domain defaults
where the roadmap leaves them unchanged. Do not auto-select profiles or
collections. Stage 10 completes the effective settings callback.
4. Remove `profiles_dir`, the app-owned `backends`/LLM credential configuration,
and `diagnostics.debug` from the new schema. Retain the diagnostic directory
setting; capture comes from the shared CLI boolean. Keep `pipeline.stages`
an ordinary ordered list, including repeated modules and explicit `[]`.
Keep no v2 decoder. Configure shapes for Stage 9 glossary definitions rather
than preserving the old standalone glossary format in the final schema.
5. Apply explicit root overrides through ConfigKit; source composition and
native inheritance/decoding happen first. Keep schema/configuration checks
in the loader, command readiness in preflight, and resource loading out of
configuration validation. Do not reject inspection for lack of a processing
profile, credentials, or populated glossary input.
Evidence: native result/failure and source metadata cover discovery, exhaustion,
selected file errors, imports, overlays, v3 defaults, and changed override order.
Verify selected overlays follow the main directory even with a wider containment
root, and fail without a usable context or named file. Check that the returned
main context supports Stage 3 without another application load.
Exercise final v3 examples after the glossary fields are connected.
## Stage 3: Build the shared PromptKit engine and account for its sources
**Completed.** The engine uses recorded application context and captures
operator source and message paths. Request adapters, role selection, CLI
acquisition, and their older tests still require the following assignments.
The focused engine checks were run independently while those callers remain
unconverted; assembled integration is deferred to the later handoff.
Use the [PromptKit outline](promptkit.md), especially its [automatic source contract](promptkit.md#automatic-prompt-sources--resolved).
Own engine assembly in `internal/framework/llm/runtime.go`,
`source_paths.go`, and embedded assets/registry under `internal/prompts`.
1. Build the engine on the new ConfigKit types. Retain PromptKit's default-on
catalog. Convert all seven embedded prompts to identified list records in
`collections.audita`, with calls using `audita/<local-id>`. Preserve text,
templates, schema references, and resource files. Remove version selection
and descriptive prompt version metadata, without changing response-schema
versions. Keep the embedded schemas supplied through `WithSchemaFS`.
2. Load embedded prompt inputs in their own filesystem underlay. When an
application main context exists, add one higher-priority operator underlay
containing native optional imports of
`prompts.yml` and recursive `prompts/` (`*.yml` and `*.yaml`), with imports
enabled and a concrete context derived from Stage 2's recorded application
main context. Preserve its lookup base, containment, and source accounting.
Both sources compose as strict peers. PromptKit's `MainRelative` refers to
its own main, so do not assume it binds to Audita's separate application load.
Do not feed Audita's document into PromptKit or reload it for its directory.
Without an application main context, omit automatic operator inputs and keep
the bundled/embedded tiers. Overlay selection does not relocate the base.
Use one acquisition path for all engine consumers, without a private parser,
directory walker, filename-derived IDs, or operator-source selector.
3. Use native root resources, collection IDs, sibling inheritance, and whole
same-ID replacement. Remove the generated backend main layer and the
curated profile projection. Preserve helpful classification of bad shipped
assets versus operator source failures using native errors/source evidence
and the existing embedded-only diagnostic where needed. Never execute a
diagnostic fallback engine in place of a failed requested configuration.
4. From captured inspection, collect consumed host source paths and effective
message `content_file` paths for collision checking. Adapt to list-index
coordinates for root and collection resources. Follow effective origins to
the declaring host source and its relative path; handle inherited/moved
evidence and exclude embedded/synthetic sources from host-file collisions.
Reuse native origin evidence and the existing path comparison machinery;
do not rediscover the directory or reopen definitions to reconstruct origins.
Evidence: optional absence, both inputs, nested imports and source-relative
messages, peer conflicts, whole replacement, untouched defaults, and edit/rerun
capture. Exercise explicit/discovered main files elsewhere, independence from
the invocation directory, recorded-context handoff, and absent-main skipping
while embedded resources remain usable. Preserve consumed-source evidence.
## Stage 4: Adapt native requests, role clients, and artifact redaction
**Completed.** Role clients use native prepared execution and retain credential
source names for artifact masking. The old process, runner, and inspection
callers and their tests remain to be migrated in the assignments below. Focused
engine and adapter checks passed; assembled validation remains in Stage 15.
Own `internal/framework/llm`, `structuredoutput`, and request construction in
`proposal_generation` and `validators`. Use the [runtime ownership contract](promptkit.md#backend-and-credential-ownership--resolved)
and [stage budget inventory](glossary-stages.md#configuration-scope--resolved).
1. Replace profile-derived local target plumbing with role clients configured
by explicit profile ID and effective per-operation budgets. Construct clients
against the same captured engine; a caller may select different role clients
per stage. Bind `RunRequest.TransientRetries`, per-call schema and repair
settings, and the logical operation context deadline. Use `PrepareExecution`
and `RunPrepared` on the same handle, discarding unused handles. Retain domain
response validation, observations, and error classification, including
recoverable exhausted operations, fatal setup failures, and parent cancellation.
2. Remove Audita registry/endpoint equality checks, direct key injection,
per-backend secret validation, finite-cap defaults, and local target synthesis.
Native backend/profile fields and null semantics govern execution. Backend
admission settings are engine configuration, not per-request overrides.
The selected ckprompt config scope has no generic `--set` forwarding; do
not add a CLI concurrency flag or a second limiter to supply it.
3. Extract the small shared request helpers needed for prompt IDs, shared
instruction variables, and domain response contracts. Keep the actual
transcript/candidate builders owned by their processing components. Remove
prompt version from logical requests, snapshots, and evidence. Carry native
completed request details only where they have meaning; never relabel
resource inspection as a completed execution target.
4. Preserve artifact/error redaction with native configuration redaction and
Audita's own diagnostic boundary. Replace `ConfiguredSecrets`' dependence
on the deleted backend map: use the selected library's public credential
source metadata, including prepared request information, to mask values from
relevant environment references when required by Audita's artifacts. Reading
a value solely for masking must not choose the credential or reject an
unavailable key during inspection. Keep native prepared/inspection reports
free of resolved keys. Exercise provider errors that echo a synthetic key;
address an actual missing public boundary upstream before adding substantial
credential plumbing. Do not scan or dump the entire environment.
Evidence: local controlled requests prove actual targets, request-specific
budgets, null/zero behavior, credential precedence, shared admission, and
secret-safe failure evidence. Leave stage client selection to Stage 12.
## Stage 5: Install CommandKit routing and native configuration/resource scopes
**Completed.** CommandKit owns routing and native inspection. The typed process
declaration awaits its processing handler, preflight, and later selection flags
as assigned below. Existing process code and earlier parser tests remain to be
reconciled; focused declaration and inspection checks passed independently.
Read [CommandKit operator experience](commandkit.md#agreed-operator-experience)
and the released consumer guide linked there. Replace the routing/parser/inspection
parts of `internal/cli`; keep `cmd/audita` responsible for process lifetime and
streams, not the command declarations.
1. Build the app with CommandKit typed declarations, native help/version and
completion, and ReleaseKit's version accessor as application identity.
Preserve the library outcome status, including native comparison status 3.
Help/version do not load application or engine data. Keep a typed `process`
declaration and wire its final handler in Stage 8. Do not preserve the old
parser as a fallback. Keep `--config`, `--overlay`, and supported application
settings under shared typed loaders with explicit supplied-state handling.
2. Install the `app` scope with `ckconfig.FromConfigKit` or its supported suite
adapter over Stage 2's native result/error. Forward standard `--set` and
comparison-side assignments for this scope only where the loader applies
them. Respect each side's independent selections; no global cached load
across comparison sides. Use native effective values, failure evidence,
path discovery, explanation, sources, comparison, and redaction.
3. Install `ckprompt.ConfigScope(loadEngine)` and the native resource and
requirements callbacks from `ckprompt.FromEngine`. Use shared invocation
acquisition for a selected engine and the Stage 3 loader for every call path.
Install the full standard inventories, namespace selection, scopes, and
inspection features; no duplicate `config print-effective` or custom
profile-summary command. Use the released declarations and their scoped
aliases rather than implementing a separate routing convention.
Evidence: native config and resource commands use the intended scope and
source selection, including failure evidence and no-main discovery. Check
help/version without filesystem/provider setup. Avoid requiring process readiness
for inspection or overriding native grammar or status behavior.
## Stage 6: Enable standard PromptKit request and smoke commands
**Completed.** Native preview, validation, and the complete smoke surface are
installed through the shared loader. Controlled transport checks cover operator
replacement, validator input, explicit smoke, and aggregate smoke. The processing
handler and maintained example projects are assigned below.
Own the remaining `internal/cli` adapters. Use
[the resolved command scope](commandkit.md#request-preview-validation-and-smoke-commands--resolved)
and `WithRequestPreparation`, `WithRequestValidation`, and `WithSmokeTesting`
from ckprompt v0.7.0. Install all capabilities with the Stage 5 declarations.
1. Forward the released native requests, overrides, namespaces, formats, and
outcomes. Use the same engine acquisition as processing. For Audita-owned
prompt IDs, supply shared instruction variables from the Stage 4 helper
only where absent; leave explicit values and generic requests intact.
Use native profile selection, not a guessed stage or automatic role/profile
default. Use native prompt output definitions for generic requests. Document
the inputs needed to preview the maintained Audita fixtures; where an adapter
adds a domain contract, call the same request helper as processing.
2. Validate and preview supplied fixtures without inference, including a
validator candidate fixture. Keep preparation distinct from resource
inspection. Install the entire upstream smoke surface, including aggregate
behavior; smoke runs only on explicit invocation. Do not add startup probes,
custom output shaping, or acceptance requiring a live provider.
Evidence: assembled CLI wiring uses shared operator replacements across
inspection, preview, validation, and controlled smoke. Verify native output and
status handoff without duplicating the upstream command grammar suite.
## Stage 7: Prepare and finalize output resources
**Completed.** Output selection and resource preparation are separate; the
session owns temporary transcript cleanup, report finalization, and optional
debug preparation. Preflight and the process handler must connect these APIs in
the next assignment. Focused diagnostics tests passed.
Own `internal/core/diagnostics/output_session.go`, file/path helpers, and
focused tests. Use the [output preparation](commandkit.md#output-resource-preparation-during-preflight--resolved)
and [failure](commandkit.md#output-failure-behavior--resolved) contracts.
1. Separate pure destination selection/collision validation from resource
preparation. Keep inactive report/debug destinations unprobed. Protect
consumed app/engine files, effective message files, and transcript input
against destructive output collisions. Allow intentional in-place final
transcript replacement. Keep the chosen Audita artifact locations and
destination selection rules where the roadmap does not change them.
2. Prepare an open sibling temporary file for a regular transcript output;
keep the final destination untouched until successful delivery. Publish by
closing and replacing after successful writes, returning any required
write/close/replace failure. Keep special pipe/device destinations direct
and unopened until delivery (including `/dev/null`); stdout uses the caller's
writer, which the session does not close. Do not add new parent-directory
creation, special-file restrictions, or filesystem durability guarantees.
3. Initialize enabled ordinary reports before processing, retaining per-file
`in_progress` publication. Keep debug directory and initial artifact
preparation optional and subsequent artifact creation on demand. On failure
or cancellation clean unpublished temporary resources and owned handles;
retain published files/evidence. Return optional debug problems for redacted
warning presentation rather than marking the run failed solely for that loss.
4. Preserve the primary failure when final reporting or cleanup also fails.
Attempt remaining required reports and failed-status finalization as supported
by the output contract. Do not remove an already published transcript,
repeat model calls, or add a transaction spanning the output bundle.
Evidence: required preparation fails before execution, regular file contents
survive preparation and abort, special files are deferred, and late failures
retain already published output and primary failure details.
## Stage 8: Wire processing, common preflight, and reporting modes
**Completed.** Processing now acquires typed inputs, prepares outputs, and
finalizes through CommandKit. The `executePipeline` handoff is intentionally
implemented with the ordered runner work below; until then the application and
unconverted tests do not build. The handler was checked with a controlled runner
boundary; later readiness checks and assembled validation remain assigned below.
Own `internal/cli/process.go` and the new `internal/framework/preflight`.
Use the [named preflight boundary](glossary-stages.md#empty-collections-and-audita-preflight--resolved)
and the [CommandKit reporting decisions](commandkit.md#debug-reporting-and-artifact-capture--resolved).
1. Bind `process` with typed inputs, one transcript operand, `--output`, and
explicitly supplied root overrides for retained settings. Use the shared
`BoolFlag` named `debug` with false default; preserve its boolean for capture
independently of `Invocation.ReportingMode()`. Do not parse raw argv or
map quiet/verbose to the capture bit. Keep `--work-dir` a directory selection
only. Do not re-declare `--glossary` or `--modules` when replacing the parser;
Stage 10 supplies glossary selection inputs and pipeline order lives in v3 YAML.
2. Resolve app settings and engine inputs and acquire transcript data using the
owning loaders. Use the final runner/preflight interfaces, with the
stage-specific input additions in Stages 9–12. Preflight takes resolved
inputs and ordinary Go dependencies; no CLI, provider transport, config
reload, or generic check framework. Check all invocation/readiness conditions
and active collisions before output preparation. Have it coordinate the
output session from Stage 7; the session owns filesystem resources.
3. Before creating artifacts or starting model work, reject effective quiet plus
stdout (including omitted/empty `--output`) with a usage explanation and a
file or `/dev/null` remedy. Use the actual resolved mode, including ordering
and aliases. Help/inspection do not take this processing path. Validate only
selected processing requirements; native credential availability remains a
request-time concern, not an eager all-backend check.
4. Dispatch after required preparation, then finalize required outputs and
return a native CommandKit outcome. Use the supplied raw output writer for
transcript bytes. Emit the summary and created locations as Info/deferred
Info only after successful required delivery; ordinary and quiet modes hide
it. Send redacted optional debug failures as native warnings. Keep stream
write failures under CommandKit's native outcome handling; domain model
recoveries and work-unit errors do not become automatic command failures.
Evidence: actual process integration proves quiet/verbose/debug behavior,
required failure versus optional debug loss, and stdout isolation. Reuse the
roadmap's selected flag combinations; avoid retesting the full upstream parser.
## Stage 9: Compose and validate native glossary definitions
**Completed.** Typed glossary definitions use native identified collection
composition and main-relative optional imports. Application source evidence
includes consumed glossary files; selection resolution and runtime consumers
remain assigned below. Focused configuration tests passed.
Own the glossary definition types and application load inputs. Read
[glossary ownership and named collections](glossary-stages.md#glossary-configuration-ownership--resolved)
through its default-source and entry-contract sections.
1. Define `glossary_collections` as a typed mapping with ordered `entries`.
Register `SequenceIdentityMatching` for the collection mapping wildcard and
`entries` destination, with literal `id` identity. Use typed known entry
fields and a native inline string-keyed map for extension values. Enforce
the selected entry fields without slug restrictions, global ID uniqueness,
or validation of arbitrary extension contents.
2. Add one application underlay with optional native `glossary.yml` and
recursive `glossary/` imports mounted at `glossary_collections`. Use a
non-file input with imports enabled and `MainRelative: configkit.MainRelative()`
so ConfigKit binds it to the selected application main during the same load.
Supply no fallback; absent main context skips the optional imports. Preserve
peer conflicts, nested relative imports and placement,
source attribution, and native cross-tier whole-record upsert. Do not use
filename identity, a private walker, or infer that main `imports: []`
cancels the application underlay. Use the separate PromptKit underlay for
prompt resources, not this application glossary tier.
3. Validate definition contracts with ConfigKit and allow empty definitions.
Retain complete typed entries for inspection, including extension data.
Capture consumed glossary source paths through the application result for
Stage 8's collision checks. Remove the legacy glossary input/parser path
as consumers move to the typed handoff in Stages 10–12; no parallel loader.
Evidence: representative native peers, layering, collection-scoped identities,
recursion, source placement, extension values, and optional absence with both
explicit and absent main configuration. Test integration, not native grammar again.
## Stage 10: Resolve stage settings and native CLI selection inputs
**Completed.** ConfigKit records root and per-entry defaults, explicit clears,
validation-profile fallback, and dependencies. Typed JSON list flags feed root
overrides. Vocabulary derivation and the ordered runner remain assigned below;
focused loader and command checks passed with a controlled runner boundary.
Own `internal/core/config` resolution and the matching process flag bindings.
Use [stage scope](glossary-stages.md#configuration-scope--resolved),
[clearing](glossary-stages.md#compound-values-and-explicit-clearing--resolved), and
[CLI precedence](glossary-stages.md#cli-overrides-and-stage-precedence--resolved).
1. In `Definition.Resolve`, use `IsExplicit` and `EntryInfo` at real key/index
paths, after root CLI assignment. Derive omitted root protection from a
detached root glossary list with a recorded dependency. Copy the effective
root values into each omitted eligible stage field independently, using
`configkit.Default` and root dependencies. Preserve explicit false, zero,
empty description, `[]`, and null according to the field contract. A partial
group contributes only its children; reject group nulls natively.
2. Apply validation-profile fallback only after combining root and stage values.
Preserve explicit root validation selections, stage replacement, and stage
null clearing. Assign the effective stage proposal profile when no validation
selection remains; record the dependency with `RecordDerivedDefault` for
an explicit null. Do not mistake a derived fallback for an explicit root value.
Record at actual list-field paths, not the whole stage merely to cover a
mutation. Copy mutable values so stages do not share their settings storage.
3. Validate known modules, known selected collection names, effective per-field
settings, and supplied IDs (nonempty, exact, unique; absence valid) through
ConfigKit. Do not register the stage list as an identified collection. Do
not make a root validation selection empty string a synonym for null. Preserve
nullable selectors in the handoff; runtime treats a nil list as empty and
never restores a default. Leave glossary nonempty and required processing
profile readiness to preflight.
4. Bind `--glossaries` and `--protected-terms` as single typed list values using
CommandKit `ValueFlag` and `ParseCLIJSON`, accepting an array of names or
`null`. Send one ConfigKit override per supplied root field; `[]` clears
and omission contributes no override. Use the same native JSON semantics
as ckconfig `--set`. Keep other existing root setting flags whose fields
survive, with CommandKit supplied-state tracking. Remove `--glossary` and
`--modules`; set pipeline order in YAML. Do not implement indexed/ID-targeted
CLI edits or introduce another list-clearing grammar.
Evidence: native inspection shows copied root dependencies and explicit clears;
CLI root changes affect only inheriting stage fields. Check the roadmap's
validation-profile fallback cases and meaningful explicit-value distinctions.
## Stage 11: Derive stage vocabulary and adapt its consumers
**Completed.** Rich context and independent, identity-aware protection views
are available to prompt, validation, and application consumers. The ordered
runner must supply those views and the application check in the next assignment;
older caller tests remain to be reconciled during the assembled cutover. Focused
projection, validator, and application checks passed.
Own the glossary-domain projection and the consumers in `internal/modules`,
`internal/validators`, and `internal/framework/proposals`. Use the
[derived views](glossary-stages.md#derived-runtime-representations--resolved)
and [ordering and protection](glossary-stages.md#runtime-vocabulary-and-ordering--resolved)
contracts.
1. Traverse selected collections then their resolved entries in order. Build
rich prompt data from known fields only, retaining first occurrence per
`(collection, id)` and all distinct entries. Do not forward extension
fields or collapse entries by display name. Derive matching vocabulary from
names, aliases, and plurals using existing matcher rules. Deduplicate
spellings while retaining contributing identities for domain checks.
2. Derive protection independently from the selected `protected_terms`. For a
glossary-correction stage subtract active recognized spellings, even when
another protected entry contributes that same spelling. Preserve unrelated
aliases and plurals of non-active entries. Keep configured selections and
entries intact; other stages get independently derived views. Preserve
ambiguous-alias handling, protected-name repetition policy, and other
existing validation business logic outside the selected exemption.
3. Pass the appropriate rich and protection views to module prompts, local
validation, and apply-time protection. Inspect downstream checks so none
reconstructs full protection from the former combined glossary. Non-glossary
modules use their selected context and full protection; empty protection
does not disable other validators. Reuse narrow consumer representations;
no generic runtime glossary merge engine.
Evidence: shared-spelling exemption plus unaffected spellings, ordered rich
input with separate identities, and no mutation/leakage between stage views.
Use controlled candidates for both permitted edits and still-protected cases.
## Stage 12: Execute the ordered effective stages and extend preflight
**Completed.** The resolved pipeline supplies independent settings, vocabulary,
and role clients to sequential execution; readiness and output checks precede
work. Controlled processing covers carried-forward edits, distinct models,
recoverable failures, an empty pipeline, and a late empty glossary. Older tests
and stage-level attribution and artifacts remain for the following assignments.
Own runner/contracts and the processing handoff. Connect Stages 4, 8, 10, and
11 in `internal/framework/runner`, `contracts`, `preflight`, and `internal/cli`.
1. Convert the fully resolved typed list to ordered run specs carrying effective
settings and vocabulary, module key, position, and optional ID. Preserve
separate execution identity even for repeated modules. Create the stage's
role clients from the shared engine and selected effective profiles/budgets;
pass its own batching budget, threshold, context, and views to consumers.
Do not rebuild/mutate backend settings per stage or re-resolve configuration
during execution. Remove the old single-glossary and global role/budget wiring.
2. Extend preflight to check every selected glossary-correction stage for at
least one effective rich entry, including later stages. Keep empty definitions
and inspection valid; an empty protection set is valid. Report stage position,
module, optional ID, and selected collection names when unready. Check needed
selected roles without synthetic requests or provider calls; a deliberately
empty pipeline needs no processing model selection. Finish all readiness and
collision checks before preparing outputs or dispatching work.
3. Normalize and chunk once for the invocation. Run stages in order on the
preceding stage's resulting transcript with fixed sections and deterministic
proposal/apply/report order. Keep the existing fatal cancellation/join and
recoverable local failure behavior, including normalized output when every
model work unit fails recoverably. Preserve domain schemas, validation, and
meaningful partial success; no rechunking or parallel stage traversal.
Evidence: party/spell/grammar controlled workflow, with the second stage seeing
prior edits and independent vocabulary/role settings. Verify late empty-stage
failure before outputs/model work and a valid no-stage normalization run.
## Stage 13: Carry stage identity through ordinary and debug evidence
**Completed.** Machine records carry execution position and optional operator ID;
human labels include position, module, and the ID when supplied. Controlled
processing and focused report checks cover repeated and unnamed entries, escaped
labels, debug evidence, recoveries, failures, and unavailable candidates.
Own `internal/framework/outcomes`, `processreport`, `structuredoutput` call
context, and `internal/core/reporting`. Use the [stage attribution contract](glossary-stages.md#stage-identity-and-attribution--resolved).
1. Carry stage index/module and optional `stage_id` through work units, error and
recovery records, correction ledger, LLM call evidence, and debug snapshots.
Keep zero-based `stage_index` in machine records; show one-based position in
human labels. Use the operator ID for labels when present, with position and
module available, otherwise identify by position/module. Keep internal and
artifact path identities based on safe generated stage coordinates; do not
treat arbitrary valid user IDs as paths or require a slug format.
2. Preserve the three ordinary files, status semantics, counts, and matrices in
execution order. Add optional attribution fields to the existing schema rather
than create a new reporting system. Escape labels for their output format.
Keep errors/recoveries distinct from CommandKit reporter categories and debug
evidence. Do not add raw prompts, provider causes, or credentials to ordinary
reports. Ensure finalization and summary use the same run facts.
Evidence: named/unnamed/repeated/reordered stages can be distinguished in real
reports and debug artifacts without changing stage order or collapsing records.
Verify existing partial-success and unavailable-candidate evidence survives.
## Stage 14: Finish the cutover documentation, examples, and attribution
**Completed.** Canonical guidance, the decision record, migration guide,
maintained projects, release procedure, and dependency attribution reflect the
cutover. Controlled-provider project checks and documented offline inspections
passed; historical example links point to the unchanged v3.0.0 tag.
Update canonical owners as behavior lands; use this stage to reconcile them.
Follow the [documentation policy](../policy/documentation.md) and glossary
[durable record](glossary-stages.md#durable-decision-record).
1. Update `docs/config.md`, `docs/cli.md`, `docs/operations.md`, affected
integration contracts and internal docs, `docs/development.md`, and README.
Explain v3 application discovery, native resource sources, role/stage scope,
preflight/output lifecycle, shared debug and quiet behavior, and the operator
cutover in `docs/migrations/v3.md`. Link to the adopted upstream CLI reference
for standard commands rather than duplicating their syntax, caveats, or
provider warnings. Describe Audita-specific inputs and effects locally.
2. Reconcile architecture policy with native resource/credential/admission and
CLI ownership, recorded config resolution, and the preflight boundary.
Add `docs/adr/0002-glossary-configuration-and-preflight.md` in Nygard format
for glossary ownership, typed handoff, and output-session coordination.
Index it; do not rewrite
the accepted ReleaseKit ADR. Retain ordinary domain guarantees selected by
the roadmaps, with no new compatibility or performance promises.
3. Replace retired examples with maintained v3 projects: a minimal local run,
a service/profile/overlay example, the embedded-prompt edit-and-rerun flow,
a validator preview fixture, and two campaigns consuming a common glossary
library. Run examples from the documented directory so automatic inputs and
overlay context are accurate. Keep example values synthetic and cover their
integration with controlled providers. Remove old backend/glossary layouts
and obsolete parser-only tests, preserving substantive domain regressions.
4. Align `docs/release.md` and release policy with the selected v0.9.0 workflow,
validators and rationale, supported platform/toolchain choices, and native
recovery. Update `docs/oss/attribution.md` for exact selected sources,
incorporated material and toolchain dependencies; retire old catalog notices
when no longer incorporated. Reuse applicable standard license texts, not
upstream policy inventories. Preserve existing release tags and notes.
Evidence: all examples, canonical contracts, ADR, and notices describe the
assembled target. No publication, new release note, or version tag is required
in the real repository during this sprint.
## Stage 15: Verify the assembled target and hand it off
**Completed.** The assembled candidate passed the selected ReleaseKit checks
with Go 1.27.3 in a clean disposable repository. A separate annotated-tag
fixture exercised the checked-in delivery workflow against a local mock,
including both Linux assets, checksums, and rejection of a mismatched commit.
Hosted delivery and source publication remain separate.
1. Run `go mod tidy` under the selected toolchain with `GOWORK=off`; inspect the
selected module graph, imports, tool registrations, and attribution together.
Confirm no old library identities, committed workspace files, or filesystem
replacements remain. Review removal of superseded loaders, parser, registry,
curated summary, and release plumbing. Update or remove assertions protecting
obsolete behavior; do not compensate with a deletion quota or blanket tests.
2. Finish any focused integration cases from the earlier stages. Use real loaders
and controlled transports; concentrate on native integration, stage isolation,
source safety, failure handling, and operator-visible behavior. Check link and
example references. Reuse already completed checks on the same final tree.
3. Use the adopted ReleaseKit `check` for assembled validation. It needs a clean
committed candidate on `main` and a matching checked-in release note. If the
actual release version is not selected, make a disposable copy on `main`,
add a temporary matching note for an unused validation version compatible
with the module path, and commit that copy. Run `scripts/release.sh check
VERSION` there. Keep this fixture outside the Audita worktree. This check
supplies the selected offline race suite, vet, formatting, Markdown and
module checks, Linux amd64/arm64 builds, and native version identity; do
not require a duplicate full run on the same source solely for handoff.
4. Exercise Audita's tag-delivery wiring with a disposable annotated tag and
controlled destination/fixtures: check the clone/event commit, native tool
bootstrap and `ci-deliver` handoff, and product/target/asset settings. Use
upstream delivery coverage rather than recreating generic forge tests. Use
synthetic authentication for local fixtures; do not use production delivery
credentials, push a tag, or publish to the hosted release service.
Report the evidence and any live-delivery limit accurately. Neither hosted
availability nor CI completion is a new release gate.
5. Check completion against each child roadmap and the master's target. Report
implementation checks, remaining upstream issues if any, and the resulting
workspace/commit state under agent policy. Release preparation, including
actual major tag/module-path selection, checked-in release notes, and source
publication, remains separate. Do not claim implementation completion on
the basis of the earlier library probes or any unresolved required behavior.

View File

@@ -1,259 +0,0 @@
# Next Major Release Roadmap
**Updated:** 2026-11-10
**Status:** Target decisions are recorded across this roadmap and its four child
roadmaps; the implementation and selected dependency changes are complete. The
[implementation plan](implementation.md) owns the sprint sequence.
## Objective and Document Ownership
Align Audita with the supported happy path of ConfigKit, PromptKit, CommandKit,
and ReleaseKit so operators and maintainers encounter the same conventions
across the application suite. Choose the best target state for Audita; maintaining
compatibility with current behavior carries no weight in this major release.
The release also includes reusable glossary configuration composed through
ConfigKit and stages that select different glossary inputs. This is required
feature scope alongside the library upgrades; the glossary roadmap owns the
configuration handoff and derived runtime representations.
This document owns shared adoption principles, dependency selection, and
cross-library decisions, including the ReleaseKit target below. The linked
outlines own feature-specific outcomes and acceptance criteria:
| Outline | Responsibility |
| --- | --- |
| [ConfigKit](configkit.md) | Stable configuration API, loading, discovery, presence, secrets, and provenance |
| [PromptKit](promptkit.md) | Native resources and bundled catalog, role integration, execution, and source accounting |
| [CommandKit](commandkit.md) | Standard operator interface, configuration commands, full ckprompt inspection, and reporting |
| [Stage-Specific Glossary Inputs](glossary-stages.md) | Reusable glossary configuration, stage selections, and derived runtime vocabulary |
This master roadmap and the three library outlines replace the removed
`import-upgrade.md`. They retain its relevant technical evidence but supersede
its recommendations to disable the OpenRouter bundle, defer CommandKit adoption,
limit standard inspection, or
preserve Audita's backend ownership restrictions without a domain justification.
They do not select unrelated work in [future.md](future.md).
## Agreed Adoption Principles
- **ConfigKit:** fully adopt and adapt to its stable public API and native
conventions. Diverge only where an identified Audita requirement makes it
necessary; a local convenience is not sufficient justification.
- **PromptKit:** follow the mature library's supported path, including its
bundled OpenRouter backend and profiles. Significant blockers or pain points
may justify a focused upstream feature request before adding substantial local
integration machinery.
- **CommandKit and integrations:** adopt the standard suite experience, including
the full ckprompt inspection command set. The libraries are young; problematic
or incomplete behavior is a candidate for an upstream change request rather
than a permanent Audita workaround. For standard commands passed through by
Audita, link concisely to upstream documentation instead of maintaining a local
reference, warnings, or caveats about upstream capabilities. Document Audita's
own inputs, wiring, and domain-specific behavior.
- **ReleaseKit:** adopt `go.maximumdirect.net/releasekit` v0.9.0 and move as much
release machinery upstream as possible. Audita may select any number of
ReleaseKit-owned validators. Retain local release validation only with a
documented domain-specific justification. Treat its maturity as broadly
similar to PromptKit, though somewhat lower; significant gaps are candidates
for focused upstream requests.
- **Major-release cutover:** old configuration, CLI, output, and release-workflow
behavior impose no compatibility requirement. Do not add compatibility aliases,
dual formats, transition modes, or legacy-behavior tests merely to ease adoption.
Release guidance may require a hard cutover. Domain requirements still guide
the target, but existing implementations and contracts are open to redesign.
Audita's application configuration uses `version: 3` with a hard cutover, as
resolved in the [ConfigKit outline](configkit.md#application-schema-version--resolved).
- **Remove redundant code:** reducing Audita's maintenance burden is an explicit
adoption goal. Retire local mechanisms, settings, wrappers, and tests superseded
by supported upstream behavior. Keep the domain logic and integration code that
Audita needs; retaining existing code is not a success criterion.
- Audita continues to own transcript formats, correction ordering, domain
validation, structured-response contracts, and truthful partial-success
behavior. Inspect each other restriction against a concrete domain need.
- Standard library inspection and native redaction are part of the target.
Retire the curated profile summary in favor of the standard inspection and
preview interfaces, as resolved in the [PromptKit outline](promptkit.md).
For each friction point, record the desired outcome, whether the constraint is
library behavior or an Audita domain requirement, the proposed adaptation or
upstream request, and its acceptance evidence. Distinguish agreed decisions from
recommendations. The [CommandKit outline](commandkit.md#upstream-review-shared-debug-input-and-reporting-mode)
records the released reporting capabilities and adoption evidence.
## Baseline and Selected Dependency Set
The reviewed application revision is
`cbcb1b3778d747ced7825d09d9e7536cabc0f0fa`. Its [module file](../../go.mod)
uses old-path ConfigKit v0.7.1 and PromptKit v0.14.0, with no CommandKit.
The source minimum is Go 1.26.0; the release runbook selects Go 1.26.8.
The following published versions are selected for adoption. The reviewed set
uses CommandKit core v0.6.0 with both integrations at v0.7.0. The CommandKit
and main-relative ConfigKit availability gates are satisfied:
| Module | Version | Reviewed source commit |
| --- | --- | --- |
| `go.maximumdirect.net/configkit` | v1.2.0 | `c1c7e87f2cdf77a0cbf3327831ac05578e756b9e` |
| `go.maximumdirect.net/promptkit` | v0.21.0 | `171fb11f4e967a1da3af57843c6467954b14ba09` |
| `go.maximumdirect.net/commandkit` | v0.6.0 | `1613ff95cab60581de5d86f6e9e2a3cc091a44a0` |
| `go.maximumdirect.net/ckconfig` | v0.7.0 | `64f6453b8453f914f272d427bb4ae6f59deacd2b` |
| `go.maximumdirect.net/ckprompt` | v0.7.0 | `f369d6a78253b6e6fcb1e023fb2e9c3af1d20ff0` |
| `go.maximumdirect.net/releasekit` | v0.9.0 | `2180aa868ec2caa95fc8279fd59d5f0ebac41bd4` |
The integration tags are `integrations/ckconfig/v0.7.0` and
`integrations/ckprompt/v0.7.0` in CommandKit's repository. Use the
[released module selection guide](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/f369d6a78253b6e6fcb1e023fb2e9c3af1d20ff0/docs/consumers/guide.md#module-selection).
The integrations select ConfigKit v1.2.0 and PromptKit v0.21.0. The combined
consumer minimum is Go 1.27.0. Use field-named ConfigKit struct literals for the
new input and layered-option fields. Changes to these selected versions require
an ordinary compatibility review rather than assuming later releases are
interchangeable.
**CommandKit release gate — satisfied:** the published v0.6.0 core provides both
the independent shared debug binding for capture and the resolved reporting-mode
accessor for quiet destination validation. The matching released integrations
were reviewed together. The [CommandKit outline](commandkit.md#adoption-gate-released-debug-binding-and-reporting-mode-access)
records the API contract and review evidence. The selected release set removes
the upstream availability blocker; Audita implementation and acceptance are
complete under the [implementation plan](implementation.md).
**Main-relative loading gate — satisfied:** ConfigKit v1.2.0 implements the
requested companion import binding and derived layered-overlay context. Follow
the [shared resource-base decision](configkit.md#companion-resource-base-and-overlays--resolved).
Load application configuration first, construct PromptKit using its recorded
context, then expose both through the CommandKit integrations. Glossary-stage
execution follows the library foundations; the implementation plan retains that
order. No preliminary discovery/load pass or local directory walker is needed.
The reviewed target dependency graph includes ReleaseKit v0.9.0, but Audita's
direct tool still uses old-path v0.4.1. The release, workflow, and validator review
is complete, with no identified upstream blocker. The agreed
[ReleaseKit adoption work](#releasekit-adoption-work) below remains to be
implemented and accepted in Audita.
## ReleaseKit Adoption Work
### Workflow and Validator Selection — Resolved
Adopt ReleaseKit v0.9.0's standard publication and asynchronous delivery workflow.
This implements the ownership decision in [ADR 0001](../adr/0001-releasekit.md).
Audita already delegates publication, builds, and delivery to ReleaseKit; the
upgrade modernizes that integration and removes duplicated generic tests. No
additional Audita-owned release validator or upstream feature request is needed
for the reviewed requirements. Audita's domain tests remain in the ordinary
offline suite executed by ReleaseKit.
The selected workflow is:
1. Prepare the release note and final committed candidate, then push that
candidate to the authoritative `main` branch.
2. Use one ReleaseKit `publish` invocation to validate the candidate, check the
required builds and version identity, and publish the annotated tag. Keep
`check` available for diagnosis; do not require it before `publish` repeats
validation.
3. Use the maintained Woodpecker tag-delivery workflow to invoke `ci-deliver`
from the tagged source. Deliver the hosted release page, Linux amd64 and arm64
binaries, and checksums asynchronously. Successful tag publication completes
the source release; report artifact delivery separately.
4. Use ReleaseKit's standard recovery commands and procedures for publication
and delivery failures, without a separate Audita recovery layer.
Use the reviewed upstream [publication guide](https://forge.maximumdirect.net/base-layer/releasekit/src/tag/v0.9.0/docs/consumers/publish.md),
[delivery guide](https://forge.maximumdirect.net/base-layer/releasekit/src/tag/v0.9.0/docs/consumers/delivery.md),
and [configuration reference](https://forge.maximumdirect.net/base-layer/releasekit/src/tag/v0.9.0/docs/config.md)
for standard behavior. Select these checks through the native release profile:
| Capability | Selection | Reason |
| --- | --- | --- |
| Standard offline Go test suite and candidate/publication guards | Retain ReleaseKit's built-in checks | Validate Audita's behavior and the exact source being published. |
| Race detection | `validation.go.race: true` | Audita's concurrent processing and cancellation warrant race detection in the single standard suite. |
| Full Go vet | `validation.go.full_vet: true` | Add static checks; ReleaseKit disables test-time vet to avoid duplication. |
| Go formatting | `validation.go_format: true` | Enforce consistent formatting through the shared implementation. |
| Local Markdown links and heading references | `validation.markdown: {}` | Protect documentation navigation using upstream defaults. |
| Committed workspace files | `validation.module_distribution.workspace_files: true` | Keep development workspace files out of releases. |
| Filesystem module replacements | `validation.module_distribution.local_replacements: true` | Prevent releases depending on local dependency checkouts. |
| Application builds and version identity | Retain `build.targets` for `linux/amd64` and `linux/arm64`, with ReleaseKit's native version check | Verify the required production binaries and their embedded version. |
| Additional compile-only targets | Omit `validation.go.compile_targets` initially | Limited additional value alongside the required application builds. |
| File-size limits | Omit `validation.file_size` initially | No application-specific size ceiling has been selected. |
| Forbidden-file paths | Omit `validation.forbidden_files` initially | Delivery uses the existing CI secret; no release-token file is configured. |
Do not duplicate these checks in profile `checks`, custom release hooks, or
surrounding scripts. Any future local release validator requires a documented
domain-specific justification; reusable gaps should be addressed upstream.
### Release Integration Acceptance
The direct tool and runtime version accessor use the same v0.9.0 module identity.
The launcher and Woodpecker bootstrap follow the v0.9.0
[adoption recipes](https://forge.maximumdirect.net/base-layer/releasekit/src/tag/v0.9.0/docs/consumers/adoption.md)
and [tag-delivery template](https://forge.maximumdirect.net/base-layer/releasekit/src/tag/v0.9.0/examples/woodpecker/tag-delivery.yml),
including host target selection, full tool-package invocation, and prepared tag
checkout verification. Audita retains its product, Linux production targets,
delivery destination, and CI secret mapping, with `delivery.forge: "gitea"`.
Local validation and CI use the selected Go 1.27-or-newer toolchain; maintainer
setup includes the C compiler and cgo prerequisites for race detection.
ReleaseKit owns generic bootstrap, launcher, and selected native validation
mechanisms. Audita retains focused evidence for its product settings, targets,
destination, and version integration. Acceptance covers the selected validators,
both production builds, version identity, and assembled launcher/CI wiring,
without publishing a release. The disposable local check below is evidence for
local candidate validation and does not establish hosted delivery. Adopted policy
and runbook describe the selected workflow, validator rationale, and native recovery.
## Shared Evidence, Validation, and Completion
The review verified release identities, requirements, and relevant upstream
contracts. On 2026-11-10, published tags matched the selected commits above.
All packages in the four newly selected releases passed their tagged suites with
Go 1.27.3, `GOWORK=off`, and no local replacements; two PromptKit packages needed
local HTTP test listeners permitted. The ckprompt module graph selected exactly
the ConfigKit, PromptKit, ckconfig, and core versions above. Upstream coverage
includes companion discovery, optional file/directory combinations, precedence,
absent-main handling, and prompt content-file context.
Earlier disposable checks using Go 1.27.3 established:
- Audita's existing core configuration tests pass after import/API adaptation;
the application build still fails at the expected PromptKit API changes.
- CLI parent overrides do not rerun ConfigKit inheritance. PromptKit same-ID
replacement drops omitted provider settings; distinct native inheritance can
retain them. Profile null endpoints permit backend fallback.
- Tagged CommandKit core, ckconfig, and ckprompt v0.6.0 suites pass independently
with released dependencies, `GOWORK=off`, and no local replacements.
- A separate consumer of all three published v0.6.0 modules passes 33 cases
covering debug capture, reporting-mode ordering, aliases, and quiet transcript
destination validation. That earlier graph selected ConfigKit v1.1.0 and
PromptKit v0.20.0 and brought in ReleaseKit v0.9.0.
- A disposable Audita copy with the ReleaseKit tool and runtime version import
migrated to v0.9.0, and toolchain references aligned, passes the selected native
validators, Linux amd64 and arm64 builds, and the native version-output check.
This exercised local `check` only; no release was published and hosted delivery
was not exercised.
These are review results, not implementation acceptance. They involved no live
provider calls and do not prove migrated Audita behavior or cross-platform
execution. Use controlled provider boundaries and proportionate tests under
[testing policy](../policy/testing.md); live diagnostics are not release gates.
Completion requires all four library adoption targets, stage-specific glossary
inputs, resolved decisions, migrated examples, useful native inspection, the
selected domain behavior, a passing assembled application, and the adopted
ReleaseKit workflow. Every retained local
release validator must have a domain-specific justification. Acceptance tests
must assert the target contracts; update or remove tests whose sole purpose is
preserving superseded behavior. Upstream requests need an explicit disposition
before calling the dependent behavior complete. Any temporary workaround must
name its reason and removal condition; it is not architecture by default.
Completion also includes retiring superseded local machinery and its obsolete
configuration, documentation, and tests. Preserve evidence for the selected
domain behavior and real integration boundaries without duplicating upstream
implementation tests. Code removal is a desired result, with no deletion quota.
Refresh [attribution](../oss/attribution.md) for the exact selected dependencies
and toolchain under [OSS policy](../policy/oss.md). The reviewed library grants
remain LGPL-3.0-or-later; remove old catalog entries when no longer incorporated
and retain shared license texts. Do not copy upstream policy inventories.

View File

@@ -1,285 +0,0 @@
# PromptKit Adoption Outline
**Updated:** 2026-11-10
**Status:** Adoption direction and automatic operator-source selection resolved;
implementation is complete. Follow the [master roadmap](library-adoption.md)
for shared adoption principles and dependency identities, and the
[implementation plan](implementation.md) for sequencing.
## Baseline and Target
Before this work, Audita used PromptKit v0.14.0. Its
[LLM runtime](../internal/llm-runtime.md) uses a shared engine, application-owned
backend overrides, curated profile inspection, and prepared execution.
Adopt PromptKit v0.21.0 through its native configuration and execution APIs.
Retain the built-in OpenRouter backend and bundled profiles. They must be usable
through the normal selection and credential mechanisms, not merely visible in
an inventory while Audita rejects them for lacking a duplicate registration.
Expose native resource and configuration inspection through the full standard
ckprompt surface described in the [CommandKit outline](commandkit.md).
PromptKit owns resources, composition, provider settings and credentials,
preparation, transport, structural repair, and backend admission. Audita owns
proposal/validation role selection, transcript processing, domain decisions,
response contracts, and truthful partial-success reporting. Remove the existing
application-only endpoint and credential restrictions as described below.
Use the pinned [migration guide](https://forge.maximumdirect.net/base-layer/promptkit/src/commit/171fb11f4e967a1da3af57843c6467954b14ba09/docs/consumers/configuration-migration.md),
[format reference](https://forge.maximumdirect.net/base-layer/promptkit/src/commit/171fb11f4e967a1da3af57843c6467954b14ba09/docs/formats.md),
and [v0.21 release notes](https://forge.maximumdirect.net/base-layer/promptkit/src/commit/171fb11f4e967a1da3af57843c6467954b14ba09/docs/releases/v0.21.0.md).
The bundle is default-on; older migration prose about catalog removal does not
mean the current release has no bundled resources. It does not select an implicit
execution profile or make provider calls during construction.
## Agreed Direction and Migration Work
### Backend Concurrency Ownership — Resolved
Adopt PromptKit's native per-backend concurrency behavior, including backend
defaults and native configuration. The purpose is to keep
requests within the concurrency a backend can accommodate; no separate Audita
domain requirement has been identified for an additional limit.
Remove Audita-owned concurrency settings, default injection, validation, and
enforcement wherever they duplicate or override that native behavior. Do not
retain a second limiter or impose an Audita-specific finite-cap requirement on
otherwise valid PromptKit configuration. Use the shared PromptKit engine so
proposal and validation work for the same backend share its admission control.
Audita still owns cancellation and deterministic processing around model calls.
The selected PromptKit configuration scope does not forward ConfigKit CLI
overrides, and request overrides do not set concurrency. Configure limits on
native backend resources. Architecture policy, runtime documentation, examples,
and tests describe the adopted ownership and hard cutover.
### Backend and Credential Ownership — Resolved
Native PromptKit backend/profile resources are authoritative for endpoints,
provider settings, and credential selection. No domain-specific requirement has
been identified for a separate Audita ownership policy.
- Remove Audita's separate `backends` mapping and generated backend override
layer. Remove duplicate registration requirements and checks that force profile
endpoints to match an Audita-owned backend endpoint. Native selection and
validation govern bundled and operator-defined resources.
- Use PromptKit's native credential sources and precedence. Remove Audita's
LLM-specific credential references, automatic direct-key injection, and
rejection of profile-level environment lookups. Backend/profile documents
contain environment-variable names, not credential values; operators may use
the bundled OpenRouter lookup or configure their own names.
- Follow native credential availability timing. Loading and resource inspection
must not require credentials for every configured backend. Preparation and
execution enforce the selected request's native required/optional semantics:
missing optional credentials permit unauthenticated requests. Do not add an
eager all-backend credential check or silently strengthen those semantics.
Audita retains role/profile selection, operation budgets, domain request
construction, response contracts, and safe handling of its reports and debug artifacts. Native
configuration redaction does not replace redaction at Audita's artifact boundary.
Keep preparing and executing the same captured request while retiring target
checks whose purpose was enforcing the removed application backend registry.
Remove superseded fields, code, and tests in the major-release cutover and update
the affected policies and current contracts with implementation. The ConfigKit
outline owns Audita main-file discovery and general import policy; this outline
owns the automatic PromptKit source selection below. PromptKit retains resource
semantics under both policies.
### Bundled Prompts and Operator Replacements — Resolved
Ship Audita's production default prompt definitions in `embed.FS`, exposed as
`io/fs.FS`. Load them through PromptKit's filesystem inputs into a ConfigKit
underlay, with operator sources at higher priority. Using the shipped prompts
must not require a separate external prompt installation.
Place all Audita-owned default prompts in the native `audita` collection
namespace. Keep local IDs such as `modules.glossary.proposal`; callers use the
qualified runtime ID `audita/modules.glossary.proposal`. Update registry entries,
call sites, references, examples, and diagnostics accordingly. Mounting a source
does not rewrite references, so qualified references must be explicit.
Operators may replace individual prompts or supply a complete replacement set
by defining the same collection and local IDs in higher-priority sources.
Unreplaced prompts continue to come from the underlay. Follow native whole-record
replacement semantics for matching IDs and document the required complete prompt
definitions. The namespace identifies Audita's prompts without making them
immutable or requiring a separate development mode.
The development workflow is edit external definitions and rerun Audita using the
same binary. A newly constructed runtime captures the changed definitions and
message files; live reload within an active run is not required. The same
mechanism supports production customization. Standard inspection, provenance,
and request preview must make effective prompts and their origins understandable.
Audita's response schemas and domain validation continue to apply.
External source selection follows the [automatic source contract below](#automatic-prompt-sources--resolved),
using the [ConfigKit import policy](configkit.md#discovery-locations-and-import-selection--resolved).
This workflow is required PromptKit adoption scope and uses native composition.
### Automatic Prompt Sources — Resolved
Automatically compose optional `./prompts.yml` and YAML files recursively under
`./prompts/`, relative to the selected main application configuration file's
directory. Follow the shared [resource-base and overlay rule](configkit.md#companion-resource-base-and-overlays--resolved).
When no main context exists, skip these automatic inputs and retain the embedded
Audita prompts and bundled catalog; do not fall back to the working directory.
Supply one operator-source underlay with these native ConfigKit imports:
```yaml
config:
imports:
- path: prompts.yml
required: false
- dir: prompts
required: false
recursive: true
pattern: ["*.yml", "*.yaml"]
```
Construct the engine after application loading. Enable imports and supply the
operator declaration's concrete filesystem context from ConfigKit's recorded
application main source/context evidence, preserving its resolved lookup base,
containment root, and source accounting. `Input.MainRelative` inside PromptKit
refers to the engine's own main input; it does not automatically refer to Audita's
separately loaded main. Do not feed the application document into PromptKit's
schema or rediscover/reload it to obtain a directory. When no main context exists,
omit the automatic operator inputs. Keep embedded prompt contexts separate.
ConfigKit owns traversal, composition, inheritance, and provenance; do not add
an Audita directory walker, YAML parser, or replacement mechanism.
Compose the engine's layers from lowest to highest priority:
1. PromptKit's default-on bundled OpenRouter catalog.
2. Audita's embedded `audita` prompt underlay.
3. The operator-source underlay containing both automatic imports.
Load both automatic locations when present. Missing optional sources contribute
nothing; present but unreadable, invalid, or conflicting sources retain native
errors. The file and directory compose as strict peers within one tier. Neither
gains priority from declaration, filename, or discovery order; duplicate resource
identities in that tier are errors. At the boundary above embedded defaults,
native same-ID replacement replaces the complete matching record while retaining
unmatched defaults. Follow the upstream
[source and profile precedence](https://forge.maximumdirect.net/base-layer/promptkit/src/commit/171fb11f4e967a1da3af57843c6467954b14ba09/docs/formats.md#source-and-profile-precedence).
Use native PromptKit documents at the document root, with namespaces and IDs
declared in their content. Each file may define one or several resources,
including supported profiles and backends. Filenames and subdirectories do not
assign identities or namespaces. Replacing an Audita prompt uses the same
`collections.audita` namespace and local prompt ID as its embedded definition,
as specified above; no source-selector setting is required.
Operators can use `prompts.yml` for definitions or as a manifest importing shared
libraries elsewhere, and organize local definitions beneath `prompts/`. Nested
imports and prompt `content_file` references retain native source-relative
handling. Avoid importing the automatically discovered directory again from the
manifest; repeated inclusion within the tier retains ConfigKit's native error.
Use one shared engine-loading path for processing, configuration/resource
inspection, request preview, validation, and smoke commands. All must observe
the same layers and captured definitions for the same invocation inputs.
`--config` selects Audita's application configuration and therefore determines
the companion lookup base. Selecting an application overlay does not relocate
that base to the overlay's directory. All engine consumers share this handoff.
### Profile Inspection and Summary — Resolved
Retire `config print-effective --view profiles` and its Audita-owned summary
code. Use application configuration inspection to show proposal/validation
profile selections, standard PromptKit resource inspection for profile/backend/
prompt definitions, and request preview for resolved execution settings and
rendered messages. These views have distinct meanings and must be presented as
such.
Do not add a replacement custom role summary at this stage. Native interfaces
cover the selected needs and reduce maintenance without a parallel target
resolver. Include the retired view and its standard replacements in the
hard-cutover guidance. The [CommandKit outline](commandkit.md) owns the operator
surface and request-preview integration work.
### Target Request and Source Boundaries
PromptKit resource sources use identified lists, native sibling `extends`, and
complete same-ID replacement records. Qualified references remain explicit.
Audita requests, registries, inspection, and diagnostics use prompt IDs without
obsolete prompt-version selection or labels. The existing domain instructions,
self-contained response schemas, per-call schema and repair controls, and
proposal/validator behavior remain distinct from resource format changes.
Resource inspection shows native optional profile fields and backend definitions;
prepared execution shows the completed request. Audita executes the captured
request it prepared, without a parallel target resolver. Native field-specific
null and presence rules govern defaults. Audita retains logical operation
budgets, cancellation, truthful partial success, and safe diagnostics.
Output-collision protection accounts for consumed host documents, including
imports, and effective source-relative `content_file` resources. Source metadata
tracks inherited and moved values at native list-index and collection paths;
array positions are addresses, not durable resource IDs. Native redaction governs
standard inspection, while Audita owns its artifact redaction.
Canonical [configuration](../config.md), [LLM integration](../integrations/openai-compatible-llm.md),
[runtime](../internal/llm-runtime.md), and [prompt guidance](../internal/prompts.md)
will describe the implemented behavior and cutover, alongside updated examples
and attribution. Standard inspection can show prompts and provider settings
where the library exposes them; old prompt hashes are not a contract.
## Acceptance and Upstream Requests
Verify native bundle inventory and selection, configuration/resource/prepared
view distinctions, inheritance and replacement, credential precedence, optional
fields, source-relative messages and collisions, and captured configuration.
Use controlled providers to verify actual targets, domain schemas, shared
admission, retry/repair budgets, cancellation, and partial success. Standard
inspection must work without model calls; library presence alone does not prove
successful Audita integration.
Verify backend defaults and explicit concurrency overrides through the assembled
application, including shared admission across proposal and validation roles.
Check that Audita no longer injects an additional limit or rejects native settings
under its former finite-cap policy. Keep integration coverage for Audita's wiring;
remove tests that only preserve retired local concurrency behavior.
Verify native bundled and custom backend selection without duplicate Audita
registration, supported profile endpoint and credential overrides, and inspection
without credential availability. Use controlled requests to cover required-key
failures and optional unauthenticated execution under native semantics. Check
that no application override layer or direct-key injection defeats native
precedence, and that synthetic keys stay out of Audita diagnostics and artifacts.
Verify the embedded `audita` prompts work without external prompt definitions.
Cover both automatic locations absent, each present alone, and both present with
distinct resources, including nested YAML files. Exercise missing optional
sources, unreadable/invalid sources, and same-tier identity conflicts through
native loading. Confirm that explicit and discovered application mains elsewhere
anchor imports beside that main, independently of the working directory. With no
main context, confirm automatic imports are skipped while bundled and embedded
resources remain available. Verify the recorded-context handoff to the separate
engine, including source accounting and overlay selection without relocation.
Check manifest imports of shared libraries and source-relative
message files, with provenance and consumed-source collision protection intact.
Exercise both individual-prompt and complete-set replacements using native
collection IDs, checking that unreplaced defaults remain available. Demonstrate
that editing external prompt/message files changes a newly constructed runtime's
prepared request without rebuilding the binary, while the existing runtime keeps
its captured inputs. Check qualified-ID selection, effective prompt inspection,
source provenance, and continued response-schema and domain validation with
controlled responses. Verify that processing and standard inspection/preview use
the same effective replacements and that the bundled catalog remains available.
Include a maintained edit-and-rerun example using the automatic sources, without
requiring a source-selector setting or binary rebuild.
Verify that role selections are visible in application configuration inspection,
resources through standard inspection, and completed request settings through
preview. Remove tests and examples that only preserve the retired curated view;
cover its replacement workflows through the assembled CLI.
No upstream request is yet selected. PromptKit is mature but pre-v1: significant
blockers or awkward public boundaries can justify focused requests. Submit the
minimal reproducer, desired outcome, and domain justification before building
substantial local machinery. A review probe demonstrated distinct base/derived
backend records preserving provider fields; that is an available native technique,
not a decision to retain Audita's old backend ownership model.

View File

@@ -1,738 +0,0 @@
# Library Adoption Review Findings
**Reviewed source:** `2844ce7e6a6b881bd4658577fd1177eae729f04d`.
**Scope:** All 15 stages in the [implementation plan](implementation.md),
compared with the [adoption roadmap](library-adoption.md) and pre-sprint
revision `40420a2`.
**Status:** Open.
The follow-up integration audit compared the two binaries against a loopback
provider. A normal grammar correction produced the same transcript and
completed both validators on each revision. Differences at the output,
credential, and glossary boundaries are recorded in R10–R12.
The algorithmic audit traced the implementation and its pinned library calls
without performance measurements. R13–R20 identify avoidable work within the
adopted design. Fixed transcript chunks, ordered stages, native provider
admission, glossary selection and matching rules, and report schemas remain
the basis of the analysis.
## Architecture Assessment
ConfigKit selects and composes the v3 application configuration, including
main-relative glossary sources and overlays, and records root and stage
resolution. PromptKit loads its bundled catalog, embedded Audita prompts, and
operator resources using the selected main's context. One engine supplies
stage-specific proposal and validation clients and owns provider admission.
CommandKit provides routing, reporting modes, and the standard configuration,
resource, request, and smoke commands.
Audita resolves independent context and protection views for each stage.
Preflight checks readiness and coordinates the output session before model
work. Processing normalizes once, then the runner chunks once, applies stages
in order, and carries recoverable failures into reports. ReleaseKit owns
validation, source publication, and asynchronous Linux delivery.
| Stages | Reviewed behavior |
| --- | --- |
| 1 and 15 | Dependency and toolchain pins, release profile, launcher, tag verification, and candidate evidence. A disposable ReleaseKit check passed with Go 1.27.3, including race tests, vet, Markdown and module checks, both Linux builds, and version output. The plan records the annotated-tag delivery rehearsal. |
| 2–4 | Native application load, main-relative engine inputs, prompt resources and source accounting, prepared role clients, retries and repairs, and redaction. See R2, R4, R10, R13, and R14. |
| 5–6 | Native app and PromptKit scopes, typed routing, preview, validation, and explicit smoke, including controlled transport tests. See R5 and R13. |
| 7–8 | Destination checks, deferred device/pipe delivery, transcript replacement, ordinary reports, optional debug, and reporting modes. The output-path loop compares a growing source list against at most four destinations. See R1, R7, R9, R11, and R18. |
| 9–10 | Native identified glossary composition, typed extensions and selections, recorded defaults, and explicit clearing after CLI assignments. See R15. |
| 11–12 | Stage-specific glossary views, late-stage readiness, fixed chunks, ordered mutation, and partial success. See R3, R9, R12, R15–R17, and R20. |
| 13–14 | Stage attribution, report schemas, canonical docs, migration, examples, ADR, and attribution. The complete stage-by-chunk matrices are part of enabled reports. See R1, R6–R8, R18, and R19. |
## R1 — P2: Keep Failure Records and Counts Consistent
**Status:** Completed. Failed report counts are derived from their records,
and fatal attribution uses the returned processing error and known stage.
**Category**
Incorrect ordinary reports in Stages 7, 8, and 13.
**Evidence**
[Finalization](../../internal/cli/process_output.go#L24) appends
run-level output errors after the report snapshot's counts have been computed.
A real run with an empty pipeline and `--output /dev/full` returned status 1.
Both YAML summaries still showed `run_errors: 0`, while `errors.yml` contained
an `output_failure` record. The Markdown report uses the same stale count.
[Report initialization](../../internal/cli/process_inputs.go#L89) prepares a
failed-status bundle by changing only the status, so a failed initialization
can leave reports with no record of the known failure.
[Pipeline failure attribution](../../internal/cli/process_pipeline.go#L48)
also takes the first operation with any failure reason from the last result.
A recoverable timeout or unusable decision set can precede the operation
that actually stopped processing. This can overwrite the cancellation reason
and cite a different chunk or validator. A stage-only origin is also rendered
as chunk zero by [report mapping](../../internal/framework/processreport/report.go#L119).
**Recommended change**
Build failed reports from the actual run failures and
known output failures, deriving counts and records together. Keep fatal
classification tied to the error that stopped the runner. Add stage, chunk,
and operation attribution only where the runner has that evidence.
**Acceptance**
A late transcript or report failure produces consistent
failed-status records and counts in the remaining reports. A recoverable error
followed by cancellation or a fatal operation retains both facts separately.
The primary failure and any already published transcript survive secondary
report failures.
## R2 — P2: Preserve Host Prompt Source Context Through Symlinks
**Status:** Completed. Prompt imports use the recorded native host context and protect the resolved sources.
**Category**
Main-relative resource loading divergence in Stage 3.
**Evidence**
[Engine assembly](../../internal/framework/llm/runtime.go#L58)
passes ConfigKit's passive host resource view back as an opaque native
filesystem. That view lacks native symlink inspection. In a disposable project,
`prompts.yml -> defs/resources.yml` acquired the prompt but resolved its
`content_file: message.txt` beside the link, failing despite the file being
present beside `defs/resources.yml`. An ordinary manifest import of the same
target worked. Adding a file beside the link also made the linked definition
load, demonstrating that it used the wrong base.
**Recommended change**
Carry the recorded host base and containment root into
PromptKit as a supported host context, so ConfigKit can acquire host sources
and resolve links using its native host rules. Keep embedded/native filesystem
inputs separate. If the public handoff cannot express the required context,
request the missing upstream facility with this fixture.
**Acceptance**
A prompt acquired through a supported in-root host symlink
resolves its message file beside the acquired definition. Source evidence and
output collision checks still protect consumed files. Preserve the absent-main
behavior and the recorded wider-root case.
## R3 — P2: Separate Glossary Context From Protection in Proposal Prompts
**Status:** Completed. Proposal requests carry separate context and protected spellings, with an empty preview default.
**Category**
An unintended prompt restriction in Stage 11.
**Evidence**
[The runner's specifications](../../internal/framework/contracts/contracts.go#L101)
correctly derive independent rich entries and protected vocabulary. The
[proposal builder](../../internal/framework/proposal_generation/module_proposal.go#L35)
passes only the rich entries. The embedded [grammar](../../internal/prompts/assets/prompts/modules.grammar.proposal.yaml#L21),
[homophones](../../internal/prompts/assets/prompts/modules.homophones.proposal.yaml#L19),
and [spoken-word](../../internal/prompts/assets/prompts/modules.spoken_word.proposal.yaml#L23)
prompts call those entries protected. With `glossaries: [party]` and
`protected_terms: []`, they still tell the model to preserve party spellings.
A protection-only selection also has no distinct representation in these prompts.
The deterministic checks see the intended independent selection, but they
cannot recover valid proposals that the model was instructed to omit.
**Recommended change**
Describe rich entries as context and give protection
instructions the effective protected spellings separately wherever they are
needed. Use the same stage-local exemption for glossary correction. Retain
the domain limits on each module, including acoustic plausibility and the
spoken-word repetition exception.
**Acceptance**
Captured requests distinguish context-only and protection-only
selections. Explicit empty protection imposes no glossary-derived prompt
restriction. The deterministic and apply-time checks still use the effective
stage vocabulary.
## R4 — P2: Show Native Configuration Diagnostics During Processing
**Status:** Completed. Processing now presents native ConfigKit error details through CommandKit and preserves the typed load error. CLI coverage checks migration guidance, an invalid setting, and the absence of output on failure.
**Category**
Missing migration guidance and actionable failure detail in
Stages 2 and 8.
**Evidence**
The [version rule](../../internal/core/config/config.go#L139)
provides migration guidance as a ConfigKit diagnostic. The
[process error path](../../internal/cli/process.go#L22) prints the load error's
summary. A real invocation using a v2 main file returned status 2 with
`configkit: configuration load failed with 1 error` and no migration guidance.
`config validate --scope app` on that same file printed the path, location,
and migration guidance.
**Recommended change**
Surface the native safe findings for application-load
failures in the process command, using CommandKit's normal error presentation
and retaining the typed cause. Reuse the native diagnostics rather than
maintaining a second configuration validator or formatter.
**Acceptance**
Processing an obsolete main file explains the migration before
creating outputs or calling a model. An ordinary invalid setting identifies
the actionable configuration problem through the same path.
## R5 — P3: Keep PromptKit Configuration Comparison Sides Independent
**Status:** Completed. The native configuration scope acquires each comparison side independently. A comparison with equal selections detects a resource edit between loads. Request commands retain invocation-local capture.
**Category**
Native behavior overridden in Stage 5.
**Evidence**
[PromptKit's loader](../../internal/cli/app_wiring.go#L46) memoizes
engines by deep equality of the selection within the invocation state. That
state is shared by the native configuration suite. The released ckprompt
comparison adapter acquires both sides independently, including equal
selections. Audita returns the left-hand capture for an equal right-hand
selection, adding a shared-snapshot rule the plan explicitly avoids.
**Recommended change**
Give the comparison loader independent acquisitions.
Keep shared acquisition within a selected processing or request workflow
where it serves the captured-engine requirement.
**Acceptance**
Each comparison side reaches the loader and gets its own
native evidence. Other standard commands continue to use the same source
selection rules and native comparison status.
## R6 — P3: Render Stage IDs as Data in Markdown
**Status:** Completed. Markdown escapes stage labels as literal cell text. Tests cover Markdown syntax, a pipe next to a backslash, and exact YAML IDs. A rendered table check confirmed the label stays in one cell.
**Category**
Incomplete output escaping in Stage 13.
**Evidence**
[Markdown rendering](../../internal/core/reporting/markdown.go#L174)
handles table separators, backticks, newlines, and HTML, but a valid ID such as
`[party](https://example.invalid/)` still renders as a link. Emphasis delimiters
can similarly hide literal characters. The stage ID is an exact operator label
and the same text is preserved in machine records.
**Recommended change**
Render IDs as literal text within report labels using
Markdown-appropriate escaping. Continue to allow arbitrary supported ID text
and use generated coordinates for paths.
**Acceptance**
A representative ID containing Markdown syntax renders with
its literal text, retains the exact YAML/JSON ID, and stays in its intended table
cell. Existing unnamed and repeated stage labels remain distinguishable.
## R7 — P3: Retire Disconnected Cutover Code and Test the Live Paths
**Status:** Completed. Removed retired report and debug builders, utilization and timing bookkeeping, and obsolete invocation fields. Report destination tests now drive the processing command. Internal and offline subprocess suites passed.
**Category**
Dead production code and misleading test coverage in Stages 7,
8, 13, and 15.
**Evidence**
The old report-directory helper in `internal/cli/config_input.go`
has only a test caller. [Processing](../../internal/cli/process_inputs.go#L72)
implements directory selection separately. The former
configuration explanation in `internal/framework/llm/safe_view.go` and
utilization view in `internal/framework/processreport/llm.go` also have
only test callers. The runner still collects validator timing for the latter.
The single `GlossaryPath` survives through report data and prints an empty
`Glossary input:` line after the standalone glossary loader was removed.
The debug invocation record still emits `modules: null` on a run with active
stages. The CLI writes resolved stages to the effective configuration artifact
instead. [Invocation metadata](../../internal/cli/process_inputs.go#L104)
**Recommended change**
Put destination-selection coverage on the live path.
Remove superseded formatters, bookkeeping, DTO fields, and tests whose only
consumer was a retired artifact. Preserve required stage attribution,
redaction, and native configuration provenance on their active paths.
**Acceptance**
Regression tests exercise actual report directory selection.
Remove the stale standalone glossary path from current evidence. Retain
diagnostics with an active consumer or a documented requirement.
## R8 — P3: Clarify the Configuration Cutover and Preflight Documentation
**Status:** Completed. Migration guidance now distinguishes the application schema from the executable version and explains glossary descriptions and completion counts. Subprocess guidance reflects early transcript parsing, and the v3.0.0 reference points to the tagged format.
**Category**
Documentation divergence in Stage 14.
**Evidence**
[The migration guide](../migrations/v3.md) calls the cutover
“Audita v3”, although Audita 3.x already shipped with application schema v2.
It also omits the change that default-mode processing hides completion
counts, including when ordinary reports are disabled.
It leaves out the rename from legacy glossary `summary` to `description`.
A copied `summary` is retained as an extension, so migration can appear
successful while the existing prompt builder loses that context.
[Legacy format](../migrations/v2.md) · [Glossary projection](../../internal/core/glossary/selection.go#L29)
[Subprocess guidance](../integrations/subprocess.md#result-handling) says
failed reports can describe invalid input after initialization. Transcript
parsing now occurs before report preparation.
[The v3.0.0 note](../releases/v3.0.0.md) pins historical examples to its tag
but still links the old format description to the current configuration guide.
**Recommended change**
Distinguish application schema v3 from the executable
release version. Explain how to see completion counts at the cutover, link
historical format guidance to its applicable revision, and align subprocess
guidance with early transcript validation. Include the glossary field mapping
so operators can preserve their prompt context.
**Acceptance**
A v3.1.x operator can identify which schema is changing and
how to observe completed runs. A migrated glossary entry retains the intended
description in prompt context. Current guidance explains which failures can
leave reports. Historical references continue to describe their own versions.
## R9 — P2: Honor Cancellation in Normalization-Only Processing
**Status:** Completed. Processing checks cancellation after normalization and before delivery. A controlled empty-pipeline test preserves the existing transcript, finalizes both YAML reports as failed, and retains the cancellation cause.
**Category**
Cancellation regression in Stages 8 and 12.
**Evidence**
[Processing](../../internal/cli/process.go#L44) lost the
post-normalization context check during the cutover. The
[runner](../../internal/framework/runner/runner.go#L172) checks for cancellation
through stage work, which an empty pipeline never enters. In a disposable
normalization-only run, sending SIGINT just after the initial reports appeared
returned status 0 and published the transcript.
**Recommended change**
Check the invocation context at the processing handoff
and before committing a successful result. Use the existing canceled outcome
and failed-report finalization for cancellation observed before delivery.
**Acceptance**
A controlled cancellation after preparation and before
successful delivery of an empty-pipeline run leaves the final transcript
untouched and attempts failed-status reports. An uncanceled empty pipeline
still produces normalized output without provider calls.
## R10 — P2: Mask the Credential Value PromptKit Actually Sends
**Status:** Completed. Redaction now includes the raw and trimmed forms of referenced credential values. A local provider regression echoes both forms and checks retained diagnostics, reports, and command output.
**Category**
Credential normalization and diagnostic redaction disagree in Stage 4.
**Evidence**
PromptKit trims surrounding whitespace from its environment credential before
setting the Authorization header. Audita supplies the literal environment
value to its existing exact-value redactor. With a synthetic credential padded
by spaces and a tab, a loopback provider observed the trimmed value and echoed
it in a schema-invalid response. The run completed with a recoverable model
error and wrote the trimmed credential to its proposal response artifact.
The same response with an unpadded credential was masked.
[Credential collection](../../internal/framework/llm/secrets.go#L40) ·
[Proposal debug output](../../internal/framework/proposal_generation/generate.go#L155)
**Recommended change**
Supply both raw and normalized nonempty values for referenced credential
variables to the existing redactor. Keep credential selection in PromptKit.
**Acceptance**
A controlled provider that echoes the effective value of a padded synthetic
credential leaves neither representation in retained diagnostics, ordinary
reports, or surfaced errors. Credential availability and processing outcomes
keep their native behavior.
## R11 — P2: Preserve Pipes That Appear After Output Preparation
**Status:** Completed. Delivery checks the destination type before opening a prepared stream or replacing a file. Tests cover both type changes, preservation of the replacement destination, and cleanup of staged output.
**Category**
The new Stage 7 preparation changes the existing special-file delivery behavior.
**Evidence**
Preparation classifies a missing destination as a regular-file output. Final
delivery then renames the staged transcript over that path without checking
its current type. In a controlled run, the provider fixture created a named
pipe at the selected path after the first proposal request arrived. The
previous binary wrote the transcript to the pipe and left it in place. The
new binary replaced it with a regular file, and both reported success.
[Output preparation](../../internal/core/diagnostics/output_session.go#L140) ·
[Transcript publication](../../internal/core/diagnostics/output_session.go#L309)
**Recommended change**
Recheck the destination type at delivery using the existing filesystem
behavior. Deliver to a current pipe or device directly, or return a clear
failure if its change makes the prepared destination unusable. Keep the
ordinary per-file replacement and temporary-file cleanup.
**Acceptance**
A FIFO created after preparation survives delivery. An existing FIFO remains
unopened during preflight. Ordinary destinations still publish from the
prepared sibling file, and failed delivery cleans up that file.
## R12 — P2: Preserve Longest-Match Context for Glossary Exemptions
**Status:** Completed. Active spellings remain longest-match boundaries without contributing protected identities. Tests cover full-name and span edits, standalone and longer protected terms, stage isolation, and apply-time agreement.
**Category**
The new Stage 11 exemption changes how the existing matcher identifies
overlapping terms.
**Evidence**
The projection removes active spellings before building the protected-term
matcher. That lets a shorter protected spelling match inside an exempt active
name. With `Greater Mage Armor` and `Greater Magus Armor` active and
`Mage Armor` protected from another collection, the previous glossary stage
accepted the full-name correction under controlled validation. The new stage
rejected it before either model validator ran. It treated the suffix of the
active name as a separate protected occurrence.
[Vocabulary projection](../../internal/core/glossary/vocabulary.go#L19) ·
[Longest-first matcher](../../internal/framework/validators/protected_terms.go#L29) ·
[Deterministic validator](../../internal/framework/validators/deterministic.go#L139)
**Recommended change**
Keep active spellings available as match boundaries and exempt the matched
active occurrence from protection. Apply the same interpretation in
deterministic validation and when evaluating the edited segment at apply time.
**Acceptance**
An exempt full name can be corrected when a shorter protected term occurs
inside it. A standalone occurrence of the shorter term and a distinct longer
protected name retain protection. Other module stages keep their independently
selected vocabulary.
## R13 — P2: Collect Prompt Message Paths From Effective Data
**Status:** Completed. Processing walks one effective PromptKit projection and uses per-field origins for host message paths. Inspection and request commands skip collision accounting. Tests cover inherited, collection-relative, and symlinked message sources.
**Category**
Repeated configuration history replay in Stages 3, 5, and 6.
**Evidence and complexity**
Audita enumerates historical fields and calls `Explain` for every effective
host-backed `content_file`, then reads only the effective YAML scalar.
ConfigKit v1.2.0's implementation of `Explain` replays source applications
and clones configuration checkpoints on each call. With `M` such fields and
`H` source history records, scanning history alone costs at least
`Ω(M × H)`. One file-backed message per source gives quadratic growth in
the number of sources, before accounting for replay and cloning costs.
The native resource commands also do the work because they build a runtime
and then retain only its engine.
[Source-path capture](../../internal/framework/llm/source_paths.go#L40) ·
[Engine wiring](../../internal/cli/app_wiring.go#L62)
**Refactoring opportunity**
Collect collision paths only for processing. Use one walk of the native
effective projection with per-field origin lookups, or use an upstream
effective-only accessor if it can expose the required path evidence. Keep
the actual load and source-relative resolution with the owning libraries.
**Acceptance**
Source accounting for processing uses a single effective pass and origin
lookups without replaying history per message. Inherited and relocated
message files still receive collision protection, including the host context
covered by R2. Inspection retains its native history commands.
## R14 — P3: Reuse Credential Source Discovery Across Diagnostics
**Status:** Completed. Credential source names are discovered once per runtime, with current values read at each masking boundary. Interaction and finalization redactors are reused, and deterministic validators receive no interaction writer. Tests cover credential changes and newly prepared names.
**Category**
Repeated catalog scans in Stages 4 and 8.
**Evidence and complexity**
`ConfiguredSecrets` lists and inspects every backend and profile each time.
Debug processing calls it per proposal interaction and per validator in each
active section, including deterministic validators that never write a model
interaction. Finalization also recollects it for each warning. With `D`
redaction preparations and `C` catalog resources, this is at least
`Θ(D × C)` resource visits, plus the work of copying each inspection result.
[Credential collection](../../internal/framework/llm/secrets.go#L11) ·
[Validator writer setup](../../internal/framework/runner/runner.go#L620) ·
[Warning presentation](../../internal/cli/process_output.go#L14)
**Refactoring opportunity**
Discover deduplicated credential source names once per captured engine.
Read values at the existing masking boundary, including additional names
supplied by prepared requests and normalized values from R10. Reuse writers
or redactors where they already share a value set, and construct interaction
writers only for consumers that can use them. This reduces catalog discovery
to one pass while retaining the cost of reading the referenced values.
**Acceptance**
Increasing the number of sections or warnings does not cause repeated
resource inventory scans. All existing masking behavior remains available,
and PromptKit still controls credential selection and availability.
## R15 — P3: Avoid Repeated Glossary Selection and Membership Scans
**Status:** Completed. List defaults clone only when inherited. Selection skips repeated collection names, readiness short-circuits without a rich projection, and contributor membership uses a set while preserving order. Existing inheritance, readiness, and glossary tests passed.
**Category**
Redundant list work and quadratic deduplication in Stages 10–12.
**Evidence and complexity**
- `resolveSettings` clones root lists before ConfigKit checks whether a stage
already supplied a list. Across `S` stages and `R` root list elements,
this copies `Θ(S × R)` elements even if every stage overrides both lists.
- `Select` walks a collection on every occurrence of its name. Selecting a
collection of `G` entries `K` times visits `Θ(K × G)` entries and
returns only `G`. Readiness also materializes a full rich selection just
to test whether it is empty.
- `Vocabulary` scans a spelling's existing contributor slice for every
insertion. When `K` distinct entries share an alias, the membership tests
for that alias alone take `Θ(K²)` comparisons.
[Recorded defaults](../../internal/core/config/resolve.go#L21) ·
[Glossary selection](../../internal/core/glossary/selection.go#L19) ·
[Readiness](../../internal/framework/preflight/preflight.go#L95) ·
[Contributor grouping](../../internal/core/glossary/vocabulary.go#L19)
**Refactoring opportunity**
Clone only lists that inherit. Skip repeated collection names before walking
their entries, and stop the readiness test at the first populated selection.
Use a membership set keyed by spelling and entry identity while keeping the
ordered output slices. That gives expected constant-time membership per
contribution, excluding the cost of normalizing and hashing the text.
**Acceptance**
First occurrence, contributor order, exact collection-scoped IDs, detached
inherited lists, and the distinction between omission and explicit clearing
are preserved. Readiness keeps the same late-stage diagnostics.
## R16 — P2: Reuse Prepared Glossary Views and Index Validation Context
**Status:** Completed. Each stage prepares shared protection and context matchers and serializes its proposal glossary variables once. Context gathers matched entry positions in selection order. Tests cover shared identities, ordering, exemptions, and request content.
**Category**
Per-section rebuilds and per-candidate glossary scans in Stages 11 and 12.
**Evidence and complexity**
The selected stage vocabulary stays fixed, but protected-term validation
compiles its matcher for each active section. Each LLM validator rebuilds the
context matcher again for its section. With `Q` such invocations and
`B` the cost of building a matcher, that is `Θ(Q × B)` preparation for
the same data. Proposal requests also re-encode identical glossary JSON in
each section. Within LLM validation, after matching text, every candidate
scans all `G` selected entries to recover their order. That adds
`Θ(P × G)` work for `P` candidates, even when nothing matches.
[Protected-term validation](../../internal/framework/validators/deterministic.go#L139) ·
[LLM validator request](../../internal/framework/validators/llm_validators.go#L252) ·
[Context selection](../../internal/framework/validators/llm_context.go#L12) ·
[Proposal variables](../../internal/framework/proposal_generation/variables.go#L14)
**Refactoring opportunity**
Prepare immutable stage-local matchers and, where used, serialized glossary
variables once. Build an identity-to-entry-position map alongside the context
view. Gather just the matched positions and order those positions before
materializing entries. After indexing, selecting `k` distinct matches per
candidate costs expected `O(k + k log k)` apart from text matching, rather
than a full glossary scan. Sharing the encoding saves local serialization
while leaving the selected glossary payload in each request.
**Acceptance**
Rich entries retain selection order and all contributing identities. Scope
and overlap rules remain as specified, including R3 and R12. Matchers and
immutable render inputs are shared safely across sections of the same stage.
## R17 — P3: Reuse Validation Payload Costs While Fitting and Batching
**Status:** Completed. The built-in estimator composes compact JSON costs across context fitting and greedy batching. Other estimators retain exact serialization. Equivalence tests cover trimmed context, oversized items, token counts, batch splits, escaped text, and local references.
**Category**
Quadratic prefix serialization in the existing budgeting path now used with
stage-specific budgets and shared glossary context.
**Evidence and complexity**
`fitValidationContext` removes one optional entry at a time and serializes
the remaining item again. Removing most of `K` similarly sized entries
serializes `Θ(K²)` entry data. `ChunkLLMValidationItems` copies, renumbers,
and marshals the entire tentative batch on each append. A batch that grows
to `N` similarly sized candidates costs `Θ(N²)` in those operations.
Small budgets bound the batch size, but the configured budget may grow and
many glossary entries can match one candidate.
[Context fitting](../../internal/framework/validators/llm_context.go#L43) ·
[Batch construction](../../internal/framework/validators/llm_batching.go#L16) ·
[Stage budget use](../../internal/framework/validators/llm_validators.go#L74)
**Refactoring opportunity**
Keep the existing drop order, greedy batch boundaries, and production
estimator. For that estimator, compose counts of whitespace-delimited runs
and punctuation from encoded components, accounting for join boundaries
and rounding once on the complete payload. Use those costs for prefix
selection and incremental batch construction, then render the selected
payload. Keep exact serialization for estimators whose costs cannot be
composed. This can reduce production work to one pass over the encoded
components and inexpensive checks over the candidate prefixes.
**Acceptance**
Representative payloads produce the same retained context, estimates,
oversized-candidate decisions, and batch boundaries. Include local reference
numbering and punctuation or escaped text at encoding boundaries.
## R18 — P3: Skip Evidence Work for Disabled Outputs
**Status:** Completed. Disabled reporting skips report payloads and detailed rows while retaining completion counts. Detailed observation hooks require an active debug writer. Subprocess coverage compares output and nonzero correction, error, and recovery counts across all four settings.
**Category**
Unused report rendering and event collection in Stages 8 and 13.
**Evidence and complexity**
Preparation renders both initial report bundles and finalization renders
the final bundle even with reporting disabled. For `S` stages and `Q`
chunks, this still builds two `Θ(S × Q)` Markdown matrices at finalization,
in addition to serializing error and recovery records. Processing also
retains all detailed LLM observations, copies them at completion, and sorts
them before testing whether debug artifacts are active. For `E` calls and
events, that is `Θ(E)` storage and up to `O(E log E)` sort comparisons.
Ordinary outcome counts use the role client's terminal event, independently
of that detailed collector.
[Report preparation](../../internal/cli/process_inputs.go#L90) ·
[Report delivery](../../internal/cli/process_output.go#L32) ·
[Observation wiring](../../internal/cli/process_pipeline.go#L18) ·
[Snapshot sorting](../../internal/framework/llm/observations.go#L148)
**Refactoring opportunity**
Build file payloads only when ordinary reporting is enabled. Install detailed
observation hooks only for an active debug writer, while retaining terminal
counts and compact completion facts for ordinary reports and CLI summaries.
Coordinate removal of unused utilization bookkeeping with R7.
**Acceptance**
Disabled outputs skip their formatting and optional observation costs.
Enabled reports and debug artifacts retain their data, and verbose completion
counts remain available with ordinary reporting disabled.
## R19 — P3: Index Interrupted Correction Ledger Entries
**Status:** Completed. The ledger retains each stage's proposal decision index and looks up interrupted candidates by generated stage instance. A repeated-module test confirms attribution, partial decisions, and ordering.
**Category**
Repeated joins in the Stage 13 debug ledger.
**Evidence and complexity**
The first pass indexes decisions by proposal for each stage and discards the
index after emitting completed entries. Every interrupted candidate then
searches stage results and scans the matching stage's entire decision list
again. With `I` interrupted candidates, `S` stages, and `D` decisions in
one failed stage, lookup can cost `Θ(I × (S + D))`. Interruption late in a
large stage can make both `I` and `D` grow with candidate count.
[Decision indexing and interrupted fallback](../../internal/framework/processreport/correction_ledger.go#L64)
**Refactoring opportunity**
Reuse the first-pass decision index through the interrupted-entry join and
index stage metadata by generated instance. Expected lookup and grouping
become linear in stages, candidates, and decisions visited, plus the
existing final sort. Keep operator IDs as labels.
**Acceptance**
Interrupted entries retain the same stage identity, partial validator
decisions, and output order without rescanning decisions for each candidate.
## R20 — P3: Skip Apply-Time Copies for Sections With No Approved Edits
**Status:** Completed. Sections without approved proposals retain their existing segments. The runner still records every work unit, and sections with approved changes use the existing ordered application and protection checks. No-edit coverage verifies transcript and work-unit results.
**Category**
Avoidable transcript copying during Stage 12 application.
**Evidence and complexity**
The runner invokes application for every section even when its approved
proposal slice is empty. Application clones the section's segments and
categories and builds the segment-ID map before inspecting proposals. For a
stage with `N` segments and no approved edits, that is `Θ(N)` segment
copies and map entries, plus category copies, to preserve identical text.
Across repeated no-op stages this grows with the number of stages times the
transcript size.
[Section application](../../internal/framework/runner/runner.go#L289) ·
[Per-section clone and index](../../internal/framework/proposals/apply.go#L42)
**Refactoring opportunity**
Retain the existing section when it has no approved proposals. Invoke
application and its protection checks only for sections with candidates.
Keep the runner's work-unit bookkeeping for every section.
**Acceptance**
No-edit and all-recoverable-failure runs produce the same normalized
transcript and reports. Sections with approved proposals still use ordered
application and recheck the current text before each edit.